ZhengyangZhang commited on
Commit
6a31876
·
verified ·
1 Parent(s): 6ce1180

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. lib/python3.12/site-packages/cloudpickle/__init__.py +18 -0
  2. lib/python3.12/site-packages/cloudpickle/__pycache__/__init__.cpython-312.pyc +0 -0
  3. lib/python3.12/site-packages/cloudpickle/__pycache__/cloudpickle.cpython-312.pyc +0 -0
  4. lib/python3.12/site-packages/cloudpickle/__pycache__/cloudpickle_fast.cpython-312.pyc +0 -0
  5. lib/python3.12/site-packages/cloudpickle/cloudpickle.py +1552 -0
  6. lib/python3.12/site-packages/cloudpickle/cloudpickle_fast.py +14 -0
  7. lib/python3.12/site-packages/ninja-1.13.0.dist-info/INSTALLER +1 -0
  8. lib/python3.12/site-packages/ninja-1.13.0.dist-info/METADATA +102 -0
  9. lib/python3.12/site-packages/ninja-1.13.0.dist-info/RECORD +18 -0
  10. lib/python3.12/site-packages/ninja-1.13.0.dist-info/WHEEL +6 -0
  11. lib/python3.12/site-packages/ninja-1.13.0.dist-info/licenses/AUTHORS.rst +5 -0
  12. lib/python3.12/site-packages/ninja-1.13.0.dist-info/licenses/LICENSE_Apache_20 +191 -0
  13. lib/python3.12/site-packages/numpy/__config__.py +162 -0
  14. lib/python3.12/site-packages/numpy/__init__.cython-30.pxd +1050 -0
  15. lib/python3.12/site-packages/numpy/__init__.pxd +1015 -0
  16. lib/python3.12/site-packages/numpy/__init__.py +461 -0
  17. lib/python3.12/site-packages/numpy/__init__.pyi +0 -0
  18. lib/python3.12/site-packages/numpy/_distributor_init.py +15 -0
  19. lib/python3.12/site-packages/numpy/_globals.py +95 -0
  20. lib/python3.12/site-packages/numpy/_pytesttester.py +207 -0
  21. lib/python3.12/site-packages/numpy/_pytesttester.pyi +18 -0
  22. lib/python3.12/site-packages/numpy/conftest.py +138 -0
  23. lib/python3.12/site-packages/numpy/ctypeslib.py +545 -0
  24. lib/python3.12/site-packages/numpy/ctypeslib.pyi +251 -0
  25. lib/python3.12/site-packages/numpy/dtypes.py +77 -0
  26. lib/python3.12/site-packages/numpy/dtypes.pyi +43 -0
  27. lib/python3.12/site-packages/numpy/exceptions.py +231 -0
  28. lib/python3.12/site-packages/numpy/exceptions.pyi +18 -0
  29. lib/python3.12/site-packages/numpy/matlib.py +378 -0
  30. lib/python3.12/site-packages/numpy/polynomial/__init__.py +185 -0
  31. lib/python3.12/site-packages/numpy/polynomial/__init__.pyi +22 -0
  32. lib/python3.12/site-packages/numpy/polynomial/_polybase.py +1206 -0
  33. lib/python3.12/site-packages/numpy/polynomial/_polybase.pyi +71 -0
  34. lib/python3.12/site-packages/numpy/polynomial/chebyshev.py +2082 -0
  35. lib/python3.12/site-packages/numpy/polynomial/chebyshev.pyi +51 -0
  36. lib/python3.12/site-packages/numpy/polynomial/hermite.py +1703 -0
  37. lib/python3.12/site-packages/numpy/polynomial/hermite.pyi +46 -0
  38. lib/python3.12/site-packages/numpy/polynomial/hermite_e.py +1695 -0
  39. lib/python3.12/site-packages/numpy/polynomial/hermite_e.pyi +46 -0
  40. lib/python3.12/site-packages/numpy/polynomial/laguerre.py +1651 -0
  41. lib/python3.12/site-packages/numpy/polynomial/laguerre.pyi +46 -0
  42. lib/python3.12/site-packages/numpy/polynomial/legendre.py +1664 -0
  43. lib/python3.12/site-packages/numpy/polynomial/legendre.pyi +46 -0
  44. lib/python3.12/site-packages/numpy/polynomial/polynomial.py +1542 -0
  45. lib/python3.12/site-packages/numpy/polynomial/polynomial.pyi +41 -0
  46. lib/python3.12/site-packages/numpy/polynomial/polyutils.py +789 -0
  47. lib/python3.12/site-packages/numpy/polynomial/polyutils.pyi +11 -0
  48. lib/python3.12/site-packages/numpy/polynomial/setup.py +10 -0
  49. lib/python3.12/site-packages/numpy/polynomial/tests/__init__.py +0 -0
  50. lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_classes.cpython-312.pyc +0 -0
lib/python3.12/site-packages/cloudpickle/__init__.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from . import cloudpickle
2
+ from .cloudpickle import * # noqa
3
+
4
+ __doc__ = cloudpickle.__doc__
5
+
6
+ __version__ = "3.1.2"
7
+
8
+ __all__ = [ # noqa
9
+ "__version__",
10
+ "Pickler",
11
+ "CloudPickler",
12
+ "dumps",
13
+ "loads",
14
+ "dump",
15
+ "load",
16
+ "register_pickle_by_value",
17
+ "unregister_pickle_by_value",
18
+ ]
lib/python3.12/site-packages/cloudpickle/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (454 Bytes). View file
 
lib/python3.12/site-packages/cloudpickle/__pycache__/cloudpickle.cpython-312.pyc ADDED
Binary file (55.6 kB). View file
 
lib/python3.12/site-packages/cloudpickle/__pycache__/cloudpickle_fast.cpython-312.pyc ADDED
Binary file (646 Bytes). View file
 
lib/python3.12/site-packages/cloudpickle/cloudpickle.py ADDED
@@ -0,0 +1,1552 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Pickler class to extend the standard pickle.Pickler functionality
2
+
3
+ The main objective is to make it natural to perform distributed computing on
4
+ clusters (such as PySpark, Dask, Ray...) with interactively defined code
5
+ (functions, classes, ...) written in notebooks or console.
6
+
7
+ In particular this pickler adds the following features:
8
+ - serialize interactively-defined or locally-defined functions, classes,
9
+ enums, typevars, lambdas and nested functions to compiled byte code;
10
+ - deal with some other non-serializable objects in an ad-hoc manner where
11
+ applicable.
12
+
13
+ This pickler is therefore meant to be used for the communication between short
14
+ lived Python processes running the same version of Python and libraries. In
15
+ particular, it is not meant to be used for long term storage of Python objects.
16
+
17
+ It does not include an unpickler, as standard Python unpickling suffices.
18
+
19
+ This module was extracted from the `cloud` package, developed by `PiCloud, Inc.
20
+ <https://web.archive.org/web/20140626004012/http://www.picloud.com/>`_.
21
+
22
+ Copyright (c) 2012-now, CloudPickle developers and contributors.
23
+ Copyright (c) 2012, Regents of the University of California.
24
+ Copyright (c) 2009 `PiCloud, Inc. <https://web.archive.org/web/20140626004012/http://www.picloud.com/>`_.
25
+ All rights reserved.
26
+
27
+ Redistribution and use in source and binary forms, with or without
28
+ modification, are permitted provided that the following conditions
29
+ are met:
30
+ * Redistributions of source code must retain the above copyright
31
+ notice, this list of conditions and the following disclaimer.
32
+ * Redistributions in binary form must reproduce the above copyright
33
+ notice, this list of conditions and the following disclaimer in the
34
+ documentation and/or other materials provided with the distribution.
35
+ * Neither the name of the University of California, Berkeley nor the
36
+ names of its contributors may be used to endorse or promote
37
+ products derived from this software without specific prior written
38
+ permission.
39
+
40
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
48
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
49
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51
+ """
52
+
53
+ import _collections_abc
54
+ from collections import ChainMap, OrderedDict
55
+ import abc
56
+ import builtins
57
+ import copyreg
58
+ import dataclasses
59
+ import dis
60
+ from enum import Enum
61
+ import io
62
+ import itertools
63
+ import logging
64
+ import opcode
65
+ import pickle
66
+ from pickle import _getattribute as _pickle_getattribute
67
+ import platform
68
+ import struct
69
+ import sys
70
+ import threading
71
+ import types
72
+ import typing
73
+ import uuid
74
+ import warnings
75
+ import weakref
76
+
77
+ # The following import is required to be imported in the cloudpickle
78
+ # namespace to be able to load pickle files generated with older versions of
79
+ # cloudpickle. See: tests/test_backward_compat.py
80
+ from types import CellType # noqa: F401
81
+
82
+
83
+ # cloudpickle is meant for inter process communication: we expect all
84
+ # communicating processes to run the same Python version hence we favor
85
+ # communication speed over compatibility:
86
+ DEFAULT_PROTOCOL = pickle.HIGHEST_PROTOCOL
87
+
88
+ # Names of modules whose resources should be treated as dynamic.
89
+ _PICKLE_BY_VALUE_MODULES = set()
90
+
91
+ # Track the provenance of reconstructed dynamic classes to make it possible to
92
+ # reconstruct instances from the matching singleton class definition when
93
+ # appropriate and preserve the usual "isinstance" semantics of Python objects.
94
+ _DYNAMIC_CLASS_TRACKER_BY_CLASS = weakref.WeakKeyDictionary()
95
+ _DYNAMIC_CLASS_TRACKER_BY_ID = weakref.WeakValueDictionary()
96
+ _DYNAMIC_CLASS_TRACKER_LOCK = threading.Lock()
97
+
98
+ PYPY = platform.python_implementation() == "PyPy"
99
+
100
+ builtin_code_type = None
101
+ if PYPY:
102
+ # builtin-code objects only exist in pypy
103
+ builtin_code_type = type(float.__new__.__code__)
104
+
105
+ _extract_code_globals_cache = weakref.WeakKeyDictionary()
106
+
107
+
108
+ def _get_or_create_tracker_id(class_def):
109
+ with _DYNAMIC_CLASS_TRACKER_LOCK:
110
+ class_tracker_id = _DYNAMIC_CLASS_TRACKER_BY_CLASS.get(class_def)
111
+ if class_tracker_id is None:
112
+ class_tracker_id = uuid.uuid4().hex
113
+ _DYNAMIC_CLASS_TRACKER_BY_CLASS[class_def] = class_tracker_id
114
+ _DYNAMIC_CLASS_TRACKER_BY_ID[class_tracker_id] = class_def
115
+ return class_tracker_id
116
+
117
+
118
+ def _lookup_class_or_track(class_tracker_id, class_def):
119
+ if class_tracker_id is not None:
120
+ with _DYNAMIC_CLASS_TRACKER_LOCK:
121
+ class_def = _DYNAMIC_CLASS_TRACKER_BY_ID.setdefault(
122
+ class_tracker_id, class_def
123
+ )
124
+ _DYNAMIC_CLASS_TRACKER_BY_CLASS[class_def] = class_tracker_id
125
+ return class_def
126
+
127
+
128
+ def register_pickle_by_value(module):
129
+ """Register a module to make its functions and classes picklable by value.
130
+
131
+ By default, functions and classes that are attributes of an importable
132
+ module are to be pickled by reference, that is relying on re-importing
133
+ the attribute from the module at load time.
134
+
135
+ If `register_pickle_by_value(module)` is called, all its functions and
136
+ classes are subsequently to be pickled by value, meaning that they can
137
+ be loaded in Python processes where the module is not importable.
138
+
139
+ This is especially useful when developing a module in a distributed
140
+ execution environment: restarting the client Python process with the new
141
+ source code is enough: there is no need to re-install the new version
142
+ of the module on all the worker nodes nor to restart the workers.
143
+
144
+ Note: this feature is considered experimental. See the cloudpickle
145
+ README.md file for more details and limitations.
146
+ """
147
+ if not isinstance(module, types.ModuleType):
148
+ raise ValueError(f"Input should be a module object, got {str(module)} instead")
149
+ # In the future, cloudpickle may need a way to access any module registered
150
+ # for pickling by value in order to introspect relative imports inside
151
+ # functions pickled by value. (see
152
+ # https://github.com/cloudpipe/cloudpickle/pull/417#issuecomment-873684633).
153
+ # This access can be ensured by checking that module is present in
154
+ # sys.modules at registering time and assuming that it will still be in
155
+ # there when accessed during pickling. Another alternative would be to
156
+ # store a weakref to the module. Even though cloudpickle does not implement
157
+ # this introspection yet, in order to avoid a possible breaking change
158
+ # later, we still enforce the presence of module inside sys.modules.
159
+ if module.__name__ not in sys.modules:
160
+ raise ValueError(
161
+ f"{module} was not imported correctly, have you used an "
162
+ "`import` statement to access it?"
163
+ )
164
+ _PICKLE_BY_VALUE_MODULES.add(module.__name__)
165
+
166
+
167
+ def unregister_pickle_by_value(module):
168
+ """Unregister that the input module should be pickled by value."""
169
+ if not isinstance(module, types.ModuleType):
170
+ raise ValueError(f"Input should be a module object, got {str(module)} instead")
171
+ if module.__name__ not in _PICKLE_BY_VALUE_MODULES:
172
+ raise ValueError(f"{module} is not registered for pickle by value")
173
+ else:
174
+ _PICKLE_BY_VALUE_MODULES.remove(module.__name__)
175
+
176
+
177
+ def list_registry_pickle_by_value():
178
+ return _PICKLE_BY_VALUE_MODULES.copy()
179
+
180
+
181
+ def _is_registered_pickle_by_value(module):
182
+ module_name = module.__name__
183
+ if module_name in _PICKLE_BY_VALUE_MODULES:
184
+ return True
185
+ while True:
186
+ parent_name = module_name.rsplit(".", 1)[0]
187
+ if parent_name == module_name:
188
+ break
189
+ if parent_name in _PICKLE_BY_VALUE_MODULES:
190
+ return True
191
+ module_name = parent_name
192
+ return False
193
+
194
+
195
+ if sys.version_info >= (3, 14):
196
+ def _getattribute(obj, name):
197
+ return _pickle_getattribute(obj, name.split('.'))
198
+ else:
199
+ def _getattribute(obj, name):
200
+ return _pickle_getattribute(obj, name)[0]
201
+
202
+
203
+ def _whichmodule(obj, name):
204
+ """Find the module an object belongs to.
205
+
206
+ This function differs from ``pickle.whichmodule`` in two ways:
207
+ - it does not mangle the cases where obj's module is __main__ and obj was
208
+ not found in any module.
209
+ - Errors arising during module introspection are ignored, as those errors
210
+ are considered unwanted side effects.
211
+ """
212
+ module_name = getattr(obj, "__module__", None)
213
+
214
+ if module_name is not None:
215
+ return module_name
216
+ # Protect the iteration by using a copy of sys.modules against dynamic
217
+ # modules that trigger imports of other modules upon calls to getattr or
218
+ # other threads importing at the same time.
219
+ for module_name, module in sys.modules.copy().items():
220
+ # Some modules such as coverage can inject non-module objects inside
221
+ # sys.modules
222
+ if (
223
+ module_name == "__main__"
224
+ or module_name == "__mp_main__"
225
+ or module is None
226
+ or not isinstance(module, types.ModuleType)
227
+ ):
228
+ continue
229
+ try:
230
+ if _getattribute(module, name) is obj:
231
+ return module_name
232
+ except Exception:
233
+ pass
234
+ return None
235
+
236
+
237
+ def _should_pickle_by_reference(obj, name=None):
238
+ """Test whether an function or a class should be pickled by reference
239
+
240
+ Pickling by reference means by that the object (typically a function or a
241
+ class) is an attribute of a module that is assumed to be importable in the
242
+ target Python environment. Loading will therefore rely on importing the
243
+ module and then calling `getattr` on it to access the function or class.
244
+
245
+ Pickling by reference is the only option to pickle functions and classes
246
+ in the standard library. In cloudpickle the alternative option is to
247
+ pickle by value (for instance for interactively or locally defined
248
+ functions and classes or for attributes of modules that have been
249
+ explicitly registered to be pickled by value.
250
+ """
251
+ if isinstance(obj, types.FunctionType) or issubclass(type(obj), type):
252
+ module_and_name = _lookup_module_and_qualname(obj, name=name)
253
+ if module_and_name is None:
254
+ return False
255
+ module, name = module_and_name
256
+ return not _is_registered_pickle_by_value(module)
257
+
258
+ elif isinstance(obj, types.ModuleType):
259
+ # We assume that sys.modules is primarily used as a cache mechanism for
260
+ # the Python import machinery. Checking if a module has been added in
261
+ # is sys.modules therefore a cheap and simple heuristic to tell us
262
+ # whether we can assume that a given module could be imported by name
263
+ # in another Python process.
264
+ if _is_registered_pickle_by_value(obj):
265
+ return False
266
+ return obj.__name__ in sys.modules
267
+ else:
268
+ raise TypeError(
269
+ "cannot check importability of {} instances".format(type(obj).__name__)
270
+ )
271
+
272
+
273
+ def _lookup_module_and_qualname(obj, name=None):
274
+ if name is None:
275
+ name = getattr(obj, "__qualname__", None)
276
+ if name is None: # pragma: no cover
277
+ # This used to be needed for Python 2.7 support but is probably not
278
+ # needed anymore. However we keep the __name__ introspection in case
279
+ # users of cloudpickle rely on this old behavior for unknown reasons.
280
+ name = getattr(obj, "__name__", None)
281
+
282
+ module_name = _whichmodule(obj, name)
283
+
284
+ if module_name is None:
285
+ # In this case, obj.__module__ is None AND obj was not found in any
286
+ # imported module. obj is thus treated as dynamic.
287
+ return None
288
+
289
+ if module_name == "__main__":
290
+ return None
291
+
292
+ # Note: if module_name is in sys.modules, the corresponding module is
293
+ # assumed importable at unpickling time. See #357
294
+ module = sys.modules.get(module_name, None)
295
+ if module is None:
296
+ # The main reason why obj's module would not be imported is that this
297
+ # module has been dynamically created, using for example
298
+ # types.ModuleType. The other possibility is that module was removed
299
+ # from sys.modules after obj was created/imported. But this case is not
300
+ # supported, as the standard pickle does not support it either.
301
+ return None
302
+
303
+ try:
304
+ obj2 = _getattribute(module, name)
305
+ except AttributeError:
306
+ # obj was not found inside the module it points to
307
+ return None
308
+ if obj2 is not obj:
309
+ return None
310
+ return module, name
311
+
312
+
313
+ def _extract_code_globals(co):
314
+ """Find all globals names read or written to by codeblock co."""
315
+ out_names = _extract_code_globals_cache.get(co)
316
+ if out_names is None:
317
+ # We use a dict with None values instead of a set to get a
318
+ # deterministic order and avoid introducing non-deterministic pickle
319
+ # bytes as a results.
320
+ out_names = {name: None for name in _walk_global_ops(co)}
321
+
322
+ # Declaring a function inside another one using the "def ..." syntax
323
+ # generates a constant code object corresponding to the one of the
324
+ # nested function's As the nested function may itself need global
325
+ # variables, we need to introspect its code, extract its globals, (look
326
+ # for code object in it's co_consts attribute..) and add the result to
327
+ # code_globals
328
+ if co.co_consts:
329
+ for const in co.co_consts:
330
+ if isinstance(const, types.CodeType):
331
+ out_names.update(_extract_code_globals(const))
332
+
333
+ _extract_code_globals_cache[co] = out_names
334
+
335
+ return out_names
336
+
337
+
338
+ def _find_imported_submodules(code, top_level_dependencies):
339
+ """Find currently imported submodules used by a function.
340
+
341
+ Submodules used by a function need to be detected and referenced for the
342
+ function to work correctly at depickling time. Because submodules can be
343
+ referenced as attribute of their parent package (``package.submodule``), we
344
+ need a special introspection technique that does not rely on GLOBAL-related
345
+ opcodes to find references of them in a code object.
346
+
347
+ Example:
348
+ ```
349
+ import concurrent.futures
350
+ import cloudpickle
351
+ def func():
352
+ x = concurrent.futures.ThreadPoolExecutor
353
+ if __name__ == '__main__':
354
+ cloudpickle.dumps(func)
355
+ ```
356
+ The globals extracted by cloudpickle in the function's state include the
357
+ concurrent package, but not its submodule (here, concurrent.futures), which
358
+ is the module used by func. Find_imported_submodules will detect the usage
359
+ of concurrent.futures. Saving this module alongside with func will ensure
360
+ that calling func once depickled does not fail due to concurrent.futures
361
+ not being imported
362
+ """
363
+
364
+ subimports = []
365
+ # check if any known dependency is an imported package
366
+ for x in top_level_dependencies:
367
+ if (
368
+ isinstance(x, types.ModuleType)
369
+ and hasattr(x, "__package__")
370
+ and x.__package__
371
+ ):
372
+ # check if the package has any currently loaded sub-imports
373
+ prefix = x.__name__ + "."
374
+ # A concurrent thread could mutate sys.modules,
375
+ # make sure we iterate over a copy to avoid exceptions
376
+ for name in list(sys.modules):
377
+ # Older versions of pytest will add a "None" module to
378
+ # sys.modules.
379
+ if name is not None and name.startswith(prefix):
380
+ # check whether the function can address the sub-module
381
+ tokens = set(name[len(prefix) :].split("."))
382
+ if not tokens - set(code.co_names):
383
+ subimports.append(sys.modules[name])
384
+ return subimports
385
+
386
+
387
+ # relevant opcodes
388
+ STORE_GLOBAL = opcode.opmap["STORE_GLOBAL"]
389
+ DELETE_GLOBAL = opcode.opmap["DELETE_GLOBAL"]
390
+ LOAD_GLOBAL = opcode.opmap["LOAD_GLOBAL"]
391
+ GLOBAL_OPS = (STORE_GLOBAL, DELETE_GLOBAL, LOAD_GLOBAL)
392
+ HAVE_ARGUMENT = dis.HAVE_ARGUMENT
393
+ EXTENDED_ARG = dis.EXTENDED_ARG
394
+
395
+
396
+ _BUILTIN_TYPE_NAMES = {}
397
+ for k, v in types.__dict__.items():
398
+ if type(v) is type:
399
+ _BUILTIN_TYPE_NAMES[v] = k
400
+
401
+
402
+ def _builtin_type(name):
403
+ if name == "ClassType": # pragma: no cover
404
+ # Backward compat to load pickle files generated with cloudpickle
405
+ # < 1.3 even if loading pickle files from older versions is not
406
+ # officially supported.
407
+ return type
408
+ return getattr(types, name)
409
+
410
+
411
+ def _walk_global_ops(code):
412
+ """Yield referenced name for global-referencing instructions in code."""
413
+ for instr in dis.get_instructions(code):
414
+ op = instr.opcode
415
+ if op in GLOBAL_OPS:
416
+ yield instr.argval
417
+
418
+
419
+ def _extract_class_dict(cls):
420
+ """Retrieve a copy of the dict of a class without the inherited method."""
421
+ # Hack to circumvent non-predictable memoization caused by string interning.
422
+ # See the inline comment in _class_setstate for details.
423
+ clsdict = {"".join(k): cls.__dict__[k] for k in sorted(cls.__dict__)}
424
+
425
+ if len(cls.__bases__) == 1:
426
+ inherited_dict = cls.__bases__[0].__dict__
427
+ else:
428
+ inherited_dict = {}
429
+ for base in reversed(cls.__bases__):
430
+ inherited_dict.update(base.__dict__)
431
+ to_remove = []
432
+ for name, value in clsdict.items():
433
+ try:
434
+ base_value = inherited_dict[name]
435
+ if value is base_value:
436
+ to_remove.append(name)
437
+ except KeyError:
438
+ pass
439
+ for name in to_remove:
440
+ clsdict.pop(name)
441
+ return clsdict
442
+
443
+
444
+ def is_tornado_coroutine(func):
445
+ """Return whether `func` is a Tornado coroutine function.
446
+
447
+ Running coroutines are not supported.
448
+ """
449
+ warnings.warn(
450
+ "is_tornado_coroutine is deprecated in cloudpickle 3.0 and will be "
451
+ "removed in cloudpickle 4.0. Use tornado.gen.is_coroutine_function "
452
+ "directly instead.",
453
+ category=DeprecationWarning,
454
+ )
455
+ if "tornado.gen" not in sys.modules:
456
+ return False
457
+ gen = sys.modules["tornado.gen"]
458
+ if not hasattr(gen, "is_coroutine_function"):
459
+ # Tornado version is too old
460
+ return False
461
+ return gen.is_coroutine_function(func)
462
+
463
+
464
+ def subimport(name):
465
+ # We cannot do simply: `return __import__(name)`: Indeed, if ``name`` is
466
+ # the name of a submodule, __import__ will return the top-level root module
467
+ # of this submodule. For instance, __import__('os.path') returns the `os`
468
+ # module.
469
+ __import__(name)
470
+ return sys.modules[name]
471
+
472
+
473
+ def dynamic_subimport(name, vars):
474
+ mod = types.ModuleType(name)
475
+ mod.__dict__.update(vars)
476
+ mod.__dict__["__builtins__"] = builtins.__dict__
477
+ return mod
478
+
479
+
480
+ def _get_cell_contents(cell):
481
+ try:
482
+ return cell.cell_contents
483
+ except ValueError:
484
+ # Handle empty cells explicitly with a sentinel value.
485
+ return _empty_cell_value
486
+
487
+
488
+ def instance(cls):
489
+ """Create a new instance of a class.
490
+
491
+ Parameters
492
+ ----------
493
+ cls : type
494
+ The class to create an instance of.
495
+
496
+ Returns
497
+ -------
498
+ instance : cls
499
+ A new instance of ``cls``.
500
+ """
501
+ return cls()
502
+
503
+
504
+ @instance
505
+ class _empty_cell_value:
506
+ """Sentinel for empty closures."""
507
+
508
+ @classmethod
509
+ def __reduce__(cls):
510
+ return cls.__name__
511
+
512
+
513
+ def _make_function(code, globals, name, argdefs, closure):
514
+ # Setting __builtins__ in globals is needed for nogil CPython.
515
+ globals["__builtins__"] = __builtins__
516
+ return types.FunctionType(code, globals, name, argdefs, closure)
517
+
518
+
519
+ def _make_empty_cell():
520
+ if False:
521
+ # trick the compiler into creating an empty cell in our lambda
522
+ cell = None
523
+ raise AssertionError("this route should not be executed")
524
+
525
+ return (lambda: cell).__closure__[0]
526
+
527
+
528
+ def _make_cell(value=_empty_cell_value):
529
+ cell = _make_empty_cell()
530
+ if value is not _empty_cell_value:
531
+ cell.cell_contents = value
532
+ return cell
533
+
534
+
535
+ def _make_skeleton_class(
536
+ type_constructor, name, bases, type_kwargs, class_tracker_id, extra
537
+ ):
538
+ """Build dynamic class with an empty __dict__ to be filled once memoized
539
+
540
+ If class_tracker_id is not None, try to lookup an existing class definition
541
+ matching that id. If none is found, track a newly reconstructed class
542
+ definition under that id so that other instances stemming from the same
543
+ class id will also reuse this class definition.
544
+
545
+ The "extra" variable is meant to be a dict (or None) that can be used for
546
+ forward compatibility shall the need arise.
547
+ """
548
+ # We need to intern the keys of the type_kwargs dict to avoid having
549
+ # different pickles for the same dynamic class depending on whether it was
550
+ # dynamically created or reconstructed from a pickled stream.
551
+ type_kwargs = {sys.intern(k): v for k, v in type_kwargs.items()}
552
+
553
+ skeleton_class = types.new_class(
554
+ name, bases, {"metaclass": type_constructor}, lambda ns: ns.update(type_kwargs)
555
+ )
556
+
557
+ return _lookup_class_or_track(class_tracker_id, skeleton_class)
558
+
559
+
560
+ def _make_skeleton_enum(
561
+ bases, name, qualname, members, module, class_tracker_id, extra
562
+ ):
563
+ """Build dynamic enum with an empty __dict__ to be filled once memoized
564
+
565
+ The creation of the enum class is inspired by the code of
566
+ EnumMeta._create_.
567
+
568
+ If class_tracker_id is not None, try to lookup an existing enum definition
569
+ matching that id. If none is found, track a newly reconstructed enum
570
+ definition under that id so that other instances stemming from the same
571
+ class id will also reuse this enum definition.
572
+
573
+ The "extra" variable is meant to be a dict (or None) that can be used for
574
+ forward compatibility shall the need arise.
575
+ """
576
+ # enums always inherit from their base Enum class at the last position in
577
+ # the list of base classes:
578
+ enum_base = bases[-1]
579
+ metacls = enum_base.__class__
580
+ classdict = metacls.__prepare__(name, bases)
581
+
582
+ for member_name, member_value in members.items():
583
+ classdict[member_name] = member_value
584
+ enum_class = metacls.__new__(metacls, name, bases, classdict)
585
+ enum_class.__module__ = module
586
+ enum_class.__qualname__ = qualname
587
+
588
+ return _lookup_class_or_track(class_tracker_id, enum_class)
589
+
590
+
591
+ def _make_typevar(name, bound, constraints, covariant, contravariant, class_tracker_id):
592
+ tv = typing.TypeVar(
593
+ name,
594
+ *constraints,
595
+ bound=bound,
596
+ covariant=covariant,
597
+ contravariant=contravariant,
598
+ )
599
+ return _lookup_class_or_track(class_tracker_id, tv)
600
+
601
+
602
+ def _decompose_typevar(obj):
603
+ return (
604
+ obj.__name__,
605
+ obj.__bound__,
606
+ obj.__constraints__,
607
+ obj.__covariant__,
608
+ obj.__contravariant__,
609
+ _get_or_create_tracker_id(obj),
610
+ )
611
+
612
+
613
+ def _typevar_reduce(obj):
614
+ # TypeVar instances require the module information hence why we
615
+ # are not using the _should_pickle_by_reference directly
616
+ module_and_name = _lookup_module_and_qualname(obj, name=obj.__name__)
617
+
618
+ if module_and_name is None:
619
+ return (_make_typevar, _decompose_typevar(obj))
620
+ elif _is_registered_pickle_by_value(module_and_name[0]):
621
+ return (_make_typevar, _decompose_typevar(obj))
622
+
623
+ return (getattr, module_and_name)
624
+
625
+
626
+ def _get_bases(typ):
627
+ if "__orig_bases__" in getattr(typ, "__dict__", {}):
628
+ # For generic types (see PEP 560)
629
+ # Note that simply checking `hasattr(typ, '__orig_bases__')` is not
630
+ # correct. Subclasses of a fully-parameterized generic class does not
631
+ # have `__orig_bases__` defined, but `hasattr(typ, '__orig_bases__')`
632
+ # will return True because it's defined in the base class.
633
+ bases_attr = "__orig_bases__"
634
+ else:
635
+ # For regular class objects
636
+ bases_attr = "__bases__"
637
+ return getattr(typ, bases_attr)
638
+
639
+
640
+ def _make_dict_keys(obj, is_ordered=False):
641
+ if is_ordered:
642
+ return OrderedDict.fromkeys(obj).keys()
643
+ else:
644
+ return dict.fromkeys(obj).keys()
645
+
646
+
647
+ def _make_dict_values(obj, is_ordered=False):
648
+ if is_ordered:
649
+ return OrderedDict((i, _) for i, _ in enumerate(obj)).values()
650
+ else:
651
+ return {i: _ for i, _ in enumerate(obj)}.values()
652
+
653
+
654
+ def _make_dict_items(obj, is_ordered=False):
655
+ if is_ordered:
656
+ return OrderedDict(obj).items()
657
+ else:
658
+ return obj.items()
659
+
660
+
661
+ # COLLECTION OF OBJECTS __getnewargs__-LIKE METHODS
662
+ # -------------------------------------------------
663
+
664
+
665
+ def _class_getnewargs(obj):
666
+ type_kwargs = {}
667
+ if "__module__" in obj.__dict__:
668
+ type_kwargs["__module__"] = obj.__module__
669
+
670
+ __dict__ = obj.__dict__.get("__dict__", None)
671
+ if isinstance(__dict__, property):
672
+ type_kwargs["__dict__"] = __dict__
673
+
674
+ return (
675
+ type(obj),
676
+ obj.__name__,
677
+ _get_bases(obj),
678
+ type_kwargs,
679
+ _get_or_create_tracker_id(obj),
680
+ None,
681
+ )
682
+
683
+
684
+ def _enum_getnewargs(obj):
685
+ members = {e.name: e.value for e in obj}
686
+ return (
687
+ obj.__bases__,
688
+ obj.__name__,
689
+ obj.__qualname__,
690
+ members,
691
+ obj.__module__,
692
+ _get_or_create_tracker_id(obj),
693
+ None,
694
+ )
695
+
696
+
697
+ # COLLECTION OF OBJECTS RECONSTRUCTORS
698
+ # ------------------------------------
699
+ def _file_reconstructor(retval):
700
+ return retval
701
+
702
+
703
+ # COLLECTION OF OBJECTS STATE GETTERS
704
+ # -----------------------------------
705
+
706
+
707
+ def _function_getstate(func):
708
+ # - Put func's dynamic attributes (stored in func.__dict__) in state. These
709
+ # attributes will be restored at unpickling time using
710
+ # f.__dict__.update(state)
711
+ # - Put func's members into slotstate. Such attributes will be restored at
712
+ # unpickling time by iterating over slotstate and calling setattr(func,
713
+ # slotname, slotvalue)
714
+ slotstate = {
715
+ # Hack to circumvent non-predictable memoization caused by string interning.
716
+ # See the inline comment in _class_setstate for details.
717
+ "__name__": "".join(func.__name__),
718
+ "__qualname__": "".join(func.__qualname__),
719
+ "__annotations__": func.__annotations__,
720
+ "__kwdefaults__": func.__kwdefaults__,
721
+ "__defaults__": func.__defaults__,
722
+ "__module__": func.__module__,
723
+ "__doc__": func.__doc__,
724
+ "__closure__": func.__closure__,
725
+ }
726
+
727
+ f_globals_ref = _extract_code_globals(func.__code__)
728
+ f_globals = {k: func.__globals__[k] for k in f_globals_ref if k in func.__globals__}
729
+
730
+ if func.__closure__ is not None:
731
+ closure_values = list(map(_get_cell_contents, func.__closure__))
732
+ else:
733
+ closure_values = ()
734
+
735
+ # Extract currently-imported submodules used by func. Storing these modules
736
+ # in a smoke _cloudpickle_subimports attribute of the object's state will
737
+ # trigger the side effect of importing these modules at unpickling time
738
+ # (which is necessary for func to work correctly once depickled)
739
+ slotstate["_cloudpickle_submodules"] = _find_imported_submodules(
740
+ func.__code__, itertools.chain(f_globals.values(), closure_values)
741
+ )
742
+ slotstate["__globals__"] = f_globals
743
+
744
+ # Hack to circumvent non-predictable memoization caused by string interning.
745
+ # See the inline comment in _class_setstate for details.
746
+ state = {"".join(k): v for k, v in func.__dict__.items()}
747
+ return state, slotstate
748
+
749
+
750
+ def _class_getstate(obj):
751
+ clsdict = _extract_class_dict(obj)
752
+ clsdict.pop("__weakref__", None)
753
+
754
+ if issubclass(type(obj), abc.ABCMeta):
755
+ # If obj is an instance of an ABCMeta subclass, don't pickle the
756
+ # cache/negative caches populated during isinstance/issubclass
757
+ # checks, but pickle the list of registered subclasses of obj.
758
+ clsdict.pop("_abc_cache", None)
759
+ clsdict.pop("_abc_negative_cache", None)
760
+ clsdict.pop("_abc_negative_cache_version", None)
761
+ registry = clsdict.pop("_abc_registry", None)
762
+ if registry is None:
763
+ # The abc caches and registered subclasses of a
764
+ # class are bundled into the single _abc_impl attribute
765
+ clsdict.pop("_abc_impl", None)
766
+ (registry, _, _, _) = abc._get_dump(obj)
767
+
768
+ clsdict["_abc_impl"] = [subclass_weakref() for subclass_weakref in registry]
769
+ else:
770
+ # In the above if clause, registry is a set of weakrefs -- in
771
+ # this case, registry is a WeakSet
772
+ clsdict["_abc_impl"] = [type_ for type_ in registry]
773
+
774
+ if "__slots__" in clsdict:
775
+ # pickle string length optimization: member descriptors of obj are
776
+ # created automatically from obj's __slots__ attribute, no need to
777
+ # save them in obj's state
778
+ if isinstance(obj.__slots__, str):
779
+ clsdict.pop(obj.__slots__)
780
+ else:
781
+ for k in obj.__slots__:
782
+ clsdict.pop(k, None)
783
+
784
+ clsdict.pop("__dict__", None) # unpicklable property object
785
+
786
+ if sys.version_info >= (3, 14):
787
+ # PEP-649/749: __annotate_func__ contains a closure that references the class
788
+ # dict. We need to exclude it from pickling. Python will recreate it when
789
+ # __annotations__ is accessed at unpickling time.
790
+ clsdict.pop("__annotate_func__", None)
791
+
792
+ return (clsdict, {})
793
+
794
+
795
+ def _enum_getstate(obj):
796
+ clsdict, slotstate = _class_getstate(obj)
797
+
798
+ members = {e.name: e.value for e in obj}
799
+ # Cleanup the clsdict that will be passed to _make_skeleton_enum:
800
+ # Those attributes are already handled by the metaclass.
801
+ for attrname in [
802
+ "_generate_next_value_",
803
+ "_member_names_",
804
+ "_member_map_",
805
+ "_member_type_",
806
+ "_value2member_map_",
807
+ ]:
808
+ clsdict.pop(attrname, None)
809
+ for member in members:
810
+ clsdict.pop(member)
811
+ # Special handling of Enum subclasses
812
+ return clsdict, slotstate
813
+
814
+
815
+ # COLLECTIONS OF OBJECTS REDUCERS
816
+ # -------------------------------
817
+ # A reducer is a function taking a single argument (obj), and that returns a
818
+ # tuple with all the necessary data to re-construct obj. Apart from a few
819
+ # exceptions (list, dict, bytes, int, etc.), a reducer is necessary to
820
+ # correctly pickle an object.
821
+ # While many built-in objects (Exceptions objects, instances of the "object"
822
+ # class, etc), are shipped with their own built-in reducer (invoked using
823
+ # obj.__reduce__), some do not. The following methods were created to "fill
824
+ # these holes".
825
+
826
+
827
+ def _code_reduce(obj):
828
+ """code object reducer."""
829
+ # If you are not sure about the order of arguments, take a look at help
830
+ # of the specific type from types, for example:
831
+ # >>> from types import CodeType
832
+ # >>> help(CodeType)
833
+
834
+ # Hack to circumvent non-predictable memoization caused by string interning.
835
+ # See the inline comment in _class_setstate for details.
836
+ co_name = "".join(obj.co_name)
837
+
838
+ # Create shallow copies of these tuple to make cloudpickle payload deterministic.
839
+ # When creating a code object during load, copies of these four tuples are
840
+ # created, while in the main process, these tuples can be shared.
841
+ # By always creating copies, we make sure the resulting payload is deterministic.
842
+ co_names = tuple(name for name in obj.co_names)
843
+ co_varnames = tuple(name for name in obj.co_varnames)
844
+ co_freevars = tuple(name for name in obj.co_freevars)
845
+ co_cellvars = tuple(name for name in obj.co_cellvars)
846
+ if hasattr(obj, "co_exceptiontable"):
847
+ # Python 3.11 and later: there are some new attributes
848
+ # related to the enhanced exceptions.
849
+ args = (
850
+ obj.co_argcount,
851
+ obj.co_posonlyargcount,
852
+ obj.co_kwonlyargcount,
853
+ obj.co_nlocals,
854
+ obj.co_stacksize,
855
+ obj.co_flags,
856
+ obj.co_code,
857
+ obj.co_consts,
858
+ co_names,
859
+ co_varnames,
860
+ obj.co_filename,
861
+ co_name,
862
+ obj.co_qualname,
863
+ obj.co_firstlineno,
864
+ obj.co_linetable,
865
+ obj.co_exceptiontable,
866
+ co_freevars,
867
+ co_cellvars,
868
+ )
869
+ elif hasattr(obj, "co_linetable"):
870
+ # Python 3.10 and later: obj.co_lnotab is deprecated and constructor
871
+ # expects obj.co_linetable instead.
872
+ args = (
873
+ obj.co_argcount,
874
+ obj.co_posonlyargcount,
875
+ obj.co_kwonlyargcount,
876
+ obj.co_nlocals,
877
+ obj.co_stacksize,
878
+ obj.co_flags,
879
+ obj.co_code,
880
+ obj.co_consts,
881
+ co_names,
882
+ co_varnames,
883
+ obj.co_filename,
884
+ co_name,
885
+ obj.co_firstlineno,
886
+ obj.co_linetable,
887
+ co_freevars,
888
+ co_cellvars,
889
+ )
890
+ elif hasattr(obj, "co_nmeta"): # pragma: no cover
891
+ # "nogil" Python: modified attributes from 3.9
892
+ args = (
893
+ obj.co_argcount,
894
+ obj.co_posonlyargcount,
895
+ obj.co_kwonlyargcount,
896
+ obj.co_nlocals,
897
+ obj.co_framesize,
898
+ obj.co_ndefaultargs,
899
+ obj.co_nmeta,
900
+ obj.co_flags,
901
+ obj.co_code,
902
+ obj.co_consts,
903
+ co_varnames,
904
+ obj.co_filename,
905
+ co_name,
906
+ obj.co_firstlineno,
907
+ obj.co_lnotab,
908
+ obj.co_exc_handlers,
909
+ obj.co_jump_table,
910
+ co_freevars,
911
+ co_cellvars,
912
+ obj.co_free2reg,
913
+ obj.co_cell2reg,
914
+ )
915
+ else:
916
+ # Backward compat for 3.8 and 3.9
917
+ args = (
918
+ obj.co_argcount,
919
+ obj.co_posonlyargcount,
920
+ obj.co_kwonlyargcount,
921
+ obj.co_nlocals,
922
+ obj.co_stacksize,
923
+ obj.co_flags,
924
+ obj.co_code,
925
+ obj.co_consts,
926
+ co_names,
927
+ co_varnames,
928
+ obj.co_filename,
929
+ co_name,
930
+ obj.co_firstlineno,
931
+ obj.co_lnotab,
932
+ co_freevars,
933
+ co_cellvars,
934
+ )
935
+ return types.CodeType, args
936
+
937
+
938
+ def _cell_reduce(obj):
939
+ """Cell (containing values of a function's free variables) reducer."""
940
+ try:
941
+ obj.cell_contents
942
+ except ValueError: # cell is empty
943
+ return _make_empty_cell, ()
944
+ else:
945
+ return _make_cell, (obj.cell_contents,)
946
+
947
+
948
+ def _classmethod_reduce(obj):
949
+ orig_func = obj.__func__
950
+ return type(obj), (orig_func,)
951
+
952
+
953
+ def _file_reduce(obj):
954
+ """Save a file."""
955
+ import io
956
+
957
+ if not hasattr(obj, "name") or not hasattr(obj, "mode"):
958
+ raise pickle.PicklingError(
959
+ "Cannot pickle files that do not map to an actual file"
960
+ )
961
+ if obj is sys.stdout:
962
+ return getattr, (sys, "stdout")
963
+ if obj is sys.stderr:
964
+ return getattr, (sys, "stderr")
965
+ if obj is sys.stdin:
966
+ raise pickle.PicklingError("Cannot pickle standard input")
967
+ if obj.closed:
968
+ raise pickle.PicklingError("Cannot pickle closed files")
969
+ if hasattr(obj, "isatty") and obj.isatty():
970
+ raise pickle.PicklingError("Cannot pickle files that map to tty objects")
971
+ if "r" not in obj.mode and "+" not in obj.mode:
972
+ raise pickle.PicklingError(
973
+ "Cannot pickle files that are not opened for reading: %s" % obj.mode
974
+ )
975
+
976
+ name = obj.name
977
+
978
+ retval = io.StringIO()
979
+
980
+ try:
981
+ # Read the whole file
982
+ curloc = obj.tell()
983
+ obj.seek(0)
984
+ contents = obj.read()
985
+ obj.seek(curloc)
986
+ except OSError as e:
987
+ raise pickle.PicklingError(
988
+ "Cannot pickle file %s as it cannot be read" % name
989
+ ) from e
990
+ retval.write(contents)
991
+ retval.seek(curloc)
992
+
993
+ retval.name = name
994
+ return _file_reconstructor, (retval,)
995
+
996
+
997
+ def _getset_descriptor_reduce(obj):
998
+ return getattr, (obj.__objclass__, obj.__name__)
999
+
1000
+
1001
+ def _mappingproxy_reduce(obj):
1002
+ return types.MappingProxyType, (dict(obj),)
1003
+
1004
+
1005
+ def _memoryview_reduce(obj):
1006
+ return bytes, (obj.tobytes(),)
1007
+
1008
+
1009
+ def _module_reduce(obj):
1010
+ if _should_pickle_by_reference(obj):
1011
+ return subimport, (obj.__name__,)
1012
+ else:
1013
+ # Some external libraries can populate the "__builtins__" entry of a
1014
+ # module's `__dict__` with unpicklable objects (see #316). For that
1015
+ # reason, we do not attempt to pickle the "__builtins__" entry, and
1016
+ # restore a default value for it at unpickling time.
1017
+ state = obj.__dict__.copy()
1018
+ state.pop("__builtins__", None)
1019
+ return dynamic_subimport, (obj.__name__, state)
1020
+
1021
+
1022
+ def _method_reduce(obj):
1023
+ return (types.MethodType, (obj.__func__, obj.__self__))
1024
+
1025
+
1026
+ def _logger_reduce(obj):
1027
+ return logging.getLogger, (obj.name,)
1028
+
1029
+
1030
+ def _root_logger_reduce(obj):
1031
+ return logging.getLogger, ()
1032
+
1033
+
1034
+ def _property_reduce(obj):
1035
+ return property, (obj.fget, obj.fset, obj.fdel, obj.__doc__)
1036
+
1037
+
1038
+ def _weakset_reduce(obj):
1039
+ return weakref.WeakSet, (list(obj),)
1040
+
1041
+
1042
+ def _dynamic_class_reduce(obj):
1043
+ """Save a class that can't be referenced as a module attribute.
1044
+
1045
+ This method is used to serialize classes that are defined inside
1046
+ functions, or that otherwise can't be serialized as attribute lookups
1047
+ from importable modules.
1048
+ """
1049
+ if Enum is not None and issubclass(obj, Enum):
1050
+ return (
1051
+ _make_skeleton_enum,
1052
+ _enum_getnewargs(obj),
1053
+ _enum_getstate(obj),
1054
+ None,
1055
+ None,
1056
+ _class_setstate,
1057
+ )
1058
+ else:
1059
+ return (
1060
+ _make_skeleton_class,
1061
+ _class_getnewargs(obj),
1062
+ _class_getstate(obj),
1063
+ None,
1064
+ None,
1065
+ _class_setstate,
1066
+ )
1067
+
1068
+
1069
+ def _class_reduce(obj):
1070
+ """Select the reducer depending on the dynamic nature of the class obj."""
1071
+ if obj is type(None): # noqa
1072
+ return type, (None,)
1073
+ elif obj is type(Ellipsis):
1074
+ return type, (Ellipsis,)
1075
+ elif obj is type(NotImplemented):
1076
+ return type, (NotImplemented,)
1077
+ elif obj in _BUILTIN_TYPE_NAMES:
1078
+ return _builtin_type, (_BUILTIN_TYPE_NAMES[obj],)
1079
+ elif not _should_pickle_by_reference(obj):
1080
+ return _dynamic_class_reduce(obj)
1081
+ return NotImplemented
1082
+
1083
+
1084
+ def _dict_keys_reduce(obj):
1085
+ # Safer not to ship the full dict as sending the rest might
1086
+ # be unintended and could potentially cause leaking of
1087
+ # sensitive information
1088
+ return _make_dict_keys, (list(obj),)
1089
+
1090
+
1091
+ def _dict_values_reduce(obj):
1092
+ # Safer not to ship the full dict as sending the rest might
1093
+ # be unintended and could potentially cause leaking of
1094
+ # sensitive information
1095
+ return _make_dict_values, (list(obj),)
1096
+
1097
+
1098
+ def _dict_items_reduce(obj):
1099
+ return _make_dict_items, (dict(obj),)
1100
+
1101
+
1102
+ def _odict_keys_reduce(obj):
1103
+ # Safer not to ship the full dict as sending the rest might
1104
+ # be unintended and could potentially cause leaking of
1105
+ # sensitive information
1106
+ return _make_dict_keys, (list(obj), True)
1107
+
1108
+
1109
+ def _odict_values_reduce(obj):
1110
+ # Safer not to ship the full dict as sending the rest might
1111
+ # be unintended and could potentially cause leaking of
1112
+ # sensitive information
1113
+ return _make_dict_values, (list(obj), True)
1114
+
1115
+
1116
+ def _odict_items_reduce(obj):
1117
+ return _make_dict_items, (dict(obj), True)
1118
+
1119
+
1120
+ def _dataclass_field_base_reduce(obj):
1121
+ return _get_dataclass_field_type_sentinel, (obj.name,)
1122
+
1123
+
1124
+ # COLLECTIONS OF OBJECTS STATE SETTERS
1125
+ # ------------------------------------
1126
+ # state setters are called at unpickling time, once the object is created and
1127
+ # it has to be updated to how it was at unpickling time.
1128
+
1129
+
1130
+ def _function_setstate(obj, state):
1131
+ """Update the state of a dynamic function.
1132
+
1133
+ As __closure__ and __globals__ are readonly attributes of a function, we
1134
+ cannot rely on the native setstate routine of pickle.load_build, that calls
1135
+ setattr on items of the slotstate. Instead, we have to modify them inplace.
1136
+ """
1137
+ state, slotstate = state
1138
+ obj.__dict__.update(state)
1139
+
1140
+ obj_globals = slotstate.pop("__globals__")
1141
+ obj_closure = slotstate.pop("__closure__")
1142
+ # _cloudpickle_subimports is a set of submodules that must be loaded for
1143
+ # the pickled function to work correctly at unpickling time. Now that these
1144
+ # submodules are depickled (hence imported), they can be removed from the
1145
+ # object's state (the object state only served as a reference holder to
1146
+ # these submodules)
1147
+ slotstate.pop("_cloudpickle_submodules")
1148
+
1149
+ obj.__globals__.update(obj_globals)
1150
+ obj.__globals__["__builtins__"] = __builtins__
1151
+
1152
+ if obj_closure is not None:
1153
+ for i, cell in enumerate(obj_closure):
1154
+ try:
1155
+ value = cell.cell_contents
1156
+ except ValueError: # cell is empty
1157
+ continue
1158
+ obj.__closure__[i].cell_contents = value
1159
+
1160
+ for k, v in slotstate.items():
1161
+ setattr(obj, k, v)
1162
+
1163
+
1164
+ def _class_setstate(obj, state):
1165
+ state, slotstate = state
1166
+ registry = None
1167
+ for attrname, attr in state.items():
1168
+ if attrname == "_abc_impl":
1169
+ registry = attr
1170
+ else:
1171
+ # Note: setting attribute names on a class automatically triggers their
1172
+ # interning in CPython:
1173
+ # https://github.com/python/cpython/blob/v3.12.0/Objects/object.c#L957
1174
+ #
1175
+ # This means that to get deterministic pickling for a dynamic class that
1176
+ # was initially defined in a different Python process, the pickler
1177
+ # needs to ensure that dynamic class and function attribute names are
1178
+ # systematically copied into a non-interned version to avoid
1179
+ # unpredictable pickle payloads.
1180
+ #
1181
+ # Indeed the Pickler's memoizer relies on physical object identity to break
1182
+ # cycles in the reference graph of the object being serialized.
1183
+ setattr(obj, attrname, attr)
1184
+
1185
+ if sys.version_info >= (3, 13) and "__firstlineno__" in state:
1186
+ # Set the Python 3.13+ only __firstlineno__ attribute one more time, as it
1187
+ # will be automatically deleted by the `setattr(obj, attrname, attr)` call
1188
+ # above when `attrname` is "__firstlineno__". We assume that preserving this
1189
+ # information might be important for some users and that it not stale in the
1190
+ # context of cloudpickle usage, hence legitimate to propagate. Furthermore it
1191
+ # is necessary to do so to keep deterministic chained pickling as tested in
1192
+ # test_deterministic_str_interning_for_chained_dynamic_class_pickling.
1193
+ obj.__firstlineno__ = state["__firstlineno__"]
1194
+
1195
+ if registry is not None:
1196
+ for subclass in registry:
1197
+ obj.register(subclass)
1198
+
1199
+ # PEP-649/749: During pickling, we excluded the __annotate_func__ attribute but it
1200
+ # will be created by Python. Subsequently, annotations will be recreated when
1201
+ # __annotations__ is accessed.
1202
+
1203
+ return obj
1204
+
1205
+
1206
+ # COLLECTION OF DATACLASS UTILITIES
1207
+ # ---------------------------------
1208
+ # There are some internal sentinel values whose identity must be preserved when
1209
+ # unpickling dataclass fields. Each sentinel value has a unique name that we can
1210
+ # use to retrieve its identity at unpickling time.
1211
+
1212
+
1213
+ _DATACLASSE_FIELD_TYPE_SENTINELS = {
1214
+ dataclasses._FIELD.name: dataclasses._FIELD,
1215
+ dataclasses._FIELD_CLASSVAR.name: dataclasses._FIELD_CLASSVAR,
1216
+ dataclasses._FIELD_INITVAR.name: dataclasses._FIELD_INITVAR,
1217
+ }
1218
+
1219
+
1220
+ def _get_dataclass_field_type_sentinel(name):
1221
+ return _DATACLASSE_FIELD_TYPE_SENTINELS[name]
1222
+
1223
+
1224
+ class Pickler(pickle.Pickler):
1225
+ # set of reducers defined and used by cloudpickle (private)
1226
+ _dispatch_table = {}
1227
+ _dispatch_table[classmethod] = _classmethod_reduce
1228
+ _dispatch_table[io.TextIOWrapper] = _file_reduce
1229
+ _dispatch_table[logging.Logger] = _logger_reduce
1230
+ _dispatch_table[logging.RootLogger] = _root_logger_reduce
1231
+ _dispatch_table[memoryview] = _memoryview_reduce
1232
+ _dispatch_table[property] = _property_reduce
1233
+ _dispatch_table[staticmethod] = _classmethod_reduce
1234
+ _dispatch_table[CellType] = _cell_reduce
1235
+ _dispatch_table[types.CodeType] = _code_reduce
1236
+ _dispatch_table[types.GetSetDescriptorType] = _getset_descriptor_reduce
1237
+ _dispatch_table[types.ModuleType] = _module_reduce
1238
+ _dispatch_table[types.MethodType] = _method_reduce
1239
+ _dispatch_table[types.MappingProxyType] = _mappingproxy_reduce
1240
+ _dispatch_table[weakref.WeakSet] = _weakset_reduce
1241
+ _dispatch_table[typing.TypeVar] = _typevar_reduce
1242
+ _dispatch_table[_collections_abc.dict_keys] = _dict_keys_reduce
1243
+ _dispatch_table[_collections_abc.dict_values] = _dict_values_reduce
1244
+ _dispatch_table[_collections_abc.dict_items] = _dict_items_reduce
1245
+ _dispatch_table[type(OrderedDict().keys())] = _odict_keys_reduce
1246
+ _dispatch_table[type(OrderedDict().values())] = _odict_values_reduce
1247
+ _dispatch_table[type(OrderedDict().items())] = _odict_items_reduce
1248
+ _dispatch_table[abc.abstractmethod] = _classmethod_reduce
1249
+ _dispatch_table[abc.abstractclassmethod] = _classmethod_reduce
1250
+ _dispatch_table[abc.abstractstaticmethod] = _classmethod_reduce
1251
+ _dispatch_table[abc.abstractproperty] = _property_reduce
1252
+ _dispatch_table[dataclasses._FIELD_BASE] = _dataclass_field_base_reduce
1253
+
1254
+ dispatch_table = ChainMap(_dispatch_table, copyreg.dispatch_table)
1255
+
1256
+ # function reducers are defined as instance methods of cloudpickle.Pickler
1257
+ # objects, as they rely on a cloudpickle.Pickler attribute (globals_ref)
1258
+ def _dynamic_function_reduce(self, func):
1259
+ """Reduce a function that is not pickleable via attribute lookup."""
1260
+ newargs = self._function_getnewargs(func)
1261
+ state = _function_getstate(func)
1262
+ return (_make_function, newargs, state, None, None, _function_setstate)
1263
+
1264
+ def _function_reduce(self, obj):
1265
+ """Reducer for function objects.
1266
+
1267
+ If obj is a top-level attribute of a file-backed module, this reducer
1268
+ returns NotImplemented, making the cloudpickle.Pickler fall back to
1269
+ traditional pickle.Pickler routines to save obj. Otherwise, it reduces
1270
+ obj using a custom cloudpickle reducer designed specifically to handle
1271
+ dynamic functions.
1272
+ """
1273
+ if _should_pickle_by_reference(obj):
1274
+ return NotImplemented
1275
+ else:
1276
+ return self._dynamic_function_reduce(obj)
1277
+
1278
+ def _function_getnewargs(self, func):
1279
+ code = func.__code__
1280
+
1281
+ # base_globals represents the future global namespace of func at
1282
+ # unpickling time. Looking it up and storing it in
1283
+ # cloudpickle.Pickler.globals_ref allow functions sharing the same
1284
+ # globals at pickling time to also share them once unpickled, at one
1285
+ # condition: since globals_ref is an attribute of a cloudpickle.Pickler
1286
+ # instance, and that a new cloudpickle.Pickler is created each time
1287
+ # cloudpickle.dump or cloudpickle.dumps is called, functions also need
1288
+ # to be saved within the same invocation of
1289
+ # cloudpickle.dump/cloudpickle.dumps (for example:
1290
+ # cloudpickle.dumps([f1, f2])). There is no such limitation when using
1291
+ # cloudpickle.Pickler.dump, as long as the multiple invocations are
1292
+ # bound to the same cloudpickle.Pickler instance.
1293
+ base_globals = self.globals_ref.setdefault(id(func.__globals__), {})
1294
+
1295
+ if base_globals == {}:
1296
+ # Add module attributes used to resolve relative imports
1297
+ # instructions inside func.
1298
+ for k in ["__package__", "__name__", "__path__", "__file__"]:
1299
+ if k in func.__globals__:
1300
+ base_globals[k] = func.__globals__[k]
1301
+
1302
+ # Do not bind the free variables before the function is created to
1303
+ # avoid infinite recursion.
1304
+ if func.__closure__ is None:
1305
+ closure = None
1306
+ else:
1307
+ closure = tuple(_make_empty_cell() for _ in range(len(code.co_freevars)))
1308
+
1309
+ return code, base_globals, None, None, closure
1310
+
1311
+ def dump(self, obj):
1312
+ try:
1313
+ return super().dump(obj)
1314
+ except RecursionError as e:
1315
+ msg = "Could not pickle object as excessively deep recursion required."
1316
+ raise pickle.PicklingError(msg) from e
1317
+
1318
+ def __init__(self, file, protocol=None, buffer_callback=None):
1319
+ if protocol is None:
1320
+ protocol = DEFAULT_PROTOCOL
1321
+ super().__init__(file, protocol=protocol, buffer_callback=buffer_callback)
1322
+ # map functions __globals__ attribute ids, to ensure that functions
1323
+ # sharing the same global namespace at pickling time also share
1324
+ # their global namespace at unpickling time.
1325
+ self.globals_ref = {}
1326
+ self.proto = int(protocol)
1327
+
1328
+ if not PYPY:
1329
+ # pickle.Pickler is the C implementation of the CPython pickler and
1330
+ # therefore we rely on reduce_override method to customize the pickler
1331
+ # behavior.
1332
+
1333
+ # `cloudpickle.Pickler.dispatch` is only left for backward
1334
+ # compatibility - note that when using protocol 5,
1335
+ # `cloudpickle.Pickler.dispatch` is not an extension of
1336
+ # `pickle._Pickler.dispatch` dictionary, because `cloudpickle.Pickler`
1337
+ # subclasses the C-implemented `pickle.Pickler`, which does not expose
1338
+ # a `dispatch` attribute. Earlier versions of `cloudpickle.Pickler`
1339
+ # used `cloudpickle.Pickler.dispatch` as a class-level attribute
1340
+ # storing all reducers implemented by cloudpickle, but the attribute
1341
+ # name was not a great choice given because it would collide with a
1342
+ # similarly named attribute in the pure-Python `pickle._Pickler`
1343
+ # implementation in the standard library.
1344
+ dispatch = dispatch_table
1345
+
1346
+ # Implementation of the reducer_override callback, in order to
1347
+ # efficiently serialize dynamic functions and classes by subclassing
1348
+ # the C-implemented `pickle.Pickler`.
1349
+ # TODO: decorrelate reducer_override (which is tied to CPython's
1350
+ # implementation - would it make sense to backport it to pypy? - and
1351
+ # pickle's protocol 5 which is implementation agnostic. Currently, the
1352
+ # availability of both notions coincide on CPython's pickle, but it may
1353
+ # not be the case anymore when pypy implements protocol 5.
1354
+
1355
+ def reducer_override(self, obj):
1356
+ """Type-agnostic reducing callback for function and classes.
1357
+
1358
+ For performance reasons, subclasses of the C `pickle.Pickler` class
1359
+ cannot register custom reducers for functions and classes in the
1360
+ dispatch_table attribute. Reducers for such types must instead
1361
+ implemented via the special `reducer_override` method.
1362
+
1363
+ Note that this method will be called for any object except a few
1364
+ builtin-types (int, lists, dicts etc.), which differs from reducers
1365
+ in the Pickler's dispatch_table, each of them being invoked for
1366
+ objects of a specific type only.
1367
+
1368
+ This property comes in handy for classes: although most classes are
1369
+ instances of the ``type`` metaclass, some of them can be instances
1370
+ of other custom metaclasses (such as enum.EnumMeta for example). In
1371
+ particular, the metaclass will likely not be known in advance, and
1372
+ thus cannot be special-cased using an entry in the dispatch_table.
1373
+ reducer_override, among other things, allows us to register a
1374
+ reducer that will be called for any class, independently of its
1375
+ type.
1376
+
1377
+ Notes:
1378
+
1379
+ * reducer_override has the priority over dispatch_table-registered
1380
+ reducers.
1381
+ * reducer_override can be used to fix other limitations of
1382
+ cloudpickle for other types that suffered from type-specific
1383
+ reducers, such as Exceptions. See
1384
+ https://github.com/cloudpipe/cloudpickle/issues/248
1385
+ """
1386
+ t = type(obj)
1387
+ try:
1388
+ is_anyclass = issubclass(t, type)
1389
+ except TypeError: # t is not a class (old Boost; see SF #502085)
1390
+ is_anyclass = False
1391
+
1392
+ if is_anyclass:
1393
+ return _class_reduce(obj)
1394
+ elif isinstance(obj, types.FunctionType):
1395
+ return self._function_reduce(obj)
1396
+ else:
1397
+ # fallback to save_global, including the Pickler's
1398
+ # dispatch_table
1399
+ return NotImplemented
1400
+
1401
+ else:
1402
+ # When reducer_override is not available, hack the pure-Python
1403
+ # Pickler's types.FunctionType and type savers. Note: the type saver
1404
+ # must override Pickler.save_global, because pickle.py contains a
1405
+ # hard-coded call to save_global when pickling meta-classes.
1406
+ dispatch = pickle.Pickler.dispatch.copy()
1407
+
1408
+ def _save_reduce_pickle5(
1409
+ self,
1410
+ func,
1411
+ args,
1412
+ state=None,
1413
+ listitems=None,
1414
+ dictitems=None,
1415
+ state_setter=None,
1416
+ obj=None,
1417
+ ):
1418
+ save = self.save
1419
+ write = self.write
1420
+ self.save_reduce(
1421
+ func,
1422
+ args,
1423
+ state=None,
1424
+ listitems=listitems,
1425
+ dictitems=dictitems,
1426
+ obj=obj,
1427
+ )
1428
+ # backport of the Python 3.8 state_setter pickle operations
1429
+ save(state_setter)
1430
+ save(obj) # simple BINGET opcode as obj is already memoized.
1431
+ save(state)
1432
+ write(pickle.TUPLE2)
1433
+ # Trigger a state_setter(obj, state) function call.
1434
+ write(pickle.REDUCE)
1435
+ # The purpose of state_setter is to carry-out an
1436
+ # inplace modification of obj. We do not care about what the
1437
+ # method might return, so its output is eventually removed from
1438
+ # the stack.
1439
+ write(pickle.POP)
1440
+
1441
+ def save_global(self, obj, name=None, pack=struct.pack):
1442
+ """Main dispatch method.
1443
+
1444
+ The name of this method is somewhat misleading: all types get
1445
+ dispatched here.
1446
+ """
1447
+ if obj is type(None): # noqa
1448
+ return self.save_reduce(type, (None,), obj=obj)
1449
+ elif obj is type(Ellipsis):
1450
+ return self.save_reduce(type, (Ellipsis,), obj=obj)
1451
+ elif obj is type(NotImplemented):
1452
+ return self.save_reduce(type, (NotImplemented,), obj=obj)
1453
+ elif obj in _BUILTIN_TYPE_NAMES:
1454
+ return self.save_reduce(
1455
+ _builtin_type, (_BUILTIN_TYPE_NAMES[obj],), obj=obj
1456
+ )
1457
+
1458
+ if name is not None:
1459
+ super().save_global(obj, name=name)
1460
+ elif not _should_pickle_by_reference(obj, name=name):
1461
+ self._save_reduce_pickle5(*_dynamic_class_reduce(obj), obj=obj)
1462
+ else:
1463
+ super().save_global(obj, name=name)
1464
+
1465
+ dispatch[type] = save_global
1466
+
1467
+ def save_function(self, obj, name=None):
1468
+ """Registered with the dispatch to handle all function types.
1469
+
1470
+ Determines what kind of function obj is (e.g. lambda, defined at
1471
+ interactive prompt, etc) and handles the pickling appropriately.
1472
+ """
1473
+ if _should_pickle_by_reference(obj, name=name):
1474
+ return super().save_global(obj, name=name)
1475
+ elif PYPY and isinstance(obj.__code__, builtin_code_type):
1476
+ return self.save_pypy_builtin_func(obj)
1477
+ else:
1478
+ return self._save_reduce_pickle5(
1479
+ *self._dynamic_function_reduce(obj), obj=obj
1480
+ )
1481
+
1482
+ def save_pypy_builtin_func(self, obj):
1483
+ """Save pypy equivalent of builtin functions.
1484
+
1485
+ PyPy does not have the concept of builtin-functions. Instead,
1486
+ builtin-functions are simple function instances, but with a
1487
+ builtin-code attribute.
1488
+ Most of the time, builtin functions should be pickled by attribute.
1489
+ But PyPy has flaky support for __qualname__, so some builtin
1490
+ functions such as float.__new__ will be classified as dynamic. For
1491
+ this reason only, we created this special routine. Because
1492
+ builtin-functions are not expected to have closure or globals,
1493
+ there is no additional hack (compared the one already implemented
1494
+ in pickle) to protect ourselves from reference cycles. A simple
1495
+ (reconstructor, newargs, obj.__dict__) tuple is save_reduced. Note
1496
+ also that PyPy improved their support for __qualname__ in v3.6, so
1497
+ this routing should be removed when cloudpickle supports only PyPy
1498
+ 3.6 and later.
1499
+ """
1500
+ rv = (
1501
+ types.FunctionType,
1502
+ (obj.__code__, {}, obj.__name__, obj.__defaults__, obj.__closure__),
1503
+ obj.__dict__,
1504
+ )
1505
+ self.save_reduce(*rv, obj=obj)
1506
+
1507
+ dispatch[types.FunctionType] = save_function
1508
+
1509
+
1510
+ # Shorthands similar to pickle.dump/pickle.dumps
1511
+
1512
+
1513
+ def dump(obj, file, protocol=None, buffer_callback=None):
1514
+ """Serialize obj as bytes streamed into file
1515
+
1516
+ protocol defaults to cloudpickle.DEFAULT_PROTOCOL which is an alias to
1517
+ pickle.HIGHEST_PROTOCOL. This setting favors maximum communication
1518
+ speed between processes running the same Python version.
1519
+
1520
+ Set protocol=pickle.DEFAULT_PROTOCOL instead if you need to ensure
1521
+ compatibility with older versions of Python (although this is not always
1522
+ guaranteed to work because cloudpickle relies on some internal
1523
+ implementation details that can change from one Python version to the
1524
+ next).
1525
+ """
1526
+ Pickler(file, protocol=protocol, buffer_callback=buffer_callback).dump(obj)
1527
+
1528
+
1529
+ def dumps(obj, protocol=None, buffer_callback=None):
1530
+ """Serialize obj as a string of bytes allocated in memory
1531
+
1532
+ protocol defaults to cloudpickle.DEFAULT_PROTOCOL which is an alias to
1533
+ pickle.HIGHEST_PROTOCOL. This setting favors maximum communication
1534
+ speed between processes running the same Python version.
1535
+
1536
+ Set protocol=pickle.DEFAULT_PROTOCOL instead if you need to ensure
1537
+ compatibility with older versions of Python (although this is not always
1538
+ guaranteed to work because cloudpickle relies on some internal
1539
+ implementation details that can change from one Python version to the
1540
+ next).
1541
+ """
1542
+ with io.BytesIO() as file:
1543
+ cp = Pickler(file, protocol=protocol, buffer_callback=buffer_callback)
1544
+ cp.dump(obj)
1545
+ return file.getvalue()
1546
+
1547
+
1548
+ # Include pickles unloading functions in this namespace for convenience.
1549
+ load, loads = pickle.load, pickle.loads
1550
+
1551
+ # Backward compat alias.
1552
+ CloudPickler = Pickler
lib/python3.12/site-packages/cloudpickle/cloudpickle_fast.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compatibility module.
2
+
3
+ It can be necessary to load files generated by previous versions of cloudpickle
4
+ that rely on symbols being defined under the `cloudpickle.cloudpickle_fast`
5
+ namespace.
6
+
7
+ See: tests/test_backward_compat.py
8
+ """
9
+
10
+ from . import cloudpickle
11
+
12
+
13
+ def __getattr__(name):
14
+ return getattr(cloudpickle, name)
lib/python3.12/site-packages/ninja-1.13.0.dist-info/INSTALLER ADDED
@@ -0,0 +1 @@
 
 
1
+ pip
lib/python3.12/site-packages/ninja-1.13.0.dist-info/METADATA ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.1
2
+ Name: ninja
3
+ Version: 1.13.0
4
+ Summary: Ninja is a small build system with a focus on speed
5
+ Keywords: build,c++,cross-compilation,cross-platform,fortran,ninja
6
+ Author-Email: Jean-Christophe Fillion-Robin <scikit-build@googlegroups.com>, Henry Schreiner <henryfs@princeton.edu>
7
+ Classifier: Development Status :: 5 - Production/Stable
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Classifier: License :: OSI Approved :: BSD License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: C
13
+ Classifier: Programming Language :: C++
14
+ Classifier: Programming Language :: Fortran
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Topic :: Software Development :: Build Tools
17
+ Classifier: Typing :: Typed
18
+ Project-URL: Bug Tracker, https://github.com/scikit-build/ninja-python-distributions/issues
19
+ Project-URL: Documentation, https://github.com/scikit-build/ninja-python-distributions#readme
20
+ Project-URL: Download, https://github.com/ninja-build/ninja/releases
21
+ Project-URL: Homepage, http://ninja-build.org/
22
+ Project-URL: Mailing list, https://groups.google.com/forum/#!forum/scikit-build
23
+ Project-URL: Source Code, https://github.com/scikit-build/ninja-python-distributions
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/x-rst
26
+
27
+ ==========================
28
+ Ninja Python Distributions
29
+ ==========================
30
+
31
+ `Ninja <http://www.ninja-build.org>`_ is a small build system with a focus on speed.
32
+
33
+ The latest Ninja python wheels provide `ninja 1.13.0.gd74ef.kitware.jobserver-pipe-1 <https://ninja-build.org/manual.html>`_ executable
34
+ and `ninja_syntax.py` for generating `.ninja` files.
35
+
36
+ .. image:: https://raw.githubusercontent.com/scikit-build/ninja-python-distributions/master/ninja-python-distributions-logo.png
37
+
38
+ Latest Release
39
+ --------------
40
+
41
+ .. table::
42
+
43
+ +----------------------------------------------------------------------+---------------------------------------------------------------------------+
44
+ | Versions | Downloads |
45
+ +======================================================================+===========================================================================+
46
+ | .. image:: https://img.shields.io/pypi/v/ninja.svg | .. image:: https://img.shields.io/badge/downloads-2535k%20total-green.svg |
47
+ | :target: https://pypi.python.org/pypi/ninja | :target: https://pypi.python.org/pypi/ninja |
48
+ +----------------------------------------------------------------------+---------------------------------------------------------------------------+
49
+
50
+ Build Status
51
+ ------------
52
+
53
+ .. table::
54
+
55
+ +---------------+-------------------------------------------------------------------------------------------------------------+
56
+ | | GitHub Actions (Windows, macOS, Linux) |
57
+ +===============+=============================================================================================================+
58
+ | PyPI | .. image:: https://github.com/scikit-build/ninja-python-distributions/actions/workflows/build.yml/badge.svg |
59
+ | | :target: https://github.com/scikit-build/ninja-python-distributions/actions/workflows/build.yml |
60
+ +---------------+-------------------------------------------------------------------------------------------------------------+
61
+
62
+ Maintainers
63
+ -----------
64
+
65
+ * `How to update ninja version ? <https://github.com/scikit-build/ninja-python-distributions/blob/master/docs/update_ninja_version.rst>`_
66
+
67
+ * `How to make a release ? <https://github.com/scikit-build/ninja-python-distributions/blob/master/docs/make_a_release.rst>`_
68
+
69
+
70
+ Miscellaneous
71
+ -------------
72
+
73
+ * Documentation: https://github.com/scikit-build/ninja-python-distributions#readme
74
+ * Source code: https://github.com/scikit-build/ninja-python-distributions
75
+ * Mailing list: https://groups.google.com/forum/#!forum/scikit-build
76
+
77
+ Python Version Support
78
+ ----------------------
79
+
80
+ Versions after 1.11.1.1 no longer support Python 2-3.6, and require manylinux2010+ on linux.
81
+ Versions after 1.13 no longer support Python 3.7, and require manylinux2014+/musllinux_1_2+ on linux.
82
+
83
+ License
84
+ -------
85
+
86
+ This project is maintained by Jean-Christophe Fillion-Robin from Kitware Inc.
87
+ It is covered by the `Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`_.
88
+
89
+ Ninja is also distributed under the `Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`_.
90
+ For more information about Ninja, visit https://ninja-build.org
91
+
92
+ Logo was originally created by Libby Rose from Kitware Inc.
93
+ It is covered by `CC BY 4.0 <https://creativecommons.org/licenses/by/4.0/>`_.
94
+
95
+
96
+ History
97
+ -------
98
+
99
+ ninja-python-distributions was initially developed in November 2016 by
100
+ Jean-Christophe Fillion-Robin to facilitate the distribution of project using
101
+ `scikit-build <http://scikit-build.readthedocs.io/>`_ and depending on CMake
102
+ and Ninja.
lib/python3.12/site-packages/ninja-1.13.0.dist-info/RECORD ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ../../../bin/ninja,sha256=aW-WKKednOUDFM-VVtfNGh0exSuP1Sgo9vnbFxlWW2c,372384
2
+ ninja-1.13.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
3
+ ninja-1.13.0.dist-info/METADATA,sha256=jXb8Tjgs7c0ivK6qdIrzmz-nkxtyRCOW0VyxgWWdCk4,5148
4
+ ninja-1.13.0.dist-info/RECORD,,
5
+ ninja-1.13.0.dist-info/WHEEL,sha256=zzOwTeuxXsHOT9QV_vcZk1hX9KJAUdqJD7e-2jGJxLA,150
6
+ ninja-1.13.0.dist-info/licenses/AUTHORS.rst,sha256=bGE1t_Lhm2ir8S7n_jbLDohP84fpJ5sNCuxvDVsKNQg,142
7
+ ninja-1.13.0.dist-info/licenses/LICENSE_Apache_20,sha256=c7p036pSC0mkAbXSFFmoUjoUbzt1GKgz7qXvqFEwv2g,10273
8
+ ninja/__init__.py,sha256=taDHI20kpmjxOT72PiSyE42Pvz3KLXlwMfTZvvnRMKM,1533
9
+ ninja/__main__.py,sha256=6iPLwHHAc2TMbojFVcUzERrzN0RvIsywuZc4KpJCg_4,100
10
+ ninja/__pycache__/__init__.cpython-312.pyc,,
11
+ ninja/__pycache__/__main__.cpython-312.pyc,,
12
+ ninja/__pycache__/_version.cpython-312.pyc,,
13
+ ninja/__pycache__/ninja_syntax.cpython-312.pyc,,
14
+ ninja/_version.py,sha256=M85oP8JJdZ4yZHcp9qfGYLKUYvnN3kTyQosVcYPCPow,19
15
+ ninja/_version.pyi,sha256=j5kbzfm6lOn8BzASXWjGIA1yT0OlHTWqlbyZ8Si_o0E,118
16
+ ninja/ninja_syntax.py,sha256=RCXZ6Roda3lwnbhtQw6I6bJcpE98mXUZ9jocnvC4IQY,8148
17
+ ninja/ninja_syntax.pyi,sha256=5IHH7N9CTKnMDDetFKHOsPK0SOSK_7Q4YtgzhIMNLE0,1576
18
+ ninja/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
lib/python3.12/site-packages/ninja-1.13.0.dist-info/WHEEL ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: scikit-build-core 0.11.5
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-manylinux_2_17_x86_64
5
+ Tag: py3-none-manylinux2014_x86_64
6
+
lib/python3.12/site-packages/ninja-1.13.0.dist-info/licenses/AUTHORS.rst ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ =======
2
+ Credits
3
+ =======
4
+
5
+ Please see the GitHub project page at https://github.com/scikit-build/ninja-python-distributions/graphs/contributors
lib/python3.12/site-packages/ninja-1.13.0.dist-info/licenses/LICENSE_Apache_20 ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction, and
10
+ distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by the copyright
13
+ owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all other entities
16
+ that control, are controlled by, or are under common control with that entity.
17
+ For the purposes of this definition, "control" means (i) the power, direct or
18
+ indirect, to cause the direction or management of such entity, whether by
19
+ contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20
+ outstanding shares, or (iii) beneficial ownership of such entity.
21
+
22
+ "You" (or "Your") shall mean an individual or Legal Entity exercising
23
+ permissions granted by this License.
24
+
25
+ "Source" form shall mean the preferred form for making modifications, including
26
+ but not limited to software source code, documentation source, and configuration
27
+ files.
28
+
29
+ "Object" form shall mean any form resulting from mechanical transformation or
30
+ translation of a Source form, including but not limited to compiled object code,
31
+ generated documentation, and conversions to other media types.
32
+
33
+ "Work" shall mean the work of authorship, whether in Source or Object form, made
34
+ available under the License, as indicated by a copyright notice that is included
35
+ in or attached to the work (an example is provided in the Appendix below).
36
+
37
+ "Derivative Works" shall mean any work, whether in Source or Object form, that
38
+ is based on (or derived from) the Work and for which the editorial revisions,
39
+ annotations, elaborations, or other modifications represent, as a whole, an
40
+ original work of authorship. For the purposes of this License, Derivative Works
41
+ shall not include works that remain separable from, or merely link (or bind by
42
+ name) to the interfaces of, the Work and Derivative Works thereof.
43
+
44
+ "Contribution" shall mean any work of authorship, including the original version
45
+ of the Work and any modifications or additions to that Work or Derivative Works
46
+ thereof, that is intentionally submitted to Licensor for inclusion in the Work
47
+ by the copyright owner or by an individual or Legal Entity authorized to submit
48
+ on behalf of the copyright owner. For the purposes of this definition,
49
+ "submitted" means any form of electronic, verbal, or written communication sent
50
+ to the Licensor or its representatives, including but not limited to
51
+ communication on electronic mailing lists, source code control systems, and
52
+ issue tracking systems that are managed by, or on behalf of, the Licensor for
53
+ the purpose of discussing and improving the Work, but excluding communication
54
+ that is conspicuously marked or otherwise designated in writing by the copyright
55
+ owner as "Not a Contribution."
56
+
57
+ "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
58
+ of whom a Contribution has been received by Licensor and subsequently
59
+ incorporated within the Work.
60
+
61
+ 2. Grant of Copyright License.
62
+
63
+ Subject to the terms and conditions of this License, each Contributor hereby
64
+ grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
65
+ irrevocable copyright license to reproduce, prepare Derivative Works of,
66
+ publicly display, publicly perform, sublicense, and distribute the Work and such
67
+ Derivative Works in Source or Object form.
68
+
69
+ 3. Grant of Patent License.
70
+
71
+ Subject to the terms and conditions of this License, each Contributor hereby
72
+ grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
73
+ irrevocable (except as stated in this section) patent license to make, have
74
+ made, use, offer to sell, sell, import, and otherwise transfer the Work, where
75
+ such license applies only to those patent claims licensable by such Contributor
76
+ that are necessarily infringed by their Contribution(s) alone or by combination
77
+ of their Contribution(s) with the Work to which such Contribution(s) was
78
+ submitted. If You institute patent litigation against any entity (including a
79
+ cross-claim or counterclaim in a lawsuit) alleging that the Work or a
80
+ Contribution incorporated within the Work constitutes direct or contributory
81
+ patent infringement, then any patent licenses granted to You under this License
82
+ for that Work shall terminate as of the date such litigation is filed.
83
+
84
+ 4. Redistribution.
85
+
86
+ You may reproduce and distribute copies of the Work or Derivative Works thereof
87
+ in any medium, with or without modifications, and in Source or Object form,
88
+ provided that You meet the following conditions:
89
+
90
+ You must give any other recipients of the Work or Derivative Works a copy of
91
+ this License; and
92
+ You must cause any modified files to carry prominent notices stating that You
93
+ changed the files; and
94
+ You must retain, in the Source form of any Derivative Works that You distribute,
95
+ all copyright, patent, trademark, and attribution notices from the Source form
96
+ of the Work, excluding those notices that do not pertain to any part of the
97
+ Derivative Works; and
98
+ If the Work includes a "NOTICE" text file as part of its distribution, then any
99
+ Derivative Works that You distribute must include a readable copy of the
100
+ attribution notices contained within such NOTICE file, excluding those notices
101
+ that do not pertain to any part of the Derivative Works, in at least one of the
102
+ following places: within a NOTICE text file distributed as part of the
103
+ Derivative Works; within the Source form or documentation, if provided along
104
+ with the Derivative Works; or, within a display generated by the Derivative
105
+ Works, if and wherever such third-party notices normally appear. The contents of
106
+ the NOTICE file are for informational purposes only and do not modify the
107
+ License. You may add Your own attribution notices within Derivative Works that
108
+ You distribute, alongside or as an addendum to the NOTICE text from the Work,
109
+ provided that such additional attribution notices cannot be construed as
110
+ modifying the License.
111
+ You may add Your own copyright statement to Your modifications and may provide
112
+ additional or different license terms and conditions for use, reproduction, or
113
+ distribution of Your modifications, or for any such Derivative Works as a whole,
114
+ provided Your use, reproduction, and distribution of the Work otherwise complies
115
+ with the conditions stated in this License.
116
+
117
+ 5. Submission of Contributions.
118
+
119
+ Unless You explicitly state otherwise, any Contribution intentionally submitted
120
+ for inclusion in the Work by You to the Licensor shall be under the terms and
121
+ conditions of this License, without any additional terms or conditions.
122
+ Notwithstanding the above, nothing herein shall supersede or modify the terms of
123
+ any separate license agreement you may have executed with Licensor regarding
124
+ such Contributions.
125
+
126
+ 6. Trademarks.
127
+
128
+ This License does not grant permission to use the trade names, trademarks,
129
+ service marks, or product names of the Licensor, except as required for
130
+ reasonable and customary use in describing the origin of the Work and
131
+ reproducing the content of the NOTICE file.
132
+
133
+ 7. Disclaimer of Warranty.
134
+
135
+ Unless required by applicable law or agreed to in writing, Licensor provides the
136
+ Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
137
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
138
+ including, without limitation, any warranties or conditions of TITLE,
139
+ NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
140
+ solely responsible for determining the appropriateness of using or
141
+ redistributing the Work and assume any risks associated with Your exercise of
142
+ permissions under this License.
143
+
144
+ 8. Limitation of Liability.
145
+
146
+ In no event and under no legal theory, whether in tort (including negligence),
147
+ contract, or otherwise, unless required by applicable law (such as deliberate
148
+ and grossly negligent acts) or agreed to in writing, shall any Contributor be
149
+ liable to You for damages, including any direct, indirect, special, incidental,
150
+ or consequential damages of any character arising as a result of this License or
151
+ out of the use or inability to use the Work (including but not limited to
152
+ damages for loss of goodwill, work stoppage, computer failure or malfunction, or
153
+ any and all other commercial damages or losses), even if such Contributor has
154
+ been advised of the possibility of such damages.
155
+
156
+ 9. Accepting Warranty or Additional Liability.
157
+
158
+ While redistributing the Work or Derivative Works thereof, You may choose to
159
+ offer, and charge a fee for, acceptance of support, warranty, indemnity, or
160
+ other liability obligations and/or rights consistent with this License. However,
161
+ in accepting such obligations, You may act only on Your own behalf and on Your
162
+ sole responsibility, not on behalf of any other Contributor, and only if You
163
+ agree to indemnify, defend, and hold each Contributor harmless for any liability
164
+ incurred by, or claims asserted against, such Contributor by reason of your
165
+ accepting any such warranty or additional liability.
166
+
167
+ END OF TERMS AND CONDITIONS
168
+
169
+ APPENDIX: How to apply the Apache License to your work
170
+
171
+ To apply the Apache License to your work, attach the following boilerplate
172
+ notice, with the fields enclosed by brackets "[]" replaced with your own
173
+ identifying information. (Don't include the brackets!) The text should be
174
+ enclosed in the appropriate comment syntax for the file format. We also
175
+ recommend that a file or class name and description of purpose be included on
176
+ the same "printed page" as the copyright notice for easier identification within
177
+ third-party archives.
178
+
179
+ Copyright [yyyy] [name of copyright owner]
180
+
181
+ Licensed under the Apache License, Version 2.0 (the "License");
182
+ you may not use this file except in compliance with the License.
183
+ You may obtain a copy of the License at
184
+
185
+ http://www.apache.org/licenses/LICENSE-2.0
186
+
187
+ Unless required by applicable law or agreed to in writing, software
188
+ distributed under the License is distributed on an "AS IS" BASIS,
189
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190
+ See the License for the specific language governing permissions and
191
+ limitations under the License.
lib/python3.12/site-packages/numpy/__config__.py ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is generated by numpy's build process
2
+ # It contains system_info results at the time of building this package.
3
+ from enum import Enum
4
+ from numpy.core._multiarray_umath import (
5
+ __cpu_features__,
6
+ __cpu_baseline__,
7
+ __cpu_dispatch__,
8
+ )
9
+
10
+ __all__ = ["show"]
11
+ _built_with_meson = True
12
+
13
+
14
+ class DisplayModes(Enum):
15
+ stdout = "stdout"
16
+ dicts = "dicts"
17
+
18
+
19
+ def _cleanup(d):
20
+ """
21
+ Removes empty values in a `dict` recursively
22
+ This ensures we remove values that Meson could not provide to CONFIG
23
+ """
24
+ if isinstance(d, dict):
25
+ return {k: _cleanup(v) for k, v in d.items() if v and _cleanup(v)}
26
+ else:
27
+ return d
28
+
29
+
30
+ CONFIG = _cleanup(
31
+ {
32
+ "Compilers": {
33
+ "c": {
34
+ "name": "gcc",
35
+ "linker": r"ld.bfd",
36
+ "version": "10.2.1",
37
+ "commands": r"cc",
38
+ "args": r"-fno-strict-aliasing",
39
+ "linker args": r"-Wl,--strip-debug, -fno-strict-aliasing",
40
+ },
41
+ "cython": {
42
+ "name": "cython",
43
+ "linker": r"cython",
44
+ "version": "3.0.8",
45
+ "commands": r"cython",
46
+ "args": r"",
47
+ "linker args": r"",
48
+ },
49
+ "c++": {
50
+ "name": "gcc",
51
+ "linker": r"ld.bfd",
52
+ "version": "10.2.1",
53
+ "commands": r"c++",
54
+ "args": r"",
55
+ "linker args": r"-Wl,--strip-debug",
56
+ },
57
+ },
58
+ "Machine Information": {
59
+ "host": {
60
+ "cpu": "x86_64",
61
+ "family": "x86_64",
62
+ "endian": "little",
63
+ "system": "linux",
64
+ },
65
+ "build": {
66
+ "cpu": "x86_64",
67
+ "family": "x86_64",
68
+ "endian": "little",
69
+ "system": "linux",
70
+ },
71
+ "cross-compiled": bool("False".lower().replace("false", "")),
72
+ },
73
+ "Build Dependencies": {
74
+ "blas": {
75
+ "name": "openblas64",
76
+ "found": bool("True".lower().replace("false", "")),
77
+ "version": "0.3.23.dev",
78
+ "detection method": "pkgconfig",
79
+ "include directory": r"/usr/local/include",
80
+ "lib directory": r"/usr/local/lib",
81
+ "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",
82
+ "pc file directory": r"/usr/local/lib/pkgconfig",
83
+ },
84
+ "lapack": {
85
+ "name": "dep140551260102944",
86
+ "found": bool("True".lower().replace("false", "")),
87
+ "version": "1.26.4",
88
+ "detection method": "internal",
89
+ "include directory": r"unknown",
90
+ "lib directory": r"unknown",
91
+ "openblas configuration": r"unknown",
92
+ "pc file directory": r"unknown",
93
+ },
94
+ },
95
+ "Python Information": {
96
+ "path": r"/opt/python/cp312-cp312/bin/python",
97
+ "version": "3.12",
98
+ },
99
+ "SIMD Extensions": {
100
+ "baseline": __cpu_baseline__,
101
+ "found": [
102
+ feature for feature in __cpu_dispatch__ if __cpu_features__[feature]
103
+ ],
104
+ "not found": [
105
+ feature for feature in __cpu_dispatch__ if not __cpu_features__[feature]
106
+ ],
107
+ },
108
+ }
109
+ )
110
+
111
+
112
+ def _check_pyyaml():
113
+ import yaml
114
+
115
+ return yaml
116
+
117
+
118
+ def show(mode=DisplayModes.stdout.value):
119
+ """
120
+ Show libraries and system information on which NumPy was built
121
+ and is being used
122
+
123
+ Parameters
124
+ ----------
125
+ mode : {`'stdout'`, `'dicts'`}, optional.
126
+ Indicates how to display the config information.
127
+ `'stdout'` prints to console, `'dicts'` returns a dictionary
128
+ of the configuration.
129
+
130
+ Returns
131
+ -------
132
+ out : {`dict`, `None`}
133
+ If mode is `'dicts'`, a dict is returned, else None
134
+
135
+ See Also
136
+ --------
137
+ get_include : Returns the directory containing NumPy C
138
+ header files.
139
+
140
+ Notes
141
+ -----
142
+ 1. The `'stdout'` mode will give more readable
143
+ output if ``pyyaml`` is installed
144
+
145
+ """
146
+ if mode == DisplayModes.stdout.value:
147
+ try: # Non-standard library, check import
148
+ yaml = _check_pyyaml()
149
+
150
+ print(yaml.dump(CONFIG))
151
+ except ModuleNotFoundError:
152
+ import warnings
153
+ import json
154
+
155
+ warnings.warn("Install `pyyaml` for better output", stacklevel=1)
156
+ print(json.dumps(CONFIG, indent=2))
157
+ elif mode == DisplayModes.dicts.value:
158
+ return CONFIG
159
+ else:
160
+ raise AttributeError(
161
+ f"Invalid `mode`, use one of: {', '.join([e.value for e in DisplayModes])}"
162
+ )
lib/python3.12/site-packages/numpy/__init__.cython-30.pxd ADDED
@@ -0,0 +1,1050 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NumPy static imports for Cython >= 3.0
2
+ #
3
+ # If any of the PyArray_* functions are called, import_array must be
4
+ # called first. This is done automatically by Cython 3.0+ if a call
5
+ # is not detected inside of the module.
6
+ #
7
+ # Author: Dag Sverre Seljebotn
8
+ #
9
+
10
+ from cpython.ref cimport Py_INCREF
11
+ from cpython.object cimport PyObject, PyTypeObject, PyObject_TypeCheck
12
+ cimport libc.stdio as stdio
13
+
14
+
15
+ cdef extern from *:
16
+ # Leave a marker that the NumPy declarations came from NumPy itself and not from Cython.
17
+ # See https://github.com/cython/cython/issues/3573
18
+ """
19
+ /* Using NumPy API declarations from "numpy/__init__.cython-30.pxd" */
20
+ """
21
+
22
+
23
+ cdef extern from "Python.h":
24
+ ctypedef int Py_intptr_t
25
+
26
+ cdef extern from "numpy/arrayobject.h":
27
+ ctypedef Py_intptr_t npy_intp
28
+ ctypedef size_t npy_uintp
29
+
30
+ cdef enum NPY_TYPES:
31
+ NPY_BOOL
32
+ NPY_BYTE
33
+ NPY_UBYTE
34
+ NPY_SHORT
35
+ NPY_USHORT
36
+ NPY_INT
37
+ NPY_UINT
38
+ NPY_LONG
39
+ NPY_ULONG
40
+ NPY_LONGLONG
41
+ NPY_ULONGLONG
42
+ NPY_FLOAT
43
+ NPY_DOUBLE
44
+ NPY_LONGDOUBLE
45
+ NPY_CFLOAT
46
+ NPY_CDOUBLE
47
+ NPY_CLONGDOUBLE
48
+ NPY_OBJECT
49
+ NPY_STRING
50
+ NPY_UNICODE
51
+ NPY_VOID
52
+ NPY_DATETIME
53
+ NPY_TIMEDELTA
54
+ NPY_NTYPES
55
+ NPY_NOTYPE
56
+
57
+ NPY_INT8
58
+ NPY_INT16
59
+ NPY_INT32
60
+ NPY_INT64
61
+ NPY_INT128
62
+ NPY_INT256
63
+ NPY_UINT8
64
+ NPY_UINT16
65
+ NPY_UINT32
66
+ NPY_UINT64
67
+ NPY_UINT128
68
+ NPY_UINT256
69
+ NPY_FLOAT16
70
+ NPY_FLOAT32
71
+ NPY_FLOAT64
72
+ NPY_FLOAT80
73
+ NPY_FLOAT96
74
+ NPY_FLOAT128
75
+ NPY_FLOAT256
76
+ NPY_COMPLEX32
77
+ NPY_COMPLEX64
78
+ NPY_COMPLEX128
79
+ NPY_COMPLEX160
80
+ NPY_COMPLEX192
81
+ NPY_COMPLEX256
82
+ NPY_COMPLEX512
83
+
84
+ NPY_INTP
85
+
86
+ ctypedef enum NPY_ORDER:
87
+ NPY_ANYORDER
88
+ NPY_CORDER
89
+ NPY_FORTRANORDER
90
+ NPY_KEEPORDER
91
+
92
+ ctypedef enum NPY_CASTING:
93
+ NPY_NO_CASTING
94
+ NPY_EQUIV_CASTING
95
+ NPY_SAFE_CASTING
96
+ NPY_SAME_KIND_CASTING
97
+ NPY_UNSAFE_CASTING
98
+
99
+ ctypedef enum NPY_CLIPMODE:
100
+ NPY_CLIP
101
+ NPY_WRAP
102
+ NPY_RAISE
103
+
104
+ ctypedef enum NPY_SCALARKIND:
105
+ NPY_NOSCALAR,
106
+ NPY_BOOL_SCALAR,
107
+ NPY_INTPOS_SCALAR,
108
+ NPY_INTNEG_SCALAR,
109
+ NPY_FLOAT_SCALAR,
110
+ NPY_COMPLEX_SCALAR,
111
+ NPY_OBJECT_SCALAR
112
+
113
+ ctypedef enum NPY_SORTKIND:
114
+ NPY_QUICKSORT
115
+ NPY_HEAPSORT
116
+ NPY_MERGESORT
117
+
118
+ ctypedef enum NPY_SEARCHSIDE:
119
+ NPY_SEARCHLEFT
120
+ NPY_SEARCHRIGHT
121
+
122
+ enum:
123
+ # DEPRECATED since NumPy 1.7 ! Do not use in new code!
124
+ NPY_C_CONTIGUOUS
125
+ NPY_F_CONTIGUOUS
126
+ NPY_CONTIGUOUS
127
+ NPY_FORTRAN
128
+ NPY_OWNDATA
129
+ NPY_FORCECAST
130
+ NPY_ENSURECOPY
131
+ NPY_ENSUREARRAY
132
+ NPY_ELEMENTSTRIDES
133
+ NPY_ALIGNED
134
+ NPY_NOTSWAPPED
135
+ NPY_WRITEABLE
136
+ NPY_ARR_HAS_DESCR
137
+
138
+ NPY_BEHAVED
139
+ NPY_BEHAVED_NS
140
+ NPY_CARRAY
141
+ NPY_CARRAY_RO
142
+ NPY_FARRAY
143
+ NPY_FARRAY_RO
144
+ NPY_DEFAULT
145
+
146
+ NPY_IN_ARRAY
147
+ NPY_OUT_ARRAY
148
+ NPY_INOUT_ARRAY
149
+ NPY_IN_FARRAY
150
+ NPY_OUT_FARRAY
151
+ NPY_INOUT_FARRAY
152
+
153
+ NPY_UPDATE_ALL
154
+
155
+ enum:
156
+ # Added in NumPy 1.7 to replace the deprecated enums above.
157
+ NPY_ARRAY_C_CONTIGUOUS
158
+ NPY_ARRAY_F_CONTIGUOUS
159
+ NPY_ARRAY_OWNDATA
160
+ NPY_ARRAY_FORCECAST
161
+ NPY_ARRAY_ENSURECOPY
162
+ NPY_ARRAY_ENSUREARRAY
163
+ NPY_ARRAY_ELEMENTSTRIDES
164
+ NPY_ARRAY_ALIGNED
165
+ NPY_ARRAY_NOTSWAPPED
166
+ NPY_ARRAY_WRITEABLE
167
+ NPY_ARRAY_WRITEBACKIFCOPY
168
+
169
+ NPY_ARRAY_BEHAVED
170
+ NPY_ARRAY_BEHAVED_NS
171
+ NPY_ARRAY_CARRAY
172
+ NPY_ARRAY_CARRAY_RO
173
+ NPY_ARRAY_FARRAY
174
+ NPY_ARRAY_FARRAY_RO
175
+ NPY_ARRAY_DEFAULT
176
+
177
+ NPY_ARRAY_IN_ARRAY
178
+ NPY_ARRAY_OUT_ARRAY
179
+ NPY_ARRAY_INOUT_ARRAY
180
+ NPY_ARRAY_IN_FARRAY
181
+ NPY_ARRAY_OUT_FARRAY
182
+ NPY_ARRAY_INOUT_FARRAY
183
+
184
+ NPY_ARRAY_UPDATE_ALL
185
+
186
+ cdef enum:
187
+ NPY_MAXDIMS
188
+
189
+ npy_intp NPY_MAX_ELSIZE
190
+
191
+ ctypedef void (*PyArray_VectorUnaryFunc)(void *, void *, npy_intp, void *, void *)
192
+
193
+ ctypedef struct PyArray_ArrayDescr:
194
+ # shape is a tuple, but Cython doesn't support "tuple shape"
195
+ # inside a non-PyObject declaration, so we have to declare it
196
+ # as just a PyObject*.
197
+ PyObject* shape
198
+
199
+ ctypedef struct PyArray_Descr:
200
+ pass
201
+
202
+ ctypedef class numpy.dtype [object PyArray_Descr, check_size ignore]:
203
+ # Use PyDataType_* macros when possible, however there are no macros
204
+ # for accessing some of the fields, so some are defined.
205
+ cdef PyTypeObject* typeobj
206
+ cdef char kind
207
+ cdef char type
208
+ # Numpy sometimes mutates this without warning (e.g. it'll
209
+ # sometimes change "|" to "<" in shared dtype objects on
210
+ # little-endian machines). If this matters to you, use
211
+ # PyArray_IsNativeByteOrder(dtype.byteorder) instead of
212
+ # directly accessing this field.
213
+ cdef char byteorder
214
+ cdef char flags
215
+ cdef int type_num
216
+ cdef int itemsize "elsize"
217
+ cdef int alignment
218
+ cdef object fields
219
+ cdef tuple names
220
+ # Use PyDataType_HASSUBARRAY to test whether this field is
221
+ # valid (the pointer can be NULL). Most users should access
222
+ # this field via the inline helper method PyDataType_SHAPE.
223
+ cdef PyArray_ArrayDescr* subarray
224
+
225
+ ctypedef class numpy.flatiter [object PyArrayIterObject, check_size ignore]:
226
+ # Use through macros
227
+ pass
228
+
229
+ ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]:
230
+ # Use through macros
231
+ pass
232
+
233
+ ctypedef struct PyArrayObject:
234
+ # For use in situations where ndarray can't replace PyArrayObject*,
235
+ # like PyArrayObject**.
236
+ pass
237
+
238
+ ctypedef class numpy.ndarray [object PyArrayObject, check_size ignore]:
239
+ cdef __cythonbufferdefaults__ = {"mode": "strided"}
240
+
241
+ # NOTE: no field declarations since direct access is deprecated since NumPy 1.7
242
+ # Instead, we use properties that map to the corresponding C-API functions.
243
+
244
+ @property
245
+ cdef inline PyObject* base(self) nogil:
246
+ """Returns a borrowed reference to the object owning the data/memory.
247
+ """
248
+ return PyArray_BASE(self)
249
+
250
+ @property
251
+ cdef inline dtype descr(self):
252
+ """Returns an owned reference to the dtype of the array.
253
+ """
254
+ return <dtype>PyArray_DESCR(self)
255
+
256
+ @property
257
+ cdef inline int ndim(self) nogil:
258
+ """Returns the number of dimensions in the array.
259
+ """
260
+ return PyArray_NDIM(self)
261
+
262
+ @property
263
+ cdef inline npy_intp *shape(self) nogil:
264
+ """Returns a pointer to the dimensions/shape of the array.
265
+ The number of elements matches the number of dimensions of the array (ndim).
266
+ Can return NULL for 0-dimensional arrays.
267
+ """
268
+ return PyArray_DIMS(self)
269
+
270
+ @property
271
+ cdef inline npy_intp *strides(self) nogil:
272
+ """Returns a pointer to the strides of the array.
273
+ The number of elements matches the number of dimensions of the array (ndim).
274
+ """
275
+ return PyArray_STRIDES(self)
276
+
277
+ @property
278
+ cdef inline npy_intp size(self) nogil:
279
+ """Returns the total size (in number of elements) of the array.
280
+ """
281
+ return PyArray_SIZE(self)
282
+
283
+ @property
284
+ cdef inline char* data(self) nogil:
285
+ """The pointer to the data buffer as a char*.
286
+ This is provided for legacy reasons to avoid direct struct field access.
287
+ For new code that needs this access, you probably want to cast the result
288
+ of `PyArray_DATA()` instead, which returns a 'void*'.
289
+ """
290
+ return PyArray_BYTES(self)
291
+
292
+ ctypedef unsigned char npy_bool
293
+
294
+ ctypedef signed char npy_byte
295
+ ctypedef signed short npy_short
296
+ ctypedef signed int npy_int
297
+ ctypedef signed long npy_long
298
+ ctypedef signed long long npy_longlong
299
+
300
+ ctypedef unsigned char npy_ubyte
301
+ ctypedef unsigned short npy_ushort
302
+ ctypedef unsigned int npy_uint
303
+ ctypedef unsigned long npy_ulong
304
+ ctypedef unsigned long long npy_ulonglong
305
+
306
+ ctypedef float npy_float
307
+ ctypedef double npy_double
308
+ ctypedef long double npy_longdouble
309
+
310
+ ctypedef signed char npy_int8
311
+ ctypedef signed short npy_int16
312
+ ctypedef signed int npy_int32
313
+ ctypedef signed long long npy_int64
314
+ ctypedef signed long long npy_int96
315
+ ctypedef signed long long npy_int128
316
+
317
+ ctypedef unsigned char npy_uint8
318
+ ctypedef unsigned short npy_uint16
319
+ ctypedef unsigned int npy_uint32
320
+ ctypedef unsigned long long npy_uint64
321
+ ctypedef unsigned long long npy_uint96
322
+ ctypedef unsigned long long npy_uint128
323
+
324
+ ctypedef float npy_float32
325
+ ctypedef double npy_float64
326
+ ctypedef long double npy_float80
327
+ ctypedef long double npy_float96
328
+ ctypedef long double npy_float128
329
+
330
+ ctypedef struct npy_cfloat:
331
+ float real
332
+ float imag
333
+
334
+ ctypedef struct npy_cdouble:
335
+ double real
336
+ double imag
337
+
338
+ ctypedef struct npy_clongdouble:
339
+ long double real
340
+ long double imag
341
+
342
+ ctypedef struct npy_complex64:
343
+ float real
344
+ float imag
345
+
346
+ ctypedef struct npy_complex128:
347
+ double real
348
+ double imag
349
+
350
+ ctypedef struct npy_complex160:
351
+ long double real
352
+ long double imag
353
+
354
+ ctypedef struct npy_complex192:
355
+ long double real
356
+ long double imag
357
+
358
+ ctypedef struct npy_complex256:
359
+ long double real
360
+ long double imag
361
+
362
+ ctypedef struct PyArray_Dims:
363
+ npy_intp *ptr
364
+ int len
365
+
366
+ int _import_array() except -1
367
+ # A second definition so _import_array isn't marked as used when we use it here.
368
+ # Do not use - subject to change any time.
369
+ int __pyx_import_array "_import_array"() except -1
370
+
371
+ #
372
+ # Macros from ndarrayobject.h
373
+ #
374
+ bint PyArray_CHKFLAGS(ndarray m, int flags) nogil
375
+ bint PyArray_IS_C_CONTIGUOUS(ndarray arr) nogil
376
+ bint PyArray_IS_F_CONTIGUOUS(ndarray arr) nogil
377
+ bint PyArray_ISCONTIGUOUS(ndarray m) nogil
378
+ bint PyArray_ISWRITEABLE(ndarray m) nogil
379
+ bint PyArray_ISALIGNED(ndarray m) nogil
380
+
381
+ int PyArray_NDIM(ndarray) nogil
382
+ bint PyArray_ISONESEGMENT(ndarray) nogil
383
+ bint PyArray_ISFORTRAN(ndarray) nogil
384
+ int PyArray_FORTRANIF(ndarray) nogil
385
+
386
+ void* PyArray_DATA(ndarray) nogil
387
+ char* PyArray_BYTES(ndarray) nogil
388
+
389
+ npy_intp* PyArray_DIMS(ndarray) nogil
390
+ npy_intp* PyArray_STRIDES(ndarray) nogil
391
+ npy_intp PyArray_DIM(ndarray, size_t) nogil
392
+ npy_intp PyArray_STRIDE(ndarray, size_t) nogil
393
+
394
+ PyObject *PyArray_BASE(ndarray) nogil # returns borrowed reference!
395
+ PyArray_Descr *PyArray_DESCR(ndarray) nogil # returns borrowed reference to dtype!
396
+ PyArray_Descr *PyArray_DTYPE(ndarray) nogil # returns borrowed reference to dtype! NP 1.7+ alias for descr.
397
+ int PyArray_FLAGS(ndarray) nogil
398
+ void PyArray_CLEARFLAGS(ndarray, int flags) nogil # Added in NumPy 1.7
399
+ void PyArray_ENABLEFLAGS(ndarray, int flags) nogil # Added in NumPy 1.7
400
+ npy_intp PyArray_ITEMSIZE(ndarray) nogil
401
+ int PyArray_TYPE(ndarray arr) nogil
402
+
403
+ object PyArray_GETITEM(ndarray arr, void *itemptr)
404
+ int PyArray_SETITEM(ndarray arr, void *itemptr, object obj) except -1
405
+
406
+ bint PyTypeNum_ISBOOL(int) nogil
407
+ bint PyTypeNum_ISUNSIGNED(int) nogil
408
+ bint PyTypeNum_ISSIGNED(int) nogil
409
+ bint PyTypeNum_ISINTEGER(int) nogil
410
+ bint PyTypeNum_ISFLOAT(int) nogil
411
+ bint PyTypeNum_ISNUMBER(int) nogil
412
+ bint PyTypeNum_ISSTRING(int) nogil
413
+ bint PyTypeNum_ISCOMPLEX(int) nogil
414
+ bint PyTypeNum_ISPYTHON(int) nogil
415
+ bint PyTypeNum_ISFLEXIBLE(int) nogil
416
+ bint PyTypeNum_ISUSERDEF(int) nogil
417
+ bint PyTypeNum_ISEXTENDED(int) nogil
418
+ bint PyTypeNum_ISOBJECT(int) nogil
419
+
420
+ bint PyDataType_ISBOOL(dtype) nogil
421
+ bint PyDataType_ISUNSIGNED(dtype) nogil
422
+ bint PyDataType_ISSIGNED(dtype) nogil
423
+ bint PyDataType_ISINTEGER(dtype) nogil
424
+ bint PyDataType_ISFLOAT(dtype) nogil
425
+ bint PyDataType_ISNUMBER(dtype) nogil
426
+ bint PyDataType_ISSTRING(dtype) nogil
427
+ bint PyDataType_ISCOMPLEX(dtype) nogil
428
+ bint PyDataType_ISPYTHON(dtype) nogil
429
+ bint PyDataType_ISFLEXIBLE(dtype) nogil
430
+ bint PyDataType_ISUSERDEF(dtype) nogil
431
+ bint PyDataType_ISEXTENDED(dtype) nogil
432
+ bint PyDataType_ISOBJECT(dtype) nogil
433
+ bint PyDataType_HASFIELDS(dtype) nogil
434
+ bint PyDataType_HASSUBARRAY(dtype) nogil
435
+
436
+ bint PyArray_ISBOOL(ndarray) nogil
437
+ bint PyArray_ISUNSIGNED(ndarray) nogil
438
+ bint PyArray_ISSIGNED(ndarray) nogil
439
+ bint PyArray_ISINTEGER(ndarray) nogil
440
+ bint PyArray_ISFLOAT(ndarray) nogil
441
+ bint PyArray_ISNUMBER(ndarray) nogil
442
+ bint PyArray_ISSTRING(ndarray) nogil
443
+ bint PyArray_ISCOMPLEX(ndarray) nogil
444
+ bint PyArray_ISPYTHON(ndarray) nogil
445
+ bint PyArray_ISFLEXIBLE(ndarray) nogil
446
+ bint PyArray_ISUSERDEF(ndarray) nogil
447
+ bint PyArray_ISEXTENDED(ndarray) nogil
448
+ bint PyArray_ISOBJECT(ndarray) nogil
449
+ bint PyArray_HASFIELDS(ndarray) nogil
450
+
451
+ bint PyArray_ISVARIABLE(ndarray) nogil
452
+
453
+ bint PyArray_SAFEALIGNEDCOPY(ndarray) nogil
454
+ bint PyArray_ISNBO(char) nogil # works on ndarray.byteorder
455
+ bint PyArray_IsNativeByteOrder(char) nogil # works on ndarray.byteorder
456
+ bint PyArray_ISNOTSWAPPED(ndarray) nogil
457
+ bint PyArray_ISBYTESWAPPED(ndarray) nogil
458
+
459
+ bint PyArray_FLAGSWAP(ndarray, int) nogil
460
+
461
+ bint PyArray_ISCARRAY(ndarray) nogil
462
+ bint PyArray_ISCARRAY_RO(ndarray) nogil
463
+ bint PyArray_ISFARRAY(ndarray) nogil
464
+ bint PyArray_ISFARRAY_RO(ndarray) nogil
465
+ bint PyArray_ISBEHAVED(ndarray) nogil
466
+ bint PyArray_ISBEHAVED_RO(ndarray) nogil
467
+
468
+
469
+ bint PyDataType_ISNOTSWAPPED(dtype) nogil
470
+ bint PyDataType_ISBYTESWAPPED(dtype) nogil
471
+
472
+ bint PyArray_DescrCheck(object)
473
+
474
+ bint PyArray_Check(object)
475
+ bint PyArray_CheckExact(object)
476
+
477
+ # Cannot be supported due to out arg:
478
+ # bint PyArray_HasArrayInterfaceType(object, dtype, object, object&)
479
+ # bint PyArray_HasArrayInterface(op, out)
480
+
481
+
482
+ bint PyArray_IsZeroDim(object)
483
+ # Cannot be supported due to ## ## in macro:
484
+ # bint PyArray_IsScalar(object, verbatim work)
485
+ bint PyArray_CheckScalar(object)
486
+ bint PyArray_IsPythonNumber(object)
487
+ bint PyArray_IsPythonScalar(object)
488
+ bint PyArray_IsAnyScalar(object)
489
+ bint PyArray_CheckAnyScalar(object)
490
+
491
+ ndarray PyArray_GETCONTIGUOUS(ndarray)
492
+ bint PyArray_SAMESHAPE(ndarray, ndarray) nogil
493
+ npy_intp PyArray_SIZE(ndarray) nogil
494
+ npy_intp PyArray_NBYTES(ndarray) nogil
495
+
496
+ object PyArray_FROM_O(object)
497
+ object PyArray_FROM_OF(object m, int flags)
498
+ object PyArray_FROM_OT(object m, int type)
499
+ object PyArray_FROM_OTF(object m, int type, int flags)
500
+ object PyArray_FROMANY(object m, int type, int min, int max, int flags)
501
+ object PyArray_ZEROS(int nd, npy_intp* dims, int type, int fortran)
502
+ object PyArray_EMPTY(int nd, npy_intp* dims, int type, int fortran)
503
+ void PyArray_FILLWBYTE(object, int val)
504
+ npy_intp PyArray_REFCOUNT(object)
505
+ object PyArray_ContiguousFromAny(op, int, int min_depth, int max_depth)
506
+ unsigned char PyArray_EquivArrTypes(ndarray a1, ndarray a2)
507
+ bint PyArray_EquivByteorders(int b1, int b2) nogil
508
+ object PyArray_SimpleNew(int nd, npy_intp* dims, int typenum)
509
+ object PyArray_SimpleNewFromData(int nd, npy_intp* dims, int typenum, void* data)
510
+ #object PyArray_SimpleNewFromDescr(int nd, npy_intp* dims, dtype descr)
511
+ object PyArray_ToScalar(void* data, ndarray arr)
512
+
513
+ void* PyArray_GETPTR1(ndarray m, npy_intp i) nogil
514
+ void* PyArray_GETPTR2(ndarray m, npy_intp i, npy_intp j) nogil
515
+ void* PyArray_GETPTR3(ndarray m, npy_intp i, npy_intp j, npy_intp k) nogil
516
+ void* PyArray_GETPTR4(ndarray m, npy_intp i, npy_intp j, npy_intp k, npy_intp l) nogil
517
+
518
+ # Cannot be supported due to out arg
519
+ # void PyArray_DESCR_REPLACE(descr)
520
+
521
+
522
+ object PyArray_Copy(ndarray)
523
+ object PyArray_FromObject(object op, int type, int min_depth, int max_depth)
524
+ object PyArray_ContiguousFromObject(object op, int type, int min_depth, int max_depth)
525
+ object PyArray_CopyFromObject(object op, int type, int min_depth, int max_depth)
526
+
527
+ object PyArray_Cast(ndarray mp, int type_num)
528
+ object PyArray_Take(ndarray ap, object items, int axis)
529
+ object PyArray_Put(ndarray ap, object items, object values)
530
+
531
+ void PyArray_ITER_RESET(flatiter it) nogil
532
+ void PyArray_ITER_NEXT(flatiter it) nogil
533
+ void PyArray_ITER_GOTO(flatiter it, npy_intp* destination) nogil
534
+ void PyArray_ITER_GOTO1D(flatiter it, npy_intp ind) nogil
535
+ void* PyArray_ITER_DATA(flatiter it) nogil
536
+ bint PyArray_ITER_NOTDONE(flatiter it) nogil
537
+
538
+ void PyArray_MultiIter_RESET(broadcast multi) nogil
539
+ void PyArray_MultiIter_NEXT(broadcast multi) nogil
540
+ void PyArray_MultiIter_GOTO(broadcast multi, npy_intp dest) nogil
541
+ void PyArray_MultiIter_GOTO1D(broadcast multi, npy_intp ind) nogil
542
+ void* PyArray_MultiIter_DATA(broadcast multi, npy_intp i) nogil
543
+ void PyArray_MultiIter_NEXTi(broadcast multi, npy_intp i) nogil
544
+ bint PyArray_MultiIter_NOTDONE(broadcast multi) nogil
545
+
546
+ # Functions from __multiarray_api.h
547
+
548
+ # Functions taking dtype and returning object/ndarray are disabled
549
+ # for now as they steal dtype references. I'm conservative and disable
550
+ # more than is probably needed until it can be checked further.
551
+ int PyArray_SetNumericOps (object) except -1
552
+ object PyArray_GetNumericOps ()
553
+ int PyArray_INCREF (ndarray) except * # uses PyArray_Item_INCREF...
554
+ int PyArray_XDECREF (ndarray) except * # uses PyArray_Item_DECREF...
555
+ void PyArray_SetStringFunction (object, int)
556
+ dtype PyArray_DescrFromType (int)
557
+ object PyArray_TypeObjectFromType (int)
558
+ char * PyArray_Zero (ndarray)
559
+ char * PyArray_One (ndarray)
560
+ #object PyArray_CastToType (ndarray, dtype, int)
561
+ int PyArray_CastTo (ndarray, ndarray) except -1
562
+ int PyArray_CastAnyTo (ndarray, ndarray) except -1
563
+ int PyArray_CanCastSafely (int, int) # writes errors
564
+ npy_bool PyArray_CanCastTo (dtype, dtype) # writes errors
565
+ int PyArray_ObjectType (object, int) except 0
566
+ dtype PyArray_DescrFromObject (object, dtype)
567
+ #ndarray* PyArray_ConvertToCommonType (object, int *)
568
+ dtype PyArray_DescrFromScalar (object)
569
+ dtype PyArray_DescrFromTypeObject (object)
570
+ npy_intp PyArray_Size (object)
571
+ #object PyArray_Scalar (void *, dtype, object)
572
+ #object PyArray_FromScalar (object, dtype)
573
+ void PyArray_ScalarAsCtype (object, void *)
574
+ #int PyArray_CastScalarToCtype (object, void *, dtype)
575
+ #int PyArray_CastScalarDirect (object, dtype, void *, int)
576
+ object PyArray_ScalarFromObject (object)
577
+ #PyArray_VectorUnaryFunc * PyArray_GetCastFunc (dtype, int)
578
+ object PyArray_FromDims (int, int *, int)
579
+ #object PyArray_FromDimsAndDataAndDescr (int, int *, dtype, char *)
580
+ #object PyArray_FromAny (object, dtype, int, int, int, object)
581
+ object PyArray_EnsureArray (object)
582
+ object PyArray_EnsureAnyArray (object)
583
+ #object PyArray_FromFile (stdio.FILE *, dtype, npy_intp, char *)
584
+ #object PyArray_FromString (char *, npy_intp, dtype, npy_intp, char *)
585
+ #object PyArray_FromBuffer (object, dtype, npy_intp, npy_intp)
586
+ #object PyArray_FromIter (object, dtype, npy_intp)
587
+ object PyArray_Return (ndarray)
588
+ #object PyArray_GetField (ndarray, dtype, int)
589
+ #int PyArray_SetField (ndarray, dtype, int, object) except -1
590
+ object PyArray_Byteswap (ndarray, npy_bool)
591
+ object PyArray_Resize (ndarray, PyArray_Dims *, int, NPY_ORDER)
592
+ int PyArray_MoveInto (ndarray, ndarray) except -1
593
+ int PyArray_CopyInto (ndarray, ndarray) except -1
594
+ int PyArray_CopyAnyInto (ndarray, ndarray) except -1
595
+ int PyArray_CopyObject (ndarray, object) except -1
596
+ object PyArray_NewCopy (ndarray, NPY_ORDER)
597
+ object PyArray_ToList (ndarray)
598
+ object PyArray_ToString (ndarray, NPY_ORDER)
599
+ int PyArray_ToFile (ndarray, stdio.FILE *, char *, char *) except -1
600
+ int PyArray_Dump (object, object, int) except -1
601
+ object PyArray_Dumps (object, int)
602
+ int PyArray_ValidType (int) # Cannot error
603
+ void PyArray_UpdateFlags (ndarray, int)
604
+ object PyArray_New (type, int, npy_intp *, int, npy_intp *, void *, int, int, object)
605
+ #object PyArray_NewFromDescr (type, dtype, int, npy_intp *, npy_intp *, void *, int, object)
606
+ #dtype PyArray_DescrNew (dtype)
607
+ dtype PyArray_DescrNewFromType (int)
608
+ double PyArray_GetPriority (object, double) # clears errors as of 1.25
609
+ object PyArray_IterNew (object)
610
+ object PyArray_MultiIterNew (int, ...)
611
+
612
+ int PyArray_PyIntAsInt (object) except? -1
613
+ npy_intp PyArray_PyIntAsIntp (object)
614
+ int PyArray_Broadcast (broadcast) except -1
615
+ void PyArray_FillObjectArray (ndarray, object) except *
616
+ int PyArray_FillWithScalar (ndarray, object) except -1
617
+ npy_bool PyArray_CheckStrides (int, int, npy_intp, npy_intp, npy_intp *, npy_intp *)
618
+ dtype PyArray_DescrNewByteorder (dtype, char)
619
+ object PyArray_IterAllButAxis (object, int *)
620
+ #object PyArray_CheckFromAny (object, dtype, int, int, int, object)
621
+ #object PyArray_FromArray (ndarray, dtype, int)
622
+ object PyArray_FromInterface (object)
623
+ object PyArray_FromStructInterface (object)
624
+ #object PyArray_FromArrayAttr (object, dtype, object)
625
+ #NPY_SCALARKIND PyArray_ScalarKind (int, ndarray*)
626
+ int PyArray_CanCoerceScalar (int, int, NPY_SCALARKIND)
627
+ object PyArray_NewFlagsObject (object)
628
+ npy_bool PyArray_CanCastScalar (type, type)
629
+ #int PyArray_CompareUCS4 (npy_ucs4 *, npy_ucs4 *, register size_t)
630
+ int PyArray_RemoveSmallest (broadcast) except -1
631
+ int PyArray_ElementStrides (object)
632
+ void PyArray_Item_INCREF (char *, dtype) except *
633
+ void PyArray_Item_XDECREF (char *, dtype) except *
634
+ object PyArray_FieldNames (object)
635
+ object PyArray_Transpose (ndarray, PyArray_Dims *)
636
+ object PyArray_TakeFrom (ndarray, object, int, ndarray, NPY_CLIPMODE)
637
+ object PyArray_PutTo (ndarray, object, object, NPY_CLIPMODE)
638
+ object PyArray_PutMask (ndarray, object, object)
639
+ object PyArray_Repeat (ndarray, object, int)
640
+ object PyArray_Choose (ndarray, object, ndarray, NPY_CLIPMODE)
641
+ int PyArray_Sort (ndarray, int, NPY_SORTKIND) except -1
642
+ object PyArray_ArgSort (ndarray, int, NPY_SORTKIND)
643
+ object PyArray_SearchSorted (ndarray, object, NPY_SEARCHSIDE, PyObject *)
644
+ object PyArray_ArgMax (ndarray, int, ndarray)
645
+ object PyArray_ArgMin (ndarray, int, ndarray)
646
+ object PyArray_Reshape (ndarray, object)
647
+ object PyArray_Newshape (ndarray, PyArray_Dims *, NPY_ORDER)
648
+ object PyArray_Squeeze (ndarray)
649
+ #object PyArray_View (ndarray, dtype, type)
650
+ object PyArray_SwapAxes (ndarray, int, int)
651
+ object PyArray_Max (ndarray, int, ndarray)
652
+ object PyArray_Min (ndarray, int, ndarray)
653
+ object PyArray_Ptp (ndarray, int, ndarray)
654
+ object PyArray_Mean (ndarray, int, int, ndarray)
655
+ object PyArray_Trace (ndarray, int, int, int, int, ndarray)
656
+ object PyArray_Diagonal (ndarray, int, int, int)
657
+ object PyArray_Clip (ndarray, object, object, ndarray)
658
+ object PyArray_Conjugate (ndarray, ndarray)
659
+ object PyArray_Nonzero (ndarray)
660
+ object PyArray_Std (ndarray, int, int, ndarray, int)
661
+ object PyArray_Sum (ndarray, int, int, ndarray)
662
+ object PyArray_CumSum (ndarray, int, int, ndarray)
663
+ object PyArray_Prod (ndarray, int, int, ndarray)
664
+ object PyArray_CumProd (ndarray, int, int, ndarray)
665
+ object PyArray_All (ndarray, int, ndarray)
666
+ object PyArray_Any (ndarray, int, ndarray)
667
+ object PyArray_Compress (ndarray, object, int, ndarray)
668
+ object PyArray_Flatten (ndarray, NPY_ORDER)
669
+ object PyArray_Ravel (ndarray, NPY_ORDER)
670
+ npy_intp PyArray_MultiplyList (npy_intp *, int)
671
+ int PyArray_MultiplyIntList (int *, int)
672
+ void * PyArray_GetPtr (ndarray, npy_intp*)
673
+ int PyArray_CompareLists (npy_intp *, npy_intp *, int)
674
+ #int PyArray_AsCArray (object*, void *, npy_intp *, int, dtype)
675
+ #int PyArray_As1D (object*, char **, int *, int)
676
+ #int PyArray_As2D (object*, char ***, int *, int *, int)
677
+ int PyArray_Free (object, void *)
678
+ #int PyArray_Converter (object, object*)
679
+ int PyArray_IntpFromSequence (object, npy_intp *, int) except -1
680
+ object PyArray_Concatenate (object, int)
681
+ object PyArray_InnerProduct (object, object)
682
+ object PyArray_MatrixProduct (object, object)
683
+ object PyArray_CopyAndTranspose (object)
684
+ object PyArray_Correlate (object, object, int)
685
+ int PyArray_TypestrConvert (int, int)
686
+ #int PyArray_DescrConverter (object, dtype*) except 0
687
+ #int PyArray_DescrConverter2 (object, dtype*) except 0
688
+ int PyArray_IntpConverter (object, PyArray_Dims *) except 0
689
+ #int PyArray_BufferConverter (object, chunk) except 0
690
+ int PyArray_AxisConverter (object, int *) except 0
691
+ int PyArray_BoolConverter (object, npy_bool *) except 0
692
+ int PyArray_ByteorderConverter (object, char *) except 0
693
+ int PyArray_OrderConverter (object, NPY_ORDER *) except 0
694
+ unsigned char PyArray_EquivTypes (dtype, dtype) # clears errors
695
+ #object PyArray_Zeros (int, npy_intp *, dtype, int)
696
+ #object PyArray_Empty (int, npy_intp *, dtype, int)
697
+ object PyArray_Where (object, object, object)
698
+ object PyArray_Arange (double, double, double, int)
699
+ #object PyArray_ArangeObj (object, object, object, dtype)
700
+ int PyArray_SortkindConverter (object, NPY_SORTKIND *) except 0
701
+ object PyArray_LexSort (object, int)
702
+ object PyArray_Round (ndarray, int, ndarray)
703
+ unsigned char PyArray_EquivTypenums (int, int)
704
+ int PyArray_RegisterDataType (dtype) except -1
705
+ int PyArray_RegisterCastFunc (dtype, int, PyArray_VectorUnaryFunc *) except -1
706
+ int PyArray_RegisterCanCast (dtype, int, NPY_SCALARKIND) except -1
707
+ #void PyArray_InitArrFuncs (PyArray_ArrFuncs *)
708
+ object PyArray_IntTupleFromIntp (int, npy_intp *)
709
+ int PyArray_TypeNumFromName (char *)
710
+ int PyArray_ClipmodeConverter (object, NPY_CLIPMODE *) except 0
711
+ #int PyArray_OutputConverter (object, ndarray*) except 0
712
+ object PyArray_BroadcastToShape (object, npy_intp *, int)
713
+ void _PyArray_SigintHandler (int)
714
+ void* _PyArray_GetSigintBuf ()
715
+ #int PyArray_DescrAlignConverter (object, dtype*) except 0
716
+ #int PyArray_DescrAlignConverter2 (object, dtype*) except 0
717
+ int PyArray_SearchsideConverter (object, void *) except 0
718
+ object PyArray_CheckAxis (ndarray, int *, int)
719
+ npy_intp PyArray_OverflowMultiplyList (npy_intp *, int)
720
+ int PyArray_CompareString (char *, char *, size_t)
721
+ int PyArray_SetBaseObject(ndarray, base) except -1 # NOTE: steals a reference to base! Use "set_array_base()" instead.
722
+
723
+
724
+ # Typedefs that matches the runtime dtype objects in
725
+ # the numpy module.
726
+
727
+ # The ones that are commented out needs an IFDEF function
728
+ # in Cython to enable them only on the right systems.
729
+
730
+ ctypedef npy_int8 int8_t
731
+ ctypedef npy_int16 int16_t
732
+ ctypedef npy_int32 int32_t
733
+ ctypedef npy_int64 int64_t
734
+ #ctypedef npy_int96 int96_t
735
+ #ctypedef npy_int128 int128_t
736
+
737
+ ctypedef npy_uint8 uint8_t
738
+ ctypedef npy_uint16 uint16_t
739
+ ctypedef npy_uint32 uint32_t
740
+ ctypedef npy_uint64 uint64_t
741
+ #ctypedef npy_uint96 uint96_t
742
+ #ctypedef npy_uint128 uint128_t
743
+
744
+ ctypedef npy_float32 float32_t
745
+ ctypedef npy_float64 float64_t
746
+ #ctypedef npy_float80 float80_t
747
+ #ctypedef npy_float128 float128_t
748
+
749
+ ctypedef float complex complex64_t
750
+ ctypedef double complex complex128_t
751
+
752
+ # The int types are mapped a bit surprising --
753
+ # numpy.int corresponds to 'l' and numpy.long to 'q'
754
+ ctypedef npy_long int_t
755
+ ctypedef npy_longlong longlong_t
756
+
757
+ ctypedef npy_ulong uint_t
758
+ ctypedef npy_ulonglong ulonglong_t
759
+
760
+ ctypedef npy_intp intp_t
761
+ ctypedef npy_uintp uintp_t
762
+
763
+ ctypedef npy_double float_t
764
+ ctypedef npy_double double_t
765
+ ctypedef npy_longdouble longdouble_t
766
+
767
+ ctypedef npy_cfloat cfloat_t
768
+ ctypedef npy_cdouble cdouble_t
769
+ ctypedef npy_clongdouble clongdouble_t
770
+
771
+ ctypedef npy_cdouble complex_t
772
+
773
+ cdef inline object PyArray_MultiIterNew1(a):
774
+ return PyArray_MultiIterNew(1, <void*>a)
775
+
776
+ cdef inline object PyArray_MultiIterNew2(a, b):
777
+ return PyArray_MultiIterNew(2, <void*>a, <void*>b)
778
+
779
+ cdef inline object PyArray_MultiIterNew3(a, b, c):
780
+ return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)
781
+
782
+ cdef inline object PyArray_MultiIterNew4(a, b, c, d):
783
+ return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)
784
+
785
+ cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
786
+ return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)
787
+
788
+ cdef inline tuple PyDataType_SHAPE(dtype d):
789
+ if PyDataType_HASSUBARRAY(d):
790
+ return <tuple>d.subarray.shape
791
+ else:
792
+ return ()
793
+
794
+
795
+ cdef extern from "numpy/ndarrayobject.h":
796
+ PyTypeObject PyTimedeltaArrType_Type
797
+ PyTypeObject PyDatetimeArrType_Type
798
+ ctypedef int64_t npy_timedelta
799
+ ctypedef int64_t npy_datetime
800
+
801
+ cdef extern from "numpy/ndarraytypes.h":
802
+ ctypedef struct PyArray_DatetimeMetaData:
803
+ NPY_DATETIMEUNIT base
804
+ int64_t num
805
+
806
+ cdef extern from "numpy/arrayscalars.h":
807
+
808
+ # abstract types
809
+ ctypedef class numpy.generic [object PyObject]:
810
+ pass
811
+ ctypedef class numpy.number [object PyObject]:
812
+ pass
813
+ ctypedef class numpy.integer [object PyObject]:
814
+ pass
815
+ ctypedef class numpy.signedinteger [object PyObject]:
816
+ pass
817
+ ctypedef class numpy.unsignedinteger [object PyObject]:
818
+ pass
819
+ ctypedef class numpy.inexact [object PyObject]:
820
+ pass
821
+ ctypedef class numpy.floating [object PyObject]:
822
+ pass
823
+ ctypedef class numpy.complexfloating [object PyObject]:
824
+ pass
825
+ ctypedef class numpy.flexible [object PyObject]:
826
+ pass
827
+ ctypedef class numpy.character [object PyObject]:
828
+ pass
829
+
830
+ ctypedef struct PyDatetimeScalarObject:
831
+ # PyObject_HEAD
832
+ npy_datetime obval
833
+ PyArray_DatetimeMetaData obmeta
834
+
835
+ ctypedef struct PyTimedeltaScalarObject:
836
+ # PyObject_HEAD
837
+ npy_timedelta obval
838
+ PyArray_DatetimeMetaData obmeta
839
+
840
+ ctypedef enum NPY_DATETIMEUNIT:
841
+ NPY_FR_Y
842
+ NPY_FR_M
843
+ NPY_FR_W
844
+ NPY_FR_D
845
+ NPY_FR_B
846
+ NPY_FR_h
847
+ NPY_FR_m
848
+ NPY_FR_s
849
+ NPY_FR_ms
850
+ NPY_FR_us
851
+ NPY_FR_ns
852
+ NPY_FR_ps
853
+ NPY_FR_fs
854
+ NPY_FR_as
855
+ NPY_FR_GENERIC
856
+
857
+
858
+ #
859
+ # ufunc API
860
+ #
861
+
862
+ cdef extern from "numpy/ufuncobject.h":
863
+
864
+ ctypedef void (*PyUFuncGenericFunction) (char **, npy_intp *, npy_intp *, void *)
865
+
866
+ ctypedef class numpy.ufunc [object PyUFuncObject, check_size ignore]:
867
+ cdef:
868
+ int nin, nout, nargs
869
+ int identity
870
+ PyUFuncGenericFunction *functions
871
+ void **data
872
+ int ntypes
873
+ int check_return
874
+ char *name
875
+ char *types
876
+ char *doc
877
+ void *ptr
878
+ PyObject *obj
879
+ PyObject *userloops
880
+
881
+ cdef enum:
882
+ PyUFunc_Zero
883
+ PyUFunc_One
884
+ PyUFunc_None
885
+ UFUNC_ERR_IGNORE
886
+ UFUNC_ERR_WARN
887
+ UFUNC_ERR_RAISE
888
+ UFUNC_ERR_CALL
889
+ UFUNC_ERR_PRINT
890
+ UFUNC_ERR_LOG
891
+ UFUNC_MASK_DIVIDEBYZERO
892
+ UFUNC_MASK_OVERFLOW
893
+ UFUNC_MASK_UNDERFLOW
894
+ UFUNC_MASK_INVALID
895
+ UFUNC_SHIFT_DIVIDEBYZERO
896
+ UFUNC_SHIFT_OVERFLOW
897
+ UFUNC_SHIFT_UNDERFLOW
898
+ UFUNC_SHIFT_INVALID
899
+ UFUNC_FPE_DIVIDEBYZERO
900
+ UFUNC_FPE_OVERFLOW
901
+ UFUNC_FPE_UNDERFLOW
902
+ UFUNC_FPE_INVALID
903
+ UFUNC_ERR_DEFAULT
904
+ UFUNC_ERR_DEFAULT2
905
+
906
+ object PyUFunc_FromFuncAndData(PyUFuncGenericFunction *,
907
+ void **, char *, int, int, int, int, char *, char *, int)
908
+ int PyUFunc_RegisterLoopForType(ufunc, int,
909
+ PyUFuncGenericFunction, int *, void *) except -1
910
+ void PyUFunc_f_f_As_d_d \
911
+ (char **, npy_intp *, npy_intp *, void *)
912
+ void PyUFunc_d_d \
913
+ (char **, npy_intp *, npy_intp *, void *)
914
+ void PyUFunc_f_f \
915
+ (char **, npy_intp *, npy_intp *, void *)
916
+ void PyUFunc_g_g \
917
+ (char **, npy_intp *, npy_intp *, void *)
918
+ void PyUFunc_F_F_As_D_D \
919
+ (char **, npy_intp *, npy_intp *, void *)
920
+ void PyUFunc_F_F \
921
+ (char **, npy_intp *, npy_intp *, void *)
922
+ void PyUFunc_D_D \
923
+ (char **, npy_intp *, npy_intp *, void *)
924
+ void PyUFunc_G_G \
925
+ (char **, npy_intp *, npy_intp *, void *)
926
+ void PyUFunc_O_O \
927
+ (char **, npy_intp *, npy_intp *, void *)
928
+ void PyUFunc_ff_f_As_dd_d \
929
+ (char **, npy_intp *, npy_intp *, void *)
930
+ void PyUFunc_ff_f \
931
+ (char **, npy_intp *, npy_intp *, void *)
932
+ void PyUFunc_dd_d \
933
+ (char **, npy_intp *, npy_intp *, void *)
934
+ void PyUFunc_gg_g \
935
+ (char **, npy_intp *, npy_intp *, void *)
936
+ void PyUFunc_FF_F_As_DD_D \
937
+ (char **, npy_intp *, npy_intp *, void *)
938
+ void PyUFunc_DD_D \
939
+ (char **, npy_intp *, npy_intp *, void *)
940
+ void PyUFunc_FF_F \
941
+ (char **, npy_intp *, npy_intp *, void *)
942
+ void PyUFunc_GG_G \
943
+ (char **, npy_intp *, npy_intp *, void *)
944
+ void PyUFunc_OO_O \
945
+ (char **, npy_intp *, npy_intp *, void *)
946
+ void PyUFunc_O_O_method \
947
+ (char **, npy_intp *, npy_intp *, void *)
948
+ void PyUFunc_OO_O_method \
949
+ (char **, npy_intp *, npy_intp *, void *)
950
+ void PyUFunc_On_Om \
951
+ (char **, npy_intp *, npy_intp *, void *)
952
+ int PyUFunc_GetPyValues \
953
+ (char *, int *, int *, PyObject **)
954
+ int PyUFunc_checkfperr \
955
+ (int, PyObject *, int *)
956
+ void PyUFunc_clearfperr()
957
+ int PyUFunc_getfperr()
958
+ int PyUFunc_handlefperr \
959
+ (int, PyObject *, int, int *) except -1
960
+ int PyUFunc_ReplaceLoopBySignature \
961
+ (ufunc, PyUFuncGenericFunction, int *, PyUFuncGenericFunction *)
962
+ object PyUFunc_FromFuncAndDataAndSignature \
963
+ (PyUFuncGenericFunction *, void **, char *, int, int, int,
964
+ int, char *, char *, int, char *)
965
+
966
+ int _import_umath() except -1
967
+
968
+ cdef inline void set_array_base(ndarray arr, object base):
969
+ Py_INCREF(base) # important to do this before stealing the reference below!
970
+ PyArray_SetBaseObject(arr, base)
971
+
972
+ cdef inline object get_array_base(ndarray arr):
973
+ base = PyArray_BASE(arr)
974
+ if base is NULL:
975
+ return None
976
+ return <object>base
977
+
978
+ # Versions of the import_* functions which are more suitable for
979
+ # Cython code.
980
+ cdef inline int import_array() except -1:
981
+ try:
982
+ __pyx_import_array()
983
+ except Exception:
984
+ raise ImportError("numpy.core.multiarray failed to import")
985
+
986
+ cdef inline int import_umath() except -1:
987
+ try:
988
+ _import_umath()
989
+ except Exception:
990
+ raise ImportError("numpy.core.umath failed to import")
991
+
992
+ cdef inline int import_ufunc() except -1:
993
+ try:
994
+ _import_umath()
995
+ except Exception:
996
+ raise ImportError("numpy.core.umath failed to import")
997
+
998
+
999
+ cdef inline bint is_timedelta64_object(object obj):
1000
+ """
1001
+ Cython equivalent of `isinstance(obj, np.timedelta64)`
1002
+
1003
+ Parameters
1004
+ ----------
1005
+ obj : object
1006
+
1007
+ Returns
1008
+ -------
1009
+ bool
1010
+ """
1011
+ return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type)
1012
+
1013
+
1014
+ cdef inline bint is_datetime64_object(object obj):
1015
+ """
1016
+ Cython equivalent of `isinstance(obj, np.datetime64)`
1017
+
1018
+ Parameters
1019
+ ----------
1020
+ obj : object
1021
+
1022
+ Returns
1023
+ -------
1024
+ bool
1025
+ """
1026
+ return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type)
1027
+
1028
+
1029
+ cdef inline npy_datetime get_datetime64_value(object obj) nogil:
1030
+ """
1031
+ returns the int64 value underlying scalar numpy datetime64 object
1032
+
1033
+ Note that to interpret this as a datetime, the corresponding unit is
1034
+ also needed. That can be found using `get_datetime64_unit`.
1035
+ """
1036
+ return (<PyDatetimeScalarObject*>obj).obval
1037
+
1038
+
1039
+ cdef inline npy_timedelta get_timedelta64_value(object obj) nogil:
1040
+ """
1041
+ returns the int64 value underlying scalar numpy timedelta64 object
1042
+ """
1043
+ return (<PyTimedeltaScalarObject*>obj).obval
1044
+
1045
+
1046
+ cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil:
1047
+ """
1048
+ returns the unit part of the dtype for a numpy datetime64 object.
1049
+ """
1050
+ return <NPY_DATETIMEUNIT>(<PyDatetimeScalarObject*>obj).obmeta.base
lib/python3.12/site-packages/numpy/__init__.pxd ADDED
@@ -0,0 +1,1015 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NumPy static imports for Cython < 3.0
2
+ #
3
+ # If any of the PyArray_* functions are called, import_array must be
4
+ # called first.
5
+ #
6
+ # Author: Dag Sverre Seljebotn
7
+ #
8
+
9
+ DEF _buffer_format_string_len = 255
10
+
11
+ cimport cpython.buffer as pybuf
12
+ from cpython.ref cimport Py_INCREF
13
+ from cpython.mem cimport PyObject_Malloc, PyObject_Free
14
+ from cpython.object cimport PyObject, PyTypeObject
15
+ from cpython.buffer cimport PyObject_GetBuffer
16
+ from cpython.type cimport type
17
+ cimport libc.stdio as stdio
18
+
19
+ cdef extern from "Python.h":
20
+ ctypedef int Py_intptr_t
21
+ bint PyObject_TypeCheck(object obj, PyTypeObject* type)
22
+
23
+ cdef extern from "numpy/arrayobject.h":
24
+ ctypedef Py_intptr_t npy_intp
25
+ ctypedef size_t npy_uintp
26
+
27
+ cdef enum NPY_TYPES:
28
+ NPY_BOOL
29
+ NPY_BYTE
30
+ NPY_UBYTE
31
+ NPY_SHORT
32
+ NPY_USHORT
33
+ NPY_INT
34
+ NPY_UINT
35
+ NPY_LONG
36
+ NPY_ULONG
37
+ NPY_LONGLONG
38
+ NPY_ULONGLONG
39
+ NPY_FLOAT
40
+ NPY_DOUBLE
41
+ NPY_LONGDOUBLE
42
+ NPY_CFLOAT
43
+ NPY_CDOUBLE
44
+ NPY_CLONGDOUBLE
45
+ NPY_OBJECT
46
+ NPY_STRING
47
+ NPY_UNICODE
48
+ NPY_VOID
49
+ NPY_DATETIME
50
+ NPY_TIMEDELTA
51
+ NPY_NTYPES
52
+ NPY_NOTYPE
53
+
54
+ NPY_INT8
55
+ NPY_INT16
56
+ NPY_INT32
57
+ NPY_INT64
58
+ NPY_INT128
59
+ NPY_INT256
60
+ NPY_UINT8
61
+ NPY_UINT16
62
+ NPY_UINT32
63
+ NPY_UINT64
64
+ NPY_UINT128
65
+ NPY_UINT256
66
+ NPY_FLOAT16
67
+ NPY_FLOAT32
68
+ NPY_FLOAT64
69
+ NPY_FLOAT80
70
+ NPY_FLOAT96
71
+ NPY_FLOAT128
72
+ NPY_FLOAT256
73
+ NPY_COMPLEX32
74
+ NPY_COMPLEX64
75
+ NPY_COMPLEX128
76
+ NPY_COMPLEX160
77
+ NPY_COMPLEX192
78
+ NPY_COMPLEX256
79
+ NPY_COMPLEX512
80
+
81
+ NPY_INTP
82
+
83
+ ctypedef enum NPY_ORDER:
84
+ NPY_ANYORDER
85
+ NPY_CORDER
86
+ NPY_FORTRANORDER
87
+ NPY_KEEPORDER
88
+
89
+ ctypedef enum NPY_CASTING:
90
+ NPY_NO_CASTING
91
+ NPY_EQUIV_CASTING
92
+ NPY_SAFE_CASTING
93
+ NPY_SAME_KIND_CASTING
94
+ NPY_UNSAFE_CASTING
95
+
96
+ ctypedef enum NPY_CLIPMODE:
97
+ NPY_CLIP
98
+ NPY_WRAP
99
+ NPY_RAISE
100
+
101
+ ctypedef enum NPY_SCALARKIND:
102
+ NPY_NOSCALAR,
103
+ NPY_BOOL_SCALAR,
104
+ NPY_INTPOS_SCALAR,
105
+ NPY_INTNEG_SCALAR,
106
+ NPY_FLOAT_SCALAR,
107
+ NPY_COMPLEX_SCALAR,
108
+ NPY_OBJECT_SCALAR
109
+
110
+ ctypedef enum NPY_SORTKIND:
111
+ NPY_QUICKSORT
112
+ NPY_HEAPSORT
113
+ NPY_MERGESORT
114
+
115
+ ctypedef enum NPY_SEARCHSIDE:
116
+ NPY_SEARCHLEFT
117
+ NPY_SEARCHRIGHT
118
+
119
+ enum:
120
+ # DEPRECATED since NumPy 1.7 ! Do not use in new code!
121
+ NPY_C_CONTIGUOUS
122
+ NPY_F_CONTIGUOUS
123
+ NPY_CONTIGUOUS
124
+ NPY_FORTRAN
125
+ NPY_OWNDATA
126
+ NPY_FORCECAST
127
+ NPY_ENSURECOPY
128
+ NPY_ENSUREARRAY
129
+ NPY_ELEMENTSTRIDES
130
+ NPY_ALIGNED
131
+ NPY_NOTSWAPPED
132
+ NPY_WRITEABLE
133
+ NPY_ARR_HAS_DESCR
134
+
135
+ NPY_BEHAVED
136
+ NPY_BEHAVED_NS
137
+ NPY_CARRAY
138
+ NPY_CARRAY_RO
139
+ NPY_FARRAY
140
+ NPY_FARRAY_RO
141
+ NPY_DEFAULT
142
+
143
+ NPY_IN_ARRAY
144
+ NPY_OUT_ARRAY
145
+ NPY_INOUT_ARRAY
146
+ NPY_IN_FARRAY
147
+ NPY_OUT_FARRAY
148
+ NPY_INOUT_FARRAY
149
+
150
+ NPY_UPDATE_ALL
151
+
152
+ enum:
153
+ # Added in NumPy 1.7 to replace the deprecated enums above.
154
+ NPY_ARRAY_C_CONTIGUOUS
155
+ NPY_ARRAY_F_CONTIGUOUS
156
+ NPY_ARRAY_OWNDATA
157
+ NPY_ARRAY_FORCECAST
158
+ NPY_ARRAY_ENSURECOPY
159
+ NPY_ARRAY_ENSUREARRAY
160
+ NPY_ARRAY_ELEMENTSTRIDES
161
+ NPY_ARRAY_ALIGNED
162
+ NPY_ARRAY_NOTSWAPPED
163
+ NPY_ARRAY_WRITEABLE
164
+ NPY_ARRAY_WRITEBACKIFCOPY
165
+
166
+ NPY_ARRAY_BEHAVED
167
+ NPY_ARRAY_BEHAVED_NS
168
+ NPY_ARRAY_CARRAY
169
+ NPY_ARRAY_CARRAY_RO
170
+ NPY_ARRAY_FARRAY
171
+ NPY_ARRAY_FARRAY_RO
172
+ NPY_ARRAY_DEFAULT
173
+
174
+ NPY_ARRAY_IN_ARRAY
175
+ NPY_ARRAY_OUT_ARRAY
176
+ NPY_ARRAY_INOUT_ARRAY
177
+ NPY_ARRAY_IN_FARRAY
178
+ NPY_ARRAY_OUT_FARRAY
179
+ NPY_ARRAY_INOUT_FARRAY
180
+
181
+ NPY_ARRAY_UPDATE_ALL
182
+
183
+ cdef enum:
184
+ NPY_MAXDIMS
185
+
186
+ npy_intp NPY_MAX_ELSIZE
187
+
188
+ ctypedef void (*PyArray_VectorUnaryFunc)(void *, void *, npy_intp, void *, void *)
189
+
190
+ ctypedef struct PyArray_ArrayDescr:
191
+ # shape is a tuple, but Cython doesn't support "tuple shape"
192
+ # inside a non-PyObject declaration, so we have to declare it
193
+ # as just a PyObject*.
194
+ PyObject* shape
195
+
196
+ ctypedef struct PyArray_Descr:
197
+ pass
198
+
199
+ ctypedef class numpy.dtype [object PyArray_Descr, check_size ignore]:
200
+ # Use PyDataType_* macros when possible, however there are no macros
201
+ # for accessing some of the fields, so some are defined.
202
+ cdef PyTypeObject* typeobj
203
+ cdef char kind
204
+ cdef char type
205
+ # Numpy sometimes mutates this without warning (e.g. it'll
206
+ # sometimes change "|" to "<" in shared dtype objects on
207
+ # little-endian machines). If this matters to you, use
208
+ # PyArray_IsNativeByteOrder(dtype.byteorder) instead of
209
+ # directly accessing this field.
210
+ cdef char byteorder
211
+ cdef char flags
212
+ cdef int type_num
213
+ cdef int itemsize "elsize"
214
+ cdef int alignment
215
+ cdef object fields
216
+ cdef tuple names
217
+ # Use PyDataType_HASSUBARRAY to test whether this field is
218
+ # valid (the pointer can be NULL). Most users should access
219
+ # this field via the inline helper method PyDataType_SHAPE.
220
+ cdef PyArray_ArrayDescr* subarray
221
+
222
+ ctypedef class numpy.flatiter [object PyArrayIterObject, check_size ignore]:
223
+ # Use through macros
224
+ pass
225
+
226
+ ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]:
227
+ cdef int numiter
228
+ cdef npy_intp size, index
229
+ cdef int nd
230
+ cdef npy_intp *dimensions
231
+ cdef void **iters
232
+
233
+ ctypedef struct PyArrayObject:
234
+ # For use in situations where ndarray can't replace PyArrayObject*,
235
+ # like PyArrayObject**.
236
+ pass
237
+
238
+ ctypedef class numpy.ndarray [object PyArrayObject, check_size ignore]:
239
+ cdef __cythonbufferdefaults__ = {"mode": "strided"}
240
+
241
+ cdef:
242
+ # Only taking a few of the most commonly used and stable fields.
243
+ # One should use PyArray_* macros instead to access the C fields.
244
+ char *data
245
+ int ndim "nd"
246
+ npy_intp *shape "dimensions"
247
+ npy_intp *strides
248
+ dtype descr # deprecated since NumPy 1.7 !
249
+ PyObject* base # NOT PUBLIC, DO NOT USE !
250
+
251
+
252
+
253
+ ctypedef unsigned char npy_bool
254
+
255
+ ctypedef signed char npy_byte
256
+ ctypedef signed short npy_short
257
+ ctypedef signed int npy_int
258
+ ctypedef signed long npy_long
259
+ ctypedef signed long long npy_longlong
260
+
261
+ ctypedef unsigned char npy_ubyte
262
+ ctypedef unsigned short npy_ushort
263
+ ctypedef unsigned int npy_uint
264
+ ctypedef unsigned long npy_ulong
265
+ ctypedef unsigned long long npy_ulonglong
266
+
267
+ ctypedef float npy_float
268
+ ctypedef double npy_double
269
+ ctypedef long double npy_longdouble
270
+
271
+ ctypedef signed char npy_int8
272
+ ctypedef signed short npy_int16
273
+ ctypedef signed int npy_int32
274
+ ctypedef signed long long npy_int64
275
+ ctypedef signed long long npy_int96
276
+ ctypedef signed long long npy_int128
277
+
278
+ ctypedef unsigned char npy_uint8
279
+ ctypedef unsigned short npy_uint16
280
+ ctypedef unsigned int npy_uint32
281
+ ctypedef unsigned long long npy_uint64
282
+ ctypedef unsigned long long npy_uint96
283
+ ctypedef unsigned long long npy_uint128
284
+
285
+ ctypedef float npy_float32
286
+ ctypedef double npy_float64
287
+ ctypedef long double npy_float80
288
+ ctypedef long double npy_float96
289
+ ctypedef long double npy_float128
290
+
291
+ ctypedef struct npy_cfloat:
292
+ float real
293
+ float imag
294
+
295
+ ctypedef struct npy_cdouble:
296
+ double real
297
+ double imag
298
+
299
+ ctypedef struct npy_clongdouble:
300
+ long double real
301
+ long double imag
302
+
303
+ ctypedef struct npy_complex64:
304
+ float real
305
+ float imag
306
+
307
+ ctypedef struct npy_complex128:
308
+ double real
309
+ double imag
310
+
311
+ ctypedef struct npy_complex160:
312
+ long double real
313
+ long double imag
314
+
315
+ ctypedef struct npy_complex192:
316
+ long double real
317
+ long double imag
318
+
319
+ ctypedef struct npy_complex256:
320
+ long double real
321
+ long double imag
322
+
323
+ ctypedef struct PyArray_Dims:
324
+ npy_intp *ptr
325
+ int len
326
+
327
+ int _import_array() except -1
328
+ # A second definition so _import_array isn't marked as used when we use it here.
329
+ # Do not use - subject to change any time.
330
+ int __pyx_import_array "_import_array"() except -1
331
+
332
+ #
333
+ # Macros from ndarrayobject.h
334
+ #
335
+ bint PyArray_CHKFLAGS(ndarray m, int flags) nogil
336
+ bint PyArray_IS_C_CONTIGUOUS(ndarray arr) nogil
337
+ bint PyArray_IS_F_CONTIGUOUS(ndarray arr) nogil
338
+ bint PyArray_ISCONTIGUOUS(ndarray m) nogil
339
+ bint PyArray_ISWRITEABLE(ndarray m) nogil
340
+ bint PyArray_ISALIGNED(ndarray m) nogil
341
+
342
+ int PyArray_NDIM(ndarray) nogil
343
+ bint PyArray_ISONESEGMENT(ndarray) nogil
344
+ bint PyArray_ISFORTRAN(ndarray) nogil
345
+ int PyArray_FORTRANIF(ndarray) nogil
346
+
347
+ void* PyArray_DATA(ndarray) nogil
348
+ char* PyArray_BYTES(ndarray) nogil
349
+
350
+ npy_intp* PyArray_DIMS(ndarray) nogil
351
+ npy_intp* PyArray_STRIDES(ndarray) nogil
352
+ npy_intp PyArray_DIM(ndarray, size_t) nogil
353
+ npy_intp PyArray_STRIDE(ndarray, size_t) nogil
354
+
355
+ PyObject *PyArray_BASE(ndarray) nogil # returns borrowed reference!
356
+ PyArray_Descr *PyArray_DESCR(ndarray) nogil # returns borrowed reference to dtype!
357
+ int PyArray_FLAGS(ndarray) nogil
358
+ npy_intp PyArray_ITEMSIZE(ndarray) nogil
359
+ int PyArray_TYPE(ndarray arr) nogil
360
+
361
+ object PyArray_GETITEM(ndarray arr, void *itemptr)
362
+ int PyArray_SETITEM(ndarray arr, void *itemptr, object obj) except -1
363
+
364
+ bint PyTypeNum_ISBOOL(int) nogil
365
+ bint PyTypeNum_ISUNSIGNED(int) nogil
366
+ bint PyTypeNum_ISSIGNED(int) nogil
367
+ bint PyTypeNum_ISINTEGER(int) nogil
368
+ bint PyTypeNum_ISFLOAT(int) nogil
369
+ bint PyTypeNum_ISNUMBER(int) nogil
370
+ bint PyTypeNum_ISSTRING(int) nogil
371
+ bint PyTypeNum_ISCOMPLEX(int) nogil
372
+ bint PyTypeNum_ISPYTHON(int) nogil
373
+ bint PyTypeNum_ISFLEXIBLE(int) nogil
374
+ bint PyTypeNum_ISUSERDEF(int) nogil
375
+ bint PyTypeNum_ISEXTENDED(int) nogil
376
+ bint PyTypeNum_ISOBJECT(int) nogil
377
+
378
+ bint PyDataType_ISBOOL(dtype) nogil
379
+ bint PyDataType_ISUNSIGNED(dtype) nogil
380
+ bint PyDataType_ISSIGNED(dtype) nogil
381
+ bint PyDataType_ISINTEGER(dtype) nogil
382
+ bint PyDataType_ISFLOAT(dtype) nogil
383
+ bint PyDataType_ISNUMBER(dtype) nogil
384
+ bint PyDataType_ISSTRING(dtype) nogil
385
+ bint PyDataType_ISCOMPLEX(dtype) nogil
386
+ bint PyDataType_ISPYTHON(dtype) nogil
387
+ bint PyDataType_ISFLEXIBLE(dtype) nogil
388
+ bint PyDataType_ISUSERDEF(dtype) nogil
389
+ bint PyDataType_ISEXTENDED(dtype) nogil
390
+ bint PyDataType_ISOBJECT(dtype) nogil
391
+ bint PyDataType_HASFIELDS(dtype) nogil
392
+ bint PyDataType_HASSUBARRAY(dtype) nogil
393
+
394
+ bint PyArray_ISBOOL(ndarray) nogil
395
+ bint PyArray_ISUNSIGNED(ndarray) nogil
396
+ bint PyArray_ISSIGNED(ndarray) nogil
397
+ bint PyArray_ISINTEGER(ndarray) nogil
398
+ bint PyArray_ISFLOAT(ndarray) nogil
399
+ bint PyArray_ISNUMBER(ndarray) nogil
400
+ bint PyArray_ISSTRING(ndarray) nogil
401
+ bint PyArray_ISCOMPLEX(ndarray) nogil
402
+ bint PyArray_ISPYTHON(ndarray) nogil
403
+ bint PyArray_ISFLEXIBLE(ndarray) nogil
404
+ bint PyArray_ISUSERDEF(ndarray) nogil
405
+ bint PyArray_ISEXTENDED(ndarray) nogil
406
+ bint PyArray_ISOBJECT(ndarray) nogil
407
+ bint PyArray_HASFIELDS(ndarray) nogil
408
+
409
+ bint PyArray_ISVARIABLE(ndarray) nogil
410
+
411
+ bint PyArray_SAFEALIGNEDCOPY(ndarray) nogil
412
+ bint PyArray_ISNBO(char) nogil # works on ndarray.byteorder
413
+ bint PyArray_IsNativeByteOrder(char) nogil # works on ndarray.byteorder
414
+ bint PyArray_ISNOTSWAPPED(ndarray) nogil
415
+ bint PyArray_ISBYTESWAPPED(ndarray) nogil
416
+
417
+ bint PyArray_FLAGSWAP(ndarray, int) nogil
418
+
419
+ bint PyArray_ISCARRAY(ndarray) nogil
420
+ bint PyArray_ISCARRAY_RO(ndarray) nogil
421
+ bint PyArray_ISFARRAY(ndarray) nogil
422
+ bint PyArray_ISFARRAY_RO(ndarray) nogil
423
+ bint PyArray_ISBEHAVED(ndarray) nogil
424
+ bint PyArray_ISBEHAVED_RO(ndarray) nogil
425
+
426
+
427
+ bint PyDataType_ISNOTSWAPPED(dtype) nogil
428
+ bint PyDataType_ISBYTESWAPPED(dtype) nogil
429
+
430
+ bint PyArray_DescrCheck(object)
431
+
432
+ bint PyArray_Check(object)
433
+ bint PyArray_CheckExact(object)
434
+
435
+ # Cannot be supported due to out arg:
436
+ # bint PyArray_HasArrayInterfaceType(object, dtype, object, object&)
437
+ # bint PyArray_HasArrayInterface(op, out)
438
+
439
+
440
+ bint PyArray_IsZeroDim(object)
441
+ # Cannot be supported due to ## ## in macro:
442
+ # bint PyArray_IsScalar(object, verbatim work)
443
+ bint PyArray_CheckScalar(object)
444
+ bint PyArray_IsPythonNumber(object)
445
+ bint PyArray_IsPythonScalar(object)
446
+ bint PyArray_IsAnyScalar(object)
447
+ bint PyArray_CheckAnyScalar(object)
448
+
449
+ ndarray PyArray_GETCONTIGUOUS(ndarray)
450
+ bint PyArray_SAMESHAPE(ndarray, ndarray) nogil
451
+ npy_intp PyArray_SIZE(ndarray) nogil
452
+ npy_intp PyArray_NBYTES(ndarray) nogil
453
+
454
+ object PyArray_FROM_O(object)
455
+ object PyArray_FROM_OF(object m, int flags)
456
+ object PyArray_FROM_OT(object m, int type)
457
+ object PyArray_FROM_OTF(object m, int type, int flags)
458
+ object PyArray_FROMANY(object m, int type, int min, int max, int flags)
459
+ object PyArray_ZEROS(int nd, npy_intp* dims, int type, int fortran)
460
+ object PyArray_EMPTY(int nd, npy_intp* dims, int type, int fortran)
461
+ void PyArray_FILLWBYTE(object, int val)
462
+ npy_intp PyArray_REFCOUNT(object)
463
+ object PyArray_ContiguousFromAny(op, int, int min_depth, int max_depth)
464
+ unsigned char PyArray_EquivArrTypes(ndarray a1, ndarray a2)
465
+ bint PyArray_EquivByteorders(int b1, int b2) nogil
466
+ object PyArray_SimpleNew(int nd, npy_intp* dims, int typenum)
467
+ object PyArray_SimpleNewFromData(int nd, npy_intp* dims, int typenum, void* data)
468
+ #object PyArray_SimpleNewFromDescr(int nd, npy_intp* dims, dtype descr)
469
+ object PyArray_ToScalar(void* data, ndarray arr)
470
+
471
+ void* PyArray_GETPTR1(ndarray m, npy_intp i) nogil
472
+ void* PyArray_GETPTR2(ndarray m, npy_intp i, npy_intp j) nogil
473
+ void* PyArray_GETPTR3(ndarray m, npy_intp i, npy_intp j, npy_intp k) nogil
474
+ void* PyArray_GETPTR4(ndarray m, npy_intp i, npy_intp j, npy_intp k, npy_intp l) nogil
475
+
476
+ # Cannot be supported due to out arg
477
+ # void PyArray_DESCR_REPLACE(descr)
478
+
479
+
480
+ object PyArray_Copy(ndarray)
481
+ object PyArray_FromObject(object op, int type, int min_depth, int max_depth)
482
+ object PyArray_ContiguousFromObject(object op, int type, int min_depth, int max_depth)
483
+ object PyArray_CopyFromObject(object op, int type, int min_depth, int max_depth)
484
+
485
+ object PyArray_Cast(ndarray mp, int type_num)
486
+ object PyArray_Take(ndarray ap, object items, int axis)
487
+ object PyArray_Put(ndarray ap, object items, object values)
488
+
489
+ void PyArray_ITER_RESET(flatiter it) nogil
490
+ void PyArray_ITER_NEXT(flatiter it) nogil
491
+ void PyArray_ITER_GOTO(flatiter it, npy_intp* destination) nogil
492
+ void PyArray_ITER_GOTO1D(flatiter it, npy_intp ind) nogil
493
+ void* PyArray_ITER_DATA(flatiter it) nogil
494
+ bint PyArray_ITER_NOTDONE(flatiter it) nogil
495
+
496
+ void PyArray_MultiIter_RESET(broadcast multi) nogil
497
+ void PyArray_MultiIter_NEXT(broadcast multi) nogil
498
+ void PyArray_MultiIter_GOTO(broadcast multi, npy_intp dest) nogil
499
+ void PyArray_MultiIter_GOTO1D(broadcast multi, npy_intp ind) nogil
500
+ void* PyArray_MultiIter_DATA(broadcast multi, npy_intp i) nogil
501
+ void PyArray_MultiIter_NEXTi(broadcast multi, npy_intp i) nogil
502
+ bint PyArray_MultiIter_NOTDONE(broadcast multi) nogil
503
+
504
+ # Functions from __multiarray_api.h
505
+
506
+ # Functions taking dtype and returning object/ndarray are disabled
507
+ # for now as they steal dtype references. I'm conservative and disable
508
+ # more than is probably needed until it can be checked further.
509
+ int PyArray_SetNumericOps (object) except -1
510
+ object PyArray_GetNumericOps ()
511
+ int PyArray_INCREF (ndarray) except * # uses PyArray_Item_INCREF...
512
+ int PyArray_XDECREF (ndarray) except * # uses PyArray_Item_DECREF...
513
+ void PyArray_SetStringFunction (object, int)
514
+ dtype PyArray_DescrFromType (int)
515
+ object PyArray_TypeObjectFromType (int)
516
+ char * PyArray_Zero (ndarray)
517
+ char * PyArray_One (ndarray)
518
+ #object PyArray_CastToType (ndarray, dtype, int)
519
+ int PyArray_CastTo (ndarray, ndarray) except -1
520
+ int PyArray_CastAnyTo (ndarray, ndarray) except -1
521
+ int PyArray_CanCastSafely (int, int) # writes errors
522
+ npy_bool PyArray_CanCastTo (dtype, dtype) # writes errors
523
+ int PyArray_ObjectType (object, int) except 0
524
+ dtype PyArray_DescrFromObject (object, dtype)
525
+ #ndarray* PyArray_ConvertToCommonType (object, int *)
526
+ dtype PyArray_DescrFromScalar (object)
527
+ dtype PyArray_DescrFromTypeObject (object)
528
+ npy_intp PyArray_Size (object)
529
+ #object PyArray_Scalar (void *, dtype, object)
530
+ #object PyArray_FromScalar (object, dtype)
531
+ void PyArray_ScalarAsCtype (object, void *)
532
+ #int PyArray_CastScalarToCtype (object, void *, dtype)
533
+ #int PyArray_CastScalarDirect (object, dtype, void *, int)
534
+ object PyArray_ScalarFromObject (object)
535
+ #PyArray_VectorUnaryFunc * PyArray_GetCastFunc (dtype, int)
536
+ object PyArray_FromDims (int, int *, int)
537
+ #object PyArray_FromDimsAndDataAndDescr (int, int *, dtype, char *)
538
+ #object PyArray_FromAny (object, dtype, int, int, int, object)
539
+ object PyArray_EnsureArray (object)
540
+ object PyArray_EnsureAnyArray (object)
541
+ #object PyArray_FromFile (stdio.FILE *, dtype, npy_intp, char *)
542
+ #object PyArray_FromString (char *, npy_intp, dtype, npy_intp, char *)
543
+ #object PyArray_FromBuffer (object, dtype, npy_intp, npy_intp)
544
+ #object PyArray_FromIter (object, dtype, npy_intp)
545
+ object PyArray_Return (ndarray)
546
+ #object PyArray_GetField (ndarray, dtype, int)
547
+ #int PyArray_SetField (ndarray, dtype, int, object) except -1
548
+ object PyArray_Byteswap (ndarray, npy_bool)
549
+ object PyArray_Resize (ndarray, PyArray_Dims *, int, NPY_ORDER)
550
+ int PyArray_MoveInto (ndarray, ndarray) except -1
551
+ int PyArray_CopyInto (ndarray, ndarray) except -1
552
+ int PyArray_CopyAnyInto (ndarray, ndarray) except -1
553
+ int PyArray_CopyObject (ndarray, object) except -1
554
+ object PyArray_NewCopy (ndarray, NPY_ORDER)
555
+ object PyArray_ToList (ndarray)
556
+ object PyArray_ToString (ndarray, NPY_ORDER)
557
+ int PyArray_ToFile (ndarray, stdio.FILE *, char *, char *) except -1
558
+ int PyArray_Dump (object, object, int) except -1
559
+ object PyArray_Dumps (object, int)
560
+ int PyArray_ValidType (int) # Cannot error
561
+ void PyArray_UpdateFlags (ndarray, int)
562
+ object PyArray_New (type, int, npy_intp *, int, npy_intp *, void *, int, int, object)
563
+ #object PyArray_NewFromDescr (type, dtype, int, npy_intp *, npy_intp *, void *, int, object)
564
+ #dtype PyArray_DescrNew (dtype)
565
+ dtype PyArray_DescrNewFromType (int)
566
+ double PyArray_GetPriority (object, double) # clears errors as of 1.25
567
+ object PyArray_IterNew (object)
568
+ object PyArray_MultiIterNew (int, ...)
569
+
570
+ int PyArray_PyIntAsInt (object) except? -1
571
+ npy_intp PyArray_PyIntAsIntp (object)
572
+ int PyArray_Broadcast (broadcast) except -1
573
+ void PyArray_FillObjectArray (ndarray, object) except *
574
+ int PyArray_FillWithScalar (ndarray, object) except -1
575
+ npy_bool PyArray_CheckStrides (int, int, npy_intp, npy_intp, npy_intp *, npy_intp *)
576
+ dtype PyArray_DescrNewByteorder (dtype, char)
577
+ object PyArray_IterAllButAxis (object, int *)
578
+ #object PyArray_CheckFromAny (object, dtype, int, int, int, object)
579
+ #object PyArray_FromArray (ndarray, dtype, int)
580
+ object PyArray_FromInterface (object)
581
+ object PyArray_FromStructInterface (object)
582
+ #object PyArray_FromArrayAttr (object, dtype, object)
583
+ #NPY_SCALARKIND PyArray_ScalarKind (int, ndarray*)
584
+ int PyArray_CanCoerceScalar (int, int, NPY_SCALARKIND)
585
+ object PyArray_NewFlagsObject (object)
586
+ npy_bool PyArray_CanCastScalar (type, type)
587
+ #int PyArray_CompareUCS4 (npy_ucs4 *, npy_ucs4 *, register size_t)
588
+ int PyArray_RemoveSmallest (broadcast) except -1
589
+ int PyArray_ElementStrides (object)
590
+ void PyArray_Item_INCREF (char *, dtype) except *
591
+ void PyArray_Item_XDECREF (char *, dtype) except *
592
+ object PyArray_FieldNames (object)
593
+ object PyArray_Transpose (ndarray, PyArray_Dims *)
594
+ object PyArray_TakeFrom (ndarray, object, int, ndarray, NPY_CLIPMODE)
595
+ object PyArray_PutTo (ndarray, object, object, NPY_CLIPMODE)
596
+ object PyArray_PutMask (ndarray, object, object)
597
+ object PyArray_Repeat (ndarray, object, int)
598
+ object PyArray_Choose (ndarray, object, ndarray, NPY_CLIPMODE)
599
+ int PyArray_Sort (ndarray, int, NPY_SORTKIND) except -1
600
+ object PyArray_ArgSort (ndarray, int, NPY_SORTKIND)
601
+ object PyArray_SearchSorted (ndarray, object, NPY_SEARCHSIDE, PyObject *)
602
+ object PyArray_ArgMax (ndarray, int, ndarray)
603
+ object PyArray_ArgMin (ndarray, int, ndarray)
604
+ object PyArray_Reshape (ndarray, object)
605
+ object PyArray_Newshape (ndarray, PyArray_Dims *, NPY_ORDER)
606
+ object PyArray_Squeeze (ndarray)
607
+ #object PyArray_View (ndarray, dtype, type)
608
+ object PyArray_SwapAxes (ndarray, int, int)
609
+ object PyArray_Max (ndarray, int, ndarray)
610
+ object PyArray_Min (ndarray, int, ndarray)
611
+ object PyArray_Ptp (ndarray, int, ndarray)
612
+ object PyArray_Mean (ndarray, int, int, ndarray)
613
+ object PyArray_Trace (ndarray, int, int, int, int, ndarray)
614
+ object PyArray_Diagonal (ndarray, int, int, int)
615
+ object PyArray_Clip (ndarray, object, object, ndarray)
616
+ object PyArray_Conjugate (ndarray, ndarray)
617
+ object PyArray_Nonzero (ndarray)
618
+ object PyArray_Std (ndarray, int, int, ndarray, int)
619
+ object PyArray_Sum (ndarray, int, int, ndarray)
620
+ object PyArray_CumSum (ndarray, int, int, ndarray)
621
+ object PyArray_Prod (ndarray, int, int, ndarray)
622
+ object PyArray_CumProd (ndarray, int, int, ndarray)
623
+ object PyArray_All (ndarray, int, ndarray)
624
+ object PyArray_Any (ndarray, int, ndarray)
625
+ object PyArray_Compress (ndarray, object, int, ndarray)
626
+ object PyArray_Flatten (ndarray, NPY_ORDER)
627
+ object PyArray_Ravel (ndarray, NPY_ORDER)
628
+ npy_intp PyArray_MultiplyList (npy_intp *, int)
629
+ int PyArray_MultiplyIntList (int *, int)
630
+ void * PyArray_GetPtr (ndarray, npy_intp*)
631
+ int PyArray_CompareLists (npy_intp *, npy_intp *, int)
632
+ #int PyArray_AsCArray (object*, void *, npy_intp *, int, dtype)
633
+ #int PyArray_As1D (object*, char **, int *, int)
634
+ #int PyArray_As2D (object*, char ***, int *, int *, int)
635
+ int PyArray_Free (object, void *)
636
+ #int PyArray_Converter (object, object*)
637
+ int PyArray_IntpFromSequence (object, npy_intp *, int) except -1
638
+ object PyArray_Concatenate (object, int)
639
+ object PyArray_InnerProduct (object, object)
640
+ object PyArray_MatrixProduct (object, object)
641
+ object PyArray_CopyAndTranspose (object)
642
+ object PyArray_Correlate (object, object, int)
643
+ int PyArray_TypestrConvert (int, int)
644
+ #int PyArray_DescrConverter (object, dtype*) except 0
645
+ #int PyArray_DescrConverter2 (object, dtype*) except 0
646
+ int PyArray_IntpConverter (object, PyArray_Dims *) except 0
647
+ #int PyArray_BufferConverter (object, chunk) except 0
648
+ int PyArray_AxisConverter (object, int *) except 0
649
+ int PyArray_BoolConverter (object, npy_bool *) except 0
650
+ int PyArray_ByteorderConverter (object, char *) except 0
651
+ int PyArray_OrderConverter (object, NPY_ORDER *) except 0
652
+ unsigned char PyArray_EquivTypes (dtype, dtype) # clears errors
653
+ #object PyArray_Zeros (int, npy_intp *, dtype, int)
654
+ #object PyArray_Empty (int, npy_intp *, dtype, int)
655
+ object PyArray_Where (object, object, object)
656
+ object PyArray_Arange (double, double, double, int)
657
+ #object PyArray_ArangeObj (object, object, object, dtype)
658
+ int PyArray_SortkindConverter (object, NPY_SORTKIND *) except 0
659
+ object PyArray_LexSort (object, int)
660
+ object PyArray_Round (ndarray, int, ndarray)
661
+ unsigned char PyArray_EquivTypenums (int, int)
662
+ int PyArray_RegisterDataType (dtype) except -1
663
+ int PyArray_RegisterCastFunc (dtype, int, PyArray_VectorUnaryFunc *) except -1
664
+ int PyArray_RegisterCanCast (dtype, int, NPY_SCALARKIND) except -1
665
+ #void PyArray_InitArrFuncs (PyArray_ArrFuncs *)
666
+ object PyArray_IntTupleFromIntp (int, npy_intp *)
667
+ int PyArray_TypeNumFromName (char *)
668
+ int PyArray_ClipmodeConverter (object, NPY_CLIPMODE *) except 0
669
+ #int PyArray_OutputConverter (object, ndarray*) except 0
670
+ object PyArray_BroadcastToShape (object, npy_intp *, int)
671
+ void _PyArray_SigintHandler (int)
672
+ void* _PyArray_GetSigintBuf ()
673
+ #int PyArray_DescrAlignConverter (object, dtype*) except 0
674
+ #int PyArray_DescrAlignConverter2 (object, dtype*) except 0
675
+ int PyArray_SearchsideConverter (object, void *) except 0
676
+ object PyArray_CheckAxis (ndarray, int *, int)
677
+ npy_intp PyArray_OverflowMultiplyList (npy_intp *, int)
678
+ int PyArray_CompareString (char *, char *, size_t)
679
+ int PyArray_SetBaseObject(ndarray, base) except -1 # NOTE: steals a reference to base! Use "set_array_base()" instead.
680
+
681
+
682
+ # Typedefs that matches the runtime dtype objects in
683
+ # the numpy module.
684
+
685
+ # The ones that are commented out needs an IFDEF function
686
+ # in Cython to enable them only on the right systems.
687
+
688
+ ctypedef npy_int8 int8_t
689
+ ctypedef npy_int16 int16_t
690
+ ctypedef npy_int32 int32_t
691
+ ctypedef npy_int64 int64_t
692
+ #ctypedef npy_int96 int96_t
693
+ #ctypedef npy_int128 int128_t
694
+
695
+ ctypedef npy_uint8 uint8_t
696
+ ctypedef npy_uint16 uint16_t
697
+ ctypedef npy_uint32 uint32_t
698
+ ctypedef npy_uint64 uint64_t
699
+ #ctypedef npy_uint96 uint96_t
700
+ #ctypedef npy_uint128 uint128_t
701
+
702
+ ctypedef npy_float32 float32_t
703
+ ctypedef npy_float64 float64_t
704
+ #ctypedef npy_float80 float80_t
705
+ #ctypedef npy_float128 float128_t
706
+
707
+ ctypedef float complex complex64_t
708
+ ctypedef double complex complex128_t
709
+
710
+ # The int types are mapped a bit surprising --
711
+ # numpy.int corresponds to 'l' and numpy.long to 'q'
712
+ ctypedef npy_long int_t
713
+ ctypedef npy_longlong longlong_t
714
+
715
+ ctypedef npy_ulong uint_t
716
+ ctypedef npy_ulonglong ulonglong_t
717
+
718
+ ctypedef npy_intp intp_t
719
+ ctypedef npy_uintp uintp_t
720
+
721
+ ctypedef npy_double float_t
722
+ ctypedef npy_double double_t
723
+ ctypedef npy_longdouble longdouble_t
724
+
725
+ ctypedef npy_cfloat cfloat_t
726
+ ctypedef npy_cdouble cdouble_t
727
+ ctypedef npy_clongdouble clongdouble_t
728
+
729
+ ctypedef npy_cdouble complex_t
730
+
731
+ cdef inline object PyArray_MultiIterNew1(a):
732
+ return PyArray_MultiIterNew(1, <void*>a)
733
+
734
+ cdef inline object PyArray_MultiIterNew2(a, b):
735
+ return PyArray_MultiIterNew(2, <void*>a, <void*>b)
736
+
737
+ cdef inline object PyArray_MultiIterNew3(a, b, c):
738
+ return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)
739
+
740
+ cdef inline object PyArray_MultiIterNew4(a, b, c, d):
741
+ return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)
742
+
743
+ cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
744
+ return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)
745
+
746
+ cdef inline tuple PyDataType_SHAPE(dtype d):
747
+ if PyDataType_HASSUBARRAY(d):
748
+ return <tuple>d.subarray.shape
749
+ else:
750
+ return ()
751
+
752
+
753
+ cdef extern from "numpy/ndarrayobject.h":
754
+ PyTypeObject PyTimedeltaArrType_Type
755
+ PyTypeObject PyDatetimeArrType_Type
756
+ ctypedef int64_t npy_timedelta
757
+ ctypedef int64_t npy_datetime
758
+
759
+ cdef extern from "numpy/ndarraytypes.h":
760
+ ctypedef struct PyArray_DatetimeMetaData:
761
+ NPY_DATETIMEUNIT base
762
+ int64_t num
763
+
764
+ cdef extern from "numpy/arrayscalars.h":
765
+
766
+ # abstract types
767
+ ctypedef class numpy.generic [object PyObject]:
768
+ pass
769
+ ctypedef class numpy.number [object PyObject]:
770
+ pass
771
+ ctypedef class numpy.integer [object PyObject]:
772
+ pass
773
+ ctypedef class numpy.signedinteger [object PyObject]:
774
+ pass
775
+ ctypedef class numpy.unsignedinteger [object PyObject]:
776
+ pass
777
+ ctypedef class numpy.inexact [object PyObject]:
778
+ pass
779
+ ctypedef class numpy.floating [object PyObject]:
780
+ pass
781
+ ctypedef class numpy.complexfloating [object PyObject]:
782
+ pass
783
+ ctypedef class numpy.flexible [object PyObject]:
784
+ pass
785
+ ctypedef class numpy.character [object PyObject]:
786
+ pass
787
+
788
+ ctypedef struct PyDatetimeScalarObject:
789
+ # PyObject_HEAD
790
+ npy_datetime obval
791
+ PyArray_DatetimeMetaData obmeta
792
+
793
+ ctypedef struct PyTimedeltaScalarObject:
794
+ # PyObject_HEAD
795
+ npy_timedelta obval
796
+ PyArray_DatetimeMetaData obmeta
797
+
798
+ ctypedef enum NPY_DATETIMEUNIT:
799
+ NPY_FR_Y
800
+ NPY_FR_M
801
+ NPY_FR_W
802
+ NPY_FR_D
803
+ NPY_FR_B
804
+ NPY_FR_h
805
+ NPY_FR_m
806
+ NPY_FR_s
807
+ NPY_FR_ms
808
+ NPY_FR_us
809
+ NPY_FR_ns
810
+ NPY_FR_ps
811
+ NPY_FR_fs
812
+ NPY_FR_as
813
+ NPY_FR_GENERIC
814
+
815
+
816
+ #
817
+ # ufunc API
818
+ #
819
+
820
+ cdef extern from "numpy/ufuncobject.h":
821
+
822
+ ctypedef void (*PyUFuncGenericFunction) (char **, npy_intp *, npy_intp *, void *)
823
+
824
+ ctypedef class numpy.ufunc [object PyUFuncObject, check_size ignore]:
825
+ cdef:
826
+ int nin, nout, nargs
827
+ int identity
828
+ PyUFuncGenericFunction *functions
829
+ void **data
830
+ int ntypes
831
+ int check_return
832
+ char *name
833
+ char *types
834
+ char *doc
835
+ void *ptr
836
+ PyObject *obj
837
+ PyObject *userloops
838
+
839
+ cdef enum:
840
+ PyUFunc_Zero
841
+ PyUFunc_One
842
+ PyUFunc_None
843
+ UFUNC_ERR_IGNORE
844
+ UFUNC_ERR_WARN
845
+ UFUNC_ERR_RAISE
846
+ UFUNC_ERR_CALL
847
+ UFUNC_ERR_PRINT
848
+ UFUNC_ERR_LOG
849
+ UFUNC_MASK_DIVIDEBYZERO
850
+ UFUNC_MASK_OVERFLOW
851
+ UFUNC_MASK_UNDERFLOW
852
+ UFUNC_MASK_INVALID
853
+ UFUNC_SHIFT_DIVIDEBYZERO
854
+ UFUNC_SHIFT_OVERFLOW
855
+ UFUNC_SHIFT_UNDERFLOW
856
+ UFUNC_SHIFT_INVALID
857
+ UFUNC_FPE_DIVIDEBYZERO
858
+ UFUNC_FPE_OVERFLOW
859
+ UFUNC_FPE_UNDERFLOW
860
+ UFUNC_FPE_INVALID
861
+ UFUNC_ERR_DEFAULT
862
+ UFUNC_ERR_DEFAULT2
863
+
864
+ object PyUFunc_FromFuncAndData(PyUFuncGenericFunction *,
865
+ void **, char *, int, int, int, int, char *, char *, int)
866
+ int PyUFunc_RegisterLoopForType(ufunc, int,
867
+ PyUFuncGenericFunction, int *, void *) except -1
868
+ void PyUFunc_f_f_As_d_d \
869
+ (char **, npy_intp *, npy_intp *, void *)
870
+ void PyUFunc_d_d \
871
+ (char **, npy_intp *, npy_intp *, void *)
872
+ void PyUFunc_f_f \
873
+ (char **, npy_intp *, npy_intp *, void *)
874
+ void PyUFunc_g_g \
875
+ (char **, npy_intp *, npy_intp *, void *)
876
+ void PyUFunc_F_F_As_D_D \
877
+ (char **, npy_intp *, npy_intp *, void *)
878
+ void PyUFunc_F_F \
879
+ (char **, npy_intp *, npy_intp *, void *)
880
+ void PyUFunc_D_D \
881
+ (char **, npy_intp *, npy_intp *, void *)
882
+ void PyUFunc_G_G \
883
+ (char **, npy_intp *, npy_intp *, void *)
884
+ void PyUFunc_O_O \
885
+ (char **, npy_intp *, npy_intp *, void *)
886
+ void PyUFunc_ff_f_As_dd_d \
887
+ (char **, npy_intp *, npy_intp *, void *)
888
+ void PyUFunc_ff_f \
889
+ (char **, npy_intp *, npy_intp *, void *)
890
+ void PyUFunc_dd_d \
891
+ (char **, npy_intp *, npy_intp *, void *)
892
+ void PyUFunc_gg_g \
893
+ (char **, npy_intp *, npy_intp *, void *)
894
+ void PyUFunc_FF_F_As_DD_D \
895
+ (char **, npy_intp *, npy_intp *, void *)
896
+ void PyUFunc_DD_D \
897
+ (char **, npy_intp *, npy_intp *, void *)
898
+ void PyUFunc_FF_F \
899
+ (char **, npy_intp *, npy_intp *, void *)
900
+ void PyUFunc_GG_G \
901
+ (char **, npy_intp *, npy_intp *, void *)
902
+ void PyUFunc_OO_O \
903
+ (char **, npy_intp *, npy_intp *, void *)
904
+ void PyUFunc_O_O_method \
905
+ (char **, npy_intp *, npy_intp *, void *)
906
+ void PyUFunc_OO_O_method \
907
+ (char **, npy_intp *, npy_intp *, void *)
908
+ void PyUFunc_On_Om \
909
+ (char **, npy_intp *, npy_intp *, void *)
910
+ int PyUFunc_GetPyValues \
911
+ (char *, int *, int *, PyObject **)
912
+ int PyUFunc_checkfperr \
913
+ (int, PyObject *, int *)
914
+ void PyUFunc_clearfperr()
915
+ int PyUFunc_getfperr()
916
+ int PyUFunc_handlefperr \
917
+ (int, PyObject *, int, int *) except -1
918
+ int PyUFunc_ReplaceLoopBySignature \
919
+ (ufunc, PyUFuncGenericFunction, int *, PyUFuncGenericFunction *)
920
+ object PyUFunc_FromFuncAndDataAndSignature \
921
+ (PyUFuncGenericFunction *, void **, char *, int, int, int,
922
+ int, char *, char *, int, char *)
923
+
924
+ int _import_umath() except -1
925
+
926
+ cdef inline void set_array_base(ndarray arr, object base):
927
+ Py_INCREF(base) # important to do this before stealing the reference below!
928
+ PyArray_SetBaseObject(arr, base)
929
+
930
+ cdef inline object get_array_base(ndarray arr):
931
+ base = PyArray_BASE(arr)
932
+ if base is NULL:
933
+ return None
934
+ return <object>base
935
+
936
+ # Versions of the import_* functions which are more suitable for
937
+ # Cython code.
938
+ cdef inline int import_array() except -1:
939
+ try:
940
+ __pyx_import_array()
941
+ except Exception:
942
+ raise ImportError("numpy.core.multiarray failed to import")
943
+
944
+ cdef inline int import_umath() except -1:
945
+ try:
946
+ _import_umath()
947
+ except Exception:
948
+ raise ImportError("numpy.core.umath failed to import")
949
+
950
+ cdef inline int import_ufunc() except -1:
951
+ try:
952
+ _import_umath()
953
+ except Exception:
954
+ raise ImportError("numpy.core.umath failed to import")
955
+
956
+ cdef extern from *:
957
+ # Leave a marker that the NumPy declarations came from this file
958
+ # See https://github.com/cython/cython/issues/3573
959
+ """
960
+ /* NumPy API declarations from "numpy/__init__.pxd" */
961
+ """
962
+
963
+
964
+ cdef inline bint is_timedelta64_object(object obj):
965
+ """
966
+ Cython equivalent of `isinstance(obj, np.timedelta64)`
967
+
968
+ Parameters
969
+ ----------
970
+ obj : object
971
+
972
+ Returns
973
+ -------
974
+ bool
975
+ """
976
+ return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type)
977
+
978
+
979
+ cdef inline bint is_datetime64_object(object obj):
980
+ """
981
+ Cython equivalent of `isinstance(obj, np.datetime64)`
982
+
983
+ Parameters
984
+ ----------
985
+ obj : object
986
+
987
+ Returns
988
+ -------
989
+ bool
990
+ """
991
+ return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type)
992
+
993
+
994
+ cdef inline npy_datetime get_datetime64_value(object obj) nogil:
995
+ """
996
+ returns the int64 value underlying scalar numpy datetime64 object
997
+
998
+ Note that to interpret this as a datetime, the corresponding unit is
999
+ also needed. That can be found using `get_datetime64_unit`.
1000
+ """
1001
+ return (<PyDatetimeScalarObject*>obj).obval
1002
+
1003
+
1004
+ cdef inline npy_timedelta get_timedelta64_value(object obj) nogil:
1005
+ """
1006
+ returns the int64 value underlying scalar numpy timedelta64 object
1007
+ """
1008
+ return (<PyTimedeltaScalarObject*>obj).obval
1009
+
1010
+
1011
+ cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil:
1012
+ """
1013
+ returns the unit part of the dtype for a numpy datetime64 object.
1014
+ """
1015
+ return <NPY_DATETIMEUNIT>(<PyDatetimeScalarObject*>obj).obmeta.base
lib/python3.12/site-packages/numpy/__init__.py ADDED
@@ -0,0 +1,461 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ NumPy
3
+ =====
4
+
5
+ Provides
6
+ 1. An array object of arbitrary homogeneous items
7
+ 2. Fast mathematical operations over arrays
8
+ 3. Linear Algebra, Fourier Transforms, Random Number Generation
9
+
10
+ How to use the documentation
11
+ ----------------------------
12
+ Documentation is available in two forms: docstrings provided
13
+ with the code, and a loose standing reference guide, available from
14
+ `the NumPy homepage <https://numpy.org>`_.
15
+
16
+ We recommend exploring the docstrings using
17
+ `IPython <https://ipython.org>`_, an advanced Python shell with
18
+ TAB-completion and introspection capabilities. See below for further
19
+ instructions.
20
+
21
+ The docstring examples assume that `numpy` has been imported as ``np``::
22
+
23
+ >>> import numpy as np
24
+
25
+ Code snippets are indicated by three greater-than signs::
26
+
27
+ >>> x = 42
28
+ >>> x = x + 1
29
+
30
+ Use the built-in ``help`` function to view a function's docstring::
31
+
32
+ >>> help(np.sort)
33
+ ... # doctest: +SKIP
34
+
35
+ For some objects, ``np.info(obj)`` may provide additional help. This is
36
+ particularly true if you see the line "Help on ufunc object:" at the top
37
+ of the help() page. Ufuncs are implemented in C, not Python, for speed.
38
+ The native Python help() does not know how to view their help, but our
39
+ np.info() function does.
40
+
41
+ To search for documents containing a keyword, do::
42
+
43
+ >>> np.lookfor('keyword')
44
+ ... # doctest: +SKIP
45
+
46
+ General-purpose documents like a glossary and help on the basic concepts
47
+ of numpy are available under the ``doc`` sub-module::
48
+
49
+ >>> from numpy import doc
50
+ >>> help(doc)
51
+ ... # doctest: +SKIP
52
+
53
+ Available subpackages
54
+ ---------------------
55
+ lib
56
+ Basic functions used by several sub-packages.
57
+ random
58
+ Core Random Tools
59
+ linalg
60
+ Core Linear Algebra Tools
61
+ fft
62
+ Core FFT routines
63
+ polynomial
64
+ Polynomial tools
65
+ testing
66
+ NumPy testing tools
67
+ distutils
68
+ Enhancements to distutils with support for
69
+ Fortran compilers support and more (for Python <= 3.11).
70
+
71
+ Utilities
72
+ ---------
73
+ test
74
+ Run numpy unittests
75
+ show_config
76
+ Show numpy build configuration
77
+ matlib
78
+ Make everything matrices.
79
+ __version__
80
+ NumPy version string
81
+
82
+ Viewing documentation using IPython
83
+ -----------------------------------
84
+
85
+ Start IPython and import `numpy` usually under the alias ``np``: `import
86
+ numpy as np`. Then, directly past or use the ``%cpaste`` magic to paste
87
+ examples into the shell. To see which functions are available in `numpy`,
88
+ type ``np.<TAB>`` (where ``<TAB>`` refers to the TAB key), or use
89
+ ``np.*cos*?<ENTER>`` (where ``<ENTER>`` refers to the ENTER key) to narrow
90
+ down the list. To view the docstring for a function, use
91
+ ``np.cos?<ENTER>`` (to view the docstring) and ``np.cos??<ENTER>`` (to view
92
+ the source code).
93
+
94
+ Copies vs. in-place operation
95
+ -----------------------------
96
+ Most of the functions in `numpy` return a copy of the array argument
97
+ (e.g., `np.sort`). In-place versions of these functions are often
98
+ available as array methods, i.e. ``x = np.array([1,2,3]); x.sort()``.
99
+ Exceptions to this rule are documented.
100
+
101
+ """
102
+ import sys
103
+ import warnings
104
+
105
+ from ._globals import _NoValue, _CopyMode
106
+ # These exceptions were moved in 1.25 and are hidden from __dir__()
107
+ from .exceptions import (
108
+ ComplexWarning, ModuleDeprecationWarning, VisibleDeprecationWarning,
109
+ TooHardError, AxisError)
110
+
111
+
112
+ # If a version with git hash was stored, use that instead
113
+ from . import version
114
+ from .version import __version__
115
+
116
+ # We first need to detect if we're being called as part of the numpy setup
117
+ # procedure itself in a reliable manner.
118
+ try:
119
+ __NUMPY_SETUP__
120
+ except NameError:
121
+ __NUMPY_SETUP__ = False
122
+
123
+ if __NUMPY_SETUP__:
124
+ sys.stderr.write('Running from numpy source directory.\n')
125
+ else:
126
+ # Allow distributors to run custom init code before importing numpy.core
127
+ from . import _distributor_init
128
+
129
+ try:
130
+ from numpy.__config__ import show as show_config
131
+ except ImportError as e:
132
+ msg = """Error importing numpy: you should not try to import numpy from
133
+ its source directory; please exit the numpy source tree, and relaunch
134
+ your python interpreter from there."""
135
+ raise ImportError(msg) from e
136
+
137
+ __all__ = [
138
+ 'exceptions', 'ModuleDeprecationWarning', 'VisibleDeprecationWarning',
139
+ 'ComplexWarning', 'TooHardError', 'AxisError']
140
+
141
+ # mapping of {name: (value, deprecation_msg)}
142
+ __deprecated_attrs__ = {}
143
+
144
+ from . import core
145
+ from .core import *
146
+ from . import compat
147
+ from . import exceptions
148
+ from . import dtypes
149
+ from . import lib
150
+ # NOTE: to be revisited following future namespace cleanup.
151
+ # See gh-14454 and gh-15672 for discussion.
152
+ from .lib import *
153
+
154
+ from . import linalg
155
+ from . import fft
156
+ from . import polynomial
157
+ from . import random
158
+ from . import ctypeslib
159
+ from . import ma
160
+ from . import matrixlib as _mat
161
+ from .matrixlib import *
162
+
163
+ # Deprecations introduced in NumPy 1.20.0, 2020-06-06
164
+ import builtins as _builtins
165
+
166
+ _msg = (
167
+ "module 'numpy' has no attribute '{n}'.\n"
168
+ "`np.{n}` was a deprecated alias for the builtin `{n}`. "
169
+ "To avoid this error in existing code, use `{n}` by itself. "
170
+ "Doing this will not modify any behavior and is safe. {extended_msg}\n"
171
+ "The aliases was originally deprecated in NumPy 1.20; for more "
172
+ "details and guidance see the original release note at:\n"
173
+ " https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations")
174
+
175
+ _specific_msg = (
176
+ "If you specifically wanted the numpy scalar type, use `np.{}` here.")
177
+
178
+ _int_extended_msg = (
179
+ "When replacing `np.{}`, you may wish to use e.g. `np.int64` "
180
+ "or `np.int32` to specify the precision. If you wish to review "
181
+ "your current use, check the release note link for "
182
+ "additional information.")
183
+
184
+ _type_info = [
185
+ ("object", ""), # The NumPy scalar only exists by name.
186
+ ("bool", _specific_msg.format("bool_")),
187
+ ("float", _specific_msg.format("float64")),
188
+ ("complex", _specific_msg.format("complex128")),
189
+ ("str", _specific_msg.format("str_")),
190
+ ("int", _int_extended_msg.format("int"))]
191
+
192
+ __former_attrs__ = {
193
+ n: _msg.format(n=n, extended_msg=extended_msg)
194
+ for n, extended_msg in _type_info
195
+ }
196
+
197
+ # Future warning introduced in NumPy 1.24.0, 2022-11-17
198
+ _msg = (
199
+ "`np.{n}` is a deprecated alias for `{an}`. (Deprecated NumPy 1.24)")
200
+
201
+ # Some of these are awkward (since `np.str` may be preferable in the long
202
+ # term), but overall the names ending in 0 seem undesirable
203
+ _type_info = [
204
+ ("bool8", bool_, "np.bool_"),
205
+ ("int0", intp, "np.intp"),
206
+ ("uint0", uintp, "np.uintp"),
207
+ ("str0", str_, "np.str_"),
208
+ ("bytes0", bytes_, "np.bytes_"),
209
+ ("void0", void, "np.void"),
210
+ ("object0", object_,
211
+ "`np.object0` is a deprecated alias for `np.object_`. "
212
+ "`object` can be used instead. (Deprecated NumPy 1.24)")]
213
+
214
+ # Some of these could be defined right away, but most were aliases to
215
+ # the Python objects and only removed in NumPy 1.24. Defining them should
216
+ # probably wait for NumPy 1.26 or 2.0.
217
+ # When defined, these should possibly not be added to `__all__` to avoid
218
+ # import with `from numpy import *`.
219
+ __future_scalars__ = {"bool", "long", "ulong", "str", "bytes", "object"}
220
+
221
+ __deprecated_attrs__.update({
222
+ n: (alias, _msg.format(n=n, an=an)) for n, alias, an in _type_info})
223
+
224
+ import math
225
+
226
+ __deprecated_attrs__['math'] = (math,
227
+ "`np.math` is a deprecated alias for the standard library `math` "
228
+ "module (Deprecated Numpy 1.25). Replace usages of `np.math` with "
229
+ "`math`")
230
+
231
+ del math, _msg, _type_info
232
+
233
+ from .core import abs
234
+ # now that numpy modules are imported, can initialize limits
235
+ core.getlimits._register_known_types()
236
+
237
+ __all__.extend(['__version__', 'show_config'])
238
+ __all__.extend(core.__all__)
239
+ __all__.extend(_mat.__all__)
240
+ __all__.extend(lib.__all__)
241
+ __all__.extend(['linalg', 'fft', 'random', 'ctypeslib', 'ma'])
242
+
243
+ # Remove min and max from __all__ to avoid `from numpy import *` override
244
+ # the builtins min/max. Temporary fix for 1.25.x/1.26.x, see gh-24229.
245
+ __all__.remove('min')
246
+ __all__.remove('max')
247
+ __all__.remove('round')
248
+
249
+ # Remove one of the two occurrences of `issubdtype`, which is exposed as
250
+ # both `numpy.core.issubdtype` and `numpy.lib.issubdtype`.
251
+ __all__.remove('issubdtype')
252
+
253
+ # These are exported by np.core, but are replaced by the builtins below
254
+ # remove them to ensure that we don't end up with `np.long == np.int_`,
255
+ # which would be a breaking change.
256
+ del long, unicode
257
+ __all__.remove('long')
258
+ __all__.remove('unicode')
259
+
260
+ # Remove things that are in the numpy.lib but not in the numpy namespace
261
+ # Note that there is a test (numpy/tests/test_public_api.py:test_numpy_namespace)
262
+ # that prevents adding more things to the main namespace by accident.
263
+ # The list below will grow until the `from .lib import *` fixme above is
264
+ # taken care of
265
+ __all__.remove('Arrayterator')
266
+ del Arrayterator
267
+
268
+ # These names were removed in NumPy 1.20. For at least one release,
269
+ # attempts to access these names in the numpy namespace will trigger
270
+ # a warning, and calling the function will raise an exception.
271
+ _financial_names = ['fv', 'ipmt', 'irr', 'mirr', 'nper', 'npv', 'pmt',
272
+ 'ppmt', 'pv', 'rate']
273
+ __expired_functions__ = {
274
+ name: (f'In accordance with NEP 32, the function {name} was removed '
275
+ 'from NumPy version 1.20. A replacement for this function '
276
+ 'is available in the numpy_financial library: '
277
+ 'https://pypi.org/project/numpy-financial')
278
+ for name in _financial_names}
279
+
280
+ # Filter out Cython harmless warnings
281
+ warnings.filterwarnings("ignore", message="numpy.dtype size changed")
282
+ warnings.filterwarnings("ignore", message="numpy.ufunc size changed")
283
+ warnings.filterwarnings("ignore", message="numpy.ndarray size changed")
284
+
285
+ # oldnumeric and numarray were removed in 1.9. In case some packages import
286
+ # but do not use them, we define them here for backward compatibility.
287
+ oldnumeric = 'removed'
288
+ numarray = 'removed'
289
+
290
+ def __getattr__(attr):
291
+ # Warn for expired attributes, and return a dummy function
292
+ # that always raises an exception.
293
+ import warnings
294
+ import math
295
+ try:
296
+ msg = __expired_functions__[attr]
297
+ except KeyError:
298
+ pass
299
+ else:
300
+ warnings.warn(msg, DeprecationWarning, stacklevel=2)
301
+
302
+ def _expired(*args, **kwds):
303
+ raise RuntimeError(msg)
304
+
305
+ return _expired
306
+
307
+ # Emit warnings for deprecated attributes
308
+ try:
309
+ val, msg = __deprecated_attrs__[attr]
310
+ except KeyError:
311
+ pass
312
+ else:
313
+ warnings.warn(msg, DeprecationWarning, stacklevel=2)
314
+ return val
315
+
316
+ if attr in __future_scalars__:
317
+ # And future warnings for those that will change, but also give
318
+ # the AttributeError
319
+ warnings.warn(
320
+ f"In the future `np.{attr}` will be defined as the "
321
+ "corresponding NumPy scalar.", FutureWarning, stacklevel=2)
322
+
323
+ if attr in __former_attrs__:
324
+ raise AttributeError(__former_attrs__[attr])
325
+
326
+ if attr == 'testing':
327
+ import numpy.testing as testing
328
+ return testing
329
+ elif attr == 'Tester':
330
+ "Removed in NumPy 1.25.0"
331
+ raise RuntimeError("Tester was removed in NumPy 1.25.")
332
+
333
+ raise AttributeError("module {!r} has no attribute "
334
+ "{!r}".format(__name__, attr))
335
+
336
+ def __dir__():
337
+ public_symbols = globals().keys() | {'testing'}
338
+ public_symbols -= {
339
+ "core", "matrixlib",
340
+ # These were moved in 1.25 and may be deprecated eventually:
341
+ "ModuleDeprecationWarning", "VisibleDeprecationWarning",
342
+ "ComplexWarning", "TooHardError", "AxisError"
343
+ }
344
+ return list(public_symbols)
345
+
346
+ # Pytest testing
347
+ from numpy._pytesttester import PytestTester
348
+ test = PytestTester(__name__)
349
+ del PytestTester
350
+
351
+ def _sanity_check():
352
+ """
353
+ Quick sanity checks for common bugs caused by environment.
354
+ There are some cases e.g. with wrong BLAS ABI that cause wrong
355
+ results under specific runtime conditions that are not necessarily
356
+ achieved during test suite runs, and it is useful to catch those early.
357
+
358
+ See https://github.com/numpy/numpy/issues/8577 and other
359
+ similar bug reports.
360
+
361
+ """
362
+ try:
363
+ x = ones(2, dtype=float32)
364
+ if not abs(x.dot(x) - float32(2.0)) < 1e-5:
365
+ raise AssertionError()
366
+ except AssertionError:
367
+ msg = ("The current Numpy installation ({!r}) fails to "
368
+ "pass simple sanity checks. This can be caused for example "
369
+ "by incorrect BLAS library being linked in, or by mixing "
370
+ "package managers (pip, conda, apt, ...). Search closed "
371
+ "numpy issues for similar problems.")
372
+ raise RuntimeError(msg.format(__file__)) from None
373
+
374
+ _sanity_check()
375
+ del _sanity_check
376
+
377
+ def _mac_os_check():
378
+ """
379
+ Quick Sanity check for Mac OS look for accelerate build bugs.
380
+ Testing numpy polyfit calls init_dgelsd(LAPACK)
381
+ """
382
+ try:
383
+ c = array([3., 2., 1.])
384
+ x = linspace(0, 2, 5)
385
+ y = polyval(c, x)
386
+ _ = polyfit(x, y, 2, cov=True)
387
+ except ValueError:
388
+ pass
389
+
390
+ if sys.platform == "darwin":
391
+ from . import exceptions
392
+ with warnings.catch_warnings(record=True) as w:
393
+ _mac_os_check()
394
+ # Throw runtime error, if the test failed Check for warning and error_message
395
+ if len(w) > 0:
396
+ for _wn in w:
397
+ if _wn.category is exceptions.RankWarning:
398
+ # Ignore other warnings, they may not be relevant (see gh-25433).
399
+ error_message = f"{_wn.category.__name__}: {str(_wn.message)}"
400
+ msg = (
401
+ "Polyfit sanity test emitted a warning, most likely due "
402
+ "to using a buggy Accelerate backend."
403
+ "\nIf you compiled yourself, more information is available at:"
404
+ "\nhttps://numpy.org/devdocs/building/index.html"
405
+ "\nOtherwise report this to the vendor "
406
+ "that provided NumPy.\n\n{}\n".format(error_message))
407
+ raise RuntimeError(msg)
408
+ del _wn
409
+ del w
410
+ del _mac_os_check
411
+
412
+ # We usually use madvise hugepages support, but on some old kernels it
413
+ # is slow and thus better avoided.
414
+ # Specifically kernel version 4.6 had a bug fix which probably fixed this:
415
+ # https://github.com/torvalds/linux/commit/7cf91a98e607c2f935dbcc177d70011e95b8faff
416
+ import os
417
+ use_hugepage = os.environ.get("NUMPY_MADVISE_HUGEPAGE", None)
418
+ if sys.platform == "linux" and use_hugepage is None:
419
+ # If there is an issue with parsing the kernel version,
420
+ # set use_hugepages to 0. Usage of LooseVersion will handle
421
+ # the kernel version parsing better, but avoided since it
422
+ # will increase the import time. See: #16679 for related discussion.
423
+ try:
424
+ use_hugepage = 1
425
+ kernel_version = os.uname().release.split(".")[:2]
426
+ kernel_version = tuple(int(v) for v in kernel_version)
427
+ if kernel_version < (4, 6):
428
+ use_hugepage = 0
429
+ except ValueError:
430
+ use_hugepages = 0
431
+ elif use_hugepage is None:
432
+ # This is not Linux, so it should not matter, just enable anyway
433
+ use_hugepage = 1
434
+ else:
435
+ use_hugepage = int(use_hugepage)
436
+
437
+ # Note that this will currently only make a difference on Linux
438
+ core.multiarray._set_madvise_hugepage(use_hugepage)
439
+ del use_hugepage
440
+
441
+ # Give a warning if NumPy is reloaded or imported on a sub-interpreter
442
+ # We do this from python, since the C-module may not be reloaded and
443
+ # it is tidier organized.
444
+ core.multiarray._multiarray_umath._reload_guard()
445
+
446
+ # default to "weak" promotion for "NumPy 2".
447
+ core._set_promotion_state(
448
+ os.environ.get("NPY_PROMOTION_STATE",
449
+ "weak" if _using_numpy2_behavior() else "legacy"))
450
+
451
+ # Tell PyInstaller where to find hook-numpy.py
452
+ def _pyinstaller_hooks_dir():
453
+ from pathlib import Path
454
+ return [str(Path(__file__).with_name("_pyinstaller").resolve())]
455
+
456
+ # Remove symbols imported for internal use
457
+ del os
458
+
459
+
460
+ # Remove symbols imported for internal use
461
+ del sys, warnings
lib/python3.12/site-packages/numpy/__init__.pyi ADDED
The diff for this file is too large to render. See raw diff
 
lib/python3.12/site-packages/numpy/_distributor_init.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ Distributor init file
2
+
3
+ Distributors: you can add custom code here to support particular distributions
4
+ of numpy.
5
+
6
+ For example, this is a good place to put any BLAS/LAPACK initialization code.
7
+
8
+ The numpy standard source distribution will not put code in this file, so you
9
+ can safely replace this file with your own version.
10
+ """
11
+
12
+ try:
13
+ from . import _distributor_init_local
14
+ except ImportError:
15
+ pass
lib/python3.12/site-packages/numpy/_globals.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Module defining global singleton classes.
3
+
4
+ This module raises a RuntimeError if an attempt to reload it is made. In that
5
+ way the identities of the classes defined here are fixed and will remain so
6
+ even if numpy itself is reloaded. In particular, a function like the following
7
+ will still work correctly after numpy is reloaded::
8
+
9
+ def foo(arg=np._NoValue):
10
+ if arg is np._NoValue:
11
+ ...
12
+
13
+ That was not the case when the singleton classes were defined in the numpy
14
+ ``__init__.py`` file. See gh-7844 for a discussion of the reload problem that
15
+ motivated this module.
16
+
17
+ """
18
+ import enum
19
+
20
+ from ._utils import set_module as _set_module
21
+
22
+ __all__ = ['_NoValue', '_CopyMode']
23
+
24
+
25
+ # Disallow reloading this module so as to preserve the identities of the
26
+ # classes defined here.
27
+ if '_is_loaded' in globals():
28
+ raise RuntimeError('Reloading numpy._globals is not allowed')
29
+ _is_loaded = True
30
+
31
+
32
+ class _NoValueType:
33
+ """Special keyword value.
34
+
35
+ The instance of this class may be used as the default value assigned to a
36
+ keyword if no other obvious default (e.g., `None`) is suitable,
37
+
38
+ Common reasons for using this keyword are:
39
+
40
+ - A new keyword is added to a function, and that function forwards its
41
+ inputs to another function or method which can be defined outside of
42
+ NumPy. For example, ``np.std(x)`` calls ``x.std``, so when a ``keepdims``
43
+ keyword was added that could only be forwarded if the user explicitly
44
+ specified ``keepdims``; downstream array libraries may not have added
45
+ the same keyword, so adding ``x.std(..., keepdims=keepdims)``
46
+ unconditionally could have broken previously working code.
47
+ - A keyword is being deprecated, and a deprecation warning must only be
48
+ emitted when the keyword is used.
49
+
50
+ """
51
+ __instance = None
52
+ def __new__(cls):
53
+ # ensure that only one instance exists
54
+ if not cls.__instance:
55
+ cls.__instance = super().__new__(cls)
56
+ return cls.__instance
57
+
58
+ def __repr__(self):
59
+ return "<no value>"
60
+
61
+
62
+ _NoValue = _NoValueType()
63
+
64
+
65
+ @_set_module("numpy")
66
+ class _CopyMode(enum.Enum):
67
+ """
68
+ An enumeration for the copy modes supported
69
+ by numpy.copy() and numpy.array(). The following three modes are supported,
70
+
71
+ - ALWAYS: This means that a deep copy of the input
72
+ array will always be taken.
73
+ - IF_NEEDED: This means that a deep copy of the input
74
+ array will be taken only if necessary.
75
+ - NEVER: This means that the deep copy will never be taken.
76
+ If a copy cannot be avoided then a `ValueError` will be
77
+ raised.
78
+
79
+ Note that the buffer-protocol could in theory do copies. NumPy currently
80
+ assumes an object exporting the buffer protocol will never do this.
81
+ """
82
+
83
+ ALWAYS = True
84
+ IF_NEEDED = False
85
+ NEVER = 2
86
+
87
+ def __bool__(self):
88
+ # For backwards compatibility
89
+ if self == _CopyMode.ALWAYS:
90
+ return True
91
+
92
+ if self == _CopyMode.IF_NEEDED:
93
+ return False
94
+
95
+ raise ValueError(f"{self} is neither True nor False.")
lib/python3.12/site-packages/numpy/_pytesttester.py ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Pytest test running.
3
+
4
+ This module implements the ``test()`` function for NumPy modules. The usual
5
+ boiler plate for doing that is to put the following in the module
6
+ ``__init__.py`` file::
7
+
8
+ from numpy._pytesttester import PytestTester
9
+ test = PytestTester(__name__)
10
+ del PytestTester
11
+
12
+
13
+ Warnings filtering and other runtime settings should be dealt with in the
14
+ ``pytest.ini`` file in the numpy repo root. The behavior of the test depends on
15
+ whether or not that file is found as follows:
16
+
17
+ * ``pytest.ini`` is present (develop mode)
18
+ All warnings except those explicitly filtered out are raised as error.
19
+ * ``pytest.ini`` is absent (release mode)
20
+ DeprecationWarnings and PendingDeprecationWarnings are ignored, other
21
+ warnings are passed through.
22
+
23
+ In practice, tests run from the numpy repo are run in develop mode. That
24
+ includes the standard ``python runtests.py`` invocation.
25
+
26
+ This module is imported by every numpy subpackage, so lies at the top level to
27
+ simplify circular import issues. For the same reason, it contains no numpy
28
+ imports at module scope, instead importing numpy within function calls.
29
+ """
30
+ import sys
31
+ import os
32
+
33
+ __all__ = ['PytestTester']
34
+
35
+
36
+ def _show_numpy_info():
37
+ import numpy as np
38
+
39
+ print("NumPy version %s" % np.__version__)
40
+ relaxed_strides = np.ones((10, 1), order="C").flags.f_contiguous
41
+ print("NumPy relaxed strides checking option:", relaxed_strides)
42
+ info = np.lib.utils._opt_info()
43
+ print("NumPy CPU features: ", (info if info else 'nothing enabled'))
44
+
45
+
46
+ class PytestTester:
47
+ """
48
+ Pytest test runner.
49
+
50
+ A test function is typically added to a package's __init__.py like so::
51
+
52
+ from numpy._pytesttester import PytestTester
53
+ test = PytestTester(__name__).test
54
+ del PytestTester
55
+
56
+ Calling this test function finds and runs all tests associated with the
57
+ module and all its sub-modules.
58
+
59
+ Attributes
60
+ ----------
61
+ module_name : str
62
+ Full path to the package to test.
63
+
64
+ Parameters
65
+ ----------
66
+ module_name : module name
67
+ The name of the module to test.
68
+
69
+ Notes
70
+ -----
71
+ Unlike the previous ``nose``-based implementation, this class is not
72
+ publicly exposed as it performs some ``numpy``-specific warning
73
+ suppression.
74
+
75
+ """
76
+ def __init__(self, module_name):
77
+ self.module_name = module_name
78
+
79
+ def __call__(self, label='fast', verbose=1, extra_argv=None,
80
+ doctests=False, coverage=False, durations=-1, tests=None):
81
+ """
82
+ Run tests for module using pytest.
83
+
84
+ Parameters
85
+ ----------
86
+ label : {'fast', 'full'}, optional
87
+ Identifies the tests to run. When set to 'fast', tests decorated
88
+ with `pytest.mark.slow` are skipped, when 'full', the slow marker
89
+ is ignored.
90
+ verbose : int, optional
91
+ Verbosity value for test outputs, in the range 1-3. Default is 1.
92
+ extra_argv : list, optional
93
+ List with any extra arguments to pass to pytests.
94
+ doctests : bool, optional
95
+ .. note:: Not supported
96
+ coverage : bool, optional
97
+ If True, report coverage of NumPy code. Default is False.
98
+ Requires installation of (pip) pytest-cov.
99
+ durations : int, optional
100
+ If < 0, do nothing, If 0, report time of all tests, if > 0,
101
+ report the time of the slowest `timer` tests. Default is -1.
102
+ tests : test or list of tests
103
+ Tests to be executed with pytest '--pyargs'
104
+
105
+ Returns
106
+ -------
107
+ result : bool
108
+ Return True on success, false otherwise.
109
+
110
+ Notes
111
+ -----
112
+ Each NumPy module exposes `test` in its namespace to run all tests for
113
+ it. For example, to run all tests for numpy.lib:
114
+
115
+ >>> np.lib.test() #doctest: +SKIP
116
+
117
+ Examples
118
+ --------
119
+ >>> result = np.lib.test() #doctest: +SKIP
120
+ ...
121
+ 1023 passed, 2 skipped, 6 deselected, 1 xfailed in 10.39 seconds
122
+ >>> result
123
+ True
124
+
125
+ """
126
+ import pytest
127
+ import warnings
128
+
129
+ module = sys.modules[self.module_name]
130
+ module_path = os.path.abspath(module.__path__[0])
131
+
132
+ # setup the pytest arguments
133
+ pytest_args = ["-l"]
134
+
135
+ # offset verbosity. The "-q" cancels a "-v".
136
+ pytest_args += ["-q"]
137
+
138
+ if sys.version_info < (3, 12):
139
+ with warnings.catch_warnings():
140
+ warnings.simplefilter("always")
141
+ # Filter out distutils cpu warnings (could be localized to
142
+ # distutils tests). ASV has problems with top level import,
143
+ # so fetch module for suppression here.
144
+ from numpy.distutils import cpuinfo
145
+
146
+ with warnings.catch_warnings(record=True):
147
+ # Ignore the warning from importing the array_api submodule. This
148
+ # warning is done on import, so it would break pytest collection,
149
+ # but importing it early here prevents the warning from being
150
+ # issued when it imported again.
151
+ import numpy.array_api
152
+
153
+ # Filter out annoying import messages. Want these in both develop and
154
+ # release mode.
155
+ pytest_args += [
156
+ "-W ignore:Not importing directory",
157
+ "-W ignore:numpy.dtype size changed",
158
+ "-W ignore:numpy.ufunc size changed",
159
+ "-W ignore::UserWarning:cpuinfo",
160
+ ]
161
+
162
+ # When testing matrices, ignore their PendingDeprecationWarnings
163
+ pytest_args += [
164
+ "-W ignore:the matrix subclass is not",
165
+ "-W ignore:Importing from numpy.matlib is",
166
+ ]
167
+
168
+ if doctests:
169
+ pytest_args += ["--doctest-modules"]
170
+
171
+ if extra_argv:
172
+ pytest_args += list(extra_argv)
173
+
174
+ if verbose > 1:
175
+ pytest_args += ["-" + "v"*(verbose - 1)]
176
+
177
+ if coverage:
178
+ pytest_args += ["--cov=" + module_path]
179
+
180
+ if label == "fast":
181
+ # not importing at the top level to avoid circular import of module
182
+ from numpy.testing import IS_PYPY
183
+ if IS_PYPY:
184
+ pytest_args += ["-m", "not slow and not slow_pypy"]
185
+ else:
186
+ pytest_args += ["-m", "not slow"]
187
+
188
+ elif label != "full":
189
+ pytest_args += ["-m", label]
190
+
191
+ if durations >= 0:
192
+ pytest_args += ["--durations=%s" % durations]
193
+
194
+ if tests is None:
195
+ tests = [self.module_name]
196
+
197
+ pytest_args += ["--pyargs"] + list(tests)
198
+
199
+ # run tests.
200
+ _show_numpy_info()
201
+
202
+ try:
203
+ code = pytest.main(pytest_args)
204
+ except SystemExit as exc:
205
+ code = exc.code
206
+
207
+ return code == 0
lib/python3.12/site-packages/numpy/_pytesttester.pyi ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections.abc import Iterable
2
+ from typing import Literal as L
3
+
4
+ __all__: list[str]
5
+
6
+ class PytestTester:
7
+ module_name: str
8
+ def __init__(self, module_name: str) -> None: ...
9
+ def __call__(
10
+ self,
11
+ label: L["fast", "full"] = ...,
12
+ verbose: int = ...,
13
+ extra_argv: None | Iterable[str] = ...,
14
+ doctests: L[False] = ...,
15
+ coverage: bool = ...,
16
+ durations: int = ...,
17
+ tests: None | Iterable[str] = ...,
18
+ ) -> bool: ...
lib/python3.12/site-packages/numpy/conftest.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Pytest configuration and fixtures for the Numpy test suite.
3
+ """
4
+ import os
5
+ import tempfile
6
+
7
+ import hypothesis
8
+ import pytest
9
+ import numpy
10
+
11
+ from numpy.core._multiarray_tests import get_fpu_mode
12
+
13
+
14
+ _old_fpu_mode = None
15
+ _collect_results = {}
16
+
17
+ # Use a known and persistent tmpdir for hypothesis' caches, which
18
+ # can be automatically cleared by the OS or user.
19
+ hypothesis.configuration.set_hypothesis_home_dir(
20
+ os.path.join(tempfile.gettempdir(), ".hypothesis")
21
+ )
22
+
23
+ # We register two custom profiles for Numpy - for details see
24
+ # https://hypothesis.readthedocs.io/en/latest/settings.html
25
+ # The first is designed for our own CI runs; the latter also
26
+ # forces determinism and is designed for use via np.test()
27
+ hypothesis.settings.register_profile(
28
+ name="numpy-profile", deadline=None, print_blob=True,
29
+ )
30
+ hypothesis.settings.register_profile(
31
+ name="np.test() profile",
32
+ deadline=None, print_blob=True, database=None, derandomize=True,
33
+ suppress_health_check=list(hypothesis.HealthCheck),
34
+ )
35
+ # Note that the default profile is chosen based on the presence
36
+ # of pytest.ini, but can be overridden by passing the
37
+ # --hypothesis-profile=NAME argument to pytest.
38
+ _pytest_ini = os.path.join(os.path.dirname(__file__), "..", "pytest.ini")
39
+ hypothesis.settings.load_profile(
40
+ "numpy-profile" if os.path.isfile(_pytest_ini) else "np.test() profile"
41
+ )
42
+
43
+ # The experimentalAPI is used in _umath_tests
44
+ os.environ["NUMPY_EXPERIMENTAL_DTYPE_API"] = "1"
45
+
46
+ def pytest_configure(config):
47
+ config.addinivalue_line("markers",
48
+ "valgrind_error: Tests that are known to error under valgrind.")
49
+ config.addinivalue_line("markers",
50
+ "leaks_references: Tests that are known to leak references.")
51
+ config.addinivalue_line("markers",
52
+ "slow: Tests that are very slow.")
53
+ config.addinivalue_line("markers",
54
+ "slow_pypy: Tests that are very slow on pypy.")
55
+
56
+
57
+ def pytest_addoption(parser):
58
+ parser.addoption("--available-memory", action="store", default=None,
59
+ help=("Set amount of memory available for running the "
60
+ "test suite. This can result to tests requiring "
61
+ "especially large amounts of memory to be skipped. "
62
+ "Equivalent to setting environment variable "
63
+ "NPY_AVAILABLE_MEM. Default: determined"
64
+ "automatically."))
65
+
66
+
67
+ def pytest_sessionstart(session):
68
+ available_mem = session.config.getoption('available_memory')
69
+ if available_mem is not None:
70
+ os.environ['NPY_AVAILABLE_MEM'] = available_mem
71
+
72
+
73
+ #FIXME when yield tests are gone.
74
+ @pytest.hookimpl()
75
+ def pytest_itemcollected(item):
76
+ """
77
+ Check FPU precision mode was not changed during test collection.
78
+
79
+ The clumsy way we do it here is mainly necessary because numpy
80
+ still uses yield tests, which can execute code at test collection
81
+ time.
82
+ """
83
+ global _old_fpu_mode
84
+
85
+ mode = get_fpu_mode()
86
+
87
+ if _old_fpu_mode is None:
88
+ _old_fpu_mode = mode
89
+ elif mode != _old_fpu_mode:
90
+ _collect_results[item] = (_old_fpu_mode, mode)
91
+ _old_fpu_mode = mode
92
+
93
+
94
+ @pytest.fixture(scope="function", autouse=True)
95
+ def check_fpu_mode(request):
96
+ """
97
+ Check FPU precision mode was not changed during the test.
98
+ """
99
+ old_mode = get_fpu_mode()
100
+ yield
101
+ new_mode = get_fpu_mode()
102
+
103
+ if old_mode != new_mode:
104
+ raise AssertionError("FPU precision mode changed from {0:#x} to {1:#x}"
105
+ " during the test".format(old_mode, new_mode))
106
+
107
+ collect_result = _collect_results.get(request.node)
108
+ if collect_result is not None:
109
+ old_mode, new_mode = collect_result
110
+ raise AssertionError("FPU precision mode changed from {0:#x} to {1:#x}"
111
+ " when collecting the test".format(old_mode,
112
+ new_mode))
113
+
114
+
115
+ @pytest.fixture(autouse=True)
116
+ def add_np(doctest_namespace):
117
+ doctest_namespace['np'] = numpy
118
+
119
+ @pytest.fixture(autouse=True)
120
+ def env_setup(monkeypatch):
121
+ monkeypatch.setenv('PYTHONHASHSEED', '0')
122
+
123
+
124
+ @pytest.fixture(params=[True, False])
125
+ def weak_promotion(request):
126
+ """
127
+ Fixture to ensure "legacy" promotion state or change it to use the new
128
+ weak promotion (plus warning). `old_promotion` should be used as a
129
+ parameter in the function.
130
+ """
131
+ state = numpy._get_promotion_state()
132
+ if request.param:
133
+ numpy._set_promotion_state("weak_and_warn")
134
+ else:
135
+ numpy._set_promotion_state("legacy")
136
+
137
+ yield request.param
138
+ numpy._set_promotion_state(state)
lib/python3.12/site-packages/numpy/ctypeslib.py ADDED
@@ -0,0 +1,545 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ============================
3
+ ``ctypes`` Utility Functions
4
+ ============================
5
+
6
+ See Also
7
+ --------
8
+ load_library : Load a C library.
9
+ ndpointer : Array restype/argtype with verification.
10
+ as_ctypes : Create a ctypes array from an ndarray.
11
+ as_array : Create an ndarray from a ctypes array.
12
+
13
+ References
14
+ ----------
15
+ .. [1] "SciPy Cookbook: ctypes", https://scipy-cookbook.readthedocs.io/items/Ctypes.html
16
+
17
+ Examples
18
+ --------
19
+ Load the C library:
20
+
21
+ >>> _lib = np.ctypeslib.load_library('libmystuff', '.') #doctest: +SKIP
22
+
23
+ Our result type, an ndarray that must be of type double, be 1-dimensional
24
+ and is C-contiguous in memory:
25
+
26
+ >>> array_1d_double = np.ctypeslib.ndpointer(
27
+ ... dtype=np.double,
28
+ ... ndim=1, flags='CONTIGUOUS') #doctest: +SKIP
29
+
30
+ Our C-function typically takes an array and updates its values
31
+ in-place. For example::
32
+
33
+ void foo_func(double* x, int length)
34
+ {
35
+ int i;
36
+ for (i = 0; i < length; i++) {
37
+ x[i] = i*i;
38
+ }
39
+ }
40
+
41
+ We wrap it using:
42
+
43
+ >>> _lib.foo_func.restype = None #doctest: +SKIP
44
+ >>> _lib.foo_func.argtypes = [array_1d_double, c_int] #doctest: +SKIP
45
+
46
+ Then, we're ready to call ``foo_func``:
47
+
48
+ >>> out = np.empty(15, dtype=np.double)
49
+ >>> _lib.foo_func(out, len(out)) #doctest: +SKIP
50
+
51
+ """
52
+ __all__ = ['load_library', 'ndpointer', 'c_intp', 'as_ctypes', 'as_array',
53
+ 'as_ctypes_type']
54
+
55
+ import os
56
+ from numpy import (
57
+ integer, ndarray, dtype as _dtype, asarray, frombuffer
58
+ )
59
+ from numpy.core.multiarray import _flagdict, flagsobj
60
+
61
+ try:
62
+ import ctypes
63
+ except ImportError:
64
+ ctypes = None
65
+
66
+ if ctypes is None:
67
+ def _dummy(*args, **kwds):
68
+ """
69
+ Dummy object that raises an ImportError if ctypes is not available.
70
+
71
+ Raises
72
+ ------
73
+ ImportError
74
+ If ctypes is not available.
75
+
76
+ """
77
+ raise ImportError("ctypes is not available.")
78
+ load_library = _dummy
79
+ as_ctypes = _dummy
80
+ as_array = _dummy
81
+ from numpy import intp as c_intp
82
+ _ndptr_base = object
83
+ else:
84
+ import numpy.core._internal as nic
85
+ c_intp = nic._getintp_ctype()
86
+ del nic
87
+ _ndptr_base = ctypes.c_void_p
88
+
89
+ # Adapted from Albert Strasheim
90
+ def load_library(libname, loader_path):
91
+ """
92
+ It is possible to load a library using
93
+
94
+ >>> lib = ctypes.cdll[<full_path_name>] # doctest: +SKIP
95
+
96
+ But there are cross-platform considerations, such as library file extensions,
97
+ plus the fact Windows will just load the first library it finds with that name.
98
+ NumPy supplies the load_library function as a convenience.
99
+
100
+ .. versionchanged:: 1.20.0
101
+ Allow libname and loader_path to take any
102
+ :term:`python:path-like object`.
103
+
104
+ Parameters
105
+ ----------
106
+ libname : path-like
107
+ Name of the library, which can have 'lib' as a prefix,
108
+ but without an extension.
109
+ loader_path : path-like
110
+ Where the library can be found.
111
+
112
+ Returns
113
+ -------
114
+ ctypes.cdll[libpath] : library object
115
+ A ctypes library object
116
+
117
+ Raises
118
+ ------
119
+ OSError
120
+ If there is no library with the expected extension, or the
121
+ library is defective and cannot be loaded.
122
+ """
123
+ # Convert path-like objects into strings
124
+ libname = os.fsdecode(libname)
125
+ loader_path = os.fsdecode(loader_path)
126
+
127
+ ext = os.path.splitext(libname)[1]
128
+ if not ext:
129
+ import sys
130
+ import sysconfig
131
+ # Try to load library with platform-specific name, otherwise
132
+ # default to libname.[so|dll|dylib]. Sometimes, these files are
133
+ # built erroneously on non-linux platforms.
134
+ base_ext = ".so"
135
+ if sys.platform.startswith("darwin"):
136
+ base_ext = ".dylib"
137
+ elif sys.platform.startswith("win"):
138
+ base_ext = ".dll"
139
+ libname_ext = [libname + base_ext]
140
+ so_ext = sysconfig.get_config_var("EXT_SUFFIX")
141
+ if not so_ext == base_ext:
142
+ libname_ext.insert(0, libname + so_ext)
143
+ else:
144
+ libname_ext = [libname]
145
+
146
+ loader_path = os.path.abspath(loader_path)
147
+ if not os.path.isdir(loader_path):
148
+ libdir = os.path.dirname(loader_path)
149
+ else:
150
+ libdir = loader_path
151
+
152
+ for ln in libname_ext:
153
+ libpath = os.path.join(libdir, ln)
154
+ if os.path.exists(libpath):
155
+ try:
156
+ return ctypes.cdll[libpath]
157
+ except OSError:
158
+ ## defective lib file
159
+ raise
160
+ ## if no successful return in the libname_ext loop:
161
+ raise OSError("no file with expected extension")
162
+
163
+
164
+ def _num_fromflags(flaglist):
165
+ num = 0
166
+ for val in flaglist:
167
+ num += _flagdict[val]
168
+ return num
169
+
170
+ _flagnames = ['C_CONTIGUOUS', 'F_CONTIGUOUS', 'ALIGNED', 'WRITEABLE',
171
+ 'OWNDATA', 'WRITEBACKIFCOPY']
172
+ def _flags_fromnum(num):
173
+ res = []
174
+ for key in _flagnames:
175
+ value = _flagdict[key]
176
+ if (num & value):
177
+ res.append(key)
178
+ return res
179
+
180
+
181
+ class _ndptr(_ndptr_base):
182
+ @classmethod
183
+ def from_param(cls, obj):
184
+ if not isinstance(obj, ndarray):
185
+ raise TypeError("argument must be an ndarray")
186
+ if cls._dtype_ is not None \
187
+ and obj.dtype != cls._dtype_:
188
+ raise TypeError("array must have data type %s" % cls._dtype_)
189
+ if cls._ndim_ is not None \
190
+ and obj.ndim != cls._ndim_:
191
+ raise TypeError("array must have %d dimension(s)" % cls._ndim_)
192
+ if cls._shape_ is not None \
193
+ and obj.shape != cls._shape_:
194
+ raise TypeError("array must have shape %s" % str(cls._shape_))
195
+ if cls._flags_ is not None \
196
+ and ((obj.flags.num & cls._flags_) != cls._flags_):
197
+ raise TypeError("array must have flags %s" %
198
+ _flags_fromnum(cls._flags_))
199
+ return obj.ctypes
200
+
201
+
202
+ class _concrete_ndptr(_ndptr):
203
+ """
204
+ Like _ndptr, but with `_shape_` and `_dtype_` specified.
205
+
206
+ Notably, this means the pointer has enough information to reconstruct
207
+ the array, which is not generally true.
208
+ """
209
+ def _check_retval_(self):
210
+ """
211
+ This method is called when this class is used as the .restype
212
+ attribute for a shared-library function, to automatically wrap the
213
+ pointer into an array.
214
+ """
215
+ return self.contents
216
+
217
+ @property
218
+ def contents(self):
219
+ """
220
+ Get an ndarray viewing the data pointed to by this pointer.
221
+
222
+ This mirrors the `contents` attribute of a normal ctypes pointer
223
+ """
224
+ full_dtype = _dtype((self._dtype_, self._shape_))
225
+ full_ctype = ctypes.c_char * full_dtype.itemsize
226
+ buffer = ctypes.cast(self, ctypes.POINTER(full_ctype)).contents
227
+ return frombuffer(buffer, dtype=full_dtype).squeeze(axis=0)
228
+
229
+
230
+ # Factory for an array-checking class with from_param defined for
231
+ # use with ctypes argtypes mechanism
232
+ _pointer_type_cache = {}
233
+ def ndpointer(dtype=None, ndim=None, shape=None, flags=None):
234
+ """
235
+ Array-checking restype/argtypes.
236
+
237
+ An ndpointer instance is used to describe an ndarray in restypes
238
+ and argtypes specifications. This approach is more flexible than
239
+ using, for example, ``POINTER(c_double)``, since several restrictions
240
+ can be specified, which are verified upon calling the ctypes function.
241
+ These include data type, number of dimensions, shape and flags. If a
242
+ given array does not satisfy the specified restrictions,
243
+ a ``TypeError`` is raised.
244
+
245
+ Parameters
246
+ ----------
247
+ dtype : data-type, optional
248
+ Array data-type.
249
+ ndim : int, optional
250
+ Number of array dimensions.
251
+ shape : tuple of ints, optional
252
+ Array shape.
253
+ flags : str or tuple of str
254
+ Array flags; may be one or more of:
255
+
256
+ - C_CONTIGUOUS / C / CONTIGUOUS
257
+ - F_CONTIGUOUS / F / FORTRAN
258
+ - OWNDATA / O
259
+ - WRITEABLE / W
260
+ - ALIGNED / A
261
+ - WRITEBACKIFCOPY / X
262
+
263
+ Returns
264
+ -------
265
+ klass : ndpointer type object
266
+ A type object, which is an ``_ndtpr`` instance containing
267
+ dtype, ndim, shape and flags information.
268
+
269
+ Raises
270
+ ------
271
+ TypeError
272
+ If a given array does not satisfy the specified restrictions.
273
+
274
+ Examples
275
+ --------
276
+ >>> clib.somefunc.argtypes = [np.ctypeslib.ndpointer(dtype=np.float64,
277
+ ... ndim=1,
278
+ ... flags='C_CONTIGUOUS')]
279
+ ... #doctest: +SKIP
280
+ >>> clib.somefunc(np.array([1, 2, 3], dtype=np.float64))
281
+ ... #doctest: +SKIP
282
+
283
+ """
284
+
285
+ # normalize dtype to an Optional[dtype]
286
+ if dtype is not None:
287
+ dtype = _dtype(dtype)
288
+
289
+ # normalize flags to an Optional[int]
290
+ num = None
291
+ if flags is not None:
292
+ if isinstance(flags, str):
293
+ flags = flags.split(',')
294
+ elif isinstance(flags, (int, integer)):
295
+ num = flags
296
+ flags = _flags_fromnum(num)
297
+ elif isinstance(flags, flagsobj):
298
+ num = flags.num
299
+ flags = _flags_fromnum(num)
300
+ if num is None:
301
+ try:
302
+ flags = [x.strip().upper() for x in flags]
303
+ except Exception as e:
304
+ raise TypeError("invalid flags specification") from e
305
+ num = _num_fromflags(flags)
306
+
307
+ # normalize shape to an Optional[tuple]
308
+ if shape is not None:
309
+ try:
310
+ shape = tuple(shape)
311
+ except TypeError:
312
+ # single integer -> 1-tuple
313
+ shape = (shape,)
314
+
315
+ cache_key = (dtype, ndim, shape, num)
316
+
317
+ try:
318
+ return _pointer_type_cache[cache_key]
319
+ except KeyError:
320
+ pass
321
+
322
+ # produce a name for the new type
323
+ if dtype is None:
324
+ name = 'any'
325
+ elif dtype.names is not None:
326
+ name = str(id(dtype))
327
+ else:
328
+ name = dtype.str
329
+ if ndim is not None:
330
+ name += "_%dd" % ndim
331
+ if shape is not None:
332
+ name += "_"+"x".join(str(x) for x in shape)
333
+ if flags is not None:
334
+ name += "_"+"_".join(flags)
335
+
336
+ if dtype is not None and shape is not None:
337
+ base = _concrete_ndptr
338
+ else:
339
+ base = _ndptr
340
+
341
+ klass = type("ndpointer_%s"%name, (base,),
342
+ {"_dtype_": dtype,
343
+ "_shape_" : shape,
344
+ "_ndim_" : ndim,
345
+ "_flags_" : num})
346
+ _pointer_type_cache[cache_key] = klass
347
+ return klass
348
+
349
+
350
+ if ctypes is not None:
351
+ def _ctype_ndarray(element_type, shape):
352
+ """ Create an ndarray of the given element type and shape """
353
+ for dim in shape[::-1]:
354
+ element_type = dim * element_type
355
+ # prevent the type name include np.ctypeslib
356
+ element_type.__module__ = None
357
+ return element_type
358
+
359
+
360
+ def _get_scalar_type_map():
361
+ """
362
+ Return a dictionary mapping native endian scalar dtype to ctypes types
363
+ """
364
+ ct = ctypes
365
+ simple_types = [
366
+ ct.c_byte, ct.c_short, ct.c_int, ct.c_long, ct.c_longlong,
367
+ ct.c_ubyte, ct.c_ushort, ct.c_uint, ct.c_ulong, ct.c_ulonglong,
368
+ ct.c_float, ct.c_double,
369
+ ct.c_bool,
370
+ ]
371
+ return {_dtype(ctype): ctype for ctype in simple_types}
372
+
373
+
374
+ _scalar_type_map = _get_scalar_type_map()
375
+
376
+
377
+ def _ctype_from_dtype_scalar(dtype):
378
+ # swapping twice ensure that `=` is promoted to <, >, or |
379
+ dtype_with_endian = dtype.newbyteorder('S').newbyteorder('S')
380
+ dtype_native = dtype.newbyteorder('=')
381
+ try:
382
+ ctype = _scalar_type_map[dtype_native]
383
+ except KeyError as e:
384
+ raise NotImplementedError(
385
+ "Converting {!r} to a ctypes type".format(dtype)
386
+ ) from None
387
+
388
+ if dtype_with_endian.byteorder == '>':
389
+ ctype = ctype.__ctype_be__
390
+ elif dtype_with_endian.byteorder == '<':
391
+ ctype = ctype.__ctype_le__
392
+
393
+ return ctype
394
+
395
+
396
+ def _ctype_from_dtype_subarray(dtype):
397
+ element_dtype, shape = dtype.subdtype
398
+ ctype = _ctype_from_dtype(element_dtype)
399
+ return _ctype_ndarray(ctype, shape)
400
+
401
+
402
+ def _ctype_from_dtype_structured(dtype):
403
+ # extract offsets of each field
404
+ field_data = []
405
+ for name in dtype.names:
406
+ field_dtype, offset = dtype.fields[name][:2]
407
+ field_data.append((offset, name, _ctype_from_dtype(field_dtype)))
408
+
409
+ # ctypes doesn't care about field order
410
+ field_data = sorted(field_data, key=lambda f: f[0])
411
+
412
+ if len(field_data) > 1 and all(offset == 0 for offset, name, ctype in field_data):
413
+ # union, if multiple fields all at address 0
414
+ size = 0
415
+ _fields_ = []
416
+ for offset, name, ctype in field_data:
417
+ _fields_.append((name, ctype))
418
+ size = max(size, ctypes.sizeof(ctype))
419
+
420
+ # pad to the right size
421
+ if dtype.itemsize != size:
422
+ _fields_.append(('', ctypes.c_char * dtype.itemsize))
423
+
424
+ # we inserted manual padding, so always `_pack_`
425
+ return type('union', (ctypes.Union,), dict(
426
+ _fields_=_fields_,
427
+ _pack_=1,
428
+ __module__=None,
429
+ ))
430
+ else:
431
+ last_offset = 0
432
+ _fields_ = []
433
+ for offset, name, ctype in field_data:
434
+ padding = offset - last_offset
435
+ if padding < 0:
436
+ raise NotImplementedError("Overlapping fields")
437
+ if padding > 0:
438
+ _fields_.append(('', ctypes.c_char * padding))
439
+
440
+ _fields_.append((name, ctype))
441
+ last_offset = offset + ctypes.sizeof(ctype)
442
+
443
+
444
+ padding = dtype.itemsize - last_offset
445
+ if padding > 0:
446
+ _fields_.append(('', ctypes.c_char * padding))
447
+
448
+ # we inserted manual padding, so always `_pack_`
449
+ return type('struct', (ctypes.Structure,), dict(
450
+ _fields_=_fields_,
451
+ _pack_=1,
452
+ __module__=None,
453
+ ))
454
+
455
+
456
+ def _ctype_from_dtype(dtype):
457
+ if dtype.fields is not None:
458
+ return _ctype_from_dtype_structured(dtype)
459
+ elif dtype.subdtype is not None:
460
+ return _ctype_from_dtype_subarray(dtype)
461
+ else:
462
+ return _ctype_from_dtype_scalar(dtype)
463
+
464
+
465
+ def as_ctypes_type(dtype):
466
+ r"""
467
+ Convert a dtype into a ctypes type.
468
+
469
+ Parameters
470
+ ----------
471
+ dtype : dtype
472
+ The dtype to convert
473
+
474
+ Returns
475
+ -------
476
+ ctype
477
+ A ctype scalar, union, array, or struct
478
+
479
+ Raises
480
+ ------
481
+ NotImplementedError
482
+ If the conversion is not possible
483
+
484
+ Notes
485
+ -----
486
+ This function does not losslessly round-trip in either direction.
487
+
488
+ ``np.dtype(as_ctypes_type(dt))`` will:
489
+
490
+ - insert padding fields
491
+ - reorder fields to be sorted by offset
492
+ - discard field titles
493
+
494
+ ``as_ctypes_type(np.dtype(ctype))`` will:
495
+
496
+ - discard the class names of `ctypes.Structure`\ s and
497
+ `ctypes.Union`\ s
498
+ - convert single-element `ctypes.Union`\ s into single-element
499
+ `ctypes.Structure`\ s
500
+ - insert padding fields
501
+
502
+ """
503
+ return _ctype_from_dtype(_dtype(dtype))
504
+
505
+
506
+ def as_array(obj, shape=None):
507
+ """
508
+ Create a numpy array from a ctypes array or POINTER.
509
+
510
+ The numpy array shares the memory with the ctypes object.
511
+
512
+ The shape parameter must be given if converting from a ctypes POINTER.
513
+ The shape parameter is ignored if converting from a ctypes array
514
+ """
515
+ if isinstance(obj, ctypes._Pointer):
516
+ # convert pointers to an array of the desired shape
517
+ if shape is None:
518
+ raise TypeError(
519
+ 'as_array() requires a shape argument when called on a '
520
+ 'pointer')
521
+ p_arr_type = ctypes.POINTER(_ctype_ndarray(obj._type_, shape))
522
+ obj = ctypes.cast(obj, p_arr_type).contents
523
+
524
+ return asarray(obj)
525
+
526
+
527
+ def as_ctypes(obj):
528
+ """Create and return a ctypes object from a numpy array. Actually
529
+ anything that exposes the __array_interface__ is accepted."""
530
+ ai = obj.__array_interface__
531
+ if ai["strides"]:
532
+ raise TypeError("strided arrays not supported")
533
+ if ai["version"] != 3:
534
+ raise TypeError("only __array_interface__ version 3 supported")
535
+ addr, readonly = ai["data"]
536
+ if readonly:
537
+ raise TypeError("readonly arrays unsupported")
538
+
539
+ # can't use `_dtype((ai["typestr"], ai["shape"]))` here, as it overflows
540
+ # dtype.itemsize (gh-14214)
541
+ ctype_scalar = as_ctypes_type(ai["typestr"])
542
+ result_type = _ctype_ndarray(ctype_scalar, ai["shape"])
543
+ result = result_type.from_address(addr)
544
+ result.__keep = obj
545
+ return result
lib/python3.12/site-packages/numpy/ctypeslib.pyi ADDED
@@ -0,0 +1,251 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NOTE: Numpy's mypy plugin is used for importing the correct
2
+ # platform-specific `ctypes._SimpleCData[int]` sub-type
3
+ from ctypes import c_int64 as _c_intp
4
+
5
+ import os
6
+ import sys
7
+ import ctypes
8
+ from collections.abc import Iterable, Sequence
9
+ from typing import (
10
+ Literal as L,
11
+ Any,
12
+ Union,
13
+ TypeVar,
14
+ Generic,
15
+ overload,
16
+ ClassVar,
17
+ )
18
+
19
+ from numpy import (
20
+ ndarray,
21
+ dtype,
22
+ generic,
23
+ bool_,
24
+ byte,
25
+ short,
26
+ intc,
27
+ int_,
28
+ longlong,
29
+ ubyte,
30
+ ushort,
31
+ uintc,
32
+ uint,
33
+ ulonglong,
34
+ single,
35
+ double,
36
+ longdouble,
37
+ void,
38
+ )
39
+ from numpy.core._internal import _ctypes
40
+ from numpy.core.multiarray import flagsobj
41
+ from numpy._typing import (
42
+ # Arrays
43
+ NDArray,
44
+ _ArrayLike,
45
+
46
+ # Shapes
47
+ _ShapeLike,
48
+
49
+ # DTypes
50
+ DTypeLike,
51
+ _DTypeLike,
52
+ _VoidDTypeLike,
53
+ _BoolCodes,
54
+ _UByteCodes,
55
+ _UShortCodes,
56
+ _UIntCCodes,
57
+ _UIntCodes,
58
+ _ULongLongCodes,
59
+ _ByteCodes,
60
+ _ShortCodes,
61
+ _IntCCodes,
62
+ _IntCodes,
63
+ _LongLongCodes,
64
+ _SingleCodes,
65
+ _DoubleCodes,
66
+ _LongDoubleCodes,
67
+ )
68
+
69
+ # TODO: Add a proper `_Shape` bound once we've got variadic typevars
70
+ _DType = TypeVar("_DType", bound=dtype[Any])
71
+ _DTypeOptional = TypeVar("_DTypeOptional", bound=None | dtype[Any])
72
+ _SCT = TypeVar("_SCT", bound=generic)
73
+
74
+ _FlagsKind = L[
75
+ 'C_CONTIGUOUS', 'CONTIGUOUS', 'C',
76
+ 'F_CONTIGUOUS', 'FORTRAN', 'F',
77
+ 'ALIGNED', 'A',
78
+ 'WRITEABLE', 'W',
79
+ 'OWNDATA', 'O',
80
+ 'WRITEBACKIFCOPY', 'X',
81
+ ]
82
+
83
+ # TODO: Add a shape typevar once we have variadic typevars (PEP 646)
84
+ class _ndptr(ctypes.c_void_p, Generic[_DTypeOptional]):
85
+ # In practice these 4 classvars are defined in the dynamic class
86
+ # returned by `ndpointer`
87
+ _dtype_: ClassVar[_DTypeOptional]
88
+ _shape_: ClassVar[None]
89
+ _ndim_: ClassVar[None | int]
90
+ _flags_: ClassVar[None | list[_FlagsKind]]
91
+
92
+ @overload
93
+ @classmethod
94
+ def from_param(cls: type[_ndptr[None]], obj: ndarray[Any, Any]) -> _ctypes[Any]: ...
95
+ @overload
96
+ @classmethod
97
+ def from_param(cls: type[_ndptr[_DType]], obj: ndarray[Any, _DType]) -> _ctypes[Any]: ...
98
+
99
+ class _concrete_ndptr(_ndptr[_DType]):
100
+ _dtype_: ClassVar[_DType]
101
+ _shape_: ClassVar[tuple[int, ...]]
102
+ @property
103
+ def contents(self) -> ndarray[Any, _DType]: ...
104
+
105
+ def load_library(
106
+ libname: str | bytes | os.PathLike[str] | os.PathLike[bytes],
107
+ loader_path: str | bytes | os.PathLike[str] | os.PathLike[bytes],
108
+ ) -> ctypes.CDLL: ...
109
+
110
+ __all__: list[str]
111
+
112
+ c_intp = _c_intp
113
+
114
+ @overload
115
+ def ndpointer(
116
+ dtype: None = ...,
117
+ ndim: int = ...,
118
+ shape: None | _ShapeLike = ...,
119
+ flags: None | _FlagsKind | Iterable[_FlagsKind] | int | flagsobj = ...,
120
+ ) -> type[_ndptr[None]]: ...
121
+ @overload
122
+ def ndpointer(
123
+ dtype: _DTypeLike[_SCT],
124
+ ndim: int = ...,
125
+ *,
126
+ shape: _ShapeLike,
127
+ flags: None | _FlagsKind | Iterable[_FlagsKind] | int | flagsobj = ...,
128
+ ) -> type[_concrete_ndptr[dtype[_SCT]]]: ...
129
+ @overload
130
+ def ndpointer(
131
+ dtype: DTypeLike,
132
+ ndim: int = ...,
133
+ *,
134
+ shape: _ShapeLike,
135
+ flags: None | _FlagsKind | Iterable[_FlagsKind] | int | flagsobj = ...,
136
+ ) -> type[_concrete_ndptr[dtype[Any]]]: ...
137
+ @overload
138
+ def ndpointer(
139
+ dtype: _DTypeLike[_SCT],
140
+ ndim: int = ...,
141
+ shape: None = ...,
142
+ flags: None | _FlagsKind | Iterable[_FlagsKind] | int | flagsobj = ...,
143
+ ) -> type[_ndptr[dtype[_SCT]]]: ...
144
+ @overload
145
+ def ndpointer(
146
+ dtype: DTypeLike,
147
+ ndim: int = ...,
148
+ shape: None = ...,
149
+ flags: None | _FlagsKind | Iterable[_FlagsKind] | int | flagsobj = ...,
150
+ ) -> type[_ndptr[dtype[Any]]]: ...
151
+
152
+ @overload
153
+ def as_ctypes_type(dtype: _BoolCodes | _DTypeLike[bool_] | type[ctypes.c_bool]) -> type[ctypes.c_bool]: ...
154
+ @overload
155
+ def as_ctypes_type(dtype: _ByteCodes | _DTypeLike[byte] | type[ctypes.c_byte]) -> type[ctypes.c_byte]: ...
156
+ @overload
157
+ def as_ctypes_type(dtype: _ShortCodes | _DTypeLike[short] | type[ctypes.c_short]) -> type[ctypes.c_short]: ...
158
+ @overload
159
+ def as_ctypes_type(dtype: _IntCCodes | _DTypeLike[intc] | type[ctypes.c_int]) -> type[ctypes.c_int]: ...
160
+ @overload
161
+ def as_ctypes_type(dtype: _IntCodes | _DTypeLike[int_] | type[int | ctypes.c_long]) -> type[ctypes.c_long]: ...
162
+ @overload
163
+ def as_ctypes_type(dtype: _LongLongCodes | _DTypeLike[longlong] | type[ctypes.c_longlong]) -> type[ctypes.c_longlong]: ...
164
+ @overload
165
+ def as_ctypes_type(dtype: _UByteCodes | _DTypeLike[ubyte] | type[ctypes.c_ubyte]) -> type[ctypes.c_ubyte]: ...
166
+ @overload
167
+ def as_ctypes_type(dtype: _UShortCodes | _DTypeLike[ushort] | type[ctypes.c_ushort]) -> type[ctypes.c_ushort]: ...
168
+ @overload
169
+ def as_ctypes_type(dtype: _UIntCCodes | _DTypeLike[uintc] | type[ctypes.c_uint]) -> type[ctypes.c_uint]: ...
170
+ @overload
171
+ def as_ctypes_type(dtype: _UIntCodes | _DTypeLike[uint] | type[ctypes.c_ulong]) -> type[ctypes.c_ulong]: ...
172
+ @overload
173
+ def as_ctypes_type(dtype: _ULongLongCodes | _DTypeLike[ulonglong] | type[ctypes.c_ulonglong]) -> type[ctypes.c_ulonglong]: ...
174
+ @overload
175
+ def as_ctypes_type(dtype: _SingleCodes | _DTypeLike[single] | type[ctypes.c_float]) -> type[ctypes.c_float]: ...
176
+ @overload
177
+ def as_ctypes_type(dtype: _DoubleCodes | _DTypeLike[double] | type[float | ctypes.c_double]) -> type[ctypes.c_double]: ...
178
+ @overload
179
+ def as_ctypes_type(dtype: _LongDoubleCodes | _DTypeLike[longdouble] | type[ctypes.c_longdouble]) -> type[ctypes.c_longdouble]: ...
180
+ @overload
181
+ def as_ctypes_type(dtype: _VoidDTypeLike) -> type[Any]: ... # `ctypes.Union` or `ctypes.Structure`
182
+ @overload
183
+ def as_ctypes_type(dtype: str) -> type[Any]: ...
184
+
185
+ @overload
186
+ def as_array(obj: ctypes._PointerLike, shape: Sequence[int]) -> NDArray[Any]: ...
187
+ @overload
188
+ def as_array(obj: _ArrayLike[_SCT], shape: None | _ShapeLike = ...) -> NDArray[_SCT]: ...
189
+ @overload
190
+ def as_array(obj: object, shape: None | _ShapeLike = ...) -> NDArray[Any]: ...
191
+
192
+ @overload
193
+ def as_ctypes(obj: bool_) -> ctypes.c_bool: ...
194
+ @overload
195
+ def as_ctypes(obj: byte) -> ctypes.c_byte: ...
196
+ @overload
197
+ def as_ctypes(obj: short) -> ctypes.c_short: ...
198
+ @overload
199
+ def as_ctypes(obj: intc) -> ctypes.c_int: ...
200
+ @overload
201
+ def as_ctypes(obj: int_) -> ctypes.c_long: ...
202
+ @overload
203
+ def as_ctypes(obj: longlong) -> ctypes.c_longlong: ...
204
+ @overload
205
+ def as_ctypes(obj: ubyte) -> ctypes.c_ubyte: ...
206
+ @overload
207
+ def as_ctypes(obj: ushort) -> ctypes.c_ushort: ...
208
+ @overload
209
+ def as_ctypes(obj: uintc) -> ctypes.c_uint: ...
210
+ @overload
211
+ def as_ctypes(obj: uint) -> ctypes.c_ulong: ...
212
+ @overload
213
+ def as_ctypes(obj: ulonglong) -> ctypes.c_ulonglong: ...
214
+ @overload
215
+ def as_ctypes(obj: single) -> ctypes.c_float: ...
216
+ @overload
217
+ def as_ctypes(obj: double) -> ctypes.c_double: ...
218
+ @overload
219
+ def as_ctypes(obj: longdouble) -> ctypes.c_longdouble: ...
220
+ @overload
221
+ def as_ctypes(obj: void) -> Any: ... # `ctypes.Union` or `ctypes.Structure`
222
+ @overload
223
+ def as_ctypes(obj: NDArray[bool_]) -> ctypes.Array[ctypes.c_bool]: ...
224
+ @overload
225
+ def as_ctypes(obj: NDArray[byte]) -> ctypes.Array[ctypes.c_byte]: ...
226
+ @overload
227
+ def as_ctypes(obj: NDArray[short]) -> ctypes.Array[ctypes.c_short]: ...
228
+ @overload
229
+ def as_ctypes(obj: NDArray[intc]) -> ctypes.Array[ctypes.c_int]: ...
230
+ @overload
231
+ def as_ctypes(obj: NDArray[int_]) -> ctypes.Array[ctypes.c_long]: ...
232
+ @overload
233
+ def as_ctypes(obj: NDArray[longlong]) -> ctypes.Array[ctypes.c_longlong]: ...
234
+ @overload
235
+ def as_ctypes(obj: NDArray[ubyte]) -> ctypes.Array[ctypes.c_ubyte]: ...
236
+ @overload
237
+ def as_ctypes(obj: NDArray[ushort]) -> ctypes.Array[ctypes.c_ushort]: ...
238
+ @overload
239
+ def as_ctypes(obj: NDArray[uintc]) -> ctypes.Array[ctypes.c_uint]: ...
240
+ @overload
241
+ def as_ctypes(obj: NDArray[uint]) -> ctypes.Array[ctypes.c_ulong]: ...
242
+ @overload
243
+ def as_ctypes(obj: NDArray[ulonglong]) -> ctypes.Array[ctypes.c_ulonglong]: ...
244
+ @overload
245
+ def as_ctypes(obj: NDArray[single]) -> ctypes.Array[ctypes.c_float]: ...
246
+ @overload
247
+ def as_ctypes(obj: NDArray[double]) -> ctypes.Array[ctypes.c_double]: ...
248
+ @overload
249
+ def as_ctypes(obj: NDArray[longdouble]) -> ctypes.Array[ctypes.c_longdouble]: ...
250
+ @overload
251
+ def as_ctypes(obj: NDArray[void]) -> ctypes.Array[Any]: ... # `ctypes.Union` or `ctypes.Structure`
lib/python3.12/site-packages/numpy/dtypes.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ DType classes and utility (:mod:`numpy.dtypes`)
3
+ ===============================================
4
+
5
+ This module is home to specific dtypes related functionality and their classes.
6
+ For more general information about dtypes, also see `numpy.dtype` and
7
+ :ref:`arrays.dtypes`.
8
+
9
+ Similar to the builtin ``types`` module, this submodule defines types (classes)
10
+ that are not widely used directly.
11
+
12
+ .. versionadded:: NumPy 1.25
13
+
14
+ The dtypes module is new in NumPy 1.25. Previously DType classes were
15
+ only accessible indirectly.
16
+
17
+
18
+ DType classes
19
+ -------------
20
+
21
+ The following are the classes of the corresponding NumPy dtype instances and
22
+ NumPy scalar types. The classes can be used in ``isinstance`` checks and can
23
+ also be instantiated or used directly. Direct use of these classes is not
24
+ typical, since their scalar counterparts (e.g. ``np.float64``) or strings
25
+ like ``"float64"`` can be used.
26
+
27
+ .. list-table::
28
+ :header-rows: 1
29
+
30
+ * - Group
31
+ - DType class
32
+
33
+ * - Boolean
34
+ - ``BoolDType``
35
+
36
+ * - Bit-sized integers
37
+ - ``Int8DType``, ``UInt8DType``, ``Int16DType``, ``UInt16DType``,
38
+ ``Int32DType``, ``UInt32DType``, ``Int64DType``, ``UInt64DType``
39
+
40
+ * - C-named integers (may be aliases)
41
+ - ``ByteDType``, ``UByteDType``, ``ShortDType``, ``UShortDType``,
42
+ ``IntDType``, ``UIntDType``, ``LongDType``, ``ULongDType``,
43
+ ``LongLongDType``, ``ULongLongDType``
44
+
45
+ * - Floating point
46
+ - ``Float16DType``, ``Float32DType``, ``Float64DType``,
47
+ ``LongDoubleDType``
48
+
49
+ * - Complex
50
+ - ``Complex64DType``, ``Complex128DType``, ``CLongDoubleDType``
51
+
52
+ * - Strings
53
+ - ``BytesDType``, ``BytesDType``
54
+
55
+ * - Times
56
+ - ``DateTime64DType``, ``TimeDelta64DType``
57
+
58
+ * - Others
59
+ - ``ObjectDType``, ``VoidDType``
60
+
61
+ """
62
+
63
+ __all__ = []
64
+
65
+
66
+ def _add_dtype_helper(DType, alias):
67
+ # Function to add DTypes a bit more conveniently without channeling them
68
+ # through `numpy.core._multiarray_umath` namespace or similar.
69
+ from numpy import dtypes
70
+
71
+ setattr(dtypes, DType.__name__, DType)
72
+ __all__.append(DType.__name__)
73
+
74
+ if alias:
75
+ alias = alias.removeprefix("numpy.dtypes.")
76
+ setattr(dtypes, alias, DType)
77
+ __all__.append(alias)
lib/python3.12/site-packages/numpy/dtypes.pyi ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+
4
+ __all__: list[str]
5
+
6
+ # Boolean:
7
+ BoolDType = np.dtype[np.bool_]
8
+ # Sized integers:
9
+ Int8DType = np.dtype[np.int8]
10
+ UInt8DType = np.dtype[np.uint8]
11
+ Int16DType = np.dtype[np.int16]
12
+ UInt16DType = np.dtype[np.uint16]
13
+ Int32DType = np.dtype[np.int32]
14
+ UInt32DType = np.dtype[np.uint32]
15
+ Int64DType = np.dtype[np.int64]
16
+ UInt64DType = np.dtype[np.uint64]
17
+ # Standard C-named version/alias:
18
+ ByteDType = np.dtype[np.byte]
19
+ UByteDType = np.dtype[np.ubyte]
20
+ ShortDType = np.dtype[np.short]
21
+ UShortDType = np.dtype[np.ushort]
22
+ IntDType = np.dtype[np.intc]
23
+ UIntDType = np.dtype[np.uintc]
24
+ LongDType = np.dtype[np.int_] # Unfortunately, the correct scalar
25
+ ULongDType = np.dtype[np.uint] # Unfortunately, the correct scalar
26
+ LongLongDType = np.dtype[np.longlong]
27
+ ULongLongDType = np.dtype[np.ulonglong]
28
+ # Floats
29
+ Float16DType = np.dtype[np.float16]
30
+ Float32DType = np.dtype[np.float32]
31
+ Float64DType = np.dtype[np.float64]
32
+ LongDoubleDType = np.dtype[np.longdouble]
33
+ # Complex:
34
+ Complex64DType = np.dtype[np.complex64]
35
+ Complex128DType = np.dtype[np.complex128]
36
+ CLongDoubleDType = np.dtype[np.clongdouble]
37
+ # Others:
38
+ ObjectDType = np.dtype[np.object_]
39
+ BytesDType = np.dtype[np.bytes_]
40
+ StrDType = np.dtype[np.str_]
41
+ VoidDType = np.dtype[np.void]
42
+ DateTime64DType = np.dtype[np.datetime64]
43
+ TimeDelta64DType = np.dtype[np.timedelta64]
lib/python3.12/site-packages/numpy/exceptions.py ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Exceptions and Warnings (:mod:`numpy.exceptions`)
3
+ =================================================
4
+
5
+ General exceptions used by NumPy. Note that some exceptions may be module
6
+ specific, such as linear algebra errors.
7
+
8
+ .. versionadded:: NumPy 1.25
9
+
10
+ The exceptions module is new in NumPy 1.25. Older exceptions remain
11
+ available through the main NumPy namespace for compatibility.
12
+
13
+ .. currentmodule:: numpy.exceptions
14
+
15
+ Warnings
16
+ --------
17
+ .. autosummary::
18
+ :toctree: generated/
19
+
20
+ ComplexWarning Given when converting complex to real.
21
+ VisibleDeprecationWarning Same as a DeprecationWarning, but more visible.
22
+
23
+ Exceptions
24
+ ----------
25
+ .. autosummary::
26
+ :toctree: generated/
27
+
28
+ AxisError Given when an axis was invalid.
29
+ DTypePromotionError Given when no common dtype could be found.
30
+ TooHardError Error specific to `numpy.shares_memory`.
31
+
32
+ """
33
+
34
+
35
+ __all__ = [
36
+ "ComplexWarning", "VisibleDeprecationWarning", "ModuleDeprecationWarning",
37
+ "TooHardError", "AxisError", "DTypePromotionError"]
38
+
39
+
40
+ # Disallow reloading this module so as to preserve the identities of the
41
+ # classes defined here.
42
+ if '_is_loaded' in globals():
43
+ raise RuntimeError('Reloading numpy._globals is not allowed')
44
+ _is_loaded = True
45
+
46
+
47
+ class ComplexWarning(RuntimeWarning):
48
+ """
49
+ The warning raised when casting a complex dtype to a real dtype.
50
+
51
+ As implemented, casting a complex number to a real discards its imaginary
52
+ part, but this behavior may not be what the user actually wants.
53
+
54
+ """
55
+ pass
56
+
57
+
58
+ class ModuleDeprecationWarning(DeprecationWarning):
59
+ """Module deprecation warning.
60
+
61
+ .. warning::
62
+
63
+ This warning should not be used, since nose testing is not relevant
64
+ anymore.
65
+
66
+ The nose tester turns ordinary Deprecation warnings into test failures.
67
+ That makes it hard to deprecate whole modules, because they get
68
+ imported by default. So this is a special Deprecation warning that the
69
+ nose tester will let pass without making tests fail.
70
+
71
+ """
72
+
73
+
74
+ class VisibleDeprecationWarning(UserWarning):
75
+ """Visible deprecation warning.
76
+
77
+ By default, python will not show deprecation warnings, so this class
78
+ can be used when a very visible warning is helpful, for example because
79
+ the usage is most likely a user bug.
80
+
81
+ """
82
+
83
+
84
+ # Exception used in shares_memory()
85
+ class TooHardError(RuntimeError):
86
+ """max_work was exceeded.
87
+
88
+ This is raised whenever the maximum number of candidate solutions
89
+ to consider specified by the ``max_work`` parameter is exceeded.
90
+ Assigning a finite number to max_work may have caused the operation
91
+ to fail.
92
+
93
+ """
94
+
95
+ pass
96
+
97
+
98
+ class AxisError(ValueError, IndexError):
99
+ """Axis supplied was invalid.
100
+
101
+ This is raised whenever an ``axis`` parameter is specified that is larger
102
+ than the number of array dimensions.
103
+ For compatibility with code written against older numpy versions, which
104
+ raised a mixture of `ValueError` and `IndexError` for this situation, this
105
+ exception subclasses both to ensure that ``except ValueError`` and
106
+ ``except IndexError`` statements continue to catch `AxisError`.
107
+
108
+ .. versionadded:: 1.13
109
+
110
+ Parameters
111
+ ----------
112
+ axis : int or str
113
+ The out of bounds axis or a custom exception message.
114
+ If an axis is provided, then `ndim` should be specified as well.
115
+ ndim : int, optional
116
+ The number of array dimensions.
117
+ msg_prefix : str, optional
118
+ A prefix for the exception message.
119
+
120
+ Attributes
121
+ ----------
122
+ axis : int, optional
123
+ The out of bounds axis or ``None`` if a custom exception
124
+ message was provided. This should be the axis as passed by
125
+ the user, before any normalization to resolve negative indices.
126
+
127
+ .. versionadded:: 1.22
128
+ ndim : int, optional
129
+ The number of array dimensions or ``None`` if a custom exception
130
+ message was provided.
131
+
132
+ .. versionadded:: 1.22
133
+
134
+
135
+ Examples
136
+ --------
137
+ >>> array_1d = np.arange(10)
138
+ >>> np.cumsum(array_1d, axis=1)
139
+ Traceback (most recent call last):
140
+ ...
141
+ numpy.exceptions.AxisError: axis 1 is out of bounds for array of dimension 1
142
+
143
+ Negative axes are preserved:
144
+
145
+ >>> np.cumsum(array_1d, axis=-2)
146
+ Traceback (most recent call last):
147
+ ...
148
+ numpy.exceptions.AxisError: axis -2 is out of bounds for array of dimension 1
149
+
150
+ The class constructor generally takes the axis and arrays'
151
+ dimensionality as arguments:
152
+
153
+ >>> print(np.AxisError(2, 1, msg_prefix='error'))
154
+ error: axis 2 is out of bounds for array of dimension 1
155
+
156
+ Alternatively, a custom exception message can be passed:
157
+
158
+ >>> print(np.AxisError('Custom error message'))
159
+ Custom error message
160
+
161
+ """
162
+
163
+ __slots__ = ("axis", "ndim", "_msg")
164
+
165
+ def __init__(self, axis, ndim=None, msg_prefix=None):
166
+ if ndim is msg_prefix is None:
167
+ # single-argument form: directly set the error message
168
+ self._msg = axis
169
+ self.axis = None
170
+ self.ndim = None
171
+ else:
172
+ self._msg = msg_prefix
173
+ self.axis = axis
174
+ self.ndim = ndim
175
+
176
+ def __str__(self):
177
+ axis = self.axis
178
+ ndim = self.ndim
179
+
180
+ if axis is ndim is None:
181
+ return self._msg
182
+ else:
183
+ msg = f"axis {axis} is out of bounds for array of dimension {ndim}"
184
+ if self._msg is not None:
185
+ msg = f"{self._msg}: {msg}"
186
+ return msg
187
+
188
+
189
+ class DTypePromotionError(TypeError):
190
+ """Multiple DTypes could not be converted to a common one.
191
+
192
+ This exception derives from ``TypeError`` and is raised whenever dtypes
193
+ cannot be converted to a single common one. This can be because they
194
+ are of a different category/class or incompatible instances of the same
195
+ one (see Examples).
196
+
197
+ Notes
198
+ -----
199
+ Many functions will use promotion to find the correct result and
200
+ implementation. For these functions the error will typically be chained
201
+ with a more specific error indicating that no implementation was found
202
+ for the input dtypes.
203
+
204
+ Typically promotion should be considered "invalid" between the dtypes of
205
+ two arrays when `arr1 == arr2` can safely return all ``False`` because the
206
+ dtypes are fundamentally different.
207
+
208
+ Examples
209
+ --------
210
+ Datetimes and complex numbers are incompatible classes and cannot be
211
+ promoted:
212
+
213
+ >>> np.result_type(np.dtype("M8[s]"), np.complex128)
214
+ DTypePromotionError: The DType <class 'numpy.dtype[datetime64]'> could not
215
+ be promoted by <class 'numpy.dtype[complex128]'>. This means that no common
216
+ DType exists for the given inputs. For example they cannot be stored in a
217
+ single array unless the dtype is `object`. The full list of DTypes is:
218
+ (<class 'numpy.dtype[datetime64]'>, <class 'numpy.dtype[complex128]'>)
219
+
220
+ For example for structured dtypes, the structure can mismatch and the
221
+ same ``DTypePromotionError`` is given when two structured dtypes with
222
+ a mismatch in their number of fields is given:
223
+
224
+ >>> dtype1 = np.dtype([("field1", np.float64), ("field2", np.int64)])
225
+ >>> dtype2 = np.dtype([("field1", np.float64)])
226
+ >>> np.promote_types(dtype1, dtype2)
227
+ DTypePromotionError: field names `('field1', 'field2')` and `('field1',)`
228
+ mismatch.
229
+
230
+ """
231
+ pass
lib/python3.12/site-packages/numpy/exceptions.pyi ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import overload
2
+
3
+ __all__: list[str]
4
+
5
+ class ComplexWarning(RuntimeWarning): ...
6
+ class ModuleDeprecationWarning(DeprecationWarning): ...
7
+ class VisibleDeprecationWarning(UserWarning): ...
8
+ class TooHardError(RuntimeError): ...
9
+ class DTypePromotionError(TypeError): ...
10
+
11
+ class AxisError(ValueError, IndexError):
12
+ axis: None | int
13
+ ndim: None | int
14
+ @overload
15
+ def __init__(self, axis: str, ndim: None = ..., msg_prefix: None = ...) -> None: ...
16
+ @overload
17
+ def __init__(self, axis: int, ndim: int, msg_prefix: None | str = ...) -> None: ...
18
+ def __str__(self) -> str: ...
lib/python3.12/site-packages/numpy/matlib.py ADDED
@@ -0,0 +1,378 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import warnings
2
+
3
+ # 2018-05-29, PendingDeprecationWarning added to matrix.__new__
4
+ # 2020-01-23, numpy 1.19.0 PendingDeprecatonWarning
5
+ warnings.warn("Importing from numpy.matlib is deprecated since 1.19.0. "
6
+ "The matrix subclass is not the recommended way to represent "
7
+ "matrices or deal with linear algebra (see "
8
+ "https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). "
9
+ "Please adjust your code to use regular ndarray. ",
10
+ PendingDeprecationWarning, stacklevel=2)
11
+
12
+ import numpy as np
13
+ from numpy.matrixlib.defmatrix import matrix, asmatrix
14
+ # Matlib.py contains all functions in the numpy namespace with a few
15
+ # replacements. See doc/source/reference/routines.matlib.rst for details.
16
+ # Need * as we're copying the numpy namespace.
17
+ from numpy import * # noqa: F403
18
+
19
+ __version__ = np.__version__
20
+
21
+ __all__ = np.__all__[:] # copy numpy namespace
22
+ __all__ += ['rand', 'randn', 'repmat']
23
+
24
+ def empty(shape, dtype=None, order='C'):
25
+ """Return a new matrix of given shape and type, without initializing entries.
26
+
27
+ Parameters
28
+ ----------
29
+ shape : int or tuple of int
30
+ Shape of the empty matrix.
31
+ dtype : data-type, optional
32
+ Desired output data-type.
33
+ order : {'C', 'F'}, optional
34
+ Whether to store multi-dimensional data in row-major
35
+ (C-style) or column-major (Fortran-style) order in
36
+ memory.
37
+
38
+ See Also
39
+ --------
40
+ empty_like, zeros
41
+
42
+ Notes
43
+ -----
44
+ `empty`, unlike `zeros`, does not set the matrix values to zero,
45
+ and may therefore be marginally faster. On the other hand, it requires
46
+ the user to manually set all the values in the array, and should be
47
+ used with caution.
48
+
49
+ Examples
50
+ --------
51
+ >>> import numpy.matlib
52
+ >>> np.matlib.empty((2, 2)) # filled with random data
53
+ matrix([[ 6.76425276e-320, 9.79033856e-307], # random
54
+ [ 7.39337286e-309, 3.22135945e-309]])
55
+ >>> np.matlib.empty((2, 2), dtype=int)
56
+ matrix([[ 6600475, 0], # random
57
+ [ 6586976, 22740995]])
58
+
59
+ """
60
+ return ndarray.__new__(matrix, shape, dtype, order=order)
61
+
62
+ def ones(shape, dtype=None, order='C'):
63
+ """
64
+ Matrix of ones.
65
+
66
+ Return a matrix of given shape and type, filled with ones.
67
+
68
+ Parameters
69
+ ----------
70
+ shape : {sequence of ints, int}
71
+ Shape of the matrix
72
+ dtype : data-type, optional
73
+ The desired data-type for the matrix, default is np.float64.
74
+ order : {'C', 'F'}, optional
75
+ Whether to store matrix in C- or Fortran-contiguous order,
76
+ default is 'C'.
77
+
78
+ Returns
79
+ -------
80
+ out : matrix
81
+ Matrix of ones of given shape, dtype, and order.
82
+
83
+ See Also
84
+ --------
85
+ ones : Array of ones.
86
+ matlib.zeros : Zero matrix.
87
+
88
+ Notes
89
+ -----
90
+ If `shape` has length one i.e. ``(N,)``, or is a scalar ``N``,
91
+ `out` becomes a single row matrix of shape ``(1,N)``.
92
+
93
+ Examples
94
+ --------
95
+ >>> np.matlib.ones((2,3))
96
+ matrix([[1., 1., 1.],
97
+ [1., 1., 1.]])
98
+
99
+ >>> np.matlib.ones(2)
100
+ matrix([[1., 1.]])
101
+
102
+ """
103
+ a = ndarray.__new__(matrix, shape, dtype, order=order)
104
+ a.fill(1)
105
+ return a
106
+
107
+ def zeros(shape, dtype=None, order='C'):
108
+ """
109
+ Return a matrix of given shape and type, filled with zeros.
110
+
111
+ Parameters
112
+ ----------
113
+ shape : int or sequence of ints
114
+ Shape of the matrix
115
+ dtype : data-type, optional
116
+ The desired data-type for the matrix, default is float.
117
+ order : {'C', 'F'}, optional
118
+ Whether to store the result in C- or Fortran-contiguous order,
119
+ default is 'C'.
120
+
121
+ Returns
122
+ -------
123
+ out : matrix
124
+ Zero matrix of given shape, dtype, and order.
125
+
126
+ See Also
127
+ --------
128
+ numpy.zeros : Equivalent array function.
129
+ matlib.ones : Return a matrix of ones.
130
+
131
+ Notes
132
+ -----
133
+ If `shape` has length one i.e. ``(N,)``, or is a scalar ``N``,
134
+ `out` becomes a single row matrix of shape ``(1,N)``.
135
+
136
+ Examples
137
+ --------
138
+ >>> import numpy.matlib
139
+ >>> np.matlib.zeros((2, 3))
140
+ matrix([[0., 0., 0.],
141
+ [0., 0., 0.]])
142
+
143
+ >>> np.matlib.zeros(2)
144
+ matrix([[0., 0.]])
145
+
146
+ """
147
+ a = ndarray.__new__(matrix, shape, dtype, order=order)
148
+ a.fill(0)
149
+ return a
150
+
151
+ def identity(n,dtype=None):
152
+ """
153
+ Returns the square identity matrix of given size.
154
+
155
+ Parameters
156
+ ----------
157
+ n : int
158
+ Size of the returned identity matrix.
159
+ dtype : data-type, optional
160
+ Data-type of the output. Defaults to ``float``.
161
+
162
+ Returns
163
+ -------
164
+ out : matrix
165
+ `n` x `n` matrix with its main diagonal set to one,
166
+ and all other elements zero.
167
+
168
+ See Also
169
+ --------
170
+ numpy.identity : Equivalent array function.
171
+ matlib.eye : More general matrix identity function.
172
+
173
+ Examples
174
+ --------
175
+ >>> import numpy.matlib
176
+ >>> np.matlib.identity(3, dtype=int)
177
+ matrix([[1, 0, 0],
178
+ [0, 1, 0],
179
+ [0, 0, 1]])
180
+
181
+ """
182
+ a = array([1]+n*[0], dtype=dtype)
183
+ b = empty((n, n), dtype=dtype)
184
+ b.flat = a
185
+ return b
186
+
187
+ def eye(n,M=None, k=0, dtype=float, order='C'):
188
+ """
189
+ Return a matrix with ones on the diagonal and zeros elsewhere.
190
+
191
+ Parameters
192
+ ----------
193
+ n : int
194
+ Number of rows in the output.
195
+ M : int, optional
196
+ Number of columns in the output, defaults to `n`.
197
+ k : int, optional
198
+ Index of the diagonal: 0 refers to the main diagonal,
199
+ a positive value refers to an upper diagonal,
200
+ and a negative value to a lower diagonal.
201
+ dtype : dtype, optional
202
+ Data-type of the returned matrix.
203
+ order : {'C', 'F'}, optional
204
+ Whether the output should be stored in row-major (C-style) or
205
+ column-major (Fortran-style) order in memory.
206
+
207
+ .. versionadded:: 1.14.0
208
+
209
+ Returns
210
+ -------
211
+ I : matrix
212
+ A `n` x `M` matrix where all elements are equal to zero,
213
+ except for the `k`-th diagonal, whose values are equal to one.
214
+
215
+ See Also
216
+ --------
217
+ numpy.eye : Equivalent array function.
218
+ identity : Square identity matrix.
219
+
220
+ Examples
221
+ --------
222
+ >>> import numpy.matlib
223
+ >>> np.matlib.eye(3, k=1, dtype=float)
224
+ matrix([[0., 1., 0.],
225
+ [0., 0., 1.],
226
+ [0., 0., 0.]])
227
+
228
+ """
229
+ return asmatrix(np.eye(n, M=M, k=k, dtype=dtype, order=order))
230
+
231
+ def rand(*args):
232
+ """
233
+ Return a matrix of random values with given shape.
234
+
235
+ Create a matrix of the given shape and propagate it with
236
+ random samples from a uniform distribution over ``[0, 1)``.
237
+
238
+ Parameters
239
+ ----------
240
+ \\*args : Arguments
241
+ Shape of the output.
242
+ If given as N integers, each integer specifies the size of one
243
+ dimension.
244
+ If given as a tuple, this tuple gives the complete shape.
245
+
246
+ Returns
247
+ -------
248
+ out : ndarray
249
+ The matrix of random values with shape given by `\\*args`.
250
+
251
+ See Also
252
+ --------
253
+ randn, numpy.random.RandomState.rand
254
+
255
+ Examples
256
+ --------
257
+ >>> np.random.seed(123)
258
+ >>> import numpy.matlib
259
+ >>> np.matlib.rand(2, 3)
260
+ matrix([[0.69646919, 0.28613933, 0.22685145],
261
+ [0.55131477, 0.71946897, 0.42310646]])
262
+ >>> np.matlib.rand((2, 3))
263
+ matrix([[0.9807642 , 0.68482974, 0.4809319 ],
264
+ [0.39211752, 0.34317802, 0.72904971]])
265
+
266
+ If the first argument is a tuple, other arguments are ignored:
267
+
268
+ >>> np.matlib.rand((2, 3), 4)
269
+ matrix([[0.43857224, 0.0596779 , 0.39804426],
270
+ [0.73799541, 0.18249173, 0.17545176]])
271
+
272
+ """
273
+ if isinstance(args[0], tuple):
274
+ args = args[0]
275
+ return asmatrix(np.random.rand(*args))
276
+
277
+ def randn(*args):
278
+ """
279
+ Return a random matrix with data from the "standard normal" distribution.
280
+
281
+ `randn` generates a matrix filled with random floats sampled from a
282
+ univariate "normal" (Gaussian) distribution of mean 0 and variance 1.
283
+
284
+ Parameters
285
+ ----------
286
+ \\*args : Arguments
287
+ Shape of the output.
288
+ If given as N integers, each integer specifies the size of one
289
+ dimension. If given as a tuple, this tuple gives the complete shape.
290
+
291
+ Returns
292
+ -------
293
+ Z : matrix of floats
294
+ A matrix of floating-point samples drawn from the standard normal
295
+ distribution.
296
+
297
+ See Also
298
+ --------
299
+ rand, numpy.random.RandomState.randn
300
+
301
+ Notes
302
+ -----
303
+ For random samples from the normal distribution with mean ``mu`` and
304
+ standard deviation ``sigma``, use::
305
+
306
+ sigma * np.matlib.randn(...) + mu
307
+
308
+ Examples
309
+ --------
310
+ >>> np.random.seed(123)
311
+ >>> import numpy.matlib
312
+ >>> np.matlib.randn(1)
313
+ matrix([[-1.0856306]])
314
+ >>> np.matlib.randn(1, 2, 3)
315
+ matrix([[ 0.99734545, 0.2829785 , -1.50629471],
316
+ [-0.57860025, 1.65143654, -2.42667924]])
317
+
318
+ Two-by-four matrix of samples from the normal distribution with
319
+ mean 3 and standard deviation 2.5:
320
+
321
+ >>> 2.5 * np.matlib.randn((2, 4)) + 3
322
+ matrix([[1.92771843, 6.16484065, 0.83314899, 1.30278462],
323
+ [2.76322758, 6.72847407, 1.40274501, 1.8900451 ]])
324
+
325
+ """
326
+ if isinstance(args[0], tuple):
327
+ args = args[0]
328
+ return asmatrix(np.random.randn(*args))
329
+
330
+ def repmat(a, m, n):
331
+ """
332
+ Repeat a 0-D to 2-D array or matrix MxN times.
333
+
334
+ Parameters
335
+ ----------
336
+ a : array_like
337
+ The array or matrix to be repeated.
338
+ m, n : int
339
+ The number of times `a` is repeated along the first and second axes.
340
+
341
+ Returns
342
+ -------
343
+ out : ndarray
344
+ The result of repeating `a`.
345
+
346
+ Examples
347
+ --------
348
+ >>> import numpy.matlib
349
+ >>> a0 = np.array(1)
350
+ >>> np.matlib.repmat(a0, 2, 3)
351
+ array([[1, 1, 1],
352
+ [1, 1, 1]])
353
+
354
+ >>> a1 = np.arange(4)
355
+ >>> np.matlib.repmat(a1, 2, 2)
356
+ array([[0, 1, 2, 3, 0, 1, 2, 3],
357
+ [0, 1, 2, 3, 0, 1, 2, 3]])
358
+
359
+ >>> a2 = np.asmatrix(np.arange(6).reshape(2, 3))
360
+ >>> np.matlib.repmat(a2, 2, 3)
361
+ matrix([[0, 1, 2, 0, 1, 2, 0, 1, 2],
362
+ [3, 4, 5, 3, 4, 5, 3, 4, 5],
363
+ [0, 1, 2, 0, 1, 2, 0, 1, 2],
364
+ [3, 4, 5, 3, 4, 5, 3, 4, 5]])
365
+
366
+ """
367
+ a = asanyarray(a)
368
+ ndim = a.ndim
369
+ if ndim == 0:
370
+ origrows, origcols = (1, 1)
371
+ elif ndim == 1:
372
+ origrows, origcols = (1, a.shape[0])
373
+ else:
374
+ origrows, origcols = a.shape
375
+ rows = origrows * m
376
+ cols = origcols * n
377
+ c = a.reshape(1, a.size).repeat(m, 0).reshape(rows, origcols).repeat(n, 0)
378
+ return c.reshape(rows, cols)
lib/python3.12/site-packages/numpy/polynomial/__init__.py ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ A sub-package for efficiently dealing with polynomials.
3
+
4
+ Within the documentation for this sub-package, a "finite power series,"
5
+ i.e., a polynomial (also referred to simply as a "series") is represented
6
+ by a 1-D numpy array of the polynomial's coefficients, ordered from lowest
7
+ order term to highest. For example, array([1,2,3]) represents
8
+ ``P_0 + 2*P_1 + 3*P_2``, where P_n is the n-th order basis polynomial
9
+ applicable to the specific module in question, e.g., `polynomial` (which
10
+ "wraps" the "standard" basis) or `chebyshev`. For optimal performance,
11
+ all operations on polynomials, including evaluation at an argument, are
12
+ implemented as operations on the coefficients. Additional (module-specific)
13
+ information can be found in the docstring for the module of interest.
14
+
15
+ This package provides *convenience classes* for each of six different kinds
16
+ of polynomials:
17
+
18
+ ======================== ================
19
+ **Name** **Provides**
20
+ ======================== ================
21
+ `~polynomial.Polynomial` Power series
22
+ `~chebyshev.Chebyshev` Chebyshev series
23
+ `~legendre.Legendre` Legendre series
24
+ `~laguerre.Laguerre` Laguerre series
25
+ `~hermite.Hermite` Hermite series
26
+ `~hermite_e.HermiteE` HermiteE series
27
+ ======================== ================
28
+
29
+ These *convenience classes* provide a consistent interface for creating,
30
+ manipulating, and fitting data with polynomials of different bases.
31
+ The convenience classes are the preferred interface for the `~numpy.polynomial`
32
+ package, and are available from the ``numpy.polynomial`` namespace.
33
+ This eliminates the need to navigate to the corresponding submodules, e.g.
34
+ ``np.polynomial.Polynomial`` or ``np.polynomial.Chebyshev`` instead of
35
+ ``np.polynomial.polynomial.Polynomial`` or
36
+ ``np.polynomial.chebyshev.Chebyshev``, respectively.
37
+ The classes provide a more consistent and concise interface than the
38
+ type-specific functions defined in the submodules for each type of polynomial.
39
+ For example, to fit a Chebyshev polynomial with degree ``1`` to data given
40
+ by arrays ``xdata`` and ``ydata``, the
41
+ `~chebyshev.Chebyshev.fit` class method::
42
+
43
+ >>> from numpy.polynomial import Chebyshev
44
+ >>> c = Chebyshev.fit(xdata, ydata, deg=1)
45
+
46
+ is preferred over the `chebyshev.chebfit` function from the
47
+ ``np.polynomial.chebyshev`` module::
48
+
49
+ >>> from numpy.polynomial.chebyshev import chebfit
50
+ >>> c = chebfit(xdata, ydata, deg=1)
51
+
52
+ See :doc:`routines.polynomials.classes` for more details.
53
+
54
+ Convenience Classes
55
+ ===================
56
+
57
+ The following lists the various constants and methods common to all of
58
+ the classes representing the various kinds of polynomials. In the following,
59
+ the term ``Poly`` represents any one of the convenience classes (e.g.
60
+ `~polynomial.Polynomial`, `~chebyshev.Chebyshev`, `~hermite.Hermite`, etc.)
61
+ while the lowercase ``p`` represents an **instance** of a polynomial class.
62
+
63
+ Constants
64
+ ---------
65
+
66
+ - ``Poly.domain`` -- Default domain
67
+ - ``Poly.window`` -- Default window
68
+ - ``Poly.basis_name`` -- String used to represent the basis
69
+ - ``Poly.maxpower`` -- Maximum value ``n`` such that ``p**n`` is allowed
70
+ - ``Poly.nickname`` -- String used in printing
71
+
72
+ Creation
73
+ --------
74
+
75
+ Methods for creating polynomial instances.
76
+
77
+ - ``Poly.basis(degree)`` -- Basis polynomial of given degree
78
+ - ``Poly.identity()`` -- ``p`` where ``p(x) = x`` for all ``x``
79
+ - ``Poly.fit(x, y, deg)`` -- ``p`` of degree ``deg`` with coefficients
80
+ determined by the least-squares fit to the data ``x``, ``y``
81
+ - ``Poly.fromroots(roots)`` -- ``p`` with specified roots
82
+ - ``p.copy()`` -- Create a copy of ``p``
83
+
84
+ Conversion
85
+ ----------
86
+
87
+ Methods for converting a polynomial instance of one kind to another.
88
+
89
+ - ``p.cast(Poly)`` -- Convert ``p`` to instance of kind ``Poly``
90
+ - ``p.convert(Poly)`` -- Convert ``p`` to instance of kind ``Poly`` or map
91
+ between ``domain`` and ``window``
92
+
93
+ Calculus
94
+ --------
95
+ - ``p.deriv()`` -- Take the derivative of ``p``
96
+ - ``p.integ()`` -- Integrate ``p``
97
+
98
+ Validation
99
+ ----------
100
+ - ``Poly.has_samecoef(p1, p2)`` -- Check if coefficients match
101
+ - ``Poly.has_samedomain(p1, p2)`` -- Check if domains match
102
+ - ``Poly.has_sametype(p1, p2)`` -- Check if types match
103
+ - ``Poly.has_samewindow(p1, p2)`` -- Check if windows match
104
+
105
+ Misc
106
+ ----
107
+ - ``p.linspace()`` -- Return ``x, p(x)`` at equally-spaced points in ``domain``
108
+ - ``p.mapparms()`` -- Return the parameters for the linear mapping between
109
+ ``domain`` and ``window``.
110
+ - ``p.roots()`` -- Return the roots of `p`.
111
+ - ``p.trim()`` -- Remove trailing coefficients.
112
+ - ``p.cutdeg(degree)`` -- Truncate p to given degree
113
+ - ``p.truncate(size)`` -- Truncate p to given size
114
+
115
+ """
116
+ from .polynomial import Polynomial
117
+ from .chebyshev import Chebyshev
118
+ from .legendre import Legendre
119
+ from .hermite import Hermite
120
+ from .hermite_e import HermiteE
121
+ from .laguerre import Laguerre
122
+
123
+ __all__ = [
124
+ "set_default_printstyle",
125
+ "polynomial", "Polynomial",
126
+ "chebyshev", "Chebyshev",
127
+ "legendre", "Legendre",
128
+ "hermite", "Hermite",
129
+ "hermite_e", "HermiteE",
130
+ "laguerre", "Laguerre",
131
+ ]
132
+
133
+
134
+ def set_default_printstyle(style):
135
+ """
136
+ Set the default format for the string representation of polynomials.
137
+
138
+ Values for ``style`` must be valid inputs to ``__format__``, i.e. 'ascii'
139
+ or 'unicode'.
140
+
141
+ Parameters
142
+ ----------
143
+ style : str
144
+ Format string for default printing style. Must be either 'ascii' or
145
+ 'unicode'.
146
+
147
+ Notes
148
+ -----
149
+ The default format depends on the platform: 'unicode' is used on
150
+ Unix-based systems and 'ascii' on Windows. This determination is based on
151
+ default font support for the unicode superscript and subscript ranges.
152
+
153
+ Examples
154
+ --------
155
+ >>> p = np.polynomial.Polynomial([1, 2, 3])
156
+ >>> c = np.polynomial.Chebyshev([1, 2, 3])
157
+ >>> np.polynomial.set_default_printstyle('unicode')
158
+ >>> print(p)
159
+ 1.0 + 2.0·x + 3.0·x²
160
+ >>> print(c)
161
+ 1.0 + 2.0·T₁(x) + 3.0·T₂(x)
162
+ >>> np.polynomial.set_default_printstyle('ascii')
163
+ >>> print(p)
164
+ 1.0 + 2.0 x + 3.0 x**2
165
+ >>> print(c)
166
+ 1.0 + 2.0 T_1(x) + 3.0 T_2(x)
167
+ >>> # Formatting supersedes all class/package-level defaults
168
+ >>> print(f"{p:unicode}")
169
+ 1.0 + 2.0·x + 3.0·x²
170
+ """
171
+ if style not in ('unicode', 'ascii'):
172
+ raise ValueError(
173
+ f"Unsupported format string '{style}'. Valid options are 'ascii' "
174
+ f"and 'unicode'"
175
+ )
176
+ _use_unicode = True
177
+ if style == 'ascii':
178
+ _use_unicode = False
179
+ from ._polybase import ABCPolyBase
180
+ ABCPolyBase._use_unicode = _use_unicode
181
+
182
+
183
+ from numpy._pytesttester import PytestTester
184
+ test = PytestTester(__name__)
185
+ del PytestTester
lib/python3.12/site-packages/numpy/polynomial/__init__.pyi ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from numpy._pytesttester import PytestTester
2
+
3
+ from numpy.polynomial import (
4
+ chebyshev as chebyshev,
5
+ hermite as hermite,
6
+ hermite_e as hermite_e,
7
+ laguerre as laguerre,
8
+ legendre as legendre,
9
+ polynomial as polynomial,
10
+ )
11
+ from numpy.polynomial.chebyshev import Chebyshev as Chebyshev
12
+ from numpy.polynomial.hermite import Hermite as Hermite
13
+ from numpy.polynomial.hermite_e import HermiteE as HermiteE
14
+ from numpy.polynomial.laguerre import Laguerre as Laguerre
15
+ from numpy.polynomial.legendre import Legendre as Legendre
16
+ from numpy.polynomial.polynomial import Polynomial as Polynomial
17
+
18
+ __all__: list[str]
19
+ __path__: list[str]
20
+ test: PytestTester
21
+
22
+ def set_default_printstyle(style): ...
lib/python3.12/site-packages/numpy/polynomial/_polybase.py ADDED
@@ -0,0 +1,1206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Abstract base class for the various polynomial Classes.
3
+
4
+ The ABCPolyBase class provides the methods needed to implement the common API
5
+ for the various polynomial classes. It operates as a mixin, but uses the
6
+ abc module from the stdlib, hence it is only available for Python >= 2.6.
7
+
8
+ """
9
+ import os
10
+ import abc
11
+ import numbers
12
+
13
+ import numpy as np
14
+ from . import polyutils as pu
15
+
16
+ __all__ = ['ABCPolyBase']
17
+
18
+ class ABCPolyBase(abc.ABC):
19
+ """An abstract base class for immutable series classes.
20
+
21
+ ABCPolyBase provides the standard Python numerical methods
22
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' along with the
23
+ methods listed below.
24
+
25
+ .. versionadded:: 1.9.0
26
+
27
+ Parameters
28
+ ----------
29
+ coef : array_like
30
+ Series coefficients in order of increasing degree, i.e.,
31
+ ``(1, 2, 3)`` gives ``1*P_0(x) + 2*P_1(x) + 3*P_2(x)``, where
32
+ ``P_i`` is the basis polynomials of degree ``i``.
33
+ domain : (2,) array_like, optional
34
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
35
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
36
+ The default value is the derived class domain.
37
+ window : (2,) array_like, optional
38
+ Window, see domain for its use. The default value is the
39
+ derived class window.
40
+ symbol : str, optional
41
+ Symbol used to represent the independent variable in string
42
+ representations of the polynomial expression, e.g. for printing.
43
+ The symbol must be a valid Python identifier. Default value is 'x'.
44
+
45
+ .. versionadded:: 1.24
46
+
47
+ Attributes
48
+ ----------
49
+ coef : (N,) ndarray
50
+ Series coefficients in order of increasing degree.
51
+ domain : (2,) ndarray
52
+ Domain that is mapped to window.
53
+ window : (2,) ndarray
54
+ Window that domain is mapped to.
55
+ symbol : str
56
+ Symbol representing the independent variable.
57
+
58
+ Class Attributes
59
+ ----------------
60
+ maxpower : int
61
+ Maximum power allowed, i.e., the largest number ``n`` such that
62
+ ``p(x)**n`` is allowed. This is to limit runaway polynomial size.
63
+ domain : (2,) ndarray
64
+ Default domain of the class.
65
+ window : (2,) ndarray
66
+ Default window of the class.
67
+
68
+ """
69
+
70
+ # Not hashable
71
+ __hash__ = None
72
+
73
+ # Opt out of numpy ufuncs and Python ops with ndarray subclasses.
74
+ __array_ufunc__ = None
75
+
76
+ # Limit runaway size. T_n^m has degree n*m
77
+ maxpower = 100
78
+
79
+ # Unicode character mappings for improved __str__
80
+ _superscript_mapping = str.maketrans({
81
+ "0": "⁰",
82
+ "1": "¹",
83
+ "2": "²",
84
+ "3": "³",
85
+ "4": "⁴",
86
+ "5": "⁵",
87
+ "6": "⁶",
88
+ "7": "⁷",
89
+ "8": "⁸",
90
+ "9": "⁹"
91
+ })
92
+ _subscript_mapping = str.maketrans({
93
+ "0": "₀",
94
+ "1": "₁",
95
+ "2": "₂",
96
+ "3": "₃",
97
+ "4": "₄",
98
+ "5": "₅",
99
+ "6": "₆",
100
+ "7": "₇",
101
+ "8": "₈",
102
+ "9": "₉"
103
+ })
104
+ # Some fonts don't support full unicode character ranges necessary for
105
+ # the full set of superscripts and subscripts, including common/default
106
+ # fonts in Windows shells/terminals. Therefore, default to ascii-only
107
+ # printing on windows.
108
+ _use_unicode = not os.name == 'nt'
109
+
110
+ @property
111
+ def symbol(self):
112
+ return self._symbol
113
+
114
+ @property
115
+ @abc.abstractmethod
116
+ def domain(self):
117
+ pass
118
+
119
+ @property
120
+ @abc.abstractmethod
121
+ def window(self):
122
+ pass
123
+
124
+ @property
125
+ @abc.abstractmethod
126
+ def basis_name(self):
127
+ pass
128
+
129
+ @staticmethod
130
+ @abc.abstractmethod
131
+ def _add(c1, c2):
132
+ pass
133
+
134
+ @staticmethod
135
+ @abc.abstractmethod
136
+ def _sub(c1, c2):
137
+ pass
138
+
139
+ @staticmethod
140
+ @abc.abstractmethod
141
+ def _mul(c1, c2):
142
+ pass
143
+
144
+ @staticmethod
145
+ @abc.abstractmethod
146
+ def _div(c1, c2):
147
+ pass
148
+
149
+ @staticmethod
150
+ @abc.abstractmethod
151
+ def _pow(c, pow, maxpower=None):
152
+ pass
153
+
154
+ @staticmethod
155
+ @abc.abstractmethod
156
+ def _val(x, c):
157
+ pass
158
+
159
+ @staticmethod
160
+ @abc.abstractmethod
161
+ def _int(c, m, k, lbnd, scl):
162
+ pass
163
+
164
+ @staticmethod
165
+ @abc.abstractmethod
166
+ def _der(c, m, scl):
167
+ pass
168
+
169
+ @staticmethod
170
+ @abc.abstractmethod
171
+ def _fit(x, y, deg, rcond, full):
172
+ pass
173
+
174
+ @staticmethod
175
+ @abc.abstractmethod
176
+ def _line(off, scl):
177
+ pass
178
+
179
+ @staticmethod
180
+ @abc.abstractmethod
181
+ def _roots(c):
182
+ pass
183
+
184
+ @staticmethod
185
+ @abc.abstractmethod
186
+ def _fromroots(r):
187
+ pass
188
+
189
+ def has_samecoef(self, other):
190
+ """Check if coefficients match.
191
+
192
+ .. versionadded:: 1.6.0
193
+
194
+ Parameters
195
+ ----------
196
+ other : class instance
197
+ The other class must have the ``coef`` attribute.
198
+
199
+ Returns
200
+ -------
201
+ bool : boolean
202
+ True if the coefficients are the same, False otherwise.
203
+
204
+ """
205
+ if len(self.coef) != len(other.coef):
206
+ return False
207
+ elif not np.all(self.coef == other.coef):
208
+ return False
209
+ else:
210
+ return True
211
+
212
+ def has_samedomain(self, other):
213
+ """Check if domains match.
214
+
215
+ .. versionadded:: 1.6.0
216
+
217
+ Parameters
218
+ ----------
219
+ other : class instance
220
+ The other class must have the ``domain`` attribute.
221
+
222
+ Returns
223
+ -------
224
+ bool : boolean
225
+ True if the domains are the same, False otherwise.
226
+
227
+ """
228
+ return np.all(self.domain == other.domain)
229
+
230
+ def has_samewindow(self, other):
231
+ """Check if windows match.
232
+
233
+ .. versionadded:: 1.6.0
234
+
235
+ Parameters
236
+ ----------
237
+ other : class instance
238
+ The other class must have the ``window`` attribute.
239
+
240
+ Returns
241
+ -------
242
+ bool : boolean
243
+ True if the windows are the same, False otherwise.
244
+
245
+ """
246
+ return np.all(self.window == other.window)
247
+
248
+ def has_sametype(self, other):
249
+ """Check if types match.
250
+
251
+ .. versionadded:: 1.7.0
252
+
253
+ Parameters
254
+ ----------
255
+ other : object
256
+ Class instance.
257
+
258
+ Returns
259
+ -------
260
+ bool : boolean
261
+ True if other is same class as self
262
+
263
+ """
264
+ return isinstance(other, self.__class__)
265
+
266
+ def _get_coefficients(self, other):
267
+ """Interpret other as polynomial coefficients.
268
+
269
+ The `other` argument is checked to see if it is of the same
270
+ class as self with identical domain and window. If so,
271
+ return its coefficients, otherwise return `other`.
272
+
273
+ .. versionadded:: 1.9.0
274
+
275
+ Parameters
276
+ ----------
277
+ other : anything
278
+ Object to be checked.
279
+
280
+ Returns
281
+ -------
282
+ coef
283
+ The coefficients of`other` if it is a compatible instance,
284
+ of ABCPolyBase, otherwise `other`.
285
+
286
+ Raises
287
+ ------
288
+ TypeError
289
+ When `other` is an incompatible instance of ABCPolyBase.
290
+
291
+ """
292
+ if isinstance(other, ABCPolyBase):
293
+ if not isinstance(other, self.__class__):
294
+ raise TypeError("Polynomial types differ")
295
+ elif not np.all(self.domain == other.domain):
296
+ raise TypeError("Domains differ")
297
+ elif not np.all(self.window == other.window):
298
+ raise TypeError("Windows differ")
299
+ elif self.symbol != other.symbol:
300
+ raise ValueError("Polynomial symbols differ")
301
+ return other.coef
302
+ return other
303
+
304
+ def __init__(self, coef, domain=None, window=None, symbol='x'):
305
+ [coef] = pu.as_series([coef], trim=False)
306
+ self.coef = coef
307
+
308
+ if domain is not None:
309
+ [domain] = pu.as_series([domain], trim=False)
310
+ if len(domain) != 2:
311
+ raise ValueError("Domain has wrong number of elements.")
312
+ self.domain = domain
313
+
314
+ if window is not None:
315
+ [window] = pu.as_series([window], trim=False)
316
+ if len(window) != 2:
317
+ raise ValueError("Window has wrong number of elements.")
318
+ self.window = window
319
+
320
+ # Validation for symbol
321
+ try:
322
+ if not symbol.isidentifier():
323
+ raise ValueError(
324
+ "Symbol string must be a valid Python identifier"
325
+ )
326
+ # If a user passes in something other than a string, the above
327
+ # results in an AttributeError. Catch this and raise a more
328
+ # informative exception
329
+ except AttributeError:
330
+ raise TypeError("Symbol must be a non-empty string")
331
+
332
+ self._symbol = symbol
333
+
334
+ def __repr__(self):
335
+ coef = repr(self.coef)[6:-1]
336
+ domain = repr(self.domain)[6:-1]
337
+ window = repr(self.window)[6:-1]
338
+ name = self.__class__.__name__
339
+ return (f"{name}({coef}, domain={domain}, window={window}, "
340
+ f"symbol='{self.symbol}')")
341
+
342
+ def __format__(self, fmt_str):
343
+ if fmt_str == '':
344
+ return self.__str__()
345
+ if fmt_str not in ('ascii', 'unicode'):
346
+ raise ValueError(
347
+ f"Unsupported format string '{fmt_str}' passed to "
348
+ f"{self.__class__}.__format__. Valid options are "
349
+ f"'ascii' and 'unicode'"
350
+ )
351
+ if fmt_str == 'ascii':
352
+ return self._generate_string(self._str_term_ascii)
353
+ return self._generate_string(self._str_term_unicode)
354
+
355
+ def __str__(self):
356
+ if self._use_unicode:
357
+ return self._generate_string(self._str_term_unicode)
358
+ return self._generate_string(self._str_term_ascii)
359
+
360
+ def _generate_string(self, term_method):
361
+ """
362
+ Generate the full string representation of the polynomial, using
363
+ ``term_method`` to generate each polynomial term.
364
+ """
365
+ # Get configuration for line breaks
366
+ linewidth = np.get_printoptions().get('linewidth', 75)
367
+ if linewidth < 1:
368
+ linewidth = 1
369
+ out = pu.format_float(self.coef[0])
370
+ for i, coef in enumerate(self.coef[1:]):
371
+ out += " "
372
+ power = str(i + 1)
373
+ # Polynomial coefficient
374
+ # The coefficient array can be an object array with elements that
375
+ # will raise a TypeError with >= 0 (e.g. strings or Python
376
+ # complex). In this case, represent the coefficient as-is.
377
+ try:
378
+ if coef >= 0:
379
+ next_term = f"+ " + pu.format_float(coef, parens=True)
380
+ else:
381
+ next_term = f"- " + pu.format_float(-coef, parens=True)
382
+ except TypeError:
383
+ next_term = f"+ {coef}"
384
+ # Polynomial term
385
+ next_term += term_method(power, self.symbol)
386
+ # Length of the current line with next term added
387
+ line_len = len(out.split('\n')[-1]) + len(next_term)
388
+ # If not the last term in the polynomial, it will be two
389
+ # characters longer due to the +/- with the next term
390
+ if i < len(self.coef[1:]) - 1:
391
+ line_len += 2
392
+ # Handle linebreaking
393
+ if line_len >= linewidth:
394
+ next_term = next_term.replace(" ", "\n", 1)
395
+ out += next_term
396
+ return out
397
+
398
+ @classmethod
399
+ def _str_term_unicode(cls, i, arg_str):
400
+ """
401
+ String representation of single polynomial term using unicode
402
+ characters for superscripts and subscripts.
403
+ """
404
+ if cls.basis_name is None:
405
+ raise NotImplementedError(
406
+ "Subclasses must define either a basis_name, or override "
407
+ "_str_term_unicode(cls, i, arg_str)"
408
+ )
409
+ return (f"·{cls.basis_name}{i.translate(cls._subscript_mapping)}"
410
+ f"({arg_str})")
411
+
412
+ @classmethod
413
+ def _str_term_ascii(cls, i, arg_str):
414
+ """
415
+ String representation of a single polynomial term using ** and _ to
416
+ represent superscripts and subscripts, respectively.
417
+ """
418
+ if cls.basis_name is None:
419
+ raise NotImplementedError(
420
+ "Subclasses must define either a basis_name, or override "
421
+ "_str_term_ascii(cls, i, arg_str)"
422
+ )
423
+ return f" {cls.basis_name}_{i}({arg_str})"
424
+
425
+ @classmethod
426
+ def _repr_latex_term(cls, i, arg_str, needs_parens):
427
+ if cls.basis_name is None:
428
+ raise NotImplementedError(
429
+ "Subclasses must define either a basis name, or override "
430
+ "_repr_latex_term(i, arg_str, needs_parens)")
431
+ # since we always add parens, we don't care if the expression needs them
432
+ return f"{{{cls.basis_name}}}_{{{i}}}({arg_str})"
433
+
434
+ @staticmethod
435
+ def _repr_latex_scalar(x, parens=False):
436
+ # TODO: we're stuck with disabling math formatting until we handle
437
+ # exponents in this function
438
+ return r'\text{{{}}}'.format(pu.format_float(x, parens=parens))
439
+
440
+ def _repr_latex_(self):
441
+ # get the scaled argument string to the basis functions
442
+ off, scale = self.mapparms()
443
+ if off == 0 and scale == 1:
444
+ term = self.symbol
445
+ needs_parens = False
446
+ elif scale == 1:
447
+ term = f"{self._repr_latex_scalar(off)} + {self.symbol}"
448
+ needs_parens = True
449
+ elif off == 0:
450
+ term = f"{self._repr_latex_scalar(scale)}{self.symbol}"
451
+ needs_parens = True
452
+ else:
453
+ term = (
454
+ f"{self._repr_latex_scalar(off)} + "
455
+ f"{self._repr_latex_scalar(scale)}{self.symbol}"
456
+ )
457
+ needs_parens = True
458
+
459
+ mute = r"\color{{LightGray}}{{{}}}".format
460
+
461
+ parts = []
462
+ for i, c in enumerate(self.coef):
463
+ # prevent duplication of + and - signs
464
+ if i == 0:
465
+ coef_str = f"{self._repr_latex_scalar(c)}"
466
+ elif not isinstance(c, numbers.Real):
467
+ coef_str = f" + ({self._repr_latex_scalar(c)})"
468
+ elif not np.signbit(c):
469
+ coef_str = f" + {self._repr_latex_scalar(c, parens=True)}"
470
+ else:
471
+ coef_str = f" - {self._repr_latex_scalar(-c, parens=True)}"
472
+
473
+ # produce the string for the term
474
+ term_str = self._repr_latex_term(i, term, needs_parens)
475
+ if term_str == '1':
476
+ part = coef_str
477
+ else:
478
+ part = rf"{coef_str}\,{term_str}"
479
+
480
+ if c == 0:
481
+ part = mute(part)
482
+
483
+ parts.append(part)
484
+
485
+ if parts:
486
+ body = ''.join(parts)
487
+ else:
488
+ # in case somehow there are no coefficients at all
489
+ body = '0'
490
+
491
+ return rf"${self.symbol} \mapsto {body}$"
492
+
493
+
494
+
495
+ # Pickle and copy
496
+
497
+ def __getstate__(self):
498
+ ret = self.__dict__.copy()
499
+ ret['coef'] = self.coef.copy()
500
+ ret['domain'] = self.domain.copy()
501
+ ret['window'] = self.window.copy()
502
+ ret['symbol'] = self.symbol
503
+ return ret
504
+
505
+ def __setstate__(self, dict):
506
+ self.__dict__ = dict
507
+
508
+ # Call
509
+
510
+ def __call__(self, arg):
511
+ off, scl = pu.mapparms(self.domain, self.window)
512
+ arg = off + scl*arg
513
+ return self._val(arg, self.coef)
514
+
515
+ def __iter__(self):
516
+ return iter(self.coef)
517
+
518
+ def __len__(self):
519
+ return len(self.coef)
520
+
521
+ # Numeric properties.
522
+
523
+ def __neg__(self):
524
+ return self.__class__(
525
+ -self.coef, self.domain, self.window, self.symbol
526
+ )
527
+
528
+ def __pos__(self):
529
+ return self
530
+
531
+ def __add__(self, other):
532
+ othercoef = self._get_coefficients(other)
533
+ try:
534
+ coef = self._add(self.coef, othercoef)
535
+ except Exception:
536
+ return NotImplemented
537
+ return self.__class__(coef, self.domain, self.window, self.symbol)
538
+
539
+ def __sub__(self, other):
540
+ othercoef = self._get_coefficients(other)
541
+ try:
542
+ coef = self._sub(self.coef, othercoef)
543
+ except Exception:
544
+ return NotImplemented
545
+ return self.__class__(coef, self.domain, self.window, self.symbol)
546
+
547
+ def __mul__(self, other):
548
+ othercoef = self._get_coefficients(other)
549
+ try:
550
+ coef = self._mul(self.coef, othercoef)
551
+ except Exception:
552
+ return NotImplemented
553
+ return self.__class__(coef, self.domain, self.window, self.symbol)
554
+
555
+ def __truediv__(self, other):
556
+ # there is no true divide if the rhs is not a Number, although it
557
+ # could return the first n elements of an infinite series.
558
+ # It is hard to see where n would come from, though.
559
+ if not isinstance(other, numbers.Number) or isinstance(other, bool):
560
+ raise TypeError(
561
+ f"unsupported types for true division: "
562
+ f"'{type(self)}', '{type(other)}'"
563
+ )
564
+ return self.__floordiv__(other)
565
+
566
+ def __floordiv__(self, other):
567
+ res = self.__divmod__(other)
568
+ if res is NotImplemented:
569
+ return res
570
+ return res[0]
571
+
572
+ def __mod__(self, other):
573
+ res = self.__divmod__(other)
574
+ if res is NotImplemented:
575
+ return res
576
+ return res[1]
577
+
578
+ def __divmod__(self, other):
579
+ othercoef = self._get_coefficients(other)
580
+ try:
581
+ quo, rem = self._div(self.coef, othercoef)
582
+ except ZeroDivisionError:
583
+ raise
584
+ except Exception:
585
+ return NotImplemented
586
+ quo = self.__class__(quo, self.domain, self.window, self.symbol)
587
+ rem = self.__class__(rem, self.domain, self.window, self.symbol)
588
+ return quo, rem
589
+
590
+ def __pow__(self, other):
591
+ coef = self._pow(self.coef, other, maxpower=self.maxpower)
592
+ res = self.__class__(coef, self.domain, self.window, self.symbol)
593
+ return res
594
+
595
+ def __radd__(self, other):
596
+ try:
597
+ coef = self._add(other, self.coef)
598
+ except Exception:
599
+ return NotImplemented
600
+ return self.__class__(coef, self.domain, self.window, self.symbol)
601
+
602
+ def __rsub__(self, other):
603
+ try:
604
+ coef = self._sub(other, self.coef)
605
+ except Exception:
606
+ return NotImplemented
607
+ return self.__class__(coef, self.domain, self.window, self.symbol)
608
+
609
+ def __rmul__(self, other):
610
+ try:
611
+ coef = self._mul(other, self.coef)
612
+ except Exception:
613
+ return NotImplemented
614
+ return self.__class__(coef, self.domain, self.window, self.symbol)
615
+
616
+ def __rdiv__(self, other):
617
+ # set to __floordiv__ /.
618
+ return self.__rfloordiv__(other)
619
+
620
+ def __rtruediv__(self, other):
621
+ # An instance of ABCPolyBase is not considered a
622
+ # Number.
623
+ return NotImplemented
624
+
625
+ def __rfloordiv__(self, other):
626
+ res = self.__rdivmod__(other)
627
+ if res is NotImplemented:
628
+ return res
629
+ return res[0]
630
+
631
+ def __rmod__(self, other):
632
+ res = self.__rdivmod__(other)
633
+ if res is NotImplemented:
634
+ return res
635
+ return res[1]
636
+
637
+ def __rdivmod__(self, other):
638
+ try:
639
+ quo, rem = self._div(other, self.coef)
640
+ except ZeroDivisionError:
641
+ raise
642
+ except Exception:
643
+ return NotImplemented
644
+ quo = self.__class__(quo, self.domain, self.window, self.symbol)
645
+ rem = self.__class__(rem, self.domain, self.window, self.symbol)
646
+ return quo, rem
647
+
648
+ def __eq__(self, other):
649
+ res = (isinstance(other, self.__class__) and
650
+ np.all(self.domain == other.domain) and
651
+ np.all(self.window == other.window) and
652
+ (self.coef.shape == other.coef.shape) and
653
+ np.all(self.coef == other.coef) and
654
+ (self.symbol == other.symbol))
655
+ return res
656
+
657
+ def __ne__(self, other):
658
+ return not self.__eq__(other)
659
+
660
+ #
661
+ # Extra methods.
662
+ #
663
+
664
+ def copy(self):
665
+ """Return a copy.
666
+
667
+ Returns
668
+ -------
669
+ new_series : series
670
+ Copy of self.
671
+
672
+ """
673
+ return self.__class__(self.coef, self.domain, self.window, self.symbol)
674
+
675
+ def degree(self):
676
+ """The degree of the series.
677
+
678
+ .. versionadded:: 1.5.0
679
+
680
+ Returns
681
+ -------
682
+ degree : int
683
+ Degree of the series, one less than the number of coefficients.
684
+
685
+ Examples
686
+ --------
687
+
688
+ Create a polynomial object for ``1 + 7*x + 4*x**2``:
689
+
690
+ >>> poly = np.polynomial.Polynomial([1, 7, 4])
691
+ >>> print(poly)
692
+ 1.0 + 7.0·x + 4.0·x²
693
+ >>> poly.degree()
694
+ 2
695
+
696
+ Note that this method does not check for non-zero coefficients.
697
+ You must trim the polynomial to remove any trailing zeroes:
698
+
699
+ >>> poly = np.polynomial.Polynomial([1, 7, 0])
700
+ >>> print(poly)
701
+ 1.0 + 7.0·x + 0.0·x²
702
+ >>> poly.degree()
703
+ 2
704
+ >>> poly.trim().degree()
705
+ 1
706
+
707
+ """
708
+ return len(self) - 1
709
+
710
+ def cutdeg(self, deg):
711
+ """Truncate series to the given degree.
712
+
713
+ Reduce the degree of the series to `deg` by discarding the
714
+ high order terms. If `deg` is greater than the current degree a
715
+ copy of the current series is returned. This can be useful in least
716
+ squares where the coefficients of the high degree terms may be very
717
+ small.
718
+
719
+ .. versionadded:: 1.5.0
720
+
721
+ Parameters
722
+ ----------
723
+ deg : non-negative int
724
+ The series is reduced to degree `deg` by discarding the high
725
+ order terms. The value of `deg` must be a non-negative integer.
726
+
727
+ Returns
728
+ -------
729
+ new_series : series
730
+ New instance of series with reduced degree.
731
+
732
+ """
733
+ return self.truncate(deg + 1)
734
+
735
+ def trim(self, tol=0):
736
+ """Remove trailing coefficients
737
+
738
+ Remove trailing coefficients until a coefficient is reached whose
739
+ absolute value greater than `tol` or the beginning of the series is
740
+ reached. If all the coefficients would be removed the series is set
741
+ to ``[0]``. A new series instance is returned with the new
742
+ coefficients. The current instance remains unchanged.
743
+
744
+ Parameters
745
+ ----------
746
+ tol : non-negative number.
747
+ All trailing coefficients less than `tol` will be removed.
748
+
749
+ Returns
750
+ -------
751
+ new_series : series
752
+ New instance of series with trimmed coefficients.
753
+
754
+ """
755
+ coef = pu.trimcoef(self.coef, tol)
756
+ return self.__class__(coef, self.domain, self.window, self.symbol)
757
+
758
+ def truncate(self, size):
759
+ """Truncate series to length `size`.
760
+
761
+ Reduce the series to length `size` by discarding the high
762
+ degree terms. The value of `size` must be a positive integer. This
763
+ can be useful in least squares where the coefficients of the
764
+ high degree terms may be very small.
765
+
766
+ Parameters
767
+ ----------
768
+ size : positive int
769
+ The series is reduced to length `size` by discarding the high
770
+ degree terms. The value of `size` must be a positive integer.
771
+
772
+ Returns
773
+ -------
774
+ new_series : series
775
+ New instance of series with truncated coefficients.
776
+
777
+ """
778
+ isize = int(size)
779
+ if isize != size or isize < 1:
780
+ raise ValueError("size must be a positive integer")
781
+ if isize >= len(self.coef):
782
+ coef = self.coef
783
+ else:
784
+ coef = self.coef[:isize]
785
+ return self.__class__(coef, self.domain, self.window, self.symbol)
786
+
787
+ def convert(self, domain=None, kind=None, window=None):
788
+ """Convert series to a different kind and/or domain and/or window.
789
+
790
+ Parameters
791
+ ----------
792
+ domain : array_like, optional
793
+ The domain of the converted series. If the value is None,
794
+ the default domain of `kind` is used.
795
+ kind : class, optional
796
+ The polynomial series type class to which the current instance
797
+ should be converted. If kind is None, then the class of the
798
+ current instance is used.
799
+ window : array_like, optional
800
+ The window of the converted series. If the value is None,
801
+ the default window of `kind` is used.
802
+
803
+ Returns
804
+ -------
805
+ new_series : series
806
+ The returned class can be of different type than the current
807
+ instance and/or have a different domain and/or different
808
+ window.
809
+
810
+ Notes
811
+ -----
812
+ Conversion between domains and class types can result in
813
+ numerically ill defined series.
814
+
815
+ """
816
+ if kind is None:
817
+ kind = self.__class__
818
+ if domain is None:
819
+ domain = kind.domain
820
+ if window is None:
821
+ window = kind.window
822
+ return self(kind.identity(domain, window=window, symbol=self.symbol))
823
+
824
+ def mapparms(self):
825
+ """Return the mapping parameters.
826
+
827
+ The returned values define a linear map ``off + scl*x`` that is
828
+ applied to the input arguments before the series is evaluated. The
829
+ map depends on the ``domain`` and ``window``; if the current
830
+ ``domain`` is equal to the ``window`` the resulting map is the
831
+ identity. If the coefficients of the series instance are to be
832
+ used by themselves outside this class, then the linear function
833
+ must be substituted for the ``x`` in the standard representation of
834
+ the base polynomials.
835
+
836
+ Returns
837
+ -------
838
+ off, scl : float or complex
839
+ The mapping function is defined by ``off + scl*x``.
840
+
841
+ Notes
842
+ -----
843
+ If the current domain is the interval ``[l1, r1]`` and the window
844
+ is ``[l2, r2]``, then the linear mapping function ``L`` is
845
+ defined by the equations::
846
+
847
+ L(l1) = l2
848
+ L(r1) = r2
849
+
850
+ """
851
+ return pu.mapparms(self.domain, self.window)
852
+
853
+ def integ(self, m=1, k=[], lbnd=None):
854
+ """Integrate.
855
+
856
+ Return a series instance that is the definite integral of the
857
+ current series.
858
+
859
+ Parameters
860
+ ----------
861
+ m : non-negative int
862
+ The number of integrations to perform.
863
+ k : array_like
864
+ Integration constants. The first constant is applied to the
865
+ first integration, the second to the second, and so on. The
866
+ list of values must less than or equal to `m` in length and any
867
+ missing values are set to zero.
868
+ lbnd : Scalar
869
+ The lower bound of the definite integral.
870
+
871
+ Returns
872
+ -------
873
+ new_series : series
874
+ A new series representing the integral. The domain is the same
875
+ as the domain of the integrated series.
876
+
877
+ """
878
+ off, scl = self.mapparms()
879
+ if lbnd is None:
880
+ lbnd = 0
881
+ else:
882
+ lbnd = off + scl*lbnd
883
+ coef = self._int(self.coef, m, k, lbnd, 1./scl)
884
+ return self.__class__(coef, self.domain, self.window, self.symbol)
885
+
886
+ def deriv(self, m=1):
887
+ """Differentiate.
888
+
889
+ Return a series instance of that is the derivative of the current
890
+ series.
891
+
892
+ Parameters
893
+ ----------
894
+ m : non-negative int
895
+ Find the derivative of order `m`.
896
+
897
+ Returns
898
+ -------
899
+ new_series : series
900
+ A new series representing the derivative. The domain is the same
901
+ as the domain of the differentiated series.
902
+
903
+ """
904
+ off, scl = self.mapparms()
905
+ coef = self._der(self.coef, m, scl)
906
+ return self.__class__(coef, self.domain, self.window, self.symbol)
907
+
908
+ def roots(self):
909
+ """Return the roots of the series polynomial.
910
+
911
+ Compute the roots for the series. Note that the accuracy of the
912
+ roots decreases the further outside the `domain` they lie.
913
+
914
+ Returns
915
+ -------
916
+ roots : ndarray
917
+ Array containing the roots of the series.
918
+
919
+ """
920
+ roots = self._roots(self.coef)
921
+ return pu.mapdomain(roots, self.window, self.domain)
922
+
923
+ def linspace(self, n=100, domain=None):
924
+ """Return x, y values at equally spaced points in domain.
925
+
926
+ Returns the x, y values at `n` linearly spaced points across the
927
+ domain. Here y is the value of the polynomial at the points x. By
928
+ default the domain is the same as that of the series instance.
929
+ This method is intended mostly as a plotting aid.
930
+
931
+ .. versionadded:: 1.5.0
932
+
933
+ Parameters
934
+ ----------
935
+ n : int, optional
936
+ Number of point pairs to return. The default value is 100.
937
+ domain : {None, array_like}, optional
938
+ If not None, the specified domain is used instead of that of
939
+ the calling instance. It should be of the form ``[beg,end]``.
940
+ The default is None which case the class domain is used.
941
+
942
+ Returns
943
+ -------
944
+ x, y : ndarray
945
+ x is equal to linspace(self.domain[0], self.domain[1], n) and
946
+ y is the series evaluated at element of x.
947
+
948
+ """
949
+ if domain is None:
950
+ domain = self.domain
951
+ x = np.linspace(domain[0], domain[1], n)
952
+ y = self(x)
953
+ return x, y
954
+
955
+ @classmethod
956
+ def fit(cls, x, y, deg, domain=None, rcond=None, full=False, w=None,
957
+ window=None, symbol='x'):
958
+ """Least squares fit to data.
959
+
960
+ Return a series instance that is the least squares fit to the data
961
+ `y` sampled at `x`. The domain of the returned instance can be
962
+ specified and this will often result in a superior fit with less
963
+ chance of ill conditioning.
964
+
965
+ Parameters
966
+ ----------
967
+ x : array_like, shape (M,)
968
+ x-coordinates of the M sample points ``(x[i], y[i])``.
969
+ y : array_like, shape (M,)
970
+ y-coordinates of the M sample points ``(x[i], y[i])``.
971
+ deg : int or 1-D array_like
972
+ Degree(s) of the fitting polynomials. If `deg` is a single integer
973
+ all terms up to and including the `deg`'th term are included in the
974
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
975
+ degrees of the terms to include may be used instead.
976
+ domain : {None, [beg, end], []}, optional
977
+ Domain to use for the returned series. If ``None``,
978
+ then a minimal domain that covers the points `x` is chosen. If
979
+ ``[]`` the class domain is used. The default value was the
980
+ class domain in NumPy 1.4 and ``None`` in later versions.
981
+ The ``[]`` option was added in numpy 1.5.0.
982
+ rcond : float, optional
983
+ Relative condition number of the fit. Singular values smaller
984
+ than this relative to the largest singular value will be
985
+ ignored. The default value is len(x)*eps, where eps is the
986
+ relative precision of the float type, about 2e-16 in most
987
+ cases.
988
+ full : bool, optional
989
+ Switch determining nature of return value. When it is False
990
+ (the default) just the coefficients are returned, when True
991
+ diagnostic information from the singular value decomposition is
992
+ also returned.
993
+ w : array_like, shape (M,), optional
994
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
995
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
996
+ chosen so that the errors of the products ``w[i]*y[i]`` all have
997
+ the same variance. When using inverse-variance weighting, use
998
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
999
+
1000
+ .. versionadded:: 1.5.0
1001
+ window : {[beg, end]}, optional
1002
+ Window to use for the returned series. The default
1003
+ value is the default class domain
1004
+
1005
+ .. versionadded:: 1.6.0
1006
+ symbol : str, optional
1007
+ Symbol representing the independent variable. Default is 'x'.
1008
+
1009
+ Returns
1010
+ -------
1011
+ new_series : series
1012
+ A series that represents the least squares fit to the data and
1013
+ has the domain and window specified in the call. If the
1014
+ coefficients for the unscaled and unshifted basis polynomials are
1015
+ of interest, do ``new_series.convert().coef``.
1016
+
1017
+ [resid, rank, sv, rcond] : list
1018
+ These values are only returned if ``full == True``
1019
+
1020
+ - resid -- sum of squared residuals of the least squares fit
1021
+ - rank -- the numerical rank of the scaled Vandermonde matrix
1022
+ - sv -- singular values of the scaled Vandermonde matrix
1023
+ - rcond -- value of `rcond`.
1024
+
1025
+ For more details, see `linalg.lstsq`.
1026
+
1027
+ """
1028
+ if domain is None:
1029
+ domain = pu.getdomain(x)
1030
+ elif type(domain) is list and len(domain) == 0:
1031
+ domain = cls.domain
1032
+
1033
+ if window is None:
1034
+ window = cls.window
1035
+
1036
+ xnew = pu.mapdomain(x, domain, window)
1037
+ res = cls._fit(xnew, y, deg, w=w, rcond=rcond, full=full)
1038
+ if full:
1039
+ [coef, status] = res
1040
+ return (
1041
+ cls(coef, domain=domain, window=window, symbol=symbol), status
1042
+ )
1043
+ else:
1044
+ coef = res
1045
+ return cls(coef, domain=domain, window=window, symbol=symbol)
1046
+
1047
+ @classmethod
1048
+ def fromroots(cls, roots, domain=[], window=None, symbol='x'):
1049
+ """Return series instance that has the specified roots.
1050
+
1051
+ Returns a series representing the product
1052
+ ``(x - r[0])*(x - r[1])*...*(x - r[n-1])``, where ``r`` is a
1053
+ list of roots.
1054
+
1055
+ Parameters
1056
+ ----------
1057
+ roots : array_like
1058
+ List of roots.
1059
+ domain : {[], None, array_like}, optional
1060
+ Domain for the resulting series. If None the domain is the
1061
+ interval from the smallest root to the largest. If [] the
1062
+ domain is the class domain. The default is [].
1063
+ window : {None, array_like}, optional
1064
+ Window for the returned series. If None the class window is
1065
+ used. The default is None.
1066
+ symbol : str, optional
1067
+ Symbol representing the independent variable. Default is 'x'.
1068
+
1069
+ Returns
1070
+ -------
1071
+ new_series : series
1072
+ Series with the specified roots.
1073
+
1074
+ """
1075
+ [roots] = pu.as_series([roots], trim=False)
1076
+ if domain is None:
1077
+ domain = pu.getdomain(roots)
1078
+ elif type(domain) is list and len(domain) == 0:
1079
+ domain = cls.domain
1080
+
1081
+ if window is None:
1082
+ window = cls.window
1083
+
1084
+ deg = len(roots)
1085
+ off, scl = pu.mapparms(domain, window)
1086
+ rnew = off + scl*roots
1087
+ coef = cls._fromroots(rnew) / scl**deg
1088
+ return cls(coef, domain=domain, window=window, symbol=symbol)
1089
+
1090
+ @classmethod
1091
+ def identity(cls, domain=None, window=None, symbol='x'):
1092
+ """Identity function.
1093
+
1094
+ If ``p`` is the returned series, then ``p(x) == x`` for all
1095
+ values of x.
1096
+
1097
+ Parameters
1098
+ ----------
1099
+ domain : {None, array_like}, optional
1100
+ If given, the array must be of the form ``[beg, end]``, where
1101
+ ``beg`` and ``end`` are the endpoints of the domain. If None is
1102
+ given then the class domain is used. The default is None.
1103
+ window : {None, array_like}, optional
1104
+ If given, the resulting array must be if the form
1105
+ ``[beg, end]``, where ``beg`` and ``end`` are the endpoints of
1106
+ the window. If None is given then the class window is used. The
1107
+ default is None.
1108
+ symbol : str, optional
1109
+ Symbol representing the independent variable. Default is 'x'.
1110
+
1111
+ Returns
1112
+ -------
1113
+ new_series : series
1114
+ Series of representing the identity.
1115
+
1116
+ """
1117
+ if domain is None:
1118
+ domain = cls.domain
1119
+ if window is None:
1120
+ window = cls.window
1121
+ off, scl = pu.mapparms(window, domain)
1122
+ coef = cls._line(off, scl)
1123
+ return cls(coef, domain, window, symbol)
1124
+
1125
+ @classmethod
1126
+ def basis(cls, deg, domain=None, window=None, symbol='x'):
1127
+ """Series basis polynomial of degree `deg`.
1128
+
1129
+ Returns the series representing the basis polynomial of degree `deg`.
1130
+
1131
+ .. versionadded:: 1.7.0
1132
+
1133
+ Parameters
1134
+ ----------
1135
+ deg : int
1136
+ Degree of the basis polynomial for the series. Must be >= 0.
1137
+ domain : {None, array_like}, optional
1138
+ If given, the array must be of the form ``[beg, end]``, where
1139
+ ``beg`` and ``end`` are the endpoints of the domain. If None is
1140
+ given then the class domain is used. The default is None.
1141
+ window : {None, array_like}, optional
1142
+ If given, the resulting array must be if the form
1143
+ ``[beg, end]``, where ``beg`` and ``end`` are the endpoints of
1144
+ the window. If None is given then the class window is used. The
1145
+ default is None.
1146
+ symbol : str, optional
1147
+ Symbol representing the independent variable. Default is 'x'.
1148
+
1149
+ Returns
1150
+ -------
1151
+ new_series : series
1152
+ A series with the coefficient of the `deg` term set to one and
1153
+ all others zero.
1154
+
1155
+ """
1156
+ if domain is None:
1157
+ domain = cls.domain
1158
+ if window is None:
1159
+ window = cls.window
1160
+ ideg = int(deg)
1161
+
1162
+ if ideg != deg or ideg < 0:
1163
+ raise ValueError("deg must be non-negative integer")
1164
+ return cls([0]*ideg + [1], domain, window, symbol)
1165
+
1166
+ @classmethod
1167
+ def cast(cls, series, domain=None, window=None):
1168
+ """Convert series to series of this class.
1169
+
1170
+ The `series` is expected to be an instance of some polynomial
1171
+ series of one of the types supported by by the numpy.polynomial
1172
+ module, but could be some other class that supports the convert
1173
+ method.
1174
+
1175
+ .. versionadded:: 1.7.0
1176
+
1177
+ Parameters
1178
+ ----------
1179
+ series : series
1180
+ The series instance to be converted.
1181
+ domain : {None, array_like}, optional
1182
+ If given, the array must be of the form ``[beg, end]``, where
1183
+ ``beg`` and ``end`` are the endpoints of the domain. If None is
1184
+ given then the class domain is used. The default is None.
1185
+ window : {None, array_like}, optional
1186
+ If given, the resulting array must be if the form
1187
+ ``[beg, end]``, where ``beg`` and ``end`` are the endpoints of
1188
+ the window. If None is given then the class window is used. The
1189
+ default is None.
1190
+
1191
+ Returns
1192
+ -------
1193
+ new_series : series
1194
+ A series of the same kind as the calling class and equal to
1195
+ `series` when evaluated.
1196
+
1197
+ See Also
1198
+ --------
1199
+ convert : similar instance method
1200
+
1201
+ """
1202
+ if domain is None:
1203
+ domain = cls.domain
1204
+ if window is None:
1205
+ window = cls.window
1206
+ return series.convert(domain, cls, window)
lib/python3.12/site-packages/numpy/polynomial/_polybase.pyi ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import abc
2
+ from typing import Any, ClassVar
3
+
4
+ __all__: list[str]
5
+
6
+ class ABCPolyBase(abc.ABC):
7
+ __hash__: ClassVar[None] # type: ignore[assignment]
8
+ __array_ufunc__: ClassVar[None]
9
+ maxpower: ClassVar[int]
10
+ coef: Any
11
+ @property
12
+ def symbol(self) -> str: ...
13
+ @property
14
+ @abc.abstractmethod
15
+ def domain(self): ...
16
+ @property
17
+ @abc.abstractmethod
18
+ def window(self): ...
19
+ @property
20
+ @abc.abstractmethod
21
+ def basis_name(self): ...
22
+ def has_samecoef(self, other): ...
23
+ def has_samedomain(self, other): ...
24
+ def has_samewindow(self, other): ...
25
+ def has_sametype(self, other): ...
26
+ def __init__(self, coef, domain=..., window=..., symbol: str = ...) -> None: ...
27
+ def __format__(self, fmt_str): ...
28
+ def __call__(self, arg): ...
29
+ def __iter__(self): ...
30
+ def __len__(self): ...
31
+ def __neg__(self): ...
32
+ def __pos__(self): ...
33
+ def __add__(self, other): ...
34
+ def __sub__(self, other): ...
35
+ def __mul__(self, other): ...
36
+ def __truediv__(self, other): ...
37
+ def __floordiv__(self, other): ...
38
+ def __mod__(self, other): ...
39
+ def __divmod__(self, other): ...
40
+ def __pow__(self, other): ...
41
+ def __radd__(self, other): ...
42
+ def __rsub__(self, other): ...
43
+ def __rmul__(self, other): ...
44
+ def __rdiv__(self, other): ...
45
+ def __rtruediv__(self, other): ...
46
+ def __rfloordiv__(self, other): ...
47
+ def __rmod__(self, other): ...
48
+ def __rdivmod__(self, other): ...
49
+ def __eq__(self, other): ...
50
+ def __ne__(self, other): ...
51
+ def copy(self): ...
52
+ def degree(self): ...
53
+ def cutdeg(self, deg): ...
54
+ def trim(self, tol=...): ...
55
+ def truncate(self, size): ...
56
+ def convert(self, domain=..., kind=..., window=...): ...
57
+ def mapparms(self): ...
58
+ def integ(self, m=..., k = ..., lbnd=...): ...
59
+ def deriv(self, m=...): ...
60
+ def roots(self): ...
61
+ def linspace(self, n=..., domain=...): ...
62
+ @classmethod
63
+ def fit(cls, x, y, deg, domain=..., rcond=..., full=..., w=..., window=...): ...
64
+ @classmethod
65
+ def fromroots(cls, roots, domain = ..., window=...): ...
66
+ @classmethod
67
+ def identity(cls, domain=..., window=...): ...
68
+ @classmethod
69
+ def basis(cls, deg, domain=..., window=...): ...
70
+ @classmethod
71
+ def cast(cls, series, domain=..., window=...): ...
lib/python3.12/site-packages/numpy/polynomial/chebyshev.py ADDED
@@ -0,0 +1,2082 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ====================================================
3
+ Chebyshev Series (:mod:`numpy.polynomial.chebyshev`)
4
+ ====================================================
5
+
6
+ This module provides a number of objects (mostly functions) useful for
7
+ dealing with Chebyshev series, including a `Chebyshev` class that
8
+ encapsulates the usual arithmetic operations. (General information
9
+ on how this module represents and works with such polynomials is in the
10
+ docstring for its "parent" sub-package, `numpy.polynomial`).
11
+
12
+ Classes
13
+ -------
14
+
15
+ .. autosummary::
16
+ :toctree: generated/
17
+
18
+ Chebyshev
19
+
20
+
21
+ Constants
22
+ ---------
23
+
24
+ .. autosummary::
25
+ :toctree: generated/
26
+
27
+ chebdomain
28
+ chebzero
29
+ chebone
30
+ chebx
31
+
32
+ Arithmetic
33
+ ----------
34
+
35
+ .. autosummary::
36
+ :toctree: generated/
37
+
38
+ chebadd
39
+ chebsub
40
+ chebmulx
41
+ chebmul
42
+ chebdiv
43
+ chebpow
44
+ chebval
45
+ chebval2d
46
+ chebval3d
47
+ chebgrid2d
48
+ chebgrid3d
49
+
50
+ Calculus
51
+ --------
52
+
53
+ .. autosummary::
54
+ :toctree: generated/
55
+
56
+ chebder
57
+ chebint
58
+
59
+ Misc Functions
60
+ --------------
61
+
62
+ .. autosummary::
63
+ :toctree: generated/
64
+
65
+ chebfromroots
66
+ chebroots
67
+ chebvander
68
+ chebvander2d
69
+ chebvander3d
70
+ chebgauss
71
+ chebweight
72
+ chebcompanion
73
+ chebfit
74
+ chebpts1
75
+ chebpts2
76
+ chebtrim
77
+ chebline
78
+ cheb2poly
79
+ poly2cheb
80
+ chebinterpolate
81
+
82
+ See also
83
+ --------
84
+ `numpy.polynomial`
85
+
86
+ Notes
87
+ -----
88
+ The implementations of multiplication, division, integration, and
89
+ differentiation use the algebraic identities [1]_:
90
+
91
+ .. math::
92
+ T_n(x) = \\frac{z^n + z^{-n}}{2} \\\\
93
+ z\\frac{dx}{dz} = \\frac{z - z^{-1}}{2}.
94
+
95
+ where
96
+
97
+ .. math:: x = \\frac{z + z^{-1}}{2}.
98
+
99
+ These identities allow a Chebyshev series to be expressed as a finite,
100
+ symmetric Laurent series. In this module, this sort of Laurent series
101
+ is referred to as a "z-series."
102
+
103
+ References
104
+ ----------
105
+ .. [1] A. T. Benjamin, et al., "Combinatorial Trigonometry with Chebyshev
106
+ Polynomials," *Journal of Statistical Planning and Inference 14*, 2008
107
+ (https://web.archive.org/web/20080221202153/https://www.math.hmc.edu/~benjamin/papers/CombTrig.pdf, pg. 4)
108
+
109
+ """
110
+ import numpy as np
111
+ import numpy.linalg as la
112
+ from numpy.core.multiarray import normalize_axis_index
113
+
114
+ from . import polyutils as pu
115
+ from ._polybase import ABCPolyBase
116
+
117
+ __all__ = [
118
+ 'chebzero', 'chebone', 'chebx', 'chebdomain', 'chebline', 'chebadd',
119
+ 'chebsub', 'chebmulx', 'chebmul', 'chebdiv', 'chebpow', 'chebval',
120
+ 'chebder', 'chebint', 'cheb2poly', 'poly2cheb', 'chebfromroots',
121
+ 'chebvander', 'chebfit', 'chebtrim', 'chebroots', 'chebpts1',
122
+ 'chebpts2', 'Chebyshev', 'chebval2d', 'chebval3d', 'chebgrid2d',
123
+ 'chebgrid3d', 'chebvander2d', 'chebvander3d', 'chebcompanion',
124
+ 'chebgauss', 'chebweight', 'chebinterpolate']
125
+
126
+ chebtrim = pu.trimcoef
127
+
128
+ #
129
+ # A collection of functions for manipulating z-series. These are private
130
+ # functions and do minimal error checking.
131
+ #
132
+
133
+ def _cseries_to_zseries(c):
134
+ """Convert Chebyshev series to z-series.
135
+
136
+ Convert a Chebyshev series to the equivalent z-series. The result is
137
+ never an empty array. The dtype of the return is the same as that of
138
+ the input. No checks are run on the arguments as this routine is for
139
+ internal use.
140
+
141
+ Parameters
142
+ ----------
143
+ c : 1-D ndarray
144
+ Chebyshev coefficients, ordered from low to high
145
+
146
+ Returns
147
+ -------
148
+ zs : 1-D ndarray
149
+ Odd length symmetric z-series, ordered from low to high.
150
+
151
+ """
152
+ n = c.size
153
+ zs = np.zeros(2*n-1, dtype=c.dtype)
154
+ zs[n-1:] = c/2
155
+ return zs + zs[::-1]
156
+
157
+
158
+ def _zseries_to_cseries(zs):
159
+ """Convert z-series to a Chebyshev series.
160
+
161
+ Convert a z series to the equivalent Chebyshev series. The result is
162
+ never an empty array. The dtype of the return is the same as that of
163
+ the input. No checks are run on the arguments as this routine is for
164
+ internal use.
165
+
166
+ Parameters
167
+ ----------
168
+ zs : 1-D ndarray
169
+ Odd length symmetric z-series, ordered from low to high.
170
+
171
+ Returns
172
+ -------
173
+ c : 1-D ndarray
174
+ Chebyshev coefficients, ordered from low to high.
175
+
176
+ """
177
+ n = (zs.size + 1)//2
178
+ c = zs[n-1:].copy()
179
+ c[1:n] *= 2
180
+ return c
181
+
182
+
183
+ def _zseries_mul(z1, z2):
184
+ """Multiply two z-series.
185
+
186
+ Multiply two z-series to produce a z-series.
187
+
188
+ Parameters
189
+ ----------
190
+ z1, z2 : 1-D ndarray
191
+ The arrays must be 1-D but this is not checked.
192
+
193
+ Returns
194
+ -------
195
+ product : 1-D ndarray
196
+ The product z-series.
197
+
198
+ Notes
199
+ -----
200
+ This is simply convolution. If symmetric/anti-symmetric z-series are
201
+ denoted by S/A then the following rules apply:
202
+
203
+ S*S, A*A -> S
204
+ S*A, A*S -> A
205
+
206
+ """
207
+ return np.convolve(z1, z2)
208
+
209
+
210
+ def _zseries_div(z1, z2):
211
+ """Divide the first z-series by the second.
212
+
213
+ Divide `z1` by `z2` and return the quotient and remainder as z-series.
214
+ Warning: this implementation only applies when both z1 and z2 have the
215
+ same symmetry, which is sufficient for present purposes.
216
+
217
+ Parameters
218
+ ----------
219
+ z1, z2 : 1-D ndarray
220
+ The arrays must be 1-D and have the same symmetry, but this is not
221
+ checked.
222
+
223
+ Returns
224
+ -------
225
+
226
+ (quotient, remainder) : 1-D ndarrays
227
+ Quotient and remainder as z-series.
228
+
229
+ Notes
230
+ -----
231
+ This is not the same as polynomial division on account of the desired form
232
+ of the remainder. If symmetric/anti-symmetric z-series are denoted by S/A
233
+ then the following rules apply:
234
+
235
+ S/S -> S,S
236
+ A/A -> S,A
237
+
238
+ The restriction to types of the same symmetry could be fixed but seems like
239
+ unneeded generality. There is no natural form for the remainder in the case
240
+ where there is no symmetry.
241
+
242
+ """
243
+ z1 = z1.copy()
244
+ z2 = z2.copy()
245
+ lc1 = len(z1)
246
+ lc2 = len(z2)
247
+ if lc2 == 1:
248
+ z1 /= z2
249
+ return z1, z1[:1]*0
250
+ elif lc1 < lc2:
251
+ return z1[:1]*0, z1
252
+ else:
253
+ dlen = lc1 - lc2
254
+ scl = z2[0]
255
+ z2 /= scl
256
+ quo = np.empty(dlen + 1, dtype=z1.dtype)
257
+ i = 0
258
+ j = dlen
259
+ while i < j:
260
+ r = z1[i]
261
+ quo[i] = z1[i]
262
+ quo[dlen - i] = r
263
+ tmp = r*z2
264
+ z1[i:i+lc2] -= tmp
265
+ z1[j:j+lc2] -= tmp
266
+ i += 1
267
+ j -= 1
268
+ r = z1[i]
269
+ quo[i] = r
270
+ tmp = r*z2
271
+ z1[i:i+lc2] -= tmp
272
+ quo /= scl
273
+ rem = z1[i+1:i-1+lc2].copy()
274
+ return quo, rem
275
+
276
+
277
+ def _zseries_der(zs):
278
+ """Differentiate a z-series.
279
+
280
+ The derivative is with respect to x, not z. This is achieved using the
281
+ chain rule and the value of dx/dz given in the module notes.
282
+
283
+ Parameters
284
+ ----------
285
+ zs : z-series
286
+ The z-series to differentiate.
287
+
288
+ Returns
289
+ -------
290
+ derivative : z-series
291
+ The derivative
292
+
293
+ Notes
294
+ -----
295
+ The zseries for x (ns) has been multiplied by two in order to avoid
296
+ using floats that are incompatible with Decimal and likely other
297
+ specialized scalar types. This scaling has been compensated by
298
+ multiplying the value of zs by two also so that the two cancels in the
299
+ division.
300
+
301
+ """
302
+ n = len(zs)//2
303
+ ns = np.array([-1, 0, 1], dtype=zs.dtype)
304
+ zs *= np.arange(-n, n+1)*2
305
+ d, r = _zseries_div(zs, ns)
306
+ return d
307
+
308
+
309
+ def _zseries_int(zs):
310
+ """Integrate a z-series.
311
+
312
+ The integral is with respect to x, not z. This is achieved by a change
313
+ of variable using dx/dz given in the module notes.
314
+
315
+ Parameters
316
+ ----------
317
+ zs : z-series
318
+ The z-series to integrate
319
+
320
+ Returns
321
+ -------
322
+ integral : z-series
323
+ The indefinite integral
324
+
325
+ Notes
326
+ -----
327
+ The zseries for x (ns) has been multiplied by two in order to avoid
328
+ using floats that are incompatible with Decimal and likely other
329
+ specialized scalar types. This scaling has been compensated by
330
+ dividing the resulting zs by two.
331
+
332
+ """
333
+ n = 1 + len(zs)//2
334
+ ns = np.array([-1, 0, 1], dtype=zs.dtype)
335
+ zs = _zseries_mul(zs, ns)
336
+ div = np.arange(-n, n+1)*2
337
+ zs[:n] /= div[:n]
338
+ zs[n+1:] /= div[n+1:]
339
+ zs[n] = 0
340
+ return zs
341
+
342
+ #
343
+ # Chebyshev series functions
344
+ #
345
+
346
+
347
+ def poly2cheb(pol):
348
+ """
349
+ Convert a polynomial to a Chebyshev series.
350
+
351
+ Convert an array representing the coefficients of a polynomial (relative
352
+ to the "standard" basis) ordered from lowest degree to highest, to an
353
+ array of the coefficients of the equivalent Chebyshev series, ordered
354
+ from lowest to highest degree.
355
+
356
+ Parameters
357
+ ----------
358
+ pol : array_like
359
+ 1-D array containing the polynomial coefficients
360
+
361
+ Returns
362
+ -------
363
+ c : ndarray
364
+ 1-D array containing the coefficients of the equivalent Chebyshev
365
+ series.
366
+
367
+ See Also
368
+ --------
369
+ cheb2poly
370
+
371
+ Notes
372
+ -----
373
+ The easy way to do conversions between polynomial basis sets
374
+ is to use the convert method of a class instance.
375
+
376
+ Examples
377
+ --------
378
+ >>> from numpy import polynomial as P
379
+ >>> p = P.Polynomial(range(4))
380
+ >>> p
381
+ Polynomial([0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
382
+ >>> c = p.convert(kind=P.Chebyshev)
383
+ >>> c
384
+ Chebyshev([1. , 3.25, 1. , 0.75], domain=[-1., 1.], window=[-1., 1.])
385
+ >>> P.chebyshev.poly2cheb(range(4))
386
+ array([1. , 3.25, 1. , 0.75])
387
+
388
+ """
389
+ [pol] = pu.as_series([pol])
390
+ deg = len(pol) - 1
391
+ res = 0
392
+ for i in range(deg, -1, -1):
393
+ res = chebadd(chebmulx(res), pol[i])
394
+ return res
395
+
396
+
397
+ def cheb2poly(c):
398
+ """
399
+ Convert a Chebyshev series to a polynomial.
400
+
401
+ Convert an array representing the coefficients of a Chebyshev series,
402
+ ordered from lowest degree to highest, to an array of the coefficients
403
+ of the equivalent polynomial (relative to the "standard" basis) ordered
404
+ from lowest to highest degree.
405
+
406
+ Parameters
407
+ ----------
408
+ c : array_like
409
+ 1-D array containing the Chebyshev series coefficients, ordered
410
+ from lowest order term to highest.
411
+
412
+ Returns
413
+ -------
414
+ pol : ndarray
415
+ 1-D array containing the coefficients of the equivalent polynomial
416
+ (relative to the "standard" basis) ordered from lowest order term
417
+ to highest.
418
+
419
+ See Also
420
+ --------
421
+ poly2cheb
422
+
423
+ Notes
424
+ -----
425
+ The easy way to do conversions between polynomial basis sets
426
+ is to use the convert method of a class instance.
427
+
428
+ Examples
429
+ --------
430
+ >>> from numpy import polynomial as P
431
+ >>> c = P.Chebyshev(range(4))
432
+ >>> c
433
+ Chebyshev([0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
434
+ >>> p = c.convert(kind=P.Polynomial)
435
+ >>> p
436
+ Polynomial([-2., -8., 4., 12.], domain=[-1., 1.], window=[-1., 1.])
437
+ >>> P.chebyshev.cheb2poly(range(4))
438
+ array([-2., -8., 4., 12.])
439
+
440
+ """
441
+ from .polynomial import polyadd, polysub, polymulx
442
+
443
+ [c] = pu.as_series([c])
444
+ n = len(c)
445
+ if n < 3:
446
+ return c
447
+ else:
448
+ c0 = c[-2]
449
+ c1 = c[-1]
450
+ # i is the current degree of c1
451
+ for i in range(n - 1, 1, -1):
452
+ tmp = c0
453
+ c0 = polysub(c[i - 2], c1)
454
+ c1 = polyadd(tmp, polymulx(c1)*2)
455
+ return polyadd(c0, polymulx(c1))
456
+
457
+
458
+ #
459
+ # These are constant arrays are of integer type so as to be compatible
460
+ # with the widest range of other types, such as Decimal.
461
+ #
462
+
463
+ # Chebyshev default domain.
464
+ chebdomain = np.array([-1, 1])
465
+
466
+ # Chebyshev coefficients representing zero.
467
+ chebzero = np.array([0])
468
+
469
+ # Chebyshev coefficients representing one.
470
+ chebone = np.array([1])
471
+
472
+ # Chebyshev coefficients representing the identity x.
473
+ chebx = np.array([0, 1])
474
+
475
+
476
+ def chebline(off, scl):
477
+ """
478
+ Chebyshev series whose graph is a straight line.
479
+
480
+ Parameters
481
+ ----------
482
+ off, scl : scalars
483
+ The specified line is given by ``off + scl*x``.
484
+
485
+ Returns
486
+ -------
487
+ y : ndarray
488
+ This module's representation of the Chebyshev series for
489
+ ``off + scl*x``.
490
+
491
+ See Also
492
+ --------
493
+ numpy.polynomial.polynomial.polyline
494
+ numpy.polynomial.legendre.legline
495
+ numpy.polynomial.laguerre.lagline
496
+ numpy.polynomial.hermite.hermline
497
+ numpy.polynomial.hermite_e.hermeline
498
+
499
+ Examples
500
+ --------
501
+ >>> import numpy.polynomial.chebyshev as C
502
+ >>> C.chebline(3,2)
503
+ array([3, 2])
504
+ >>> C.chebval(-3, C.chebline(3,2)) # should be -3
505
+ -3.0
506
+
507
+ """
508
+ if scl != 0:
509
+ return np.array([off, scl])
510
+ else:
511
+ return np.array([off])
512
+
513
+
514
+ def chebfromroots(roots):
515
+ """
516
+ Generate a Chebyshev series with given roots.
517
+
518
+ The function returns the coefficients of the polynomial
519
+
520
+ .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
521
+
522
+ in Chebyshev form, where the `r_n` are the roots specified in `roots`.
523
+ If a zero has multiplicity n, then it must appear in `roots` n times.
524
+ For instance, if 2 is a root of multiplicity three and 3 is a root of
525
+ multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3]. The
526
+ roots can appear in any order.
527
+
528
+ If the returned coefficients are `c`, then
529
+
530
+ .. math:: p(x) = c_0 + c_1 * T_1(x) + ... + c_n * T_n(x)
531
+
532
+ The coefficient of the last term is not generally 1 for monic
533
+ polynomials in Chebyshev form.
534
+
535
+ Parameters
536
+ ----------
537
+ roots : array_like
538
+ Sequence containing the roots.
539
+
540
+ Returns
541
+ -------
542
+ out : ndarray
543
+ 1-D array of coefficients. If all roots are real then `out` is a
544
+ real array, if some of the roots are complex, then `out` is complex
545
+ even if all the coefficients in the result are real (see Examples
546
+ below).
547
+
548
+ See Also
549
+ --------
550
+ numpy.polynomial.polynomial.polyfromroots
551
+ numpy.polynomial.legendre.legfromroots
552
+ numpy.polynomial.laguerre.lagfromroots
553
+ numpy.polynomial.hermite.hermfromroots
554
+ numpy.polynomial.hermite_e.hermefromroots
555
+
556
+ Examples
557
+ --------
558
+ >>> import numpy.polynomial.chebyshev as C
559
+ >>> C.chebfromroots((-1,0,1)) # x^3 - x relative to the standard basis
560
+ array([ 0. , -0.25, 0. , 0.25])
561
+ >>> j = complex(0,1)
562
+ >>> C.chebfromroots((-j,j)) # x^2 + 1 relative to the standard basis
563
+ array([1.5+0.j, 0. +0.j, 0.5+0.j])
564
+
565
+ """
566
+ return pu._fromroots(chebline, chebmul, roots)
567
+
568
+
569
+ def chebadd(c1, c2):
570
+ """
571
+ Add one Chebyshev series to another.
572
+
573
+ Returns the sum of two Chebyshev series `c1` + `c2`. The arguments
574
+ are sequences of coefficients ordered from lowest order term to
575
+ highest, i.e., [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
576
+
577
+ Parameters
578
+ ----------
579
+ c1, c2 : array_like
580
+ 1-D arrays of Chebyshev series coefficients ordered from low to
581
+ high.
582
+
583
+ Returns
584
+ -------
585
+ out : ndarray
586
+ Array representing the Chebyshev series of their sum.
587
+
588
+ See Also
589
+ --------
590
+ chebsub, chebmulx, chebmul, chebdiv, chebpow
591
+
592
+ Notes
593
+ -----
594
+ Unlike multiplication, division, etc., the sum of two Chebyshev series
595
+ is a Chebyshev series (without having to "reproject" the result onto
596
+ the basis set) so addition, just like that of "standard" polynomials,
597
+ is simply "component-wise."
598
+
599
+ Examples
600
+ --------
601
+ >>> from numpy.polynomial import chebyshev as C
602
+ >>> c1 = (1,2,3)
603
+ >>> c2 = (3,2,1)
604
+ >>> C.chebadd(c1,c2)
605
+ array([4., 4., 4.])
606
+
607
+ """
608
+ return pu._add(c1, c2)
609
+
610
+
611
+ def chebsub(c1, c2):
612
+ """
613
+ Subtract one Chebyshev series from another.
614
+
615
+ Returns the difference of two Chebyshev series `c1` - `c2`. The
616
+ sequences of coefficients are from lowest order term to highest, i.e.,
617
+ [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
618
+
619
+ Parameters
620
+ ----------
621
+ c1, c2 : array_like
622
+ 1-D arrays of Chebyshev series coefficients ordered from low to
623
+ high.
624
+
625
+ Returns
626
+ -------
627
+ out : ndarray
628
+ Of Chebyshev series coefficients representing their difference.
629
+
630
+ See Also
631
+ --------
632
+ chebadd, chebmulx, chebmul, chebdiv, chebpow
633
+
634
+ Notes
635
+ -----
636
+ Unlike multiplication, division, etc., the difference of two Chebyshev
637
+ series is a Chebyshev series (without having to "reproject" the result
638
+ onto the basis set) so subtraction, just like that of "standard"
639
+ polynomials, is simply "component-wise."
640
+
641
+ Examples
642
+ --------
643
+ >>> from numpy.polynomial import chebyshev as C
644
+ >>> c1 = (1,2,3)
645
+ >>> c2 = (3,2,1)
646
+ >>> C.chebsub(c1,c2)
647
+ array([-2., 0., 2.])
648
+ >>> C.chebsub(c2,c1) # -C.chebsub(c1,c2)
649
+ array([ 2., 0., -2.])
650
+
651
+ """
652
+ return pu._sub(c1, c2)
653
+
654
+
655
+ def chebmulx(c):
656
+ """Multiply a Chebyshev series by x.
657
+
658
+ Multiply the polynomial `c` by x, where x is the independent
659
+ variable.
660
+
661
+
662
+ Parameters
663
+ ----------
664
+ c : array_like
665
+ 1-D array of Chebyshev series coefficients ordered from low to
666
+ high.
667
+
668
+ Returns
669
+ -------
670
+ out : ndarray
671
+ Array representing the result of the multiplication.
672
+
673
+ Notes
674
+ -----
675
+
676
+ .. versionadded:: 1.5.0
677
+
678
+ Examples
679
+ --------
680
+ >>> from numpy.polynomial import chebyshev as C
681
+ >>> C.chebmulx([1,2,3])
682
+ array([1. , 2.5, 1. , 1.5])
683
+
684
+ """
685
+ # c is a trimmed copy
686
+ [c] = pu.as_series([c])
687
+ # The zero series needs special treatment
688
+ if len(c) == 1 and c[0] == 0:
689
+ return c
690
+
691
+ prd = np.empty(len(c) + 1, dtype=c.dtype)
692
+ prd[0] = c[0]*0
693
+ prd[1] = c[0]
694
+ if len(c) > 1:
695
+ tmp = c[1:]/2
696
+ prd[2:] = tmp
697
+ prd[0:-2] += tmp
698
+ return prd
699
+
700
+
701
+ def chebmul(c1, c2):
702
+ """
703
+ Multiply one Chebyshev series by another.
704
+
705
+ Returns the product of two Chebyshev series `c1` * `c2`. The arguments
706
+ are sequences of coefficients, from lowest order "term" to highest,
707
+ e.g., [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
708
+
709
+ Parameters
710
+ ----------
711
+ c1, c2 : array_like
712
+ 1-D arrays of Chebyshev series coefficients ordered from low to
713
+ high.
714
+
715
+ Returns
716
+ -------
717
+ out : ndarray
718
+ Of Chebyshev series coefficients representing their product.
719
+
720
+ See Also
721
+ --------
722
+ chebadd, chebsub, chebmulx, chebdiv, chebpow
723
+
724
+ Notes
725
+ -----
726
+ In general, the (polynomial) product of two C-series results in terms
727
+ that are not in the Chebyshev polynomial basis set. Thus, to express
728
+ the product as a C-series, it is typically necessary to "reproject"
729
+ the product onto said basis set, which typically produces
730
+ "unintuitive live" (but correct) results; see Examples section below.
731
+
732
+ Examples
733
+ --------
734
+ >>> from numpy.polynomial import chebyshev as C
735
+ >>> c1 = (1,2,3)
736
+ >>> c2 = (3,2,1)
737
+ >>> C.chebmul(c1,c2) # multiplication requires "reprojection"
738
+ array([ 6.5, 12. , 12. , 4. , 1.5])
739
+
740
+ """
741
+ # c1, c2 are trimmed copies
742
+ [c1, c2] = pu.as_series([c1, c2])
743
+ z1 = _cseries_to_zseries(c1)
744
+ z2 = _cseries_to_zseries(c2)
745
+ prd = _zseries_mul(z1, z2)
746
+ ret = _zseries_to_cseries(prd)
747
+ return pu.trimseq(ret)
748
+
749
+
750
+ def chebdiv(c1, c2):
751
+ """
752
+ Divide one Chebyshev series by another.
753
+
754
+ Returns the quotient-with-remainder of two Chebyshev series
755
+ `c1` / `c2`. The arguments are sequences of coefficients from lowest
756
+ order "term" to highest, e.g., [1,2,3] represents the series
757
+ ``T_0 + 2*T_1 + 3*T_2``.
758
+
759
+ Parameters
760
+ ----------
761
+ c1, c2 : array_like
762
+ 1-D arrays of Chebyshev series coefficients ordered from low to
763
+ high.
764
+
765
+ Returns
766
+ -------
767
+ [quo, rem] : ndarrays
768
+ Of Chebyshev series coefficients representing the quotient and
769
+ remainder.
770
+
771
+ See Also
772
+ --------
773
+ chebadd, chebsub, chebmulx, chebmul, chebpow
774
+
775
+ Notes
776
+ -----
777
+ In general, the (polynomial) division of one C-series by another
778
+ results in quotient and remainder terms that are not in the Chebyshev
779
+ polynomial basis set. Thus, to express these results as C-series, it
780
+ is typically necessary to "reproject" the results onto said basis
781
+ set, which typically produces "unintuitive" (but correct) results;
782
+ see Examples section below.
783
+
784
+ Examples
785
+ --------
786
+ >>> from numpy.polynomial import chebyshev as C
787
+ >>> c1 = (1,2,3)
788
+ >>> c2 = (3,2,1)
789
+ >>> C.chebdiv(c1,c2) # quotient "intuitive," remainder not
790
+ (array([3.]), array([-8., -4.]))
791
+ >>> c2 = (0,1,2,3)
792
+ >>> C.chebdiv(c2,c1) # neither "intuitive"
793
+ (array([0., 2.]), array([-2., -4.]))
794
+
795
+ """
796
+ # c1, c2 are trimmed copies
797
+ [c1, c2] = pu.as_series([c1, c2])
798
+ if c2[-1] == 0:
799
+ raise ZeroDivisionError()
800
+
801
+ # note: this is more efficient than `pu._div(chebmul, c1, c2)`
802
+ lc1 = len(c1)
803
+ lc2 = len(c2)
804
+ if lc1 < lc2:
805
+ return c1[:1]*0, c1
806
+ elif lc2 == 1:
807
+ return c1/c2[-1], c1[:1]*0
808
+ else:
809
+ z1 = _cseries_to_zseries(c1)
810
+ z2 = _cseries_to_zseries(c2)
811
+ quo, rem = _zseries_div(z1, z2)
812
+ quo = pu.trimseq(_zseries_to_cseries(quo))
813
+ rem = pu.trimseq(_zseries_to_cseries(rem))
814
+ return quo, rem
815
+
816
+
817
+ def chebpow(c, pow, maxpower=16):
818
+ """Raise a Chebyshev series to a power.
819
+
820
+ Returns the Chebyshev series `c` raised to the power `pow`. The
821
+ argument `c` is a sequence of coefficients ordered from low to high.
822
+ i.e., [1,2,3] is the series ``T_0 + 2*T_1 + 3*T_2.``
823
+
824
+ Parameters
825
+ ----------
826
+ c : array_like
827
+ 1-D array of Chebyshev series coefficients ordered from low to
828
+ high.
829
+ pow : integer
830
+ Power to which the series will be raised
831
+ maxpower : integer, optional
832
+ Maximum power allowed. This is mainly to limit growth of the series
833
+ to unmanageable size. Default is 16
834
+
835
+ Returns
836
+ -------
837
+ coef : ndarray
838
+ Chebyshev series of power.
839
+
840
+ See Also
841
+ --------
842
+ chebadd, chebsub, chebmulx, chebmul, chebdiv
843
+
844
+ Examples
845
+ --------
846
+ >>> from numpy.polynomial import chebyshev as C
847
+ >>> C.chebpow([1, 2, 3, 4], 2)
848
+ array([15.5, 22. , 16. , ..., 12.5, 12. , 8. ])
849
+
850
+ """
851
+ # note: this is more efficient than `pu._pow(chebmul, c1, c2)`, as it
852
+ # avoids converting between z and c series repeatedly
853
+
854
+ # c is a trimmed copy
855
+ [c] = pu.as_series([c])
856
+ power = int(pow)
857
+ if power != pow or power < 0:
858
+ raise ValueError("Power must be a non-negative integer.")
859
+ elif maxpower is not None and power > maxpower:
860
+ raise ValueError("Power is too large")
861
+ elif power == 0:
862
+ return np.array([1], dtype=c.dtype)
863
+ elif power == 1:
864
+ return c
865
+ else:
866
+ # This can be made more efficient by using powers of two
867
+ # in the usual way.
868
+ zs = _cseries_to_zseries(c)
869
+ prd = zs
870
+ for i in range(2, power + 1):
871
+ prd = np.convolve(prd, zs)
872
+ return _zseries_to_cseries(prd)
873
+
874
+
875
+ def chebder(c, m=1, scl=1, axis=0):
876
+ """
877
+ Differentiate a Chebyshev series.
878
+
879
+ Returns the Chebyshev series coefficients `c` differentiated `m` times
880
+ along `axis`. At each iteration the result is multiplied by `scl` (the
881
+ scaling factor is for use in a linear change of variable). The argument
882
+ `c` is an array of coefficients from low to high degree along each
883
+ axis, e.g., [1,2,3] represents the series ``1*T_0 + 2*T_1 + 3*T_2``
884
+ while [[1,2],[1,2]] represents ``1*T_0(x)*T_0(y) + 1*T_1(x)*T_0(y) +
885
+ 2*T_0(x)*T_1(y) + 2*T_1(x)*T_1(y)`` if axis=0 is ``x`` and axis=1 is
886
+ ``y``.
887
+
888
+ Parameters
889
+ ----------
890
+ c : array_like
891
+ Array of Chebyshev series coefficients. If c is multidimensional
892
+ the different axis correspond to different variables with the
893
+ degree in each axis given by the corresponding index.
894
+ m : int, optional
895
+ Number of derivatives taken, must be non-negative. (Default: 1)
896
+ scl : scalar, optional
897
+ Each differentiation is multiplied by `scl`. The end result is
898
+ multiplication by ``scl**m``. This is for use in a linear change of
899
+ variable. (Default: 1)
900
+ axis : int, optional
901
+ Axis over which the derivative is taken. (Default: 0).
902
+
903
+ .. versionadded:: 1.7.0
904
+
905
+ Returns
906
+ -------
907
+ der : ndarray
908
+ Chebyshev series of the derivative.
909
+
910
+ See Also
911
+ --------
912
+ chebint
913
+
914
+ Notes
915
+ -----
916
+ In general, the result of differentiating a C-series needs to be
917
+ "reprojected" onto the C-series basis set. Thus, typically, the
918
+ result of this function is "unintuitive," albeit correct; see Examples
919
+ section below.
920
+
921
+ Examples
922
+ --------
923
+ >>> from numpy.polynomial import chebyshev as C
924
+ >>> c = (1,2,3,4)
925
+ >>> C.chebder(c)
926
+ array([14., 12., 24.])
927
+ >>> C.chebder(c,3)
928
+ array([96.])
929
+ >>> C.chebder(c,scl=-1)
930
+ array([-14., -12., -24.])
931
+ >>> C.chebder(c,2,-1)
932
+ array([12., 96.])
933
+
934
+ """
935
+ c = np.array(c, ndmin=1, copy=True)
936
+ if c.dtype.char in '?bBhHiIlLqQpP':
937
+ c = c.astype(np.double)
938
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
939
+ iaxis = pu._deprecate_as_int(axis, "the axis")
940
+ if cnt < 0:
941
+ raise ValueError("The order of derivation must be non-negative")
942
+ iaxis = normalize_axis_index(iaxis, c.ndim)
943
+
944
+ if cnt == 0:
945
+ return c
946
+
947
+ c = np.moveaxis(c, iaxis, 0)
948
+ n = len(c)
949
+ if cnt >= n:
950
+ c = c[:1]*0
951
+ else:
952
+ for i in range(cnt):
953
+ n = n - 1
954
+ c *= scl
955
+ der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
956
+ for j in range(n, 2, -1):
957
+ der[j - 1] = (2*j)*c[j]
958
+ c[j - 2] += (j*c[j])/(j - 2)
959
+ if n > 1:
960
+ der[1] = 4*c[2]
961
+ der[0] = c[1]
962
+ c = der
963
+ c = np.moveaxis(c, 0, iaxis)
964
+ return c
965
+
966
+
967
+ def chebint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
968
+ """
969
+ Integrate a Chebyshev series.
970
+
971
+ Returns the Chebyshev series coefficients `c` integrated `m` times from
972
+ `lbnd` along `axis`. At each iteration the resulting series is
973
+ **multiplied** by `scl` and an integration constant, `k`, is added.
974
+ The scaling factor is for use in a linear change of variable. ("Buyer
975
+ beware": note that, depending on what one is doing, one may want `scl`
976
+ to be the reciprocal of what one might expect; for more information,
977
+ see the Notes section below.) The argument `c` is an array of
978
+ coefficients from low to high degree along each axis, e.g., [1,2,3]
979
+ represents the series ``T_0 + 2*T_1 + 3*T_2`` while [[1,2],[1,2]]
980
+ represents ``1*T_0(x)*T_0(y) + 1*T_1(x)*T_0(y) + 2*T_0(x)*T_1(y) +
981
+ 2*T_1(x)*T_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
982
+
983
+ Parameters
984
+ ----------
985
+ c : array_like
986
+ Array of Chebyshev series coefficients. If c is multidimensional
987
+ the different axis correspond to different variables with the
988
+ degree in each axis given by the corresponding index.
989
+ m : int, optional
990
+ Order of integration, must be positive. (Default: 1)
991
+ k : {[], list, scalar}, optional
992
+ Integration constant(s). The value of the first integral at zero
993
+ is the first value in the list, the value of the second integral
994
+ at zero is the second value, etc. If ``k == []`` (the default),
995
+ all constants are set to zero. If ``m == 1``, a single scalar can
996
+ be given instead of a list.
997
+ lbnd : scalar, optional
998
+ The lower bound of the integral. (Default: 0)
999
+ scl : scalar, optional
1000
+ Following each integration the result is *multiplied* by `scl`
1001
+ before the integration constant is added. (Default: 1)
1002
+ axis : int, optional
1003
+ Axis over which the integral is taken. (Default: 0).
1004
+
1005
+ .. versionadded:: 1.7.0
1006
+
1007
+ Returns
1008
+ -------
1009
+ S : ndarray
1010
+ C-series coefficients of the integral.
1011
+
1012
+ Raises
1013
+ ------
1014
+ ValueError
1015
+ If ``m < 1``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
1016
+ ``np.ndim(scl) != 0``.
1017
+
1018
+ See Also
1019
+ --------
1020
+ chebder
1021
+
1022
+ Notes
1023
+ -----
1024
+ Note that the result of each integration is *multiplied* by `scl`.
1025
+ Why is this important to note? Say one is making a linear change of
1026
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
1027
+ :math:`dx = du/a`, so one will need to set `scl` equal to
1028
+ :math:`1/a`- perhaps not what one would have first thought.
1029
+
1030
+ Also note that, in general, the result of integrating a C-series needs
1031
+ to be "reprojected" onto the C-series basis set. Thus, typically,
1032
+ the result of this function is "unintuitive," albeit correct; see
1033
+ Examples section below.
1034
+
1035
+ Examples
1036
+ --------
1037
+ >>> from numpy.polynomial import chebyshev as C
1038
+ >>> c = (1,2,3)
1039
+ >>> C.chebint(c)
1040
+ array([ 0.5, -0.5, 0.5, 0.5])
1041
+ >>> C.chebint(c,3)
1042
+ array([ 0.03125 , -0.1875 , 0.04166667, -0.05208333, 0.01041667, # may vary
1043
+ 0.00625 ])
1044
+ >>> C.chebint(c, k=3)
1045
+ array([ 3.5, -0.5, 0.5, 0.5])
1046
+ >>> C.chebint(c,lbnd=-2)
1047
+ array([ 8.5, -0.5, 0.5, 0.5])
1048
+ >>> C.chebint(c,scl=-2)
1049
+ array([-1., 1., -1., -1.])
1050
+
1051
+ """
1052
+ c = np.array(c, ndmin=1, copy=True)
1053
+ if c.dtype.char in '?bBhHiIlLqQpP':
1054
+ c = c.astype(np.double)
1055
+ if not np.iterable(k):
1056
+ k = [k]
1057
+ cnt = pu._deprecate_as_int(m, "the order of integration")
1058
+ iaxis = pu._deprecate_as_int(axis, "the axis")
1059
+ if cnt < 0:
1060
+ raise ValueError("The order of integration must be non-negative")
1061
+ if len(k) > cnt:
1062
+ raise ValueError("Too many integration constants")
1063
+ if np.ndim(lbnd) != 0:
1064
+ raise ValueError("lbnd must be a scalar.")
1065
+ if np.ndim(scl) != 0:
1066
+ raise ValueError("scl must be a scalar.")
1067
+ iaxis = normalize_axis_index(iaxis, c.ndim)
1068
+
1069
+ if cnt == 0:
1070
+ return c
1071
+
1072
+ c = np.moveaxis(c, iaxis, 0)
1073
+ k = list(k) + [0]*(cnt - len(k))
1074
+ for i in range(cnt):
1075
+ n = len(c)
1076
+ c *= scl
1077
+ if n == 1 and np.all(c[0] == 0):
1078
+ c[0] += k[i]
1079
+ else:
1080
+ tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
1081
+ tmp[0] = c[0]*0
1082
+ tmp[1] = c[0]
1083
+ if n > 1:
1084
+ tmp[2] = c[1]/4
1085
+ for j in range(2, n):
1086
+ tmp[j + 1] = c[j]/(2*(j + 1))
1087
+ tmp[j - 1] -= c[j]/(2*(j - 1))
1088
+ tmp[0] += k[i] - chebval(lbnd, tmp)
1089
+ c = tmp
1090
+ c = np.moveaxis(c, 0, iaxis)
1091
+ return c
1092
+
1093
+
1094
+ def chebval(x, c, tensor=True):
1095
+ """
1096
+ Evaluate a Chebyshev series at points x.
1097
+
1098
+ If `c` is of length `n + 1`, this function returns the value:
1099
+
1100
+ .. math:: p(x) = c_0 * T_0(x) + c_1 * T_1(x) + ... + c_n * T_n(x)
1101
+
1102
+ The parameter `x` is converted to an array only if it is a tuple or a
1103
+ list, otherwise it is treated as a scalar. In either case, either `x`
1104
+ or its elements must support multiplication and addition both with
1105
+ themselves and with the elements of `c`.
1106
+
1107
+ If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
1108
+ `c` is multidimensional, then the shape of the result depends on the
1109
+ value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
1110
+ x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
1111
+ scalars have shape (,).
1112
+
1113
+ Trailing zeros in the coefficients will be used in the evaluation, so
1114
+ they should be avoided if efficiency is a concern.
1115
+
1116
+ Parameters
1117
+ ----------
1118
+ x : array_like, compatible object
1119
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
1120
+ it is left unchanged and treated as a scalar. In either case, `x`
1121
+ or its elements must support addition and multiplication with
1122
+ themselves and with the elements of `c`.
1123
+ c : array_like
1124
+ Array of coefficients ordered so that the coefficients for terms of
1125
+ degree n are contained in c[n]. If `c` is multidimensional the
1126
+ remaining indices enumerate multiple polynomials. In the two
1127
+ dimensional case the coefficients may be thought of as stored in
1128
+ the columns of `c`.
1129
+ tensor : boolean, optional
1130
+ If True, the shape of the coefficient array is extended with ones
1131
+ on the right, one for each dimension of `x`. Scalars have dimension 0
1132
+ for this action. The result is that every column of coefficients in
1133
+ `c` is evaluated for every element of `x`. If False, `x` is broadcast
1134
+ over the columns of `c` for the evaluation. This keyword is useful
1135
+ when `c` is multidimensional. The default value is True.
1136
+
1137
+ .. versionadded:: 1.7.0
1138
+
1139
+ Returns
1140
+ -------
1141
+ values : ndarray, algebra_like
1142
+ The shape of the return value is described above.
1143
+
1144
+ See Also
1145
+ --------
1146
+ chebval2d, chebgrid2d, chebval3d, chebgrid3d
1147
+
1148
+ Notes
1149
+ -----
1150
+ The evaluation uses Clenshaw recursion, aka synthetic division.
1151
+
1152
+ """
1153
+ c = np.array(c, ndmin=1, copy=True)
1154
+ if c.dtype.char in '?bBhHiIlLqQpP':
1155
+ c = c.astype(np.double)
1156
+ if isinstance(x, (tuple, list)):
1157
+ x = np.asarray(x)
1158
+ if isinstance(x, np.ndarray) and tensor:
1159
+ c = c.reshape(c.shape + (1,)*x.ndim)
1160
+
1161
+ if len(c) == 1:
1162
+ c0 = c[0]
1163
+ c1 = 0
1164
+ elif len(c) == 2:
1165
+ c0 = c[0]
1166
+ c1 = c[1]
1167
+ else:
1168
+ x2 = 2*x
1169
+ c0 = c[-2]
1170
+ c1 = c[-1]
1171
+ for i in range(3, len(c) + 1):
1172
+ tmp = c0
1173
+ c0 = c[-i] - c1
1174
+ c1 = tmp + c1*x2
1175
+ return c0 + c1*x
1176
+
1177
+
1178
+ def chebval2d(x, y, c):
1179
+ """
1180
+ Evaluate a 2-D Chebyshev series at points (x, y).
1181
+
1182
+ This function returns the values:
1183
+
1184
+ .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * T_i(x) * T_j(y)
1185
+
1186
+ The parameters `x` and `y` are converted to arrays only if they are
1187
+ tuples or a lists, otherwise they are treated as a scalars and they
1188
+ must have the same shape after conversion. In either case, either `x`
1189
+ and `y` or their elements must support multiplication and addition both
1190
+ with themselves and with the elements of `c`.
1191
+
1192
+ If `c` is a 1-D array a one is implicitly appended to its shape to make
1193
+ it 2-D. The shape of the result will be c.shape[2:] + x.shape.
1194
+
1195
+ Parameters
1196
+ ----------
1197
+ x, y : array_like, compatible objects
1198
+ The two dimensional series is evaluated at the points `(x, y)`,
1199
+ where `x` and `y` must have the same shape. If `x` or `y` is a list
1200
+ or tuple, it is first converted to an ndarray, otherwise it is left
1201
+ unchanged and if it isn't an ndarray it is treated as a scalar.
1202
+ c : array_like
1203
+ Array of coefficients ordered so that the coefficient of the term
1204
+ of multi-degree i,j is contained in ``c[i,j]``. If `c` has
1205
+ dimension greater than 2 the remaining indices enumerate multiple
1206
+ sets of coefficients.
1207
+
1208
+ Returns
1209
+ -------
1210
+ values : ndarray, compatible object
1211
+ The values of the two dimensional Chebyshev series at points formed
1212
+ from pairs of corresponding values from `x` and `y`.
1213
+
1214
+ See Also
1215
+ --------
1216
+ chebval, chebgrid2d, chebval3d, chebgrid3d
1217
+
1218
+ Notes
1219
+ -----
1220
+
1221
+ .. versionadded:: 1.7.0
1222
+
1223
+ """
1224
+ return pu._valnd(chebval, c, x, y)
1225
+
1226
+
1227
+ def chebgrid2d(x, y, c):
1228
+ """
1229
+ Evaluate a 2-D Chebyshev series on the Cartesian product of x and y.
1230
+
1231
+ This function returns the values:
1232
+
1233
+ .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * T_i(a) * T_j(b),
1234
+
1235
+ where the points `(a, b)` consist of all pairs formed by taking
1236
+ `a` from `x` and `b` from `y`. The resulting points form a grid with
1237
+ `x` in the first dimension and `y` in the second.
1238
+
1239
+ The parameters `x` and `y` are converted to arrays only if they are
1240
+ tuples or a lists, otherwise they are treated as a scalars. In either
1241
+ case, either `x` and `y` or their elements must support multiplication
1242
+ and addition both with themselves and with the elements of `c`.
1243
+
1244
+ If `c` has fewer than two dimensions, ones are implicitly appended to
1245
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
1246
+ x.shape + y.shape.
1247
+
1248
+ Parameters
1249
+ ----------
1250
+ x, y : array_like, compatible objects
1251
+ The two dimensional series is evaluated at the points in the
1252
+ Cartesian product of `x` and `y`. If `x` or `y` is a list or
1253
+ tuple, it is first converted to an ndarray, otherwise it is left
1254
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
1255
+ c : array_like
1256
+ Array of coefficients ordered so that the coefficient of the term of
1257
+ multi-degree i,j is contained in `c[i,j]`. If `c` has dimension
1258
+ greater than two the remaining indices enumerate multiple sets of
1259
+ coefficients.
1260
+
1261
+ Returns
1262
+ -------
1263
+ values : ndarray, compatible object
1264
+ The values of the two dimensional Chebyshev series at points in the
1265
+ Cartesian product of `x` and `y`.
1266
+
1267
+ See Also
1268
+ --------
1269
+ chebval, chebval2d, chebval3d, chebgrid3d
1270
+
1271
+ Notes
1272
+ -----
1273
+
1274
+ .. versionadded:: 1.7.0
1275
+
1276
+ """
1277
+ return pu._gridnd(chebval, c, x, y)
1278
+
1279
+
1280
+ def chebval3d(x, y, z, c):
1281
+ """
1282
+ Evaluate a 3-D Chebyshev series at points (x, y, z).
1283
+
1284
+ This function returns the values:
1285
+
1286
+ .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * T_i(x) * T_j(y) * T_k(z)
1287
+
1288
+ The parameters `x`, `y`, and `z` are converted to arrays only if
1289
+ they are tuples or a lists, otherwise they are treated as a scalars and
1290
+ they must have the same shape after conversion. In either case, either
1291
+ `x`, `y`, and `z` or their elements must support multiplication and
1292
+ addition both with themselves and with the elements of `c`.
1293
+
1294
+ If `c` has fewer than 3 dimensions, ones are implicitly appended to its
1295
+ shape to make it 3-D. The shape of the result will be c.shape[3:] +
1296
+ x.shape.
1297
+
1298
+ Parameters
1299
+ ----------
1300
+ x, y, z : array_like, compatible object
1301
+ The three dimensional series is evaluated at the points
1302
+ `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
1303
+ any of `x`, `y`, or `z` is a list or tuple, it is first converted
1304
+ to an ndarray, otherwise it is left unchanged and if it isn't an
1305
+ ndarray it is treated as a scalar.
1306
+ c : array_like
1307
+ Array of coefficients ordered so that the coefficient of the term of
1308
+ multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
1309
+ greater than 3 the remaining indices enumerate multiple sets of
1310
+ coefficients.
1311
+
1312
+ Returns
1313
+ -------
1314
+ values : ndarray, compatible object
1315
+ The values of the multidimensional polynomial on points formed with
1316
+ triples of corresponding values from `x`, `y`, and `z`.
1317
+
1318
+ See Also
1319
+ --------
1320
+ chebval, chebval2d, chebgrid2d, chebgrid3d
1321
+
1322
+ Notes
1323
+ -----
1324
+
1325
+ .. versionadded:: 1.7.0
1326
+
1327
+ """
1328
+ return pu._valnd(chebval, c, x, y, z)
1329
+
1330
+
1331
+ def chebgrid3d(x, y, z, c):
1332
+ """
1333
+ Evaluate a 3-D Chebyshev series on the Cartesian product of x, y, and z.
1334
+
1335
+ This function returns the values:
1336
+
1337
+ .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * T_i(a) * T_j(b) * T_k(c)
1338
+
1339
+ where the points `(a, b, c)` consist of all triples formed by taking
1340
+ `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
1341
+ a grid with `x` in the first dimension, `y` in the second, and `z` in
1342
+ the third.
1343
+
1344
+ The parameters `x`, `y`, and `z` are converted to arrays only if they
1345
+ are tuples or a lists, otherwise they are treated as a scalars. In
1346
+ either case, either `x`, `y`, and `z` or their elements must support
1347
+ multiplication and addition both with themselves and with the elements
1348
+ of `c`.
1349
+
1350
+ If `c` has fewer than three dimensions, ones are implicitly appended to
1351
+ its shape to make it 3-D. The shape of the result will be c.shape[3:] +
1352
+ x.shape + y.shape + z.shape.
1353
+
1354
+ Parameters
1355
+ ----------
1356
+ x, y, z : array_like, compatible objects
1357
+ The three dimensional series is evaluated at the points in the
1358
+ Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
1359
+ list or tuple, it is first converted to an ndarray, otherwise it is
1360
+ left unchanged and, if it isn't an ndarray, it is treated as a
1361
+ scalar.
1362
+ c : array_like
1363
+ Array of coefficients ordered so that the coefficients for terms of
1364
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
1365
+ greater than two the remaining indices enumerate multiple sets of
1366
+ coefficients.
1367
+
1368
+ Returns
1369
+ -------
1370
+ values : ndarray, compatible object
1371
+ The values of the two dimensional polynomial at points in the Cartesian
1372
+ product of `x` and `y`.
1373
+
1374
+ See Also
1375
+ --------
1376
+ chebval, chebval2d, chebgrid2d, chebval3d
1377
+
1378
+ Notes
1379
+ -----
1380
+
1381
+ .. versionadded:: 1.7.0
1382
+
1383
+ """
1384
+ return pu._gridnd(chebval, c, x, y, z)
1385
+
1386
+
1387
+ def chebvander(x, deg):
1388
+ """Pseudo-Vandermonde matrix of given degree.
1389
+
1390
+ Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
1391
+ `x`. The pseudo-Vandermonde matrix is defined by
1392
+
1393
+ .. math:: V[..., i] = T_i(x),
1394
+
1395
+ where `0 <= i <= deg`. The leading indices of `V` index the elements of
1396
+ `x` and the last index is the degree of the Chebyshev polynomial.
1397
+
1398
+ If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
1399
+ matrix ``V = chebvander(x, n)``, then ``np.dot(V, c)`` and
1400
+ ``chebval(x, c)`` are the same up to roundoff. This equivalence is
1401
+ useful both for least squares fitting and for the evaluation of a large
1402
+ number of Chebyshev series of the same degree and sample points.
1403
+
1404
+ Parameters
1405
+ ----------
1406
+ x : array_like
1407
+ Array of points. The dtype is converted to float64 or complex128
1408
+ depending on whether any of the elements are complex. If `x` is
1409
+ scalar it is converted to a 1-D array.
1410
+ deg : int
1411
+ Degree of the resulting matrix.
1412
+
1413
+ Returns
1414
+ -------
1415
+ vander : ndarray
1416
+ The pseudo Vandermonde matrix. The shape of the returned matrix is
1417
+ ``x.shape + (deg + 1,)``, where The last index is the degree of the
1418
+ corresponding Chebyshev polynomial. The dtype will be the same as
1419
+ the converted `x`.
1420
+
1421
+ """
1422
+ ideg = pu._deprecate_as_int(deg, "deg")
1423
+ if ideg < 0:
1424
+ raise ValueError("deg must be non-negative")
1425
+
1426
+ x = np.array(x, copy=False, ndmin=1) + 0.0
1427
+ dims = (ideg + 1,) + x.shape
1428
+ dtyp = x.dtype
1429
+ v = np.empty(dims, dtype=dtyp)
1430
+ # Use forward recursion to generate the entries.
1431
+ v[0] = x*0 + 1
1432
+ if ideg > 0:
1433
+ x2 = 2*x
1434
+ v[1] = x
1435
+ for i in range(2, ideg + 1):
1436
+ v[i] = v[i-1]*x2 - v[i-2]
1437
+ return np.moveaxis(v, 0, -1)
1438
+
1439
+
1440
+ def chebvander2d(x, y, deg):
1441
+ """Pseudo-Vandermonde matrix of given degrees.
1442
+
1443
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1444
+ points `(x, y)`. The pseudo-Vandermonde matrix is defined by
1445
+
1446
+ .. math:: V[..., (deg[1] + 1)*i + j] = T_i(x) * T_j(y),
1447
+
1448
+ where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
1449
+ `V` index the points `(x, y)` and the last index encodes the degrees of
1450
+ the Chebyshev polynomials.
1451
+
1452
+ If ``V = chebvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
1453
+ correspond to the elements of a 2-D coefficient array `c` of shape
1454
+ (xdeg + 1, ydeg + 1) in the order
1455
+
1456
+ .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
1457
+
1458
+ and ``np.dot(V, c.flat)`` and ``chebval2d(x, y, c)`` will be the same
1459
+ up to roundoff. This equivalence is useful both for least squares
1460
+ fitting and for the evaluation of a large number of 2-D Chebyshev
1461
+ series of the same degrees and sample points.
1462
+
1463
+ Parameters
1464
+ ----------
1465
+ x, y : array_like
1466
+ Arrays of point coordinates, all of the same shape. The dtypes
1467
+ will be converted to either float64 or complex128 depending on
1468
+ whether any of the elements are complex. Scalars are converted to
1469
+ 1-D arrays.
1470
+ deg : list of ints
1471
+ List of maximum degrees of the form [x_deg, y_deg].
1472
+
1473
+ Returns
1474
+ -------
1475
+ vander2d : ndarray
1476
+ The shape of the returned matrix is ``x.shape + (order,)``, where
1477
+ :math:`order = (deg[0]+1)*(deg[1]+1)`. The dtype will be the same
1478
+ as the converted `x` and `y`.
1479
+
1480
+ See Also
1481
+ --------
1482
+ chebvander, chebvander3d, chebval2d, chebval3d
1483
+
1484
+ Notes
1485
+ -----
1486
+
1487
+ .. versionadded:: 1.7.0
1488
+
1489
+ """
1490
+ return pu._vander_nd_flat((chebvander, chebvander), (x, y), deg)
1491
+
1492
+
1493
+ def chebvander3d(x, y, z, deg):
1494
+ """Pseudo-Vandermonde matrix of given degrees.
1495
+
1496
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1497
+ points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
1498
+ then The pseudo-Vandermonde matrix is defined by
1499
+
1500
+ .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = T_i(x)*T_j(y)*T_k(z),
1501
+
1502
+ where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
1503
+ indices of `V` index the points `(x, y, z)` and the last index encodes
1504
+ the degrees of the Chebyshev polynomials.
1505
+
1506
+ If ``V = chebvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
1507
+ of `V` correspond to the elements of a 3-D coefficient array `c` of
1508
+ shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
1509
+
1510
+ .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
1511
+
1512
+ and ``np.dot(V, c.flat)`` and ``chebval3d(x, y, z, c)`` will be the
1513
+ same up to roundoff. This equivalence is useful both for least squares
1514
+ fitting and for the evaluation of a large number of 3-D Chebyshev
1515
+ series of the same degrees and sample points.
1516
+
1517
+ Parameters
1518
+ ----------
1519
+ x, y, z : array_like
1520
+ Arrays of point coordinates, all of the same shape. The dtypes will
1521
+ be converted to either float64 or complex128 depending on whether
1522
+ any of the elements are complex. Scalars are converted to 1-D
1523
+ arrays.
1524
+ deg : list of ints
1525
+ List of maximum degrees of the form [x_deg, y_deg, z_deg].
1526
+
1527
+ Returns
1528
+ -------
1529
+ vander3d : ndarray
1530
+ The shape of the returned matrix is ``x.shape + (order,)``, where
1531
+ :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`. The dtype will
1532
+ be the same as the converted `x`, `y`, and `z`.
1533
+
1534
+ See Also
1535
+ --------
1536
+ chebvander, chebvander3d, chebval2d, chebval3d
1537
+
1538
+ Notes
1539
+ -----
1540
+
1541
+ .. versionadded:: 1.7.0
1542
+
1543
+ """
1544
+ return pu._vander_nd_flat((chebvander, chebvander, chebvander), (x, y, z), deg)
1545
+
1546
+
1547
+ def chebfit(x, y, deg, rcond=None, full=False, w=None):
1548
+ """
1549
+ Least squares fit of Chebyshev series to data.
1550
+
1551
+ Return the coefficients of a Chebyshev series of degree `deg` that is the
1552
+ least squares fit to the data values `y` given at points `x`. If `y` is
1553
+ 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
1554
+ fits are done, one for each column of `y`, and the resulting
1555
+ coefficients are stored in the corresponding columns of a 2-D return.
1556
+ The fitted polynomial(s) are in the form
1557
+
1558
+ .. math:: p(x) = c_0 + c_1 * T_1(x) + ... + c_n * T_n(x),
1559
+
1560
+ where `n` is `deg`.
1561
+
1562
+ Parameters
1563
+ ----------
1564
+ x : array_like, shape (M,)
1565
+ x-coordinates of the M sample points ``(x[i], y[i])``.
1566
+ y : array_like, shape (M,) or (M, K)
1567
+ y-coordinates of the sample points. Several data sets of sample
1568
+ points sharing the same x-coordinates can be fitted at once by
1569
+ passing in a 2D-array that contains one dataset per column.
1570
+ deg : int or 1-D array_like
1571
+ Degree(s) of the fitting polynomials. If `deg` is a single integer,
1572
+ all terms up to and including the `deg`'th term are included in the
1573
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
1574
+ degrees of the terms to include may be used instead.
1575
+ rcond : float, optional
1576
+ Relative condition number of the fit. Singular values smaller than
1577
+ this relative to the largest singular value will be ignored. The
1578
+ default value is len(x)*eps, where eps is the relative precision of
1579
+ the float type, about 2e-16 in most cases.
1580
+ full : bool, optional
1581
+ Switch determining nature of return value. When it is False (the
1582
+ default) just the coefficients are returned, when True diagnostic
1583
+ information from the singular value decomposition is also returned.
1584
+ w : array_like, shape (`M`,), optional
1585
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
1586
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
1587
+ chosen so that the errors of the products ``w[i]*y[i]`` all have the
1588
+ same variance. When using inverse-variance weighting, use
1589
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
1590
+
1591
+ .. versionadded:: 1.5.0
1592
+
1593
+ Returns
1594
+ -------
1595
+ coef : ndarray, shape (M,) or (M, K)
1596
+ Chebyshev coefficients ordered from low to high. If `y` was 2-D,
1597
+ the coefficients for the data in column k of `y` are in column
1598
+ `k`.
1599
+
1600
+ [residuals, rank, singular_values, rcond] : list
1601
+ These values are only returned if ``full == True``
1602
+
1603
+ - residuals -- sum of squared residuals of the least squares fit
1604
+ - rank -- the numerical rank of the scaled Vandermonde matrix
1605
+ - singular_values -- singular values of the scaled Vandermonde matrix
1606
+ - rcond -- value of `rcond`.
1607
+
1608
+ For more details, see `numpy.linalg.lstsq`.
1609
+
1610
+ Warns
1611
+ -----
1612
+ RankWarning
1613
+ The rank of the coefficient matrix in the least-squares fit is
1614
+ deficient. The warning is only raised if ``full == False``. The
1615
+ warnings can be turned off by
1616
+
1617
+ >>> import warnings
1618
+ >>> warnings.simplefilter('ignore', np.RankWarning)
1619
+
1620
+ See Also
1621
+ --------
1622
+ numpy.polynomial.polynomial.polyfit
1623
+ numpy.polynomial.legendre.legfit
1624
+ numpy.polynomial.laguerre.lagfit
1625
+ numpy.polynomial.hermite.hermfit
1626
+ numpy.polynomial.hermite_e.hermefit
1627
+ chebval : Evaluates a Chebyshev series.
1628
+ chebvander : Vandermonde matrix of Chebyshev series.
1629
+ chebweight : Chebyshev weight function.
1630
+ numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
1631
+ scipy.interpolate.UnivariateSpline : Computes spline fits.
1632
+
1633
+ Notes
1634
+ -----
1635
+ The solution is the coefficients of the Chebyshev series `p` that
1636
+ minimizes the sum of the weighted squared errors
1637
+
1638
+ .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
1639
+
1640
+ where :math:`w_j` are the weights. This problem is solved by setting up
1641
+ as the (typically) overdetermined matrix equation
1642
+
1643
+ .. math:: V(x) * c = w * y,
1644
+
1645
+ where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the
1646
+ coefficients to be solved for, `w` are the weights, and `y` are the
1647
+ observed values. This equation is then solved using the singular value
1648
+ decomposition of `V`.
1649
+
1650
+ If some of the singular values of `V` are so small that they are
1651
+ neglected, then a `RankWarning` will be issued. This means that the
1652
+ coefficient values may be poorly determined. Using a lower order fit
1653
+ will usually get rid of the warning. The `rcond` parameter can also be
1654
+ set to a value smaller than its default, but the resulting fit may be
1655
+ spurious and have large contributions from roundoff error.
1656
+
1657
+ Fits using Chebyshev series are usually better conditioned than fits
1658
+ using power series, but much can depend on the distribution of the
1659
+ sample points and the smoothness of the data. If the quality of the fit
1660
+ is inadequate splines may be a good alternative.
1661
+
1662
+ References
1663
+ ----------
1664
+ .. [1] Wikipedia, "Curve fitting",
1665
+ https://en.wikipedia.org/wiki/Curve_fitting
1666
+
1667
+ Examples
1668
+ --------
1669
+
1670
+ """
1671
+ return pu._fit(chebvander, x, y, deg, rcond, full, w)
1672
+
1673
+
1674
+ def chebcompanion(c):
1675
+ """Return the scaled companion matrix of c.
1676
+
1677
+ The basis polynomials are scaled so that the companion matrix is
1678
+ symmetric when `c` is a Chebyshev basis polynomial. This provides
1679
+ better eigenvalue estimates than the unscaled case and for basis
1680
+ polynomials the eigenvalues are guaranteed to be real if
1681
+ `numpy.linalg.eigvalsh` is used to obtain them.
1682
+
1683
+ Parameters
1684
+ ----------
1685
+ c : array_like
1686
+ 1-D array of Chebyshev series coefficients ordered from low to high
1687
+ degree.
1688
+
1689
+ Returns
1690
+ -------
1691
+ mat : ndarray
1692
+ Scaled companion matrix of dimensions (deg, deg).
1693
+
1694
+ Notes
1695
+ -----
1696
+
1697
+ .. versionadded:: 1.7.0
1698
+
1699
+ """
1700
+ # c is a trimmed copy
1701
+ [c] = pu.as_series([c])
1702
+ if len(c) < 2:
1703
+ raise ValueError('Series must have maximum degree of at least 1.')
1704
+ if len(c) == 2:
1705
+ return np.array([[-c[0]/c[1]]])
1706
+
1707
+ n = len(c) - 1
1708
+ mat = np.zeros((n, n), dtype=c.dtype)
1709
+ scl = np.array([1.] + [np.sqrt(.5)]*(n-1))
1710
+ top = mat.reshape(-1)[1::n+1]
1711
+ bot = mat.reshape(-1)[n::n+1]
1712
+ top[0] = np.sqrt(.5)
1713
+ top[1:] = 1/2
1714
+ bot[...] = top
1715
+ mat[:, -1] -= (c[:-1]/c[-1])*(scl/scl[-1])*.5
1716
+ return mat
1717
+
1718
+
1719
+ def chebroots(c):
1720
+ """
1721
+ Compute the roots of a Chebyshev series.
1722
+
1723
+ Return the roots (a.k.a. "zeros") of the polynomial
1724
+
1725
+ .. math:: p(x) = \\sum_i c[i] * T_i(x).
1726
+
1727
+ Parameters
1728
+ ----------
1729
+ c : 1-D array_like
1730
+ 1-D array of coefficients.
1731
+
1732
+ Returns
1733
+ -------
1734
+ out : ndarray
1735
+ Array of the roots of the series. If all the roots are real,
1736
+ then `out` is also real, otherwise it is complex.
1737
+
1738
+ See Also
1739
+ --------
1740
+ numpy.polynomial.polynomial.polyroots
1741
+ numpy.polynomial.legendre.legroots
1742
+ numpy.polynomial.laguerre.lagroots
1743
+ numpy.polynomial.hermite.hermroots
1744
+ numpy.polynomial.hermite_e.hermeroots
1745
+
1746
+ Notes
1747
+ -----
1748
+ The root estimates are obtained as the eigenvalues of the companion
1749
+ matrix, Roots far from the origin of the complex plane may have large
1750
+ errors due to the numerical instability of the series for such
1751
+ values. Roots with multiplicity greater than 1 will also show larger
1752
+ errors as the value of the series near such points is relatively
1753
+ insensitive to errors in the roots. Isolated roots near the origin can
1754
+ be improved by a few iterations of Newton's method.
1755
+
1756
+ The Chebyshev series basis polynomials aren't powers of `x` so the
1757
+ results of this function may seem unintuitive.
1758
+
1759
+ Examples
1760
+ --------
1761
+ >>> import numpy.polynomial.chebyshev as cheb
1762
+ >>> cheb.chebroots((-1, 1,-1, 1)) # T3 - T2 + T1 - T0 has real roots
1763
+ array([ -5.00000000e-01, 2.60860684e-17, 1.00000000e+00]) # may vary
1764
+
1765
+ """
1766
+ # c is a trimmed copy
1767
+ [c] = pu.as_series([c])
1768
+ if len(c) < 2:
1769
+ return np.array([], dtype=c.dtype)
1770
+ if len(c) == 2:
1771
+ return np.array([-c[0]/c[1]])
1772
+
1773
+ # rotated companion matrix reduces error
1774
+ m = chebcompanion(c)[::-1,::-1]
1775
+ r = la.eigvals(m)
1776
+ r.sort()
1777
+ return r
1778
+
1779
+
1780
+ def chebinterpolate(func, deg, args=()):
1781
+ """Interpolate a function at the Chebyshev points of the first kind.
1782
+
1783
+ Returns the Chebyshev series that interpolates `func` at the Chebyshev
1784
+ points of the first kind in the interval [-1, 1]. The interpolating
1785
+ series tends to a minmax approximation to `func` with increasing `deg`
1786
+ if the function is continuous in the interval.
1787
+
1788
+ .. versionadded:: 1.14.0
1789
+
1790
+ Parameters
1791
+ ----------
1792
+ func : function
1793
+ The function to be approximated. It must be a function of a single
1794
+ variable of the form ``f(x, a, b, c...)``, where ``a, b, c...`` are
1795
+ extra arguments passed in the `args` parameter.
1796
+ deg : int
1797
+ Degree of the interpolating polynomial
1798
+ args : tuple, optional
1799
+ Extra arguments to be used in the function call. Default is no extra
1800
+ arguments.
1801
+
1802
+ Returns
1803
+ -------
1804
+ coef : ndarray, shape (deg + 1,)
1805
+ Chebyshev coefficients of the interpolating series ordered from low to
1806
+ high.
1807
+
1808
+ Examples
1809
+ --------
1810
+ >>> import numpy.polynomial.chebyshev as C
1811
+ >>> C.chebfromfunction(lambda x: np.tanh(x) + 0.5, 8)
1812
+ array([ 5.00000000e-01, 8.11675684e-01, -9.86864911e-17,
1813
+ -5.42457905e-02, -2.71387850e-16, 4.51658839e-03,
1814
+ 2.46716228e-17, -3.79694221e-04, -3.26899002e-16])
1815
+
1816
+ Notes
1817
+ -----
1818
+
1819
+ The Chebyshev polynomials used in the interpolation are orthogonal when
1820
+ sampled at the Chebyshev points of the first kind. If it is desired to
1821
+ constrain some of the coefficients they can simply be set to the desired
1822
+ value after the interpolation, no new interpolation or fit is needed. This
1823
+ is especially useful if it is known apriori that some of coefficients are
1824
+ zero. For instance, if the function is even then the coefficients of the
1825
+ terms of odd degree in the result can be set to zero.
1826
+
1827
+ """
1828
+ deg = np.asarray(deg)
1829
+
1830
+ # check arguments.
1831
+ if deg.ndim > 0 or deg.dtype.kind not in 'iu' or deg.size == 0:
1832
+ raise TypeError("deg must be an int")
1833
+ if deg < 0:
1834
+ raise ValueError("expected deg >= 0")
1835
+
1836
+ order = deg + 1
1837
+ xcheb = chebpts1(order)
1838
+ yfunc = func(xcheb, *args)
1839
+ m = chebvander(xcheb, deg)
1840
+ c = np.dot(m.T, yfunc)
1841
+ c[0] /= order
1842
+ c[1:] /= 0.5*order
1843
+
1844
+ return c
1845
+
1846
+
1847
+ def chebgauss(deg):
1848
+ """
1849
+ Gauss-Chebyshev quadrature.
1850
+
1851
+ Computes the sample points and weights for Gauss-Chebyshev quadrature.
1852
+ These sample points and weights will correctly integrate polynomials of
1853
+ degree :math:`2*deg - 1` or less over the interval :math:`[-1, 1]` with
1854
+ the weight function :math:`f(x) = 1/\\sqrt{1 - x^2}`.
1855
+
1856
+ Parameters
1857
+ ----------
1858
+ deg : int
1859
+ Number of sample points and weights. It must be >= 1.
1860
+
1861
+ Returns
1862
+ -------
1863
+ x : ndarray
1864
+ 1-D ndarray containing the sample points.
1865
+ y : ndarray
1866
+ 1-D ndarray containing the weights.
1867
+
1868
+ Notes
1869
+ -----
1870
+
1871
+ .. versionadded:: 1.7.0
1872
+
1873
+ The results have only been tested up to degree 100, higher degrees may
1874
+ be problematic. For Gauss-Chebyshev there are closed form solutions for
1875
+ the sample points and weights. If n = `deg`, then
1876
+
1877
+ .. math:: x_i = \\cos(\\pi (2 i - 1) / (2 n))
1878
+
1879
+ .. math:: w_i = \\pi / n
1880
+
1881
+ """
1882
+ ideg = pu._deprecate_as_int(deg, "deg")
1883
+ if ideg <= 0:
1884
+ raise ValueError("deg must be a positive integer")
1885
+
1886
+ x = np.cos(np.pi * np.arange(1, 2*ideg, 2) / (2.0*ideg))
1887
+ w = np.ones(ideg)*(np.pi/ideg)
1888
+
1889
+ return x, w
1890
+
1891
+
1892
+ def chebweight(x):
1893
+ """
1894
+ The weight function of the Chebyshev polynomials.
1895
+
1896
+ The weight function is :math:`1/\\sqrt{1 - x^2}` and the interval of
1897
+ integration is :math:`[-1, 1]`. The Chebyshev polynomials are
1898
+ orthogonal, but not normalized, with respect to this weight function.
1899
+
1900
+ Parameters
1901
+ ----------
1902
+ x : array_like
1903
+ Values at which the weight function will be computed.
1904
+
1905
+ Returns
1906
+ -------
1907
+ w : ndarray
1908
+ The weight function at `x`.
1909
+
1910
+ Notes
1911
+ -----
1912
+
1913
+ .. versionadded:: 1.7.0
1914
+
1915
+ """
1916
+ w = 1./(np.sqrt(1. + x) * np.sqrt(1. - x))
1917
+ return w
1918
+
1919
+
1920
+ def chebpts1(npts):
1921
+ """
1922
+ Chebyshev points of the first kind.
1923
+
1924
+ The Chebyshev points of the first kind are the points ``cos(x)``,
1925
+ where ``x = [pi*(k + .5)/npts for k in range(npts)]``.
1926
+
1927
+ Parameters
1928
+ ----------
1929
+ npts : int
1930
+ Number of sample points desired.
1931
+
1932
+ Returns
1933
+ -------
1934
+ pts : ndarray
1935
+ The Chebyshev points of the first kind.
1936
+
1937
+ See Also
1938
+ --------
1939
+ chebpts2
1940
+
1941
+ Notes
1942
+ -----
1943
+
1944
+ .. versionadded:: 1.5.0
1945
+
1946
+ """
1947
+ _npts = int(npts)
1948
+ if _npts != npts:
1949
+ raise ValueError("npts must be integer")
1950
+ if _npts < 1:
1951
+ raise ValueError("npts must be >= 1")
1952
+
1953
+ x = 0.5 * np.pi / _npts * np.arange(-_npts+1, _npts+1, 2)
1954
+ return np.sin(x)
1955
+
1956
+
1957
+ def chebpts2(npts):
1958
+ """
1959
+ Chebyshev points of the second kind.
1960
+
1961
+ The Chebyshev points of the second kind are the points ``cos(x)``,
1962
+ where ``x = [pi*k/(npts - 1) for k in range(npts)]`` sorted in ascending
1963
+ order.
1964
+
1965
+ Parameters
1966
+ ----------
1967
+ npts : int
1968
+ Number of sample points desired.
1969
+
1970
+ Returns
1971
+ -------
1972
+ pts : ndarray
1973
+ The Chebyshev points of the second kind.
1974
+
1975
+ Notes
1976
+ -----
1977
+
1978
+ .. versionadded:: 1.5.0
1979
+
1980
+ """
1981
+ _npts = int(npts)
1982
+ if _npts != npts:
1983
+ raise ValueError("npts must be integer")
1984
+ if _npts < 2:
1985
+ raise ValueError("npts must be >= 2")
1986
+
1987
+ x = np.linspace(-np.pi, 0, _npts)
1988
+ return np.cos(x)
1989
+
1990
+
1991
+ #
1992
+ # Chebyshev series class
1993
+ #
1994
+
1995
+ class Chebyshev(ABCPolyBase):
1996
+ """A Chebyshev series class.
1997
+
1998
+ The Chebyshev class provides the standard Python numerical methods
1999
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
2000
+ methods listed below.
2001
+
2002
+ Parameters
2003
+ ----------
2004
+ coef : array_like
2005
+ Chebyshev coefficients in order of increasing degree, i.e.,
2006
+ ``(1, 2, 3)`` gives ``1*T_0(x) + 2*T_1(x) + 3*T_2(x)``.
2007
+ domain : (2,) array_like, optional
2008
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
2009
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
2010
+ The default value is [-1, 1].
2011
+ window : (2,) array_like, optional
2012
+ Window, see `domain` for its use. The default value is [-1, 1].
2013
+
2014
+ .. versionadded:: 1.6.0
2015
+ symbol : str, optional
2016
+ Symbol used to represent the independent variable in string
2017
+ representations of the polynomial expression, e.g. for printing.
2018
+ The symbol must be a valid Python identifier. Default value is 'x'.
2019
+
2020
+ .. versionadded:: 1.24
2021
+
2022
+ """
2023
+ # Virtual Functions
2024
+ _add = staticmethod(chebadd)
2025
+ _sub = staticmethod(chebsub)
2026
+ _mul = staticmethod(chebmul)
2027
+ _div = staticmethod(chebdiv)
2028
+ _pow = staticmethod(chebpow)
2029
+ _val = staticmethod(chebval)
2030
+ _int = staticmethod(chebint)
2031
+ _der = staticmethod(chebder)
2032
+ _fit = staticmethod(chebfit)
2033
+ _line = staticmethod(chebline)
2034
+ _roots = staticmethod(chebroots)
2035
+ _fromroots = staticmethod(chebfromroots)
2036
+
2037
+ @classmethod
2038
+ def interpolate(cls, func, deg, domain=None, args=()):
2039
+ """Interpolate a function at the Chebyshev points of the first kind.
2040
+
2041
+ Returns the series that interpolates `func` at the Chebyshev points of
2042
+ the first kind scaled and shifted to the `domain`. The resulting series
2043
+ tends to a minmax approximation of `func` when the function is
2044
+ continuous in the domain.
2045
+
2046
+ .. versionadded:: 1.14.0
2047
+
2048
+ Parameters
2049
+ ----------
2050
+ func : function
2051
+ The function to be interpolated. It must be a function of a single
2052
+ variable of the form ``f(x, a, b, c...)``, where ``a, b, c...`` are
2053
+ extra arguments passed in the `args` parameter.
2054
+ deg : int
2055
+ Degree of the interpolating polynomial.
2056
+ domain : {None, [beg, end]}, optional
2057
+ Domain over which `func` is interpolated. The default is None, in
2058
+ which case the domain is [-1, 1].
2059
+ args : tuple, optional
2060
+ Extra arguments to be used in the function call. Default is no
2061
+ extra arguments.
2062
+
2063
+ Returns
2064
+ -------
2065
+ polynomial : Chebyshev instance
2066
+ Interpolating Chebyshev instance.
2067
+
2068
+ Notes
2069
+ -----
2070
+ See `numpy.polynomial.chebfromfunction` for more details.
2071
+
2072
+ """
2073
+ if domain is None:
2074
+ domain = cls.domain
2075
+ xfunc = lambda x: func(pu.mapdomain(x, cls.window, domain), *args)
2076
+ coef = chebinterpolate(xfunc, deg)
2077
+ return cls(coef, domain=domain)
2078
+
2079
+ # Virtual properties
2080
+ domain = np.array(chebdomain)
2081
+ window = np.array(chebdomain)
2082
+ basis_name = 'T'
lib/python3.12/site-packages/numpy/polynomial/chebyshev.pyi ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any
2
+
3
+ from numpy import ndarray, dtype, int_
4
+ from numpy.polynomial._polybase import ABCPolyBase
5
+ from numpy.polynomial.polyutils import trimcoef
6
+
7
+ __all__: list[str]
8
+
9
+ chebtrim = trimcoef
10
+
11
+ def poly2cheb(pol): ...
12
+ def cheb2poly(c): ...
13
+
14
+ chebdomain: ndarray[Any, dtype[int_]]
15
+ chebzero: ndarray[Any, dtype[int_]]
16
+ chebone: ndarray[Any, dtype[int_]]
17
+ chebx: ndarray[Any, dtype[int_]]
18
+
19
+ def chebline(off, scl): ...
20
+ def chebfromroots(roots): ...
21
+ def chebadd(c1, c2): ...
22
+ def chebsub(c1, c2): ...
23
+ def chebmulx(c): ...
24
+ def chebmul(c1, c2): ...
25
+ def chebdiv(c1, c2): ...
26
+ def chebpow(c, pow, maxpower=...): ...
27
+ def chebder(c, m=..., scl=..., axis=...): ...
28
+ def chebint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
29
+ def chebval(x, c, tensor=...): ...
30
+ def chebval2d(x, y, c): ...
31
+ def chebgrid2d(x, y, c): ...
32
+ def chebval3d(x, y, z, c): ...
33
+ def chebgrid3d(x, y, z, c): ...
34
+ def chebvander(x, deg): ...
35
+ def chebvander2d(x, y, deg): ...
36
+ def chebvander3d(x, y, z, deg): ...
37
+ def chebfit(x, y, deg, rcond=..., full=..., w=...): ...
38
+ def chebcompanion(c): ...
39
+ def chebroots(c): ...
40
+ def chebinterpolate(func, deg, args = ...): ...
41
+ def chebgauss(deg): ...
42
+ def chebweight(x): ...
43
+ def chebpts1(npts): ...
44
+ def chebpts2(npts): ...
45
+
46
+ class Chebyshev(ABCPolyBase):
47
+ @classmethod
48
+ def interpolate(cls, func, deg, domain=..., args = ...): ...
49
+ domain: Any
50
+ window: Any
51
+ basis_name: Any
lib/python3.12/site-packages/numpy/polynomial/hermite.py ADDED
@@ -0,0 +1,1703 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ==============================================================
3
+ Hermite Series, "Physicists" (:mod:`numpy.polynomial.hermite`)
4
+ ==============================================================
5
+
6
+ This module provides a number of objects (mostly functions) useful for
7
+ dealing with Hermite series, including a `Hermite` class that
8
+ encapsulates the usual arithmetic operations. (General information
9
+ on how this module represents and works with such polynomials is in the
10
+ docstring for its "parent" sub-package, `numpy.polynomial`).
11
+
12
+ Classes
13
+ -------
14
+ .. autosummary::
15
+ :toctree: generated/
16
+
17
+ Hermite
18
+
19
+ Constants
20
+ ---------
21
+ .. autosummary::
22
+ :toctree: generated/
23
+
24
+ hermdomain
25
+ hermzero
26
+ hermone
27
+ hermx
28
+
29
+ Arithmetic
30
+ ----------
31
+ .. autosummary::
32
+ :toctree: generated/
33
+
34
+ hermadd
35
+ hermsub
36
+ hermmulx
37
+ hermmul
38
+ hermdiv
39
+ hermpow
40
+ hermval
41
+ hermval2d
42
+ hermval3d
43
+ hermgrid2d
44
+ hermgrid3d
45
+
46
+ Calculus
47
+ --------
48
+ .. autosummary::
49
+ :toctree: generated/
50
+
51
+ hermder
52
+ hermint
53
+
54
+ Misc Functions
55
+ --------------
56
+ .. autosummary::
57
+ :toctree: generated/
58
+
59
+ hermfromroots
60
+ hermroots
61
+ hermvander
62
+ hermvander2d
63
+ hermvander3d
64
+ hermgauss
65
+ hermweight
66
+ hermcompanion
67
+ hermfit
68
+ hermtrim
69
+ hermline
70
+ herm2poly
71
+ poly2herm
72
+
73
+ See also
74
+ --------
75
+ `numpy.polynomial`
76
+
77
+ """
78
+ import numpy as np
79
+ import numpy.linalg as la
80
+ from numpy.core.multiarray import normalize_axis_index
81
+
82
+ from . import polyutils as pu
83
+ from ._polybase import ABCPolyBase
84
+
85
+ __all__ = [
86
+ 'hermzero', 'hermone', 'hermx', 'hermdomain', 'hermline', 'hermadd',
87
+ 'hermsub', 'hermmulx', 'hermmul', 'hermdiv', 'hermpow', 'hermval',
88
+ 'hermder', 'hermint', 'herm2poly', 'poly2herm', 'hermfromroots',
89
+ 'hermvander', 'hermfit', 'hermtrim', 'hermroots', 'Hermite',
90
+ 'hermval2d', 'hermval3d', 'hermgrid2d', 'hermgrid3d', 'hermvander2d',
91
+ 'hermvander3d', 'hermcompanion', 'hermgauss', 'hermweight']
92
+
93
+ hermtrim = pu.trimcoef
94
+
95
+
96
+ def poly2herm(pol):
97
+ """
98
+ poly2herm(pol)
99
+
100
+ Convert a polynomial to a Hermite series.
101
+
102
+ Convert an array representing the coefficients of a polynomial (relative
103
+ to the "standard" basis) ordered from lowest degree to highest, to an
104
+ array of the coefficients of the equivalent Hermite series, ordered
105
+ from lowest to highest degree.
106
+
107
+ Parameters
108
+ ----------
109
+ pol : array_like
110
+ 1-D array containing the polynomial coefficients
111
+
112
+ Returns
113
+ -------
114
+ c : ndarray
115
+ 1-D array containing the coefficients of the equivalent Hermite
116
+ series.
117
+
118
+ See Also
119
+ --------
120
+ herm2poly
121
+
122
+ Notes
123
+ -----
124
+ The easy way to do conversions between polynomial basis sets
125
+ is to use the convert method of a class instance.
126
+
127
+ Examples
128
+ --------
129
+ >>> from numpy.polynomial.hermite import poly2herm
130
+ >>> poly2herm(np.arange(4))
131
+ array([1. , 2.75 , 0.5 , 0.375])
132
+
133
+ """
134
+ [pol] = pu.as_series([pol])
135
+ deg = len(pol) - 1
136
+ res = 0
137
+ for i in range(deg, -1, -1):
138
+ res = hermadd(hermmulx(res), pol[i])
139
+ return res
140
+
141
+
142
+ def herm2poly(c):
143
+ """
144
+ Convert a Hermite series to a polynomial.
145
+
146
+ Convert an array representing the coefficients of a Hermite series,
147
+ ordered from lowest degree to highest, to an array of the coefficients
148
+ of the equivalent polynomial (relative to the "standard" basis) ordered
149
+ from lowest to highest degree.
150
+
151
+ Parameters
152
+ ----------
153
+ c : array_like
154
+ 1-D array containing the Hermite series coefficients, ordered
155
+ from lowest order term to highest.
156
+
157
+ Returns
158
+ -------
159
+ pol : ndarray
160
+ 1-D array containing the coefficients of the equivalent polynomial
161
+ (relative to the "standard" basis) ordered from lowest order term
162
+ to highest.
163
+
164
+ See Also
165
+ --------
166
+ poly2herm
167
+
168
+ Notes
169
+ -----
170
+ The easy way to do conversions between polynomial basis sets
171
+ is to use the convert method of a class instance.
172
+
173
+ Examples
174
+ --------
175
+ >>> from numpy.polynomial.hermite import herm2poly
176
+ >>> herm2poly([ 1. , 2.75 , 0.5 , 0.375])
177
+ array([0., 1., 2., 3.])
178
+
179
+ """
180
+ from .polynomial import polyadd, polysub, polymulx
181
+
182
+ [c] = pu.as_series([c])
183
+ n = len(c)
184
+ if n == 1:
185
+ return c
186
+ if n == 2:
187
+ c[1] *= 2
188
+ return c
189
+ else:
190
+ c0 = c[-2]
191
+ c1 = c[-1]
192
+ # i is the current degree of c1
193
+ for i in range(n - 1, 1, -1):
194
+ tmp = c0
195
+ c0 = polysub(c[i - 2], c1*(2*(i - 1)))
196
+ c1 = polyadd(tmp, polymulx(c1)*2)
197
+ return polyadd(c0, polymulx(c1)*2)
198
+
199
+ #
200
+ # These are constant arrays are of integer type so as to be compatible
201
+ # with the widest range of other types, such as Decimal.
202
+ #
203
+
204
+ # Hermite
205
+ hermdomain = np.array([-1, 1])
206
+
207
+ # Hermite coefficients representing zero.
208
+ hermzero = np.array([0])
209
+
210
+ # Hermite coefficients representing one.
211
+ hermone = np.array([1])
212
+
213
+ # Hermite coefficients representing the identity x.
214
+ hermx = np.array([0, 1/2])
215
+
216
+
217
+ def hermline(off, scl):
218
+ """
219
+ Hermite series whose graph is a straight line.
220
+
221
+
222
+
223
+ Parameters
224
+ ----------
225
+ off, scl : scalars
226
+ The specified line is given by ``off + scl*x``.
227
+
228
+ Returns
229
+ -------
230
+ y : ndarray
231
+ This module's representation of the Hermite series for
232
+ ``off + scl*x``.
233
+
234
+ See Also
235
+ --------
236
+ numpy.polynomial.polynomial.polyline
237
+ numpy.polynomial.chebyshev.chebline
238
+ numpy.polynomial.legendre.legline
239
+ numpy.polynomial.laguerre.lagline
240
+ numpy.polynomial.hermite_e.hermeline
241
+
242
+ Examples
243
+ --------
244
+ >>> from numpy.polynomial.hermite import hermline, hermval
245
+ >>> hermval(0,hermline(3, 2))
246
+ 3.0
247
+ >>> hermval(1,hermline(3, 2))
248
+ 5.0
249
+
250
+ """
251
+ if scl != 0:
252
+ return np.array([off, scl/2])
253
+ else:
254
+ return np.array([off])
255
+
256
+
257
+ def hermfromroots(roots):
258
+ """
259
+ Generate a Hermite series with given roots.
260
+
261
+ The function returns the coefficients of the polynomial
262
+
263
+ .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
264
+
265
+ in Hermite form, where the `r_n` are the roots specified in `roots`.
266
+ If a zero has multiplicity n, then it must appear in `roots` n times.
267
+ For instance, if 2 is a root of multiplicity three and 3 is a root of
268
+ multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3]. The
269
+ roots can appear in any order.
270
+
271
+ If the returned coefficients are `c`, then
272
+
273
+ .. math:: p(x) = c_0 + c_1 * H_1(x) + ... + c_n * H_n(x)
274
+
275
+ The coefficient of the last term is not generally 1 for monic
276
+ polynomials in Hermite form.
277
+
278
+ Parameters
279
+ ----------
280
+ roots : array_like
281
+ Sequence containing the roots.
282
+
283
+ Returns
284
+ -------
285
+ out : ndarray
286
+ 1-D array of coefficients. If all roots are real then `out` is a
287
+ real array, if some of the roots are complex, then `out` is complex
288
+ even if all the coefficients in the result are real (see Examples
289
+ below).
290
+
291
+ See Also
292
+ --------
293
+ numpy.polynomial.polynomial.polyfromroots
294
+ numpy.polynomial.legendre.legfromroots
295
+ numpy.polynomial.laguerre.lagfromroots
296
+ numpy.polynomial.chebyshev.chebfromroots
297
+ numpy.polynomial.hermite_e.hermefromroots
298
+
299
+ Examples
300
+ --------
301
+ >>> from numpy.polynomial.hermite import hermfromroots, hermval
302
+ >>> coef = hermfromroots((-1, 0, 1))
303
+ >>> hermval((-1, 0, 1), coef)
304
+ array([0., 0., 0.])
305
+ >>> coef = hermfromroots((-1j, 1j))
306
+ >>> hermval((-1j, 1j), coef)
307
+ array([0.+0.j, 0.+0.j])
308
+
309
+ """
310
+ return pu._fromroots(hermline, hermmul, roots)
311
+
312
+
313
+ def hermadd(c1, c2):
314
+ """
315
+ Add one Hermite series to another.
316
+
317
+ Returns the sum of two Hermite series `c1` + `c2`. The arguments
318
+ are sequences of coefficients ordered from lowest order term to
319
+ highest, i.e., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
320
+
321
+ Parameters
322
+ ----------
323
+ c1, c2 : array_like
324
+ 1-D arrays of Hermite series coefficients ordered from low to
325
+ high.
326
+
327
+ Returns
328
+ -------
329
+ out : ndarray
330
+ Array representing the Hermite series of their sum.
331
+
332
+ See Also
333
+ --------
334
+ hermsub, hermmulx, hermmul, hermdiv, hermpow
335
+
336
+ Notes
337
+ -----
338
+ Unlike multiplication, division, etc., the sum of two Hermite series
339
+ is a Hermite series (without having to "reproject" the result onto
340
+ the basis set) so addition, just like that of "standard" polynomials,
341
+ is simply "component-wise."
342
+
343
+ Examples
344
+ --------
345
+ >>> from numpy.polynomial.hermite import hermadd
346
+ >>> hermadd([1, 2, 3], [1, 2, 3, 4])
347
+ array([2., 4., 6., 4.])
348
+
349
+ """
350
+ return pu._add(c1, c2)
351
+
352
+
353
+ def hermsub(c1, c2):
354
+ """
355
+ Subtract one Hermite series from another.
356
+
357
+ Returns the difference of two Hermite series `c1` - `c2`. The
358
+ sequences of coefficients are from lowest order term to highest, i.e.,
359
+ [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
360
+
361
+ Parameters
362
+ ----------
363
+ c1, c2 : array_like
364
+ 1-D arrays of Hermite series coefficients ordered from low to
365
+ high.
366
+
367
+ Returns
368
+ -------
369
+ out : ndarray
370
+ Of Hermite series coefficients representing their difference.
371
+
372
+ See Also
373
+ --------
374
+ hermadd, hermmulx, hermmul, hermdiv, hermpow
375
+
376
+ Notes
377
+ -----
378
+ Unlike multiplication, division, etc., the difference of two Hermite
379
+ series is a Hermite series (without having to "reproject" the result
380
+ onto the basis set) so subtraction, just like that of "standard"
381
+ polynomials, is simply "component-wise."
382
+
383
+ Examples
384
+ --------
385
+ >>> from numpy.polynomial.hermite import hermsub
386
+ >>> hermsub([1, 2, 3, 4], [1, 2, 3])
387
+ array([0., 0., 0., 4.])
388
+
389
+ """
390
+ return pu._sub(c1, c2)
391
+
392
+
393
+ def hermmulx(c):
394
+ """Multiply a Hermite series by x.
395
+
396
+ Multiply the Hermite series `c` by x, where x is the independent
397
+ variable.
398
+
399
+
400
+ Parameters
401
+ ----------
402
+ c : array_like
403
+ 1-D array of Hermite series coefficients ordered from low to
404
+ high.
405
+
406
+ Returns
407
+ -------
408
+ out : ndarray
409
+ Array representing the result of the multiplication.
410
+
411
+ See Also
412
+ --------
413
+ hermadd, hermsub, hermmul, hermdiv, hermpow
414
+
415
+ Notes
416
+ -----
417
+ The multiplication uses the recursion relationship for Hermite
418
+ polynomials in the form
419
+
420
+ .. math::
421
+
422
+ xP_i(x) = (P_{i + 1}(x)/2 + i*P_{i - 1}(x))
423
+
424
+ Examples
425
+ --------
426
+ >>> from numpy.polynomial.hermite import hermmulx
427
+ >>> hermmulx([1, 2, 3])
428
+ array([2. , 6.5, 1. , 1.5])
429
+
430
+ """
431
+ # c is a trimmed copy
432
+ [c] = pu.as_series([c])
433
+ # The zero series needs special treatment
434
+ if len(c) == 1 and c[0] == 0:
435
+ return c
436
+
437
+ prd = np.empty(len(c) + 1, dtype=c.dtype)
438
+ prd[0] = c[0]*0
439
+ prd[1] = c[0]/2
440
+ for i in range(1, len(c)):
441
+ prd[i + 1] = c[i]/2
442
+ prd[i - 1] += c[i]*i
443
+ return prd
444
+
445
+
446
+ def hermmul(c1, c2):
447
+ """
448
+ Multiply one Hermite series by another.
449
+
450
+ Returns the product of two Hermite series `c1` * `c2`. The arguments
451
+ are sequences of coefficients, from lowest order "term" to highest,
452
+ e.g., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
453
+
454
+ Parameters
455
+ ----------
456
+ c1, c2 : array_like
457
+ 1-D arrays of Hermite series coefficients ordered from low to
458
+ high.
459
+
460
+ Returns
461
+ -------
462
+ out : ndarray
463
+ Of Hermite series coefficients representing their product.
464
+
465
+ See Also
466
+ --------
467
+ hermadd, hermsub, hermmulx, hermdiv, hermpow
468
+
469
+ Notes
470
+ -----
471
+ In general, the (polynomial) product of two C-series results in terms
472
+ that are not in the Hermite polynomial basis set. Thus, to express
473
+ the product as a Hermite series, it is necessary to "reproject" the
474
+ product onto said basis set, which may produce "unintuitive" (but
475
+ correct) results; see Examples section below.
476
+
477
+ Examples
478
+ --------
479
+ >>> from numpy.polynomial.hermite import hermmul
480
+ >>> hermmul([1, 2, 3], [0, 1, 2])
481
+ array([52., 29., 52., 7., 6.])
482
+
483
+ """
484
+ # s1, s2 are trimmed copies
485
+ [c1, c2] = pu.as_series([c1, c2])
486
+
487
+ if len(c1) > len(c2):
488
+ c = c2
489
+ xs = c1
490
+ else:
491
+ c = c1
492
+ xs = c2
493
+
494
+ if len(c) == 1:
495
+ c0 = c[0]*xs
496
+ c1 = 0
497
+ elif len(c) == 2:
498
+ c0 = c[0]*xs
499
+ c1 = c[1]*xs
500
+ else:
501
+ nd = len(c)
502
+ c0 = c[-2]*xs
503
+ c1 = c[-1]*xs
504
+ for i in range(3, len(c) + 1):
505
+ tmp = c0
506
+ nd = nd - 1
507
+ c0 = hermsub(c[-i]*xs, c1*(2*(nd - 1)))
508
+ c1 = hermadd(tmp, hermmulx(c1)*2)
509
+ return hermadd(c0, hermmulx(c1)*2)
510
+
511
+
512
+ def hermdiv(c1, c2):
513
+ """
514
+ Divide one Hermite series by another.
515
+
516
+ Returns the quotient-with-remainder of two Hermite series
517
+ `c1` / `c2`. The arguments are sequences of coefficients from lowest
518
+ order "term" to highest, e.g., [1,2,3] represents the series
519
+ ``P_0 + 2*P_1 + 3*P_2``.
520
+
521
+ Parameters
522
+ ----------
523
+ c1, c2 : array_like
524
+ 1-D arrays of Hermite series coefficients ordered from low to
525
+ high.
526
+
527
+ Returns
528
+ -------
529
+ [quo, rem] : ndarrays
530
+ Of Hermite series coefficients representing the quotient and
531
+ remainder.
532
+
533
+ See Also
534
+ --------
535
+ hermadd, hermsub, hermmulx, hermmul, hermpow
536
+
537
+ Notes
538
+ -----
539
+ In general, the (polynomial) division of one Hermite series by another
540
+ results in quotient and remainder terms that are not in the Hermite
541
+ polynomial basis set. Thus, to express these results as a Hermite
542
+ series, it is necessary to "reproject" the results onto the Hermite
543
+ basis set, which may produce "unintuitive" (but correct) results; see
544
+ Examples section below.
545
+
546
+ Examples
547
+ --------
548
+ >>> from numpy.polynomial.hermite import hermdiv
549
+ >>> hermdiv([ 52., 29., 52., 7., 6.], [0, 1, 2])
550
+ (array([1., 2., 3.]), array([0.]))
551
+ >>> hermdiv([ 54., 31., 52., 7., 6.], [0, 1, 2])
552
+ (array([1., 2., 3.]), array([2., 2.]))
553
+ >>> hermdiv([ 53., 30., 52., 7., 6.], [0, 1, 2])
554
+ (array([1., 2., 3.]), array([1., 1.]))
555
+
556
+ """
557
+ return pu._div(hermmul, c1, c2)
558
+
559
+
560
+ def hermpow(c, pow, maxpower=16):
561
+ """Raise a Hermite series to a power.
562
+
563
+ Returns the Hermite series `c` raised to the power `pow`. The
564
+ argument `c` is a sequence of coefficients ordered from low to high.
565
+ i.e., [1,2,3] is the series ``P_0 + 2*P_1 + 3*P_2.``
566
+
567
+ Parameters
568
+ ----------
569
+ c : array_like
570
+ 1-D array of Hermite series coefficients ordered from low to
571
+ high.
572
+ pow : integer
573
+ Power to which the series will be raised
574
+ maxpower : integer, optional
575
+ Maximum power allowed. This is mainly to limit growth of the series
576
+ to unmanageable size. Default is 16
577
+
578
+ Returns
579
+ -------
580
+ coef : ndarray
581
+ Hermite series of power.
582
+
583
+ See Also
584
+ --------
585
+ hermadd, hermsub, hermmulx, hermmul, hermdiv
586
+
587
+ Examples
588
+ --------
589
+ >>> from numpy.polynomial.hermite import hermpow
590
+ >>> hermpow([1, 2, 3], 2)
591
+ array([81., 52., 82., 12., 9.])
592
+
593
+ """
594
+ return pu._pow(hermmul, c, pow, maxpower)
595
+
596
+
597
+ def hermder(c, m=1, scl=1, axis=0):
598
+ """
599
+ Differentiate a Hermite series.
600
+
601
+ Returns the Hermite series coefficients `c` differentiated `m` times
602
+ along `axis`. At each iteration the result is multiplied by `scl` (the
603
+ scaling factor is for use in a linear change of variable). The argument
604
+ `c` is an array of coefficients from low to high degree along each
605
+ axis, e.g., [1,2,3] represents the series ``1*H_0 + 2*H_1 + 3*H_2``
606
+ while [[1,2],[1,2]] represents ``1*H_0(x)*H_0(y) + 1*H_1(x)*H_0(y) +
607
+ 2*H_0(x)*H_1(y) + 2*H_1(x)*H_1(y)`` if axis=0 is ``x`` and axis=1 is
608
+ ``y``.
609
+
610
+ Parameters
611
+ ----------
612
+ c : array_like
613
+ Array of Hermite series coefficients. If `c` is multidimensional the
614
+ different axis correspond to different variables with the degree in
615
+ each axis given by the corresponding index.
616
+ m : int, optional
617
+ Number of derivatives taken, must be non-negative. (Default: 1)
618
+ scl : scalar, optional
619
+ Each differentiation is multiplied by `scl`. The end result is
620
+ multiplication by ``scl**m``. This is for use in a linear change of
621
+ variable. (Default: 1)
622
+ axis : int, optional
623
+ Axis over which the derivative is taken. (Default: 0).
624
+
625
+ .. versionadded:: 1.7.0
626
+
627
+ Returns
628
+ -------
629
+ der : ndarray
630
+ Hermite series of the derivative.
631
+
632
+ See Also
633
+ --------
634
+ hermint
635
+
636
+ Notes
637
+ -----
638
+ In general, the result of differentiating a Hermite series does not
639
+ resemble the same operation on a power series. Thus the result of this
640
+ function may be "unintuitive," albeit correct; see Examples section
641
+ below.
642
+
643
+ Examples
644
+ --------
645
+ >>> from numpy.polynomial.hermite import hermder
646
+ >>> hermder([ 1. , 0.5, 0.5, 0.5])
647
+ array([1., 2., 3.])
648
+ >>> hermder([-0.5, 1./2., 1./8., 1./12., 1./16.], m=2)
649
+ array([1., 2., 3.])
650
+
651
+ """
652
+ c = np.array(c, ndmin=1, copy=True)
653
+ if c.dtype.char in '?bBhHiIlLqQpP':
654
+ c = c.astype(np.double)
655
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
656
+ iaxis = pu._deprecate_as_int(axis, "the axis")
657
+ if cnt < 0:
658
+ raise ValueError("The order of derivation must be non-negative")
659
+ iaxis = normalize_axis_index(iaxis, c.ndim)
660
+
661
+ if cnt == 0:
662
+ return c
663
+
664
+ c = np.moveaxis(c, iaxis, 0)
665
+ n = len(c)
666
+ if cnt >= n:
667
+ c = c[:1]*0
668
+ else:
669
+ for i in range(cnt):
670
+ n = n - 1
671
+ c *= scl
672
+ der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
673
+ for j in range(n, 0, -1):
674
+ der[j - 1] = (2*j)*c[j]
675
+ c = der
676
+ c = np.moveaxis(c, 0, iaxis)
677
+ return c
678
+
679
+
680
+ def hermint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
681
+ """
682
+ Integrate a Hermite series.
683
+
684
+ Returns the Hermite series coefficients `c` integrated `m` times from
685
+ `lbnd` along `axis`. At each iteration the resulting series is
686
+ **multiplied** by `scl` and an integration constant, `k`, is added.
687
+ The scaling factor is for use in a linear change of variable. ("Buyer
688
+ beware": note that, depending on what one is doing, one may want `scl`
689
+ to be the reciprocal of what one might expect; for more information,
690
+ see the Notes section below.) The argument `c` is an array of
691
+ coefficients from low to high degree along each axis, e.g., [1,2,3]
692
+ represents the series ``H_0 + 2*H_1 + 3*H_2`` while [[1,2],[1,2]]
693
+ represents ``1*H_0(x)*H_0(y) + 1*H_1(x)*H_0(y) + 2*H_0(x)*H_1(y) +
694
+ 2*H_1(x)*H_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
695
+
696
+ Parameters
697
+ ----------
698
+ c : array_like
699
+ Array of Hermite series coefficients. If c is multidimensional the
700
+ different axis correspond to different variables with the degree in
701
+ each axis given by the corresponding index.
702
+ m : int, optional
703
+ Order of integration, must be positive. (Default: 1)
704
+ k : {[], list, scalar}, optional
705
+ Integration constant(s). The value of the first integral at
706
+ ``lbnd`` is the first value in the list, the value of the second
707
+ integral at ``lbnd`` is the second value, etc. If ``k == []`` (the
708
+ default), all constants are set to zero. If ``m == 1``, a single
709
+ scalar can be given instead of a list.
710
+ lbnd : scalar, optional
711
+ The lower bound of the integral. (Default: 0)
712
+ scl : scalar, optional
713
+ Following each integration the result is *multiplied* by `scl`
714
+ before the integration constant is added. (Default: 1)
715
+ axis : int, optional
716
+ Axis over which the integral is taken. (Default: 0).
717
+
718
+ .. versionadded:: 1.7.0
719
+
720
+ Returns
721
+ -------
722
+ S : ndarray
723
+ Hermite series coefficients of the integral.
724
+
725
+ Raises
726
+ ------
727
+ ValueError
728
+ If ``m < 0``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
729
+ ``np.ndim(scl) != 0``.
730
+
731
+ See Also
732
+ --------
733
+ hermder
734
+
735
+ Notes
736
+ -----
737
+ Note that the result of each integration is *multiplied* by `scl`.
738
+ Why is this important to note? Say one is making a linear change of
739
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
740
+ :math:`dx = du/a`, so one will need to set `scl` equal to
741
+ :math:`1/a` - perhaps not what one would have first thought.
742
+
743
+ Also note that, in general, the result of integrating a C-series needs
744
+ to be "reprojected" onto the C-series basis set. Thus, typically,
745
+ the result of this function is "unintuitive," albeit correct; see
746
+ Examples section below.
747
+
748
+ Examples
749
+ --------
750
+ >>> from numpy.polynomial.hermite import hermint
751
+ >>> hermint([1,2,3]) # integrate once, value 0 at 0.
752
+ array([1. , 0.5, 0.5, 0.5])
753
+ >>> hermint([1,2,3], m=2) # integrate twice, value & deriv 0 at 0
754
+ array([-0.5 , 0.5 , 0.125 , 0.08333333, 0.0625 ]) # may vary
755
+ >>> hermint([1,2,3], k=1) # integrate once, value 1 at 0.
756
+ array([2. , 0.5, 0.5, 0.5])
757
+ >>> hermint([1,2,3], lbnd=-1) # integrate once, value 0 at -1
758
+ array([-2. , 0.5, 0.5, 0.5])
759
+ >>> hermint([1,2,3], m=2, k=[1,2], lbnd=-1)
760
+ array([ 1.66666667, -0.5 , 0.125 , 0.08333333, 0.0625 ]) # may vary
761
+
762
+ """
763
+ c = np.array(c, ndmin=1, copy=True)
764
+ if c.dtype.char in '?bBhHiIlLqQpP':
765
+ c = c.astype(np.double)
766
+ if not np.iterable(k):
767
+ k = [k]
768
+ cnt = pu._deprecate_as_int(m, "the order of integration")
769
+ iaxis = pu._deprecate_as_int(axis, "the axis")
770
+ if cnt < 0:
771
+ raise ValueError("The order of integration must be non-negative")
772
+ if len(k) > cnt:
773
+ raise ValueError("Too many integration constants")
774
+ if np.ndim(lbnd) != 0:
775
+ raise ValueError("lbnd must be a scalar.")
776
+ if np.ndim(scl) != 0:
777
+ raise ValueError("scl must be a scalar.")
778
+ iaxis = normalize_axis_index(iaxis, c.ndim)
779
+
780
+ if cnt == 0:
781
+ return c
782
+
783
+ c = np.moveaxis(c, iaxis, 0)
784
+ k = list(k) + [0]*(cnt - len(k))
785
+ for i in range(cnt):
786
+ n = len(c)
787
+ c *= scl
788
+ if n == 1 and np.all(c[0] == 0):
789
+ c[0] += k[i]
790
+ else:
791
+ tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
792
+ tmp[0] = c[0]*0
793
+ tmp[1] = c[0]/2
794
+ for j in range(1, n):
795
+ tmp[j + 1] = c[j]/(2*(j + 1))
796
+ tmp[0] += k[i] - hermval(lbnd, tmp)
797
+ c = tmp
798
+ c = np.moveaxis(c, 0, iaxis)
799
+ return c
800
+
801
+
802
+ def hermval(x, c, tensor=True):
803
+ """
804
+ Evaluate an Hermite series at points x.
805
+
806
+ If `c` is of length `n + 1`, this function returns the value:
807
+
808
+ .. math:: p(x) = c_0 * H_0(x) + c_1 * H_1(x) + ... + c_n * H_n(x)
809
+
810
+ The parameter `x` is converted to an array only if it is a tuple or a
811
+ list, otherwise it is treated as a scalar. In either case, either `x`
812
+ or its elements must support multiplication and addition both with
813
+ themselves and with the elements of `c`.
814
+
815
+ If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
816
+ `c` is multidimensional, then the shape of the result depends on the
817
+ value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
818
+ x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
819
+ scalars have shape (,).
820
+
821
+ Trailing zeros in the coefficients will be used in the evaluation, so
822
+ they should be avoided if efficiency is a concern.
823
+
824
+ Parameters
825
+ ----------
826
+ x : array_like, compatible object
827
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
828
+ it is left unchanged and treated as a scalar. In either case, `x`
829
+ or its elements must support addition and multiplication with
830
+ themselves and with the elements of `c`.
831
+ c : array_like
832
+ Array of coefficients ordered so that the coefficients for terms of
833
+ degree n are contained in c[n]. If `c` is multidimensional the
834
+ remaining indices enumerate multiple polynomials. In the two
835
+ dimensional case the coefficients may be thought of as stored in
836
+ the columns of `c`.
837
+ tensor : boolean, optional
838
+ If True, the shape of the coefficient array is extended with ones
839
+ on the right, one for each dimension of `x`. Scalars have dimension 0
840
+ for this action. The result is that every column of coefficients in
841
+ `c` is evaluated for every element of `x`. If False, `x` is broadcast
842
+ over the columns of `c` for the evaluation. This keyword is useful
843
+ when `c` is multidimensional. The default value is True.
844
+
845
+ .. versionadded:: 1.7.0
846
+
847
+ Returns
848
+ -------
849
+ values : ndarray, algebra_like
850
+ The shape of the return value is described above.
851
+
852
+ See Also
853
+ --------
854
+ hermval2d, hermgrid2d, hermval3d, hermgrid3d
855
+
856
+ Notes
857
+ -----
858
+ The evaluation uses Clenshaw recursion, aka synthetic division.
859
+
860
+ Examples
861
+ --------
862
+ >>> from numpy.polynomial.hermite import hermval
863
+ >>> coef = [1,2,3]
864
+ >>> hermval(1, coef)
865
+ 11.0
866
+ >>> hermval([[1,2],[3,4]], coef)
867
+ array([[ 11., 51.],
868
+ [115., 203.]])
869
+
870
+ """
871
+ c = np.array(c, ndmin=1, copy=False)
872
+ if c.dtype.char in '?bBhHiIlLqQpP':
873
+ c = c.astype(np.double)
874
+ if isinstance(x, (tuple, list)):
875
+ x = np.asarray(x)
876
+ if isinstance(x, np.ndarray) and tensor:
877
+ c = c.reshape(c.shape + (1,)*x.ndim)
878
+
879
+ x2 = x*2
880
+ if len(c) == 1:
881
+ c0 = c[0]
882
+ c1 = 0
883
+ elif len(c) == 2:
884
+ c0 = c[0]
885
+ c1 = c[1]
886
+ else:
887
+ nd = len(c)
888
+ c0 = c[-2]
889
+ c1 = c[-1]
890
+ for i in range(3, len(c) + 1):
891
+ tmp = c0
892
+ nd = nd - 1
893
+ c0 = c[-i] - c1*(2*(nd - 1))
894
+ c1 = tmp + c1*x2
895
+ return c0 + c1*x2
896
+
897
+
898
+ def hermval2d(x, y, c):
899
+ """
900
+ Evaluate a 2-D Hermite series at points (x, y).
901
+
902
+ This function returns the values:
903
+
904
+ .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * H_i(x) * H_j(y)
905
+
906
+ The parameters `x` and `y` are converted to arrays only if they are
907
+ tuples or a lists, otherwise they are treated as a scalars and they
908
+ must have the same shape after conversion. In either case, either `x`
909
+ and `y` or their elements must support multiplication and addition both
910
+ with themselves and with the elements of `c`.
911
+
912
+ If `c` is a 1-D array a one is implicitly appended to its shape to make
913
+ it 2-D. The shape of the result will be c.shape[2:] + x.shape.
914
+
915
+ Parameters
916
+ ----------
917
+ x, y : array_like, compatible objects
918
+ The two dimensional series is evaluated at the points `(x, y)`,
919
+ where `x` and `y` must have the same shape. If `x` or `y` is a list
920
+ or tuple, it is first converted to an ndarray, otherwise it is left
921
+ unchanged and if it isn't an ndarray it is treated as a scalar.
922
+ c : array_like
923
+ Array of coefficients ordered so that the coefficient of the term
924
+ of multi-degree i,j is contained in ``c[i,j]``. If `c` has
925
+ dimension greater than two the remaining indices enumerate multiple
926
+ sets of coefficients.
927
+
928
+ Returns
929
+ -------
930
+ values : ndarray, compatible object
931
+ The values of the two dimensional polynomial at points formed with
932
+ pairs of corresponding values from `x` and `y`.
933
+
934
+ See Also
935
+ --------
936
+ hermval, hermgrid2d, hermval3d, hermgrid3d
937
+
938
+ Notes
939
+ -----
940
+
941
+ .. versionadded:: 1.7.0
942
+
943
+ """
944
+ return pu._valnd(hermval, c, x, y)
945
+
946
+
947
+ def hermgrid2d(x, y, c):
948
+ """
949
+ Evaluate a 2-D Hermite series on the Cartesian product of x and y.
950
+
951
+ This function returns the values:
952
+
953
+ .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * H_i(a) * H_j(b)
954
+
955
+ where the points `(a, b)` consist of all pairs formed by taking
956
+ `a` from `x` and `b` from `y`. The resulting points form a grid with
957
+ `x` in the first dimension and `y` in the second.
958
+
959
+ The parameters `x` and `y` are converted to arrays only if they are
960
+ tuples or a lists, otherwise they are treated as a scalars. In either
961
+ case, either `x` and `y` or their elements must support multiplication
962
+ and addition both with themselves and with the elements of `c`.
963
+
964
+ If `c` has fewer than two dimensions, ones are implicitly appended to
965
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
966
+ x.shape.
967
+
968
+ Parameters
969
+ ----------
970
+ x, y : array_like, compatible objects
971
+ The two dimensional series is evaluated at the points in the
972
+ Cartesian product of `x` and `y`. If `x` or `y` is a list or
973
+ tuple, it is first converted to an ndarray, otherwise it is left
974
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
975
+ c : array_like
976
+ Array of coefficients ordered so that the coefficients for terms of
977
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
978
+ greater than two the remaining indices enumerate multiple sets of
979
+ coefficients.
980
+
981
+ Returns
982
+ -------
983
+ values : ndarray, compatible object
984
+ The values of the two dimensional polynomial at points in the Cartesian
985
+ product of `x` and `y`.
986
+
987
+ See Also
988
+ --------
989
+ hermval, hermval2d, hermval3d, hermgrid3d
990
+
991
+ Notes
992
+ -----
993
+
994
+ .. versionadded:: 1.7.0
995
+
996
+ """
997
+ return pu._gridnd(hermval, c, x, y)
998
+
999
+
1000
+ def hermval3d(x, y, z, c):
1001
+ """
1002
+ Evaluate a 3-D Hermite series at points (x, y, z).
1003
+
1004
+ This function returns the values:
1005
+
1006
+ .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * H_i(x) * H_j(y) * H_k(z)
1007
+
1008
+ The parameters `x`, `y`, and `z` are converted to arrays only if
1009
+ they are tuples or a lists, otherwise they are treated as a scalars and
1010
+ they must have the same shape after conversion. In either case, either
1011
+ `x`, `y`, and `z` or their elements must support multiplication and
1012
+ addition both with themselves and with the elements of `c`.
1013
+
1014
+ If `c` has fewer than 3 dimensions, ones are implicitly appended to its
1015
+ shape to make it 3-D. The shape of the result will be c.shape[3:] +
1016
+ x.shape.
1017
+
1018
+ Parameters
1019
+ ----------
1020
+ x, y, z : array_like, compatible object
1021
+ The three dimensional series is evaluated at the points
1022
+ `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
1023
+ any of `x`, `y`, or `z` is a list or tuple, it is first converted
1024
+ to an ndarray, otherwise it is left unchanged and if it isn't an
1025
+ ndarray it is treated as a scalar.
1026
+ c : array_like
1027
+ Array of coefficients ordered so that the coefficient of the term of
1028
+ multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
1029
+ greater than 3 the remaining indices enumerate multiple sets of
1030
+ coefficients.
1031
+
1032
+ Returns
1033
+ -------
1034
+ values : ndarray, compatible object
1035
+ The values of the multidimensional polynomial on points formed with
1036
+ triples of corresponding values from `x`, `y`, and `z`.
1037
+
1038
+ See Also
1039
+ --------
1040
+ hermval, hermval2d, hermgrid2d, hermgrid3d
1041
+
1042
+ Notes
1043
+ -----
1044
+
1045
+ .. versionadded:: 1.7.0
1046
+
1047
+ """
1048
+ return pu._valnd(hermval, c, x, y, z)
1049
+
1050
+
1051
+ def hermgrid3d(x, y, z, c):
1052
+ """
1053
+ Evaluate a 3-D Hermite series on the Cartesian product of x, y, and z.
1054
+
1055
+ This function returns the values:
1056
+
1057
+ .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * H_i(a) * H_j(b) * H_k(c)
1058
+
1059
+ where the points `(a, b, c)` consist of all triples formed by taking
1060
+ `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
1061
+ a grid with `x` in the first dimension, `y` in the second, and `z` in
1062
+ the third.
1063
+
1064
+ The parameters `x`, `y`, and `z` are converted to arrays only if they
1065
+ are tuples or a lists, otherwise they are treated as a scalars. In
1066
+ either case, either `x`, `y`, and `z` or their elements must support
1067
+ multiplication and addition both with themselves and with the elements
1068
+ of `c`.
1069
+
1070
+ If `c` has fewer than three dimensions, ones are implicitly appended to
1071
+ its shape to make it 3-D. The shape of the result will be c.shape[3:] +
1072
+ x.shape + y.shape + z.shape.
1073
+
1074
+ Parameters
1075
+ ----------
1076
+ x, y, z : array_like, compatible objects
1077
+ The three dimensional series is evaluated at the points in the
1078
+ Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
1079
+ list or tuple, it is first converted to an ndarray, otherwise it is
1080
+ left unchanged and, if it isn't an ndarray, it is treated as a
1081
+ scalar.
1082
+ c : array_like
1083
+ Array of coefficients ordered so that the coefficients for terms of
1084
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
1085
+ greater than two the remaining indices enumerate multiple sets of
1086
+ coefficients.
1087
+
1088
+ Returns
1089
+ -------
1090
+ values : ndarray, compatible object
1091
+ The values of the two dimensional polynomial at points in the Cartesian
1092
+ product of `x` and `y`.
1093
+
1094
+ See Also
1095
+ --------
1096
+ hermval, hermval2d, hermgrid2d, hermval3d
1097
+
1098
+ Notes
1099
+ -----
1100
+
1101
+ .. versionadded:: 1.7.0
1102
+
1103
+ """
1104
+ return pu._gridnd(hermval, c, x, y, z)
1105
+
1106
+
1107
+ def hermvander(x, deg):
1108
+ """Pseudo-Vandermonde matrix of given degree.
1109
+
1110
+ Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
1111
+ `x`. The pseudo-Vandermonde matrix is defined by
1112
+
1113
+ .. math:: V[..., i] = H_i(x),
1114
+
1115
+ where `0 <= i <= deg`. The leading indices of `V` index the elements of
1116
+ `x` and the last index is the degree of the Hermite polynomial.
1117
+
1118
+ If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
1119
+ array ``V = hermvander(x, n)``, then ``np.dot(V, c)`` and
1120
+ ``hermval(x, c)`` are the same up to roundoff. This equivalence is
1121
+ useful both for least squares fitting and for the evaluation of a large
1122
+ number of Hermite series of the same degree and sample points.
1123
+
1124
+ Parameters
1125
+ ----------
1126
+ x : array_like
1127
+ Array of points. The dtype is converted to float64 or complex128
1128
+ depending on whether any of the elements are complex. If `x` is
1129
+ scalar it is converted to a 1-D array.
1130
+ deg : int
1131
+ Degree of the resulting matrix.
1132
+
1133
+ Returns
1134
+ -------
1135
+ vander : ndarray
1136
+ The pseudo-Vandermonde matrix. The shape of the returned matrix is
1137
+ ``x.shape + (deg + 1,)``, where The last index is the degree of the
1138
+ corresponding Hermite polynomial. The dtype will be the same as
1139
+ the converted `x`.
1140
+
1141
+ Examples
1142
+ --------
1143
+ >>> from numpy.polynomial.hermite import hermvander
1144
+ >>> x = np.array([-1, 0, 1])
1145
+ >>> hermvander(x, 3)
1146
+ array([[ 1., -2., 2., 4.],
1147
+ [ 1., 0., -2., -0.],
1148
+ [ 1., 2., 2., -4.]])
1149
+
1150
+ """
1151
+ ideg = pu._deprecate_as_int(deg, "deg")
1152
+ if ideg < 0:
1153
+ raise ValueError("deg must be non-negative")
1154
+
1155
+ x = np.array(x, copy=False, ndmin=1) + 0.0
1156
+ dims = (ideg + 1,) + x.shape
1157
+ dtyp = x.dtype
1158
+ v = np.empty(dims, dtype=dtyp)
1159
+ v[0] = x*0 + 1
1160
+ if ideg > 0:
1161
+ x2 = x*2
1162
+ v[1] = x2
1163
+ for i in range(2, ideg + 1):
1164
+ v[i] = (v[i-1]*x2 - v[i-2]*(2*(i - 1)))
1165
+ return np.moveaxis(v, 0, -1)
1166
+
1167
+
1168
+ def hermvander2d(x, y, deg):
1169
+ """Pseudo-Vandermonde matrix of given degrees.
1170
+
1171
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1172
+ points `(x, y)`. The pseudo-Vandermonde matrix is defined by
1173
+
1174
+ .. math:: V[..., (deg[1] + 1)*i + j] = H_i(x) * H_j(y),
1175
+
1176
+ where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
1177
+ `V` index the points `(x, y)` and the last index encodes the degrees of
1178
+ the Hermite polynomials.
1179
+
1180
+ If ``V = hermvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
1181
+ correspond to the elements of a 2-D coefficient array `c` of shape
1182
+ (xdeg + 1, ydeg + 1) in the order
1183
+
1184
+ .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
1185
+
1186
+ and ``np.dot(V, c.flat)`` and ``hermval2d(x, y, c)`` will be the same
1187
+ up to roundoff. This equivalence is useful both for least squares
1188
+ fitting and for the evaluation of a large number of 2-D Hermite
1189
+ series of the same degrees and sample points.
1190
+
1191
+ Parameters
1192
+ ----------
1193
+ x, y : array_like
1194
+ Arrays of point coordinates, all of the same shape. The dtypes
1195
+ will be converted to either float64 or complex128 depending on
1196
+ whether any of the elements are complex. Scalars are converted to 1-D
1197
+ arrays.
1198
+ deg : list of ints
1199
+ List of maximum degrees of the form [x_deg, y_deg].
1200
+
1201
+ Returns
1202
+ -------
1203
+ vander2d : ndarray
1204
+ The shape of the returned matrix is ``x.shape + (order,)``, where
1205
+ :math:`order = (deg[0]+1)*(deg[1]+1)`. The dtype will be the same
1206
+ as the converted `x` and `y`.
1207
+
1208
+ See Also
1209
+ --------
1210
+ hermvander, hermvander3d, hermval2d, hermval3d
1211
+
1212
+ Notes
1213
+ -----
1214
+
1215
+ .. versionadded:: 1.7.0
1216
+
1217
+ """
1218
+ return pu._vander_nd_flat((hermvander, hermvander), (x, y), deg)
1219
+
1220
+
1221
+ def hermvander3d(x, y, z, deg):
1222
+ """Pseudo-Vandermonde matrix of given degrees.
1223
+
1224
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1225
+ points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
1226
+ then The pseudo-Vandermonde matrix is defined by
1227
+
1228
+ .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = H_i(x)*H_j(y)*H_k(z),
1229
+
1230
+ where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
1231
+ indices of `V` index the points `(x, y, z)` and the last index encodes
1232
+ the degrees of the Hermite polynomials.
1233
+
1234
+ If ``V = hermvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
1235
+ of `V` correspond to the elements of a 3-D coefficient array `c` of
1236
+ shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
1237
+
1238
+ .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
1239
+
1240
+ and ``np.dot(V, c.flat)`` and ``hermval3d(x, y, z, c)`` will be the
1241
+ same up to roundoff. This equivalence is useful both for least squares
1242
+ fitting and for the evaluation of a large number of 3-D Hermite
1243
+ series of the same degrees and sample points.
1244
+
1245
+ Parameters
1246
+ ----------
1247
+ x, y, z : array_like
1248
+ Arrays of point coordinates, all of the same shape. The dtypes will
1249
+ be converted to either float64 or complex128 depending on whether
1250
+ any of the elements are complex. Scalars are converted to 1-D
1251
+ arrays.
1252
+ deg : list of ints
1253
+ List of maximum degrees of the form [x_deg, y_deg, z_deg].
1254
+
1255
+ Returns
1256
+ -------
1257
+ vander3d : ndarray
1258
+ The shape of the returned matrix is ``x.shape + (order,)``, where
1259
+ :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`. The dtype will
1260
+ be the same as the converted `x`, `y`, and `z`.
1261
+
1262
+ See Also
1263
+ --------
1264
+ hermvander, hermvander3d, hermval2d, hermval3d
1265
+
1266
+ Notes
1267
+ -----
1268
+
1269
+ .. versionadded:: 1.7.0
1270
+
1271
+ """
1272
+ return pu._vander_nd_flat((hermvander, hermvander, hermvander), (x, y, z), deg)
1273
+
1274
+
1275
+ def hermfit(x, y, deg, rcond=None, full=False, w=None):
1276
+ """
1277
+ Least squares fit of Hermite series to data.
1278
+
1279
+ Return the coefficients of a Hermite series of degree `deg` that is the
1280
+ least squares fit to the data values `y` given at points `x`. If `y` is
1281
+ 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
1282
+ fits are done, one for each column of `y`, and the resulting
1283
+ coefficients are stored in the corresponding columns of a 2-D return.
1284
+ The fitted polynomial(s) are in the form
1285
+
1286
+ .. math:: p(x) = c_0 + c_1 * H_1(x) + ... + c_n * H_n(x),
1287
+
1288
+ where `n` is `deg`.
1289
+
1290
+ Parameters
1291
+ ----------
1292
+ x : array_like, shape (M,)
1293
+ x-coordinates of the M sample points ``(x[i], y[i])``.
1294
+ y : array_like, shape (M,) or (M, K)
1295
+ y-coordinates of the sample points. Several data sets of sample
1296
+ points sharing the same x-coordinates can be fitted at once by
1297
+ passing in a 2D-array that contains one dataset per column.
1298
+ deg : int or 1-D array_like
1299
+ Degree(s) of the fitting polynomials. If `deg` is a single integer
1300
+ all terms up to and including the `deg`'th term are included in the
1301
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
1302
+ degrees of the terms to include may be used instead.
1303
+ rcond : float, optional
1304
+ Relative condition number of the fit. Singular values smaller than
1305
+ this relative to the largest singular value will be ignored. The
1306
+ default value is len(x)*eps, where eps is the relative precision of
1307
+ the float type, about 2e-16 in most cases.
1308
+ full : bool, optional
1309
+ Switch determining nature of return value. When it is False (the
1310
+ default) just the coefficients are returned, when True diagnostic
1311
+ information from the singular value decomposition is also returned.
1312
+ w : array_like, shape (`M`,), optional
1313
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
1314
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
1315
+ chosen so that the errors of the products ``w[i]*y[i]`` all have the
1316
+ same variance. When using inverse-variance weighting, use
1317
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
1318
+
1319
+ Returns
1320
+ -------
1321
+ coef : ndarray, shape (M,) or (M, K)
1322
+ Hermite coefficients ordered from low to high. If `y` was 2-D,
1323
+ the coefficients for the data in column k of `y` are in column
1324
+ `k`.
1325
+
1326
+ [residuals, rank, singular_values, rcond] : list
1327
+ These values are only returned if ``full == True``
1328
+
1329
+ - residuals -- sum of squared residuals of the least squares fit
1330
+ - rank -- the numerical rank of the scaled Vandermonde matrix
1331
+ - singular_values -- singular values of the scaled Vandermonde matrix
1332
+ - rcond -- value of `rcond`.
1333
+
1334
+ For more details, see `numpy.linalg.lstsq`.
1335
+
1336
+ Warns
1337
+ -----
1338
+ RankWarning
1339
+ The rank of the coefficient matrix in the least-squares fit is
1340
+ deficient. The warning is only raised if ``full == False``. The
1341
+ warnings can be turned off by
1342
+
1343
+ >>> import warnings
1344
+ >>> warnings.simplefilter('ignore', np.RankWarning)
1345
+
1346
+ See Also
1347
+ --------
1348
+ numpy.polynomial.chebyshev.chebfit
1349
+ numpy.polynomial.legendre.legfit
1350
+ numpy.polynomial.laguerre.lagfit
1351
+ numpy.polynomial.polynomial.polyfit
1352
+ numpy.polynomial.hermite_e.hermefit
1353
+ hermval : Evaluates a Hermite series.
1354
+ hermvander : Vandermonde matrix of Hermite series.
1355
+ hermweight : Hermite weight function
1356
+ numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
1357
+ scipy.interpolate.UnivariateSpline : Computes spline fits.
1358
+
1359
+ Notes
1360
+ -----
1361
+ The solution is the coefficients of the Hermite series `p` that
1362
+ minimizes the sum of the weighted squared errors
1363
+
1364
+ .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
1365
+
1366
+ where the :math:`w_j` are the weights. This problem is solved by
1367
+ setting up the (typically) overdetermined matrix equation
1368
+
1369
+ .. math:: V(x) * c = w * y,
1370
+
1371
+ where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the
1372
+ coefficients to be solved for, `w` are the weights, `y` are the
1373
+ observed values. This equation is then solved using the singular value
1374
+ decomposition of `V`.
1375
+
1376
+ If some of the singular values of `V` are so small that they are
1377
+ neglected, then a `RankWarning` will be issued. This means that the
1378
+ coefficient values may be poorly determined. Using a lower order fit
1379
+ will usually get rid of the warning. The `rcond` parameter can also be
1380
+ set to a value smaller than its default, but the resulting fit may be
1381
+ spurious and have large contributions from roundoff error.
1382
+
1383
+ Fits using Hermite series are probably most useful when the data can be
1384
+ approximated by ``sqrt(w(x)) * p(x)``, where `w(x)` is the Hermite
1385
+ weight. In that case the weight ``sqrt(w(x[i]))`` should be used
1386
+ together with data values ``y[i]/sqrt(w(x[i]))``. The weight function is
1387
+ available as `hermweight`.
1388
+
1389
+ References
1390
+ ----------
1391
+ .. [1] Wikipedia, "Curve fitting",
1392
+ https://en.wikipedia.org/wiki/Curve_fitting
1393
+
1394
+ Examples
1395
+ --------
1396
+ >>> from numpy.polynomial.hermite import hermfit, hermval
1397
+ >>> x = np.linspace(-10, 10)
1398
+ >>> err = np.random.randn(len(x))/10
1399
+ >>> y = hermval(x, [1, 2, 3]) + err
1400
+ >>> hermfit(x, y, 2)
1401
+ array([1.0218, 1.9986, 2.9999]) # may vary
1402
+
1403
+ """
1404
+ return pu._fit(hermvander, x, y, deg, rcond, full, w)
1405
+
1406
+
1407
+ def hermcompanion(c):
1408
+ """Return the scaled companion matrix of c.
1409
+
1410
+ The basis polynomials are scaled so that the companion matrix is
1411
+ symmetric when `c` is an Hermite basis polynomial. This provides
1412
+ better eigenvalue estimates than the unscaled case and for basis
1413
+ polynomials the eigenvalues are guaranteed to be real if
1414
+ `numpy.linalg.eigvalsh` is used to obtain them.
1415
+
1416
+ Parameters
1417
+ ----------
1418
+ c : array_like
1419
+ 1-D array of Hermite series coefficients ordered from low to high
1420
+ degree.
1421
+
1422
+ Returns
1423
+ -------
1424
+ mat : ndarray
1425
+ Scaled companion matrix of dimensions (deg, deg).
1426
+
1427
+ Notes
1428
+ -----
1429
+
1430
+ .. versionadded:: 1.7.0
1431
+
1432
+ """
1433
+ # c is a trimmed copy
1434
+ [c] = pu.as_series([c])
1435
+ if len(c) < 2:
1436
+ raise ValueError('Series must have maximum degree of at least 1.')
1437
+ if len(c) == 2:
1438
+ return np.array([[-.5*c[0]/c[1]]])
1439
+
1440
+ n = len(c) - 1
1441
+ mat = np.zeros((n, n), dtype=c.dtype)
1442
+ scl = np.hstack((1., 1./np.sqrt(2.*np.arange(n - 1, 0, -1))))
1443
+ scl = np.multiply.accumulate(scl)[::-1]
1444
+ top = mat.reshape(-1)[1::n+1]
1445
+ bot = mat.reshape(-1)[n::n+1]
1446
+ top[...] = np.sqrt(.5*np.arange(1, n))
1447
+ bot[...] = top
1448
+ mat[:, -1] -= scl*c[:-1]/(2.0*c[-1])
1449
+ return mat
1450
+
1451
+
1452
+ def hermroots(c):
1453
+ """
1454
+ Compute the roots of a Hermite series.
1455
+
1456
+ Return the roots (a.k.a. "zeros") of the polynomial
1457
+
1458
+ .. math:: p(x) = \\sum_i c[i] * H_i(x).
1459
+
1460
+ Parameters
1461
+ ----------
1462
+ c : 1-D array_like
1463
+ 1-D array of coefficients.
1464
+
1465
+ Returns
1466
+ -------
1467
+ out : ndarray
1468
+ Array of the roots of the series. If all the roots are real,
1469
+ then `out` is also real, otherwise it is complex.
1470
+
1471
+ See Also
1472
+ --------
1473
+ numpy.polynomial.polynomial.polyroots
1474
+ numpy.polynomial.legendre.legroots
1475
+ numpy.polynomial.laguerre.lagroots
1476
+ numpy.polynomial.chebyshev.chebroots
1477
+ numpy.polynomial.hermite_e.hermeroots
1478
+
1479
+ Notes
1480
+ -----
1481
+ The root estimates are obtained as the eigenvalues of the companion
1482
+ matrix, Roots far from the origin of the complex plane may have large
1483
+ errors due to the numerical instability of the series for such
1484
+ values. Roots with multiplicity greater than 1 will also show larger
1485
+ errors as the value of the series near such points is relatively
1486
+ insensitive to errors in the roots. Isolated roots near the origin can
1487
+ be improved by a few iterations of Newton's method.
1488
+
1489
+ The Hermite series basis polynomials aren't powers of `x` so the
1490
+ results of this function may seem unintuitive.
1491
+
1492
+ Examples
1493
+ --------
1494
+ >>> from numpy.polynomial.hermite import hermroots, hermfromroots
1495
+ >>> coef = hermfromroots([-1, 0, 1])
1496
+ >>> coef
1497
+ array([0. , 0.25 , 0. , 0.125])
1498
+ >>> hermroots(coef)
1499
+ array([-1.00000000e+00, -1.38777878e-17, 1.00000000e+00])
1500
+
1501
+ """
1502
+ # c is a trimmed copy
1503
+ [c] = pu.as_series([c])
1504
+ if len(c) <= 1:
1505
+ return np.array([], dtype=c.dtype)
1506
+ if len(c) == 2:
1507
+ return np.array([-.5*c[0]/c[1]])
1508
+
1509
+ # rotated companion matrix reduces error
1510
+ m = hermcompanion(c)[::-1,::-1]
1511
+ r = la.eigvals(m)
1512
+ r.sort()
1513
+ return r
1514
+
1515
+
1516
+ def _normed_hermite_n(x, n):
1517
+ """
1518
+ Evaluate a normalized Hermite polynomial.
1519
+
1520
+ Compute the value of the normalized Hermite polynomial of degree ``n``
1521
+ at the points ``x``.
1522
+
1523
+
1524
+ Parameters
1525
+ ----------
1526
+ x : ndarray of double.
1527
+ Points at which to evaluate the function
1528
+ n : int
1529
+ Degree of the normalized Hermite function to be evaluated.
1530
+
1531
+ Returns
1532
+ -------
1533
+ values : ndarray
1534
+ The shape of the return value is described above.
1535
+
1536
+ Notes
1537
+ -----
1538
+ .. versionadded:: 1.10.0
1539
+
1540
+ This function is needed for finding the Gauss points and integration
1541
+ weights for high degrees. The values of the standard Hermite functions
1542
+ overflow when n >= 207.
1543
+
1544
+ """
1545
+ if n == 0:
1546
+ return np.full(x.shape, 1/np.sqrt(np.sqrt(np.pi)))
1547
+
1548
+ c0 = 0.
1549
+ c1 = 1./np.sqrt(np.sqrt(np.pi))
1550
+ nd = float(n)
1551
+ for i in range(n - 1):
1552
+ tmp = c0
1553
+ c0 = -c1*np.sqrt((nd - 1.)/nd)
1554
+ c1 = tmp + c1*x*np.sqrt(2./nd)
1555
+ nd = nd - 1.0
1556
+ return c0 + c1*x*np.sqrt(2)
1557
+
1558
+
1559
+ def hermgauss(deg):
1560
+ """
1561
+ Gauss-Hermite quadrature.
1562
+
1563
+ Computes the sample points and weights for Gauss-Hermite quadrature.
1564
+ These sample points and weights will correctly integrate polynomials of
1565
+ degree :math:`2*deg - 1` or less over the interval :math:`[-\\inf, \\inf]`
1566
+ with the weight function :math:`f(x) = \\exp(-x^2)`.
1567
+
1568
+ Parameters
1569
+ ----------
1570
+ deg : int
1571
+ Number of sample points and weights. It must be >= 1.
1572
+
1573
+ Returns
1574
+ -------
1575
+ x : ndarray
1576
+ 1-D ndarray containing the sample points.
1577
+ y : ndarray
1578
+ 1-D ndarray containing the weights.
1579
+
1580
+ Notes
1581
+ -----
1582
+
1583
+ .. versionadded:: 1.7.0
1584
+
1585
+ The results have only been tested up to degree 100, higher degrees may
1586
+ be problematic. The weights are determined by using the fact that
1587
+
1588
+ .. math:: w_k = c / (H'_n(x_k) * H_{n-1}(x_k))
1589
+
1590
+ where :math:`c` is a constant independent of :math:`k` and :math:`x_k`
1591
+ is the k'th root of :math:`H_n`, and then scaling the results to get
1592
+ the right value when integrating 1.
1593
+
1594
+ """
1595
+ ideg = pu._deprecate_as_int(deg, "deg")
1596
+ if ideg <= 0:
1597
+ raise ValueError("deg must be a positive integer")
1598
+
1599
+ # first approximation of roots. We use the fact that the companion
1600
+ # matrix is symmetric in this case in order to obtain better zeros.
1601
+ c = np.array([0]*deg + [1], dtype=np.float64)
1602
+ m = hermcompanion(c)
1603
+ x = la.eigvalsh(m)
1604
+
1605
+ # improve roots by one application of Newton
1606
+ dy = _normed_hermite_n(x, ideg)
1607
+ df = _normed_hermite_n(x, ideg - 1) * np.sqrt(2*ideg)
1608
+ x -= dy/df
1609
+
1610
+ # compute the weights. We scale the factor to avoid possible numerical
1611
+ # overflow.
1612
+ fm = _normed_hermite_n(x, ideg - 1)
1613
+ fm /= np.abs(fm).max()
1614
+ w = 1/(fm * fm)
1615
+
1616
+ # for Hermite we can also symmetrize
1617
+ w = (w + w[::-1])/2
1618
+ x = (x - x[::-1])/2
1619
+
1620
+ # scale w to get the right value
1621
+ w *= np.sqrt(np.pi) / w.sum()
1622
+
1623
+ return x, w
1624
+
1625
+
1626
+ def hermweight(x):
1627
+ """
1628
+ Weight function of the Hermite polynomials.
1629
+
1630
+ The weight function is :math:`\\exp(-x^2)` and the interval of
1631
+ integration is :math:`[-\\inf, \\inf]`. the Hermite polynomials are
1632
+ orthogonal, but not normalized, with respect to this weight function.
1633
+
1634
+ Parameters
1635
+ ----------
1636
+ x : array_like
1637
+ Values at which the weight function will be computed.
1638
+
1639
+ Returns
1640
+ -------
1641
+ w : ndarray
1642
+ The weight function at `x`.
1643
+
1644
+ Notes
1645
+ -----
1646
+
1647
+ .. versionadded:: 1.7.0
1648
+
1649
+ """
1650
+ w = np.exp(-x**2)
1651
+ return w
1652
+
1653
+
1654
+ #
1655
+ # Hermite series class
1656
+ #
1657
+
1658
+ class Hermite(ABCPolyBase):
1659
+ """An Hermite series class.
1660
+
1661
+ The Hermite class provides the standard Python numerical methods
1662
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
1663
+ attributes and methods listed in the `ABCPolyBase` documentation.
1664
+
1665
+ Parameters
1666
+ ----------
1667
+ coef : array_like
1668
+ Hermite coefficients in order of increasing degree, i.e,
1669
+ ``(1, 2, 3)`` gives ``1*H_0(x) + 2*H_1(X) + 3*H_2(x)``.
1670
+ domain : (2,) array_like, optional
1671
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
1672
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
1673
+ The default value is [-1, 1].
1674
+ window : (2,) array_like, optional
1675
+ Window, see `domain` for its use. The default value is [-1, 1].
1676
+
1677
+ .. versionadded:: 1.6.0
1678
+ symbol : str, optional
1679
+ Symbol used to represent the independent variable in string
1680
+ representations of the polynomial expression, e.g. for printing.
1681
+ The symbol must be a valid Python identifier. Default value is 'x'.
1682
+
1683
+ .. versionadded:: 1.24
1684
+
1685
+ """
1686
+ # Virtual Functions
1687
+ _add = staticmethod(hermadd)
1688
+ _sub = staticmethod(hermsub)
1689
+ _mul = staticmethod(hermmul)
1690
+ _div = staticmethod(hermdiv)
1691
+ _pow = staticmethod(hermpow)
1692
+ _val = staticmethod(hermval)
1693
+ _int = staticmethod(hermint)
1694
+ _der = staticmethod(hermder)
1695
+ _fit = staticmethod(hermfit)
1696
+ _line = staticmethod(hermline)
1697
+ _roots = staticmethod(hermroots)
1698
+ _fromroots = staticmethod(hermfromroots)
1699
+
1700
+ # Virtual properties
1701
+ domain = np.array(hermdomain)
1702
+ window = np.array(hermdomain)
1703
+ basis_name = 'H'
lib/python3.12/site-packages/numpy/polynomial/hermite.pyi ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any
2
+
3
+ from numpy import ndarray, dtype, int_, float_
4
+ from numpy.polynomial._polybase import ABCPolyBase
5
+ from numpy.polynomial.polyutils import trimcoef
6
+
7
+ __all__: list[str]
8
+
9
+ hermtrim = trimcoef
10
+
11
+ def poly2herm(pol): ...
12
+ def herm2poly(c): ...
13
+
14
+ hermdomain: ndarray[Any, dtype[int_]]
15
+ hermzero: ndarray[Any, dtype[int_]]
16
+ hermone: ndarray[Any, dtype[int_]]
17
+ hermx: ndarray[Any, dtype[float_]]
18
+
19
+ def hermline(off, scl): ...
20
+ def hermfromroots(roots): ...
21
+ def hermadd(c1, c2): ...
22
+ def hermsub(c1, c2): ...
23
+ def hermmulx(c): ...
24
+ def hermmul(c1, c2): ...
25
+ def hermdiv(c1, c2): ...
26
+ def hermpow(c, pow, maxpower=...): ...
27
+ def hermder(c, m=..., scl=..., axis=...): ...
28
+ def hermint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
29
+ def hermval(x, c, tensor=...): ...
30
+ def hermval2d(x, y, c): ...
31
+ def hermgrid2d(x, y, c): ...
32
+ def hermval3d(x, y, z, c): ...
33
+ def hermgrid3d(x, y, z, c): ...
34
+ def hermvander(x, deg): ...
35
+ def hermvander2d(x, y, deg): ...
36
+ def hermvander3d(x, y, z, deg): ...
37
+ def hermfit(x, y, deg, rcond=..., full=..., w=...): ...
38
+ def hermcompanion(c): ...
39
+ def hermroots(c): ...
40
+ def hermgauss(deg): ...
41
+ def hermweight(x): ...
42
+
43
+ class Hermite(ABCPolyBase):
44
+ domain: Any
45
+ window: Any
46
+ basis_name: Any
lib/python3.12/site-packages/numpy/polynomial/hermite_e.py ADDED
@@ -0,0 +1,1695 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ===================================================================
3
+ HermiteE Series, "Probabilists" (:mod:`numpy.polynomial.hermite_e`)
4
+ ===================================================================
5
+
6
+ This module provides a number of objects (mostly functions) useful for
7
+ dealing with Hermite_e series, including a `HermiteE` class that
8
+ encapsulates the usual arithmetic operations. (General information
9
+ on how this module represents and works with such polynomials is in the
10
+ docstring for its "parent" sub-package, `numpy.polynomial`).
11
+
12
+ Classes
13
+ -------
14
+ .. autosummary::
15
+ :toctree: generated/
16
+
17
+ HermiteE
18
+
19
+ Constants
20
+ ---------
21
+ .. autosummary::
22
+ :toctree: generated/
23
+
24
+ hermedomain
25
+ hermezero
26
+ hermeone
27
+ hermex
28
+
29
+ Arithmetic
30
+ ----------
31
+ .. autosummary::
32
+ :toctree: generated/
33
+
34
+ hermeadd
35
+ hermesub
36
+ hermemulx
37
+ hermemul
38
+ hermediv
39
+ hermepow
40
+ hermeval
41
+ hermeval2d
42
+ hermeval3d
43
+ hermegrid2d
44
+ hermegrid3d
45
+
46
+ Calculus
47
+ --------
48
+ .. autosummary::
49
+ :toctree: generated/
50
+
51
+ hermeder
52
+ hermeint
53
+
54
+ Misc Functions
55
+ --------------
56
+ .. autosummary::
57
+ :toctree: generated/
58
+
59
+ hermefromroots
60
+ hermeroots
61
+ hermevander
62
+ hermevander2d
63
+ hermevander3d
64
+ hermegauss
65
+ hermeweight
66
+ hermecompanion
67
+ hermefit
68
+ hermetrim
69
+ hermeline
70
+ herme2poly
71
+ poly2herme
72
+
73
+ See also
74
+ --------
75
+ `numpy.polynomial`
76
+
77
+ """
78
+ import numpy as np
79
+ import numpy.linalg as la
80
+ from numpy.core.multiarray import normalize_axis_index
81
+
82
+ from . import polyutils as pu
83
+ from ._polybase import ABCPolyBase
84
+
85
+ __all__ = [
86
+ 'hermezero', 'hermeone', 'hermex', 'hermedomain', 'hermeline',
87
+ 'hermeadd', 'hermesub', 'hermemulx', 'hermemul', 'hermediv',
88
+ 'hermepow', 'hermeval', 'hermeder', 'hermeint', 'herme2poly',
89
+ 'poly2herme', 'hermefromroots', 'hermevander', 'hermefit', 'hermetrim',
90
+ 'hermeroots', 'HermiteE', 'hermeval2d', 'hermeval3d', 'hermegrid2d',
91
+ 'hermegrid3d', 'hermevander2d', 'hermevander3d', 'hermecompanion',
92
+ 'hermegauss', 'hermeweight']
93
+
94
+ hermetrim = pu.trimcoef
95
+
96
+
97
+ def poly2herme(pol):
98
+ """
99
+ poly2herme(pol)
100
+
101
+ Convert a polynomial to a Hermite series.
102
+
103
+ Convert an array representing the coefficients of a polynomial (relative
104
+ to the "standard" basis) ordered from lowest degree to highest, to an
105
+ array of the coefficients of the equivalent Hermite series, ordered
106
+ from lowest to highest degree.
107
+
108
+ Parameters
109
+ ----------
110
+ pol : array_like
111
+ 1-D array containing the polynomial coefficients
112
+
113
+ Returns
114
+ -------
115
+ c : ndarray
116
+ 1-D array containing the coefficients of the equivalent Hermite
117
+ series.
118
+
119
+ See Also
120
+ --------
121
+ herme2poly
122
+
123
+ Notes
124
+ -----
125
+ The easy way to do conversions between polynomial basis sets
126
+ is to use the convert method of a class instance.
127
+
128
+ Examples
129
+ --------
130
+ >>> from numpy.polynomial.hermite_e import poly2herme
131
+ >>> poly2herme(np.arange(4))
132
+ array([ 2., 10., 2., 3.])
133
+
134
+ """
135
+ [pol] = pu.as_series([pol])
136
+ deg = len(pol) - 1
137
+ res = 0
138
+ for i in range(deg, -1, -1):
139
+ res = hermeadd(hermemulx(res), pol[i])
140
+ return res
141
+
142
+
143
+ def herme2poly(c):
144
+ """
145
+ Convert a Hermite series to a polynomial.
146
+
147
+ Convert an array representing the coefficients of a Hermite series,
148
+ ordered from lowest degree to highest, to an array of the coefficients
149
+ of the equivalent polynomial (relative to the "standard" basis) ordered
150
+ from lowest to highest degree.
151
+
152
+ Parameters
153
+ ----------
154
+ c : array_like
155
+ 1-D array containing the Hermite series coefficients, ordered
156
+ from lowest order term to highest.
157
+
158
+ Returns
159
+ -------
160
+ pol : ndarray
161
+ 1-D array containing the coefficients of the equivalent polynomial
162
+ (relative to the "standard" basis) ordered from lowest order term
163
+ to highest.
164
+
165
+ See Also
166
+ --------
167
+ poly2herme
168
+
169
+ Notes
170
+ -----
171
+ The easy way to do conversions between polynomial basis sets
172
+ is to use the convert method of a class instance.
173
+
174
+ Examples
175
+ --------
176
+ >>> from numpy.polynomial.hermite_e import herme2poly
177
+ >>> herme2poly([ 2., 10., 2., 3.])
178
+ array([0., 1., 2., 3.])
179
+
180
+ """
181
+ from .polynomial import polyadd, polysub, polymulx
182
+
183
+ [c] = pu.as_series([c])
184
+ n = len(c)
185
+ if n == 1:
186
+ return c
187
+ if n == 2:
188
+ return c
189
+ else:
190
+ c0 = c[-2]
191
+ c1 = c[-1]
192
+ # i is the current degree of c1
193
+ for i in range(n - 1, 1, -1):
194
+ tmp = c0
195
+ c0 = polysub(c[i - 2], c1*(i - 1))
196
+ c1 = polyadd(tmp, polymulx(c1))
197
+ return polyadd(c0, polymulx(c1))
198
+
199
+ #
200
+ # These are constant arrays are of integer type so as to be compatible
201
+ # with the widest range of other types, such as Decimal.
202
+ #
203
+
204
+ # Hermite
205
+ hermedomain = np.array([-1, 1])
206
+
207
+ # Hermite coefficients representing zero.
208
+ hermezero = np.array([0])
209
+
210
+ # Hermite coefficients representing one.
211
+ hermeone = np.array([1])
212
+
213
+ # Hermite coefficients representing the identity x.
214
+ hermex = np.array([0, 1])
215
+
216
+
217
+ def hermeline(off, scl):
218
+ """
219
+ Hermite series whose graph is a straight line.
220
+
221
+ Parameters
222
+ ----------
223
+ off, scl : scalars
224
+ The specified line is given by ``off + scl*x``.
225
+
226
+ Returns
227
+ -------
228
+ y : ndarray
229
+ This module's representation of the Hermite series for
230
+ ``off + scl*x``.
231
+
232
+ See Also
233
+ --------
234
+ numpy.polynomial.polynomial.polyline
235
+ numpy.polynomial.chebyshev.chebline
236
+ numpy.polynomial.legendre.legline
237
+ numpy.polynomial.laguerre.lagline
238
+ numpy.polynomial.hermite.hermline
239
+
240
+ Examples
241
+ --------
242
+ >>> from numpy.polynomial.hermite_e import hermeline
243
+ >>> from numpy.polynomial.hermite_e import hermeline, hermeval
244
+ >>> hermeval(0,hermeline(3, 2))
245
+ 3.0
246
+ >>> hermeval(1,hermeline(3, 2))
247
+ 5.0
248
+
249
+ """
250
+ if scl != 0:
251
+ return np.array([off, scl])
252
+ else:
253
+ return np.array([off])
254
+
255
+
256
+ def hermefromroots(roots):
257
+ """
258
+ Generate a HermiteE series with given roots.
259
+
260
+ The function returns the coefficients of the polynomial
261
+
262
+ .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
263
+
264
+ in HermiteE form, where the `r_n` are the roots specified in `roots`.
265
+ If a zero has multiplicity n, then it must appear in `roots` n times.
266
+ For instance, if 2 is a root of multiplicity three and 3 is a root of
267
+ multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3]. The
268
+ roots can appear in any order.
269
+
270
+ If the returned coefficients are `c`, then
271
+
272
+ .. math:: p(x) = c_0 + c_1 * He_1(x) + ... + c_n * He_n(x)
273
+
274
+ The coefficient of the last term is not generally 1 for monic
275
+ polynomials in HermiteE form.
276
+
277
+ Parameters
278
+ ----------
279
+ roots : array_like
280
+ Sequence containing the roots.
281
+
282
+ Returns
283
+ -------
284
+ out : ndarray
285
+ 1-D array of coefficients. If all roots are real then `out` is a
286
+ real array, if some of the roots are complex, then `out` is complex
287
+ even if all the coefficients in the result are real (see Examples
288
+ below).
289
+
290
+ See Also
291
+ --------
292
+ numpy.polynomial.polynomial.polyfromroots
293
+ numpy.polynomial.legendre.legfromroots
294
+ numpy.polynomial.laguerre.lagfromroots
295
+ numpy.polynomial.hermite.hermfromroots
296
+ numpy.polynomial.chebyshev.chebfromroots
297
+
298
+ Examples
299
+ --------
300
+ >>> from numpy.polynomial.hermite_e import hermefromroots, hermeval
301
+ >>> coef = hermefromroots((-1, 0, 1))
302
+ >>> hermeval((-1, 0, 1), coef)
303
+ array([0., 0., 0.])
304
+ >>> coef = hermefromroots((-1j, 1j))
305
+ >>> hermeval((-1j, 1j), coef)
306
+ array([0.+0.j, 0.+0.j])
307
+
308
+ """
309
+ return pu._fromroots(hermeline, hermemul, roots)
310
+
311
+
312
+ def hermeadd(c1, c2):
313
+ """
314
+ Add one Hermite series to another.
315
+
316
+ Returns the sum of two Hermite series `c1` + `c2`. The arguments
317
+ are sequences of coefficients ordered from lowest order term to
318
+ highest, i.e., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
319
+
320
+ Parameters
321
+ ----------
322
+ c1, c2 : array_like
323
+ 1-D arrays of Hermite series coefficients ordered from low to
324
+ high.
325
+
326
+ Returns
327
+ -------
328
+ out : ndarray
329
+ Array representing the Hermite series of their sum.
330
+
331
+ See Also
332
+ --------
333
+ hermesub, hermemulx, hermemul, hermediv, hermepow
334
+
335
+ Notes
336
+ -----
337
+ Unlike multiplication, division, etc., the sum of two Hermite series
338
+ is a Hermite series (without having to "reproject" the result onto
339
+ the basis set) so addition, just like that of "standard" polynomials,
340
+ is simply "component-wise."
341
+
342
+ Examples
343
+ --------
344
+ >>> from numpy.polynomial.hermite_e import hermeadd
345
+ >>> hermeadd([1, 2, 3], [1, 2, 3, 4])
346
+ array([2., 4., 6., 4.])
347
+
348
+ """
349
+ return pu._add(c1, c2)
350
+
351
+
352
+ def hermesub(c1, c2):
353
+ """
354
+ Subtract one Hermite series from another.
355
+
356
+ Returns the difference of two Hermite series `c1` - `c2`. The
357
+ sequences of coefficients are from lowest order term to highest, i.e.,
358
+ [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
359
+
360
+ Parameters
361
+ ----------
362
+ c1, c2 : array_like
363
+ 1-D arrays of Hermite series coefficients ordered from low to
364
+ high.
365
+
366
+ Returns
367
+ -------
368
+ out : ndarray
369
+ Of Hermite series coefficients representing their difference.
370
+
371
+ See Also
372
+ --------
373
+ hermeadd, hermemulx, hermemul, hermediv, hermepow
374
+
375
+ Notes
376
+ -----
377
+ Unlike multiplication, division, etc., the difference of two Hermite
378
+ series is a Hermite series (without having to "reproject" the result
379
+ onto the basis set) so subtraction, just like that of "standard"
380
+ polynomials, is simply "component-wise."
381
+
382
+ Examples
383
+ --------
384
+ >>> from numpy.polynomial.hermite_e import hermesub
385
+ >>> hermesub([1, 2, 3, 4], [1, 2, 3])
386
+ array([0., 0., 0., 4.])
387
+
388
+ """
389
+ return pu._sub(c1, c2)
390
+
391
+
392
+ def hermemulx(c):
393
+ """Multiply a Hermite series by x.
394
+
395
+ Multiply the Hermite series `c` by x, where x is the independent
396
+ variable.
397
+
398
+
399
+ Parameters
400
+ ----------
401
+ c : array_like
402
+ 1-D array of Hermite series coefficients ordered from low to
403
+ high.
404
+
405
+ Returns
406
+ -------
407
+ out : ndarray
408
+ Array representing the result of the multiplication.
409
+
410
+ Notes
411
+ -----
412
+ The multiplication uses the recursion relationship for Hermite
413
+ polynomials in the form
414
+
415
+ .. math::
416
+
417
+ xP_i(x) = (P_{i + 1}(x) + iP_{i - 1}(x)))
418
+
419
+ Examples
420
+ --------
421
+ >>> from numpy.polynomial.hermite_e import hermemulx
422
+ >>> hermemulx([1, 2, 3])
423
+ array([2., 7., 2., 3.])
424
+
425
+ """
426
+ # c is a trimmed copy
427
+ [c] = pu.as_series([c])
428
+ # The zero series needs special treatment
429
+ if len(c) == 1 and c[0] == 0:
430
+ return c
431
+
432
+ prd = np.empty(len(c) + 1, dtype=c.dtype)
433
+ prd[0] = c[0]*0
434
+ prd[1] = c[0]
435
+ for i in range(1, len(c)):
436
+ prd[i + 1] = c[i]
437
+ prd[i - 1] += c[i]*i
438
+ return prd
439
+
440
+
441
+ def hermemul(c1, c2):
442
+ """
443
+ Multiply one Hermite series by another.
444
+
445
+ Returns the product of two Hermite series `c1` * `c2`. The arguments
446
+ are sequences of coefficients, from lowest order "term" to highest,
447
+ e.g., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
448
+
449
+ Parameters
450
+ ----------
451
+ c1, c2 : array_like
452
+ 1-D arrays of Hermite series coefficients ordered from low to
453
+ high.
454
+
455
+ Returns
456
+ -------
457
+ out : ndarray
458
+ Of Hermite series coefficients representing their product.
459
+
460
+ See Also
461
+ --------
462
+ hermeadd, hermesub, hermemulx, hermediv, hermepow
463
+
464
+ Notes
465
+ -----
466
+ In general, the (polynomial) product of two C-series results in terms
467
+ that are not in the Hermite polynomial basis set. Thus, to express
468
+ the product as a Hermite series, it is necessary to "reproject" the
469
+ product onto said basis set, which may produce "unintuitive" (but
470
+ correct) results; see Examples section below.
471
+
472
+ Examples
473
+ --------
474
+ >>> from numpy.polynomial.hermite_e import hermemul
475
+ >>> hermemul([1, 2, 3], [0, 1, 2])
476
+ array([14., 15., 28., 7., 6.])
477
+
478
+ """
479
+ # s1, s2 are trimmed copies
480
+ [c1, c2] = pu.as_series([c1, c2])
481
+
482
+ if len(c1) > len(c2):
483
+ c = c2
484
+ xs = c1
485
+ else:
486
+ c = c1
487
+ xs = c2
488
+
489
+ if len(c) == 1:
490
+ c0 = c[0]*xs
491
+ c1 = 0
492
+ elif len(c) == 2:
493
+ c0 = c[0]*xs
494
+ c1 = c[1]*xs
495
+ else:
496
+ nd = len(c)
497
+ c0 = c[-2]*xs
498
+ c1 = c[-1]*xs
499
+ for i in range(3, len(c) + 1):
500
+ tmp = c0
501
+ nd = nd - 1
502
+ c0 = hermesub(c[-i]*xs, c1*(nd - 1))
503
+ c1 = hermeadd(tmp, hermemulx(c1))
504
+ return hermeadd(c0, hermemulx(c1))
505
+
506
+
507
+ def hermediv(c1, c2):
508
+ """
509
+ Divide one Hermite series by another.
510
+
511
+ Returns the quotient-with-remainder of two Hermite series
512
+ `c1` / `c2`. The arguments are sequences of coefficients from lowest
513
+ order "term" to highest, e.g., [1,2,3] represents the series
514
+ ``P_0 + 2*P_1 + 3*P_2``.
515
+
516
+ Parameters
517
+ ----------
518
+ c1, c2 : array_like
519
+ 1-D arrays of Hermite series coefficients ordered from low to
520
+ high.
521
+
522
+ Returns
523
+ -------
524
+ [quo, rem] : ndarrays
525
+ Of Hermite series coefficients representing the quotient and
526
+ remainder.
527
+
528
+ See Also
529
+ --------
530
+ hermeadd, hermesub, hermemulx, hermemul, hermepow
531
+
532
+ Notes
533
+ -----
534
+ In general, the (polynomial) division of one Hermite series by another
535
+ results in quotient and remainder terms that are not in the Hermite
536
+ polynomial basis set. Thus, to express these results as a Hermite
537
+ series, it is necessary to "reproject" the results onto the Hermite
538
+ basis set, which may produce "unintuitive" (but correct) results; see
539
+ Examples section below.
540
+
541
+ Examples
542
+ --------
543
+ >>> from numpy.polynomial.hermite_e import hermediv
544
+ >>> hermediv([ 14., 15., 28., 7., 6.], [0, 1, 2])
545
+ (array([1., 2., 3.]), array([0.]))
546
+ >>> hermediv([ 15., 17., 28., 7., 6.], [0, 1, 2])
547
+ (array([1., 2., 3.]), array([1., 2.]))
548
+
549
+ """
550
+ return pu._div(hermemul, c1, c2)
551
+
552
+
553
+ def hermepow(c, pow, maxpower=16):
554
+ """Raise a Hermite series to a power.
555
+
556
+ Returns the Hermite series `c` raised to the power `pow`. The
557
+ argument `c` is a sequence of coefficients ordered from low to high.
558
+ i.e., [1,2,3] is the series ``P_0 + 2*P_1 + 3*P_2.``
559
+
560
+ Parameters
561
+ ----------
562
+ c : array_like
563
+ 1-D array of Hermite series coefficients ordered from low to
564
+ high.
565
+ pow : integer
566
+ Power to which the series will be raised
567
+ maxpower : integer, optional
568
+ Maximum power allowed. This is mainly to limit growth of the series
569
+ to unmanageable size. Default is 16
570
+
571
+ Returns
572
+ -------
573
+ coef : ndarray
574
+ Hermite series of power.
575
+
576
+ See Also
577
+ --------
578
+ hermeadd, hermesub, hermemulx, hermemul, hermediv
579
+
580
+ Examples
581
+ --------
582
+ >>> from numpy.polynomial.hermite_e import hermepow
583
+ >>> hermepow([1, 2, 3], 2)
584
+ array([23., 28., 46., 12., 9.])
585
+
586
+ """
587
+ return pu._pow(hermemul, c, pow, maxpower)
588
+
589
+
590
+ def hermeder(c, m=1, scl=1, axis=0):
591
+ """
592
+ Differentiate a Hermite_e series.
593
+
594
+ Returns the series coefficients `c` differentiated `m` times along
595
+ `axis`. At each iteration the result is multiplied by `scl` (the
596
+ scaling factor is for use in a linear change of variable). The argument
597
+ `c` is an array of coefficients from low to high degree along each
598
+ axis, e.g., [1,2,3] represents the series ``1*He_0 + 2*He_1 + 3*He_2``
599
+ while [[1,2],[1,2]] represents ``1*He_0(x)*He_0(y) + 1*He_1(x)*He_0(y)
600
+ + 2*He_0(x)*He_1(y) + 2*He_1(x)*He_1(y)`` if axis=0 is ``x`` and axis=1
601
+ is ``y``.
602
+
603
+ Parameters
604
+ ----------
605
+ c : array_like
606
+ Array of Hermite_e series coefficients. If `c` is multidimensional
607
+ the different axis correspond to different variables with the
608
+ degree in each axis given by the corresponding index.
609
+ m : int, optional
610
+ Number of derivatives taken, must be non-negative. (Default: 1)
611
+ scl : scalar, optional
612
+ Each differentiation is multiplied by `scl`. The end result is
613
+ multiplication by ``scl**m``. This is for use in a linear change of
614
+ variable. (Default: 1)
615
+ axis : int, optional
616
+ Axis over which the derivative is taken. (Default: 0).
617
+
618
+ .. versionadded:: 1.7.0
619
+
620
+ Returns
621
+ -------
622
+ der : ndarray
623
+ Hermite series of the derivative.
624
+
625
+ See Also
626
+ --------
627
+ hermeint
628
+
629
+ Notes
630
+ -----
631
+ In general, the result of differentiating a Hermite series does not
632
+ resemble the same operation on a power series. Thus the result of this
633
+ function may be "unintuitive," albeit correct; see Examples section
634
+ below.
635
+
636
+ Examples
637
+ --------
638
+ >>> from numpy.polynomial.hermite_e import hermeder
639
+ >>> hermeder([ 1., 1., 1., 1.])
640
+ array([1., 2., 3.])
641
+ >>> hermeder([-0.25, 1., 1./2., 1./3., 1./4 ], m=2)
642
+ array([1., 2., 3.])
643
+
644
+ """
645
+ c = np.array(c, ndmin=1, copy=True)
646
+ if c.dtype.char in '?bBhHiIlLqQpP':
647
+ c = c.astype(np.double)
648
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
649
+ iaxis = pu._deprecate_as_int(axis, "the axis")
650
+ if cnt < 0:
651
+ raise ValueError("The order of derivation must be non-negative")
652
+ iaxis = normalize_axis_index(iaxis, c.ndim)
653
+
654
+ if cnt == 0:
655
+ return c
656
+
657
+ c = np.moveaxis(c, iaxis, 0)
658
+ n = len(c)
659
+ if cnt >= n:
660
+ return c[:1]*0
661
+ else:
662
+ for i in range(cnt):
663
+ n = n - 1
664
+ c *= scl
665
+ der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
666
+ for j in range(n, 0, -1):
667
+ der[j - 1] = j*c[j]
668
+ c = der
669
+ c = np.moveaxis(c, 0, iaxis)
670
+ return c
671
+
672
+
673
+ def hermeint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
674
+ """
675
+ Integrate a Hermite_e series.
676
+
677
+ Returns the Hermite_e series coefficients `c` integrated `m` times from
678
+ `lbnd` along `axis`. At each iteration the resulting series is
679
+ **multiplied** by `scl` and an integration constant, `k`, is added.
680
+ The scaling factor is for use in a linear change of variable. ("Buyer
681
+ beware": note that, depending on what one is doing, one may want `scl`
682
+ to be the reciprocal of what one might expect; for more information,
683
+ see the Notes section below.) The argument `c` is an array of
684
+ coefficients from low to high degree along each axis, e.g., [1,2,3]
685
+ represents the series ``H_0 + 2*H_1 + 3*H_2`` while [[1,2],[1,2]]
686
+ represents ``1*H_0(x)*H_0(y) + 1*H_1(x)*H_0(y) + 2*H_0(x)*H_1(y) +
687
+ 2*H_1(x)*H_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
688
+
689
+ Parameters
690
+ ----------
691
+ c : array_like
692
+ Array of Hermite_e series coefficients. If c is multidimensional
693
+ the different axis correspond to different variables with the
694
+ degree in each axis given by the corresponding index.
695
+ m : int, optional
696
+ Order of integration, must be positive. (Default: 1)
697
+ k : {[], list, scalar}, optional
698
+ Integration constant(s). The value of the first integral at
699
+ ``lbnd`` is the first value in the list, the value of the second
700
+ integral at ``lbnd`` is the second value, etc. If ``k == []`` (the
701
+ default), all constants are set to zero. If ``m == 1``, a single
702
+ scalar can be given instead of a list.
703
+ lbnd : scalar, optional
704
+ The lower bound of the integral. (Default: 0)
705
+ scl : scalar, optional
706
+ Following each integration the result is *multiplied* by `scl`
707
+ before the integration constant is added. (Default: 1)
708
+ axis : int, optional
709
+ Axis over which the integral is taken. (Default: 0).
710
+
711
+ .. versionadded:: 1.7.0
712
+
713
+ Returns
714
+ -------
715
+ S : ndarray
716
+ Hermite_e series coefficients of the integral.
717
+
718
+ Raises
719
+ ------
720
+ ValueError
721
+ If ``m < 0``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
722
+ ``np.ndim(scl) != 0``.
723
+
724
+ See Also
725
+ --------
726
+ hermeder
727
+
728
+ Notes
729
+ -----
730
+ Note that the result of each integration is *multiplied* by `scl`.
731
+ Why is this important to note? Say one is making a linear change of
732
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
733
+ :math:`dx = du/a`, so one will need to set `scl` equal to
734
+ :math:`1/a` - perhaps not what one would have first thought.
735
+
736
+ Also note that, in general, the result of integrating a C-series needs
737
+ to be "reprojected" onto the C-series basis set. Thus, typically,
738
+ the result of this function is "unintuitive," albeit correct; see
739
+ Examples section below.
740
+
741
+ Examples
742
+ --------
743
+ >>> from numpy.polynomial.hermite_e import hermeint
744
+ >>> hermeint([1, 2, 3]) # integrate once, value 0 at 0.
745
+ array([1., 1., 1., 1.])
746
+ >>> hermeint([1, 2, 3], m=2) # integrate twice, value & deriv 0 at 0
747
+ array([-0.25 , 1. , 0.5 , 0.33333333, 0.25 ]) # may vary
748
+ >>> hermeint([1, 2, 3], k=1) # integrate once, value 1 at 0.
749
+ array([2., 1., 1., 1.])
750
+ >>> hermeint([1, 2, 3], lbnd=-1) # integrate once, value 0 at -1
751
+ array([-1., 1., 1., 1.])
752
+ >>> hermeint([1, 2, 3], m=2, k=[1, 2], lbnd=-1)
753
+ array([ 1.83333333, 0. , 0.5 , 0.33333333, 0.25 ]) # may vary
754
+
755
+ """
756
+ c = np.array(c, ndmin=1, copy=True)
757
+ if c.dtype.char in '?bBhHiIlLqQpP':
758
+ c = c.astype(np.double)
759
+ if not np.iterable(k):
760
+ k = [k]
761
+ cnt = pu._deprecate_as_int(m, "the order of integration")
762
+ iaxis = pu._deprecate_as_int(axis, "the axis")
763
+ if cnt < 0:
764
+ raise ValueError("The order of integration must be non-negative")
765
+ if len(k) > cnt:
766
+ raise ValueError("Too many integration constants")
767
+ if np.ndim(lbnd) != 0:
768
+ raise ValueError("lbnd must be a scalar.")
769
+ if np.ndim(scl) != 0:
770
+ raise ValueError("scl must be a scalar.")
771
+ iaxis = normalize_axis_index(iaxis, c.ndim)
772
+
773
+ if cnt == 0:
774
+ return c
775
+
776
+ c = np.moveaxis(c, iaxis, 0)
777
+ k = list(k) + [0]*(cnt - len(k))
778
+ for i in range(cnt):
779
+ n = len(c)
780
+ c *= scl
781
+ if n == 1 and np.all(c[0] == 0):
782
+ c[0] += k[i]
783
+ else:
784
+ tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
785
+ tmp[0] = c[0]*0
786
+ tmp[1] = c[0]
787
+ for j in range(1, n):
788
+ tmp[j + 1] = c[j]/(j + 1)
789
+ tmp[0] += k[i] - hermeval(lbnd, tmp)
790
+ c = tmp
791
+ c = np.moveaxis(c, 0, iaxis)
792
+ return c
793
+
794
+
795
+ def hermeval(x, c, tensor=True):
796
+ """
797
+ Evaluate an HermiteE series at points x.
798
+
799
+ If `c` is of length `n + 1`, this function returns the value:
800
+
801
+ .. math:: p(x) = c_0 * He_0(x) + c_1 * He_1(x) + ... + c_n * He_n(x)
802
+
803
+ The parameter `x` is converted to an array only if it is a tuple or a
804
+ list, otherwise it is treated as a scalar. In either case, either `x`
805
+ or its elements must support multiplication and addition both with
806
+ themselves and with the elements of `c`.
807
+
808
+ If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
809
+ `c` is multidimensional, then the shape of the result depends on the
810
+ value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
811
+ x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
812
+ scalars have shape (,).
813
+
814
+ Trailing zeros in the coefficients will be used in the evaluation, so
815
+ they should be avoided if efficiency is a concern.
816
+
817
+ Parameters
818
+ ----------
819
+ x : array_like, compatible object
820
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
821
+ it is left unchanged and treated as a scalar. In either case, `x`
822
+ or its elements must support addition and multiplication with
823
+ with themselves and with the elements of `c`.
824
+ c : array_like
825
+ Array of coefficients ordered so that the coefficients for terms of
826
+ degree n are contained in c[n]. If `c` is multidimensional the
827
+ remaining indices enumerate multiple polynomials. In the two
828
+ dimensional case the coefficients may be thought of as stored in
829
+ the columns of `c`.
830
+ tensor : boolean, optional
831
+ If True, the shape of the coefficient array is extended with ones
832
+ on the right, one for each dimension of `x`. Scalars have dimension 0
833
+ for this action. The result is that every column of coefficients in
834
+ `c` is evaluated for every element of `x`. If False, `x` is broadcast
835
+ over the columns of `c` for the evaluation. This keyword is useful
836
+ when `c` is multidimensional. The default value is True.
837
+
838
+ .. versionadded:: 1.7.0
839
+
840
+ Returns
841
+ -------
842
+ values : ndarray, algebra_like
843
+ The shape of the return value is described above.
844
+
845
+ See Also
846
+ --------
847
+ hermeval2d, hermegrid2d, hermeval3d, hermegrid3d
848
+
849
+ Notes
850
+ -----
851
+ The evaluation uses Clenshaw recursion, aka synthetic division.
852
+
853
+ Examples
854
+ --------
855
+ >>> from numpy.polynomial.hermite_e import hermeval
856
+ >>> coef = [1,2,3]
857
+ >>> hermeval(1, coef)
858
+ 3.0
859
+ >>> hermeval([[1,2],[3,4]], coef)
860
+ array([[ 3., 14.],
861
+ [31., 54.]])
862
+
863
+ """
864
+ c = np.array(c, ndmin=1, copy=False)
865
+ if c.dtype.char in '?bBhHiIlLqQpP':
866
+ c = c.astype(np.double)
867
+ if isinstance(x, (tuple, list)):
868
+ x = np.asarray(x)
869
+ if isinstance(x, np.ndarray) and tensor:
870
+ c = c.reshape(c.shape + (1,)*x.ndim)
871
+
872
+ if len(c) == 1:
873
+ c0 = c[0]
874
+ c1 = 0
875
+ elif len(c) == 2:
876
+ c0 = c[0]
877
+ c1 = c[1]
878
+ else:
879
+ nd = len(c)
880
+ c0 = c[-2]
881
+ c1 = c[-1]
882
+ for i in range(3, len(c) + 1):
883
+ tmp = c0
884
+ nd = nd - 1
885
+ c0 = c[-i] - c1*(nd - 1)
886
+ c1 = tmp + c1*x
887
+ return c0 + c1*x
888
+
889
+
890
+ def hermeval2d(x, y, c):
891
+ """
892
+ Evaluate a 2-D HermiteE series at points (x, y).
893
+
894
+ This function returns the values:
895
+
896
+ .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * He_i(x) * He_j(y)
897
+
898
+ The parameters `x` and `y` are converted to arrays only if they are
899
+ tuples or a lists, otherwise they are treated as a scalars and they
900
+ must have the same shape after conversion. In either case, either `x`
901
+ and `y` or their elements must support multiplication and addition both
902
+ with themselves and with the elements of `c`.
903
+
904
+ If `c` is a 1-D array a one is implicitly appended to its shape to make
905
+ it 2-D. The shape of the result will be c.shape[2:] + x.shape.
906
+
907
+ Parameters
908
+ ----------
909
+ x, y : array_like, compatible objects
910
+ The two dimensional series is evaluated at the points `(x, y)`,
911
+ where `x` and `y` must have the same shape. If `x` or `y` is a list
912
+ or tuple, it is first converted to an ndarray, otherwise it is left
913
+ unchanged and if it isn't an ndarray it is treated as a scalar.
914
+ c : array_like
915
+ Array of coefficients ordered so that the coefficient of the term
916
+ of multi-degree i,j is contained in ``c[i,j]``. If `c` has
917
+ dimension greater than two the remaining indices enumerate multiple
918
+ sets of coefficients.
919
+
920
+ Returns
921
+ -------
922
+ values : ndarray, compatible object
923
+ The values of the two dimensional polynomial at points formed with
924
+ pairs of corresponding values from `x` and `y`.
925
+
926
+ See Also
927
+ --------
928
+ hermeval, hermegrid2d, hermeval3d, hermegrid3d
929
+
930
+ Notes
931
+ -----
932
+
933
+ .. versionadded:: 1.7.0
934
+
935
+ """
936
+ return pu._valnd(hermeval, c, x, y)
937
+
938
+
939
+ def hermegrid2d(x, y, c):
940
+ """
941
+ Evaluate a 2-D HermiteE series on the Cartesian product of x and y.
942
+
943
+ This function returns the values:
944
+
945
+ .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * H_i(a) * H_j(b)
946
+
947
+ where the points `(a, b)` consist of all pairs formed by taking
948
+ `a` from `x` and `b` from `y`. The resulting points form a grid with
949
+ `x` in the first dimension and `y` in the second.
950
+
951
+ The parameters `x` and `y` are converted to arrays only if they are
952
+ tuples or a lists, otherwise they are treated as a scalars. In either
953
+ case, either `x` and `y` or their elements must support multiplication
954
+ and addition both with themselves and with the elements of `c`.
955
+
956
+ If `c` has fewer than two dimensions, ones are implicitly appended to
957
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
958
+ x.shape.
959
+
960
+ Parameters
961
+ ----------
962
+ x, y : array_like, compatible objects
963
+ The two dimensional series is evaluated at the points in the
964
+ Cartesian product of `x` and `y`. If `x` or `y` is a list or
965
+ tuple, it is first converted to an ndarray, otherwise it is left
966
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
967
+ c : array_like
968
+ Array of coefficients ordered so that the coefficients for terms of
969
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
970
+ greater than two the remaining indices enumerate multiple sets of
971
+ coefficients.
972
+
973
+ Returns
974
+ -------
975
+ values : ndarray, compatible object
976
+ The values of the two dimensional polynomial at points in the Cartesian
977
+ product of `x` and `y`.
978
+
979
+ See Also
980
+ --------
981
+ hermeval, hermeval2d, hermeval3d, hermegrid3d
982
+
983
+ Notes
984
+ -----
985
+
986
+ .. versionadded:: 1.7.0
987
+
988
+ """
989
+ return pu._gridnd(hermeval, c, x, y)
990
+
991
+
992
+ def hermeval3d(x, y, z, c):
993
+ """
994
+ Evaluate a 3-D Hermite_e series at points (x, y, z).
995
+
996
+ This function returns the values:
997
+
998
+ .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * He_i(x) * He_j(y) * He_k(z)
999
+
1000
+ The parameters `x`, `y`, and `z` are converted to arrays only if
1001
+ they are tuples or a lists, otherwise they are treated as a scalars and
1002
+ they must have the same shape after conversion. In either case, either
1003
+ `x`, `y`, and `z` or their elements must support multiplication and
1004
+ addition both with themselves and with the elements of `c`.
1005
+
1006
+ If `c` has fewer than 3 dimensions, ones are implicitly appended to its
1007
+ shape to make it 3-D. The shape of the result will be c.shape[3:] +
1008
+ x.shape.
1009
+
1010
+ Parameters
1011
+ ----------
1012
+ x, y, z : array_like, compatible object
1013
+ The three dimensional series is evaluated at the points
1014
+ `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
1015
+ any of `x`, `y`, or `z` is a list or tuple, it is first converted
1016
+ to an ndarray, otherwise it is left unchanged and if it isn't an
1017
+ ndarray it is treated as a scalar.
1018
+ c : array_like
1019
+ Array of coefficients ordered so that the coefficient of the term of
1020
+ multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
1021
+ greater than 3 the remaining indices enumerate multiple sets of
1022
+ coefficients.
1023
+
1024
+ Returns
1025
+ -------
1026
+ values : ndarray, compatible object
1027
+ The values of the multidimensional polynomial on points formed with
1028
+ triples of corresponding values from `x`, `y`, and `z`.
1029
+
1030
+ See Also
1031
+ --------
1032
+ hermeval, hermeval2d, hermegrid2d, hermegrid3d
1033
+
1034
+ Notes
1035
+ -----
1036
+
1037
+ .. versionadded:: 1.7.0
1038
+
1039
+ """
1040
+ return pu._valnd(hermeval, c, x, y, z)
1041
+
1042
+
1043
+ def hermegrid3d(x, y, z, c):
1044
+ """
1045
+ Evaluate a 3-D HermiteE series on the Cartesian product of x, y, and z.
1046
+
1047
+ This function returns the values:
1048
+
1049
+ .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * He_i(a) * He_j(b) * He_k(c)
1050
+
1051
+ where the points `(a, b, c)` consist of all triples formed by taking
1052
+ `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
1053
+ a grid with `x` in the first dimension, `y` in the second, and `z` in
1054
+ the third.
1055
+
1056
+ The parameters `x`, `y`, and `z` are converted to arrays only if they
1057
+ are tuples or a lists, otherwise they are treated as a scalars. In
1058
+ either case, either `x`, `y`, and `z` or their elements must support
1059
+ multiplication and addition both with themselves and with the elements
1060
+ of `c`.
1061
+
1062
+ If `c` has fewer than three dimensions, ones are implicitly appended to
1063
+ its shape to make it 3-D. The shape of the result will be c.shape[3:] +
1064
+ x.shape + y.shape + z.shape.
1065
+
1066
+ Parameters
1067
+ ----------
1068
+ x, y, z : array_like, compatible objects
1069
+ The three dimensional series is evaluated at the points in the
1070
+ Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
1071
+ list or tuple, it is first converted to an ndarray, otherwise it is
1072
+ left unchanged and, if it isn't an ndarray, it is treated as a
1073
+ scalar.
1074
+ c : array_like
1075
+ Array of coefficients ordered so that the coefficients for terms of
1076
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
1077
+ greater than two the remaining indices enumerate multiple sets of
1078
+ coefficients.
1079
+
1080
+ Returns
1081
+ -------
1082
+ values : ndarray, compatible object
1083
+ The values of the two dimensional polynomial at points in the Cartesian
1084
+ product of `x` and `y`.
1085
+
1086
+ See Also
1087
+ --------
1088
+ hermeval, hermeval2d, hermegrid2d, hermeval3d
1089
+
1090
+ Notes
1091
+ -----
1092
+
1093
+ .. versionadded:: 1.7.0
1094
+
1095
+ """
1096
+ return pu._gridnd(hermeval, c, x, y, z)
1097
+
1098
+
1099
+ def hermevander(x, deg):
1100
+ """Pseudo-Vandermonde matrix of given degree.
1101
+
1102
+ Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
1103
+ `x`. The pseudo-Vandermonde matrix is defined by
1104
+
1105
+ .. math:: V[..., i] = He_i(x),
1106
+
1107
+ where `0 <= i <= deg`. The leading indices of `V` index the elements of
1108
+ `x` and the last index is the degree of the HermiteE polynomial.
1109
+
1110
+ If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
1111
+ array ``V = hermevander(x, n)``, then ``np.dot(V, c)`` and
1112
+ ``hermeval(x, c)`` are the same up to roundoff. This equivalence is
1113
+ useful both for least squares fitting and for the evaluation of a large
1114
+ number of HermiteE series of the same degree and sample points.
1115
+
1116
+ Parameters
1117
+ ----------
1118
+ x : array_like
1119
+ Array of points. The dtype is converted to float64 or complex128
1120
+ depending on whether any of the elements are complex. If `x` is
1121
+ scalar it is converted to a 1-D array.
1122
+ deg : int
1123
+ Degree of the resulting matrix.
1124
+
1125
+ Returns
1126
+ -------
1127
+ vander : ndarray
1128
+ The pseudo-Vandermonde matrix. The shape of the returned matrix is
1129
+ ``x.shape + (deg + 1,)``, where The last index is the degree of the
1130
+ corresponding HermiteE polynomial. The dtype will be the same as
1131
+ the converted `x`.
1132
+
1133
+ Examples
1134
+ --------
1135
+ >>> from numpy.polynomial.hermite_e import hermevander
1136
+ >>> x = np.array([-1, 0, 1])
1137
+ >>> hermevander(x, 3)
1138
+ array([[ 1., -1., 0., 2.],
1139
+ [ 1., 0., -1., -0.],
1140
+ [ 1., 1., 0., -2.]])
1141
+
1142
+ """
1143
+ ideg = pu._deprecate_as_int(deg, "deg")
1144
+ if ideg < 0:
1145
+ raise ValueError("deg must be non-negative")
1146
+
1147
+ x = np.array(x, copy=False, ndmin=1) + 0.0
1148
+ dims = (ideg + 1,) + x.shape
1149
+ dtyp = x.dtype
1150
+ v = np.empty(dims, dtype=dtyp)
1151
+ v[0] = x*0 + 1
1152
+ if ideg > 0:
1153
+ v[1] = x
1154
+ for i in range(2, ideg + 1):
1155
+ v[i] = (v[i-1]*x - v[i-2]*(i - 1))
1156
+ return np.moveaxis(v, 0, -1)
1157
+
1158
+
1159
+ def hermevander2d(x, y, deg):
1160
+ """Pseudo-Vandermonde matrix of given degrees.
1161
+
1162
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1163
+ points `(x, y)`. The pseudo-Vandermonde matrix is defined by
1164
+
1165
+ .. math:: V[..., (deg[1] + 1)*i + j] = He_i(x) * He_j(y),
1166
+
1167
+ where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
1168
+ `V` index the points `(x, y)` and the last index encodes the degrees of
1169
+ the HermiteE polynomials.
1170
+
1171
+ If ``V = hermevander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
1172
+ correspond to the elements of a 2-D coefficient array `c` of shape
1173
+ (xdeg + 1, ydeg + 1) in the order
1174
+
1175
+ .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
1176
+
1177
+ and ``np.dot(V, c.flat)`` and ``hermeval2d(x, y, c)`` will be the same
1178
+ up to roundoff. This equivalence is useful both for least squares
1179
+ fitting and for the evaluation of a large number of 2-D HermiteE
1180
+ series of the same degrees and sample points.
1181
+
1182
+ Parameters
1183
+ ----------
1184
+ x, y : array_like
1185
+ Arrays of point coordinates, all of the same shape. The dtypes
1186
+ will be converted to either float64 or complex128 depending on
1187
+ whether any of the elements are complex. Scalars are converted to
1188
+ 1-D arrays.
1189
+ deg : list of ints
1190
+ List of maximum degrees of the form [x_deg, y_deg].
1191
+
1192
+ Returns
1193
+ -------
1194
+ vander2d : ndarray
1195
+ The shape of the returned matrix is ``x.shape + (order,)``, where
1196
+ :math:`order = (deg[0]+1)*(deg[1]+1)`. The dtype will be the same
1197
+ as the converted `x` and `y`.
1198
+
1199
+ See Also
1200
+ --------
1201
+ hermevander, hermevander3d, hermeval2d, hermeval3d
1202
+
1203
+ Notes
1204
+ -----
1205
+
1206
+ .. versionadded:: 1.7.0
1207
+
1208
+ """
1209
+ return pu._vander_nd_flat((hermevander, hermevander), (x, y), deg)
1210
+
1211
+
1212
+ def hermevander3d(x, y, z, deg):
1213
+ """Pseudo-Vandermonde matrix of given degrees.
1214
+
1215
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1216
+ points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
1217
+ then Hehe pseudo-Vandermonde matrix is defined by
1218
+
1219
+ .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = He_i(x)*He_j(y)*He_k(z),
1220
+
1221
+ where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
1222
+ indices of `V` index the points `(x, y, z)` and the last index encodes
1223
+ the degrees of the HermiteE polynomials.
1224
+
1225
+ If ``V = hermevander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
1226
+ of `V` correspond to the elements of a 3-D coefficient array `c` of
1227
+ shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
1228
+
1229
+ .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
1230
+
1231
+ and ``np.dot(V, c.flat)`` and ``hermeval3d(x, y, z, c)`` will be the
1232
+ same up to roundoff. This equivalence is useful both for least squares
1233
+ fitting and for the evaluation of a large number of 3-D HermiteE
1234
+ series of the same degrees and sample points.
1235
+
1236
+ Parameters
1237
+ ----------
1238
+ x, y, z : array_like
1239
+ Arrays of point coordinates, all of the same shape. The dtypes will
1240
+ be converted to either float64 or complex128 depending on whether
1241
+ any of the elements are complex. Scalars are converted to 1-D
1242
+ arrays.
1243
+ deg : list of ints
1244
+ List of maximum degrees of the form [x_deg, y_deg, z_deg].
1245
+
1246
+ Returns
1247
+ -------
1248
+ vander3d : ndarray
1249
+ The shape of the returned matrix is ``x.shape + (order,)``, where
1250
+ :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`. The dtype will
1251
+ be the same as the converted `x`, `y`, and `z`.
1252
+
1253
+ See Also
1254
+ --------
1255
+ hermevander, hermevander3d, hermeval2d, hermeval3d
1256
+
1257
+ Notes
1258
+ -----
1259
+
1260
+ .. versionadded:: 1.7.0
1261
+
1262
+ """
1263
+ return pu._vander_nd_flat((hermevander, hermevander, hermevander), (x, y, z), deg)
1264
+
1265
+
1266
+ def hermefit(x, y, deg, rcond=None, full=False, w=None):
1267
+ """
1268
+ Least squares fit of Hermite series to data.
1269
+
1270
+ Return the coefficients of a HermiteE series of degree `deg` that is
1271
+ the least squares fit to the data values `y` given at points `x`. If
1272
+ `y` is 1-D the returned coefficients will also be 1-D. If `y` is 2-D
1273
+ multiple fits are done, one for each column of `y`, and the resulting
1274
+ coefficients are stored in the corresponding columns of a 2-D return.
1275
+ The fitted polynomial(s) are in the form
1276
+
1277
+ .. math:: p(x) = c_0 + c_1 * He_1(x) + ... + c_n * He_n(x),
1278
+
1279
+ where `n` is `deg`.
1280
+
1281
+ Parameters
1282
+ ----------
1283
+ x : array_like, shape (M,)
1284
+ x-coordinates of the M sample points ``(x[i], y[i])``.
1285
+ y : array_like, shape (M,) or (M, K)
1286
+ y-coordinates of the sample points. Several data sets of sample
1287
+ points sharing the same x-coordinates can be fitted at once by
1288
+ passing in a 2D-array that contains one dataset per column.
1289
+ deg : int or 1-D array_like
1290
+ Degree(s) of the fitting polynomials. If `deg` is a single integer
1291
+ all terms up to and including the `deg`'th term are included in the
1292
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
1293
+ degrees of the terms to include may be used instead.
1294
+ rcond : float, optional
1295
+ Relative condition number of the fit. Singular values smaller than
1296
+ this relative to the largest singular value will be ignored. The
1297
+ default value is len(x)*eps, where eps is the relative precision of
1298
+ the float type, about 2e-16 in most cases.
1299
+ full : bool, optional
1300
+ Switch determining nature of return value. When it is False (the
1301
+ default) just the coefficients are returned, when True diagnostic
1302
+ information from the singular value decomposition is also returned.
1303
+ w : array_like, shape (`M`,), optional
1304
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
1305
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
1306
+ chosen so that the errors of the products ``w[i]*y[i]`` all have the
1307
+ same variance. When using inverse-variance weighting, use
1308
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
1309
+
1310
+ Returns
1311
+ -------
1312
+ coef : ndarray, shape (M,) or (M, K)
1313
+ Hermite coefficients ordered from low to high. If `y` was 2-D,
1314
+ the coefficients for the data in column k of `y` are in column
1315
+ `k`.
1316
+
1317
+ [residuals, rank, singular_values, rcond] : list
1318
+ These values are only returned if ``full == True``
1319
+
1320
+ - residuals -- sum of squared residuals of the least squares fit
1321
+ - rank -- the numerical rank of the scaled Vandermonde matrix
1322
+ - singular_values -- singular values of the scaled Vandermonde matrix
1323
+ - rcond -- value of `rcond`.
1324
+
1325
+ For more details, see `numpy.linalg.lstsq`.
1326
+
1327
+ Warns
1328
+ -----
1329
+ RankWarning
1330
+ The rank of the coefficient matrix in the least-squares fit is
1331
+ deficient. The warning is only raised if ``full = False``. The
1332
+ warnings can be turned off by
1333
+
1334
+ >>> import warnings
1335
+ >>> warnings.simplefilter('ignore', np.RankWarning)
1336
+
1337
+ See Also
1338
+ --------
1339
+ numpy.polynomial.chebyshev.chebfit
1340
+ numpy.polynomial.legendre.legfit
1341
+ numpy.polynomial.polynomial.polyfit
1342
+ numpy.polynomial.hermite.hermfit
1343
+ numpy.polynomial.laguerre.lagfit
1344
+ hermeval : Evaluates a Hermite series.
1345
+ hermevander : pseudo Vandermonde matrix of Hermite series.
1346
+ hermeweight : HermiteE weight function.
1347
+ numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
1348
+ scipy.interpolate.UnivariateSpline : Computes spline fits.
1349
+
1350
+ Notes
1351
+ -----
1352
+ The solution is the coefficients of the HermiteE series `p` that
1353
+ minimizes the sum of the weighted squared errors
1354
+
1355
+ .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
1356
+
1357
+ where the :math:`w_j` are the weights. This problem is solved by
1358
+ setting up the (typically) overdetermined matrix equation
1359
+
1360
+ .. math:: V(x) * c = w * y,
1361
+
1362
+ where `V` is the pseudo Vandermonde matrix of `x`, the elements of `c`
1363
+ are the coefficients to be solved for, and the elements of `y` are the
1364
+ observed values. This equation is then solved using the singular value
1365
+ decomposition of `V`.
1366
+
1367
+ If some of the singular values of `V` are so small that they are
1368
+ neglected, then a `RankWarning` will be issued. This means that the
1369
+ coefficient values may be poorly determined. Using a lower order fit
1370
+ will usually get rid of the warning. The `rcond` parameter can also be
1371
+ set to a value smaller than its default, but the resulting fit may be
1372
+ spurious and have large contributions from roundoff error.
1373
+
1374
+ Fits using HermiteE series are probably most useful when the data can
1375
+ be approximated by ``sqrt(w(x)) * p(x)``, where `w(x)` is the HermiteE
1376
+ weight. In that case the weight ``sqrt(w(x[i]))`` should be used
1377
+ together with data values ``y[i]/sqrt(w(x[i]))``. The weight function is
1378
+ available as `hermeweight`.
1379
+
1380
+ References
1381
+ ----------
1382
+ .. [1] Wikipedia, "Curve fitting",
1383
+ https://en.wikipedia.org/wiki/Curve_fitting
1384
+
1385
+ Examples
1386
+ --------
1387
+ >>> from numpy.polynomial.hermite_e import hermefit, hermeval
1388
+ >>> x = np.linspace(-10, 10)
1389
+ >>> np.random.seed(123)
1390
+ >>> err = np.random.randn(len(x))/10
1391
+ >>> y = hermeval(x, [1, 2, 3]) + err
1392
+ >>> hermefit(x, y, 2)
1393
+ array([ 1.01690445, 1.99951418, 2.99948696]) # may vary
1394
+
1395
+ """
1396
+ return pu._fit(hermevander, x, y, deg, rcond, full, w)
1397
+
1398
+
1399
+ def hermecompanion(c):
1400
+ """
1401
+ Return the scaled companion matrix of c.
1402
+
1403
+ The basis polynomials are scaled so that the companion matrix is
1404
+ symmetric when `c` is an HermiteE basis polynomial. This provides
1405
+ better eigenvalue estimates than the unscaled case and for basis
1406
+ polynomials the eigenvalues are guaranteed to be real if
1407
+ `numpy.linalg.eigvalsh` is used to obtain them.
1408
+
1409
+ Parameters
1410
+ ----------
1411
+ c : array_like
1412
+ 1-D array of HermiteE series coefficients ordered from low to high
1413
+ degree.
1414
+
1415
+ Returns
1416
+ -------
1417
+ mat : ndarray
1418
+ Scaled companion matrix of dimensions (deg, deg).
1419
+
1420
+ Notes
1421
+ -----
1422
+
1423
+ .. versionadded:: 1.7.0
1424
+
1425
+ """
1426
+ # c is a trimmed copy
1427
+ [c] = pu.as_series([c])
1428
+ if len(c) < 2:
1429
+ raise ValueError('Series must have maximum degree of at least 1.')
1430
+ if len(c) == 2:
1431
+ return np.array([[-c[0]/c[1]]])
1432
+
1433
+ n = len(c) - 1
1434
+ mat = np.zeros((n, n), dtype=c.dtype)
1435
+ scl = np.hstack((1., 1./np.sqrt(np.arange(n - 1, 0, -1))))
1436
+ scl = np.multiply.accumulate(scl)[::-1]
1437
+ top = mat.reshape(-1)[1::n+1]
1438
+ bot = mat.reshape(-1)[n::n+1]
1439
+ top[...] = np.sqrt(np.arange(1, n))
1440
+ bot[...] = top
1441
+ mat[:, -1] -= scl*c[:-1]/c[-1]
1442
+ return mat
1443
+
1444
+
1445
+ def hermeroots(c):
1446
+ """
1447
+ Compute the roots of a HermiteE series.
1448
+
1449
+ Return the roots (a.k.a. "zeros") of the polynomial
1450
+
1451
+ .. math:: p(x) = \\sum_i c[i] * He_i(x).
1452
+
1453
+ Parameters
1454
+ ----------
1455
+ c : 1-D array_like
1456
+ 1-D array of coefficients.
1457
+
1458
+ Returns
1459
+ -------
1460
+ out : ndarray
1461
+ Array of the roots of the series. If all the roots are real,
1462
+ then `out` is also real, otherwise it is complex.
1463
+
1464
+ See Also
1465
+ --------
1466
+ numpy.polynomial.polynomial.polyroots
1467
+ numpy.polynomial.legendre.legroots
1468
+ numpy.polynomial.laguerre.lagroots
1469
+ numpy.polynomial.hermite.hermroots
1470
+ numpy.polynomial.chebyshev.chebroots
1471
+
1472
+ Notes
1473
+ -----
1474
+ The root estimates are obtained as the eigenvalues of the companion
1475
+ matrix, Roots far from the origin of the complex plane may have large
1476
+ errors due to the numerical instability of the series for such
1477
+ values. Roots with multiplicity greater than 1 will also show larger
1478
+ errors as the value of the series near such points is relatively
1479
+ insensitive to errors in the roots. Isolated roots near the origin can
1480
+ be improved by a few iterations of Newton's method.
1481
+
1482
+ The HermiteE series basis polynomials aren't powers of `x` so the
1483
+ results of this function may seem unintuitive.
1484
+
1485
+ Examples
1486
+ --------
1487
+ >>> from numpy.polynomial.hermite_e import hermeroots, hermefromroots
1488
+ >>> coef = hermefromroots([-1, 0, 1])
1489
+ >>> coef
1490
+ array([0., 2., 0., 1.])
1491
+ >>> hermeroots(coef)
1492
+ array([-1., 0., 1.]) # may vary
1493
+
1494
+ """
1495
+ # c is a trimmed copy
1496
+ [c] = pu.as_series([c])
1497
+ if len(c) <= 1:
1498
+ return np.array([], dtype=c.dtype)
1499
+ if len(c) == 2:
1500
+ return np.array([-c[0]/c[1]])
1501
+
1502
+ # rotated companion matrix reduces error
1503
+ m = hermecompanion(c)[::-1,::-1]
1504
+ r = la.eigvals(m)
1505
+ r.sort()
1506
+ return r
1507
+
1508
+
1509
+ def _normed_hermite_e_n(x, n):
1510
+ """
1511
+ Evaluate a normalized HermiteE polynomial.
1512
+
1513
+ Compute the value of the normalized HermiteE polynomial of degree ``n``
1514
+ at the points ``x``.
1515
+
1516
+
1517
+ Parameters
1518
+ ----------
1519
+ x : ndarray of double.
1520
+ Points at which to evaluate the function
1521
+ n : int
1522
+ Degree of the normalized HermiteE function to be evaluated.
1523
+
1524
+ Returns
1525
+ -------
1526
+ values : ndarray
1527
+ The shape of the return value is described above.
1528
+
1529
+ Notes
1530
+ -----
1531
+ .. versionadded:: 1.10.0
1532
+
1533
+ This function is needed for finding the Gauss points and integration
1534
+ weights for high degrees. The values of the standard HermiteE functions
1535
+ overflow when n >= 207.
1536
+
1537
+ """
1538
+ if n == 0:
1539
+ return np.full(x.shape, 1/np.sqrt(np.sqrt(2*np.pi)))
1540
+
1541
+ c0 = 0.
1542
+ c1 = 1./np.sqrt(np.sqrt(2*np.pi))
1543
+ nd = float(n)
1544
+ for i in range(n - 1):
1545
+ tmp = c0
1546
+ c0 = -c1*np.sqrt((nd - 1.)/nd)
1547
+ c1 = tmp + c1*x*np.sqrt(1./nd)
1548
+ nd = nd - 1.0
1549
+ return c0 + c1*x
1550
+
1551
+
1552
+ def hermegauss(deg):
1553
+ """
1554
+ Gauss-HermiteE quadrature.
1555
+
1556
+ Computes the sample points and weights for Gauss-HermiteE quadrature.
1557
+ These sample points and weights will correctly integrate polynomials of
1558
+ degree :math:`2*deg - 1` or less over the interval :math:`[-\\inf, \\inf]`
1559
+ with the weight function :math:`f(x) = \\exp(-x^2/2)`.
1560
+
1561
+ Parameters
1562
+ ----------
1563
+ deg : int
1564
+ Number of sample points and weights. It must be >= 1.
1565
+
1566
+ Returns
1567
+ -------
1568
+ x : ndarray
1569
+ 1-D ndarray containing the sample points.
1570
+ y : ndarray
1571
+ 1-D ndarray containing the weights.
1572
+
1573
+ Notes
1574
+ -----
1575
+
1576
+ .. versionadded:: 1.7.0
1577
+
1578
+ The results have only been tested up to degree 100, higher degrees may
1579
+ be problematic. The weights are determined by using the fact that
1580
+
1581
+ .. math:: w_k = c / (He'_n(x_k) * He_{n-1}(x_k))
1582
+
1583
+ where :math:`c` is a constant independent of :math:`k` and :math:`x_k`
1584
+ is the k'th root of :math:`He_n`, and then scaling the results to get
1585
+ the right value when integrating 1.
1586
+
1587
+ """
1588
+ ideg = pu._deprecate_as_int(deg, "deg")
1589
+ if ideg <= 0:
1590
+ raise ValueError("deg must be a positive integer")
1591
+
1592
+ # first approximation of roots. We use the fact that the companion
1593
+ # matrix is symmetric in this case in order to obtain better zeros.
1594
+ c = np.array([0]*deg + [1])
1595
+ m = hermecompanion(c)
1596
+ x = la.eigvalsh(m)
1597
+
1598
+ # improve roots by one application of Newton
1599
+ dy = _normed_hermite_e_n(x, ideg)
1600
+ df = _normed_hermite_e_n(x, ideg - 1) * np.sqrt(ideg)
1601
+ x -= dy/df
1602
+
1603
+ # compute the weights. We scale the factor to avoid possible numerical
1604
+ # overflow.
1605
+ fm = _normed_hermite_e_n(x, ideg - 1)
1606
+ fm /= np.abs(fm).max()
1607
+ w = 1/(fm * fm)
1608
+
1609
+ # for Hermite_e we can also symmetrize
1610
+ w = (w + w[::-1])/2
1611
+ x = (x - x[::-1])/2
1612
+
1613
+ # scale w to get the right value
1614
+ w *= np.sqrt(2*np.pi) / w.sum()
1615
+
1616
+ return x, w
1617
+
1618
+
1619
+ def hermeweight(x):
1620
+ """Weight function of the Hermite_e polynomials.
1621
+
1622
+ The weight function is :math:`\\exp(-x^2/2)` and the interval of
1623
+ integration is :math:`[-\\inf, \\inf]`. the HermiteE polynomials are
1624
+ orthogonal, but not normalized, with respect to this weight function.
1625
+
1626
+ Parameters
1627
+ ----------
1628
+ x : array_like
1629
+ Values at which the weight function will be computed.
1630
+
1631
+ Returns
1632
+ -------
1633
+ w : ndarray
1634
+ The weight function at `x`.
1635
+
1636
+ Notes
1637
+ -----
1638
+
1639
+ .. versionadded:: 1.7.0
1640
+
1641
+ """
1642
+ w = np.exp(-.5*x**2)
1643
+ return w
1644
+
1645
+
1646
+ #
1647
+ # HermiteE series class
1648
+ #
1649
+
1650
+ class HermiteE(ABCPolyBase):
1651
+ """An HermiteE series class.
1652
+
1653
+ The HermiteE class provides the standard Python numerical methods
1654
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
1655
+ attributes and methods listed in the `ABCPolyBase` documentation.
1656
+
1657
+ Parameters
1658
+ ----------
1659
+ coef : array_like
1660
+ HermiteE coefficients in order of increasing degree, i.e,
1661
+ ``(1, 2, 3)`` gives ``1*He_0(x) + 2*He_1(X) + 3*He_2(x)``.
1662
+ domain : (2,) array_like, optional
1663
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
1664
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
1665
+ The default value is [-1, 1].
1666
+ window : (2,) array_like, optional
1667
+ Window, see `domain` for its use. The default value is [-1, 1].
1668
+
1669
+ .. versionadded:: 1.6.0
1670
+ symbol : str, optional
1671
+ Symbol used to represent the independent variable in string
1672
+ representations of the polynomial expression, e.g. for printing.
1673
+ The symbol must be a valid Python identifier. Default value is 'x'.
1674
+
1675
+ .. versionadded:: 1.24
1676
+
1677
+ """
1678
+ # Virtual Functions
1679
+ _add = staticmethod(hermeadd)
1680
+ _sub = staticmethod(hermesub)
1681
+ _mul = staticmethod(hermemul)
1682
+ _div = staticmethod(hermediv)
1683
+ _pow = staticmethod(hermepow)
1684
+ _val = staticmethod(hermeval)
1685
+ _int = staticmethod(hermeint)
1686
+ _der = staticmethod(hermeder)
1687
+ _fit = staticmethod(hermefit)
1688
+ _line = staticmethod(hermeline)
1689
+ _roots = staticmethod(hermeroots)
1690
+ _fromroots = staticmethod(hermefromroots)
1691
+
1692
+ # Virtual properties
1693
+ domain = np.array(hermedomain)
1694
+ window = np.array(hermedomain)
1695
+ basis_name = 'He'
lib/python3.12/site-packages/numpy/polynomial/hermite_e.pyi ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any
2
+
3
+ from numpy import ndarray, dtype, int_
4
+ from numpy.polynomial._polybase import ABCPolyBase
5
+ from numpy.polynomial.polyutils import trimcoef
6
+
7
+ __all__: list[str]
8
+
9
+ hermetrim = trimcoef
10
+
11
+ def poly2herme(pol): ...
12
+ def herme2poly(c): ...
13
+
14
+ hermedomain: ndarray[Any, dtype[int_]]
15
+ hermezero: ndarray[Any, dtype[int_]]
16
+ hermeone: ndarray[Any, dtype[int_]]
17
+ hermex: ndarray[Any, dtype[int_]]
18
+
19
+ def hermeline(off, scl): ...
20
+ def hermefromroots(roots): ...
21
+ def hermeadd(c1, c2): ...
22
+ def hermesub(c1, c2): ...
23
+ def hermemulx(c): ...
24
+ def hermemul(c1, c2): ...
25
+ def hermediv(c1, c2): ...
26
+ def hermepow(c, pow, maxpower=...): ...
27
+ def hermeder(c, m=..., scl=..., axis=...): ...
28
+ def hermeint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
29
+ def hermeval(x, c, tensor=...): ...
30
+ def hermeval2d(x, y, c): ...
31
+ def hermegrid2d(x, y, c): ...
32
+ def hermeval3d(x, y, z, c): ...
33
+ def hermegrid3d(x, y, z, c): ...
34
+ def hermevander(x, deg): ...
35
+ def hermevander2d(x, y, deg): ...
36
+ def hermevander3d(x, y, z, deg): ...
37
+ def hermefit(x, y, deg, rcond=..., full=..., w=...): ...
38
+ def hermecompanion(c): ...
39
+ def hermeroots(c): ...
40
+ def hermegauss(deg): ...
41
+ def hermeweight(x): ...
42
+
43
+ class HermiteE(ABCPolyBase):
44
+ domain: Any
45
+ window: Any
46
+ basis_name: Any
lib/python3.12/site-packages/numpy/polynomial/laguerre.py ADDED
@@ -0,0 +1,1651 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ==================================================
3
+ Laguerre Series (:mod:`numpy.polynomial.laguerre`)
4
+ ==================================================
5
+
6
+ This module provides a number of objects (mostly functions) useful for
7
+ dealing with Laguerre series, including a `Laguerre` class that
8
+ encapsulates the usual arithmetic operations. (General information
9
+ on how this module represents and works with such polynomials is in the
10
+ docstring for its "parent" sub-package, `numpy.polynomial`).
11
+
12
+ Classes
13
+ -------
14
+ .. autosummary::
15
+ :toctree: generated/
16
+
17
+ Laguerre
18
+
19
+ Constants
20
+ ---------
21
+ .. autosummary::
22
+ :toctree: generated/
23
+
24
+ lagdomain
25
+ lagzero
26
+ lagone
27
+ lagx
28
+
29
+ Arithmetic
30
+ ----------
31
+ .. autosummary::
32
+ :toctree: generated/
33
+
34
+ lagadd
35
+ lagsub
36
+ lagmulx
37
+ lagmul
38
+ lagdiv
39
+ lagpow
40
+ lagval
41
+ lagval2d
42
+ lagval3d
43
+ laggrid2d
44
+ laggrid3d
45
+
46
+ Calculus
47
+ --------
48
+ .. autosummary::
49
+ :toctree: generated/
50
+
51
+ lagder
52
+ lagint
53
+
54
+ Misc Functions
55
+ --------------
56
+ .. autosummary::
57
+ :toctree: generated/
58
+
59
+ lagfromroots
60
+ lagroots
61
+ lagvander
62
+ lagvander2d
63
+ lagvander3d
64
+ laggauss
65
+ lagweight
66
+ lagcompanion
67
+ lagfit
68
+ lagtrim
69
+ lagline
70
+ lag2poly
71
+ poly2lag
72
+
73
+ See also
74
+ --------
75
+ `numpy.polynomial`
76
+
77
+ """
78
+ import numpy as np
79
+ import numpy.linalg as la
80
+ from numpy.core.multiarray import normalize_axis_index
81
+
82
+ from . import polyutils as pu
83
+ from ._polybase import ABCPolyBase
84
+
85
+ __all__ = [
86
+ 'lagzero', 'lagone', 'lagx', 'lagdomain', 'lagline', 'lagadd',
87
+ 'lagsub', 'lagmulx', 'lagmul', 'lagdiv', 'lagpow', 'lagval', 'lagder',
88
+ 'lagint', 'lag2poly', 'poly2lag', 'lagfromroots', 'lagvander',
89
+ 'lagfit', 'lagtrim', 'lagroots', 'Laguerre', 'lagval2d', 'lagval3d',
90
+ 'laggrid2d', 'laggrid3d', 'lagvander2d', 'lagvander3d', 'lagcompanion',
91
+ 'laggauss', 'lagweight']
92
+
93
+ lagtrim = pu.trimcoef
94
+
95
+
96
+ def poly2lag(pol):
97
+ """
98
+ poly2lag(pol)
99
+
100
+ Convert a polynomial to a Laguerre series.
101
+
102
+ Convert an array representing the coefficients of a polynomial (relative
103
+ to the "standard" basis) ordered from lowest degree to highest, to an
104
+ array of the coefficients of the equivalent Laguerre series, ordered
105
+ from lowest to highest degree.
106
+
107
+ Parameters
108
+ ----------
109
+ pol : array_like
110
+ 1-D array containing the polynomial coefficients
111
+
112
+ Returns
113
+ -------
114
+ c : ndarray
115
+ 1-D array containing the coefficients of the equivalent Laguerre
116
+ series.
117
+
118
+ See Also
119
+ --------
120
+ lag2poly
121
+
122
+ Notes
123
+ -----
124
+ The easy way to do conversions between polynomial basis sets
125
+ is to use the convert method of a class instance.
126
+
127
+ Examples
128
+ --------
129
+ >>> from numpy.polynomial.laguerre import poly2lag
130
+ >>> poly2lag(np.arange(4))
131
+ array([ 23., -63., 58., -18.])
132
+
133
+ """
134
+ [pol] = pu.as_series([pol])
135
+ res = 0
136
+ for p in pol[::-1]:
137
+ res = lagadd(lagmulx(res), p)
138
+ return res
139
+
140
+
141
+ def lag2poly(c):
142
+ """
143
+ Convert a Laguerre series to a polynomial.
144
+
145
+ Convert an array representing the coefficients of a Laguerre series,
146
+ ordered from lowest degree to highest, to an array of the coefficients
147
+ of the equivalent polynomial (relative to the "standard" basis) ordered
148
+ from lowest to highest degree.
149
+
150
+ Parameters
151
+ ----------
152
+ c : array_like
153
+ 1-D array containing the Laguerre series coefficients, ordered
154
+ from lowest order term to highest.
155
+
156
+ Returns
157
+ -------
158
+ pol : ndarray
159
+ 1-D array containing the coefficients of the equivalent polynomial
160
+ (relative to the "standard" basis) ordered from lowest order term
161
+ to highest.
162
+
163
+ See Also
164
+ --------
165
+ poly2lag
166
+
167
+ Notes
168
+ -----
169
+ The easy way to do conversions between polynomial basis sets
170
+ is to use the convert method of a class instance.
171
+
172
+ Examples
173
+ --------
174
+ >>> from numpy.polynomial.laguerre import lag2poly
175
+ >>> lag2poly([ 23., -63., 58., -18.])
176
+ array([0., 1., 2., 3.])
177
+
178
+ """
179
+ from .polynomial import polyadd, polysub, polymulx
180
+
181
+ [c] = pu.as_series([c])
182
+ n = len(c)
183
+ if n == 1:
184
+ return c
185
+ else:
186
+ c0 = c[-2]
187
+ c1 = c[-1]
188
+ # i is the current degree of c1
189
+ for i in range(n - 1, 1, -1):
190
+ tmp = c0
191
+ c0 = polysub(c[i - 2], (c1*(i - 1))/i)
192
+ c1 = polyadd(tmp, polysub((2*i - 1)*c1, polymulx(c1))/i)
193
+ return polyadd(c0, polysub(c1, polymulx(c1)))
194
+
195
+ #
196
+ # These are constant arrays are of integer type so as to be compatible
197
+ # with the widest range of other types, such as Decimal.
198
+ #
199
+
200
+ # Laguerre
201
+ lagdomain = np.array([0, 1])
202
+
203
+ # Laguerre coefficients representing zero.
204
+ lagzero = np.array([0])
205
+
206
+ # Laguerre coefficients representing one.
207
+ lagone = np.array([1])
208
+
209
+ # Laguerre coefficients representing the identity x.
210
+ lagx = np.array([1, -1])
211
+
212
+
213
+ def lagline(off, scl):
214
+ """
215
+ Laguerre series whose graph is a straight line.
216
+
217
+ Parameters
218
+ ----------
219
+ off, scl : scalars
220
+ The specified line is given by ``off + scl*x``.
221
+
222
+ Returns
223
+ -------
224
+ y : ndarray
225
+ This module's representation of the Laguerre series for
226
+ ``off + scl*x``.
227
+
228
+ See Also
229
+ --------
230
+ numpy.polynomial.polynomial.polyline
231
+ numpy.polynomial.chebyshev.chebline
232
+ numpy.polynomial.legendre.legline
233
+ numpy.polynomial.hermite.hermline
234
+ numpy.polynomial.hermite_e.hermeline
235
+
236
+ Examples
237
+ --------
238
+ >>> from numpy.polynomial.laguerre import lagline, lagval
239
+ >>> lagval(0,lagline(3, 2))
240
+ 3.0
241
+ >>> lagval(1,lagline(3, 2))
242
+ 5.0
243
+
244
+ """
245
+ if scl != 0:
246
+ return np.array([off + scl, -scl])
247
+ else:
248
+ return np.array([off])
249
+
250
+
251
+ def lagfromroots(roots):
252
+ """
253
+ Generate a Laguerre series with given roots.
254
+
255
+ The function returns the coefficients of the polynomial
256
+
257
+ .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
258
+
259
+ in Laguerre form, where the `r_n` are the roots specified in `roots`.
260
+ If a zero has multiplicity n, then it must appear in `roots` n times.
261
+ For instance, if 2 is a root of multiplicity three and 3 is a root of
262
+ multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3]. The
263
+ roots can appear in any order.
264
+
265
+ If the returned coefficients are `c`, then
266
+
267
+ .. math:: p(x) = c_0 + c_1 * L_1(x) + ... + c_n * L_n(x)
268
+
269
+ The coefficient of the last term is not generally 1 for monic
270
+ polynomials in Laguerre form.
271
+
272
+ Parameters
273
+ ----------
274
+ roots : array_like
275
+ Sequence containing the roots.
276
+
277
+ Returns
278
+ -------
279
+ out : ndarray
280
+ 1-D array of coefficients. If all roots are real then `out` is a
281
+ real array, if some of the roots are complex, then `out` is complex
282
+ even if all the coefficients in the result are real (see Examples
283
+ below).
284
+
285
+ See Also
286
+ --------
287
+ numpy.polynomial.polynomial.polyfromroots
288
+ numpy.polynomial.legendre.legfromroots
289
+ numpy.polynomial.chebyshev.chebfromroots
290
+ numpy.polynomial.hermite.hermfromroots
291
+ numpy.polynomial.hermite_e.hermefromroots
292
+
293
+ Examples
294
+ --------
295
+ >>> from numpy.polynomial.laguerre import lagfromroots, lagval
296
+ >>> coef = lagfromroots((-1, 0, 1))
297
+ >>> lagval((-1, 0, 1), coef)
298
+ array([0., 0., 0.])
299
+ >>> coef = lagfromroots((-1j, 1j))
300
+ >>> lagval((-1j, 1j), coef)
301
+ array([0.+0.j, 0.+0.j])
302
+
303
+ """
304
+ return pu._fromroots(lagline, lagmul, roots)
305
+
306
+
307
+ def lagadd(c1, c2):
308
+ """
309
+ Add one Laguerre series to another.
310
+
311
+ Returns the sum of two Laguerre series `c1` + `c2`. The arguments
312
+ are sequences of coefficients ordered from lowest order term to
313
+ highest, i.e., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
314
+
315
+ Parameters
316
+ ----------
317
+ c1, c2 : array_like
318
+ 1-D arrays of Laguerre series coefficients ordered from low to
319
+ high.
320
+
321
+ Returns
322
+ -------
323
+ out : ndarray
324
+ Array representing the Laguerre series of their sum.
325
+
326
+ See Also
327
+ --------
328
+ lagsub, lagmulx, lagmul, lagdiv, lagpow
329
+
330
+ Notes
331
+ -----
332
+ Unlike multiplication, division, etc., the sum of two Laguerre series
333
+ is a Laguerre series (without having to "reproject" the result onto
334
+ the basis set) so addition, just like that of "standard" polynomials,
335
+ is simply "component-wise."
336
+
337
+ Examples
338
+ --------
339
+ >>> from numpy.polynomial.laguerre import lagadd
340
+ >>> lagadd([1, 2, 3], [1, 2, 3, 4])
341
+ array([2., 4., 6., 4.])
342
+
343
+
344
+ """
345
+ return pu._add(c1, c2)
346
+
347
+
348
+ def lagsub(c1, c2):
349
+ """
350
+ Subtract one Laguerre series from another.
351
+
352
+ Returns the difference of two Laguerre series `c1` - `c2`. The
353
+ sequences of coefficients are from lowest order term to highest, i.e.,
354
+ [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
355
+
356
+ Parameters
357
+ ----------
358
+ c1, c2 : array_like
359
+ 1-D arrays of Laguerre series coefficients ordered from low to
360
+ high.
361
+
362
+ Returns
363
+ -------
364
+ out : ndarray
365
+ Of Laguerre series coefficients representing their difference.
366
+
367
+ See Also
368
+ --------
369
+ lagadd, lagmulx, lagmul, lagdiv, lagpow
370
+
371
+ Notes
372
+ -----
373
+ Unlike multiplication, division, etc., the difference of two Laguerre
374
+ series is a Laguerre series (without having to "reproject" the result
375
+ onto the basis set) so subtraction, just like that of "standard"
376
+ polynomials, is simply "component-wise."
377
+
378
+ Examples
379
+ --------
380
+ >>> from numpy.polynomial.laguerre import lagsub
381
+ >>> lagsub([1, 2, 3, 4], [1, 2, 3])
382
+ array([0., 0., 0., 4.])
383
+
384
+ """
385
+ return pu._sub(c1, c2)
386
+
387
+
388
+ def lagmulx(c):
389
+ """Multiply a Laguerre series by x.
390
+
391
+ Multiply the Laguerre series `c` by x, where x is the independent
392
+ variable.
393
+
394
+
395
+ Parameters
396
+ ----------
397
+ c : array_like
398
+ 1-D array of Laguerre series coefficients ordered from low to
399
+ high.
400
+
401
+ Returns
402
+ -------
403
+ out : ndarray
404
+ Array representing the result of the multiplication.
405
+
406
+ See Also
407
+ --------
408
+ lagadd, lagsub, lagmul, lagdiv, lagpow
409
+
410
+ Notes
411
+ -----
412
+ The multiplication uses the recursion relationship for Laguerre
413
+ polynomials in the form
414
+
415
+ .. math::
416
+
417
+ xP_i(x) = (-(i + 1)*P_{i + 1}(x) + (2i + 1)P_{i}(x) - iP_{i - 1}(x))
418
+
419
+ Examples
420
+ --------
421
+ >>> from numpy.polynomial.laguerre import lagmulx
422
+ >>> lagmulx([1, 2, 3])
423
+ array([-1., -1., 11., -9.])
424
+
425
+ """
426
+ # c is a trimmed copy
427
+ [c] = pu.as_series([c])
428
+ # The zero series needs special treatment
429
+ if len(c) == 1 and c[0] == 0:
430
+ return c
431
+
432
+ prd = np.empty(len(c) + 1, dtype=c.dtype)
433
+ prd[0] = c[0]
434
+ prd[1] = -c[0]
435
+ for i in range(1, len(c)):
436
+ prd[i + 1] = -c[i]*(i + 1)
437
+ prd[i] += c[i]*(2*i + 1)
438
+ prd[i - 1] -= c[i]*i
439
+ return prd
440
+
441
+
442
+ def lagmul(c1, c2):
443
+ """
444
+ Multiply one Laguerre series by another.
445
+
446
+ Returns the product of two Laguerre series `c1` * `c2`. The arguments
447
+ are sequences of coefficients, from lowest order "term" to highest,
448
+ e.g., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
449
+
450
+ Parameters
451
+ ----------
452
+ c1, c2 : array_like
453
+ 1-D arrays of Laguerre series coefficients ordered from low to
454
+ high.
455
+
456
+ Returns
457
+ -------
458
+ out : ndarray
459
+ Of Laguerre series coefficients representing their product.
460
+
461
+ See Also
462
+ --------
463
+ lagadd, lagsub, lagmulx, lagdiv, lagpow
464
+
465
+ Notes
466
+ -----
467
+ In general, the (polynomial) product of two C-series results in terms
468
+ that are not in the Laguerre polynomial basis set. Thus, to express
469
+ the product as a Laguerre series, it is necessary to "reproject" the
470
+ product onto said basis set, which may produce "unintuitive" (but
471
+ correct) results; see Examples section below.
472
+
473
+ Examples
474
+ --------
475
+ >>> from numpy.polynomial.laguerre import lagmul
476
+ >>> lagmul([1, 2, 3], [0, 1, 2])
477
+ array([ 8., -13., 38., -51., 36.])
478
+
479
+ """
480
+ # s1, s2 are trimmed copies
481
+ [c1, c2] = pu.as_series([c1, c2])
482
+
483
+ if len(c1) > len(c2):
484
+ c = c2
485
+ xs = c1
486
+ else:
487
+ c = c1
488
+ xs = c2
489
+
490
+ if len(c) == 1:
491
+ c0 = c[0]*xs
492
+ c1 = 0
493
+ elif len(c) == 2:
494
+ c0 = c[0]*xs
495
+ c1 = c[1]*xs
496
+ else:
497
+ nd = len(c)
498
+ c0 = c[-2]*xs
499
+ c1 = c[-1]*xs
500
+ for i in range(3, len(c) + 1):
501
+ tmp = c0
502
+ nd = nd - 1
503
+ c0 = lagsub(c[-i]*xs, (c1*(nd - 1))/nd)
504
+ c1 = lagadd(tmp, lagsub((2*nd - 1)*c1, lagmulx(c1))/nd)
505
+ return lagadd(c0, lagsub(c1, lagmulx(c1)))
506
+
507
+
508
+ def lagdiv(c1, c2):
509
+ """
510
+ Divide one Laguerre series by another.
511
+
512
+ Returns the quotient-with-remainder of two Laguerre series
513
+ `c1` / `c2`. The arguments are sequences of coefficients from lowest
514
+ order "term" to highest, e.g., [1,2,3] represents the series
515
+ ``P_0 + 2*P_1 + 3*P_2``.
516
+
517
+ Parameters
518
+ ----------
519
+ c1, c2 : array_like
520
+ 1-D arrays of Laguerre series coefficients ordered from low to
521
+ high.
522
+
523
+ Returns
524
+ -------
525
+ [quo, rem] : ndarrays
526
+ Of Laguerre series coefficients representing the quotient and
527
+ remainder.
528
+
529
+ See Also
530
+ --------
531
+ lagadd, lagsub, lagmulx, lagmul, lagpow
532
+
533
+ Notes
534
+ -----
535
+ In general, the (polynomial) division of one Laguerre series by another
536
+ results in quotient and remainder terms that are not in the Laguerre
537
+ polynomial basis set. Thus, to express these results as a Laguerre
538
+ series, it is necessary to "reproject" the results onto the Laguerre
539
+ basis set, which may produce "unintuitive" (but correct) results; see
540
+ Examples section below.
541
+
542
+ Examples
543
+ --------
544
+ >>> from numpy.polynomial.laguerre import lagdiv
545
+ >>> lagdiv([ 8., -13., 38., -51., 36.], [0, 1, 2])
546
+ (array([1., 2., 3.]), array([0.]))
547
+ >>> lagdiv([ 9., -12., 38., -51., 36.], [0, 1, 2])
548
+ (array([1., 2., 3.]), array([1., 1.]))
549
+
550
+ """
551
+ return pu._div(lagmul, c1, c2)
552
+
553
+
554
+ def lagpow(c, pow, maxpower=16):
555
+ """Raise a Laguerre series to a power.
556
+
557
+ Returns the Laguerre series `c` raised to the power `pow`. The
558
+ argument `c` is a sequence of coefficients ordered from low to high.
559
+ i.e., [1,2,3] is the series ``P_0 + 2*P_1 + 3*P_2.``
560
+
561
+ Parameters
562
+ ----------
563
+ c : array_like
564
+ 1-D array of Laguerre series coefficients ordered from low to
565
+ high.
566
+ pow : integer
567
+ Power to which the series will be raised
568
+ maxpower : integer, optional
569
+ Maximum power allowed. This is mainly to limit growth of the series
570
+ to unmanageable size. Default is 16
571
+
572
+ Returns
573
+ -------
574
+ coef : ndarray
575
+ Laguerre series of power.
576
+
577
+ See Also
578
+ --------
579
+ lagadd, lagsub, lagmulx, lagmul, lagdiv
580
+
581
+ Examples
582
+ --------
583
+ >>> from numpy.polynomial.laguerre import lagpow
584
+ >>> lagpow([1, 2, 3], 2)
585
+ array([ 14., -16., 56., -72., 54.])
586
+
587
+ """
588
+ return pu._pow(lagmul, c, pow, maxpower)
589
+
590
+
591
+ def lagder(c, m=1, scl=1, axis=0):
592
+ """
593
+ Differentiate a Laguerre series.
594
+
595
+ Returns the Laguerre series coefficients `c` differentiated `m` times
596
+ along `axis`. At each iteration the result is multiplied by `scl` (the
597
+ scaling factor is for use in a linear change of variable). The argument
598
+ `c` is an array of coefficients from low to high degree along each
599
+ axis, e.g., [1,2,3] represents the series ``1*L_0 + 2*L_1 + 3*L_2``
600
+ while [[1,2],[1,2]] represents ``1*L_0(x)*L_0(y) + 1*L_1(x)*L_0(y) +
601
+ 2*L_0(x)*L_1(y) + 2*L_1(x)*L_1(y)`` if axis=0 is ``x`` and axis=1 is
602
+ ``y``.
603
+
604
+ Parameters
605
+ ----------
606
+ c : array_like
607
+ Array of Laguerre series coefficients. If `c` is multidimensional
608
+ the different axis correspond to different variables with the
609
+ degree in each axis given by the corresponding index.
610
+ m : int, optional
611
+ Number of derivatives taken, must be non-negative. (Default: 1)
612
+ scl : scalar, optional
613
+ Each differentiation is multiplied by `scl`. The end result is
614
+ multiplication by ``scl**m``. This is for use in a linear change of
615
+ variable. (Default: 1)
616
+ axis : int, optional
617
+ Axis over which the derivative is taken. (Default: 0).
618
+
619
+ .. versionadded:: 1.7.0
620
+
621
+ Returns
622
+ -------
623
+ der : ndarray
624
+ Laguerre series of the derivative.
625
+
626
+ See Also
627
+ --------
628
+ lagint
629
+
630
+ Notes
631
+ -----
632
+ In general, the result of differentiating a Laguerre series does not
633
+ resemble the same operation on a power series. Thus the result of this
634
+ function may be "unintuitive," albeit correct; see Examples section
635
+ below.
636
+
637
+ Examples
638
+ --------
639
+ >>> from numpy.polynomial.laguerre import lagder
640
+ >>> lagder([ 1., 1., 1., -3.])
641
+ array([1., 2., 3.])
642
+ >>> lagder([ 1., 0., 0., -4., 3.], m=2)
643
+ array([1., 2., 3.])
644
+
645
+ """
646
+ c = np.array(c, ndmin=1, copy=True)
647
+ if c.dtype.char in '?bBhHiIlLqQpP':
648
+ c = c.astype(np.double)
649
+
650
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
651
+ iaxis = pu._deprecate_as_int(axis, "the axis")
652
+ if cnt < 0:
653
+ raise ValueError("The order of derivation must be non-negative")
654
+ iaxis = normalize_axis_index(iaxis, c.ndim)
655
+
656
+ if cnt == 0:
657
+ return c
658
+
659
+ c = np.moveaxis(c, iaxis, 0)
660
+ n = len(c)
661
+ if cnt >= n:
662
+ c = c[:1]*0
663
+ else:
664
+ for i in range(cnt):
665
+ n = n - 1
666
+ c *= scl
667
+ der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
668
+ for j in range(n, 1, -1):
669
+ der[j - 1] = -c[j]
670
+ c[j - 1] += c[j]
671
+ der[0] = -c[1]
672
+ c = der
673
+ c = np.moveaxis(c, 0, iaxis)
674
+ return c
675
+
676
+
677
+ def lagint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
678
+ """
679
+ Integrate a Laguerre series.
680
+
681
+ Returns the Laguerre series coefficients `c` integrated `m` times from
682
+ `lbnd` along `axis`. At each iteration the resulting series is
683
+ **multiplied** by `scl` and an integration constant, `k`, is added.
684
+ The scaling factor is for use in a linear change of variable. ("Buyer
685
+ beware": note that, depending on what one is doing, one may want `scl`
686
+ to be the reciprocal of what one might expect; for more information,
687
+ see the Notes section below.) The argument `c` is an array of
688
+ coefficients from low to high degree along each axis, e.g., [1,2,3]
689
+ represents the series ``L_0 + 2*L_1 + 3*L_2`` while [[1,2],[1,2]]
690
+ represents ``1*L_0(x)*L_0(y) + 1*L_1(x)*L_0(y) + 2*L_0(x)*L_1(y) +
691
+ 2*L_1(x)*L_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
692
+
693
+
694
+ Parameters
695
+ ----------
696
+ c : array_like
697
+ Array of Laguerre series coefficients. If `c` is multidimensional
698
+ the different axis correspond to different variables with the
699
+ degree in each axis given by the corresponding index.
700
+ m : int, optional
701
+ Order of integration, must be positive. (Default: 1)
702
+ k : {[], list, scalar}, optional
703
+ Integration constant(s). The value of the first integral at
704
+ ``lbnd`` is the first value in the list, the value of the second
705
+ integral at ``lbnd`` is the second value, etc. If ``k == []`` (the
706
+ default), all constants are set to zero. If ``m == 1``, a single
707
+ scalar can be given instead of a list.
708
+ lbnd : scalar, optional
709
+ The lower bound of the integral. (Default: 0)
710
+ scl : scalar, optional
711
+ Following each integration the result is *multiplied* by `scl`
712
+ before the integration constant is added. (Default: 1)
713
+ axis : int, optional
714
+ Axis over which the integral is taken. (Default: 0).
715
+
716
+ .. versionadded:: 1.7.0
717
+
718
+ Returns
719
+ -------
720
+ S : ndarray
721
+ Laguerre series coefficients of the integral.
722
+
723
+ Raises
724
+ ------
725
+ ValueError
726
+ If ``m < 0``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
727
+ ``np.ndim(scl) != 0``.
728
+
729
+ See Also
730
+ --------
731
+ lagder
732
+
733
+ Notes
734
+ -----
735
+ Note that the result of each integration is *multiplied* by `scl`.
736
+ Why is this important to note? Say one is making a linear change of
737
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
738
+ :math:`dx = du/a`, so one will need to set `scl` equal to
739
+ :math:`1/a` - perhaps not what one would have first thought.
740
+
741
+ Also note that, in general, the result of integrating a C-series needs
742
+ to be "reprojected" onto the C-series basis set. Thus, typically,
743
+ the result of this function is "unintuitive," albeit correct; see
744
+ Examples section below.
745
+
746
+ Examples
747
+ --------
748
+ >>> from numpy.polynomial.laguerre import lagint
749
+ >>> lagint([1,2,3])
750
+ array([ 1., 1., 1., -3.])
751
+ >>> lagint([1,2,3], m=2)
752
+ array([ 1., 0., 0., -4., 3.])
753
+ >>> lagint([1,2,3], k=1)
754
+ array([ 2., 1., 1., -3.])
755
+ >>> lagint([1,2,3], lbnd=-1)
756
+ array([11.5, 1. , 1. , -3. ])
757
+ >>> lagint([1,2], m=2, k=[1,2], lbnd=-1)
758
+ array([ 11.16666667, -5. , -3. , 2. ]) # may vary
759
+
760
+ """
761
+ c = np.array(c, ndmin=1, copy=True)
762
+ if c.dtype.char in '?bBhHiIlLqQpP':
763
+ c = c.astype(np.double)
764
+ if not np.iterable(k):
765
+ k = [k]
766
+ cnt = pu._deprecate_as_int(m, "the order of integration")
767
+ iaxis = pu._deprecate_as_int(axis, "the axis")
768
+ if cnt < 0:
769
+ raise ValueError("The order of integration must be non-negative")
770
+ if len(k) > cnt:
771
+ raise ValueError("Too many integration constants")
772
+ if np.ndim(lbnd) != 0:
773
+ raise ValueError("lbnd must be a scalar.")
774
+ if np.ndim(scl) != 0:
775
+ raise ValueError("scl must be a scalar.")
776
+ iaxis = normalize_axis_index(iaxis, c.ndim)
777
+
778
+ if cnt == 0:
779
+ return c
780
+
781
+ c = np.moveaxis(c, iaxis, 0)
782
+ k = list(k) + [0]*(cnt - len(k))
783
+ for i in range(cnt):
784
+ n = len(c)
785
+ c *= scl
786
+ if n == 1 and np.all(c[0] == 0):
787
+ c[0] += k[i]
788
+ else:
789
+ tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
790
+ tmp[0] = c[0]
791
+ tmp[1] = -c[0]
792
+ for j in range(1, n):
793
+ tmp[j] += c[j]
794
+ tmp[j + 1] = -c[j]
795
+ tmp[0] += k[i] - lagval(lbnd, tmp)
796
+ c = tmp
797
+ c = np.moveaxis(c, 0, iaxis)
798
+ return c
799
+
800
+
801
+ def lagval(x, c, tensor=True):
802
+ """
803
+ Evaluate a Laguerre series at points x.
804
+
805
+ If `c` is of length `n + 1`, this function returns the value:
806
+
807
+ .. math:: p(x) = c_0 * L_0(x) + c_1 * L_1(x) + ... + c_n * L_n(x)
808
+
809
+ The parameter `x` is converted to an array only if it is a tuple or a
810
+ list, otherwise it is treated as a scalar. In either case, either `x`
811
+ or its elements must support multiplication and addition both with
812
+ themselves and with the elements of `c`.
813
+
814
+ If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
815
+ `c` is multidimensional, then the shape of the result depends on the
816
+ value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
817
+ x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
818
+ scalars have shape (,).
819
+
820
+ Trailing zeros in the coefficients will be used in the evaluation, so
821
+ they should be avoided if efficiency is a concern.
822
+
823
+ Parameters
824
+ ----------
825
+ x : array_like, compatible object
826
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
827
+ it is left unchanged and treated as a scalar. In either case, `x`
828
+ or its elements must support addition and multiplication with
829
+ themselves and with the elements of `c`.
830
+ c : array_like
831
+ Array of coefficients ordered so that the coefficients for terms of
832
+ degree n are contained in c[n]. If `c` is multidimensional the
833
+ remaining indices enumerate multiple polynomials. In the two
834
+ dimensional case the coefficients may be thought of as stored in
835
+ the columns of `c`.
836
+ tensor : boolean, optional
837
+ If True, the shape of the coefficient array is extended with ones
838
+ on the right, one for each dimension of `x`. Scalars have dimension 0
839
+ for this action. The result is that every column of coefficients in
840
+ `c` is evaluated for every element of `x`. If False, `x` is broadcast
841
+ over the columns of `c` for the evaluation. This keyword is useful
842
+ when `c` is multidimensional. The default value is True.
843
+
844
+ .. versionadded:: 1.7.0
845
+
846
+ Returns
847
+ -------
848
+ values : ndarray, algebra_like
849
+ The shape of the return value is described above.
850
+
851
+ See Also
852
+ --------
853
+ lagval2d, laggrid2d, lagval3d, laggrid3d
854
+
855
+ Notes
856
+ -----
857
+ The evaluation uses Clenshaw recursion, aka synthetic division.
858
+
859
+ Examples
860
+ --------
861
+ >>> from numpy.polynomial.laguerre import lagval
862
+ >>> coef = [1,2,3]
863
+ >>> lagval(1, coef)
864
+ -0.5
865
+ >>> lagval([[1,2],[3,4]], coef)
866
+ array([[-0.5, -4. ],
867
+ [-4.5, -2. ]])
868
+
869
+ """
870
+ c = np.array(c, ndmin=1, copy=False)
871
+ if c.dtype.char in '?bBhHiIlLqQpP':
872
+ c = c.astype(np.double)
873
+ if isinstance(x, (tuple, list)):
874
+ x = np.asarray(x)
875
+ if isinstance(x, np.ndarray) and tensor:
876
+ c = c.reshape(c.shape + (1,)*x.ndim)
877
+
878
+ if len(c) == 1:
879
+ c0 = c[0]
880
+ c1 = 0
881
+ elif len(c) == 2:
882
+ c0 = c[0]
883
+ c1 = c[1]
884
+ else:
885
+ nd = len(c)
886
+ c0 = c[-2]
887
+ c1 = c[-1]
888
+ for i in range(3, len(c) + 1):
889
+ tmp = c0
890
+ nd = nd - 1
891
+ c0 = c[-i] - (c1*(nd - 1))/nd
892
+ c1 = tmp + (c1*((2*nd - 1) - x))/nd
893
+ return c0 + c1*(1 - x)
894
+
895
+
896
+ def lagval2d(x, y, c):
897
+ """
898
+ Evaluate a 2-D Laguerre series at points (x, y).
899
+
900
+ This function returns the values:
901
+
902
+ .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * L_i(x) * L_j(y)
903
+
904
+ The parameters `x` and `y` are converted to arrays only if they are
905
+ tuples or a lists, otherwise they are treated as a scalars and they
906
+ must have the same shape after conversion. In either case, either `x`
907
+ and `y` or their elements must support multiplication and addition both
908
+ with themselves and with the elements of `c`.
909
+
910
+ If `c` is a 1-D array a one is implicitly appended to its shape to make
911
+ it 2-D. The shape of the result will be c.shape[2:] + x.shape.
912
+
913
+ Parameters
914
+ ----------
915
+ x, y : array_like, compatible objects
916
+ The two dimensional series is evaluated at the points `(x, y)`,
917
+ where `x` and `y` must have the same shape. If `x` or `y` is a list
918
+ or tuple, it is first converted to an ndarray, otherwise it is left
919
+ unchanged and if it isn't an ndarray it is treated as a scalar.
920
+ c : array_like
921
+ Array of coefficients ordered so that the coefficient of the term
922
+ of multi-degree i,j is contained in ``c[i,j]``. If `c` has
923
+ dimension greater than two the remaining indices enumerate multiple
924
+ sets of coefficients.
925
+
926
+ Returns
927
+ -------
928
+ values : ndarray, compatible object
929
+ The values of the two dimensional polynomial at points formed with
930
+ pairs of corresponding values from `x` and `y`.
931
+
932
+ See Also
933
+ --------
934
+ lagval, laggrid2d, lagval3d, laggrid3d
935
+
936
+ Notes
937
+ -----
938
+
939
+ .. versionadded:: 1.7.0
940
+
941
+ """
942
+ return pu._valnd(lagval, c, x, y)
943
+
944
+
945
+ def laggrid2d(x, y, c):
946
+ """
947
+ Evaluate a 2-D Laguerre series on the Cartesian product of x and y.
948
+
949
+ This function returns the values:
950
+
951
+ .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * L_i(a) * L_j(b)
952
+
953
+ where the points `(a, b)` consist of all pairs formed by taking
954
+ `a` from `x` and `b` from `y`. The resulting points form a grid with
955
+ `x` in the first dimension and `y` in the second.
956
+
957
+ The parameters `x` and `y` are converted to arrays only if they are
958
+ tuples or a lists, otherwise they are treated as a scalars. In either
959
+ case, either `x` and `y` or their elements must support multiplication
960
+ and addition both with themselves and with the elements of `c`.
961
+
962
+ If `c` has fewer than two dimensions, ones are implicitly appended to
963
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
964
+ x.shape + y.shape.
965
+
966
+ Parameters
967
+ ----------
968
+ x, y : array_like, compatible objects
969
+ The two dimensional series is evaluated at the points in the
970
+ Cartesian product of `x` and `y`. If `x` or `y` is a list or
971
+ tuple, it is first converted to an ndarray, otherwise it is left
972
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
973
+ c : array_like
974
+ Array of coefficients ordered so that the coefficient of the term of
975
+ multi-degree i,j is contained in `c[i,j]`. If `c` has dimension
976
+ greater than two the remaining indices enumerate multiple sets of
977
+ coefficients.
978
+
979
+ Returns
980
+ -------
981
+ values : ndarray, compatible object
982
+ The values of the two dimensional Chebyshev series at points in the
983
+ Cartesian product of `x` and `y`.
984
+
985
+ See Also
986
+ --------
987
+ lagval, lagval2d, lagval3d, laggrid3d
988
+
989
+ Notes
990
+ -----
991
+
992
+ .. versionadded:: 1.7.0
993
+
994
+ """
995
+ return pu._gridnd(lagval, c, x, y)
996
+
997
+
998
+ def lagval3d(x, y, z, c):
999
+ """
1000
+ Evaluate a 3-D Laguerre series at points (x, y, z).
1001
+
1002
+ This function returns the values:
1003
+
1004
+ .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * L_i(x) * L_j(y) * L_k(z)
1005
+
1006
+ The parameters `x`, `y`, and `z` are converted to arrays only if
1007
+ they are tuples or a lists, otherwise they are treated as a scalars and
1008
+ they must have the same shape after conversion. In either case, either
1009
+ `x`, `y`, and `z` or their elements must support multiplication and
1010
+ addition both with themselves and with the elements of `c`.
1011
+
1012
+ If `c` has fewer than 3 dimensions, ones are implicitly appended to its
1013
+ shape to make it 3-D. The shape of the result will be c.shape[3:] +
1014
+ x.shape.
1015
+
1016
+ Parameters
1017
+ ----------
1018
+ x, y, z : array_like, compatible object
1019
+ The three dimensional series is evaluated at the points
1020
+ `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
1021
+ any of `x`, `y`, or `z` is a list or tuple, it is first converted
1022
+ to an ndarray, otherwise it is left unchanged and if it isn't an
1023
+ ndarray it is treated as a scalar.
1024
+ c : array_like
1025
+ Array of coefficients ordered so that the coefficient of the term of
1026
+ multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
1027
+ greater than 3 the remaining indices enumerate multiple sets of
1028
+ coefficients.
1029
+
1030
+ Returns
1031
+ -------
1032
+ values : ndarray, compatible object
1033
+ The values of the multidimensional polynomial on points formed with
1034
+ triples of corresponding values from `x`, `y`, and `z`.
1035
+
1036
+ See Also
1037
+ --------
1038
+ lagval, lagval2d, laggrid2d, laggrid3d
1039
+
1040
+ Notes
1041
+ -----
1042
+
1043
+ .. versionadded:: 1.7.0
1044
+
1045
+ """
1046
+ return pu._valnd(lagval, c, x, y, z)
1047
+
1048
+
1049
+ def laggrid3d(x, y, z, c):
1050
+ """
1051
+ Evaluate a 3-D Laguerre series on the Cartesian product of x, y, and z.
1052
+
1053
+ This function returns the values:
1054
+
1055
+ .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * L_i(a) * L_j(b) * L_k(c)
1056
+
1057
+ where the points `(a, b, c)` consist of all triples formed by taking
1058
+ `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
1059
+ a grid with `x` in the first dimension, `y` in the second, and `z` in
1060
+ the third.
1061
+
1062
+ The parameters `x`, `y`, and `z` are converted to arrays only if they
1063
+ are tuples or a lists, otherwise they are treated as a scalars. In
1064
+ either case, either `x`, `y`, and `z` or their elements must support
1065
+ multiplication and addition both with themselves and with the elements
1066
+ of `c`.
1067
+
1068
+ If `c` has fewer than three dimensions, ones are implicitly appended to
1069
+ its shape to make it 3-D. The shape of the result will be c.shape[3:] +
1070
+ x.shape + y.shape + z.shape.
1071
+
1072
+ Parameters
1073
+ ----------
1074
+ x, y, z : array_like, compatible objects
1075
+ The three dimensional series is evaluated at the points in the
1076
+ Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
1077
+ list or tuple, it is first converted to an ndarray, otherwise it is
1078
+ left unchanged and, if it isn't an ndarray, it is treated as a
1079
+ scalar.
1080
+ c : array_like
1081
+ Array of coefficients ordered so that the coefficients for terms of
1082
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
1083
+ greater than two the remaining indices enumerate multiple sets of
1084
+ coefficients.
1085
+
1086
+ Returns
1087
+ -------
1088
+ values : ndarray, compatible object
1089
+ The values of the two dimensional polynomial at points in the Cartesian
1090
+ product of `x` and `y`.
1091
+
1092
+ See Also
1093
+ --------
1094
+ lagval, lagval2d, laggrid2d, lagval3d
1095
+
1096
+ Notes
1097
+ -----
1098
+
1099
+ .. versionadded:: 1.7.0
1100
+
1101
+ """
1102
+ return pu._gridnd(lagval, c, x, y, z)
1103
+
1104
+
1105
+ def lagvander(x, deg):
1106
+ """Pseudo-Vandermonde matrix of given degree.
1107
+
1108
+ Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
1109
+ `x`. The pseudo-Vandermonde matrix is defined by
1110
+
1111
+ .. math:: V[..., i] = L_i(x)
1112
+
1113
+ where `0 <= i <= deg`. The leading indices of `V` index the elements of
1114
+ `x` and the last index is the degree of the Laguerre polynomial.
1115
+
1116
+ If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
1117
+ array ``V = lagvander(x, n)``, then ``np.dot(V, c)`` and
1118
+ ``lagval(x, c)`` are the same up to roundoff. This equivalence is
1119
+ useful both for least squares fitting and for the evaluation of a large
1120
+ number of Laguerre series of the same degree and sample points.
1121
+
1122
+ Parameters
1123
+ ----------
1124
+ x : array_like
1125
+ Array of points. The dtype is converted to float64 or complex128
1126
+ depending on whether any of the elements are complex. If `x` is
1127
+ scalar it is converted to a 1-D array.
1128
+ deg : int
1129
+ Degree of the resulting matrix.
1130
+
1131
+ Returns
1132
+ -------
1133
+ vander : ndarray
1134
+ The pseudo-Vandermonde matrix. The shape of the returned matrix is
1135
+ ``x.shape + (deg + 1,)``, where The last index is the degree of the
1136
+ corresponding Laguerre polynomial. The dtype will be the same as
1137
+ the converted `x`.
1138
+
1139
+ Examples
1140
+ --------
1141
+ >>> from numpy.polynomial.laguerre import lagvander
1142
+ >>> x = np.array([0, 1, 2])
1143
+ >>> lagvander(x, 3)
1144
+ array([[ 1. , 1. , 1. , 1. ],
1145
+ [ 1. , 0. , -0.5 , -0.66666667],
1146
+ [ 1. , -1. , -1. , -0.33333333]])
1147
+
1148
+ """
1149
+ ideg = pu._deprecate_as_int(deg, "deg")
1150
+ if ideg < 0:
1151
+ raise ValueError("deg must be non-negative")
1152
+
1153
+ x = np.array(x, copy=False, ndmin=1) + 0.0
1154
+ dims = (ideg + 1,) + x.shape
1155
+ dtyp = x.dtype
1156
+ v = np.empty(dims, dtype=dtyp)
1157
+ v[0] = x*0 + 1
1158
+ if ideg > 0:
1159
+ v[1] = 1 - x
1160
+ for i in range(2, ideg + 1):
1161
+ v[i] = (v[i-1]*(2*i - 1 - x) - v[i-2]*(i - 1))/i
1162
+ return np.moveaxis(v, 0, -1)
1163
+
1164
+
1165
+ def lagvander2d(x, y, deg):
1166
+ """Pseudo-Vandermonde matrix of given degrees.
1167
+
1168
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1169
+ points `(x, y)`. The pseudo-Vandermonde matrix is defined by
1170
+
1171
+ .. math:: V[..., (deg[1] + 1)*i + j] = L_i(x) * L_j(y),
1172
+
1173
+ where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
1174
+ `V` index the points `(x, y)` and the last index encodes the degrees of
1175
+ the Laguerre polynomials.
1176
+
1177
+ If ``V = lagvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
1178
+ correspond to the elements of a 2-D coefficient array `c` of shape
1179
+ (xdeg + 1, ydeg + 1) in the order
1180
+
1181
+ .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
1182
+
1183
+ and ``np.dot(V, c.flat)`` and ``lagval2d(x, y, c)`` will be the same
1184
+ up to roundoff. This equivalence is useful both for least squares
1185
+ fitting and for the evaluation of a large number of 2-D Laguerre
1186
+ series of the same degrees and sample points.
1187
+
1188
+ Parameters
1189
+ ----------
1190
+ x, y : array_like
1191
+ Arrays of point coordinates, all of the same shape. The dtypes
1192
+ will be converted to either float64 or complex128 depending on
1193
+ whether any of the elements are complex. Scalars are converted to
1194
+ 1-D arrays.
1195
+ deg : list of ints
1196
+ List of maximum degrees of the form [x_deg, y_deg].
1197
+
1198
+ Returns
1199
+ -------
1200
+ vander2d : ndarray
1201
+ The shape of the returned matrix is ``x.shape + (order,)``, where
1202
+ :math:`order = (deg[0]+1)*(deg[1]+1)`. The dtype will be the same
1203
+ as the converted `x` and `y`.
1204
+
1205
+ See Also
1206
+ --------
1207
+ lagvander, lagvander3d, lagval2d, lagval3d
1208
+
1209
+ Notes
1210
+ -----
1211
+
1212
+ .. versionadded:: 1.7.0
1213
+
1214
+ """
1215
+ return pu._vander_nd_flat((lagvander, lagvander), (x, y), deg)
1216
+
1217
+
1218
+ def lagvander3d(x, y, z, deg):
1219
+ """Pseudo-Vandermonde matrix of given degrees.
1220
+
1221
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1222
+ points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
1223
+ then The pseudo-Vandermonde matrix is defined by
1224
+
1225
+ .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = L_i(x)*L_j(y)*L_k(z),
1226
+
1227
+ where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
1228
+ indices of `V` index the points `(x, y, z)` and the last index encodes
1229
+ the degrees of the Laguerre polynomials.
1230
+
1231
+ If ``V = lagvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
1232
+ of `V` correspond to the elements of a 3-D coefficient array `c` of
1233
+ shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
1234
+
1235
+ .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
1236
+
1237
+ and ``np.dot(V, c.flat)`` and ``lagval3d(x, y, z, c)`` will be the
1238
+ same up to roundoff. This equivalence is useful both for least squares
1239
+ fitting and for the evaluation of a large number of 3-D Laguerre
1240
+ series of the same degrees and sample points.
1241
+
1242
+ Parameters
1243
+ ----------
1244
+ x, y, z : array_like
1245
+ Arrays of point coordinates, all of the same shape. The dtypes will
1246
+ be converted to either float64 or complex128 depending on whether
1247
+ any of the elements are complex. Scalars are converted to 1-D
1248
+ arrays.
1249
+ deg : list of ints
1250
+ List of maximum degrees of the form [x_deg, y_deg, z_deg].
1251
+
1252
+ Returns
1253
+ -------
1254
+ vander3d : ndarray
1255
+ The shape of the returned matrix is ``x.shape + (order,)``, where
1256
+ :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`. The dtype will
1257
+ be the same as the converted `x`, `y`, and `z`.
1258
+
1259
+ See Also
1260
+ --------
1261
+ lagvander, lagvander3d, lagval2d, lagval3d
1262
+
1263
+ Notes
1264
+ -----
1265
+
1266
+ .. versionadded:: 1.7.0
1267
+
1268
+ """
1269
+ return pu._vander_nd_flat((lagvander, lagvander, lagvander), (x, y, z), deg)
1270
+
1271
+
1272
+ def lagfit(x, y, deg, rcond=None, full=False, w=None):
1273
+ """
1274
+ Least squares fit of Laguerre series to data.
1275
+
1276
+ Return the coefficients of a Laguerre series of degree `deg` that is the
1277
+ least squares fit to the data values `y` given at points `x`. If `y` is
1278
+ 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
1279
+ fits are done, one for each column of `y`, and the resulting
1280
+ coefficients are stored in the corresponding columns of a 2-D return.
1281
+ The fitted polynomial(s) are in the form
1282
+
1283
+ .. math:: p(x) = c_0 + c_1 * L_1(x) + ... + c_n * L_n(x),
1284
+
1285
+ where ``n`` is `deg`.
1286
+
1287
+ Parameters
1288
+ ----------
1289
+ x : array_like, shape (M,)
1290
+ x-coordinates of the M sample points ``(x[i], y[i])``.
1291
+ y : array_like, shape (M,) or (M, K)
1292
+ y-coordinates of the sample points. Several data sets of sample
1293
+ points sharing the same x-coordinates can be fitted at once by
1294
+ passing in a 2D-array that contains one dataset per column.
1295
+ deg : int or 1-D array_like
1296
+ Degree(s) of the fitting polynomials. If `deg` is a single integer
1297
+ all terms up to and including the `deg`'th term are included in the
1298
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
1299
+ degrees of the terms to include may be used instead.
1300
+ rcond : float, optional
1301
+ Relative condition number of the fit. Singular values smaller than
1302
+ this relative to the largest singular value will be ignored. The
1303
+ default value is len(x)*eps, where eps is the relative precision of
1304
+ the float type, about 2e-16 in most cases.
1305
+ full : bool, optional
1306
+ Switch determining nature of return value. When it is False (the
1307
+ default) just the coefficients are returned, when True diagnostic
1308
+ information from the singular value decomposition is also returned.
1309
+ w : array_like, shape (`M`,), optional
1310
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
1311
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
1312
+ chosen so that the errors of the products ``w[i]*y[i]`` all have the
1313
+ same variance. When using inverse-variance weighting, use
1314
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
1315
+
1316
+ Returns
1317
+ -------
1318
+ coef : ndarray, shape (M,) or (M, K)
1319
+ Laguerre coefficients ordered from low to high. If `y` was 2-D,
1320
+ the coefficients for the data in column *k* of `y` are in column
1321
+ *k*.
1322
+
1323
+ [residuals, rank, singular_values, rcond] : list
1324
+ These values are only returned if ``full == True``
1325
+
1326
+ - residuals -- sum of squared residuals of the least squares fit
1327
+ - rank -- the numerical rank of the scaled Vandermonde matrix
1328
+ - singular_values -- singular values of the scaled Vandermonde matrix
1329
+ - rcond -- value of `rcond`.
1330
+
1331
+ For more details, see `numpy.linalg.lstsq`.
1332
+
1333
+ Warns
1334
+ -----
1335
+ RankWarning
1336
+ The rank of the coefficient matrix in the least-squares fit is
1337
+ deficient. The warning is only raised if ``full == False``. The
1338
+ warnings can be turned off by
1339
+
1340
+ >>> import warnings
1341
+ >>> warnings.simplefilter('ignore', np.RankWarning)
1342
+
1343
+ See Also
1344
+ --------
1345
+ numpy.polynomial.polynomial.polyfit
1346
+ numpy.polynomial.legendre.legfit
1347
+ numpy.polynomial.chebyshev.chebfit
1348
+ numpy.polynomial.hermite.hermfit
1349
+ numpy.polynomial.hermite_e.hermefit
1350
+ lagval : Evaluates a Laguerre series.
1351
+ lagvander : pseudo Vandermonde matrix of Laguerre series.
1352
+ lagweight : Laguerre weight function.
1353
+ numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
1354
+ scipy.interpolate.UnivariateSpline : Computes spline fits.
1355
+
1356
+ Notes
1357
+ -----
1358
+ The solution is the coefficients of the Laguerre series ``p`` that
1359
+ minimizes the sum of the weighted squared errors
1360
+
1361
+ .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
1362
+
1363
+ where the :math:`w_j` are the weights. This problem is solved by
1364
+ setting up as the (typically) overdetermined matrix equation
1365
+
1366
+ .. math:: V(x) * c = w * y,
1367
+
1368
+ where ``V`` is the weighted pseudo Vandermonde matrix of `x`, ``c`` are the
1369
+ coefficients to be solved for, `w` are the weights, and `y` are the
1370
+ observed values. This equation is then solved using the singular value
1371
+ decomposition of ``V``.
1372
+
1373
+ If some of the singular values of `V` are so small that they are
1374
+ neglected, then a `RankWarning` will be issued. This means that the
1375
+ coefficient values may be poorly determined. Using a lower order fit
1376
+ will usually get rid of the warning. The `rcond` parameter can also be
1377
+ set to a value smaller than its default, but the resulting fit may be
1378
+ spurious and have large contributions from roundoff error.
1379
+
1380
+ Fits using Laguerre series are probably most useful when the data can
1381
+ be approximated by ``sqrt(w(x)) * p(x)``, where ``w(x)`` is the Laguerre
1382
+ weight. In that case the weight ``sqrt(w(x[i]))`` should be used
1383
+ together with data values ``y[i]/sqrt(w(x[i]))``. The weight function is
1384
+ available as `lagweight`.
1385
+
1386
+ References
1387
+ ----------
1388
+ .. [1] Wikipedia, "Curve fitting",
1389
+ https://en.wikipedia.org/wiki/Curve_fitting
1390
+
1391
+ Examples
1392
+ --------
1393
+ >>> from numpy.polynomial.laguerre import lagfit, lagval
1394
+ >>> x = np.linspace(0, 10)
1395
+ >>> err = np.random.randn(len(x))/10
1396
+ >>> y = lagval(x, [1, 2, 3]) + err
1397
+ >>> lagfit(x, y, 2)
1398
+ array([ 0.96971004, 2.00193749, 3.00288744]) # may vary
1399
+
1400
+ """
1401
+ return pu._fit(lagvander, x, y, deg, rcond, full, w)
1402
+
1403
+
1404
+ def lagcompanion(c):
1405
+ """
1406
+ Return the companion matrix of c.
1407
+
1408
+ The usual companion matrix of the Laguerre polynomials is already
1409
+ symmetric when `c` is a basis Laguerre polynomial, so no scaling is
1410
+ applied.
1411
+
1412
+ Parameters
1413
+ ----------
1414
+ c : array_like
1415
+ 1-D array of Laguerre series coefficients ordered from low to high
1416
+ degree.
1417
+
1418
+ Returns
1419
+ -------
1420
+ mat : ndarray
1421
+ Companion matrix of dimensions (deg, deg).
1422
+
1423
+ Notes
1424
+ -----
1425
+
1426
+ .. versionadded:: 1.7.0
1427
+
1428
+ """
1429
+ # c is a trimmed copy
1430
+ [c] = pu.as_series([c])
1431
+ if len(c) < 2:
1432
+ raise ValueError('Series must have maximum degree of at least 1.')
1433
+ if len(c) == 2:
1434
+ return np.array([[1 + c[0]/c[1]]])
1435
+
1436
+ n = len(c) - 1
1437
+ mat = np.zeros((n, n), dtype=c.dtype)
1438
+ top = mat.reshape(-1)[1::n+1]
1439
+ mid = mat.reshape(-1)[0::n+1]
1440
+ bot = mat.reshape(-1)[n::n+1]
1441
+ top[...] = -np.arange(1, n)
1442
+ mid[...] = 2.*np.arange(n) + 1.
1443
+ bot[...] = top
1444
+ mat[:, -1] += (c[:-1]/c[-1])*n
1445
+ return mat
1446
+
1447
+
1448
+ def lagroots(c):
1449
+ """
1450
+ Compute the roots of a Laguerre series.
1451
+
1452
+ Return the roots (a.k.a. "zeros") of the polynomial
1453
+
1454
+ .. math:: p(x) = \\sum_i c[i] * L_i(x).
1455
+
1456
+ Parameters
1457
+ ----------
1458
+ c : 1-D array_like
1459
+ 1-D array of coefficients.
1460
+
1461
+ Returns
1462
+ -------
1463
+ out : ndarray
1464
+ Array of the roots of the series. If all the roots are real,
1465
+ then `out` is also real, otherwise it is complex.
1466
+
1467
+ See Also
1468
+ --------
1469
+ numpy.polynomial.polynomial.polyroots
1470
+ numpy.polynomial.legendre.legroots
1471
+ numpy.polynomial.chebyshev.chebroots
1472
+ numpy.polynomial.hermite.hermroots
1473
+ numpy.polynomial.hermite_e.hermeroots
1474
+
1475
+ Notes
1476
+ -----
1477
+ The root estimates are obtained as the eigenvalues of the companion
1478
+ matrix, Roots far from the origin of the complex plane may have large
1479
+ errors due to the numerical instability of the series for such
1480
+ values. Roots with multiplicity greater than 1 will also show larger
1481
+ errors as the value of the series near such points is relatively
1482
+ insensitive to errors in the roots. Isolated roots near the origin can
1483
+ be improved by a few iterations of Newton's method.
1484
+
1485
+ The Laguerre series basis polynomials aren't powers of `x` so the
1486
+ results of this function may seem unintuitive.
1487
+
1488
+ Examples
1489
+ --------
1490
+ >>> from numpy.polynomial.laguerre import lagroots, lagfromroots
1491
+ >>> coef = lagfromroots([0, 1, 2])
1492
+ >>> coef
1493
+ array([ 2., -8., 12., -6.])
1494
+ >>> lagroots(coef)
1495
+ array([-4.4408921e-16, 1.0000000e+00, 2.0000000e+00])
1496
+
1497
+ """
1498
+ # c is a trimmed copy
1499
+ [c] = pu.as_series([c])
1500
+ if len(c) <= 1:
1501
+ return np.array([], dtype=c.dtype)
1502
+ if len(c) == 2:
1503
+ return np.array([1 + c[0]/c[1]])
1504
+
1505
+ # rotated companion matrix reduces error
1506
+ m = lagcompanion(c)[::-1,::-1]
1507
+ r = la.eigvals(m)
1508
+ r.sort()
1509
+ return r
1510
+
1511
+
1512
+ def laggauss(deg):
1513
+ """
1514
+ Gauss-Laguerre quadrature.
1515
+
1516
+ Computes the sample points and weights for Gauss-Laguerre quadrature.
1517
+ These sample points and weights will correctly integrate polynomials of
1518
+ degree :math:`2*deg - 1` or less over the interval :math:`[0, \\inf]`
1519
+ with the weight function :math:`f(x) = \\exp(-x)`.
1520
+
1521
+ Parameters
1522
+ ----------
1523
+ deg : int
1524
+ Number of sample points and weights. It must be >= 1.
1525
+
1526
+ Returns
1527
+ -------
1528
+ x : ndarray
1529
+ 1-D ndarray containing the sample points.
1530
+ y : ndarray
1531
+ 1-D ndarray containing the weights.
1532
+
1533
+ Notes
1534
+ -----
1535
+
1536
+ .. versionadded:: 1.7.0
1537
+
1538
+ The results have only been tested up to degree 100 higher degrees may
1539
+ be problematic. The weights are determined by using the fact that
1540
+
1541
+ .. math:: w_k = c / (L'_n(x_k) * L_{n-1}(x_k))
1542
+
1543
+ where :math:`c` is a constant independent of :math:`k` and :math:`x_k`
1544
+ is the k'th root of :math:`L_n`, and then scaling the results to get
1545
+ the right value when integrating 1.
1546
+
1547
+ """
1548
+ ideg = pu._deprecate_as_int(deg, "deg")
1549
+ if ideg <= 0:
1550
+ raise ValueError("deg must be a positive integer")
1551
+
1552
+ # first approximation of roots. We use the fact that the companion
1553
+ # matrix is symmetric in this case in order to obtain better zeros.
1554
+ c = np.array([0]*deg + [1])
1555
+ m = lagcompanion(c)
1556
+ x = la.eigvalsh(m)
1557
+
1558
+ # improve roots by one application of Newton
1559
+ dy = lagval(x, c)
1560
+ df = lagval(x, lagder(c))
1561
+ x -= dy/df
1562
+
1563
+ # compute the weights. We scale the factor to avoid possible numerical
1564
+ # overflow.
1565
+ fm = lagval(x, c[1:])
1566
+ fm /= np.abs(fm).max()
1567
+ df /= np.abs(df).max()
1568
+ w = 1/(fm * df)
1569
+
1570
+ # scale w to get the right value, 1 in this case
1571
+ w /= w.sum()
1572
+
1573
+ return x, w
1574
+
1575
+
1576
+ def lagweight(x):
1577
+ """Weight function of the Laguerre polynomials.
1578
+
1579
+ The weight function is :math:`exp(-x)` and the interval of integration
1580
+ is :math:`[0, \\inf]`. The Laguerre polynomials are orthogonal, but not
1581
+ normalized, with respect to this weight function.
1582
+
1583
+ Parameters
1584
+ ----------
1585
+ x : array_like
1586
+ Values at which the weight function will be computed.
1587
+
1588
+ Returns
1589
+ -------
1590
+ w : ndarray
1591
+ The weight function at `x`.
1592
+
1593
+ Notes
1594
+ -----
1595
+
1596
+ .. versionadded:: 1.7.0
1597
+
1598
+ """
1599
+ w = np.exp(-x)
1600
+ return w
1601
+
1602
+ #
1603
+ # Laguerre series class
1604
+ #
1605
+
1606
+ class Laguerre(ABCPolyBase):
1607
+ """A Laguerre series class.
1608
+
1609
+ The Laguerre class provides the standard Python numerical methods
1610
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
1611
+ attributes and methods listed in the `ABCPolyBase` documentation.
1612
+
1613
+ Parameters
1614
+ ----------
1615
+ coef : array_like
1616
+ Laguerre coefficients in order of increasing degree, i.e,
1617
+ ``(1, 2, 3)`` gives ``1*L_0(x) + 2*L_1(X) + 3*L_2(x)``.
1618
+ domain : (2,) array_like, optional
1619
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
1620
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
1621
+ The default value is [0, 1].
1622
+ window : (2,) array_like, optional
1623
+ Window, see `domain` for its use. The default value is [0, 1].
1624
+
1625
+ .. versionadded:: 1.6.0
1626
+ symbol : str, optional
1627
+ Symbol used to represent the independent variable in string
1628
+ representations of the polynomial expression, e.g. for printing.
1629
+ The symbol must be a valid Python identifier. Default value is 'x'.
1630
+
1631
+ .. versionadded:: 1.24
1632
+
1633
+ """
1634
+ # Virtual Functions
1635
+ _add = staticmethod(lagadd)
1636
+ _sub = staticmethod(lagsub)
1637
+ _mul = staticmethod(lagmul)
1638
+ _div = staticmethod(lagdiv)
1639
+ _pow = staticmethod(lagpow)
1640
+ _val = staticmethod(lagval)
1641
+ _int = staticmethod(lagint)
1642
+ _der = staticmethod(lagder)
1643
+ _fit = staticmethod(lagfit)
1644
+ _line = staticmethod(lagline)
1645
+ _roots = staticmethod(lagroots)
1646
+ _fromroots = staticmethod(lagfromroots)
1647
+
1648
+ # Virtual properties
1649
+ domain = np.array(lagdomain)
1650
+ window = np.array(lagdomain)
1651
+ basis_name = 'L'
lib/python3.12/site-packages/numpy/polynomial/laguerre.pyi ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any
2
+
3
+ from numpy import ndarray, dtype, int_
4
+ from numpy.polynomial._polybase import ABCPolyBase
5
+ from numpy.polynomial.polyutils import trimcoef
6
+
7
+ __all__: list[str]
8
+
9
+ lagtrim = trimcoef
10
+
11
+ def poly2lag(pol): ...
12
+ def lag2poly(c): ...
13
+
14
+ lagdomain: ndarray[Any, dtype[int_]]
15
+ lagzero: ndarray[Any, dtype[int_]]
16
+ lagone: ndarray[Any, dtype[int_]]
17
+ lagx: ndarray[Any, dtype[int_]]
18
+
19
+ def lagline(off, scl): ...
20
+ def lagfromroots(roots): ...
21
+ def lagadd(c1, c2): ...
22
+ def lagsub(c1, c2): ...
23
+ def lagmulx(c): ...
24
+ def lagmul(c1, c2): ...
25
+ def lagdiv(c1, c2): ...
26
+ def lagpow(c, pow, maxpower=...): ...
27
+ def lagder(c, m=..., scl=..., axis=...): ...
28
+ def lagint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
29
+ def lagval(x, c, tensor=...): ...
30
+ def lagval2d(x, y, c): ...
31
+ def laggrid2d(x, y, c): ...
32
+ def lagval3d(x, y, z, c): ...
33
+ def laggrid3d(x, y, z, c): ...
34
+ def lagvander(x, deg): ...
35
+ def lagvander2d(x, y, deg): ...
36
+ def lagvander3d(x, y, z, deg): ...
37
+ def lagfit(x, y, deg, rcond=..., full=..., w=...): ...
38
+ def lagcompanion(c): ...
39
+ def lagroots(c): ...
40
+ def laggauss(deg): ...
41
+ def lagweight(x): ...
42
+
43
+ class Laguerre(ABCPolyBase):
44
+ domain: Any
45
+ window: Any
46
+ basis_name: Any
lib/python3.12/site-packages/numpy/polynomial/legendre.py ADDED
@@ -0,0 +1,1664 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ==================================================
3
+ Legendre Series (:mod:`numpy.polynomial.legendre`)
4
+ ==================================================
5
+
6
+ This module provides a number of objects (mostly functions) useful for
7
+ dealing with Legendre series, including a `Legendre` class that
8
+ encapsulates the usual arithmetic operations. (General information
9
+ on how this module represents and works with such polynomials is in the
10
+ docstring for its "parent" sub-package, `numpy.polynomial`).
11
+
12
+ Classes
13
+ -------
14
+ .. autosummary::
15
+ :toctree: generated/
16
+
17
+ Legendre
18
+
19
+ Constants
20
+ ---------
21
+
22
+ .. autosummary::
23
+ :toctree: generated/
24
+
25
+ legdomain
26
+ legzero
27
+ legone
28
+ legx
29
+
30
+ Arithmetic
31
+ ----------
32
+
33
+ .. autosummary::
34
+ :toctree: generated/
35
+
36
+ legadd
37
+ legsub
38
+ legmulx
39
+ legmul
40
+ legdiv
41
+ legpow
42
+ legval
43
+ legval2d
44
+ legval3d
45
+ leggrid2d
46
+ leggrid3d
47
+
48
+ Calculus
49
+ --------
50
+
51
+ .. autosummary::
52
+ :toctree: generated/
53
+
54
+ legder
55
+ legint
56
+
57
+ Misc Functions
58
+ --------------
59
+
60
+ .. autosummary::
61
+ :toctree: generated/
62
+
63
+ legfromroots
64
+ legroots
65
+ legvander
66
+ legvander2d
67
+ legvander3d
68
+ leggauss
69
+ legweight
70
+ legcompanion
71
+ legfit
72
+ legtrim
73
+ legline
74
+ leg2poly
75
+ poly2leg
76
+
77
+ See also
78
+ --------
79
+ numpy.polynomial
80
+
81
+ """
82
+ import numpy as np
83
+ import numpy.linalg as la
84
+ from numpy.core.multiarray import normalize_axis_index
85
+
86
+ from . import polyutils as pu
87
+ from ._polybase import ABCPolyBase
88
+
89
+ __all__ = [
90
+ 'legzero', 'legone', 'legx', 'legdomain', 'legline', 'legadd',
91
+ 'legsub', 'legmulx', 'legmul', 'legdiv', 'legpow', 'legval', 'legder',
92
+ 'legint', 'leg2poly', 'poly2leg', 'legfromroots', 'legvander',
93
+ 'legfit', 'legtrim', 'legroots', 'Legendre', 'legval2d', 'legval3d',
94
+ 'leggrid2d', 'leggrid3d', 'legvander2d', 'legvander3d', 'legcompanion',
95
+ 'leggauss', 'legweight']
96
+
97
+ legtrim = pu.trimcoef
98
+
99
+
100
+ def poly2leg(pol):
101
+ """
102
+ Convert a polynomial to a Legendre series.
103
+
104
+ Convert an array representing the coefficients of a polynomial (relative
105
+ to the "standard" basis) ordered from lowest degree to highest, to an
106
+ array of the coefficients of the equivalent Legendre series, ordered
107
+ from lowest to highest degree.
108
+
109
+ Parameters
110
+ ----------
111
+ pol : array_like
112
+ 1-D array containing the polynomial coefficients
113
+
114
+ Returns
115
+ -------
116
+ c : ndarray
117
+ 1-D array containing the coefficients of the equivalent Legendre
118
+ series.
119
+
120
+ See Also
121
+ --------
122
+ leg2poly
123
+
124
+ Notes
125
+ -----
126
+ The easy way to do conversions between polynomial basis sets
127
+ is to use the convert method of a class instance.
128
+
129
+ Examples
130
+ --------
131
+ >>> from numpy import polynomial as P
132
+ >>> p = P.Polynomial(np.arange(4))
133
+ >>> p
134
+ Polynomial([0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
135
+ >>> c = P.Legendre(P.legendre.poly2leg(p.coef))
136
+ >>> c
137
+ Legendre([ 1. , 3.25, 1. , 0.75], domain=[-1, 1], window=[-1, 1]) # may vary
138
+
139
+ """
140
+ [pol] = pu.as_series([pol])
141
+ deg = len(pol) - 1
142
+ res = 0
143
+ for i in range(deg, -1, -1):
144
+ res = legadd(legmulx(res), pol[i])
145
+ return res
146
+
147
+
148
+ def leg2poly(c):
149
+ """
150
+ Convert a Legendre series to a polynomial.
151
+
152
+ Convert an array representing the coefficients of a Legendre series,
153
+ ordered from lowest degree to highest, to an array of the coefficients
154
+ of the equivalent polynomial (relative to the "standard" basis) ordered
155
+ from lowest to highest degree.
156
+
157
+ Parameters
158
+ ----------
159
+ c : array_like
160
+ 1-D array containing the Legendre series coefficients, ordered
161
+ from lowest order term to highest.
162
+
163
+ Returns
164
+ -------
165
+ pol : ndarray
166
+ 1-D array containing the coefficients of the equivalent polynomial
167
+ (relative to the "standard" basis) ordered from lowest order term
168
+ to highest.
169
+
170
+ See Also
171
+ --------
172
+ poly2leg
173
+
174
+ Notes
175
+ -----
176
+ The easy way to do conversions between polynomial basis sets
177
+ is to use the convert method of a class instance.
178
+
179
+ Examples
180
+ --------
181
+ >>> from numpy import polynomial as P
182
+ >>> c = P.Legendre(range(4))
183
+ >>> c
184
+ Legendre([0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
185
+ >>> p = c.convert(kind=P.Polynomial)
186
+ >>> p
187
+ Polynomial([-1. , -3.5, 3. , 7.5], domain=[-1., 1.], window=[-1., 1.])
188
+ >>> P.legendre.leg2poly(range(4))
189
+ array([-1. , -3.5, 3. , 7.5])
190
+
191
+
192
+ """
193
+ from .polynomial import polyadd, polysub, polymulx
194
+
195
+ [c] = pu.as_series([c])
196
+ n = len(c)
197
+ if n < 3:
198
+ return c
199
+ else:
200
+ c0 = c[-2]
201
+ c1 = c[-1]
202
+ # i is the current degree of c1
203
+ for i in range(n - 1, 1, -1):
204
+ tmp = c0
205
+ c0 = polysub(c[i - 2], (c1*(i - 1))/i)
206
+ c1 = polyadd(tmp, (polymulx(c1)*(2*i - 1))/i)
207
+ return polyadd(c0, polymulx(c1))
208
+
209
+ #
210
+ # These are constant arrays are of integer type so as to be compatible
211
+ # with the widest range of other types, such as Decimal.
212
+ #
213
+
214
+ # Legendre
215
+ legdomain = np.array([-1, 1])
216
+
217
+ # Legendre coefficients representing zero.
218
+ legzero = np.array([0])
219
+
220
+ # Legendre coefficients representing one.
221
+ legone = np.array([1])
222
+
223
+ # Legendre coefficients representing the identity x.
224
+ legx = np.array([0, 1])
225
+
226
+
227
+ def legline(off, scl):
228
+ """
229
+ Legendre series whose graph is a straight line.
230
+
231
+
232
+
233
+ Parameters
234
+ ----------
235
+ off, scl : scalars
236
+ The specified line is given by ``off + scl*x``.
237
+
238
+ Returns
239
+ -------
240
+ y : ndarray
241
+ This module's representation of the Legendre series for
242
+ ``off + scl*x``.
243
+
244
+ See Also
245
+ --------
246
+ numpy.polynomial.polynomial.polyline
247
+ numpy.polynomial.chebyshev.chebline
248
+ numpy.polynomial.laguerre.lagline
249
+ numpy.polynomial.hermite.hermline
250
+ numpy.polynomial.hermite_e.hermeline
251
+
252
+ Examples
253
+ --------
254
+ >>> import numpy.polynomial.legendre as L
255
+ >>> L.legline(3,2)
256
+ array([3, 2])
257
+ >>> L.legval(-3, L.legline(3,2)) # should be -3
258
+ -3.0
259
+
260
+ """
261
+ if scl != 0:
262
+ return np.array([off, scl])
263
+ else:
264
+ return np.array([off])
265
+
266
+
267
+ def legfromroots(roots):
268
+ """
269
+ Generate a Legendre series with given roots.
270
+
271
+ The function returns the coefficients of the polynomial
272
+
273
+ .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
274
+
275
+ in Legendre form, where the `r_n` are the roots specified in `roots`.
276
+ If a zero has multiplicity n, then it must appear in `roots` n times.
277
+ For instance, if 2 is a root of multiplicity three and 3 is a root of
278
+ multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3]. The
279
+ roots can appear in any order.
280
+
281
+ If the returned coefficients are `c`, then
282
+
283
+ .. math:: p(x) = c_0 + c_1 * L_1(x) + ... + c_n * L_n(x)
284
+
285
+ The coefficient of the last term is not generally 1 for monic
286
+ polynomials in Legendre form.
287
+
288
+ Parameters
289
+ ----------
290
+ roots : array_like
291
+ Sequence containing the roots.
292
+
293
+ Returns
294
+ -------
295
+ out : ndarray
296
+ 1-D array of coefficients. If all roots are real then `out` is a
297
+ real array, if some of the roots are complex, then `out` is complex
298
+ even if all the coefficients in the result are real (see Examples
299
+ below).
300
+
301
+ See Also
302
+ --------
303
+ numpy.polynomial.polynomial.polyfromroots
304
+ numpy.polynomial.chebyshev.chebfromroots
305
+ numpy.polynomial.laguerre.lagfromroots
306
+ numpy.polynomial.hermite.hermfromroots
307
+ numpy.polynomial.hermite_e.hermefromroots
308
+
309
+ Examples
310
+ --------
311
+ >>> import numpy.polynomial.legendre as L
312
+ >>> L.legfromroots((-1,0,1)) # x^3 - x relative to the standard basis
313
+ array([ 0. , -0.4, 0. , 0.4])
314
+ >>> j = complex(0,1)
315
+ >>> L.legfromroots((-j,j)) # x^2 + 1 relative to the standard basis
316
+ array([ 1.33333333+0.j, 0.00000000+0.j, 0.66666667+0.j]) # may vary
317
+
318
+ """
319
+ return pu._fromroots(legline, legmul, roots)
320
+
321
+
322
+ def legadd(c1, c2):
323
+ """
324
+ Add one Legendre series to another.
325
+
326
+ Returns the sum of two Legendre series `c1` + `c2`. The arguments
327
+ are sequences of coefficients ordered from lowest order term to
328
+ highest, i.e., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
329
+
330
+ Parameters
331
+ ----------
332
+ c1, c2 : array_like
333
+ 1-D arrays of Legendre series coefficients ordered from low to
334
+ high.
335
+
336
+ Returns
337
+ -------
338
+ out : ndarray
339
+ Array representing the Legendre series of their sum.
340
+
341
+ See Also
342
+ --------
343
+ legsub, legmulx, legmul, legdiv, legpow
344
+
345
+ Notes
346
+ -----
347
+ Unlike multiplication, division, etc., the sum of two Legendre series
348
+ is a Legendre series (without having to "reproject" the result onto
349
+ the basis set) so addition, just like that of "standard" polynomials,
350
+ is simply "component-wise."
351
+
352
+ Examples
353
+ --------
354
+ >>> from numpy.polynomial import legendre as L
355
+ >>> c1 = (1,2,3)
356
+ >>> c2 = (3,2,1)
357
+ >>> L.legadd(c1,c2)
358
+ array([4., 4., 4.])
359
+
360
+ """
361
+ return pu._add(c1, c2)
362
+
363
+
364
+ def legsub(c1, c2):
365
+ """
366
+ Subtract one Legendre series from another.
367
+
368
+ Returns the difference of two Legendre series `c1` - `c2`. The
369
+ sequences of coefficients are from lowest order term to highest, i.e.,
370
+ [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
371
+
372
+ Parameters
373
+ ----------
374
+ c1, c2 : array_like
375
+ 1-D arrays of Legendre series coefficients ordered from low to
376
+ high.
377
+
378
+ Returns
379
+ -------
380
+ out : ndarray
381
+ Of Legendre series coefficients representing their difference.
382
+
383
+ See Also
384
+ --------
385
+ legadd, legmulx, legmul, legdiv, legpow
386
+
387
+ Notes
388
+ -----
389
+ Unlike multiplication, division, etc., the difference of two Legendre
390
+ series is a Legendre series (without having to "reproject" the result
391
+ onto the basis set) so subtraction, just like that of "standard"
392
+ polynomials, is simply "component-wise."
393
+
394
+ Examples
395
+ --------
396
+ >>> from numpy.polynomial import legendre as L
397
+ >>> c1 = (1,2,3)
398
+ >>> c2 = (3,2,1)
399
+ >>> L.legsub(c1,c2)
400
+ array([-2., 0., 2.])
401
+ >>> L.legsub(c2,c1) # -C.legsub(c1,c2)
402
+ array([ 2., 0., -2.])
403
+
404
+ """
405
+ return pu._sub(c1, c2)
406
+
407
+
408
+ def legmulx(c):
409
+ """Multiply a Legendre series by x.
410
+
411
+ Multiply the Legendre series `c` by x, where x is the independent
412
+ variable.
413
+
414
+
415
+ Parameters
416
+ ----------
417
+ c : array_like
418
+ 1-D array of Legendre series coefficients ordered from low to
419
+ high.
420
+
421
+ Returns
422
+ -------
423
+ out : ndarray
424
+ Array representing the result of the multiplication.
425
+
426
+ See Also
427
+ --------
428
+ legadd, legmul, legdiv, legpow
429
+
430
+ Notes
431
+ -----
432
+ The multiplication uses the recursion relationship for Legendre
433
+ polynomials in the form
434
+
435
+ .. math::
436
+
437
+ xP_i(x) = ((i + 1)*P_{i + 1}(x) + i*P_{i - 1}(x))/(2i + 1)
438
+
439
+ Examples
440
+ --------
441
+ >>> from numpy.polynomial import legendre as L
442
+ >>> L.legmulx([1,2,3])
443
+ array([ 0.66666667, 2.2, 1.33333333, 1.8]) # may vary
444
+
445
+ """
446
+ # c is a trimmed copy
447
+ [c] = pu.as_series([c])
448
+ # The zero series needs special treatment
449
+ if len(c) == 1 and c[0] == 0:
450
+ return c
451
+
452
+ prd = np.empty(len(c) + 1, dtype=c.dtype)
453
+ prd[0] = c[0]*0
454
+ prd[1] = c[0]
455
+ for i in range(1, len(c)):
456
+ j = i + 1
457
+ k = i - 1
458
+ s = i + j
459
+ prd[j] = (c[i]*j)/s
460
+ prd[k] += (c[i]*i)/s
461
+ return prd
462
+
463
+
464
+ def legmul(c1, c2):
465
+ """
466
+ Multiply one Legendre series by another.
467
+
468
+ Returns the product of two Legendre series `c1` * `c2`. The arguments
469
+ are sequences of coefficients, from lowest order "term" to highest,
470
+ e.g., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
471
+
472
+ Parameters
473
+ ----------
474
+ c1, c2 : array_like
475
+ 1-D arrays of Legendre series coefficients ordered from low to
476
+ high.
477
+
478
+ Returns
479
+ -------
480
+ out : ndarray
481
+ Of Legendre series coefficients representing their product.
482
+
483
+ See Also
484
+ --------
485
+ legadd, legsub, legmulx, legdiv, legpow
486
+
487
+ Notes
488
+ -----
489
+ In general, the (polynomial) product of two C-series results in terms
490
+ that are not in the Legendre polynomial basis set. Thus, to express
491
+ the product as a Legendre series, it is necessary to "reproject" the
492
+ product onto said basis set, which may produce "unintuitive" (but
493
+ correct) results; see Examples section below.
494
+
495
+ Examples
496
+ --------
497
+ >>> from numpy.polynomial import legendre as L
498
+ >>> c1 = (1,2,3)
499
+ >>> c2 = (3,2)
500
+ >>> L.legmul(c1,c2) # multiplication requires "reprojection"
501
+ array([ 4.33333333, 10.4 , 11.66666667, 3.6 ]) # may vary
502
+
503
+ """
504
+ # s1, s2 are trimmed copies
505
+ [c1, c2] = pu.as_series([c1, c2])
506
+
507
+ if len(c1) > len(c2):
508
+ c = c2
509
+ xs = c1
510
+ else:
511
+ c = c1
512
+ xs = c2
513
+
514
+ if len(c) == 1:
515
+ c0 = c[0]*xs
516
+ c1 = 0
517
+ elif len(c) == 2:
518
+ c0 = c[0]*xs
519
+ c1 = c[1]*xs
520
+ else:
521
+ nd = len(c)
522
+ c0 = c[-2]*xs
523
+ c1 = c[-1]*xs
524
+ for i in range(3, len(c) + 1):
525
+ tmp = c0
526
+ nd = nd - 1
527
+ c0 = legsub(c[-i]*xs, (c1*(nd - 1))/nd)
528
+ c1 = legadd(tmp, (legmulx(c1)*(2*nd - 1))/nd)
529
+ return legadd(c0, legmulx(c1))
530
+
531
+
532
+ def legdiv(c1, c2):
533
+ """
534
+ Divide one Legendre series by another.
535
+
536
+ Returns the quotient-with-remainder of two Legendre series
537
+ `c1` / `c2`. The arguments are sequences of coefficients from lowest
538
+ order "term" to highest, e.g., [1,2,3] represents the series
539
+ ``P_0 + 2*P_1 + 3*P_2``.
540
+
541
+ Parameters
542
+ ----------
543
+ c1, c2 : array_like
544
+ 1-D arrays of Legendre series coefficients ordered from low to
545
+ high.
546
+
547
+ Returns
548
+ -------
549
+ quo, rem : ndarrays
550
+ Of Legendre series coefficients representing the quotient and
551
+ remainder.
552
+
553
+ See Also
554
+ --------
555
+ legadd, legsub, legmulx, legmul, legpow
556
+
557
+ Notes
558
+ -----
559
+ In general, the (polynomial) division of one Legendre series by another
560
+ results in quotient and remainder terms that are not in the Legendre
561
+ polynomial basis set. Thus, to express these results as a Legendre
562
+ series, it is necessary to "reproject" the results onto the Legendre
563
+ basis set, which may produce "unintuitive" (but correct) results; see
564
+ Examples section below.
565
+
566
+ Examples
567
+ --------
568
+ >>> from numpy.polynomial import legendre as L
569
+ >>> c1 = (1,2,3)
570
+ >>> c2 = (3,2,1)
571
+ >>> L.legdiv(c1,c2) # quotient "intuitive," remainder not
572
+ (array([3.]), array([-8., -4.]))
573
+ >>> c2 = (0,1,2,3)
574
+ >>> L.legdiv(c2,c1) # neither "intuitive"
575
+ (array([-0.07407407, 1.66666667]), array([-1.03703704, -2.51851852])) # may vary
576
+
577
+ """
578
+ return pu._div(legmul, c1, c2)
579
+
580
+
581
+ def legpow(c, pow, maxpower=16):
582
+ """Raise a Legendre series to a power.
583
+
584
+ Returns the Legendre series `c` raised to the power `pow`. The
585
+ argument `c` is a sequence of coefficients ordered from low to high.
586
+ i.e., [1,2,3] is the series ``P_0 + 2*P_1 + 3*P_2.``
587
+
588
+ Parameters
589
+ ----------
590
+ c : array_like
591
+ 1-D array of Legendre series coefficients ordered from low to
592
+ high.
593
+ pow : integer
594
+ Power to which the series will be raised
595
+ maxpower : integer, optional
596
+ Maximum power allowed. This is mainly to limit growth of the series
597
+ to unmanageable size. Default is 16
598
+
599
+ Returns
600
+ -------
601
+ coef : ndarray
602
+ Legendre series of power.
603
+
604
+ See Also
605
+ --------
606
+ legadd, legsub, legmulx, legmul, legdiv
607
+
608
+ """
609
+ return pu._pow(legmul, c, pow, maxpower)
610
+
611
+
612
+ def legder(c, m=1, scl=1, axis=0):
613
+ """
614
+ Differentiate a Legendre series.
615
+
616
+ Returns the Legendre series coefficients `c` differentiated `m` times
617
+ along `axis`. At each iteration the result is multiplied by `scl` (the
618
+ scaling factor is for use in a linear change of variable). The argument
619
+ `c` is an array of coefficients from low to high degree along each
620
+ axis, e.g., [1,2,3] represents the series ``1*L_0 + 2*L_1 + 3*L_2``
621
+ while [[1,2],[1,2]] represents ``1*L_0(x)*L_0(y) + 1*L_1(x)*L_0(y) +
622
+ 2*L_0(x)*L_1(y) + 2*L_1(x)*L_1(y)`` if axis=0 is ``x`` and axis=1 is
623
+ ``y``.
624
+
625
+ Parameters
626
+ ----------
627
+ c : array_like
628
+ Array of Legendre series coefficients. If c is multidimensional the
629
+ different axis correspond to different variables with the degree in
630
+ each axis given by the corresponding index.
631
+ m : int, optional
632
+ Number of derivatives taken, must be non-negative. (Default: 1)
633
+ scl : scalar, optional
634
+ Each differentiation is multiplied by `scl`. The end result is
635
+ multiplication by ``scl**m``. This is for use in a linear change of
636
+ variable. (Default: 1)
637
+ axis : int, optional
638
+ Axis over which the derivative is taken. (Default: 0).
639
+
640
+ .. versionadded:: 1.7.0
641
+
642
+ Returns
643
+ -------
644
+ der : ndarray
645
+ Legendre series of the derivative.
646
+
647
+ See Also
648
+ --------
649
+ legint
650
+
651
+ Notes
652
+ -----
653
+ In general, the result of differentiating a Legendre series does not
654
+ resemble the same operation on a power series. Thus the result of this
655
+ function may be "unintuitive," albeit correct; see Examples section
656
+ below.
657
+
658
+ Examples
659
+ --------
660
+ >>> from numpy.polynomial import legendre as L
661
+ >>> c = (1,2,3,4)
662
+ >>> L.legder(c)
663
+ array([ 6., 9., 20.])
664
+ >>> L.legder(c, 3)
665
+ array([60.])
666
+ >>> L.legder(c, scl=-1)
667
+ array([ -6., -9., -20.])
668
+ >>> L.legder(c, 2,-1)
669
+ array([ 9., 60.])
670
+
671
+ """
672
+ c = np.array(c, ndmin=1, copy=True)
673
+ if c.dtype.char in '?bBhHiIlLqQpP':
674
+ c = c.astype(np.double)
675
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
676
+ iaxis = pu._deprecate_as_int(axis, "the axis")
677
+ if cnt < 0:
678
+ raise ValueError("The order of derivation must be non-negative")
679
+ iaxis = normalize_axis_index(iaxis, c.ndim)
680
+
681
+ if cnt == 0:
682
+ return c
683
+
684
+ c = np.moveaxis(c, iaxis, 0)
685
+ n = len(c)
686
+ if cnt >= n:
687
+ c = c[:1]*0
688
+ else:
689
+ for i in range(cnt):
690
+ n = n - 1
691
+ c *= scl
692
+ der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
693
+ for j in range(n, 2, -1):
694
+ der[j - 1] = (2*j - 1)*c[j]
695
+ c[j - 2] += c[j]
696
+ if n > 1:
697
+ der[1] = 3*c[2]
698
+ der[0] = c[1]
699
+ c = der
700
+ c = np.moveaxis(c, 0, iaxis)
701
+ return c
702
+
703
+
704
+ def legint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
705
+ """
706
+ Integrate a Legendre series.
707
+
708
+ Returns the Legendre series coefficients `c` integrated `m` times from
709
+ `lbnd` along `axis`. At each iteration the resulting series is
710
+ **multiplied** by `scl` and an integration constant, `k`, is added.
711
+ The scaling factor is for use in a linear change of variable. ("Buyer
712
+ beware": note that, depending on what one is doing, one may want `scl`
713
+ to be the reciprocal of what one might expect; for more information,
714
+ see the Notes section below.) The argument `c` is an array of
715
+ coefficients from low to high degree along each axis, e.g., [1,2,3]
716
+ represents the series ``L_0 + 2*L_1 + 3*L_2`` while [[1,2],[1,2]]
717
+ represents ``1*L_0(x)*L_0(y) + 1*L_1(x)*L_0(y) + 2*L_0(x)*L_1(y) +
718
+ 2*L_1(x)*L_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
719
+
720
+ Parameters
721
+ ----------
722
+ c : array_like
723
+ Array of Legendre series coefficients. If c is multidimensional the
724
+ different axis correspond to different variables with the degree in
725
+ each axis given by the corresponding index.
726
+ m : int, optional
727
+ Order of integration, must be positive. (Default: 1)
728
+ k : {[], list, scalar}, optional
729
+ Integration constant(s). The value of the first integral at
730
+ ``lbnd`` is the first value in the list, the value of the second
731
+ integral at ``lbnd`` is the second value, etc. If ``k == []`` (the
732
+ default), all constants are set to zero. If ``m == 1``, a single
733
+ scalar can be given instead of a list.
734
+ lbnd : scalar, optional
735
+ The lower bound of the integral. (Default: 0)
736
+ scl : scalar, optional
737
+ Following each integration the result is *multiplied* by `scl`
738
+ before the integration constant is added. (Default: 1)
739
+ axis : int, optional
740
+ Axis over which the integral is taken. (Default: 0).
741
+
742
+ .. versionadded:: 1.7.0
743
+
744
+ Returns
745
+ -------
746
+ S : ndarray
747
+ Legendre series coefficient array of the integral.
748
+
749
+ Raises
750
+ ------
751
+ ValueError
752
+ If ``m < 0``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
753
+ ``np.ndim(scl) != 0``.
754
+
755
+ See Also
756
+ --------
757
+ legder
758
+
759
+ Notes
760
+ -----
761
+ Note that the result of each integration is *multiplied* by `scl`.
762
+ Why is this important to note? Say one is making a linear change of
763
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
764
+ :math:`dx = du/a`, so one will need to set `scl` equal to
765
+ :math:`1/a` - perhaps not what one would have first thought.
766
+
767
+ Also note that, in general, the result of integrating a C-series needs
768
+ to be "reprojected" onto the C-series basis set. Thus, typically,
769
+ the result of this function is "unintuitive," albeit correct; see
770
+ Examples section below.
771
+
772
+ Examples
773
+ --------
774
+ >>> from numpy.polynomial import legendre as L
775
+ >>> c = (1,2,3)
776
+ >>> L.legint(c)
777
+ array([ 0.33333333, 0.4 , 0.66666667, 0.6 ]) # may vary
778
+ >>> L.legint(c, 3)
779
+ array([ 1.66666667e-02, -1.78571429e-02, 4.76190476e-02, # may vary
780
+ -1.73472348e-18, 1.90476190e-02, 9.52380952e-03])
781
+ >>> L.legint(c, k=3)
782
+ array([ 3.33333333, 0.4 , 0.66666667, 0.6 ]) # may vary
783
+ >>> L.legint(c, lbnd=-2)
784
+ array([ 7.33333333, 0.4 , 0.66666667, 0.6 ]) # may vary
785
+ >>> L.legint(c, scl=2)
786
+ array([ 0.66666667, 0.8 , 1.33333333, 1.2 ]) # may vary
787
+
788
+ """
789
+ c = np.array(c, ndmin=1, copy=True)
790
+ if c.dtype.char in '?bBhHiIlLqQpP':
791
+ c = c.astype(np.double)
792
+ if not np.iterable(k):
793
+ k = [k]
794
+ cnt = pu._deprecate_as_int(m, "the order of integration")
795
+ iaxis = pu._deprecate_as_int(axis, "the axis")
796
+ if cnt < 0:
797
+ raise ValueError("The order of integration must be non-negative")
798
+ if len(k) > cnt:
799
+ raise ValueError("Too many integration constants")
800
+ if np.ndim(lbnd) != 0:
801
+ raise ValueError("lbnd must be a scalar.")
802
+ if np.ndim(scl) != 0:
803
+ raise ValueError("scl must be a scalar.")
804
+ iaxis = normalize_axis_index(iaxis, c.ndim)
805
+
806
+ if cnt == 0:
807
+ return c
808
+
809
+ c = np.moveaxis(c, iaxis, 0)
810
+ k = list(k) + [0]*(cnt - len(k))
811
+ for i in range(cnt):
812
+ n = len(c)
813
+ c *= scl
814
+ if n == 1 and np.all(c[0] == 0):
815
+ c[0] += k[i]
816
+ else:
817
+ tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
818
+ tmp[0] = c[0]*0
819
+ tmp[1] = c[0]
820
+ if n > 1:
821
+ tmp[2] = c[1]/3
822
+ for j in range(2, n):
823
+ t = c[j]/(2*j + 1)
824
+ tmp[j + 1] = t
825
+ tmp[j - 1] -= t
826
+ tmp[0] += k[i] - legval(lbnd, tmp)
827
+ c = tmp
828
+ c = np.moveaxis(c, 0, iaxis)
829
+ return c
830
+
831
+
832
+ def legval(x, c, tensor=True):
833
+ """
834
+ Evaluate a Legendre series at points x.
835
+
836
+ If `c` is of length `n + 1`, this function returns the value:
837
+
838
+ .. math:: p(x) = c_0 * L_0(x) + c_1 * L_1(x) + ... + c_n * L_n(x)
839
+
840
+ The parameter `x` is converted to an array only if it is a tuple or a
841
+ list, otherwise it is treated as a scalar. In either case, either `x`
842
+ or its elements must support multiplication and addition both with
843
+ themselves and with the elements of `c`.
844
+
845
+ If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
846
+ `c` is multidimensional, then the shape of the result depends on the
847
+ value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
848
+ x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
849
+ scalars have shape (,).
850
+
851
+ Trailing zeros in the coefficients will be used in the evaluation, so
852
+ they should be avoided if efficiency is a concern.
853
+
854
+ Parameters
855
+ ----------
856
+ x : array_like, compatible object
857
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
858
+ it is left unchanged and treated as a scalar. In either case, `x`
859
+ or its elements must support addition and multiplication with
860
+ themselves and with the elements of `c`.
861
+ c : array_like
862
+ Array of coefficients ordered so that the coefficients for terms of
863
+ degree n are contained in c[n]. If `c` is multidimensional the
864
+ remaining indices enumerate multiple polynomials. In the two
865
+ dimensional case the coefficients may be thought of as stored in
866
+ the columns of `c`.
867
+ tensor : boolean, optional
868
+ If True, the shape of the coefficient array is extended with ones
869
+ on the right, one for each dimension of `x`. Scalars have dimension 0
870
+ for this action. The result is that every column of coefficients in
871
+ `c` is evaluated for every element of `x`. If False, `x` is broadcast
872
+ over the columns of `c` for the evaluation. This keyword is useful
873
+ when `c` is multidimensional. The default value is True.
874
+
875
+ .. versionadded:: 1.7.0
876
+
877
+ Returns
878
+ -------
879
+ values : ndarray, algebra_like
880
+ The shape of the return value is described above.
881
+
882
+ See Also
883
+ --------
884
+ legval2d, leggrid2d, legval3d, leggrid3d
885
+
886
+ Notes
887
+ -----
888
+ The evaluation uses Clenshaw recursion, aka synthetic division.
889
+
890
+ """
891
+ c = np.array(c, ndmin=1, copy=False)
892
+ if c.dtype.char in '?bBhHiIlLqQpP':
893
+ c = c.astype(np.double)
894
+ if isinstance(x, (tuple, list)):
895
+ x = np.asarray(x)
896
+ if isinstance(x, np.ndarray) and tensor:
897
+ c = c.reshape(c.shape + (1,)*x.ndim)
898
+
899
+ if len(c) == 1:
900
+ c0 = c[0]
901
+ c1 = 0
902
+ elif len(c) == 2:
903
+ c0 = c[0]
904
+ c1 = c[1]
905
+ else:
906
+ nd = len(c)
907
+ c0 = c[-2]
908
+ c1 = c[-1]
909
+ for i in range(3, len(c) + 1):
910
+ tmp = c0
911
+ nd = nd - 1
912
+ c0 = c[-i] - (c1*(nd - 1))/nd
913
+ c1 = tmp + (c1*x*(2*nd - 1))/nd
914
+ return c0 + c1*x
915
+
916
+
917
+ def legval2d(x, y, c):
918
+ """
919
+ Evaluate a 2-D Legendre series at points (x, y).
920
+
921
+ This function returns the values:
922
+
923
+ .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * L_i(x) * L_j(y)
924
+
925
+ The parameters `x` and `y` are converted to arrays only if they are
926
+ tuples or a lists, otherwise they are treated as a scalars and they
927
+ must have the same shape after conversion. In either case, either `x`
928
+ and `y` or their elements must support multiplication and addition both
929
+ with themselves and with the elements of `c`.
930
+
931
+ If `c` is a 1-D array a one is implicitly appended to its shape to make
932
+ it 2-D. The shape of the result will be c.shape[2:] + x.shape.
933
+
934
+ Parameters
935
+ ----------
936
+ x, y : array_like, compatible objects
937
+ The two dimensional series is evaluated at the points `(x, y)`,
938
+ where `x` and `y` must have the same shape. If `x` or `y` is a list
939
+ or tuple, it is first converted to an ndarray, otherwise it is left
940
+ unchanged and if it isn't an ndarray it is treated as a scalar.
941
+ c : array_like
942
+ Array of coefficients ordered so that the coefficient of the term
943
+ of multi-degree i,j is contained in ``c[i,j]``. If `c` has
944
+ dimension greater than two the remaining indices enumerate multiple
945
+ sets of coefficients.
946
+
947
+ Returns
948
+ -------
949
+ values : ndarray, compatible object
950
+ The values of the two dimensional Legendre series at points formed
951
+ from pairs of corresponding values from `x` and `y`.
952
+
953
+ See Also
954
+ --------
955
+ legval, leggrid2d, legval3d, leggrid3d
956
+
957
+ Notes
958
+ -----
959
+
960
+ .. versionadded:: 1.7.0
961
+
962
+ """
963
+ return pu._valnd(legval, c, x, y)
964
+
965
+
966
+ def leggrid2d(x, y, c):
967
+ """
968
+ Evaluate a 2-D Legendre series on the Cartesian product of x and y.
969
+
970
+ This function returns the values:
971
+
972
+ .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * L_i(a) * L_j(b)
973
+
974
+ where the points `(a, b)` consist of all pairs formed by taking
975
+ `a` from `x` and `b` from `y`. The resulting points form a grid with
976
+ `x` in the first dimension and `y` in the second.
977
+
978
+ The parameters `x` and `y` are converted to arrays only if they are
979
+ tuples or a lists, otherwise they are treated as a scalars. In either
980
+ case, either `x` and `y` or their elements must support multiplication
981
+ and addition both with themselves and with the elements of `c`.
982
+
983
+ If `c` has fewer than two dimensions, ones are implicitly appended to
984
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
985
+ x.shape + y.shape.
986
+
987
+ Parameters
988
+ ----------
989
+ x, y : array_like, compatible objects
990
+ The two dimensional series is evaluated at the points in the
991
+ Cartesian product of `x` and `y`. If `x` or `y` is a list or
992
+ tuple, it is first converted to an ndarray, otherwise it is left
993
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
994
+ c : array_like
995
+ Array of coefficients ordered so that the coefficient of the term of
996
+ multi-degree i,j is contained in `c[i,j]`. If `c` has dimension
997
+ greater than two the remaining indices enumerate multiple sets of
998
+ coefficients.
999
+
1000
+ Returns
1001
+ -------
1002
+ values : ndarray, compatible object
1003
+ The values of the two dimensional Chebyshev series at points in the
1004
+ Cartesian product of `x` and `y`.
1005
+
1006
+ See Also
1007
+ --------
1008
+ legval, legval2d, legval3d, leggrid3d
1009
+
1010
+ Notes
1011
+ -----
1012
+
1013
+ .. versionadded:: 1.7.0
1014
+
1015
+ """
1016
+ return pu._gridnd(legval, c, x, y)
1017
+
1018
+
1019
+ def legval3d(x, y, z, c):
1020
+ """
1021
+ Evaluate a 3-D Legendre series at points (x, y, z).
1022
+
1023
+ This function returns the values:
1024
+
1025
+ .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * L_i(x) * L_j(y) * L_k(z)
1026
+
1027
+ The parameters `x`, `y`, and `z` are converted to arrays only if
1028
+ they are tuples or a lists, otherwise they are treated as a scalars and
1029
+ they must have the same shape after conversion. In either case, either
1030
+ `x`, `y`, and `z` or their elements must support multiplication and
1031
+ addition both with themselves and with the elements of `c`.
1032
+
1033
+ If `c` has fewer than 3 dimensions, ones are implicitly appended to its
1034
+ shape to make it 3-D. The shape of the result will be c.shape[3:] +
1035
+ x.shape.
1036
+
1037
+ Parameters
1038
+ ----------
1039
+ x, y, z : array_like, compatible object
1040
+ The three dimensional series is evaluated at the points
1041
+ `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
1042
+ any of `x`, `y`, or `z` is a list or tuple, it is first converted
1043
+ to an ndarray, otherwise it is left unchanged and if it isn't an
1044
+ ndarray it is treated as a scalar.
1045
+ c : array_like
1046
+ Array of coefficients ordered so that the coefficient of the term of
1047
+ multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
1048
+ greater than 3 the remaining indices enumerate multiple sets of
1049
+ coefficients.
1050
+
1051
+ Returns
1052
+ -------
1053
+ values : ndarray, compatible object
1054
+ The values of the multidimensional polynomial on points formed with
1055
+ triples of corresponding values from `x`, `y`, and `z`.
1056
+
1057
+ See Also
1058
+ --------
1059
+ legval, legval2d, leggrid2d, leggrid3d
1060
+
1061
+ Notes
1062
+ -----
1063
+
1064
+ .. versionadded:: 1.7.0
1065
+
1066
+ """
1067
+ return pu._valnd(legval, c, x, y, z)
1068
+
1069
+
1070
+ def leggrid3d(x, y, z, c):
1071
+ """
1072
+ Evaluate a 3-D Legendre series on the Cartesian product of x, y, and z.
1073
+
1074
+ This function returns the values:
1075
+
1076
+ .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * L_i(a) * L_j(b) * L_k(c)
1077
+
1078
+ where the points `(a, b, c)` consist of all triples formed by taking
1079
+ `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
1080
+ a grid with `x` in the first dimension, `y` in the second, and `z` in
1081
+ the third.
1082
+
1083
+ The parameters `x`, `y`, and `z` are converted to arrays only if they
1084
+ are tuples or a lists, otherwise they are treated as a scalars. In
1085
+ either case, either `x`, `y`, and `z` or their elements must support
1086
+ multiplication and addition both with themselves and with the elements
1087
+ of `c`.
1088
+
1089
+ If `c` has fewer than three dimensions, ones are implicitly appended to
1090
+ its shape to make it 3-D. The shape of the result will be c.shape[3:] +
1091
+ x.shape + y.shape + z.shape.
1092
+
1093
+ Parameters
1094
+ ----------
1095
+ x, y, z : array_like, compatible objects
1096
+ The three dimensional series is evaluated at the points in the
1097
+ Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
1098
+ list or tuple, it is first converted to an ndarray, otherwise it is
1099
+ left unchanged and, if it isn't an ndarray, it is treated as a
1100
+ scalar.
1101
+ c : array_like
1102
+ Array of coefficients ordered so that the coefficients for terms of
1103
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
1104
+ greater than two the remaining indices enumerate multiple sets of
1105
+ coefficients.
1106
+
1107
+ Returns
1108
+ -------
1109
+ values : ndarray, compatible object
1110
+ The values of the two dimensional polynomial at points in the Cartesian
1111
+ product of `x` and `y`.
1112
+
1113
+ See Also
1114
+ --------
1115
+ legval, legval2d, leggrid2d, legval3d
1116
+
1117
+ Notes
1118
+ -----
1119
+
1120
+ .. versionadded:: 1.7.0
1121
+
1122
+ """
1123
+ return pu._gridnd(legval, c, x, y, z)
1124
+
1125
+
1126
+ def legvander(x, deg):
1127
+ """Pseudo-Vandermonde matrix of given degree.
1128
+
1129
+ Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
1130
+ `x`. The pseudo-Vandermonde matrix is defined by
1131
+
1132
+ .. math:: V[..., i] = L_i(x)
1133
+
1134
+ where `0 <= i <= deg`. The leading indices of `V` index the elements of
1135
+ `x` and the last index is the degree of the Legendre polynomial.
1136
+
1137
+ If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
1138
+ array ``V = legvander(x, n)``, then ``np.dot(V, c)`` and
1139
+ ``legval(x, c)`` are the same up to roundoff. This equivalence is
1140
+ useful both for least squares fitting and for the evaluation of a large
1141
+ number of Legendre series of the same degree and sample points.
1142
+
1143
+ Parameters
1144
+ ----------
1145
+ x : array_like
1146
+ Array of points. The dtype is converted to float64 or complex128
1147
+ depending on whether any of the elements are complex. If `x` is
1148
+ scalar it is converted to a 1-D array.
1149
+ deg : int
1150
+ Degree of the resulting matrix.
1151
+
1152
+ Returns
1153
+ -------
1154
+ vander : ndarray
1155
+ The pseudo-Vandermonde matrix. The shape of the returned matrix is
1156
+ ``x.shape + (deg + 1,)``, where The last index is the degree of the
1157
+ corresponding Legendre polynomial. The dtype will be the same as
1158
+ the converted `x`.
1159
+
1160
+ """
1161
+ ideg = pu._deprecate_as_int(deg, "deg")
1162
+ if ideg < 0:
1163
+ raise ValueError("deg must be non-negative")
1164
+
1165
+ x = np.array(x, copy=False, ndmin=1) + 0.0
1166
+ dims = (ideg + 1,) + x.shape
1167
+ dtyp = x.dtype
1168
+ v = np.empty(dims, dtype=dtyp)
1169
+ # Use forward recursion to generate the entries. This is not as accurate
1170
+ # as reverse recursion in this application but it is more efficient.
1171
+ v[0] = x*0 + 1
1172
+ if ideg > 0:
1173
+ v[1] = x
1174
+ for i in range(2, ideg + 1):
1175
+ v[i] = (v[i-1]*x*(2*i - 1) - v[i-2]*(i - 1))/i
1176
+ return np.moveaxis(v, 0, -1)
1177
+
1178
+
1179
+ def legvander2d(x, y, deg):
1180
+ """Pseudo-Vandermonde matrix of given degrees.
1181
+
1182
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1183
+ points `(x, y)`. The pseudo-Vandermonde matrix is defined by
1184
+
1185
+ .. math:: V[..., (deg[1] + 1)*i + j] = L_i(x) * L_j(y),
1186
+
1187
+ where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
1188
+ `V` index the points `(x, y)` and the last index encodes the degrees of
1189
+ the Legendre polynomials.
1190
+
1191
+ If ``V = legvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
1192
+ correspond to the elements of a 2-D coefficient array `c` of shape
1193
+ (xdeg + 1, ydeg + 1) in the order
1194
+
1195
+ .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
1196
+
1197
+ and ``np.dot(V, c.flat)`` and ``legval2d(x, y, c)`` will be the same
1198
+ up to roundoff. This equivalence is useful both for least squares
1199
+ fitting and for the evaluation of a large number of 2-D Legendre
1200
+ series of the same degrees and sample points.
1201
+
1202
+ Parameters
1203
+ ----------
1204
+ x, y : array_like
1205
+ Arrays of point coordinates, all of the same shape. The dtypes
1206
+ will be converted to either float64 or complex128 depending on
1207
+ whether any of the elements are complex. Scalars are converted to
1208
+ 1-D arrays.
1209
+ deg : list of ints
1210
+ List of maximum degrees of the form [x_deg, y_deg].
1211
+
1212
+ Returns
1213
+ -------
1214
+ vander2d : ndarray
1215
+ The shape of the returned matrix is ``x.shape + (order,)``, where
1216
+ :math:`order = (deg[0]+1)*(deg[1]+1)`. The dtype will be the same
1217
+ as the converted `x` and `y`.
1218
+
1219
+ See Also
1220
+ --------
1221
+ legvander, legvander3d, legval2d, legval3d
1222
+
1223
+ Notes
1224
+ -----
1225
+
1226
+ .. versionadded:: 1.7.0
1227
+
1228
+ """
1229
+ return pu._vander_nd_flat((legvander, legvander), (x, y), deg)
1230
+
1231
+
1232
+ def legvander3d(x, y, z, deg):
1233
+ """Pseudo-Vandermonde matrix of given degrees.
1234
+
1235
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1236
+ points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
1237
+ then The pseudo-Vandermonde matrix is defined by
1238
+
1239
+ .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = L_i(x)*L_j(y)*L_k(z),
1240
+
1241
+ where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
1242
+ indices of `V` index the points `(x, y, z)` and the last index encodes
1243
+ the degrees of the Legendre polynomials.
1244
+
1245
+ If ``V = legvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
1246
+ of `V` correspond to the elements of a 3-D coefficient array `c` of
1247
+ shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
1248
+
1249
+ .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
1250
+
1251
+ and ``np.dot(V, c.flat)`` and ``legval3d(x, y, z, c)`` will be the
1252
+ same up to roundoff. This equivalence is useful both for least squares
1253
+ fitting and for the evaluation of a large number of 3-D Legendre
1254
+ series of the same degrees and sample points.
1255
+
1256
+ Parameters
1257
+ ----------
1258
+ x, y, z : array_like
1259
+ Arrays of point coordinates, all of the same shape. The dtypes will
1260
+ be converted to either float64 or complex128 depending on whether
1261
+ any of the elements are complex. Scalars are converted to 1-D
1262
+ arrays.
1263
+ deg : list of ints
1264
+ List of maximum degrees of the form [x_deg, y_deg, z_deg].
1265
+
1266
+ Returns
1267
+ -------
1268
+ vander3d : ndarray
1269
+ The shape of the returned matrix is ``x.shape + (order,)``, where
1270
+ :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`. The dtype will
1271
+ be the same as the converted `x`, `y`, and `z`.
1272
+
1273
+ See Also
1274
+ --------
1275
+ legvander, legvander3d, legval2d, legval3d
1276
+
1277
+ Notes
1278
+ -----
1279
+
1280
+ .. versionadded:: 1.7.0
1281
+
1282
+ """
1283
+ return pu._vander_nd_flat((legvander, legvander, legvander), (x, y, z), deg)
1284
+
1285
+
1286
+ def legfit(x, y, deg, rcond=None, full=False, w=None):
1287
+ """
1288
+ Least squares fit of Legendre series to data.
1289
+
1290
+ Return the coefficients of a Legendre series of degree `deg` that is the
1291
+ least squares fit to the data values `y` given at points `x`. If `y` is
1292
+ 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
1293
+ fits are done, one for each column of `y`, and the resulting
1294
+ coefficients are stored in the corresponding columns of a 2-D return.
1295
+ The fitted polynomial(s) are in the form
1296
+
1297
+ .. math:: p(x) = c_0 + c_1 * L_1(x) + ... + c_n * L_n(x),
1298
+
1299
+ where `n` is `deg`.
1300
+
1301
+ Parameters
1302
+ ----------
1303
+ x : array_like, shape (M,)
1304
+ x-coordinates of the M sample points ``(x[i], y[i])``.
1305
+ y : array_like, shape (M,) or (M, K)
1306
+ y-coordinates of the sample points. Several data sets of sample
1307
+ points sharing the same x-coordinates can be fitted at once by
1308
+ passing in a 2D-array that contains one dataset per column.
1309
+ deg : int or 1-D array_like
1310
+ Degree(s) of the fitting polynomials. If `deg` is a single integer
1311
+ all terms up to and including the `deg`'th term are included in the
1312
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
1313
+ degrees of the terms to include may be used instead.
1314
+ rcond : float, optional
1315
+ Relative condition number of the fit. Singular values smaller than
1316
+ this relative to the largest singular value will be ignored. The
1317
+ default value is len(x)*eps, where eps is the relative precision of
1318
+ the float type, about 2e-16 in most cases.
1319
+ full : bool, optional
1320
+ Switch determining nature of return value. When it is False (the
1321
+ default) just the coefficients are returned, when True diagnostic
1322
+ information from the singular value decomposition is also returned.
1323
+ w : array_like, shape (`M`,), optional
1324
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
1325
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
1326
+ chosen so that the errors of the products ``w[i]*y[i]`` all have the
1327
+ same variance. When using inverse-variance weighting, use
1328
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
1329
+
1330
+ .. versionadded:: 1.5.0
1331
+
1332
+ Returns
1333
+ -------
1334
+ coef : ndarray, shape (M,) or (M, K)
1335
+ Legendre coefficients ordered from low to high. If `y` was
1336
+ 2-D, the coefficients for the data in column k of `y` are in
1337
+ column `k`. If `deg` is specified as a list, coefficients for
1338
+ terms not included in the fit are set equal to zero in the
1339
+ returned `coef`.
1340
+
1341
+ [residuals, rank, singular_values, rcond] : list
1342
+ These values are only returned if ``full == True``
1343
+
1344
+ - residuals -- sum of squared residuals of the least squares fit
1345
+ - rank -- the numerical rank of the scaled Vandermonde matrix
1346
+ - singular_values -- singular values of the scaled Vandermonde matrix
1347
+ - rcond -- value of `rcond`.
1348
+
1349
+ For more details, see `numpy.linalg.lstsq`.
1350
+
1351
+ Warns
1352
+ -----
1353
+ RankWarning
1354
+ The rank of the coefficient matrix in the least-squares fit is
1355
+ deficient. The warning is only raised if ``full == False``. The
1356
+ warnings can be turned off by
1357
+
1358
+ >>> import warnings
1359
+ >>> warnings.simplefilter('ignore', np.RankWarning)
1360
+
1361
+ See Also
1362
+ --------
1363
+ numpy.polynomial.polynomial.polyfit
1364
+ numpy.polynomial.chebyshev.chebfit
1365
+ numpy.polynomial.laguerre.lagfit
1366
+ numpy.polynomial.hermite.hermfit
1367
+ numpy.polynomial.hermite_e.hermefit
1368
+ legval : Evaluates a Legendre series.
1369
+ legvander : Vandermonde matrix of Legendre series.
1370
+ legweight : Legendre weight function (= 1).
1371
+ numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
1372
+ scipy.interpolate.UnivariateSpline : Computes spline fits.
1373
+
1374
+ Notes
1375
+ -----
1376
+ The solution is the coefficients of the Legendre series `p` that
1377
+ minimizes the sum of the weighted squared errors
1378
+
1379
+ .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
1380
+
1381
+ where :math:`w_j` are the weights. This problem is solved by setting up
1382
+ as the (typically) overdetermined matrix equation
1383
+
1384
+ .. math:: V(x) * c = w * y,
1385
+
1386
+ where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the
1387
+ coefficients to be solved for, `w` are the weights, and `y` are the
1388
+ observed values. This equation is then solved using the singular value
1389
+ decomposition of `V`.
1390
+
1391
+ If some of the singular values of `V` are so small that they are
1392
+ neglected, then a `RankWarning` will be issued. This means that the
1393
+ coefficient values may be poorly determined. Using a lower order fit
1394
+ will usually get rid of the warning. The `rcond` parameter can also be
1395
+ set to a value smaller than its default, but the resulting fit may be
1396
+ spurious and have large contributions from roundoff error.
1397
+
1398
+ Fits using Legendre series are usually better conditioned than fits
1399
+ using power series, but much can depend on the distribution of the
1400
+ sample points and the smoothness of the data. If the quality of the fit
1401
+ is inadequate splines may be a good alternative.
1402
+
1403
+ References
1404
+ ----------
1405
+ .. [1] Wikipedia, "Curve fitting",
1406
+ https://en.wikipedia.org/wiki/Curve_fitting
1407
+
1408
+ Examples
1409
+ --------
1410
+
1411
+ """
1412
+ return pu._fit(legvander, x, y, deg, rcond, full, w)
1413
+
1414
+
1415
+ def legcompanion(c):
1416
+ """Return the scaled companion matrix of c.
1417
+
1418
+ The basis polynomials are scaled so that the companion matrix is
1419
+ symmetric when `c` is an Legendre basis polynomial. This provides
1420
+ better eigenvalue estimates than the unscaled case and for basis
1421
+ polynomials the eigenvalues are guaranteed to be real if
1422
+ `numpy.linalg.eigvalsh` is used to obtain them.
1423
+
1424
+ Parameters
1425
+ ----------
1426
+ c : array_like
1427
+ 1-D array of Legendre series coefficients ordered from low to high
1428
+ degree.
1429
+
1430
+ Returns
1431
+ -------
1432
+ mat : ndarray
1433
+ Scaled companion matrix of dimensions (deg, deg).
1434
+
1435
+ Notes
1436
+ -----
1437
+
1438
+ .. versionadded:: 1.7.0
1439
+
1440
+ """
1441
+ # c is a trimmed copy
1442
+ [c] = pu.as_series([c])
1443
+ if len(c) < 2:
1444
+ raise ValueError('Series must have maximum degree of at least 1.')
1445
+ if len(c) == 2:
1446
+ return np.array([[-c[0]/c[1]]])
1447
+
1448
+ n = len(c) - 1
1449
+ mat = np.zeros((n, n), dtype=c.dtype)
1450
+ scl = 1./np.sqrt(2*np.arange(n) + 1)
1451
+ top = mat.reshape(-1)[1::n+1]
1452
+ bot = mat.reshape(-1)[n::n+1]
1453
+ top[...] = np.arange(1, n)*scl[:n-1]*scl[1:n]
1454
+ bot[...] = top
1455
+ mat[:, -1] -= (c[:-1]/c[-1])*(scl/scl[-1])*(n/(2*n - 1))
1456
+ return mat
1457
+
1458
+
1459
+ def legroots(c):
1460
+ """
1461
+ Compute the roots of a Legendre series.
1462
+
1463
+ Return the roots (a.k.a. "zeros") of the polynomial
1464
+
1465
+ .. math:: p(x) = \\sum_i c[i] * L_i(x).
1466
+
1467
+ Parameters
1468
+ ----------
1469
+ c : 1-D array_like
1470
+ 1-D array of coefficients.
1471
+
1472
+ Returns
1473
+ -------
1474
+ out : ndarray
1475
+ Array of the roots of the series. If all the roots are real,
1476
+ then `out` is also real, otherwise it is complex.
1477
+
1478
+ See Also
1479
+ --------
1480
+ numpy.polynomial.polynomial.polyroots
1481
+ numpy.polynomial.chebyshev.chebroots
1482
+ numpy.polynomial.laguerre.lagroots
1483
+ numpy.polynomial.hermite.hermroots
1484
+ numpy.polynomial.hermite_e.hermeroots
1485
+
1486
+ Notes
1487
+ -----
1488
+ The root estimates are obtained as the eigenvalues of the companion
1489
+ matrix, Roots far from the origin of the complex plane may have large
1490
+ errors due to the numerical instability of the series for such values.
1491
+ Roots with multiplicity greater than 1 will also show larger errors as
1492
+ the value of the series near such points is relatively insensitive to
1493
+ errors in the roots. Isolated roots near the origin can be improved by
1494
+ a few iterations of Newton's method.
1495
+
1496
+ The Legendre series basis polynomials aren't powers of ``x`` so the
1497
+ results of this function may seem unintuitive.
1498
+
1499
+ Examples
1500
+ --------
1501
+ >>> import numpy.polynomial.legendre as leg
1502
+ >>> leg.legroots((1, 2, 3, 4)) # 4L_3 + 3L_2 + 2L_1 + 1L_0, all real roots
1503
+ array([-0.85099543, -0.11407192, 0.51506735]) # may vary
1504
+
1505
+ """
1506
+ # c is a trimmed copy
1507
+ [c] = pu.as_series([c])
1508
+ if len(c) < 2:
1509
+ return np.array([], dtype=c.dtype)
1510
+ if len(c) == 2:
1511
+ return np.array([-c[0]/c[1]])
1512
+
1513
+ # rotated companion matrix reduces error
1514
+ m = legcompanion(c)[::-1,::-1]
1515
+ r = la.eigvals(m)
1516
+ r.sort()
1517
+ return r
1518
+
1519
+
1520
+ def leggauss(deg):
1521
+ """
1522
+ Gauss-Legendre quadrature.
1523
+
1524
+ Computes the sample points and weights for Gauss-Legendre quadrature.
1525
+ These sample points and weights will correctly integrate polynomials of
1526
+ degree :math:`2*deg - 1` or less over the interval :math:`[-1, 1]` with
1527
+ the weight function :math:`f(x) = 1`.
1528
+
1529
+ Parameters
1530
+ ----------
1531
+ deg : int
1532
+ Number of sample points and weights. It must be >= 1.
1533
+
1534
+ Returns
1535
+ -------
1536
+ x : ndarray
1537
+ 1-D ndarray containing the sample points.
1538
+ y : ndarray
1539
+ 1-D ndarray containing the weights.
1540
+
1541
+ Notes
1542
+ -----
1543
+
1544
+ .. versionadded:: 1.7.0
1545
+
1546
+ The results have only been tested up to degree 100, higher degrees may
1547
+ be problematic. The weights are determined by using the fact that
1548
+
1549
+ .. math:: w_k = c / (L'_n(x_k) * L_{n-1}(x_k))
1550
+
1551
+ where :math:`c` is a constant independent of :math:`k` and :math:`x_k`
1552
+ is the k'th root of :math:`L_n`, and then scaling the results to get
1553
+ the right value when integrating 1.
1554
+
1555
+ """
1556
+ ideg = pu._deprecate_as_int(deg, "deg")
1557
+ if ideg <= 0:
1558
+ raise ValueError("deg must be a positive integer")
1559
+
1560
+ # first approximation of roots. We use the fact that the companion
1561
+ # matrix is symmetric in this case in order to obtain better zeros.
1562
+ c = np.array([0]*deg + [1])
1563
+ m = legcompanion(c)
1564
+ x = la.eigvalsh(m)
1565
+
1566
+ # improve roots by one application of Newton
1567
+ dy = legval(x, c)
1568
+ df = legval(x, legder(c))
1569
+ x -= dy/df
1570
+
1571
+ # compute the weights. We scale the factor to avoid possible numerical
1572
+ # overflow.
1573
+ fm = legval(x, c[1:])
1574
+ fm /= np.abs(fm).max()
1575
+ df /= np.abs(df).max()
1576
+ w = 1/(fm * df)
1577
+
1578
+ # for Legendre we can also symmetrize
1579
+ w = (w + w[::-1])/2
1580
+ x = (x - x[::-1])/2
1581
+
1582
+ # scale w to get the right value
1583
+ w *= 2. / w.sum()
1584
+
1585
+ return x, w
1586
+
1587
+
1588
+ def legweight(x):
1589
+ """
1590
+ Weight function of the Legendre polynomials.
1591
+
1592
+ The weight function is :math:`1` and the interval of integration is
1593
+ :math:`[-1, 1]`. The Legendre polynomials are orthogonal, but not
1594
+ normalized, with respect to this weight function.
1595
+
1596
+ Parameters
1597
+ ----------
1598
+ x : array_like
1599
+ Values at which the weight function will be computed.
1600
+
1601
+ Returns
1602
+ -------
1603
+ w : ndarray
1604
+ The weight function at `x`.
1605
+
1606
+ Notes
1607
+ -----
1608
+
1609
+ .. versionadded:: 1.7.0
1610
+
1611
+ """
1612
+ w = x*0.0 + 1.0
1613
+ return w
1614
+
1615
+ #
1616
+ # Legendre series class
1617
+ #
1618
+
1619
+ class Legendre(ABCPolyBase):
1620
+ """A Legendre series class.
1621
+
1622
+ The Legendre class provides the standard Python numerical methods
1623
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
1624
+ attributes and methods listed in the `ABCPolyBase` documentation.
1625
+
1626
+ Parameters
1627
+ ----------
1628
+ coef : array_like
1629
+ Legendre coefficients in order of increasing degree, i.e.,
1630
+ ``(1, 2, 3)`` gives ``1*P_0(x) + 2*P_1(x) + 3*P_2(x)``.
1631
+ domain : (2,) array_like, optional
1632
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
1633
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
1634
+ The default value is [-1, 1].
1635
+ window : (2,) array_like, optional
1636
+ Window, see `domain` for its use. The default value is [-1, 1].
1637
+
1638
+ .. versionadded:: 1.6.0
1639
+ symbol : str, optional
1640
+ Symbol used to represent the independent variable in string
1641
+ representations of the polynomial expression, e.g. for printing.
1642
+ The symbol must be a valid Python identifier. Default value is 'x'.
1643
+
1644
+ .. versionadded:: 1.24
1645
+
1646
+ """
1647
+ # Virtual Functions
1648
+ _add = staticmethod(legadd)
1649
+ _sub = staticmethod(legsub)
1650
+ _mul = staticmethod(legmul)
1651
+ _div = staticmethod(legdiv)
1652
+ _pow = staticmethod(legpow)
1653
+ _val = staticmethod(legval)
1654
+ _int = staticmethod(legint)
1655
+ _der = staticmethod(legder)
1656
+ _fit = staticmethod(legfit)
1657
+ _line = staticmethod(legline)
1658
+ _roots = staticmethod(legroots)
1659
+ _fromroots = staticmethod(legfromroots)
1660
+
1661
+ # Virtual properties
1662
+ domain = np.array(legdomain)
1663
+ window = np.array(legdomain)
1664
+ basis_name = 'P'
lib/python3.12/site-packages/numpy/polynomial/legendre.pyi ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any
2
+
3
+ from numpy import ndarray, dtype, int_
4
+ from numpy.polynomial._polybase import ABCPolyBase
5
+ from numpy.polynomial.polyutils import trimcoef
6
+
7
+ __all__: list[str]
8
+
9
+ legtrim = trimcoef
10
+
11
+ def poly2leg(pol): ...
12
+ def leg2poly(c): ...
13
+
14
+ legdomain: ndarray[Any, dtype[int_]]
15
+ legzero: ndarray[Any, dtype[int_]]
16
+ legone: ndarray[Any, dtype[int_]]
17
+ legx: ndarray[Any, dtype[int_]]
18
+
19
+ def legline(off, scl): ...
20
+ def legfromroots(roots): ...
21
+ def legadd(c1, c2): ...
22
+ def legsub(c1, c2): ...
23
+ def legmulx(c): ...
24
+ def legmul(c1, c2): ...
25
+ def legdiv(c1, c2): ...
26
+ def legpow(c, pow, maxpower=...): ...
27
+ def legder(c, m=..., scl=..., axis=...): ...
28
+ def legint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
29
+ def legval(x, c, tensor=...): ...
30
+ def legval2d(x, y, c): ...
31
+ def leggrid2d(x, y, c): ...
32
+ def legval3d(x, y, z, c): ...
33
+ def leggrid3d(x, y, z, c): ...
34
+ def legvander(x, deg): ...
35
+ def legvander2d(x, y, deg): ...
36
+ def legvander3d(x, y, z, deg): ...
37
+ def legfit(x, y, deg, rcond=..., full=..., w=...): ...
38
+ def legcompanion(c): ...
39
+ def legroots(c): ...
40
+ def leggauss(deg): ...
41
+ def legweight(x): ...
42
+
43
+ class Legendre(ABCPolyBase):
44
+ domain: Any
45
+ window: Any
46
+ basis_name: Any
lib/python3.12/site-packages/numpy/polynomial/polynomial.py ADDED
@@ -0,0 +1,1542 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ =================================================
3
+ Power Series (:mod:`numpy.polynomial.polynomial`)
4
+ =================================================
5
+
6
+ This module provides a number of objects (mostly functions) useful for
7
+ dealing with polynomials, including a `Polynomial` class that
8
+ encapsulates the usual arithmetic operations. (General information
9
+ on how this module represents and works with polynomial objects is in
10
+ the docstring for its "parent" sub-package, `numpy.polynomial`).
11
+
12
+ Classes
13
+ -------
14
+ .. autosummary::
15
+ :toctree: generated/
16
+
17
+ Polynomial
18
+
19
+ Constants
20
+ ---------
21
+ .. autosummary::
22
+ :toctree: generated/
23
+
24
+ polydomain
25
+ polyzero
26
+ polyone
27
+ polyx
28
+
29
+ Arithmetic
30
+ ----------
31
+ .. autosummary::
32
+ :toctree: generated/
33
+
34
+ polyadd
35
+ polysub
36
+ polymulx
37
+ polymul
38
+ polydiv
39
+ polypow
40
+ polyval
41
+ polyval2d
42
+ polyval3d
43
+ polygrid2d
44
+ polygrid3d
45
+
46
+ Calculus
47
+ --------
48
+ .. autosummary::
49
+ :toctree: generated/
50
+
51
+ polyder
52
+ polyint
53
+
54
+ Misc Functions
55
+ --------------
56
+ .. autosummary::
57
+ :toctree: generated/
58
+
59
+ polyfromroots
60
+ polyroots
61
+ polyvalfromroots
62
+ polyvander
63
+ polyvander2d
64
+ polyvander3d
65
+ polycompanion
66
+ polyfit
67
+ polytrim
68
+ polyline
69
+
70
+ See Also
71
+ --------
72
+ `numpy.polynomial`
73
+
74
+ """
75
+ __all__ = [
76
+ 'polyzero', 'polyone', 'polyx', 'polydomain', 'polyline', 'polyadd',
77
+ 'polysub', 'polymulx', 'polymul', 'polydiv', 'polypow', 'polyval',
78
+ 'polyvalfromroots', 'polyder', 'polyint', 'polyfromroots', 'polyvander',
79
+ 'polyfit', 'polytrim', 'polyroots', 'Polynomial', 'polyval2d', 'polyval3d',
80
+ 'polygrid2d', 'polygrid3d', 'polyvander2d', 'polyvander3d']
81
+
82
+ import numpy as np
83
+ import numpy.linalg as la
84
+ from numpy.core.multiarray import normalize_axis_index
85
+
86
+ from . import polyutils as pu
87
+ from ._polybase import ABCPolyBase
88
+
89
+ polytrim = pu.trimcoef
90
+
91
+ #
92
+ # These are constant arrays are of integer type so as to be compatible
93
+ # with the widest range of other types, such as Decimal.
94
+ #
95
+
96
+ # Polynomial default domain.
97
+ polydomain = np.array([-1, 1])
98
+
99
+ # Polynomial coefficients representing zero.
100
+ polyzero = np.array([0])
101
+
102
+ # Polynomial coefficients representing one.
103
+ polyone = np.array([1])
104
+
105
+ # Polynomial coefficients representing the identity x.
106
+ polyx = np.array([0, 1])
107
+
108
+ #
109
+ # Polynomial series functions
110
+ #
111
+
112
+
113
+ def polyline(off, scl):
114
+ """
115
+ Returns an array representing a linear polynomial.
116
+
117
+ Parameters
118
+ ----------
119
+ off, scl : scalars
120
+ The "y-intercept" and "slope" of the line, respectively.
121
+
122
+ Returns
123
+ -------
124
+ y : ndarray
125
+ This module's representation of the linear polynomial ``off +
126
+ scl*x``.
127
+
128
+ See Also
129
+ --------
130
+ numpy.polynomial.chebyshev.chebline
131
+ numpy.polynomial.legendre.legline
132
+ numpy.polynomial.laguerre.lagline
133
+ numpy.polynomial.hermite.hermline
134
+ numpy.polynomial.hermite_e.hermeline
135
+
136
+ Examples
137
+ --------
138
+ >>> from numpy.polynomial import polynomial as P
139
+ >>> P.polyline(1,-1)
140
+ array([ 1, -1])
141
+ >>> P.polyval(1, P.polyline(1,-1)) # should be 0
142
+ 0.0
143
+
144
+ """
145
+ if scl != 0:
146
+ return np.array([off, scl])
147
+ else:
148
+ return np.array([off])
149
+
150
+
151
+ def polyfromroots(roots):
152
+ """
153
+ Generate a monic polynomial with given roots.
154
+
155
+ Return the coefficients of the polynomial
156
+
157
+ .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
158
+
159
+ where the ``r_n`` are the roots specified in `roots`. If a zero has
160
+ multiplicity n, then it must appear in `roots` n times. For instance,
161
+ if 2 is a root of multiplicity three and 3 is a root of multiplicity 2,
162
+ then `roots` looks something like [2, 2, 2, 3, 3]. The roots can appear
163
+ in any order.
164
+
165
+ If the returned coefficients are `c`, then
166
+
167
+ .. math:: p(x) = c_0 + c_1 * x + ... + x^n
168
+
169
+ The coefficient of the last term is 1 for monic polynomials in this
170
+ form.
171
+
172
+ Parameters
173
+ ----------
174
+ roots : array_like
175
+ Sequence containing the roots.
176
+
177
+ Returns
178
+ -------
179
+ out : ndarray
180
+ 1-D array of the polynomial's coefficients If all the roots are
181
+ real, then `out` is also real, otherwise it is complex. (see
182
+ Examples below).
183
+
184
+ See Also
185
+ --------
186
+ numpy.polynomial.chebyshev.chebfromroots
187
+ numpy.polynomial.legendre.legfromroots
188
+ numpy.polynomial.laguerre.lagfromroots
189
+ numpy.polynomial.hermite.hermfromroots
190
+ numpy.polynomial.hermite_e.hermefromroots
191
+
192
+ Notes
193
+ -----
194
+ The coefficients are determined by multiplying together linear factors
195
+ of the form ``(x - r_i)``, i.e.
196
+
197
+ .. math:: p(x) = (x - r_0) (x - r_1) ... (x - r_n)
198
+
199
+ where ``n == len(roots) - 1``; note that this implies that ``1`` is always
200
+ returned for :math:`a_n`.
201
+
202
+ Examples
203
+ --------
204
+ >>> from numpy.polynomial import polynomial as P
205
+ >>> P.polyfromroots((-1,0,1)) # x(x - 1)(x + 1) = x^3 - x
206
+ array([ 0., -1., 0., 1.])
207
+ >>> j = complex(0,1)
208
+ >>> P.polyfromroots((-j,j)) # complex returned, though values are real
209
+ array([1.+0.j, 0.+0.j, 1.+0.j])
210
+
211
+ """
212
+ return pu._fromroots(polyline, polymul, roots)
213
+
214
+
215
+ def polyadd(c1, c2):
216
+ """
217
+ Add one polynomial to another.
218
+
219
+ Returns the sum of two polynomials `c1` + `c2`. The arguments are
220
+ sequences of coefficients from lowest order term to highest, i.e.,
221
+ [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``.
222
+
223
+ Parameters
224
+ ----------
225
+ c1, c2 : array_like
226
+ 1-D arrays of polynomial coefficients ordered from low to high.
227
+
228
+ Returns
229
+ -------
230
+ out : ndarray
231
+ The coefficient array representing their sum.
232
+
233
+ See Also
234
+ --------
235
+ polysub, polymulx, polymul, polydiv, polypow
236
+
237
+ Examples
238
+ --------
239
+ >>> from numpy.polynomial import polynomial as P
240
+ >>> c1 = (1,2,3)
241
+ >>> c2 = (3,2,1)
242
+ >>> sum = P.polyadd(c1,c2); sum
243
+ array([4., 4., 4.])
244
+ >>> P.polyval(2, sum) # 4 + 4(2) + 4(2**2)
245
+ 28.0
246
+
247
+ """
248
+ return pu._add(c1, c2)
249
+
250
+
251
+ def polysub(c1, c2):
252
+ """
253
+ Subtract one polynomial from another.
254
+
255
+ Returns the difference of two polynomials `c1` - `c2`. The arguments
256
+ are sequences of coefficients from lowest order term to highest, i.e.,
257
+ [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``.
258
+
259
+ Parameters
260
+ ----------
261
+ c1, c2 : array_like
262
+ 1-D arrays of polynomial coefficients ordered from low to
263
+ high.
264
+
265
+ Returns
266
+ -------
267
+ out : ndarray
268
+ Of coefficients representing their difference.
269
+
270
+ See Also
271
+ --------
272
+ polyadd, polymulx, polymul, polydiv, polypow
273
+
274
+ Examples
275
+ --------
276
+ >>> from numpy.polynomial import polynomial as P
277
+ >>> c1 = (1,2,3)
278
+ >>> c2 = (3,2,1)
279
+ >>> P.polysub(c1,c2)
280
+ array([-2., 0., 2.])
281
+ >>> P.polysub(c2,c1) # -P.polysub(c1,c2)
282
+ array([ 2., 0., -2.])
283
+
284
+ """
285
+ return pu._sub(c1, c2)
286
+
287
+
288
+ def polymulx(c):
289
+ """Multiply a polynomial by x.
290
+
291
+ Multiply the polynomial `c` by x, where x is the independent
292
+ variable.
293
+
294
+
295
+ Parameters
296
+ ----------
297
+ c : array_like
298
+ 1-D array of polynomial coefficients ordered from low to
299
+ high.
300
+
301
+ Returns
302
+ -------
303
+ out : ndarray
304
+ Array representing the result of the multiplication.
305
+
306
+ See Also
307
+ --------
308
+ polyadd, polysub, polymul, polydiv, polypow
309
+
310
+ Notes
311
+ -----
312
+
313
+ .. versionadded:: 1.5.0
314
+
315
+ """
316
+ # c is a trimmed copy
317
+ [c] = pu.as_series([c])
318
+ # The zero series needs special treatment
319
+ if len(c) == 1 and c[0] == 0:
320
+ return c
321
+
322
+ prd = np.empty(len(c) + 1, dtype=c.dtype)
323
+ prd[0] = c[0]*0
324
+ prd[1:] = c
325
+ return prd
326
+
327
+
328
+ def polymul(c1, c2):
329
+ """
330
+ Multiply one polynomial by another.
331
+
332
+ Returns the product of two polynomials `c1` * `c2`. The arguments are
333
+ sequences of coefficients, from lowest order term to highest, e.g.,
334
+ [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2.``
335
+
336
+ Parameters
337
+ ----------
338
+ c1, c2 : array_like
339
+ 1-D arrays of coefficients representing a polynomial, relative to the
340
+ "standard" basis, and ordered from lowest order term to highest.
341
+
342
+ Returns
343
+ -------
344
+ out : ndarray
345
+ Of the coefficients of their product.
346
+
347
+ See Also
348
+ --------
349
+ polyadd, polysub, polymulx, polydiv, polypow
350
+
351
+ Examples
352
+ --------
353
+ >>> from numpy.polynomial import polynomial as P
354
+ >>> c1 = (1,2,3)
355
+ >>> c2 = (3,2,1)
356
+ >>> P.polymul(c1,c2)
357
+ array([ 3., 8., 14., 8., 3.])
358
+
359
+ """
360
+ # c1, c2 are trimmed copies
361
+ [c1, c2] = pu.as_series([c1, c2])
362
+ ret = np.convolve(c1, c2)
363
+ return pu.trimseq(ret)
364
+
365
+
366
+ def polydiv(c1, c2):
367
+ """
368
+ Divide one polynomial by another.
369
+
370
+ Returns the quotient-with-remainder of two polynomials `c1` / `c2`.
371
+ The arguments are sequences of coefficients, from lowest order term
372
+ to highest, e.g., [1,2,3] represents ``1 + 2*x + 3*x**2``.
373
+
374
+ Parameters
375
+ ----------
376
+ c1, c2 : array_like
377
+ 1-D arrays of polynomial coefficients ordered from low to high.
378
+
379
+ Returns
380
+ -------
381
+ [quo, rem] : ndarrays
382
+ Of coefficient series representing the quotient and remainder.
383
+
384
+ See Also
385
+ --------
386
+ polyadd, polysub, polymulx, polymul, polypow
387
+
388
+ Examples
389
+ --------
390
+ >>> from numpy.polynomial import polynomial as P
391
+ >>> c1 = (1,2,3)
392
+ >>> c2 = (3,2,1)
393
+ >>> P.polydiv(c1,c2)
394
+ (array([3.]), array([-8., -4.]))
395
+ >>> P.polydiv(c2,c1)
396
+ (array([ 0.33333333]), array([ 2.66666667, 1.33333333])) # may vary
397
+
398
+ """
399
+ # c1, c2 are trimmed copies
400
+ [c1, c2] = pu.as_series([c1, c2])
401
+ if c2[-1] == 0:
402
+ raise ZeroDivisionError()
403
+
404
+ # note: this is more efficient than `pu._div(polymul, c1, c2)`
405
+ lc1 = len(c1)
406
+ lc2 = len(c2)
407
+ if lc1 < lc2:
408
+ return c1[:1]*0, c1
409
+ elif lc2 == 1:
410
+ return c1/c2[-1], c1[:1]*0
411
+ else:
412
+ dlen = lc1 - lc2
413
+ scl = c2[-1]
414
+ c2 = c2[:-1]/scl
415
+ i = dlen
416
+ j = lc1 - 1
417
+ while i >= 0:
418
+ c1[i:j] -= c2*c1[j]
419
+ i -= 1
420
+ j -= 1
421
+ return c1[j+1:]/scl, pu.trimseq(c1[:j+1])
422
+
423
+
424
+ def polypow(c, pow, maxpower=None):
425
+ """Raise a polynomial to a power.
426
+
427
+ Returns the polynomial `c` raised to the power `pow`. The argument
428
+ `c` is a sequence of coefficients ordered from low to high. i.e.,
429
+ [1,2,3] is the series ``1 + 2*x + 3*x**2.``
430
+
431
+ Parameters
432
+ ----------
433
+ c : array_like
434
+ 1-D array of array of series coefficients ordered from low to
435
+ high degree.
436
+ pow : integer
437
+ Power to which the series will be raised
438
+ maxpower : integer, optional
439
+ Maximum power allowed. This is mainly to limit growth of the series
440
+ to unmanageable size. Default is 16
441
+
442
+ Returns
443
+ -------
444
+ coef : ndarray
445
+ Power series of power.
446
+
447
+ See Also
448
+ --------
449
+ polyadd, polysub, polymulx, polymul, polydiv
450
+
451
+ Examples
452
+ --------
453
+ >>> from numpy.polynomial import polynomial as P
454
+ >>> P.polypow([1,2,3], 2)
455
+ array([ 1., 4., 10., 12., 9.])
456
+
457
+ """
458
+ # note: this is more efficient than `pu._pow(polymul, c1, c2)`, as it
459
+ # avoids calling `as_series` repeatedly
460
+ return pu._pow(np.convolve, c, pow, maxpower)
461
+
462
+
463
+ def polyder(c, m=1, scl=1, axis=0):
464
+ """
465
+ Differentiate a polynomial.
466
+
467
+ Returns the polynomial coefficients `c` differentiated `m` times along
468
+ `axis`. At each iteration the result is multiplied by `scl` (the
469
+ scaling factor is for use in a linear change of variable). The
470
+ argument `c` is an array of coefficients from low to high degree along
471
+ each axis, e.g., [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``
472
+ while [[1,2],[1,2]] represents ``1 + 1*x + 2*y + 2*x*y`` if axis=0 is
473
+ ``x`` and axis=1 is ``y``.
474
+
475
+ Parameters
476
+ ----------
477
+ c : array_like
478
+ Array of polynomial coefficients. If c is multidimensional the
479
+ different axis correspond to different variables with the degree
480
+ in each axis given by the corresponding index.
481
+ m : int, optional
482
+ Number of derivatives taken, must be non-negative. (Default: 1)
483
+ scl : scalar, optional
484
+ Each differentiation is multiplied by `scl`. The end result is
485
+ multiplication by ``scl**m``. This is for use in a linear change
486
+ of variable. (Default: 1)
487
+ axis : int, optional
488
+ Axis over which the derivative is taken. (Default: 0).
489
+
490
+ .. versionadded:: 1.7.0
491
+
492
+ Returns
493
+ -------
494
+ der : ndarray
495
+ Polynomial coefficients of the derivative.
496
+
497
+ See Also
498
+ --------
499
+ polyint
500
+
501
+ Examples
502
+ --------
503
+ >>> from numpy.polynomial import polynomial as P
504
+ >>> c = (1,2,3,4) # 1 + 2x + 3x**2 + 4x**3
505
+ >>> P.polyder(c) # (d/dx)(c) = 2 + 6x + 12x**2
506
+ array([ 2., 6., 12.])
507
+ >>> P.polyder(c,3) # (d**3/dx**3)(c) = 24
508
+ array([24.])
509
+ >>> P.polyder(c,scl=-1) # (d/d(-x))(c) = -2 - 6x - 12x**2
510
+ array([ -2., -6., -12.])
511
+ >>> P.polyder(c,2,-1) # (d**2/d(-x)**2)(c) = 6 + 24x
512
+ array([ 6., 24.])
513
+
514
+ """
515
+ c = np.array(c, ndmin=1, copy=True)
516
+ if c.dtype.char in '?bBhHiIlLqQpP':
517
+ # astype fails with NA
518
+ c = c + 0.0
519
+ cdt = c.dtype
520
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
521
+ iaxis = pu._deprecate_as_int(axis, "the axis")
522
+ if cnt < 0:
523
+ raise ValueError("The order of derivation must be non-negative")
524
+ iaxis = normalize_axis_index(iaxis, c.ndim)
525
+
526
+ if cnt == 0:
527
+ return c
528
+
529
+ c = np.moveaxis(c, iaxis, 0)
530
+ n = len(c)
531
+ if cnt >= n:
532
+ c = c[:1]*0
533
+ else:
534
+ for i in range(cnt):
535
+ n = n - 1
536
+ c *= scl
537
+ der = np.empty((n,) + c.shape[1:], dtype=cdt)
538
+ for j in range(n, 0, -1):
539
+ der[j - 1] = j*c[j]
540
+ c = der
541
+ c = np.moveaxis(c, 0, iaxis)
542
+ return c
543
+
544
+
545
+ def polyint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
546
+ """
547
+ Integrate a polynomial.
548
+
549
+ Returns the polynomial coefficients `c` integrated `m` times from
550
+ `lbnd` along `axis`. At each iteration the resulting series is
551
+ **multiplied** by `scl` and an integration constant, `k`, is added.
552
+ The scaling factor is for use in a linear change of variable. ("Buyer
553
+ beware": note that, depending on what one is doing, one may want `scl`
554
+ to be the reciprocal of what one might expect; for more information,
555
+ see the Notes section below.) The argument `c` is an array of
556
+ coefficients, from low to high degree along each axis, e.g., [1,2,3]
557
+ represents the polynomial ``1 + 2*x + 3*x**2`` while [[1,2],[1,2]]
558
+ represents ``1 + 1*x + 2*y + 2*x*y`` if axis=0 is ``x`` and axis=1 is
559
+ ``y``.
560
+
561
+ Parameters
562
+ ----------
563
+ c : array_like
564
+ 1-D array of polynomial coefficients, ordered from low to high.
565
+ m : int, optional
566
+ Order of integration, must be positive. (Default: 1)
567
+ k : {[], list, scalar}, optional
568
+ Integration constant(s). The value of the first integral at zero
569
+ is the first value in the list, the value of the second integral
570
+ at zero is the second value, etc. If ``k == []`` (the default),
571
+ all constants are set to zero. If ``m == 1``, a single scalar can
572
+ be given instead of a list.
573
+ lbnd : scalar, optional
574
+ The lower bound of the integral. (Default: 0)
575
+ scl : scalar, optional
576
+ Following each integration the result is *multiplied* by `scl`
577
+ before the integration constant is added. (Default: 1)
578
+ axis : int, optional
579
+ Axis over which the integral is taken. (Default: 0).
580
+
581
+ .. versionadded:: 1.7.0
582
+
583
+ Returns
584
+ -------
585
+ S : ndarray
586
+ Coefficient array of the integral.
587
+
588
+ Raises
589
+ ------
590
+ ValueError
591
+ If ``m < 1``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
592
+ ``np.ndim(scl) != 0``.
593
+
594
+ See Also
595
+ --------
596
+ polyder
597
+
598
+ Notes
599
+ -----
600
+ Note that the result of each integration is *multiplied* by `scl`. Why
601
+ is this important to note? Say one is making a linear change of
602
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
603
+ :math:`dx = du/a`, so one will need to set `scl` equal to
604
+ :math:`1/a` - perhaps not what one would have first thought.
605
+
606
+ Examples
607
+ --------
608
+ >>> from numpy.polynomial import polynomial as P
609
+ >>> c = (1,2,3)
610
+ >>> P.polyint(c) # should return array([0, 1, 1, 1])
611
+ array([0., 1., 1., 1.])
612
+ >>> P.polyint(c,3) # should return array([0, 0, 0, 1/6, 1/12, 1/20])
613
+ array([ 0. , 0. , 0. , 0.16666667, 0.08333333, # may vary
614
+ 0.05 ])
615
+ >>> P.polyint(c,k=3) # should return array([3, 1, 1, 1])
616
+ array([3., 1., 1., 1.])
617
+ >>> P.polyint(c,lbnd=-2) # should return array([6, 1, 1, 1])
618
+ array([6., 1., 1., 1.])
619
+ >>> P.polyint(c,scl=-2) # should return array([0, -2, -2, -2])
620
+ array([ 0., -2., -2., -2.])
621
+
622
+ """
623
+ c = np.array(c, ndmin=1, copy=True)
624
+ if c.dtype.char in '?bBhHiIlLqQpP':
625
+ # astype doesn't preserve mask attribute.
626
+ c = c + 0.0
627
+ cdt = c.dtype
628
+ if not np.iterable(k):
629
+ k = [k]
630
+ cnt = pu._deprecate_as_int(m, "the order of integration")
631
+ iaxis = pu._deprecate_as_int(axis, "the axis")
632
+ if cnt < 0:
633
+ raise ValueError("The order of integration must be non-negative")
634
+ if len(k) > cnt:
635
+ raise ValueError("Too many integration constants")
636
+ if np.ndim(lbnd) != 0:
637
+ raise ValueError("lbnd must be a scalar.")
638
+ if np.ndim(scl) != 0:
639
+ raise ValueError("scl must be a scalar.")
640
+ iaxis = normalize_axis_index(iaxis, c.ndim)
641
+
642
+ if cnt == 0:
643
+ return c
644
+
645
+ k = list(k) + [0]*(cnt - len(k))
646
+ c = np.moveaxis(c, iaxis, 0)
647
+ for i in range(cnt):
648
+ n = len(c)
649
+ c *= scl
650
+ if n == 1 and np.all(c[0] == 0):
651
+ c[0] += k[i]
652
+ else:
653
+ tmp = np.empty((n + 1,) + c.shape[1:], dtype=cdt)
654
+ tmp[0] = c[0]*0
655
+ tmp[1] = c[0]
656
+ for j in range(1, n):
657
+ tmp[j + 1] = c[j]/(j + 1)
658
+ tmp[0] += k[i] - polyval(lbnd, tmp)
659
+ c = tmp
660
+ c = np.moveaxis(c, 0, iaxis)
661
+ return c
662
+
663
+
664
+ def polyval(x, c, tensor=True):
665
+ """
666
+ Evaluate a polynomial at points x.
667
+
668
+ If `c` is of length `n + 1`, this function returns the value
669
+
670
+ .. math:: p(x) = c_0 + c_1 * x + ... + c_n * x^n
671
+
672
+ The parameter `x` is converted to an array only if it is a tuple or a
673
+ list, otherwise it is treated as a scalar. In either case, either `x`
674
+ or its elements must support multiplication and addition both with
675
+ themselves and with the elements of `c`.
676
+
677
+ If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
678
+ `c` is multidimensional, then the shape of the result depends on the
679
+ value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
680
+ x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
681
+ scalars have shape (,).
682
+
683
+ Trailing zeros in the coefficients will be used in the evaluation, so
684
+ they should be avoided if efficiency is a concern.
685
+
686
+ Parameters
687
+ ----------
688
+ x : array_like, compatible object
689
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
690
+ it is left unchanged and treated as a scalar. In either case, `x`
691
+ or its elements must support addition and multiplication with
692
+ with themselves and with the elements of `c`.
693
+ c : array_like
694
+ Array of coefficients ordered so that the coefficients for terms of
695
+ degree n are contained in c[n]. If `c` is multidimensional the
696
+ remaining indices enumerate multiple polynomials. In the two
697
+ dimensional case the coefficients may be thought of as stored in
698
+ the columns of `c`.
699
+ tensor : boolean, optional
700
+ If True, the shape of the coefficient array is extended with ones
701
+ on the right, one for each dimension of `x`. Scalars have dimension 0
702
+ for this action. The result is that every column of coefficients in
703
+ `c` is evaluated for every element of `x`. If False, `x` is broadcast
704
+ over the columns of `c` for the evaluation. This keyword is useful
705
+ when `c` is multidimensional. The default value is True.
706
+
707
+ .. versionadded:: 1.7.0
708
+
709
+ Returns
710
+ -------
711
+ values : ndarray, compatible object
712
+ The shape of the returned array is described above.
713
+
714
+ See Also
715
+ --------
716
+ polyval2d, polygrid2d, polyval3d, polygrid3d
717
+
718
+ Notes
719
+ -----
720
+ The evaluation uses Horner's method.
721
+
722
+ Examples
723
+ --------
724
+ >>> from numpy.polynomial.polynomial import polyval
725
+ >>> polyval(1, [1,2,3])
726
+ 6.0
727
+ >>> a = np.arange(4).reshape(2,2)
728
+ >>> a
729
+ array([[0, 1],
730
+ [2, 3]])
731
+ >>> polyval(a, [1,2,3])
732
+ array([[ 1., 6.],
733
+ [17., 34.]])
734
+ >>> coef = np.arange(4).reshape(2,2) # multidimensional coefficients
735
+ >>> coef
736
+ array([[0, 1],
737
+ [2, 3]])
738
+ >>> polyval([1,2], coef, tensor=True)
739
+ array([[2., 4.],
740
+ [4., 7.]])
741
+ >>> polyval([1,2], coef, tensor=False)
742
+ array([2., 7.])
743
+
744
+ """
745
+ c = np.array(c, ndmin=1, copy=False)
746
+ if c.dtype.char in '?bBhHiIlLqQpP':
747
+ # astype fails with NA
748
+ c = c + 0.0
749
+ if isinstance(x, (tuple, list)):
750
+ x = np.asarray(x)
751
+ if isinstance(x, np.ndarray) and tensor:
752
+ c = c.reshape(c.shape + (1,)*x.ndim)
753
+
754
+ c0 = c[-1] + x*0
755
+ for i in range(2, len(c) + 1):
756
+ c0 = c[-i] + c0*x
757
+ return c0
758
+
759
+
760
+ def polyvalfromroots(x, r, tensor=True):
761
+ """
762
+ Evaluate a polynomial specified by its roots at points x.
763
+
764
+ If `r` is of length `N`, this function returns the value
765
+
766
+ .. math:: p(x) = \\prod_{n=1}^{N} (x - r_n)
767
+
768
+ The parameter `x` is converted to an array only if it is a tuple or a
769
+ list, otherwise it is treated as a scalar. In either case, either `x`
770
+ or its elements must support multiplication and addition both with
771
+ themselves and with the elements of `r`.
772
+
773
+ If `r` is a 1-D array, then `p(x)` will have the same shape as `x`. If `r`
774
+ is multidimensional, then the shape of the result depends on the value of
775
+ `tensor`. If `tensor` is ``True`` the shape will be r.shape[1:] + x.shape;
776
+ that is, each polynomial is evaluated at every value of `x`. If `tensor` is
777
+ ``False``, the shape will be r.shape[1:]; that is, each polynomial is
778
+ evaluated only for the corresponding broadcast value of `x`. Note that
779
+ scalars have shape (,).
780
+
781
+ .. versionadded:: 1.12
782
+
783
+ Parameters
784
+ ----------
785
+ x : array_like, compatible object
786
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
787
+ it is left unchanged and treated as a scalar. In either case, `x`
788
+ or its elements must support addition and multiplication with
789
+ with themselves and with the elements of `r`.
790
+ r : array_like
791
+ Array of roots. If `r` is multidimensional the first index is the
792
+ root index, while the remaining indices enumerate multiple
793
+ polynomials. For instance, in the two dimensional case the roots
794
+ of each polynomial may be thought of as stored in the columns of `r`.
795
+ tensor : boolean, optional
796
+ If True, the shape of the roots array is extended with ones on the
797
+ right, one for each dimension of `x`. Scalars have dimension 0 for this
798
+ action. The result is that every column of coefficients in `r` is
799
+ evaluated for every element of `x`. If False, `x` is broadcast over the
800
+ columns of `r` for the evaluation. This keyword is useful when `r` is
801
+ multidimensional. The default value is True.
802
+
803
+ Returns
804
+ -------
805
+ values : ndarray, compatible object
806
+ The shape of the returned array is described above.
807
+
808
+ See Also
809
+ --------
810
+ polyroots, polyfromroots, polyval
811
+
812
+ Examples
813
+ --------
814
+ >>> from numpy.polynomial.polynomial import polyvalfromroots
815
+ >>> polyvalfromroots(1, [1,2,3])
816
+ 0.0
817
+ >>> a = np.arange(4).reshape(2,2)
818
+ >>> a
819
+ array([[0, 1],
820
+ [2, 3]])
821
+ >>> polyvalfromroots(a, [-1, 0, 1])
822
+ array([[-0., 0.],
823
+ [ 6., 24.]])
824
+ >>> r = np.arange(-2, 2).reshape(2,2) # multidimensional coefficients
825
+ >>> r # each column of r defines one polynomial
826
+ array([[-2, -1],
827
+ [ 0, 1]])
828
+ >>> b = [-2, 1]
829
+ >>> polyvalfromroots(b, r, tensor=True)
830
+ array([[-0., 3.],
831
+ [ 3., 0.]])
832
+ >>> polyvalfromroots(b, r, tensor=False)
833
+ array([-0., 0.])
834
+ """
835
+ r = np.array(r, ndmin=1, copy=False)
836
+ if r.dtype.char in '?bBhHiIlLqQpP':
837
+ r = r.astype(np.double)
838
+ if isinstance(x, (tuple, list)):
839
+ x = np.asarray(x)
840
+ if isinstance(x, np.ndarray):
841
+ if tensor:
842
+ r = r.reshape(r.shape + (1,)*x.ndim)
843
+ elif x.ndim >= r.ndim:
844
+ raise ValueError("x.ndim must be < r.ndim when tensor == False")
845
+ return np.prod(x - r, axis=0)
846
+
847
+
848
+ def polyval2d(x, y, c):
849
+ """
850
+ Evaluate a 2-D polynomial at points (x, y).
851
+
852
+ This function returns the value
853
+
854
+ .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * x^i * y^j
855
+
856
+ The parameters `x` and `y` are converted to arrays only if they are
857
+ tuples or a lists, otherwise they are treated as a scalars and they
858
+ must have the same shape after conversion. In either case, either `x`
859
+ and `y` or their elements must support multiplication and addition both
860
+ with themselves and with the elements of `c`.
861
+
862
+ If `c` has fewer than two dimensions, ones are implicitly appended to
863
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
864
+ x.shape.
865
+
866
+ Parameters
867
+ ----------
868
+ x, y : array_like, compatible objects
869
+ The two dimensional series is evaluated at the points `(x, y)`,
870
+ where `x` and `y` must have the same shape. If `x` or `y` is a list
871
+ or tuple, it is first converted to an ndarray, otherwise it is left
872
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
873
+ c : array_like
874
+ Array of coefficients ordered so that the coefficient of the term
875
+ of multi-degree i,j is contained in `c[i,j]`. If `c` has
876
+ dimension greater than two the remaining indices enumerate multiple
877
+ sets of coefficients.
878
+
879
+ Returns
880
+ -------
881
+ values : ndarray, compatible object
882
+ The values of the two dimensional polynomial at points formed with
883
+ pairs of corresponding values from `x` and `y`.
884
+
885
+ See Also
886
+ --------
887
+ polyval, polygrid2d, polyval3d, polygrid3d
888
+
889
+ Notes
890
+ -----
891
+
892
+ .. versionadded:: 1.7.0
893
+
894
+ """
895
+ return pu._valnd(polyval, c, x, y)
896
+
897
+
898
+ def polygrid2d(x, y, c):
899
+ """
900
+ Evaluate a 2-D polynomial on the Cartesian product of x and y.
901
+
902
+ This function returns the values:
903
+
904
+ .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * a^i * b^j
905
+
906
+ where the points `(a, b)` consist of all pairs formed by taking
907
+ `a` from `x` and `b` from `y`. The resulting points form a grid with
908
+ `x` in the first dimension and `y` in the second.
909
+
910
+ The parameters `x` and `y` are converted to arrays only if they are
911
+ tuples or a lists, otherwise they are treated as a scalars. In either
912
+ case, either `x` and `y` or their elements must support multiplication
913
+ and addition both with themselves and with the elements of `c`.
914
+
915
+ If `c` has fewer than two dimensions, ones are implicitly appended to
916
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
917
+ x.shape + y.shape.
918
+
919
+ Parameters
920
+ ----------
921
+ x, y : array_like, compatible objects
922
+ The two dimensional series is evaluated at the points in the
923
+ Cartesian product of `x` and `y`. If `x` or `y` is a list or
924
+ tuple, it is first converted to an ndarray, otherwise it is left
925
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
926
+ c : array_like
927
+ Array of coefficients ordered so that the coefficients for terms of
928
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
929
+ greater than two the remaining indices enumerate multiple sets of
930
+ coefficients.
931
+
932
+ Returns
933
+ -------
934
+ values : ndarray, compatible object
935
+ The values of the two dimensional polynomial at points in the Cartesian
936
+ product of `x` and `y`.
937
+
938
+ See Also
939
+ --------
940
+ polyval, polyval2d, polyval3d, polygrid3d
941
+
942
+ Notes
943
+ -----
944
+
945
+ .. versionadded:: 1.7.0
946
+
947
+ """
948
+ return pu._gridnd(polyval, c, x, y)
949
+
950
+
951
+ def polyval3d(x, y, z, c):
952
+ """
953
+ Evaluate a 3-D polynomial at points (x, y, z).
954
+
955
+ This function returns the values:
956
+
957
+ .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * x^i * y^j * z^k
958
+
959
+ The parameters `x`, `y`, and `z` are converted to arrays only if
960
+ they are tuples or a lists, otherwise they are treated as a scalars and
961
+ they must have the same shape after conversion. In either case, either
962
+ `x`, `y`, and `z` or their elements must support multiplication and
963
+ addition both with themselves and with the elements of `c`.
964
+
965
+ If `c` has fewer than 3 dimensions, ones are implicitly appended to its
966
+ shape to make it 3-D. The shape of the result will be c.shape[3:] +
967
+ x.shape.
968
+
969
+ Parameters
970
+ ----------
971
+ x, y, z : array_like, compatible object
972
+ The three dimensional series is evaluated at the points
973
+ `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
974
+ any of `x`, `y`, or `z` is a list or tuple, it is first converted
975
+ to an ndarray, otherwise it is left unchanged and if it isn't an
976
+ ndarray it is treated as a scalar.
977
+ c : array_like
978
+ Array of coefficients ordered so that the coefficient of the term of
979
+ multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
980
+ greater than 3 the remaining indices enumerate multiple sets of
981
+ coefficients.
982
+
983
+ Returns
984
+ -------
985
+ values : ndarray, compatible object
986
+ The values of the multidimensional polynomial on points formed with
987
+ triples of corresponding values from `x`, `y`, and `z`.
988
+
989
+ See Also
990
+ --------
991
+ polyval, polyval2d, polygrid2d, polygrid3d
992
+
993
+ Notes
994
+ -----
995
+
996
+ .. versionadded:: 1.7.0
997
+
998
+ """
999
+ return pu._valnd(polyval, c, x, y, z)
1000
+
1001
+
1002
+ def polygrid3d(x, y, z, c):
1003
+ """
1004
+ Evaluate a 3-D polynomial on the Cartesian product of x, y and z.
1005
+
1006
+ This function returns the values:
1007
+
1008
+ .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * a^i * b^j * c^k
1009
+
1010
+ where the points `(a, b, c)` consist of all triples formed by taking
1011
+ `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
1012
+ a grid with `x` in the first dimension, `y` in the second, and `z` in
1013
+ the third.
1014
+
1015
+ The parameters `x`, `y`, and `z` are converted to arrays only if they
1016
+ are tuples or a lists, otherwise they are treated as a scalars. In
1017
+ either case, either `x`, `y`, and `z` or their elements must support
1018
+ multiplication and addition both with themselves and with the elements
1019
+ of `c`.
1020
+
1021
+ If `c` has fewer than three dimensions, ones are implicitly appended to
1022
+ its shape to make it 3-D. The shape of the result will be c.shape[3:] +
1023
+ x.shape + y.shape + z.shape.
1024
+
1025
+ Parameters
1026
+ ----------
1027
+ x, y, z : array_like, compatible objects
1028
+ The three dimensional series is evaluated at the points in the
1029
+ Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
1030
+ list or tuple, it is first converted to an ndarray, otherwise it is
1031
+ left unchanged and, if it isn't an ndarray, it is treated as a
1032
+ scalar.
1033
+ c : array_like
1034
+ Array of coefficients ordered so that the coefficients for terms of
1035
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
1036
+ greater than two the remaining indices enumerate multiple sets of
1037
+ coefficients.
1038
+
1039
+ Returns
1040
+ -------
1041
+ values : ndarray, compatible object
1042
+ The values of the two dimensional polynomial at points in the Cartesian
1043
+ product of `x` and `y`.
1044
+
1045
+ See Also
1046
+ --------
1047
+ polyval, polyval2d, polygrid2d, polyval3d
1048
+
1049
+ Notes
1050
+ -----
1051
+
1052
+ .. versionadded:: 1.7.0
1053
+
1054
+ """
1055
+ return pu._gridnd(polyval, c, x, y, z)
1056
+
1057
+
1058
+ def polyvander(x, deg):
1059
+ """Vandermonde matrix of given degree.
1060
+
1061
+ Returns the Vandermonde matrix of degree `deg` and sample points
1062
+ `x`. The Vandermonde matrix is defined by
1063
+
1064
+ .. math:: V[..., i] = x^i,
1065
+
1066
+ where `0 <= i <= deg`. The leading indices of `V` index the elements of
1067
+ `x` and the last index is the power of `x`.
1068
+
1069
+ If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
1070
+ matrix ``V = polyvander(x, n)``, then ``np.dot(V, c)`` and
1071
+ ``polyval(x, c)`` are the same up to roundoff. This equivalence is
1072
+ useful both for least squares fitting and for the evaluation of a large
1073
+ number of polynomials of the same degree and sample points.
1074
+
1075
+ Parameters
1076
+ ----------
1077
+ x : array_like
1078
+ Array of points. The dtype is converted to float64 or complex128
1079
+ depending on whether any of the elements are complex. If `x` is
1080
+ scalar it is converted to a 1-D array.
1081
+ deg : int
1082
+ Degree of the resulting matrix.
1083
+
1084
+ Returns
1085
+ -------
1086
+ vander : ndarray.
1087
+ The Vandermonde matrix. The shape of the returned matrix is
1088
+ ``x.shape + (deg + 1,)``, where the last index is the power of `x`.
1089
+ The dtype will be the same as the converted `x`.
1090
+
1091
+ See Also
1092
+ --------
1093
+ polyvander2d, polyvander3d
1094
+
1095
+ """
1096
+ ideg = pu._deprecate_as_int(deg, "deg")
1097
+ if ideg < 0:
1098
+ raise ValueError("deg must be non-negative")
1099
+
1100
+ x = np.array(x, copy=False, ndmin=1) + 0.0
1101
+ dims = (ideg + 1,) + x.shape
1102
+ dtyp = x.dtype
1103
+ v = np.empty(dims, dtype=dtyp)
1104
+ v[0] = x*0 + 1
1105
+ if ideg > 0:
1106
+ v[1] = x
1107
+ for i in range(2, ideg + 1):
1108
+ v[i] = v[i-1]*x
1109
+ return np.moveaxis(v, 0, -1)
1110
+
1111
+
1112
+ def polyvander2d(x, y, deg):
1113
+ """Pseudo-Vandermonde matrix of given degrees.
1114
+
1115
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1116
+ points `(x, y)`. The pseudo-Vandermonde matrix is defined by
1117
+
1118
+ .. math:: V[..., (deg[1] + 1)*i + j] = x^i * y^j,
1119
+
1120
+ where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
1121
+ `V` index the points `(x, y)` and the last index encodes the powers of
1122
+ `x` and `y`.
1123
+
1124
+ If ``V = polyvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
1125
+ correspond to the elements of a 2-D coefficient array `c` of shape
1126
+ (xdeg + 1, ydeg + 1) in the order
1127
+
1128
+ .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
1129
+
1130
+ and ``np.dot(V, c.flat)`` and ``polyval2d(x, y, c)`` will be the same
1131
+ up to roundoff. This equivalence is useful both for least squares
1132
+ fitting and for the evaluation of a large number of 2-D polynomials
1133
+ of the same degrees and sample points.
1134
+
1135
+ Parameters
1136
+ ----------
1137
+ x, y : array_like
1138
+ Arrays of point coordinates, all of the same shape. The dtypes
1139
+ will be converted to either float64 or complex128 depending on
1140
+ whether any of the elements are complex. Scalars are converted to
1141
+ 1-D arrays.
1142
+ deg : list of ints
1143
+ List of maximum degrees of the form [x_deg, y_deg].
1144
+
1145
+ Returns
1146
+ -------
1147
+ vander2d : ndarray
1148
+ The shape of the returned matrix is ``x.shape + (order,)``, where
1149
+ :math:`order = (deg[0]+1)*(deg([1]+1)`. The dtype will be the same
1150
+ as the converted `x` and `y`.
1151
+
1152
+ See Also
1153
+ --------
1154
+ polyvander, polyvander3d, polyval2d, polyval3d
1155
+
1156
+ """
1157
+ return pu._vander_nd_flat((polyvander, polyvander), (x, y), deg)
1158
+
1159
+
1160
+ def polyvander3d(x, y, z, deg):
1161
+ """Pseudo-Vandermonde matrix of given degrees.
1162
+
1163
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1164
+ points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
1165
+ then The pseudo-Vandermonde matrix is defined by
1166
+
1167
+ .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = x^i * y^j * z^k,
1168
+
1169
+ where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
1170
+ indices of `V` index the points `(x, y, z)` and the last index encodes
1171
+ the powers of `x`, `y`, and `z`.
1172
+
1173
+ If ``V = polyvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
1174
+ of `V` correspond to the elements of a 3-D coefficient array `c` of
1175
+ shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
1176
+
1177
+ .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
1178
+
1179
+ and ``np.dot(V, c.flat)`` and ``polyval3d(x, y, z, c)`` will be the
1180
+ same up to roundoff. This equivalence is useful both for least squares
1181
+ fitting and for the evaluation of a large number of 3-D polynomials
1182
+ of the same degrees and sample points.
1183
+
1184
+ Parameters
1185
+ ----------
1186
+ x, y, z : array_like
1187
+ Arrays of point coordinates, all of the same shape. The dtypes will
1188
+ be converted to either float64 or complex128 depending on whether
1189
+ any of the elements are complex. Scalars are converted to 1-D
1190
+ arrays.
1191
+ deg : list of ints
1192
+ List of maximum degrees of the form [x_deg, y_deg, z_deg].
1193
+
1194
+ Returns
1195
+ -------
1196
+ vander3d : ndarray
1197
+ The shape of the returned matrix is ``x.shape + (order,)``, where
1198
+ :math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`. The dtype will
1199
+ be the same as the converted `x`, `y`, and `z`.
1200
+
1201
+ See Also
1202
+ --------
1203
+ polyvander, polyvander3d, polyval2d, polyval3d
1204
+
1205
+ Notes
1206
+ -----
1207
+
1208
+ .. versionadded:: 1.7.0
1209
+
1210
+ """
1211
+ return pu._vander_nd_flat((polyvander, polyvander, polyvander), (x, y, z), deg)
1212
+
1213
+
1214
+ def polyfit(x, y, deg, rcond=None, full=False, w=None):
1215
+ """
1216
+ Least-squares fit of a polynomial to data.
1217
+
1218
+ Return the coefficients of a polynomial of degree `deg` that is the
1219
+ least squares fit to the data values `y` given at points `x`. If `y` is
1220
+ 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
1221
+ fits are done, one for each column of `y`, and the resulting
1222
+ coefficients are stored in the corresponding columns of a 2-D return.
1223
+ The fitted polynomial(s) are in the form
1224
+
1225
+ .. math:: p(x) = c_0 + c_1 * x + ... + c_n * x^n,
1226
+
1227
+ where `n` is `deg`.
1228
+
1229
+ Parameters
1230
+ ----------
1231
+ x : array_like, shape (`M`,)
1232
+ x-coordinates of the `M` sample (data) points ``(x[i], y[i])``.
1233
+ y : array_like, shape (`M`,) or (`M`, `K`)
1234
+ y-coordinates of the sample points. Several sets of sample points
1235
+ sharing the same x-coordinates can be (independently) fit with one
1236
+ call to `polyfit` by passing in for `y` a 2-D array that contains
1237
+ one data set per column.
1238
+ deg : int or 1-D array_like
1239
+ Degree(s) of the fitting polynomials. If `deg` is a single integer
1240
+ all terms up to and including the `deg`'th term are included in the
1241
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
1242
+ degrees of the terms to include may be used instead.
1243
+ rcond : float, optional
1244
+ Relative condition number of the fit. Singular values smaller
1245
+ than `rcond`, relative to the largest singular value, will be
1246
+ ignored. The default value is ``len(x)*eps``, where `eps` is the
1247
+ relative precision of the platform's float type, about 2e-16 in
1248
+ most cases.
1249
+ full : bool, optional
1250
+ Switch determining the nature of the return value. When ``False``
1251
+ (the default) just the coefficients are returned; when ``True``,
1252
+ diagnostic information from the singular value decomposition (used
1253
+ to solve the fit's matrix equation) is also returned.
1254
+ w : array_like, shape (`M`,), optional
1255
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
1256
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
1257
+ chosen so that the errors of the products ``w[i]*y[i]`` all have the
1258
+ same variance. When using inverse-variance weighting, use
1259
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
1260
+
1261
+ .. versionadded:: 1.5.0
1262
+
1263
+ Returns
1264
+ -------
1265
+ coef : ndarray, shape (`deg` + 1,) or (`deg` + 1, `K`)
1266
+ Polynomial coefficients ordered from low to high. If `y` was 2-D,
1267
+ the coefficients in column `k` of `coef` represent the polynomial
1268
+ fit to the data in `y`'s `k`-th column.
1269
+
1270
+ [residuals, rank, singular_values, rcond] : list
1271
+ These values are only returned if ``full == True``
1272
+
1273
+ - residuals -- sum of squared residuals of the least squares fit
1274
+ - rank -- the numerical rank of the scaled Vandermonde matrix
1275
+ - singular_values -- singular values of the scaled Vandermonde matrix
1276
+ - rcond -- value of `rcond`.
1277
+
1278
+ For more details, see `numpy.linalg.lstsq`.
1279
+
1280
+ Raises
1281
+ ------
1282
+ RankWarning
1283
+ Raised if the matrix in the least-squares fit is rank deficient.
1284
+ The warning is only raised if ``full == False``. The warnings can
1285
+ be turned off by:
1286
+
1287
+ >>> import warnings
1288
+ >>> warnings.simplefilter('ignore', np.RankWarning)
1289
+
1290
+ See Also
1291
+ --------
1292
+ numpy.polynomial.chebyshev.chebfit
1293
+ numpy.polynomial.legendre.legfit
1294
+ numpy.polynomial.laguerre.lagfit
1295
+ numpy.polynomial.hermite.hermfit
1296
+ numpy.polynomial.hermite_e.hermefit
1297
+ polyval : Evaluates a polynomial.
1298
+ polyvander : Vandermonde matrix for powers.
1299
+ numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
1300
+ scipy.interpolate.UnivariateSpline : Computes spline fits.
1301
+
1302
+ Notes
1303
+ -----
1304
+ The solution is the coefficients of the polynomial `p` that minimizes
1305
+ the sum of the weighted squared errors
1306
+
1307
+ .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
1308
+
1309
+ where the :math:`w_j` are the weights. This problem is solved by
1310
+ setting up the (typically) over-determined matrix equation:
1311
+
1312
+ .. math:: V(x) * c = w * y,
1313
+
1314
+ where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the
1315
+ coefficients to be solved for, `w` are the weights, and `y` are the
1316
+ observed values. This equation is then solved using the singular value
1317
+ decomposition of `V`.
1318
+
1319
+ If some of the singular values of `V` are so small that they are
1320
+ neglected (and `full` == ``False``), a `RankWarning` will be raised.
1321
+ This means that the coefficient values may be poorly determined.
1322
+ Fitting to a lower order polynomial will usually get rid of the warning
1323
+ (but may not be what you want, of course; if you have independent
1324
+ reason(s) for choosing the degree which isn't working, you may have to:
1325
+ a) reconsider those reasons, and/or b) reconsider the quality of your
1326
+ data). The `rcond` parameter can also be set to a value smaller than
1327
+ its default, but the resulting fit may be spurious and have large
1328
+ contributions from roundoff error.
1329
+
1330
+ Polynomial fits using double precision tend to "fail" at about
1331
+ (polynomial) degree 20. Fits using Chebyshev or Legendre series are
1332
+ generally better conditioned, but much can still depend on the
1333
+ distribution of the sample points and the smoothness of the data. If
1334
+ the quality of the fit is inadequate, splines may be a good
1335
+ alternative.
1336
+
1337
+ Examples
1338
+ --------
1339
+ >>> np.random.seed(123)
1340
+ >>> from numpy.polynomial import polynomial as P
1341
+ >>> x = np.linspace(-1,1,51) # x "data": [-1, -0.96, ..., 0.96, 1]
1342
+ >>> y = x**3 - x + np.random.randn(len(x)) # x^3 - x + Gaussian noise
1343
+ >>> c, stats = P.polyfit(x,y,3,full=True)
1344
+ >>> np.random.seed(123)
1345
+ >>> c # c[0], c[2] should be approx. 0, c[1] approx. -1, c[3] approx. 1
1346
+ array([ 0.01909725, -1.30598256, -0.00577963, 1.02644286]) # may vary
1347
+ >>> stats # note the large SSR, explaining the rather poor results
1348
+ [array([ 38.06116253]), 4, array([ 1.38446749, 1.32119158, 0.50443316, # may vary
1349
+ 0.28853036]), 1.1324274851176597e-014]
1350
+
1351
+ Same thing without the added noise
1352
+
1353
+ >>> y = x**3 - x
1354
+ >>> c, stats = P.polyfit(x,y,3,full=True)
1355
+ >>> c # c[0], c[2] should be "very close to 0", c[1] ~= -1, c[3] ~= 1
1356
+ array([-6.36925336e-18, -1.00000000e+00, -4.08053781e-16, 1.00000000e+00])
1357
+ >>> stats # note the minuscule SSR
1358
+ [array([ 7.46346754e-31]), 4, array([ 1.38446749, 1.32119158, # may vary
1359
+ 0.50443316, 0.28853036]), 1.1324274851176597e-014]
1360
+
1361
+ """
1362
+ return pu._fit(polyvander, x, y, deg, rcond, full, w)
1363
+
1364
+
1365
+ def polycompanion(c):
1366
+ """
1367
+ Return the companion matrix of c.
1368
+
1369
+ The companion matrix for power series cannot be made symmetric by
1370
+ scaling the basis, so this function differs from those for the
1371
+ orthogonal polynomials.
1372
+
1373
+ Parameters
1374
+ ----------
1375
+ c : array_like
1376
+ 1-D array of polynomial coefficients ordered from low to high
1377
+ degree.
1378
+
1379
+ Returns
1380
+ -------
1381
+ mat : ndarray
1382
+ Companion matrix of dimensions (deg, deg).
1383
+
1384
+ Notes
1385
+ -----
1386
+
1387
+ .. versionadded:: 1.7.0
1388
+
1389
+ """
1390
+ # c is a trimmed copy
1391
+ [c] = pu.as_series([c])
1392
+ if len(c) < 2:
1393
+ raise ValueError('Series must have maximum degree of at least 1.')
1394
+ if len(c) == 2:
1395
+ return np.array([[-c[0]/c[1]]])
1396
+
1397
+ n = len(c) - 1
1398
+ mat = np.zeros((n, n), dtype=c.dtype)
1399
+ bot = mat.reshape(-1)[n::n+1]
1400
+ bot[...] = 1
1401
+ mat[:, -1] -= c[:-1]/c[-1]
1402
+ return mat
1403
+
1404
+
1405
+ def polyroots(c):
1406
+ """
1407
+ Compute the roots of a polynomial.
1408
+
1409
+ Return the roots (a.k.a. "zeros") of the polynomial
1410
+
1411
+ .. math:: p(x) = \\sum_i c[i] * x^i.
1412
+
1413
+ Parameters
1414
+ ----------
1415
+ c : 1-D array_like
1416
+ 1-D array of polynomial coefficients.
1417
+
1418
+ Returns
1419
+ -------
1420
+ out : ndarray
1421
+ Array of the roots of the polynomial. If all the roots are real,
1422
+ then `out` is also real, otherwise it is complex.
1423
+
1424
+ See Also
1425
+ --------
1426
+ numpy.polynomial.chebyshev.chebroots
1427
+ numpy.polynomial.legendre.legroots
1428
+ numpy.polynomial.laguerre.lagroots
1429
+ numpy.polynomial.hermite.hermroots
1430
+ numpy.polynomial.hermite_e.hermeroots
1431
+
1432
+ Notes
1433
+ -----
1434
+ The root estimates are obtained as the eigenvalues of the companion
1435
+ matrix, Roots far from the origin of the complex plane may have large
1436
+ errors due to the numerical instability of the power series for such
1437
+ values. Roots with multiplicity greater than 1 will also show larger
1438
+ errors as the value of the series near such points is relatively
1439
+ insensitive to errors in the roots. Isolated roots near the origin can
1440
+ be improved by a few iterations of Newton's method.
1441
+
1442
+ Examples
1443
+ --------
1444
+ >>> import numpy.polynomial.polynomial as poly
1445
+ >>> poly.polyroots(poly.polyfromroots((-1,0,1)))
1446
+ array([-1., 0., 1.])
1447
+ >>> poly.polyroots(poly.polyfromroots((-1,0,1))).dtype
1448
+ dtype('float64')
1449
+ >>> j = complex(0,1)
1450
+ >>> poly.polyroots(poly.polyfromroots((-j,0,j)))
1451
+ array([ 0.00000000e+00+0.j, 0.00000000e+00+1.j, 2.77555756e-17-1.j]) # may vary
1452
+
1453
+ """
1454
+ # c is a trimmed copy
1455
+ [c] = pu.as_series([c])
1456
+ if len(c) < 2:
1457
+ return np.array([], dtype=c.dtype)
1458
+ if len(c) == 2:
1459
+ return np.array([-c[0]/c[1]])
1460
+
1461
+ # rotated companion matrix reduces error
1462
+ m = polycompanion(c)[::-1,::-1]
1463
+ r = la.eigvals(m)
1464
+ r.sort()
1465
+ return r
1466
+
1467
+
1468
+ #
1469
+ # polynomial class
1470
+ #
1471
+
1472
+ class Polynomial(ABCPolyBase):
1473
+ """A power series class.
1474
+
1475
+ The Polynomial class provides the standard Python numerical methods
1476
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
1477
+ attributes and methods listed in the `ABCPolyBase` documentation.
1478
+
1479
+ Parameters
1480
+ ----------
1481
+ coef : array_like
1482
+ Polynomial coefficients in order of increasing degree, i.e.,
1483
+ ``(1, 2, 3)`` give ``1 + 2*x + 3*x**2``.
1484
+ domain : (2,) array_like, optional
1485
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
1486
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
1487
+ The default value is [-1, 1].
1488
+ window : (2,) array_like, optional
1489
+ Window, see `domain` for its use. The default value is [-1, 1].
1490
+
1491
+ .. versionadded:: 1.6.0
1492
+ symbol : str, optional
1493
+ Symbol used to represent the independent variable in string
1494
+ representations of the polynomial expression, e.g. for printing.
1495
+ The symbol must be a valid Python identifier. Default value is 'x'.
1496
+
1497
+ .. versionadded:: 1.24
1498
+
1499
+ """
1500
+ # Virtual Functions
1501
+ _add = staticmethod(polyadd)
1502
+ _sub = staticmethod(polysub)
1503
+ _mul = staticmethod(polymul)
1504
+ _div = staticmethod(polydiv)
1505
+ _pow = staticmethod(polypow)
1506
+ _val = staticmethod(polyval)
1507
+ _int = staticmethod(polyint)
1508
+ _der = staticmethod(polyder)
1509
+ _fit = staticmethod(polyfit)
1510
+ _line = staticmethod(polyline)
1511
+ _roots = staticmethod(polyroots)
1512
+ _fromroots = staticmethod(polyfromroots)
1513
+
1514
+ # Virtual properties
1515
+ domain = np.array(polydomain)
1516
+ window = np.array(polydomain)
1517
+ basis_name = None
1518
+
1519
+ @classmethod
1520
+ def _str_term_unicode(cls, i, arg_str):
1521
+ if i == '1':
1522
+ return f"·{arg_str}"
1523
+ else:
1524
+ return f"·{arg_str}{i.translate(cls._superscript_mapping)}"
1525
+
1526
+ @staticmethod
1527
+ def _str_term_ascii(i, arg_str):
1528
+ if i == '1':
1529
+ return f" {arg_str}"
1530
+ else:
1531
+ return f" {arg_str}**{i}"
1532
+
1533
+ @staticmethod
1534
+ def _repr_latex_term(i, arg_str, needs_parens):
1535
+ if needs_parens:
1536
+ arg_str = rf"\left({arg_str}\right)"
1537
+ if i == 0:
1538
+ return '1'
1539
+ elif i == 1:
1540
+ return arg_str
1541
+ else:
1542
+ return f"{arg_str}^{{{i}}}"
lib/python3.12/site-packages/numpy/polynomial/polynomial.pyi ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any
2
+
3
+ from numpy import ndarray, dtype, int_
4
+ from numpy.polynomial._polybase import ABCPolyBase
5
+ from numpy.polynomial.polyutils import trimcoef
6
+
7
+ __all__: list[str]
8
+
9
+ polytrim = trimcoef
10
+
11
+ polydomain: ndarray[Any, dtype[int_]]
12
+ polyzero: ndarray[Any, dtype[int_]]
13
+ polyone: ndarray[Any, dtype[int_]]
14
+ polyx: ndarray[Any, dtype[int_]]
15
+
16
+ def polyline(off, scl): ...
17
+ def polyfromroots(roots): ...
18
+ def polyadd(c1, c2): ...
19
+ def polysub(c1, c2): ...
20
+ def polymulx(c): ...
21
+ def polymul(c1, c2): ...
22
+ def polydiv(c1, c2): ...
23
+ def polypow(c, pow, maxpower=...): ...
24
+ def polyder(c, m=..., scl=..., axis=...): ...
25
+ def polyint(c, m=..., k=..., lbnd=..., scl=..., axis=...): ...
26
+ def polyval(x, c, tensor=...): ...
27
+ def polyvalfromroots(x, r, tensor=...): ...
28
+ def polyval2d(x, y, c): ...
29
+ def polygrid2d(x, y, c): ...
30
+ def polyval3d(x, y, z, c): ...
31
+ def polygrid3d(x, y, z, c): ...
32
+ def polyvander(x, deg): ...
33
+ def polyvander2d(x, y, deg): ...
34
+ def polyvander3d(x, y, z, deg): ...
35
+ def polyfit(x, y, deg, rcond=..., full=..., w=...): ...
36
+ def polyroots(c): ...
37
+
38
+ class Polynomial(ABCPolyBase):
39
+ domain: Any
40
+ window: Any
41
+ basis_name: Any
lib/python3.12/site-packages/numpy/polynomial/polyutils.py ADDED
@@ -0,0 +1,789 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Utility classes and functions for the polynomial modules.
3
+
4
+ This module provides: error and warning objects; a polynomial base class;
5
+ and some routines used in both the `polynomial` and `chebyshev` modules.
6
+
7
+ Warning objects
8
+ ---------------
9
+
10
+ .. autosummary::
11
+ :toctree: generated/
12
+
13
+ RankWarning raised in least-squares fit for rank-deficient matrix.
14
+
15
+ Functions
16
+ ---------
17
+
18
+ .. autosummary::
19
+ :toctree: generated/
20
+
21
+ as_series convert list of array_likes into 1-D arrays of common type.
22
+ trimseq remove trailing zeros.
23
+ trimcoef remove small trailing coefficients.
24
+ getdomain return the domain appropriate for a given set of abscissae.
25
+ mapdomain maps points between domains.
26
+ mapparms parameters of the linear map between domains.
27
+
28
+ """
29
+ import operator
30
+ import functools
31
+ import warnings
32
+
33
+ import numpy as np
34
+
35
+ from numpy.core.multiarray import dragon4_positional, dragon4_scientific
36
+ from numpy.core.umath import absolute
37
+
38
+ __all__ = [
39
+ 'RankWarning', 'as_series', 'trimseq',
40
+ 'trimcoef', 'getdomain', 'mapdomain', 'mapparms',
41
+ 'format_float']
42
+
43
+ #
44
+ # Warnings and Exceptions
45
+ #
46
+
47
+ class RankWarning(UserWarning):
48
+ """Issued by chebfit when the design matrix is rank deficient."""
49
+ pass
50
+
51
+ #
52
+ # Helper functions to convert inputs to 1-D arrays
53
+ #
54
+ def trimseq(seq):
55
+ """Remove small Poly series coefficients.
56
+
57
+ Parameters
58
+ ----------
59
+ seq : sequence
60
+ Sequence of Poly series coefficients. This routine fails for
61
+ empty sequences.
62
+
63
+ Returns
64
+ -------
65
+ series : sequence
66
+ Subsequence with trailing zeros removed. If the resulting sequence
67
+ would be empty, return the first element. The returned sequence may
68
+ or may not be a view.
69
+
70
+ Notes
71
+ -----
72
+ Do not lose the type info if the sequence contains unknown objects.
73
+
74
+ """
75
+ if len(seq) == 0:
76
+ return seq
77
+ else:
78
+ for i in range(len(seq) - 1, -1, -1):
79
+ if seq[i] != 0:
80
+ break
81
+ return seq[:i+1]
82
+
83
+
84
+ def as_series(alist, trim=True):
85
+ """
86
+ Return argument as a list of 1-d arrays.
87
+
88
+ The returned list contains array(s) of dtype double, complex double, or
89
+ object. A 1-d argument of shape ``(N,)`` is parsed into ``N`` arrays of
90
+ size one; a 2-d argument of shape ``(M,N)`` is parsed into ``M`` arrays
91
+ of size ``N`` (i.e., is "parsed by row"); and a higher dimensional array
92
+ raises a Value Error if it is not first reshaped into either a 1-d or 2-d
93
+ array.
94
+
95
+ Parameters
96
+ ----------
97
+ alist : array_like
98
+ A 1- or 2-d array_like
99
+ trim : boolean, optional
100
+ When True, trailing zeros are removed from the inputs.
101
+ When False, the inputs are passed through intact.
102
+
103
+ Returns
104
+ -------
105
+ [a1, a2,...] : list of 1-D arrays
106
+ A copy of the input data as a list of 1-d arrays.
107
+
108
+ Raises
109
+ ------
110
+ ValueError
111
+ Raised when `as_series` cannot convert its input to 1-d arrays, or at
112
+ least one of the resulting arrays is empty.
113
+
114
+ Examples
115
+ --------
116
+ >>> from numpy.polynomial import polyutils as pu
117
+ >>> a = np.arange(4)
118
+ >>> pu.as_series(a)
119
+ [array([0.]), array([1.]), array([2.]), array([3.])]
120
+ >>> b = np.arange(6).reshape((2,3))
121
+ >>> pu.as_series(b)
122
+ [array([0., 1., 2.]), array([3., 4., 5.])]
123
+
124
+ >>> pu.as_series((1, np.arange(3), np.arange(2, dtype=np.float16)))
125
+ [array([1.]), array([0., 1., 2.]), array([0., 1.])]
126
+
127
+ >>> pu.as_series([2, [1.1, 0.]])
128
+ [array([2.]), array([1.1])]
129
+
130
+ >>> pu.as_series([2, [1.1, 0.]], trim=False)
131
+ [array([2.]), array([1.1, 0. ])]
132
+
133
+ """
134
+ arrays = [np.array(a, ndmin=1, copy=False) for a in alist]
135
+ if min([a.size for a in arrays]) == 0:
136
+ raise ValueError("Coefficient array is empty")
137
+ if any(a.ndim != 1 for a in arrays):
138
+ raise ValueError("Coefficient array is not 1-d")
139
+ if trim:
140
+ arrays = [trimseq(a) for a in arrays]
141
+
142
+ if any(a.dtype == np.dtype(object) for a in arrays):
143
+ ret = []
144
+ for a in arrays:
145
+ if a.dtype != np.dtype(object):
146
+ tmp = np.empty(len(a), dtype=np.dtype(object))
147
+ tmp[:] = a[:]
148
+ ret.append(tmp)
149
+ else:
150
+ ret.append(a.copy())
151
+ else:
152
+ try:
153
+ dtype = np.common_type(*arrays)
154
+ except Exception as e:
155
+ raise ValueError("Coefficient arrays have no common type") from e
156
+ ret = [np.array(a, copy=True, dtype=dtype) for a in arrays]
157
+ return ret
158
+
159
+
160
+ def trimcoef(c, tol=0):
161
+ """
162
+ Remove "small" "trailing" coefficients from a polynomial.
163
+
164
+ "Small" means "small in absolute value" and is controlled by the
165
+ parameter `tol`; "trailing" means highest order coefficient(s), e.g., in
166
+ ``[0, 1, 1, 0, 0]`` (which represents ``0 + x + x**2 + 0*x**3 + 0*x**4``)
167
+ both the 3-rd and 4-th order coefficients would be "trimmed."
168
+
169
+ Parameters
170
+ ----------
171
+ c : array_like
172
+ 1-d array of coefficients, ordered from lowest order to highest.
173
+ tol : number, optional
174
+ Trailing (i.e., highest order) elements with absolute value less
175
+ than or equal to `tol` (default value is zero) are removed.
176
+
177
+ Returns
178
+ -------
179
+ trimmed : ndarray
180
+ 1-d array with trailing zeros removed. If the resulting series
181
+ would be empty, a series containing a single zero is returned.
182
+
183
+ Raises
184
+ ------
185
+ ValueError
186
+ If `tol` < 0
187
+
188
+ See Also
189
+ --------
190
+ trimseq
191
+
192
+ Examples
193
+ --------
194
+ >>> from numpy.polynomial import polyutils as pu
195
+ >>> pu.trimcoef((0,0,3,0,5,0,0))
196
+ array([0., 0., 3., 0., 5.])
197
+ >>> pu.trimcoef((0,0,1e-3,0,1e-5,0,0),1e-3) # item == tol is trimmed
198
+ array([0.])
199
+ >>> i = complex(0,1) # works for complex
200
+ >>> pu.trimcoef((3e-4,1e-3*(1-i),5e-4,2e-5*(1+i)), 1e-3)
201
+ array([0.0003+0.j , 0.001 -0.001j])
202
+
203
+ """
204
+ if tol < 0:
205
+ raise ValueError("tol must be non-negative")
206
+
207
+ [c] = as_series([c])
208
+ [ind] = np.nonzero(np.abs(c) > tol)
209
+ if len(ind) == 0:
210
+ return c[:1]*0
211
+ else:
212
+ return c[:ind[-1] + 1].copy()
213
+
214
+ def getdomain(x):
215
+ """
216
+ Return a domain suitable for given abscissae.
217
+
218
+ Find a domain suitable for a polynomial or Chebyshev series
219
+ defined at the values supplied.
220
+
221
+ Parameters
222
+ ----------
223
+ x : array_like
224
+ 1-d array of abscissae whose domain will be determined.
225
+
226
+ Returns
227
+ -------
228
+ domain : ndarray
229
+ 1-d array containing two values. If the inputs are complex, then
230
+ the two returned points are the lower left and upper right corners
231
+ of the smallest rectangle (aligned with the axes) in the complex
232
+ plane containing the points `x`. If the inputs are real, then the
233
+ two points are the ends of the smallest interval containing the
234
+ points `x`.
235
+
236
+ See Also
237
+ --------
238
+ mapparms, mapdomain
239
+
240
+ Examples
241
+ --------
242
+ >>> from numpy.polynomial import polyutils as pu
243
+ >>> points = np.arange(4)**2 - 5; points
244
+ array([-5, -4, -1, 4])
245
+ >>> pu.getdomain(points)
246
+ array([-5., 4.])
247
+ >>> c = np.exp(complex(0,1)*np.pi*np.arange(12)/6) # unit circle
248
+ >>> pu.getdomain(c)
249
+ array([-1.-1.j, 1.+1.j])
250
+
251
+ """
252
+ [x] = as_series([x], trim=False)
253
+ if x.dtype.char in np.typecodes['Complex']:
254
+ rmin, rmax = x.real.min(), x.real.max()
255
+ imin, imax = x.imag.min(), x.imag.max()
256
+ return np.array((complex(rmin, imin), complex(rmax, imax)))
257
+ else:
258
+ return np.array((x.min(), x.max()))
259
+
260
+ def mapparms(old, new):
261
+ """
262
+ Linear map parameters between domains.
263
+
264
+ Return the parameters of the linear map ``offset + scale*x`` that maps
265
+ `old` to `new` such that ``old[i] -> new[i]``, ``i = 0, 1``.
266
+
267
+ Parameters
268
+ ----------
269
+ old, new : array_like
270
+ Domains. Each domain must (successfully) convert to a 1-d array
271
+ containing precisely two values.
272
+
273
+ Returns
274
+ -------
275
+ offset, scale : scalars
276
+ The map ``L(x) = offset + scale*x`` maps the first domain to the
277
+ second.
278
+
279
+ See Also
280
+ --------
281
+ getdomain, mapdomain
282
+
283
+ Notes
284
+ -----
285
+ Also works for complex numbers, and thus can be used to calculate the
286
+ parameters required to map any line in the complex plane to any other
287
+ line therein.
288
+
289
+ Examples
290
+ --------
291
+ >>> from numpy.polynomial import polyutils as pu
292
+ >>> pu.mapparms((-1,1),(-1,1))
293
+ (0.0, 1.0)
294
+ >>> pu.mapparms((1,-1),(-1,1))
295
+ (-0.0, -1.0)
296
+ >>> i = complex(0,1)
297
+ >>> pu.mapparms((-i,-1),(1,i))
298
+ ((1+1j), (1-0j))
299
+
300
+ """
301
+ oldlen = old[1] - old[0]
302
+ newlen = new[1] - new[0]
303
+ off = (old[1]*new[0] - old[0]*new[1])/oldlen
304
+ scl = newlen/oldlen
305
+ return off, scl
306
+
307
+ def mapdomain(x, old, new):
308
+ """
309
+ Apply linear map to input points.
310
+
311
+ The linear map ``offset + scale*x`` that maps the domain `old` to
312
+ the domain `new` is applied to the points `x`.
313
+
314
+ Parameters
315
+ ----------
316
+ x : array_like
317
+ Points to be mapped. If `x` is a subtype of ndarray the subtype
318
+ will be preserved.
319
+ old, new : array_like
320
+ The two domains that determine the map. Each must (successfully)
321
+ convert to 1-d arrays containing precisely two values.
322
+
323
+ Returns
324
+ -------
325
+ x_out : ndarray
326
+ Array of points of the same shape as `x`, after application of the
327
+ linear map between the two domains.
328
+
329
+ See Also
330
+ --------
331
+ getdomain, mapparms
332
+
333
+ Notes
334
+ -----
335
+ Effectively, this implements:
336
+
337
+ .. math::
338
+ x\\_out = new[0] + m(x - old[0])
339
+
340
+ where
341
+
342
+ .. math::
343
+ m = \\frac{new[1]-new[0]}{old[1]-old[0]}
344
+
345
+ Examples
346
+ --------
347
+ >>> from numpy.polynomial import polyutils as pu
348
+ >>> old_domain = (-1,1)
349
+ >>> new_domain = (0,2*np.pi)
350
+ >>> x = np.linspace(-1,1,6); x
351
+ array([-1. , -0.6, -0.2, 0.2, 0.6, 1. ])
352
+ >>> x_out = pu.mapdomain(x, old_domain, new_domain); x_out
353
+ array([ 0. , 1.25663706, 2.51327412, 3.76991118, 5.02654825, # may vary
354
+ 6.28318531])
355
+ >>> x - pu.mapdomain(x_out, new_domain, old_domain)
356
+ array([0., 0., 0., 0., 0., 0.])
357
+
358
+ Also works for complex numbers (and thus can be used to map any line in
359
+ the complex plane to any other line therein).
360
+
361
+ >>> i = complex(0,1)
362
+ >>> old = (-1 - i, 1 + i)
363
+ >>> new = (-1 + i, 1 - i)
364
+ >>> z = np.linspace(old[0], old[1], 6); z
365
+ array([-1. -1.j , -0.6-0.6j, -0.2-0.2j, 0.2+0.2j, 0.6+0.6j, 1. +1.j ])
366
+ >>> new_z = pu.mapdomain(z, old, new); new_z
367
+ 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
368
+
369
+ """
370
+ x = np.asanyarray(x)
371
+ off, scl = mapparms(old, new)
372
+ return off + scl*x
373
+
374
+
375
+ def _nth_slice(i, ndim):
376
+ sl = [np.newaxis] * ndim
377
+ sl[i] = slice(None)
378
+ return tuple(sl)
379
+
380
+
381
+ def _vander_nd(vander_fs, points, degrees):
382
+ r"""
383
+ A generalization of the Vandermonde matrix for N dimensions
384
+
385
+ The result is built by combining the results of 1d Vandermonde matrices,
386
+
387
+ .. math::
388
+ 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]}
389
+
390
+ where
391
+
392
+ .. math::
393
+ N &= \texttt{len(points)} = \texttt{len(degrees)} = \texttt{len(vander\_fs)} \\
394
+ M &= \texttt{points[k].ndim} \\
395
+ V_k &= \texttt{vander\_fs[k]} \\
396
+ x_k &= \texttt{points[k]} \\
397
+ 0 \le j_k &\le \texttt{degrees[k]}
398
+
399
+ Expanding the one-dimensional :math:`V_k` functions gives:
400
+
401
+ .. math::
402
+ 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])}
403
+
404
+ where :math:`B_{k,m}` is the m'th basis of the polynomial construction used along
405
+ dimension :math:`k`. For a regular polynomial, :math:`B_{k, m}(x) = P_m(x) = x^m`.
406
+
407
+ Parameters
408
+ ----------
409
+ vander_fs : Sequence[function(array_like, int) -> ndarray]
410
+ The 1d vander function to use for each axis, such as ``polyvander``
411
+ points : Sequence[array_like]
412
+ Arrays of point coordinates, all of the same shape. The dtypes
413
+ will be converted to either float64 or complex128 depending on
414
+ whether any of the elements are complex. Scalars are converted to
415
+ 1-D arrays.
416
+ This must be the same length as `vander_fs`.
417
+ degrees : Sequence[int]
418
+ The maximum degree (inclusive) to use for each axis.
419
+ This must be the same length as `vander_fs`.
420
+
421
+ Returns
422
+ -------
423
+ vander_nd : ndarray
424
+ An array of shape ``points[0].shape + tuple(d + 1 for d in degrees)``.
425
+ """
426
+ n_dims = len(vander_fs)
427
+ if n_dims != len(points):
428
+ raise ValueError(
429
+ f"Expected {n_dims} dimensions of sample points, got {len(points)}")
430
+ if n_dims != len(degrees):
431
+ raise ValueError(
432
+ f"Expected {n_dims} dimensions of degrees, got {len(degrees)}")
433
+ if n_dims == 0:
434
+ raise ValueError("Unable to guess a dtype or shape when no points are given")
435
+
436
+ # convert to the same shape and type
437
+ points = tuple(np.array(tuple(points), copy=False) + 0.0)
438
+
439
+ # produce the vandermonde matrix for each dimension, placing the last
440
+ # axis of each in an independent trailing axis of the output
441
+ vander_arrays = (
442
+ vander_fs[i](points[i], degrees[i])[(...,) + _nth_slice(i, n_dims)]
443
+ for i in range(n_dims)
444
+ )
445
+
446
+ # we checked this wasn't empty already, so no `initial` needed
447
+ return functools.reduce(operator.mul, vander_arrays)
448
+
449
+
450
+ def _vander_nd_flat(vander_fs, points, degrees):
451
+ """
452
+ Like `_vander_nd`, but flattens the last ``len(degrees)`` axes into a single axis
453
+
454
+ Used to implement the public ``<type>vander<n>d`` functions.
455
+ """
456
+ v = _vander_nd(vander_fs, points, degrees)
457
+ return v.reshape(v.shape[:-len(degrees)] + (-1,))
458
+
459
+
460
+ def _fromroots(line_f, mul_f, roots):
461
+ """
462
+ Helper function used to implement the ``<type>fromroots`` functions.
463
+
464
+ Parameters
465
+ ----------
466
+ line_f : function(float, float) -> ndarray
467
+ The ``<type>line`` function, such as ``polyline``
468
+ mul_f : function(array_like, array_like) -> ndarray
469
+ The ``<type>mul`` function, such as ``polymul``
470
+ roots
471
+ See the ``<type>fromroots`` functions for more detail
472
+ """
473
+ if len(roots) == 0:
474
+ return np.ones(1)
475
+ else:
476
+ [roots] = as_series([roots], trim=False)
477
+ roots.sort()
478
+ p = [line_f(-r, 1) for r in roots]
479
+ n = len(p)
480
+ while n > 1:
481
+ m, r = divmod(n, 2)
482
+ tmp = [mul_f(p[i], p[i+m]) for i in range(m)]
483
+ if r:
484
+ tmp[0] = mul_f(tmp[0], p[-1])
485
+ p = tmp
486
+ n = m
487
+ return p[0]
488
+
489
+
490
+ def _valnd(val_f, c, *args):
491
+ """
492
+ Helper function used to implement the ``<type>val<n>d`` functions.
493
+
494
+ Parameters
495
+ ----------
496
+ val_f : function(array_like, array_like, tensor: bool) -> array_like
497
+ The ``<type>val`` function, such as ``polyval``
498
+ c, args
499
+ See the ``<type>val<n>d`` functions for more detail
500
+ """
501
+ args = [np.asanyarray(a) for a in args]
502
+ shape0 = args[0].shape
503
+ if not all((a.shape == shape0 for a in args[1:])):
504
+ if len(args) == 3:
505
+ raise ValueError('x, y, z are incompatible')
506
+ elif len(args) == 2:
507
+ raise ValueError('x, y are incompatible')
508
+ else:
509
+ raise ValueError('ordinates are incompatible')
510
+ it = iter(args)
511
+ x0 = next(it)
512
+
513
+ # use tensor on only the first
514
+ c = val_f(x0, c)
515
+ for xi in it:
516
+ c = val_f(xi, c, tensor=False)
517
+ return c
518
+
519
+
520
+ def _gridnd(val_f, c, *args):
521
+ """
522
+ Helper function used to implement the ``<type>grid<n>d`` functions.
523
+
524
+ Parameters
525
+ ----------
526
+ val_f : function(array_like, array_like, tensor: bool) -> array_like
527
+ The ``<type>val`` function, such as ``polyval``
528
+ c, args
529
+ See the ``<type>grid<n>d`` functions for more detail
530
+ """
531
+ for xi in args:
532
+ c = val_f(xi, c)
533
+ return c
534
+
535
+
536
+ def _div(mul_f, c1, c2):
537
+ """
538
+ Helper function used to implement the ``<type>div`` functions.
539
+
540
+ Implementation uses repeated subtraction of c2 multiplied by the nth basis.
541
+ For some polynomial types, a more efficient approach may be possible.
542
+
543
+ Parameters
544
+ ----------
545
+ mul_f : function(array_like, array_like) -> array_like
546
+ The ``<type>mul`` function, such as ``polymul``
547
+ c1, c2
548
+ See the ``<type>div`` functions for more detail
549
+ """
550
+ # c1, c2 are trimmed copies
551
+ [c1, c2] = as_series([c1, c2])
552
+ if c2[-1] == 0:
553
+ raise ZeroDivisionError()
554
+
555
+ lc1 = len(c1)
556
+ lc2 = len(c2)
557
+ if lc1 < lc2:
558
+ return c1[:1]*0, c1
559
+ elif lc2 == 1:
560
+ return c1/c2[-1], c1[:1]*0
561
+ else:
562
+ quo = np.empty(lc1 - lc2 + 1, dtype=c1.dtype)
563
+ rem = c1
564
+ for i in range(lc1 - lc2, - 1, -1):
565
+ p = mul_f([0]*i + [1], c2)
566
+ q = rem[-1]/p[-1]
567
+ rem = rem[:-1] - q*p[:-1]
568
+ quo[i] = q
569
+ return quo, trimseq(rem)
570
+
571
+
572
+ def _add(c1, c2):
573
+ """ Helper function used to implement the ``<type>add`` functions. """
574
+ # c1, c2 are trimmed copies
575
+ [c1, c2] = as_series([c1, c2])
576
+ if len(c1) > len(c2):
577
+ c1[:c2.size] += c2
578
+ ret = c1
579
+ else:
580
+ c2[:c1.size] += c1
581
+ ret = c2
582
+ return trimseq(ret)
583
+
584
+
585
+ def _sub(c1, c2):
586
+ """ Helper function used to implement the ``<type>sub`` functions. """
587
+ # c1, c2 are trimmed copies
588
+ [c1, c2] = as_series([c1, c2])
589
+ if len(c1) > len(c2):
590
+ c1[:c2.size] -= c2
591
+ ret = c1
592
+ else:
593
+ c2 = -c2
594
+ c2[:c1.size] += c1
595
+ ret = c2
596
+ return trimseq(ret)
597
+
598
+
599
+ def _fit(vander_f, x, y, deg, rcond=None, full=False, w=None):
600
+ """
601
+ Helper function used to implement the ``<type>fit`` functions.
602
+
603
+ Parameters
604
+ ----------
605
+ vander_f : function(array_like, int) -> ndarray
606
+ The 1d vander function, such as ``polyvander``
607
+ c1, c2
608
+ See the ``<type>fit`` functions for more detail
609
+ """
610
+ x = np.asarray(x) + 0.0
611
+ y = np.asarray(y) + 0.0
612
+ deg = np.asarray(deg)
613
+
614
+ # check arguments.
615
+ if deg.ndim > 1 or deg.dtype.kind not in 'iu' or deg.size == 0:
616
+ raise TypeError("deg must be an int or non-empty 1-D array of int")
617
+ if deg.min() < 0:
618
+ raise ValueError("expected deg >= 0")
619
+ if x.ndim != 1:
620
+ raise TypeError("expected 1D vector for x")
621
+ if x.size == 0:
622
+ raise TypeError("expected non-empty vector for x")
623
+ if y.ndim < 1 or y.ndim > 2:
624
+ raise TypeError("expected 1D or 2D array for y")
625
+ if len(x) != len(y):
626
+ raise TypeError("expected x and y to have same length")
627
+
628
+ if deg.ndim == 0:
629
+ lmax = deg
630
+ order = lmax + 1
631
+ van = vander_f(x, lmax)
632
+ else:
633
+ deg = np.sort(deg)
634
+ lmax = deg[-1]
635
+ order = len(deg)
636
+ van = vander_f(x, lmax)[:, deg]
637
+
638
+ # set up the least squares matrices in transposed form
639
+ lhs = van.T
640
+ rhs = y.T
641
+ if w is not None:
642
+ w = np.asarray(w) + 0.0
643
+ if w.ndim != 1:
644
+ raise TypeError("expected 1D vector for w")
645
+ if len(x) != len(w):
646
+ raise TypeError("expected x and w to have same length")
647
+ # apply weights. Don't use inplace operations as they
648
+ # can cause problems with NA.
649
+ lhs = lhs * w
650
+ rhs = rhs * w
651
+
652
+ # set rcond
653
+ if rcond is None:
654
+ rcond = len(x)*np.finfo(x.dtype).eps
655
+
656
+ # Determine the norms of the design matrix columns.
657
+ if issubclass(lhs.dtype.type, np.complexfloating):
658
+ scl = np.sqrt((np.square(lhs.real) + np.square(lhs.imag)).sum(1))
659
+ else:
660
+ scl = np.sqrt(np.square(lhs).sum(1))
661
+ scl[scl == 0] = 1
662
+
663
+ # Solve the least squares problem.
664
+ c, resids, rank, s = np.linalg.lstsq(lhs.T/scl, rhs.T, rcond)
665
+ c = (c.T/scl).T
666
+
667
+ # Expand c to include non-fitted coefficients which are set to zero
668
+ if deg.ndim > 0:
669
+ if c.ndim == 2:
670
+ cc = np.zeros((lmax+1, c.shape[1]), dtype=c.dtype)
671
+ else:
672
+ cc = np.zeros(lmax+1, dtype=c.dtype)
673
+ cc[deg] = c
674
+ c = cc
675
+
676
+ # warn on rank reduction
677
+ if rank != order and not full:
678
+ msg = "The fit may be poorly conditioned"
679
+ warnings.warn(msg, RankWarning, stacklevel=2)
680
+
681
+ if full:
682
+ return c, [resids, rank, s, rcond]
683
+ else:
684
+ return c
685
+
686
+
687
+ def _pow(mul_f, c, pow, maxpower):
688
+ """
689
+ Helper function used to implement the ``<type>pow`` functions.
690
+
691
+ Parameters
692
+ ----------
693
+ mul_f : function(array_like, array_like) -> ndarray
694
+ The ``<type>mul`` function, such as ``polymul``
695
+ c : array_like
696
+ 1-D array of array of series coefficients
697
+ pow, maxpower
698
+ See the ``<type>pow`` functions for more detail
699
+ """
700
+ # c is a trimmed copy
701
+ [c] = as_series([c])
702
+ power = int(pow)
703
+ if power != pow or power < 0:
704
+ raise ValueError("Power must be a non-negative integer.")
705
+ elif maxpower is not None and power > maxpower:
706
+ raise ValueError("Power is too large")
707
+ elif power == 0:
708
+ return np.array([1], dtype=c.dtype)
709
+ elif power == 1:
710
+ return c
711
+ else:
712
+ # This can be made more efficient by using powers of two
713
+ # in the usual way.
714
+ prd = c
715
+ for i in range(2, power + 1):
716
+ prd = mul_f(prd, c)
717
+ return prd
718
+
719
+
720
+ def _deprecate_as_int(x, desc):
721
+ """
722
+ Like `operator.index`, but emits a deprecation warning when passed a float
723
+
724
+ Parameters
725
+ ----------
726
+ x : int-like, or float with integral value
727
+ Value to interpret as an integer
728
+ desc : str
729
+ description to include in any error message
730
+
731
+ Raises
732
+ ------
733
+ TypeError : if x is a non-integral float or non-numeric
734
+ DeprecationWarning : if x is an integral float
735
+ """
736
+ try:
737
+ return operator.index(x)
738
+ except TypeError as e:
739
+ # Numpy 1.17.0, 2019-03-11
740
+ try:
741
+ ix = int(x)
742
+ except TypeError:
743
+ pass
744
+ else:
745
+ if ix == x:
746
+ warnings.warn(
747
+ f"In future, this will raise TypeError, as {desc} will "
748
+ "need to be an integer not just an integral float.",
749
+ DeprecationWarning,
750
+ stacklevel=3
751
+ )
752
+ return ix
753
+
754
+ raise TypeError(f"{desc} must be an integer") from e
755
+
756
+
757
+ def format_float(x, parens=False):
758
+ if not np.issubdtype(type(x), np.floating):
759
+ return str(x)
760
+
761
+ opts = np.get_printoptions()
762
+
763
+ if np.isnan(x):
764
+ return opts['nanstr']
765
+ elif np.isinf(x):
766
+ return opts['infstr']
767
+
768
+ exp_format = False
769
+ if x != 0:
770
+ a = absolute(x)
771
+ if a >= 1.e8 or a < 10**min(0, -(opts['precision']-1)//2):
772
+ exp_format = True
773
+
774
+ trim, unique = '0', True
775
+ if opts['floatmode'] == 'fixed':
776
+ trim, unique = 'k', False
777
+
778
+ if exp_format:
779
+ s = dragon4_scientific(x, precision=opts['precision'],
780
+ unique=unique, trim=trim,
781
+ sign=opts['sign'] == '+')
782
+ if parens:
783
+ s = '(' + s + ')'
784
+ else:
785
+ s = dragon4_positional(x, precision=opts['precision'],
786
+ fractional=True,
787
+ unique=unique, trim=trim,
788
+ sign=opts['sign'] == '+')
789
+ return s
lib/python3.12/site-packages/numpy/polynomial/polyutils.pyi ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __all__: list[str]
2
+
3
+ class RankWarning(UserWarning): ...
4
+
5
+ def trimseq(seq): ...
6
+ def as_series(alist, trim=...): ...
7
+ def trimcoef(c, tol=...): ...
8
+ def getdomain(x): ...
9
+ def mapparms(old, new): ...
10
+ def mapdomain(x, old, new): ...
11
+ def format_float(x, parens=...): ...
lib/python3.12/site-packages/numpy/polynomial/setup.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ def configuration(parent_package='',top_path=None):
2
+ from numpy.distutils.misc_util import Configuration
3
+ config = Configuration('polynomial', parent_package, top_path)
4
+ config.add_subpackage('tests')
5
+ config.add_data_files('*.pyi')
6
+ return config
7
+
8
+ if __name__ == '__main__':
9
+ from numpy.distutils.core import setup
10
+ setup(configuration=configuration)
lib/python3.12/site-packages/numpy/polynomial/tests/__init__.py ADDED
File without changes
lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_classes.cpython-312.pyc ADDED
Binary file (33.4 kB). View file