parent
57b53ca18d
commit
3a40812d5d
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Olli-Pekka Heinisuo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,181 @@
|
||||
'''
|
||||
OpenCV Python binary extension loader
|
||||
'''
|
||||
import os
|
||||
import importlib
|
||||
import sys
|
||||
|
||||
__all__ = []
|
||||
|
||||
try:
|
||||
import numpy
|
||||
import numpy.core.multiarray
|
||||
except ImportError:
|
||||
print('OpenCV bindings requires "numpy" package.')
|
||||
print('Install it via command:')
|
||||
print(' pip install numpy')
|
||||
raise
|
||||
|
||||
# TODO
|
||||
# is_x64 = sys.maxsize > 2**32
|
||||
|
||||
|
||||
def __load_extra_py_code_for_module(base, name, enable_debug_print=False):
|
||||
module_name = "{}.{}".format(__name__, name)
|
||||
export_module_name = "{}.{}".format(base, name)
|
||||
native_module = sys.modules.pop(module_name, None)
|
||||
try:
|
||||
py_module = importlib.import_module(module_name)
|
||||
except ImportError as err:
|
||||
if enable_debug_print:
|
||||
print("Can't load Python code for module:", module_name,
|
||||
". Reason:", err)
|
||||
# Extension doesn't contain extra py code
|
||||
return False
|
||||
|
||||
if not hasattr(base, name):
|
||||
setattr(sys.modules[base], name, py_module)
|
||||
sys.modules[export_module_name] = py_module
|
||||
# If it is C extension module it is already loaded by cv2 package
|
||||
if native_module:
|
||||
setattr(py_module, "_native", native_module)
|
||||
for k, v in filter(lambda kv: not hasattr(py_module, kv[0]),
|
||||
native_module.__dict__.items()):
|
||||
if enable_debug_print: print(' symbol({}): {} = {}'.format(name, k, v))
|
||||
setattr(py_module, k, v)
|
||||
return True
|
||||
|
||||
|
||||
def __collect_extra_submodules(enable_debug_print=False):
|
||||
def modules_filter(module):
|
||||
return all((
|
||||
# module is not internal
|
||||
not module.startswith("_"),
|
||||
not module.startswith("python-"),
|
||||
# it is not a file
|
||||
os.path.isdir(os.path.join(_extra_submodules_init_path, module))
|
||||
))
|
||||
if sys.version_info[0] < 3:
|
||||
if enable_debug_print:
|
||||
print("Extra submodules is loaded only for Python 3")
|
||||
return []
|
||||
|
||||
__INIT_FILE_PATH = os.path.abspath(__file__)
|
||||
_extra_submodules_init_path = os.path.dirname(__INIT_FILE_PATH)
|
||||
return filter(modules_filter, os.listdir(_extra_submodules_init_path))
|
||||
|
||||
|
||||
def bootstrap():
|
||||
import sys
|
||||
|
||||
import copy
|
||||
save_sys_path = copy.copy(sys.path)
|
||||
|
||||
if hasattr(sys, 'OpenCV_LOADER'):
|
||||
print(sys.path)
|
||||
raise ImportError('ERROR: recursion is detected during loading of "cv2" binary extensions. Check OpenCV installation.')
|
||||
sys.OpenCV_LOADER = True
|
||||
|
||||
DEBUG = False
|
||||
if hasattr(sys, 'OpenCV_LOADER_DEBUG'):
|
||||
DEBUG = True
|
||||
|
||||
import platform
|
||||
if DEBUG: print('OpenCV loader: os.name="{}" platform.system()="{}"'.format(os.name, str(platform.system())))
|
||||
|
||||
LOADER_DIR = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
|
||||
|
||||
PYTHON_EXTENSIONS_PATHS = []
|
||||
BINARIES_PATHS = []
|
||||
|
||||
g_vars = globals()
|
||||
l_vars = locals()
|
||||
|
||||
if sys.version_info[:2] < (3, 0):
|
||||
from . load_config_py2 import exec_file_wrapper
|
||||
else:
|
||||
from . load_config_py3 import exec_file_wrapper
|
||||
|
||||
def load_first_config(fnames, required=True):
|
||||
for fname in fnames:
|
||||
fpath = os.path.join(LOADER_DIR, fname)
|
||||
if not os.path.exists(fpath):
|
||||
if DEBUG: print('OpenCV loader: config not found, skip: {}'.format(fpath))
|
||||
continue
|
||||
if DEBUG: print('OpenCV loader: loading config: {}'.format(fpath))
|
||||
exec_file_wrapper(fpath, g_vars, l_vars)
|
||||
return True
|
||||
if required:
|
||||
raise ImportError('OpenCV loader: missing configuration file: {}. Check OpenCV installation.'.format(fnames))
|
||||
|
||||
load_first_config(['config.py'], True)
|
||||
load_first_config([
|
||||
'config-{}.{}.py'.format(sys.version_info[0], sys.version_info[1]),
|
||||
'config-{}.py'.format(sys.version_info[0])
|
||||
], True)
|
||||
|
||||
if DEBUG: print('OpenCV loader: PYTHON_EXTENSIONS_PATHS={}'.format(str(l_vars['PYTHON_EXTENSIONS_PATHS'])))
|
||||
if DEBUG: print('OpenCV loader: BINARIES_PATHS={}'.format(str(l_vars['BINARIES_PATHS'])))
|
||||
|
||||
applySysPathWorkaround = False
|
||||
if hasattr(sys, 'OpenCV_REPLACE_SYS_PATH_0'):
|
||||
applySysPathWorkaround = True
|
||||
else:
|
||||
try:
|
||||
BASE_DIR = os.path.dirname(LOADER_DIR)
|
||||
if sys.path[0] == BASE_DIR or os.path.realpath(sys.path[0]) == BASE_DIR:
|
||||
applySysPathWorkaround = True
|
||||
except:
|
||||
if DEBUG: print('OpenCV loader: exception during checking workaround for sys.path[0]')
|
||||
pass # applySysPathWorkaround is False
|
||||
|
||||
for p in reversed(l_vars['PYTHON_EXTENSIONS_PATHS']):
|
||||
sys.path.insert(1 if not applySysPathWorkaround else 0, p)
|
||||
|
||||
if os.name == 'nt':
|
||||
if sys.version_info[:2] >= (3, 8): # https://github.com/python/cpython/pull/12302
|
||||
for p in l_vars['BINARIES_PATHS']:
|
||||
try:
|
||||
os.add_dll_directory(p)
|
||||
except Exception as e:
|
||||
if DEBUG: print('Failed os.add_dll_directory(): '+ str(e))
|
||||
pass
|
||||
os.environ['PATH'] = ';'.join(l_vars['BINARIES_PATHS']) + ';' + os.environ.get('PATH', '')
|
||||
if DEBUG: print('OpenCV loader: PATH={}'.format(str(os.environ['PATH'])))
|
||||
else:
|
||||
# amending of LD_LIBRARY_PATH works for sub-processes only
|
||||
os.environ['LD_LIBRARY_PATH'] = ':'.join(l_vars['BINARIES_PATHS']) + ':' + os.environ.get('LD_LIBRARY_PATH', '')
|
||||
|
||||
if DEBUG: print("Relink everything from native cv2 module to cv2 package")
|
||||
|
||||
py_module = sys.modules.pop("cv2")
|
||||
|
||||
native_module = importlib.import_module("cv2")
|
||||
|
||||
sys.modules["cv2"] = py_module
|
||||
setattr(py_module, "_native", native_module)
|
||||
|
||||
for item_name, item in filter(lambda kv: kv[0] not in ("__file__", "__loader__", "__spec__",
|
||||
"__name__", "__package__"),
|
||||
native_module.__dict__.items()):
|
||||
if item_name not in g_vars:
|
||||
g_vars[item_name] = item
|
||||
|
||||
sys.path = save_sys_path # multiprocessing should start from bootstrap code (https://github.com/opencv/opencv/issues/18502)
|
||||
|
||||
try:
|
||||
del sys.OpenCV_LOADER
|
||||
except Exception as e:
|
||||
if DEBUG:
|
||||
print("Exception during delete OpenCV_LOADER:", e)
|
||||
|
||||
if DEBUG: print('OpenCV loader: binary extension... OK')
|
||||
|
||||
for submodule in __collect_extra_submodules(DEBUG):
|
||||
if __load_extra_py_code_for_module("cv2", submodule, DEBUG):
|
||||
if DEBUG: print("Extra Python code for", submodule, "is loaded")
|
||||
|
||||
if DEBUG: print('OpenCV loader: DONE')
|
||||
|
||||
|
||||
bootstrap()
|
@ -0,0 +1,24 @@
|
||||
PYTHON_EXTENSIONS_PATHS = [
|
||||
LOADER_DIR
|
||||
] + PYTHON_EXTENSIONS_PATHS
|
||||
|
||||
ci_and_not_headless = False
|
||||
|
||||
try:
|
||||
from .version import ci_build, headless
|
||||
|
||||
ci_and_not_headless = ci_build and not headless
|
||||
except:
|
||||
pass
|
||||
|
||||
# the Qt plugin is included currently only in the pre-built wheels
|
||||
if sys.platform.startswith("linux") and ci_and_not_headless:
|
||||
os.environ["QT_QPA_PLATFORM_PLUGIN_PATH"] = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), "qt", "plugins"
|
||||
)
|
||||
|
||||
# Qt will throw warning on Linux if fonts are not found
|
||||
if sys.platform.startswith("linux") and ci_and_not_headless:
|
||||
os.environ["QT_QPA_FONTDIR"] = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), "qt", "fonts"
|
||||
)
|
@ -0,0 +1,5 @@
|
||||
import os
|
||||
|
||||
BINARIES_PATHS = [
|
||||
os.path.join(os.path.join(LOADER_DIR, '../../'), 'x64/vc14/bin')
|
||||
] + BINARIES_PATHS
|
Binary file not shown.
@ -0,0 +1,3 @@
|
||||
import os
|
||||
|
||||
haarcascades = os.path.join(os.path.dirname(__file__), "")
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,290 @@
|
||||
__all__ = ['op', 'kernel']
|
||||
|
||||
import sys
|
||||
import cv2 as cv
|
||||
|
||||
# NB: Register function in specific module
|
||||
def register(mname):
|
||||
def parameterized(func):
|
||||
sys.modules[mname].__dict__[func.__name__] = func
|
||||
return func
|
||||
return parameterized
|
||||
|
||||
|
||||
@register('cv2.gapi')
|
||||
def networks(*args):
|
||||
return cv.gapi_GNetPackage(list(map(cv.detail.strip, args)))
|
||||
|
||||
|
||||
@register('cv2.gapi')
|
||||
def compile_args(*args):
|
||||
return list(map(cv.GCompileArg, args))
|
||||
|
||||
|
||||
@register('cv2')
|
||||
def GIn(*args):
|
||||
return [*args]
|
||||
|
||||
|
||||
@register('cv2')
|
||||
def GOut(*args):
|
||||
return [*args]
|
||||
|
||||
|
||||
@register('cv2')
|
||||
def gin(*args):
|
||||
return [*args]
|
||||
|
||||
|
||||
@register('cv2.gapi')
|
||||
def descr_of(*args):
|
||||
return [*args]
|
||||
|
||||
|
||||
@register('cv2')
|
||||
class GOpaque():
|
||||
# NB: Inheritance from c++ class cause segfault.
|
||||
# So just aggregate cv.GOpaqueT instead of inheritance
|
||||
def __new__(cls, argtype):
|
||||
return cv.GOpaqueT(argtype)
|
||||
|
||||
class Bool():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_BOOL)
|
||||
|
||||
class Int():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_INT)
|
||||
|
||||
class Double():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_DOUBLE)
|
||||
|
||||
class Float():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_FLOAT)
|
||||
|
||||
class String():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_STRING)
|
||||
|
||||
class Point():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_POINT)
|
||||
|
||||
class Point2f():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_POINT2F)
|
||||
|
||||
class Size():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_SIZE)
|
||||
|
||||
class Rect():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_RECT)
|
||||
|
||||
class Prim():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_DRAW_PRIM)
|
||||
|
||||
class Any():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_ANY)
|
||||
|
||||
@register('cv2')
|
||||
class GArray():
|
||||
# NB: Inheritance from c++ class cause segfault.
|
||||
# So just aggregate cv.GArrayT instead of inheritance
|
||||
def __new__(cls, argtype):
|
||||
return cv.GArrayT(argtype)
|
||||
|
||||
class Bool():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_BOOL)
|
||||
|
||||
class Int():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_INT)
|
||||
|
||||
class Double():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_DOUBLE)
|
||||
|
||||
class Float():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_FLOAT)
|
||||
|
||||
class String():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_STRING)
|
||||
|
||||
class Point():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_POINT)
|
||||
|
||||
class Point2f():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_POINT2F)
|
||||
|
||||
class Size():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_SIZE)
|
||||
|
||||
class Rect():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_RECT)
|
||||
|
||||
class Scalar():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_SCALAR)
|
||||
|
||||
class Mat():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_MAT)
|
||||
|
||||
class GMat():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_GMAT)
|
||||
|
||||
class Prim():
|
||||
def __new__(self):
|
||||
return cv.GArray(cv.gapi.CV_DRAW_PRIM)
|
||||
|
||||
class Any():
|
||||
def __new__(self):
|
||||
return cv.GArray(cv.gapi.CV_ANY)
|
||||
|
||||
|
||||
# NB: Top lvl decorator takes arguments
|
||||
def op(op_id, in_types, out_types):
|
||||
|
||||
garray_types= {
|
||||
cv.GArray.Bool: cv.gapi.CV_BOOL,
|
||||
cv.GArray.Int: cv.gapi.CV_INT,
|
||||
cv.GArray.Double: cv.gapi.CV_DOUBLE,
|
||||
cv.GArray.Float: cv.gapi.CV_FLOAT,
|
||||
cv.GArray.String: cv.gapi.CV_STRING,
|
||||
cv.GArray.Point: cv.gapi.CV_POINT,
|
||||
cv.GArray.Point2f: cv.gapi.CV_POINT2F,
|
||||
cv.GArray.Size: cv.gapi.CV_SIZE,
|
||||
cv.GArray.Rect: cv.gapi.CV_RECT,
|
||||
cv.GArray.Scalar: cv.gapi.CV_SCALAR,
|
||||
cv.GArray.Mat: cv.gapi.CV_MAT,
|
||||
cv.GArray.GMat: cv.gapi.CV_GMAT,
|
||||
cv.GArray.Prim: cv.gapi.CV_DRAW_PRIM,
|
||||
cv.GArray.Any: cv.gapi.CV_ANY
|
||||
}
|
||||
|
||||
gopaque_types= {
|
||||
cv.GOpaque.Size: cv.gapi.CV_SIZE,
|
||||
cv.GOpaque.Rect: cv.gapi.CV_RECT,
|
||||
cv.GOpaque.Bool: cv.gapi.CV_BOOL,
|
||||
cv.GOpaque.Int: cv.gapi.CV_INT,
|
||||
cv.GOpaque.Double: cv.gapi.CV_DOUBLE,
|
||||
cv.GOpaque.Float: cv.gapi.CV_FLOAT,
|
||||
cv.GOpaque.String: cv.gapi.CV_STRING,
|
||||
cv.GOpaque.Point: cv.gapi.CV_POINT,
|
||||
cv.GOpaque.Point2f: cv.gapi.CV_POINT2F,
|
||||
cv.GOpaque.Size: cv.gapi.CV_SIZE,
|
||||
cv.GOpaque.Rect: cv.gapi.CV_RECT,
|
||||
cv.GOpaque.Prim: cv.gapi.CV_DRAW_PRIM,
|
||||
cv.GOpaque.Any: cv.gapi.CV_ANY
|
||||
}
|
||||
|
||||
type2str = {
|
||||
cv.gapi.CV_BOOL: 'cv.gapi.CV_BOOL' ,
|
||||
cv.gapi.CV_INT: 'cv.gapi.CV_INT' ,
|
||||
cv.gapi.CV_DOUBLE: 'cv.gapi.CV_DOUBLE' ,
|
||||
cv.gapi.CV_FLOAT: 'cv.gapi.CV_FLOAT' ,
|
||||
cv.gapi.CV_STRING: 'cv.gapi.CV_STRING' ,
|
||||
cv.gapi.CV_POINT: 'cv.gapi.CV_POINT' ,
|
||||
cv.gapi.CV_POINT2F: 'cv.gapi.CV_POINT2F' ,
|
||||
cv.gapi.CV_SIZE: 'cv.gapi.CV_SIZE',
|
||||
cv.gapi.CV_RECT: 'cv.gapi.CV_RECT',
|
||||
cv.gapi.CV_SCALAR: 'cv.gapi.CV_SCALAR',
|
||||
cv.gapi.CV_MAT: 'cv.gapi.CV_MAT',
|
||||
cv.gapi.CV_GMAT: 'cv.gapi.CV_GMAT',
|
||||
cv.gapi.CV_DRAW_PRIM: 'cv.gapi.CV_DRAW_PRIM'
|
||||
}
|
||||
|
||||
# NB: Second lvl decorator takes class to decorate
|
||||
def op_with_params(cls):
|
||||
if not in_types:
|
||||
raise Exception('{} operation should have at least one input!'.format(cls.__name__))
|
||||
|
||||
if not out_types:
|
||||
raise Exception('{} operation should have at least one output!'.format(cls.__name__))
|
||||
|
||||
for i, t in enumerate(out_types):
|
||||
if t not in [cv.GMat, cv.GScalar, *garray_types, *gopaque_types]:
|
||||
raise Exception('{} unsupported output type: {} in position: {}'
|
||||
.format(cls.__name__, t.__name__, i))
|
||||
|
||||
def on(*args):
|
||||
if len(in_types) != len(args):
|
||||
raise Exception('Invalid number of input elements!\nExpected: {}, Actual: {}'
|
||||
.format(len(in_types), len(args)))
|
||||
|
||||
for i, (t, a) in enumerate(zip(in_types, args)):
|
||||
if t in garray_types:
|
||||
if not isinstance(a, cv.GArrayT):
|
||||
raise Exception("{} invalid type for argument {}.\nExpected: {}, Actual: {}"
|
||||
.format(cls.__name__, i, cv.GArrayT.__name__, type(a).__name__))
|
||||
|
||||
elif a.type() != garray_types[t]:
|
||||
raise Exception("{} invalid GArrayT type for argument {}.\nExpected: {}, Actual: {}"
|
||||
.format(cls.__name__, i, type2str[garray_types[t]], type2str[a.type()]))
|
||||
|
||||
elif t in gopaque_types:
|
||||
if not isinstance(a, cv.GOpaqueT):
|
||||
raise Exception("{} invalid type for argument {}.\nExpected: {}, Actual: {}"
|
||||
.format(cls.__name__, i, cv.GOpaqueT.__name__, type(a).__name__))
|
||||
|
||||
elif a.type() != gopaque_types[t]:
|
||||
raise Exception("{} invalid GOpaque type for argument {}.\nExpected: {}, Actual: {}"
|
||||
.format(cls.__name__, i, type2str[gopaque_types[t]], type2str[a.type()]))
|
||||
|
||||
else:
|
||||
if t != type(a):
|
||||
raise Exception('{} invalid input type for argument {}.\nExpected: {}, Actual: {}'
|
||||
.format(cls.__name__, i, t.__name__, type(a).__name__))
|
||||
|
||||
op = cv.gapi.__op(op_id, cls.outMeta, *args)
|
||||
|
||||
out_protos = []
|
||||
for i, out_type in enumerate(out_types):
|
||||
if out_type == cv.GMat:
|
||||
out_protos.append(op.getGMat())
|
||||
elif out_type == cv.GScalar:
|
||||
out_protos.append(op.getGScalar())
|
||||
elif out_type in gopaque_types:
|
||||
out_protos.append(op.getGOpaque(gopaque_types[out_type]))
|
||||
elif out_type in garray_types:
|
||||
out_protos.append(op.getGArray(garray_types[out_type]))
|
||||
else:
|
||||
raise Exception("""In {}: G-API operation can't produce the output with type: {} in position: {}"""
|
||||
.format(cls.__name__, out_type.__name__, i))
|
||||
|
||||
return tuple(out_protos) if len(out_protos) != 1 else out_protos[0]
|
||||
|
||||
# NB: Extend operation class
|
||||
cls.id = op_id
|
||||
cls.on = staticmethod(on)
|
||||
return cls
|
||||
|
||||
return op_with_params
|
||||
|
||||
|
||||
def kernel(op_cls):
|
||||
# NB: Second lvl decorator takes class to decorate
|
||||
def kernel_with_params(cls):
|
||||
# NB: Add new members to kernel class
|
||||
cls.id = op_cls.id
|
||||
cls.outMeta = op_cls.outMeta
|
||||
return cls
|
||||
|
||||
return kernel_with_params
|
||||
|
||||
|
||||
cv.gapi.wip.GStreamerPipeline = cv.gapi_wip_gst_GStreamerPipeline
|
@ -0,0 +1,6 @@
|
||||
# flake8: noqa
|
||||
import sys
|
||||
|
||||
if sys.version_info[:2] < (3, 0):
|
||||
def exec_file_wrapper(fpath, g_vars, l_vars):
|
||||
execfile(fpath, g_vars, l_vars)
|
@ -0,0 +1,9 @@
|
||||
# flake8: noqa
|
||||
import os
|
||||
import sys
|
||||
|
||||
if sys.version_info[:2] >= (3, 0):
|
||||
def exec_file_wrapper(fpath, g_vars, l_vars):
|
||||
with open(fpath) as f:
|
||||
code = compile(f.read(), os.path.basename(fpath), 'exec')
|
||||
exec(code, g_vars, l_vars)
|
@ -0,0 +1,33 @@
|
||||
__all__ = []
|
||||
|
||||
import sys
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
# NumPy documentation: https://numpy.org/doc/stable/user/basics.subclassing.html
|
||||
|
||||
class Mat(np.ndarray):
|
||||
'''
|
||||
cv.Mat wrapper for numpy array.
|
||||
|
||||
Stores extra metadata information how to interpret and process of numpy array for underlying C++ code.
|
||||
'''
|
||||
|
||||
def __new__(cls, arr, **kwargs):
|
||||
obj = arr.view(Mat)
|
||||
return obj
|
||||
|
||||
def __init__(self, arr, **kwargs):
|
||||
self.wrap_channels = kwargs.pop('wrap_channels', getattr(arr, 'wrap_channels', False))
|
||||
if len(kwargs) > 0:
|
||||
raise TypeError('Unknown parameters: {}'.format(repr(kwargs)))
|
||||
|
||||
def __array_finalize__(self, obj):
|
||||
if obj is None:
|
||||
return
|
||||
self.wrap_channels = getattr(obj, 'wrap_channels', None)
|
||||
|
||||
|
||||
Mat.__module__ = cv.__name__
|
||||
cv.Mat = Mat
|
||||
cv._registerMatType(Mat)
|
@ -0,0 +1 @@
|
||||
from .version import get_ocv_version
|
@ -0,0 +1,5 @@
|
||||
import cv2
|
||||
|
||||
|
||||
def get_ocv_version():
|
||||
return getattr(cv2, "__version__", "unavailable")
|
Binary file not shown.
@ -0,0 +1,14 @@
|
||||
from collections import namedtuple
|
||||
|
||||
import cv2
|
||||
|
||||
|
||||
NativeMethodPatchedResult = namedtuple("NativeMethodPatchedResult",
|
||||
("py", "native"))
|
||||
|
||||
|
||||
def testOverwriteNativeMethod(arg):
|
||||
return NativeMethodPatchedResult(
|
||||
arg + 1,
|
||||
cv2.utils._native.testOverwriteNativeMethod(arg)
|
||||
)
|
@ -0,0 +1,4 @@
|
||||
opencv_version = "4.6.0.66"
|
||||
contrib = False
|
||||
headless = False
|
||||
ci_build = True
|
@ -0,0 +1 @@
|
||||
pip
|
@ -0,0 +1,22 @@
|
||||
The NumPy repository and source distributions bundle several libraries that are
|
||||
compatibly licensed. We list these here.
|
||||
|
||||
Name: lapack-lite
|
||||
Files: numpy/linalg/lapack_lite/*
|
||||
License: BSD-3-Clause
|
||||
For details, see numpy/linalg/lapack_lite/LICENSE.txt
|
||||
|
||||
Name: tempita
|
||||
Files: tools/npy_tempita/*
|
||||
License: MIT
|
||||
For details, see tools/npy_tempita/license.txt
|
||||
|
||||
Name: dragon4
|
||||
Files: numpy/core/src/multiarray/dragon4.c
|
||||
License: MIT
|
||||
For license text, see numpy/core/src/multiarray/dragon4.c
|
||||
|
||||
Name: libdivide
|
||||
Files: numpy/core/include/numpy/libdivide/*
|
||||
License: Zlib
|
||||
For license text, see numpy/core/include/numpy/libdivide/LICENSE.txt
|
@ -0,0 +1,59 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: numpy
|
||||
Version: 1.21.6
|
||||
Summary: NumPy is the fundamental package for array computing with Python.
|
||||
Home-page: https://www.numpy.org
|
||||
Author: Travis E. Oliphant et al.
|
||||
Maintainer: NumPy Developers
|
||||
Maintainer-email: numpy-discussion@python.org
|
||||
License: BSD
|
||||
Download-URL: https://pypi.python.org/pypi/numpy
|
||||
Project-URL: Bug Tracker, https://github.com/numpy/numpy/issues
|
||||
Project-URL: Documentation, https://numpy.org/doc/1.21
|
||||
Project-URL: Source Code, https://github.com/numpy/numpy
|
||||
Platform: Windows
|
||||
Platform: Linux
|
||||
Platform: Solaris
|
||||
Platform: Mac OS-X
|
||||
Platform: Unix
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Science/Research
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Programming Language :: C
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3 :: Only
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Topic :: Software Development
|
||||
Classifier: Topic :: Scientific/Engineering
|
||||
Classifier: Typing :: Typed
|
||||
Classifier: Operating System :: Microsoft :: Windows
|
||||
Classifier: Operating System :: POSIX
|
||||
Classifier: Operating System :: Unix
|
||||
Classifier: Operating System :: MacOS
|
||||
Requires-Python: >=3.7,<3.11
|
||||
License-File: LICENSE.txt
|
||||
License-File: LICENSES_bundled.txt
|
||||
|
||||
It provides:
|
||||
|
||||
- a powerful N-dimensional array object
|
||||
- sophisticated (broadcasting) functions
|
||||
- tools for integrating C/C++ and Fortran code
|
||||
- useful linear algebra, Fourier transform, and random number capabilities
|
||||
- and much more
|
||||
|
||||
Besides its obvious scientific uses, NumPy can also be used as an efficient
|
||||
multi-dimensional container of generic data. Arbitrary data-types can be
|
||||
defined. This allows NumPy to seamlessly and speedily integrate with a wide
|
||||
variety of databases.
|
||||
|
||||
All NumPy wheels distributed on PyPI are BSD licensed.
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.37.0)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp37-cp37m-win_amd64
|
||||
|
@ -0,0 +1,3 @@
|
||||
[console_scripts]
|
||||
f2py = numpy.f2py.f2py2e:main
|
||||
|
@ -0,0 +1 @@
|
||||
numpy
|
Binary file not shown.
@ -0,0 +1,98 @@
|
||||
# This file is generated by numpy's setup.py
|
||||
# It contains system_info results at the time of building this package.
|
||||
__all__ = ["get_info","show"]
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
extra_dll_dir = os.path.join(os.path.dirname(__file__), '.libs')
|
||||
|
||||
if sys.platform == 'win32' and os.path.isdir(extra_dll_dir):
|
||||
if sys.version_info >= (3, 8):
|
||||
os.add_dll_directory(extra_dll_dir)
|
||||
else:
|
||||
os.environ.setdefault('PATH', '')
|
||||
os.environ['PATH'] += os.pathsep + extra_dll_dir
|
||||
|
||||
blas_mkl_info={}
|
||||
blis_info={}
|
||||
openblas_info={'library_dirs': ['D:\\a\\1\\s\\numpy\\build\\openblas_info'], 'libraries': ['openblas_info'], 'language': 'f77', 'define_macros': [('HAVE_CBLAS', None)]}
|
||||
blas_opt_info={'library_dirs': ['D:\\a\\1\\s\\numpy\\build\\openblas_info'], 'libraries': ['openblas_info'], 'language': 'f77', 'define_macros': [('HAVE_CBLAS', None)]}
|
||||
lapack_mkl_info={}
|
||||
openblas_lapack_info={'library_dirs': ['D:\\a\\1\\s\\numpy\\build\\openblas_lapack_info'], 'libraries': ['openblas_lapack_info'], 'language': 'f77', 'define_macros': [('HAVE_CBLAS', None)]}
|
||||
lapack_opt_info={'library_dirs': ['D:\\a\\1\\s\\numpy\\build\\openblas_lapack_info'], 'libraries': ['openblas_lapack_info'], 'language': 'f77', 'define_macros': [('HAVE_CBLAS', None)]}
|
||||
|
||||
def get_info(name):
|
||||
g = globals()
|
||||
return g.get(name, g.get(name + "_info", {}))
|
||||
|
||||
def show():
|
||||
"""
|
||||
Show libraries in the system on which NumPy was built.
|
||||
|
||||
Print information about various resources (libraries, library
|
||||
directories, include directories, etc.) in the system on which
|
||||
NumPy was built.
|
||||
|
||||
See Also
|
||||
--------
|
||||
get_include : Returns the directory containing NumPy C
|
||||
header files.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Classes specifying the information to be printed are defined
|
||||
in the `numpy.distutils.system_info` module.
|
||||
|
||||
Information may include:
|
||||
|
||||
* ``language``: language used to write the libraries (mostly
|
||||
C or f77)
|
||||
* ``libraries``: names of libraries found in the system
|
||||
* ``library_dirs``: directories containing the libraries
|
||||
* ``include_dirs``: directories containing library header files
|
||||
* ``src_dirs``: directories containing library source files
|
||||
* ``define_macros``: preprocessor macros used by
|
||||
``distutils.setup``
|
||||
* ``baseline``: minimum CPU features required
|
||||
* ``found``: dispatched features supported in the system
|
||||
* ``not found``: dispatched features that are not supported
|
||||
in the system
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> import numpy as np
|
||||
>>> np.show_config()
|
||||
blas_opt_info:
|
||||
language = c
|
||||
define_macros = [('HAVE_CBLAS', None)]
|
||||
libraries = ['openblas', 'openblas']
|
||||
library_dirs = ['/usr/local/lib']
|
||||
"""
|
||||
from numpy.core._multiarray_umath import (
|
||||
__cpu_features__, __cpu_baseline__, __cpu_dispatch__
|
||||
)
|
||||
for name,info_dict in globals().items():
|
||||
if name[0] == "_" or type(info_dict) is not type({}): continue
|
||||
print(name + ":")
|
||||
if not info_dict:
|
||||
print(" NOT AVAILABLE")
|
||||
for k,v in info_dict.items():
|
||||
v = str(v)
|
||||
if k == "sources" and len(v) > 200:
|
||||
v = v[:60] + " ...\n... " + v[-60:]
|
||||
print(" %s = %s" % (k,v))
|
||||
|
||||
features_found, features_not_found = [], []
|
||||
for feature in __cpu_dispatch__:
|
||||
if __cpu_features__[feature]:
|
||||
features_found.append(feature)
|
||||
else:
|
||||
features_not_found.append(feature)
|
||||
|
||||
print("Supported SIMD extensions in this NumPy install:")
|
||||
print(" baseline = %s" % (','.join(__cpu_baseline__)))
|
||||
print(" found = %s" % (','.join(features_found)))
|
||||
print(" not found = %s" % (','.join(features_not_found)))
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,429 @@
|
||||
"""
|
||||
NumPy
|
||||
=====
|
||||
|
||||
Provides
|
||||
1. An array object of arbitrary homogeneous items
|
||||
2. Fast mathematical operations over arrays
|
||||
3. Linear Algebra, Fourier Transforms, Random Number Generation
|
||||
|
||||
How to use the documentation
|
||||
----------------------------
|
||||
Documentation is available in two forms: docstrings provided
|
||||
with the code, and a loose standing reference guide, available from
|
||||
`the NumPy homepage <https://www.scipy.org>`_.
|
||||
|
||||
We recommend exploring the docstrings using
|
||||
`IPython <https://ipython.org>`_, an advanced Python shell with
|
||||
TAB-completion and introspection capabilities. See below for further
|
||||
instructions.
|
||||
|
||||
The docstring examples assume that `numpy` has been imported as `np`::
|
||||
|
||||
>>> import numpy as np
|
||||
|
||||
Code snippets are indicated by three greater-than signs::
|
||||
|
||||
>>> x = 42
|
||||
>>> x = x + 1
|
||||
|
||||
Use the built-in ``help`` function to view a function's docstring::
|
||||
|
||||
>>> help(np.sort)
|
||||
... # doctest: +SKIP
|
||||
|
||||
For some objects, ``np.info(obj)`` may provide additional help. This is
|
||||
particularly true if you see the line "Help on ufunc object:" at the top
|
||||
of the help() page. Ufuncs are implemented in C, not Python, for speed.
|
||||
The native Python help() does not know how to view their help, but our
|
||||
np.info() function does.
|
||||
|
||||
To search for documents containing a keyword, do::
|
||||
|
||||
>>> np.lookfor('keyword')
|
||||
... # doctest: +SKIP
|
||||
|
||||
General-purpose documents like a glossary and help on the basic concepts
|
||||
of numpy are available under the ``doc`` sub-module::
|
||||
|
||||
>>> from numpy import doc
|
||||
>>> help(doc)
|
||||
... # doctest: +SKIP
|
||||
|
||||
Available subpackages
|
||||
---------------------
|
||||
doc
|
||||
Topical documentation on broadcasting, indexing, etc.
|
||||
lib
|
||||
Basic functions used by several sub-packages.
|
||||
random
|
||||
Core Random Tools
|
||||
linalg
|
||||
Core Linear Algebra Tools
|
||||
fft
|
||||
Core FFT routines
|
||||
polynomial
|
||||
Polynomial tools
|
||||
testing
|
||||
NumPy testing tools
|
||||
f2py
|
||||
Fortran to Python Interface Generator.
|
||||
distutils
|
||||
Enhancements to distutils with support for
|
||||
Fortran compilers support and more.
|
||||
|
||||
Utilities
|
||||
---------
|
||||
test
|
||||
Run numpy unittests
|
||||
show_config
|
||||
Show numpy build configuration
|
||||
dual
|
||||
Overwrite certain functions with high-performance SciPy tools.
|
||||
Note: `numpy.dual` is deprecated. Use the functions from NumPy or Scipy
|
||||
directly instead of importing them from `numpy.dual`.
|
||||
matlib
|
||||
Make everything matrices.
|
||||
__version__
|
||||
NumPy version string
|
||||
|
||||
Viewing documentation using IPython
|
||||
-----------------------------------
|
||||
Start IPython with the NumPy profile (``ipython -p numpy``), which will
|
||||
import `numpy` under the alias `np`. Then, use the ``cpaste`` command to
|
||||
paste examples into the shell. To see which functions are available in
|
||||
`numpy`, type ``np.<TAB>`` (where ``<TAB>`` refers to the TAB key), or use
|
||||
``np.*cos*?<ENTER>`` (where ``<ENTER>`` refers to the ENTER key) to narrow
|
||||
down the list. To view the docstring for a function, use
|
||||
``np.cos?<ENTER>`` (to view the docstring) and ``np.cos??<ENTER>`` (to view
|
||||
the source code).
|
||||
|
||||
Copies vs. in-place operation
|
||||
-----------------------------
|
||||
Most of the functions in `numpy` return a copy of the array argument
|
||||
(e.g., `np.sort`). In-place versions of these functions are often
|
||||
available as array methods, i.e. ``x = np.array([1,2,3]); x.sort()``.
|
||||
Exceptions to this rule are documented.
|
||||
|
||||
"""
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
from ._globals import (
|
||||
ModuleDeprecationWarning, VisibleDeprecationWarning, _NoValue
|
||||
)
|
||||
|
||||
# We first need to detect if we're being called as part of the numpy setup
|
||||
# procedure itself in a reliable manner.
|
||||
try:
|
||||
__NUMPY_SETUP__
|
||||
except NameError:
|
||||
__NUMPY_SETUP__ = False
|
||||
|
||||
if __NUMPY_SETUP__:
|
||||
sys.stderr.write('Running from numpy source directory.\n')
|
||||
else:
|
||||
try:
|
||||
from numpy.__config__ import show as show_config
|
||||
except ImportError as e:
|
||||
msg = """Error importing numpy: you should not try to import numpy from
|
||||
its source directory; please exit the numpy source tree, and relaunch
|
||||
your python interpreter from there."""
|
||||
raise ImportError(msg) from e
|
||||
|
||||
__all__ = ['ModuleDeprecationWarning',
|
||||
'VisibleDeprecationWarning']
|
||||
|
||||
# get the version using versioneer
|
||||
from ._version import get_versions
|
||||
vinfo = get_versions()
|
||||
__version__ = vinfo.get("closest-tag", vinfo["version"])
|
||||
__git_version__ = vinfo.get("full-revisionid")
|
||||
del get_versions, vinfo
|
||||
|
||||
# mapping of {name: (value, deprecation_msg)}
|
||||
__deprecated_attrs__ = {}
|
||||
|
||||
# Allow distributors to run custom init code
|
||||
from . import _distributor_init
|
||||
|
||||
from . import core
|
||||
from .core import *
|
||||
from . import compat
|
||||
from . import lib
|
||||
# NOTE: to be revisited following future namespace cleanup.
|
||||
# See gh-14454 and gh-15672 for discussion.
|
||||
from .lib import *
|
||||
|
||||
from . import linalg
|
||||
from . import fft
|
||||
from . import polynomial
|
||||
from . import random
|
||||
from . import ctypeslib
|
||||
from . import ma
|
||||
from . import matrixlib as _mat
|
||||
from .matrixlib import *
|
||||
|
||||
# Deprecations introduced in NumPy 1.20.0, 2020-06-06
|
||||
import builtins as _builtins
|
||||
|
||||
_msg = (
|
||||
"`np.{n}` is a deprecated alias for the builtin `{n}`. "
|
||||
"To silence this warning, use `{n}` by itself. Doing this will not "
|
||||
"modify any behavior and is safe. {extended_msg}\n"
|
||||
"Deprecated in NumPy 1.20; for more details and guidance: "
|
||||
"https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations")
|
||||
|
||||
_specific_msg = (
|
||||
"If you specifically wanted the numpy scalar type, use `np.{}` here.")
|
||||
|
||||
_int_extended_msg = (
|
||||
"When replacing `np.{}`, you may wish to use e.g. `np.int64` "
|
||||
"or `np.int32` to specify the precision. If you wish to review "
|
||||
"your current use, check the release note link for "
|
||||
"additional information.")
|
||||
|
||||
_type_info = [
|
||||
("object", ""), # The NumPy scalar only exists by name.
|
||||
("bool", _specific_msg.format("bool_")),
|
||||
("float", _specific_msg.format("float64")),
|
||||
("complex", _specific_msg.format("complex128")),
|
||||
("str", _specific_msg.format("str_")),
|
||||
("int", _int_extended_msg.format("int"))]
|
||||
|
||||
__deprecated_attrs__.update({
|
||||
n: (getattr(_builtins, n), _msg.format(n=n, extended_msg=extended_msg))
|
||||
for n, extended_msg in _type_info
|
||||
})
|
||||
# Numpy 1.20.0, 2020-10-19
|
||||
__deprecated_attrs__["typeDict"] = (
|
||||
core.numerictypes.typeDict,
|
||||
"`np.typeDict` is a deprecated alias for `np.sctypeDict`."
|
||||
)
|
||||
|
||||
_msg = (
|
||||
"`np.{n}` is a deprecated alias for `np.compat.{n}`. "
|
||||
"To silence this warning, use `np.compat.{n}` by itself. "
|
||||
"In the likely event your code does not need to work on Python 2 "
|
||||
"you can use the builtin `{n2}` for which `np.compat.{n}` is itself "
|
||||
"an alias. Doing this will not modify any behaviour and is safe. "
|
||||
"{extended_msg}\n"
|
||||
"Deprecated in NumPy 1.20; for more details and guidance: "
|
||||
"https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations")
|
||||
|
||||
__deprecated_attrs__["long"] = (
|
||||
getattr(compat, "long"),
|
||||
_msg.format(n="long", n2="int",
|
||||
extended_msg=_int_extended_msg.format("long")))
|
||||
|
||||
__deprecated_attrs__["unicode"] = (
|
||||
getattr(compat, "unicode"),
|
||||
_msg.format(n="unicode", n2="str",
|
||||
extended_msg=_specific_msg.format("str_")))
|
||||
|
||||
del _msg, _specific_msg, _int_extended_msg, _type_info, _builtins
|
||||
|
||||
from .core import round, abs, max, min
|
||||
# now that numpy modules are imported, can initialize limits
|
||||
core.getlimits._register_known_types()
|
||||
|
||||
__all__.extend(['__version__', 'show_config'])
|
||||
__all__.extend(core.__all__)
|
||||
__all__.extend(_mat.__all__)
|
||||
__all__.extend(lib.__all__)
|
||||
__all__.extend(['linalg', 'fft', 'random', 'ctypeslib', 'ma'])
|
||||
|
||||
# These are exported by np.core, but are replaced by the builtins below
|
||||
# remove them to ensure that we don't end up with `np.long == np.int_`,
|
||||
# which would be a breaking change.
|
||||
del long, unicode
|
||||
__all__.remove('long')
|
||||
__all__.remove('unicode')
|
||||
|
||||
# Remove things that are in the numpy.lib but not in the numpy namespace
|
||||
# Note that there is a test (numpy/tests/test_public_api.py:test_numpy_namespace)
|
||||
# that prevents adding more things to the main namespace by accident.
|
||||
# The list below will grow until the `from .lib import *` fixme above is
|
||||
# taken care of
|
||||
__all__.remove('Arrayterator')
|
||||
del Arrayterator
|
||||
|
||||
# These names were removed in NumPy 1.20. For at least one release,
|
||||
# attempts to access these names in the numpy namespace will trigger
|
||||
# a warning, and calling the function will raise an exception.
|
||||
_financial_names = ['fv', 'ipmt', 'irr', 'mirr', 'nper', 'npv', 'pmt',
|
||||
'ppmt', 'pv', 'rate']
|
||||
__expired_functions__ = {
|
||||
name: (f'In accordance with NEP 32, the function {name} was removed '
|
||||
'from NumPy version 1.20. A replacement for this function '
|
||||
'is available in the numpy_financial library: '
|
||||
'https://pypi.org/project/numpy-financial')
|
||||
for name in _financial_names}
|
||||
|
||||
# Filter out Cython harmless warnings
|
||||
warnings.filterwarnings("ignore", message="numpy.dtype size changed")
|
||||
warnings.filterwarnings("ignore", message="numpy.ufunc size changed")
|
||||
warnings.filterwarnings("ignore", message="numpy.ndarray size changed")
|
||||
|
||||
# oldnumeric and numarray were removed in 1.9. In case some packages import
|
||||
# but do not use them, we define them here for backward compatibility.
|
||||
oldnumeric = 'removed'
|
||||
numarray = 'removed'
|
||||
|
||||
if sys.version_info[:2] >= (3, 7):
|
||||
# module level getattr is only supported in 3.7 onwards
|
||||
# https://www.python.org/dev/peps/pep-0562/
|
||||
def __getattr__(attr):
|
||||
# Warn for expired attributes, and return a dummy function
|
||||
# that always raises an exception.
|
||||
try:
|
||||
msg = __expired_functions__[attr]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
warnings.warn(msg, DeprecationWarning, stacklevel=2)
|
||||
|
||||
def _expired(*args, **kwds):
|
||||
raise RuntimeError(msg)
|
||||
|
||||
return _expired
|
||||
|
||||
# Emit warnings for deprecated attributes
|
||||
try:
|
||||
val, msg = __deprecated_attrs__[attr]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
warnings.warn(msg, DeprecationWarning, stacklevel=2)
|
||||
return val
|
||||
|
||||
# Importing Tester requires importing all of UnitTest which is not a
|
||||
# cheap import Since it is mainly used in test suits, we lazy import it
|
||||
# here to save on the order of 10 ms of import time for most users
|
||||
#
|
||||
# The previous way Tester was imported also had a side effect of adding
|
||||
# the full `numpy.testing` namespace
|
||||
if attr == 'testing':
|
||||
import numpy.testing as testing
|
||||
return testing
|
||||
elif attr == 'Tester':
|
||||
from .testing import Tester
|
||||
return Tester
|
||||
|
||||
raise AttributeError("module {!r} has no attribute "
|
||||
"{!r}".format(__name__, attr))
|
||||
|
||||
def __dir__():
|
||||
return list(globals().keys() | {'Tester', 'testing'})
|
||||
|
||||
else:
|
||||
# We don't actually use this ourselves anymore, but I'm not 100% sure that
|
||||
# no-one else in the world is using it (though I hope not)
|
||||
from .testing import Tester
|
||||
|
||||
# We weren't able to emit a warning about these, so keep them around
|
||||
globals().update({
|
||||
k: v
|
||||
for k, (v, msg) in __deprecated_attrs__.items()
|
||||
})
|
||||
|
||||
|
||||
# Pytest testing
|
||||
from numpy._pytesttester import PytestTester
|
||||
test = PytestTester(__name__)
|
||||
del PytestTester
|
||||
|
||||
|
||||
def _sanity_check():
|
||||
"""
|
||||
Quick sanity checks for common bugs caused by environment.
|
||||
There are some cases e.g. with wrong BLAS ABI that cause wrong
|
||||
results under specific runtime conditions that are not necessarily
|
||||
achieved during test suite runs, and it is useful to catch those early.
|
||||
|
||||
See https://github.com/numpy/numpy/issues/8577 and other
|
||||
similar bug reports.
|
||||
|
||||
"""
|
||||
try:
|
||||
x = ones(2, dtype=float32)
|
||||
if not abs(x.dot(x) - 2.0) < 1e-5:
|
||||
raise AssertionError()
|
||||
except AssertionError:
|
||||
msg = ("The current Numpy installation ({!r}) fails to "
|
||||
"pass simple sanity checks. This can be caused for example "
|
||||
"by incorrect BLAS library being linked in, or by mixing "
|
||||
"package managers (pip, conda, apt, ...). Search closed "
|
||||
"numpy issues for similar problems.")
|
||||
raise RuntimeError(msg.format(__file__)) from None
|
||||
|
||||
_sanity_check()
|
||||
del _sanity_check
|
||||
|
||||
def _mac_os_check():
|
||||
"""
|
||||
Quick Sanity check for Mac OS look for accelerate build bugs.
|
||||
Testing numpy polyfit calls init_dgelsd(LAPACK)
|
||||
"""
|
||||
try:
|
||||
c = array([3., 2., 1.])
|
||||
x = linspace(0, 2, 5)
|
||||
y = polyval(c, x)
|
||||
_ = polyfit(x, y, 2, cov=True)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
import sys
|
||||
if sys.platform == "darwin":
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
_mac_os_check()
|
||||
# Throw runtime error, if the test failed Check for warning and error_message
|
||||
error_message = ""
|
||||
if len(w) > 0:
|
||||
error_message = "{}: {}".format(w[-1].category.__name__, str(w[-1].message))
|
||||
msg = (
|
||||
"Polyfit sanity test emitted a warning, most likely due "
|
||||
"to using a buggy Accelerate backend. If you compiled "
|
||||
"yourself, more information is available at "
|
||||
"https://numpy.org/doc/stable/user/building.html#accelerated-blas-lapack-libraries "
|
||||
"Otherwise report this to the vendor "
|
||||
"that provided NumPy.\n{}\n".format(error_message))
|
||||
raise RuntimeError(msg)
|
||||
del _mac_os_check
|
||||
|
||||
# We usually use madvise hugepages support, but on some old kernels it
|
||||
# is slow and thus better avoided.
|
||||
# Specifically kernel version 4.6 had a bug fix which probably fixed this:
|
||||
# https://github.com/torvalds/linux/commit/7cf91a98e607c2f935dbcc177d70011e95b8faff
|
||||
import os
|
||||
use_hugepage = os.environ.get("NUMPY_MADVISE_HUGEPAGE", None)
|
||||
if sys.platform == "linux" and use_hugepage is None:
|
||||
# If there is an issue with parsing the kernel version,
|
||||
# set use_hugepages to 0. Usage of LooseVersion will handle
|
||||
# the kernel version parsing better, but avoided since it
|
||||
# will increase the import time. See: #16679 for related discussion.
|
||||
try:
|
||||
use_hugepage = 1
|
||||
kernel_version = os.uname().release.split(".")[:2]
|
||||
kernel_version = tuple(int(v) for v in kernel_version)
|
||||
if kernel_version < (4, 6):
|
||||
use_hugepage = 0
|
||||
except ValueError:
|
||||
use_hugepages = 0
|
||||
elif use_hugepage is None:
|
||||
# This is not Linux, so it should not matter, just enable anyway
|
||||
use_hugepage = 1
|
||||
else:
|
||||
use_hugepage = int(use_hugepage)
|
||||
|
||||
# Note that this will currently only make a difference on Linux
|
||||
core.multiarray._set_madvise_hugepage(use_hugepage)
|
||||
|
||||
# Give a warning if NumPy is reloaded or imported on a sub-interpreter
|
||||
# We do this from python, since the C-module may not be reloaded and
|
||||
# it is tidier organized.
|
||||
core.multiarray._multiarray_umath._reload_guard()
|
||||
|
||||
from ._version import get_versions
|
||||
__version__ = get_versions()['version']
|
||||
del get_versions
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,32 @@
|
||||
|
||||
'''
|
||||
Helper to preload windows dlls to prevent dll not found errors.
|
||||
Once a DLL is preloaded, its namespace is made available to any
|
||||
subsequent DLL. This file originated in the numpy-wheels repo,
|
||||
and is created as part of the scripts that build the wheel.
|
||||
'''
|
||||
import os
|
||||
import glob
|
||||
if os.name == 'nt':
|
||||
# convention for storing / loading the DLL from
|
||||
# numpy/.libs/, if present
|
||||
try:
|
||||
from ctypes import WinDLL
|
||||
basedir = os.path.dirname(__file__)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
libs_dir = os.path.abspath(os.path.join(basedir, '.libs'))
|
||||
DLL_filenames = []
|
||||
if os.path.isdir(libs_dir):
|
||||
for filename in glob.glob(os.path.join(libs_dir,
|
||||
'*openblas*dll')):
|
||||
# NOTE: would it change behavior to load ALL
|
||||
# DLLs at this path vs. the name restriction?
|
||||
WinDLL(os.path.abspath(filename))
|
||||
DLL_filenames.append(filename)
|
||||
if len(DLL_filenames) > 1:
|
||||
import warnings
|
||||
warnings.warn("loaded more than 1 DLL from .libs:"
|
||||
"\n%s" % "\n".join(DLL_filenames),
|
||||
stacklevel=1)
|
@ -0,0 +1,91 @@
|
||||
"""
|
||||
Module defining global singleton classes.
|
||||
|
||||
This module raises a RuntimeError if an attempt to reload it is made. In that
|
||||
way the identities of the classes defined here are fixed and will remain so
|
||||
even if numpy itself is reloaded. In particular, a function like the following
|
||||
will still work correctly after numpy is reloaded::
|
||||
|
||||
def foo(arg=np._NoValue):
|
||||
if arg is np._NoValue:
|
||||
...
|
||||
|
||||
That was not the case when the singleton classes were defined in the numpy
|
||||
``__init__.py`` file. See gh-7844 for a discussion of the reload problem that
|
||||
motivated this module.
|
||||
|
||||
"""
|
||||
__ALL__ = [
|
||||
'ModuleDeprecationWarning', 'VisibleDeprecationWarning', '_NoValue'
|
||||
]
|
||||
|
||||
|
||||
# Disallow reloading this module so as to preserve the identities of the
|
||||
# classes defined here.
|
||||
if '_is_loaded' in globals():
|
||||
raise RuntimeError('Reloading numpy._globals is not allowed')
|
||||
_is_loaded = True
|
||||
|
||||
|
||||
class ModuleDeprecationWarning(DeprecationWarning):
|
||||
"""Module deprecation warning.
|
||||
|
||||
The nose tester turns ordinary Deprecation warnings into test failures.
|
||||
That makes it hard to deprecate whole modules, because they get
|
||||
imported by default. So this is a special Deprecation warning that the
|
||||
nose tester will let pass without making tests fail.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
ModuleDeprecationWarning.__module__ = 'numpy'
|
||||
|
||||
|
||||
class VisibleDeprecationWarning(UserWarning):
|
||||
"""Visible deprecation warning.
|
||||
|
||||
By default, python will not show deprecation warnings, so this class
|
||||
can be used when a very visible warning is helpful, for example because
|
||||
the usage is most likely a user bug.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
VisibleDeprecationWarning.__module__ = 'numpy'
|
||||
|
||||
|
||||
class _NoValueType:
|
||||
"""Special keyword value.
|
||||
|
||||
The instance of this class may be used as the default value assigned to a
|
||||
keyword if no other obvious default (e.g., `None`) is suitable,
|
||||
|
||||
Common reasons for using this keyword are:
|
||||
|
||||
- A new keyword is added to a function, and that function forwards its
|
||||
inputs to another function or method which can be defined outside of
|
||||
NumPy. For example, ``np.std(x)`` calls ``x.std``, so when a ``keepdims``
|
||||
keyword was added that could only be forwarded if the user explicitly
|
||||
specified ``keepdims``; downstream array libraries may not have added
|
||||
the same keyword, so adding ``x.std(..., keepdims=keepdims)``
|
||||
unconditionally could have broken previously working code.
|
||||
- A keyword is being deprecated, and a deprecation warning must only be
|
||||
emitted when the keyword is used.
|
||||
|
||||
"""
|
||||
__instance = None
|
||||
def __new__(cls):
|
||||
# ensure that only one instance exists
|
||||
if not cls.__instance:
|
||||
cls.__instance = super().__new__(cls)
|
||||
return cls.__instance
|
||||
|
||||
# needed for python 2 to preserve identity through a pickle
|
||||
def __reduce__(self):
|
||||
return (self.__class__, ())
|
||||
|
||||
def __repr__(self):
|
||||
return "<no value>"
|
||||
|
||||
|
||||
_NoValue = _NoValueType()
|
@ -0,0 +1,201 @@
|
||||
"""
|
||||
Pytest test running.
|
||||
|
||||
This module implements the ``test()`` function for NumPy modules. The usual
|
||||
boiler plate for doing that is to put the following in the module
|
||||
``__init__.py`` file::
|
||||
|
||||
from numpy._pytesttester import PytestTester
|
||||
test = PytestTester(__name__)
|
||||
del PytestTester
|
||||
|
||||
|
||||
Warnings filtering and other runtime settings should be dealt with in the
|
||||
``pytest.ini`` file in the numpy repo root. The behavior of the test depends on
|
||||
whether or not that file is found as follows:
|
||||
|
||||
* ``pytest.ini`` is present (develop mode)
|
||||
All warnings except those explicitly filtered out are raised as error.
|
||||
* ``pytest.ini`` is absent (release mode)
|
||||
DeprecationWarnings and PendingDeprecationWarnings are ignored, other
|
||||
warnings are passed through.
|
||||
|
||||
In practice, tests run from the numpy repo are run in develop mode. That
|
||||
includes the standard ``python runtests.py`` invocation.
|
||||
|
||||
This module is imported by every numpy subpackage, so lies at the top level to
|
||||
simplify circular import issues. For the same reason, it contains no numpy
|
||||
imports at module scope, instead importing numpy within function calls.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
|
||||
__all__ = ['PytestTester']
|
||||
|
||||
|
||||
|
||||
def _show_numpy_info():
|
||||
import numpy as np
|
||||
|
||||
print("NumPy version %s" % np.__version__)
|
||||
relaxed_strides = np.ones((10, 1), order="C").flags.f_contiguous
|
||||
print("NumPy relaxed strides checking option:", relaxed_strides)
|
||||
info = np.lib.utils._opt_info()
|
||||
print("NumPy CPU features: ", (info if info else 'nothing enabled'))
|
||||
|
||||
|
||||
|
||||
class PytestTester:
|
||||
"""
|
||||
Pytest test runner.
|
||||
|
||||
A test function is typically added to a package's __init__.py like so::
|
||||
|
||||
from numpy._pytesttester import PytestTester
|
||||
test = PytestTester(__name__).test
|
||||
del PytestTester
|
||||
|
||||
Calling this test function finds and runs all tests associated with the
|
||||
module and all its sub-modules.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
module_name : str
|
||||
Full path to the package to test.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
module_name : module name
|
||||
The name of the module to test.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Unlike the previous ``nose``-based implementation, this class is not
|
||||
publicly exposed as it performs some ``numpy``-specific warning
|
||||
suppression.
|
||||
|
||||
"""
|
||||
def __init__(self, module_name):
|
||||
self.module_name = module_name
|
||||
|
||||
def __call__(self, label='fast', verbose=1, extra_argv=None,
|
||||
doctests=False, coverage=False, durations=-1, tests=None):
|
||||
"""
|
||||
Run tests for module using pytest.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
label : {'fast', 'full'}, optional
|
||||
Identifies the tests to run. When set to 'fast', tests decorated
|
||||
with `pytest.mark.slow` are skipped, when 'full', the slow marker
|
||||
is ignored.
|
||||
verbose : int, optional
|
||||
Verbosity value for test outputs, in the range 1-3. Default is 1.
|
||||
extra_argv : list, optional
|
||||
List with any extra arguments to pass to pytests.
|
||||
doctests : bool, optional
|
||||
.. note:: Not supported
|
||||
coverage : bool, optional
|
||||
If True, report coverage of NumPy code. Default is False.
|
||||
Requires installation of (pip) pytest-cov.
|
||||
durations : int, optional
|
||||
If < 0, do nothing, If 0, report time of all tests, if > 0,
|
||||
report the time of the slowest `timer` tests. Default is -1.
|
||||
tests : test or list of tests
|
||||
Tests to be executed with pytest '--pyargs'
|
||||
|
||||
Returns
|
||||
-------
|
||||
result : bool
|
||||
Return True on success, false otherwise.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Each NumPy module exposes `test` in its namespace to run all tests for
|
||||
it. For example, to run all tests for numpy.lib:
|
||||
|
||||
>>> np.lib.test() #doctest: +SKIP
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> result = np.lib.test() #doctest: +SKIP
|
||||
...
|
||||
1023 passed, 2 skipped, 6 deselected, 1 xfailed in 10.39 seconds
|
||||
>>> result
|
||||
True
|
||||
|
||||
"""
|
||||
import pytest
|
||||
import warnings
|
||||
|
||||
module = sys.modules[self.module_name]
|
||||
module_path = os.path.abspath(module.__path__[0])
|
||||
|
||||
# setup the pytest arguments
|
||||
pytest_args = ["-l"]
|
||||
|
||||
# offset verbosity. The "-q" cancels a "-v".
|
||||
pytest_args += ["-q"]
|
||||
|
||||
# Filter out distutils cpu warnings (could be localized to
|
||||
# distutils tests). ASV has problems with top level import,
|
||||
# so fetch module for suppression here.
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("always")
|
||||
from numpy.distutils import cpuinfo
|
||||
|
||||
# Filter out annoying import messages. Want these in both develop and
|
||||
# release mode.
|
||||
pytest_args += [
|
||||
"-W ignore:Not importing directory",
|
||||
"-W ignore:numpy.dtype size changed",
|
||||
"-W ignore:numpy.ufunc size changed",
|
||||
"-W ignore::UserWarning:cpuinfo",
|
||||
]
|
||||
|
||||
# When testing matrices, ignore their PendingDeprecationWarnings
|
||||
pytest_args += [
|
||||
"-W ignore:the matrix subclass is not",
|
||||
"-W ignore:Importing from numpy.matlib is",
|
||||
]
|
||||
|
||||
if doctests:
|
||||
raise ValueError("Doctests not supported")
|
||||
|
||||
if extra_argv:
|
||||
pytest_args += list(extra_argv)
|
||||
|
||||
if verbose > 1:
|
||||
pytest_args += ["-" + "v"*(verbose - 1)]
|
||||
|
||||
if coverage:
|
||||
pytest_args += ["--cov=" + module_path]
|
||||
|
||||
if label == "fast":
|
||||
# not importing at the top level to avoid circular import of module
|
||||
from numpy.testing import IS_PYPY
|
||||
if IS_PYPY:
|
||||
pytest_args += ["-m", "not slow and not slow_pypy"]
|
||||
else:
|
||||
pytest_args += ["-m", "not slow"]
|
||||
|
||||
elif label != "full":
|
||||
pytest_args += ["-m", label]
|
||||
|
||||
if durations >= 0:
|
||||
pytest_args += ["--durations=%s" % durations]
|
||||
|
||||
if tests is None:
|
||||
tests = [self.module_name]
|
||||
|
||||
pytest_args += ["--pyargs"] + list(tests)
|
||||
|
||||
# run tests.
|
||||
_show_numpy_info()
|
||||
|
||||
try:
|
||||
code = pytest.main(pytest_args)
|
||||
except SystemExit as exc:
|
||||
code = exc.code
|
||||
|
||||
return code == 0
|
@ -0,0 +1,21 @@
|
||||
|
||||
# This file was generated by 'versioneer.py' (0.19) from
|
||||
# revision-control system data, or from the parent directory name of an
|
||||
# unpacked source archive. Distribution tarballs contain a pre-generated copy
|
||||
# of this file.
|
||||
|
||||
import json
|
||||
|
||||
version_json = '''
|
||||
{
|
||||
"date": "2022-04-11T17:43:10-0600",
|
||||
"dirty": false,
|
||||
"error": null,
|
||||
"full-revisionid": "ef0ec786fd4c7622ad2fa0e54d3881f3b9bbd792",
|
||||
"version": "1.21.6"
|
||||
}
|
||||
''' # END VERSION_JSON
|
||||
|
||||
|
||||
def get_versions():
|
||||
return json.loads(version_json)
|
@ -0,0 +1,59 @@
|
||||
from typing import Any, List
|
||||
|
||||
from numpy import (
|
||||
chararray as chararray,
|
||||
)
|
||||
|
||||
__all__: List[str]
|
||||
|
||||
def equal(x1, x2): ...
|
||||
def not_equal(x1, x2): ...
|
||||
def greater_equal(x1, x2): ...
|
||||
def less_equal(x1, x2): ...
|
||||
def greater(x1, x2): ...
|
||||
def less(x1, x2): ...
|
||||
def str_len(a): ...
|
||||
def add(x1, x2): ...
|
||||
def multiply(a, i): ...
|
||||
def mod(a, values): ...
|
||||
def capitalize(a): ...
|
||||
def center(a, width, fillchar=...): ...
|
||||
def count(a, sub, start=..., end=...): ...
|
||||
def decode(a, encoding=..., errors=...): ...
|
||||
def encode(a, encoding=..., errors=...): ...
|
||||
def endswith(a, suffix, start=..., end=...): ...
|
||||
def expandtabs(a, tabsize=...): ...
|
||||
def find(a, sub, start=..., end=...): ...
|
||||
def index(a, sub, start=..., end=...): ...
|
||||
def isalnum(a): ...
|
||||
def isalpha(a): ...
|
||||
def isdigit(a): ...
|
||||
def islower(a): ...
|
||||
def isspace(a): ...
|
||||
def istitle(a): ...
|
||||
def isupper(a): ...
|
||||
def join(sep, seq): ...
|
||||
def ljust(a, width, fillchar=...): ...
|
||||
def lower(a): ...
|
||||
def lstrip(a, chars=...): ...
|
||||
def partition(a, sep): ...
|
||||
def replace(a, old, new, count=...): ...
|
||||
def rfind(a, sub, start=..., end=...): ...
|
||||
def rindex(a, sub, start=..., end=...): ...
|
||||
def rjust(a, width, fillchar=...): ...
|
||||
def rpartition(a, sep): ...
|
||||
def rsplit(a, sep=..., maxsplit=...): ...
|
||||
def rstrip(a, chars=...): ...
|
||||
def split(a, sep=..., maxsplit=...): ...
|
||||
def splitlines(a, keepends=...): ...
|
||||
def startswith(a, prefix, start=..., end=...): ...
|
||||
def strip(a, chars=...): ...
|
||||
def swapcase(a): ...
|
||||
def title(a): ...
|
||||
def translate(a, table, deletechars=...): ...
|
||||
def upper(a): ...
|
||||
def zfill(a, width): ...
|
||||
def isnumeric(a): ...
|
||||
def isdecimal(a): ...
|
||||
def array(obj, itemsize=..., copy=..., unicode=..., order=...): ...
|
||||
def asarray(obj, itemsize=..., unicode=..., order=...): ...
|
@ -0,0 +1,18 @@
|
||||
"""
|
||||
Compatibility module.
|
||||
|
||||
This module contains duplicated code from Python itself or 3rd party
|
||||
extensions, which may be included for the following reasons:
|
||||
|
||||
* compatibility
|
||||
* we may only need a small subset of the copied library/module
|
||||
|
||||
"""
|
||||
from . import _inspect
|
||||
from . import py3k
|
||||
from ._inspect import getargspec, formatargspec
|
||||
from .py3k import *
|
||||
|
||||
__all__ = []
|
||||
__all__.extend(_inspect.__all__)
|
||||
__all__.extend(py3k.__all__)
|
@ -0,0 +1,191 @@
|
||||
"""Subset of inspect module from upstream python
|
||||
|
||||
We use this instead of upstream because upstream inspect is slow to import, and
|
||||
significantly contributes to numpy import times. Importing this copy has almost
|
||||
no overhead.
|
||||
|
||||
"""
|
||||
import types
|
||||
|
||||
__all__ = ['getargspec', 'formatargspec']
|
||||
|
||||
# ----------------------------------------------------------- type-checking
|
||||
def ismethod(object):
|
||||
"""Return true if the object is an instance method.
|
||||
|
||||
Instance method objects provide these attributes:
|
||||
__doc__ documentation string
|
||||
__name__ name with which this method was defined
|
||||
im_class class object in which this method belongs
|
||||
im_func function object containing implementation of method
|
||||
im_self instance to which this method is bound, or None
|
||||
|
||||
"""
|
||||
return isinstance(object, types.MethodType)
|
||||
|
||||
def isfunction(object):
|
||||
"""Return true if the object is a user-defined function.
|
||||
|
||||
Function objects provide these attributes:
|
||||
__doc__ documentation string
|
||||
__name__ name with which this function was defined
|
||||
func_code code object containing compiled function bytecode
|
||||
func_defaults tuple of any default values for arguments
|
||||
func_doc (same as __doc__)
|
||||
func_globals global namespace in which this function was defined
|
||||
func_name (same as __name__)
|
||||
|
||||
"""
|
||||
return isinstance(object, types.FunctionType)
|
||||
|
||||
def iscode(object):
|
||||
"""Return true if the object is a code object.
|
||||
|
||||
Code objects provide these attributes:
|
||||
co_argcount number of arguments (not including * or ** args)
|
||||
co_code string of raw compiled bytecode
|
||||
co_consts tuple of constants used in the bytecode
|
||||
co_filename name of file in which this code object was created
|
||||
co_firstlineno number of first line in Python source code
|
||||
co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
|
||||
co_lnotab encoded mapping of line numbers to bytecode indices
|
||||
co_name name with which this code object was defined
|
||||
co_names tuple of names of local variables
|
||||
co_nlocals number of local variables
|
||||
co_stacksize virtual machine stack space required
|
||||
co_varnames tuple of names of arguments and local variables
|
||||
|
||||
"""
|
||||
return isinstance(object, types.CodeType)
|
||||
|
||||
# ------------------------------------------------ argument list extraction
|
||||
# These constants are from Python's compile.h.
|
||||
CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 1, 2, 4, 8
|
||||
|
||||
def getargs(co):
|
||||
"""Get information about the arguments accepted by a code object.
|
||||
|
||||
Three things are returned: (args, varargs, varkw), where 'args' is
|
||||
a list of argument names (possibly containing nested lists), and
|
||||
'varargs' and 'varkw' are the names of the * and ** arguments or None.
|
||||
|
||||
"""
|
||||
|
||||
if not iscode(co):
|
||||
raise TypeError('arg is not a code object')
|
||||
|
||||
nargs = co.co_argcount
|
||||
names = co.co_varnames
|
||||
args = list(names[:nargs])
|
||||
|
||||
# The following acrobatics are for anonymous (tuple) arguments.
|
||||
# Which we do not need to support, so remove to avoid importing
|
||||
# the dis module.
|
||||
for i in range(nargs):
|
||||
if args[i][:1] in ['', '.']:
|
||||
raise TypeError("tuple function arguments are not supported")
|
||||
varargs = None
|
||||
if co.co_flags & CO_VARARGS:
|
||||
varargs = co.co_varnames[nargs]
|
||||
nargs = nargs + 1
|
||||
varkw = None
|
||||
if co.co_flags & CO_VARKEYWORDS:
|
||||
varkw = co.co_varnames[nargs]
|
||||
return args, varargs, varkw
|
||||
|
||||
def getargspec(func):
|
||||
"""Get the names and default values of a function's arguments.
|
||||
|
||||
A tuple of four things is returned: (args, varargs, varkw, defaults).
|
||||
'args' is a list of the argument names (it may contain nested lists).
|
||||
'varargs' and 'varkw' are the names of the * and ** arguments or None.
|
||||
'defaults' is an n-tuple of the default values of the last n arguments.
|
||||
|
||||
"""
|
||||
|
||||
if ismethod(func):
|
||||
func = func.__func__
|
||||
if not isfunction(func):
|
||||
raise TypeError('arg is not a Python function')
|
||||
args, varargs, varkw = getargs(func.__code__)
|
||||
return args, varargs, varkw, func.__defaults__
|
||||
|
||||
def getargvalues(frame):
|
||||
"""Get information about arguments passed into a particular frame.
|
||||
|
||||
A tuple of four things is returned: (args, varargs, varkw, locals).
|
||||
'args' is a list of the argument names (it may contain nested lists).
|
||||
'varargs' and 'varkw' are the names of the * and ** arguments or None.
|
||||
'locals' is the locals dictionary of the given frame.
|
||||
|
||||
"""
|
||||
args, varargs, varkw = getargs(frame.f_code)
|
||||
return args, varargs, varkw, frame.f_locals
|
||||
|
||||
def joinseq(seq):
|
||||
if len(seq) == 1:
|
||||
return '(' + seq[0] + ',)'
|
||||
else:
|
||||
return '(' + ', '.join(seq) + ')'
|
||||
|
||||
def strseq(object, convert, join=joinseq):
|
||||
"""Recursively walk a sequence, stringifying each element.
|
||||
|
||||
"""
|
||||
if type(object) in [list, tuple]:
|
||||
return join([strseq(_o, convert, join) for _o in object])
|
||||
else:
|
||||
return convert(object)
|
||||
|
||||
def formatargspec(args, varargs=None, varkw=None, defaults=None,
|
||||
formatarg=str,
|
||||
formatvarargs=lambda name: '*' + name,
|
||||
formatvarkw=lambda name: '**' + name,
|
||||
formatvalue=lambda value: '=' + repr(value),
|
||||
join=joinseq):
|
||||
"""Format an argument spec from the 4 values returned by getargspec.
|
||||
|
||||
The first four arguments are (args, varargs, varkw, defaults). The
|
||||
other four arguments are the corresponding optional formatting functions
|
||||
that are called to turn names and values into strings. The ninth
|
||||
argument is an optional function to format the sequence of arguments.
|
||||
|
||||
"""
|
||||
specs = []
|
||||
if defaults:
|
||||
firstdefault = len(args) - len(defaults)
|
||||
for i in range(len(args)):
|
||||
spec = strseq(args[i], formatarg, join)
|
||||
if defaults and i >= firstdefault:
|
||||
spec = spec + formatvalue(defaults[i - firstdefault])
|
||||
specs.append(spec)
|
||||
if varargs is not None:
|
||||
specs.append(formatvarargs(varargs))
|
||||
if varkw is not None:
|
||||
specs.append(formatvarkw(varkw))
|
||||
return '(' + ', '.join(specs) + ')'
|
||||
|
||||
def formatargvalues(args, varargs, varkw, locals,
|
||||
formatarg=str,
|
||||
formatvarargs=lambda name: '*' + name,
|
||||
formatvarkw=lambda name: '**' + name,
|
||||
formatvalue=lambda value: '=' + repr(value),
|
||||
join=joinseq):
|
||||
"""Format an argument spec from the 4 values returned by getargvalues.
|
||||
|
||||
The first four arguments are (args, varargs, varkw, locals). The
|
||||
next four arguments are the corresponding optional formatting functions
|
||||
that are called to turn names and values into strings. The ninth
|
||||
argument is an optional function to format the sequence of arguments.
|
||||
|
||||
"""
|
||||
def convert(name, locals=locals,
|
||||
formatarg=formatarg, formatvalue=formatvalue):
|
||||
return formatarg(name) + formatvalue(locals[name])
|
||||
specs = [strseq(arg, convert, join) for arg in args]
|
||||
|
||||
if varargs:
|
||||
specs.append(formatvarargs(varargs) + formatvalue(locals[varargs]))
|
||||
if varkw:
|
||||
specs.append(formatvarkw(varkw) + formatvalue(locals[varkw]))
|
||||
return '(' + ', '.join(specs) + ')'
|
@ -0,0 +1,141 @@
|
||||
"""
|
||||
Python 3.X compatibility tools.
|
||||
|
||||
While this file was originally intended for Python 2 -> 3 transition,
|
||||
it is now used to create a compatibility layer between different
|
||||
minor versions of Python 3.
|
||||
|
||||
While the active version of numpy may not support a given version of python, we
|
||||
allow downstream libraries to continue to use these shims for forward
|
||||
compatibility with numpy while they transition their code to newer versions of
|
||||
Python.
|
||||
"""
|
||||
__all__ = ['bytes', 'asbytes', 'isfileobj', 'getexception', 'strchar',
|
||||
'unicode', 'asunicode', 'asbytes_nested', 'asunicode_nested',
|
||||
'asstr', 'open_latin1', 'long', 'basestring', 'sixu',
|
||||
'integer_types', 'is_pathlib_path', 'npy_load_module', 'Path',
|
||||
'pickle', 'contextlib_nullcontext', 'os_fspath', 'os_PathLike']
|
||||
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
import io
|
||||
|
||||
import abc
|
||||
from abc import ABC as abc_ABC
|
||||
|
||||
try:
|
||||
import pickle5 as pickle
|
||||
except ImportError:
|
||||
import pickle
|
||||
|
||||
long = int
|
||||
integer_types = (int,)
|
||||
basestring = str
|
||||
unicode = str
|
||||
bytes = bytes
|
||||
|
||||
def asunicode(s):
|
||||
if isinstance(s, bytes):
|
||||
return s.decode('latin1')
|
||||
return str(s)
|
||||
|
||||
def asbytes(s):
|
||||
if isinstance(s, bytes):
|
||||
return s
|
||||
return str(s).encode('latin1')
|
||||
|
||||
def asstr(s):
|
||||
if isinstance(s, bytes):
|
||||
return s.decode('latin1')
|
||||
return str(s)
|
||||
|
||||
def isfileobj(f):
|
||||
return isinstance(f, (io.FileIO, io.BufferedReader, io.BufferedWriter))
|
||||
|
||||
def open_latin1(filename, mode='r'):
|
||||
return open(filename, mode=mode, encoding='iso-8859-1')
|
||||
|
||||
def sixu(s):
|
||||
return s
|
||||
|
||||
strchar = 'U'
|
||||
|
||||
def getexception():
|
||||
return sys.exc_info()[1]
|
||||
|
||||
def asbytes_nested(x):
|
||||
if hasattr(x, '__iter__') and not isinstance(x, (bytes, unicode)):
|
||||
return [asbytes_nested(y) for y in x]
|
||||
else:
|
||||
return asbytes(x)
|
||||
|
||||
def asunicode_nested(x):
|
||||
if hasattr(x, '__iter__') and not isinstance(x, (bytes, unicode)):
|
||||
return [asunicode_nested(y) for y in x]
|
||||
else:
|
||||
return asunicode(x)
|
||||
|
||||
def is_pathlib_path(obj):
|
||||
"""
|
||||
Check whether obj is a `pathlib.Path` object.
|
||||
|
||||
Prefer using ``isinstance(obj, os.PathLike)`` instead of this function.
|
||||
"""
|
||||
return isinstance(obj, Path)
|
||||
|
||||
# from Python 3.7
|
||||
class contextlib_nullcontext:
|
||||
"""Context manager that does no additional processing.
|
||||
|
||||
Used as a stand-in for a normal context manager, when a particular
|
||||
block of code is only sometimes used with a normal context manager:
|
||||
|
||||
cm = optional_cm if condition else nullcontext()
|
||||
with cm:
|
||||
# Perform operation, using optional_cm if condition is True
|
||||
|
||||
.. note::
|
||||
Prefer using `contextlib.nullcontext` instead of this context manager.
|
||||
"""
|
||||
|
||||
def __init__(self, enter_result=None):
|
||||
self.enter_result = enter_result
|
||||
|
||||
def __enter__(self):
|
||||
return self.enter_result
|
||||
|
||||
def __exit__(self, *excinfo):
|
||||
pass
|
||||
|
||||
|
||||
def npy_load_module(name, fn, info=None):
|
||||
"""
|
||||
Load a module. Uses ``load_module`` which will be deprecated in python
|
||||
3.12. An alternative that uses ``exec_module`` is in
|
||||
numpy.distutils.misc_util.exec_mod_from_location
|
||||
|
||||
.. versionadded:: 1.11.2
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Full module name.
|
||||
fn : str
|
||||
Path to module file.
|
||||
info : tuple, optional
|
||||
Only here for backward compatibility with Python 2.*.
|
||||
|
||||
Returns
|
||||
-------
|
||||
mod : module
|
||||
|
||||
"""
|
||||
# Explicitly lazy import this to avoid paying the cost
|
||||
# of importing importlib at startup
|
||||
from importlib.machinery import SourceFileLoader
|
||||
return SourceFileLoader(name, fn).load_module()
|
||||
|
||||
|
||||
os_fspath = os.fspath
|
||||
os_PathLike = os.PathLike
|
@ -0,0 +1,10 @@
|
||||
def configuration(parent_package='',top_path=None):
|
||||
from numpy.distutils.misc_util import Configuration
|
||||
|
||||
config = Configuration('compat', parent_package, top_path)
|
||||
config.add_subpackage('tests')
|
||||
return config
|
||||
|
||||
if __name__ == '__main__':
|
||||
from numpy.distutils.core import setup
|
||||
setup(configuration=configuration)
|
@ -0,0 +1,19 @@
|
||||
from os.path import join
|
||||
|
||||
from numpy.compat import isfileobj
|
||||
from numpy.testing import assert_
|
||||
from numpy.testing import tempdir
|
||||
|
||||
|
||||
def test_isfileobj():
|
||||
with tempdir(prefix="numpy_test_compat_") as folder:
|
||||
filename = join(folder, 'a.bin')
|
||||
|
||||
with open(filename, 'wb') as f:
|
||||
assert_(isfileobj(f))
|
||||
|
||||
with open(filename, 'ab') as f:
|
||||
assert_(isfileobj(f))
|
||||
|
||||
with open(filename, 'rb') as f:
|
||||
assert_(isfileobj(f))
|
@ -0,0 +1,119 @@
|
||||
"""
|
||||
Pytest configuration and fixtures for the Numpy test suite.
|
||||
"""
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import hypothesis
|
||||
import pytest
|
||||
import numpy
|
||||
|
||||
from numpy.core._multiarray_tests import get_fpu_mode
|
||||
|
||||
|
||||
_old_fpu_mode = None
|
||||
_collect_results = {}
|
||||
|
||||
# Use a known and persistent tmpdir for hypothesis' caches, which
|
||||
# can be automatically cleared by the OS or user.
|
||||
hypothesis.configuration.set_hypothesis_home_dir(
|
||||
os.path.join(tempfile.gettempdir(), ".hypothesis")
|
||||
)
|
||||
|
||||
# We register two custom profiles for Numpy - for details see
|
||||
# https://hypothesis.readthedocs.io/en/latest/settings.html
|
||||
# The first is designed for our own CI runs; the latter also
|
||||
# forces determinism and is designed for use via np.test()
|
||||
hypothesis.settings.register_profile(
|
||||
name="numpy-profile", deadline=None, print_blob=True,
|
||||
)
|
||||
hypothesis.settings.register_profile(
|
||||
name="np.test() profile",
|
||||
deadline=None, print_blob=True, database=None, derandomize=True,
|
||||
suppress_health_check=hypothesis.HealthCheck.all(),
|
||||
)
|
||||
# Note that the default profile is chosen based on the presence
|
||||
# of pytest.ini, but can be overriden by passing the
|
||||
# --hypothesis-profile=NAME argument to pytest.
|
||||
_pytest_ini = os.path.join(os.path.dirname(__file__), "..", "pytest.ini")
|
||||
hypothesis.settings.load_profile(
|
||||
"numpy-profile" if os.path.isfile(_pytest_ini) else "np.test() profile"
|
||||
)
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
config.addinivalue_line("markers",
|
||||
"valgrind_error: Tests that are known to error under valgrind.")
|
||||
config.addinivalue_line("markers",
|
||||
"leaks_references: Tests that are known to leak references.")
|
||||
config.addinivalue_line("markers",
|
||||
"slow: Tests that are very slow.")
|
||||
config.addinivalue_line("markers",
|
||||
"slow_pypy: Tests that are very slow on pypy.")
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--available-memory", action="store", default=None,
|
||||
help=("Set amount of memory available for running the "
|
||||
"test suite. This can result to tests requiring "
|
||||
"especially large amounts of memory to be skipped. "
|
||||
"Equivalent to setting environment variable "
|
||||
"NPY_AVAILABLE_MEM. Default: determined"
|
||||
"automatically."))
|
||||
|
||||
|
||||
def pytest_sessionstart(session):
|
||||
available_mem = session.config.getoption('available_memory')
|
||||
if available_mem is not None:
|
||||
os.environ['NPY_AVAILABLE_MEM'] = available_mem
|
||||
|
||||
|
||||
#FIXME when yield tests are gone.
|
||||
@pytest.hookimpl()
|
||||
def pytest_itemcollected(item):
|
||||
"""
|
||||
Check FPU precision mode was not changed during test collection.
|
||||
|
||||
The clumsy way we do it here is mainly necessary because numpy
|
||||
still uses yield tests, which can execute code at test collection
|
||||
time.
|
||||
"""
|
||||
global _old_fpu_mode
|
||||
|
||||
mode = get_fpu_mode()
|
||||
|
||||
if _old_fpu_mode is None:
|
||||
_old_fpu_mode = mode
|
||||
elif mode != _old_fpu_mode:
|
||||
_collect_results[item] = (_old_fpu_mode, mode)
|
||||
_old_fpu_mode = mode
|
||||
|
||||
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def check_fpu_mode(request):
|
||||
"""
|
||||
Check FPU precision mode was not changed during the test.
|
||||
"""
|
||||
old_mode = get_fpu_mode()
|
||||
yield
|
||||
new_mode = get_fpu_mode()
|
||||
|
||||
if old_mode != new_mode:
|
||||
raise AssertionError("FPU precision mode changed from {0:#x} to {1:#x}"
|
||||
" during the test".format(old_mode, new_mode))
|
||||
|
||||
collect_result = _collect_results.get(request.node)
|
||||
if collect_result is not None:
|
||||
old_mode, new_mode = collect_result
|
||||
raise AssertionError("FPU precision mode changed from {0:#x} to {1:#x}"
|
||||
" when collecting the test".format(old_mode,
|
||||
new_mode))
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def add_np(doctest_namespace):
|
||||
doctest_namespace['np'] = numpy
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def env_setup(monkeypatch):
|
||||
monkeypatch.setenv('PYTHONHASHSEED', '0')
|
@ -0,0 +1,166 @@
|
||||
"""
|
||||
Contains the core of NumPy: ndarray, ufuncs, dtypes, etc.
|
||||
|
||||
Please note that this module is private. All functions and objects
|
||||
are available in the main ``numpy`` namespace - use that instead.
|
||||
|
||||
"""
|
||||
|
||||
from numpy.version import version as __version__
|
||||
|
||||
import os
|
||||
|
||||
# disables OpenBLAS affinity setting of the main thread that limits
|
||||
# python threads or processes to one core
|
||||
env_added = []
|
||||
for envkey in ['OPENBLAS_MAIN_FREE', 'GOTOBLAS_MAIN_FREE']:
|
||||
if envkey not in os.environ:
|
||||
os.environ[envkey] = '1'
|
||||
env_added.append(envkey)
|
||||
|
||||
try:
|
||||
from . import multiarray
|
||||
except ImportError as exc:
|
||||
import sys
|
||||
msg = """
|
||||
|
||||
IMPORTANT: PLEASE READ THIS FOR ADVICE ON HOW TO SOLVE THIS ISSUE!
|
||||
|
||||
Importing the numpy C-extensions failed. This error can happen for
|
||||
many reasons, often due to issues with your setup or how NumPy was
|
||||
installed.
|
||||
|
||||
We have compiled some common reasons and troubleshooting tips at:
|
||||
|
||||
https://numpy.org/devdocs/user/troubleshooting-importerror.html
|
||||
|
||||
Please note and check the following:
|
||||
|
||||
* The Python version is: Python%d.%d from "%s"
|
||||
* The NumPy version is: "%s"
|
||||
|
||||
and make sure that they are the versions you expect.
|
||||
Please carefully study the documentation linked above for further help.
|
||||
|
||||
Original error was: %s
|
||||
""" % (sys.version_info[0], sys.version_info[1], sys.executable,
|
||||
__version__, exc)
|
||||
raise ImportError(msg)
|
||||
finally:
|
||||
for envkey in env_added:
|
||||
del os.environ[envkey]
|
||||
del envkey
|
||||
del env_added
|
||||
del os
|
||||
|
||||
from . import umath
|
||||
|
||||
# Check that multiarray,umath are pure python modules wrapping
|
||||
# _multiarray_umath and not either of the old c-extension modules
|
||||
if not (hasattr(multiarray, '_multiarray_umath') and
|
||||
hasattr(umath, '_multiarray_umath')):
|
||||
import sys
|
||||
path = sys.modules['numpy'].__path__
|
||||
msg = ("Something is wrong with the numpy installation. "
|
||||
"While importing we detected an older version of "
|
||||
"numpy in {}. One method of fixing this is to repeatedly uninstall "
|
||||
"numpy until none is found, then reinstall this version.")
|
||||
raise ImportError(msg.format(path))
|
||||
|
||||
from . import numerictypes as nt
|
||||
multiarray.set_typeDict(nt.sctypeDict)
|
||||
from . import numeric
|
||||
from .numeric import *
|
||||
from . import fromnumeric
|
||||
from .fromnumeric import *
|
||||
from . import defchararray as char
|
||||
from . import records as rec
|
||||
from .records import record, recarray, format_parser
|
||||
from .memmap import *
|
||||
from .defchararray import chararray
|
||||
from . import function_base
|
||||
from .function_base import *
|
||||
from . import machar
|
||||
from .machar import *
|
||||
from . import getlimits
|
||||
from .getlimits import *
|
||||
from . import shape_base
|
||||
from .shape_base import *
|
||||
from . import einsumfunc
|
||||
from .einsumfunc import *
|
||||
del nt
|
||||
|
||||
from .fromnumeric import amax as max, amin as min, round_ as round
|
||||
from .numeric import absolute as abs
|
||||
|
||||
# do this after everything else, to minimize the chance of this misleadingly
|
||||
# appearing in an import-time traceback
|
||||
from . import _add_newdocs
|
||||
from . import _add_newdocs_scalars
|
||||
# add these for module-freeze analysis (like PyInstaller)
|
||||
from . import _dtype_ctypes
|
||||
from . import _internal
|
||||
from . import _dtype
|
||||
from . import _methods
|
||||
|
||||
__all__ = ['char', 'rec', 'memmap']
|
||||
__all__ += numeric.__all__
|
||||
__all__ += fromnumeric.__all__
|
||||
__all__ += ['record', 'recarray', 'format_parser']
|
||||
__all__ += ['chararray']
|
||||
__all__ += function_base.__all__
|
||||
__all__ += machar.__all__
|
||||
__all__ += getlimits.__all__
|
||||
__all__ += shape_base.__all__
|
||||
__all__ += einsumfunc.__all__
|
||||
|
||||
# We used to use `np.core._ufunc_reconstruct` to unpickle. This is unnecessary,
|
||||
# but old pickles saved before 1.20 will be using it, and there is no reason
|
||||
# to break loading them.
|
||||
def _ufunc_reconstruct(module, name):
|
||||
# The `fromlist` kwarg is required to ensure that `mod` points to the
|
||||
# inner-most module rather than the parent package when module name is
|
||||
# nested. This makes it possible to pickle non-toplevel ufuncs such as
|
||||
# scipy.special.expit for instance.
|
||||
mod = __import__(module, fromlist=[name])
|
||||
return getattr(mod, name)
|
||||
|
||||
|
||||
def _ufunc_reduce(func):
|
||||
# Report the `__name__`. pickle will try to find the module. Note that
|
||||
# pickle supports for this `__name__` to be a `__qualname__`. It may
|
||||
# make sense to add a `__qualname__` to ufuncs, to allow this more
|
||||
# explicitly (Numba has ufuncs as attributes).
|
||||
# See also: https://github.com/dask/distributed/issues/3450
|
||||
return func.__name__
|
||||
|
||||
|
||||
def _DType_reconstruct(scalar_type):
|
||||
# This is a work-around to pickle type(np.dtype(np.float64)), etc.
|
||||
# and it should eventually be replaced with a better solution, e.g. when
|
||||
# DTypes become HeapTypes.
|
||||
return type(dtype(scalar_type))
|
||||
|
||||
|
||||
def _DType_reduce(DType):
|
||||
# To pickle a DType without having to add top-level names, pickle the
|
||||
# scalar type for now (and assume that reconstruction will be possible).
|
||||
if DType is dtype:
|
||||
return "dtype" # must pickle `np.dtype` as a singleton.
|
||||
scalar_type = DType.type # pickle the scalar type for reconstruction
|
||||
return _DType_reconstruct, (scalar_type,)
|
||||
|
||||
|
||||
import copyreg
|
||||
|
||||
copyreg.pickle(ufunc, _ufunc_reduce)
|
||||
copyreg.pickle(type(dtype), _DType_reduce, _DType_reconstruct)
|
||||
|
||||
# Unclutter namespace (must keep _*_reconstruct for unpickling)
|
||||
del copyreg
|
||||
del _ufunc_reduce
|
||||
del _DType_reduce
|
||||
|
||||
from numpy._pytesttester import PytestTester
|
||||
test = PytestTester(__name__)
|
||||
del PytestTester
|
@ -0,0 +1,2 @@
|
||||
# NOTE: The `np.core` namespace is deliberately kept empty due to it
|
||||
# being private (despite the lack of leading underscore)
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,259 @@
|
||||
"""
|
||||
This file is separate from ``_add_newdocs.py`` so that it can be mocked out by
|
||||
our sphinx ``conf.py`` during doc builds, where we want to avoid showing
|
||||
platform-dependent information.
|
||||
"""
|
||||
from numpy.core import dtype
|
||||
from numpy.core import numerictypes as _numerictypes
|
||||
from numpy.core.function_base import add_newdoc
|
||||
import platform
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Documentation for concrete scalar classes
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
def numeric_type_aliases(aliases):
|
||||
def type_aliases_gen():
|
||||
for alias, doc in aliases:
|
||||
try:
|
||||
alias_type = getattr(_numerictypes, alias)
|
||||
except AttributeError:
|
||||
# The set of aliases that actually exist varies between platforms
|
||||
pass
|
||||
else:
|
||||
yield (alias_type, alias, doc)
|
||||
return list(type_aliases_gen())
|
||||
|
||||
|
||||
possible_aliases = numeric_type_aliases([
|
||||
('int8', '8-bit signed integer (``-128`` to ``127``)'),
|
||||
('int16', '16-bit signed integer (``-32_768`` to ``32_767``)'),
|
||||
('int32', '32-bit signed integer (``-2_147_483_648`` to ``2_147_483_647``)'),
|
||||
('int64', '64-bit signed integer (``-9_223_372_036_854_775_808`` to ``9_223_372_036_854_775_807``)'),
|
||||
('intp', 'Signed integer large enough to fit pointer, compatible with C ``intptr_t``'),
|
||||
('uint8', '8-bit unsigned integer (``0`` to ``255``)'),
|
||||
('uint16', '16-bit unsigned integer (``0`` to ``65_535``)'),
|
||||
('uint32', '32-bit unsigned integer (``0`` to ``4_294_967_295``)'),
|
||||
('uint64', '64-bit unsigned integer (``0`` to ``18_446_744_073_709_551_615``)'),
|
||||
('uintp', 'Unsigned integer large enough to fit pointer, compatible with C ``uintptr_t``'),
|
||||
('float16', '16-bit-precision floating-point number type: sign bit, 5 bits exponent, 10 bits mantissa'),
|
||||
('float32', '32-bit-precision floating-point number type: sign bit, 8 bits exponent, 23 bits mantissa'),
|
||||
('float64', '64-bit precision floating-point number type: sign bit, 11 bits exponent, 52 bits mantissa'),
|
||||
('float96', '96-bit extended-precision floating-point number type'),
|
||||
('float128', '128-bit extended-precision floating-point number type'),
|
||||
('complex64', 'Complex number type composed of 2 32-bit-precision floating-point numbers'),
|
||||
('complex128', 'Complex number type composed of 2 64-bit-precision floating-point numbers'),
|
||||
('complex192', 'Complex number type composed of 2 96-bit extended-precision floating-point numbers'),
|
||||
('complex256', 'Complex number type composed of 2 128-bit extended-precision floating-point numbers'),
|
||||
])
|
||||
|
||||
|
||||
|
||||
|
||||
def add_newdoc_for_scalar_type(obj, fixed_aliases, doc):
|
||||
# note: `:field: value` is rST syntax which renders as field lists.
|
||||
o = getattr(_numerictypes, obj)
|
||||
|
||||
character_code = dtype(o).char
|
||||
canonical_name_doc = "" if obj == o.__name__ else ":Canonical name: `numpy.{}`\n ".format(obj)
|
||||
alias_doc = ''.join(":Alias: `numpy.{}`\n ".format(alias) for alias in fixed_aliases)
|
||||
alias_doc += ''.join(":Alias on this platform ({} {}): `numpy.{}`: {}.\n ".format(platform.system(), platform.machine(), alias, doc)
|
||||
for (alias_type, alias, doc) in possible_aliases if alias_type is o)
|
||||
docstring = """
|
||||
{doc}
|
||||
|
||||
:Character code: ``'{character_code}'``
|
||||
{canonical_name_doc}{alias_doc}
|
||||
""".format(doc=doc.strip(), character_code=character_code,
|
||||
canonical_name_doc=canonical_name_doc, alias_doc=alias_doc)
|
||||
|
||||
add_newdoc('numpy.core.numerictypes', obj, docstring)
|
||||
|
||||
|
||||
add_newdoc_for_scalar_type('bool_', ['bool8'],
|
||||
"""
|
||||
Boolean type (True or False), stored as a byte.
|
||||
|
||||
.. warning::
|
||||
|
||||
The :class:`bool_` type is not a subclass of the :class:`int_` type
|
||||
(the :class:`bool_` is not even a number type). This is different
|
||||
than Python's default implementation of :class:`bool` as a
|
||||
sub-class of :class:`int`.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('byte', [],
|
||||
"""
|
||||
Signed integer type, compatible with C ``char``.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('short', [],
|
||||
"""
|
||||
Signed integer type, compatible with C ``short``.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('intc', [],
|
||||
"""
|
||||
Signed integer type, compatible with C ``int``.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('int_', [],
|
||||
"""
|
||||
Signed integer type, compatible with Python `int` and C ``long``.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('longlong', [],
|
||||
"""
|
||||
Signed integer type, compatible with C ``long long``.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('ubyte', [],
|
||||
"""
|
||||
Unsigned integer type, compatible with C ``unsigned char``.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('ushort', [],
|
||||
"""
|
||||
Unsigned integer type, compatible with C ``unsigned short``.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('uintc', [],
|
||||
"""
|
||||
Unsigned integer type, compatible with C ``unsigned int``.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('uint', [],
|
||||
"""
|
||||
Unsigned integer type, compatible with C ``unsigned long``.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('ulonglong', [],
|
||||
"""
|
||||
Signed integer type, compatible with C ``unsigned long long``.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('half', [],
|
||||
"""
|
||||
Half-precision floating-point number type.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('single', [],
|
||||
"""
|
||||
Single-precision floating-point number type, compatible with C ``float``.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('double', ['float_'],
|
||||
"""
|
||||
Double-precision floating-point number type, compatible with Python `float`
|
||||
and C ``double``.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('longdouble', ['longfloat'],
|
||||
"""
|
||||
Extended-precision floating-point number type, compatible with C
|
||||
``long double`` but not necessarily with IEEE 754 quadruple-precision.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('csingle', ['singlecomplex'],
|
||||
"""
|
||||
Complex number type composed of two single-precision floating-point
|
||||
numbers.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('cdouble', ['cfloat', 'complex_'],
|
||||
"""
|
||||
Complex number type composed of two double-precision floating-point
|
||||
numbers, compatible with Python `complex`.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('clongdouble', ['clongfloat', 'longcomplex'],
|
||||
"""
|
||||
Complex number type composed of two extended-precision floating-point
|
||||
numbers.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('object_', [],
|
||||
"""
|
||||
Any Python object.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('str_', ['unicode_'],
|
||||
r"""
|
||||
A unicode string.
|
||||
|
||||
When used in arrays, this type strips trailing null codepoints.
|
||||
|
||||
Unlike the builtin `str`, this supports the :ref:`python:bufferobjects`, exposing its
|
||||
contents as UCS4:
|
||||
|
||||
>>> m = memoryview(np.str_("abc"))
|
||||
>>> m.format
|
||||
'3w'
|
||||
>>> m.tobytes()
|
||||
b'a\x00\x00\x00b\x00\x00\x00c\x00\x00\x00'
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('bytes_', ['string_'],
|
||||
r"""
|
||||
A byte string.
|
||||
|
||||
When used in arrays, this type strips trailing null bytes.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('void', [],
|
||||
r"""
|
||||
Either an opaque sequence of bytes, or a structure.
|
||||
|
||||
>>> np.void(b'abcd')
|
||||
void(b'\x61\x62\x63\x64')
|
||||
|
||||
Structured `void` scalars can only be constructed via extraction from :ref:`structured_arrays`:
|
||||
|
||||
>>> arr = np.array((1, 2), dtype=[('x', np.int8), ('y', np.int8)])
|
||||
>>> arr[()]
|
||||
(1, 2) # looks like a tuple, but is `np.void`
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('datetime64', [],
|
||||
"""
|
||||
If created from a 64-bit integer, it represents an offset from
|
||||
``1970-01-01T00:00:00``.
|
||||
If created from string, the string can be in ISO 8601 date
|
||||
or datetime format.
|
||||
|
||||
>>> np.datetime64(10, 'Y')
|
||||
numpy.datetime64('1980')
|
||||
>>> np.datetime64('1980', 'Y')
|
||||
numpy.datetime64('1980')
|
||||
>>> np.datetime64(10, 'D')
|
||||
numpy.datetime64('1970-01-11')
|
||||
|
||||
See :ref:`arrays.datetime` for more information.
|
||||
""")
|
||||
|
||||
add_newdoc_for_scalar_type('timedelta64', [],
|
||||
"""
|
||||
A timedelta stored as a 64-bit integer.
|
||||
|
||||
See :ref:`arrays.datetime` for more information.
|
||||
""")
|
||||
|
||||
# TODO: work out how to put this on the base class, np.floating
|
||||
for float_name in ('half', 'single', 'double', 'longdouble'):
|
||||
add_newdoc('numpy.core.numerictypes', float_name, ('as_integer_ratio',
|
||||
"""
|
||||
{ftype}.as_integer_ratio() -> (int, int)
|
||||
|
||||
Return a pair of integers, whose ratio is exactly equal to the original
|
||||
floating point number, and with a positive denominator.
|
||||
Raise `OverflowError` on infinities and a `ValueError` on NaNs.
|
||||
|
||||
>>> np.{ftype}(10.0).as_integer_ratio()
|
||||
(10, 1)
|
||||
>>> np.{ftype}(0.0).as_integer_ratio()
|
||||
(0, 1)
|
||||
>>> np.{ftype}(-.25).as_integer_ratio()
|
||||
(-1, 4)
|
||||
""".format(ftype=float_name)))
|
@ -0,0 +1,140 @@
|
||||
"""
|
||||
Functions in the ``as*array`` family that promote array-likes into arrays.
|
||||
|
||||
`require` fits this category despite its name not matching this pattern.
|
||||
"""
|
||||
from .overrides import (
|
||||
array_function_dispatch,
|
||||
set_array_function_like_doc,
|
||||
set_module,
|
||||
)
|
||||
from .multiarray import array, asanyarray
|
||||
|
||||
|
||||
__all__ = ["require"]
|
||||
|
||||
|
||||
|
||||
def _require_dispatcher(a, dtype=None, requirements=None, *, like=None):
|
||||
return (like,)
|
||||
|
||||
|
||||
@set_array_function_like_doc
|
||||
@set_module('numpy')
|
||||
def require(a, dtype=None, requirements=None, *, like=None):
|
||||
"""
|
||||
Return an ndarray of the provided type that satisfies requirements.
|
||||
|
||||
This function is useful to be sure that an array with the correct flags
|
||||
is returned for passing to compiled code (perhaps through ctypes).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
a : array_like
|
||||
The object to be converted to a type-and-requirement-satisfying array.
|
||||
dtype : data-type
|
||||
The required data-type. If None preserve the current dtype. If your
|
||||
application requires the data to be in native byteorder, include
|
||||
a byteorder specification as a part of the dtype specification.
|
||||
requirements : str or list of str
|
||||
The requirements list can be any of the following
|
||||
|
||||
* 'F_CONTIGUOUS' ('F') - ensure a Fortran-contiguous array
|
||||
* 'C_CONTIGUOUS' ('C') - ensure a C-contiguous array
|
||||
* 'ALIGNED' ('A') - ensure a data-type aligned array
|
||||
* 'WRITEABLE' ('W') - ensure a writable array
|
||||
* 'OWNDATA' ('O') - ensure an array that owns its own data
|
||||
* 'ENSUREARRAY', ('E') - ensure a base array, instead of a subclass
|
||||
${ARRAY_FUNCTION_LIKE}
|
||||
|
||||
.. versionadded:: 1.20.0
|
||||
|
||||
Returns
|
||||
-------
|
||||
out : ndarray
|
||||
Array with specified requirements and type if given.
|
||||
|
||||
See Also
|
||||
--------
|
||||
asarray : Convert input to an ndarray.
|
||||
asanyarray : Convert to an ndarray, but pass through ndarray subclasses.
|
||||
ascontiguousarray : Convert input to a contiguous array.
|
||||
asfortranarray : Convert input to an ndarray with column-major
|
||||
memory order.
|
||||
ndarray.flags : Information about the memory layout of the array.
|
||||
|
||||
Notes
|
||||
-----
|
||||
The returned array will be guaranteed to have the listed requirements
|
||||
by making a copy if needed.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> x = np.arange(6).reshape(2,3)
|
||||
>>> x.flags
|
||||
C_CONTIGUOUS : True
|
||||
F_CONTIGUOUS : False
|
||||
OWNDATA : False
|
||||
WRITEABLE : True
|
||||
ALIGNED : True
|
||||
WRITEBACKIFCOPY : False
|
||||
UPDATEIFCOPY : False
|
||||
|
||||
>>> y = np.require(x, dtype=np.float32, requirements=['A', 'O', 'W', 'F'])
|
||||
>>> y.flags
|
||||
C_CONTIGUOUS : False
|
||||
F_CONTIGUOUS : True
|
||||
OWNDATA : True
|
||||
WRITEABLE : True
|
||||
ALIGNED : True
|
||||
WRITEBACKIFCOPY : False
|
||||
UPDATEIFCOPY : False
|
||||
|
||||
"""
|
||||
if like is not None:
|
||||
return _require_with_like(
|
||||
a,
|
||||
dtype=dtype,
|
||||
requirements=requirements,
|
||||
like=like,
|
||||
)
|
||||
|
||||
possible_flags = {'C': 'C', 'C_CONTIGUOUS': 'C', 'CONTIGUOUS': 'C',
|
||||
'F': 'F', 'F_CONTIGUOUS': 'F', 'FORTRAN': 'F',
|
||||
'A': 'A', 'ALIGNED': 'A',
|
||||
'W': 'W', 'WRITEABLE': 'W',
|
||||
'O': 'O', 'OWNDATA': 'O',
|
||||
'E': 'E', 'ENSUREARRAY': 'E'}
|
||||
if not requirements:
|
||||
return asanyarray(a, dtype=dtype)
|
||||
else:
|
||||
requirements = {possible_flags[x.upper()] for x in requirements}
|
||||
|
||||
if 'E' in requirements:
|
||||
requirements.remove('E')
|
||||
subok = False
|
||||
else:
|
||||
subok = True
|
||||
|
||||
order = 'A'
|
||||
if requirements >= {'C', 'F'}:
|
||||
raise ValueError('Cannot specify both "C" and "F" order')
|
||||
elif 'F' in requirements:
|
||||
order = 'F'
|
||||
requirements.remove('F')
|
||||
elif 'C' in requirements:
|
||||
order = 'C'
|
||||
requirements.remove('C')
|
||||
|
||||
arr = array(a, dtype=dtype, order=order, copy=False, subok=subok)
|
||||
|
||||
for prop in requirements:
|
||||
if not arr.flags[prop]:
|
||||
arr = arr.copy(order)
|
||||
break
|
||||
return arr
|
||||
|
||||
|
||||
_require_with_like = array_function_dispatch(
|
||||
_require_dispatcher
|
||||
)(require)
|
@ -0,0 +1,81 @@
|
||||
import sys
|
||||
from typing import TypeVar, Union, Iterable, overload
|
||||
|
||||
from numpy import ndarray, _OrderKACF
|
||||
from numpy.typing import ArrayLike, DTypeLike
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from typing import Literal
|
||||
else:
|
||||
from typing_extensions import Literal
|
||||
|
||||
_ArrayType = TypeVar("_ArrayType", bound=ndarray)
|
||||
|
||||
# TODO: The following functions are now defined in C, so should be defined
|
||||
# in a (not yet existing) `multiarray.pyi`.
|
||||
# (with the exception of `require`)
|
||||
|
||||
def asarray(
|
||||
a: object,
|
||||
dtype: DTypeLike = ...,
|
||||
order: _OrderKACF = ...,
|
||||
*,
|
||||
like: ArrayLike = ...
|
||||
) -> ndarray: ...
|
||||
@overload
|
||||
def asanyarray(
|
||||
a: _ArrayType,
|
||||
dtype: None = ...,
|
||||
order: _OrderKACF = ...,
|
||||
*,
|
||||
like: ArrayLike = ...
|
||||
) -> _ArrayType: ...
|
||||
@overload
|
||||
def asanyarray(
|
||||
a: object,
|
||||
dtype: DTypeLike = ...,
|
||||
order: _OrderKACF = ...,
|
||||
*,
|
||||
like: ArrayLike = ...
|
||||
) -> ndarray: ...
|
||||
def ascontiguousarray(
|
||||
a: object, dtype: DTypeLike = ..., *, like: ArrayLike = ...
|
||||
) -> ndarray: ...
|
||||
def asfortranarray(
|
||||
a: object, dtype: DTypeLike = ..., *, like: ArrayLike = ...
|
||||
) -> ndarray: ...
|
||||
|
||||
_Requirements = Literal[
|
||||
"C", "C_CONTIGUOUS", "CONTIGUOUS",
|
||||
"F", "F_CONTIGUOUS", "FORTRAN",
|
||||
"A", "ALIGNED",
|
||||
"W", "WRITEABLE",
|
||||
"O", "OWNDATA"
|
||||
]
|
||||
_E = Literal["E", "ENSUREARRAY"]
|
||||
_RequirementsWithE = Union[_Requirements, _E]
|
||||
|
||||
@overload
|
||||
def require(
|
||||
a: _ArrayType,
|
||||
dtype: None = ...,
|
||||
requirements: Union[None, _Requirements, Iterable[_Requirements]] = ...,
|
||||
*,
|
||||
like: ArrayLike = ...
|
||||
) -> _ArrayType: ...
|
||||
@overload
|
||||
def require(
|
||||
a: object,
|
||||
dtype: DTypeLike = ...,
|
||||
requirements: Union[_E, Iterable[_RequirementsWithE]] = ...,
|
||||
*,
|
||||
like: ArrayLike = ...
|
||||
) -> ndarray: ...
|
||||
@overload
|
||||
def require(
|
||||
a: object,
|
||||
dtype: DTypeLike = ...,
|
||||
requirements: Union[None, _Requirements, Iterable[_Requirements]] = ...,
|
||||
*,
|
||||
like: ArrayLike = ...
|
||||
) -> ndarray: ...
|
@ -0,0 +1,342 @@
|
||||
"""
|
||||
A place for code to be called from the implementation of np.dtype
|
||||
|
||||
String handling is much easier to do correctly in python.
|
||||
"""
|
||||
import numpy as np
|
||||
|
||||
|
||||
_kind_to_stem = {
|
||||
'u': 'uint',
|
||||
'i': 'int',
|
||||
'c': 'complex',
|
||||
'f': 'float',
|
||||
'b': 'bool',
|
||||
'V': 'void',
|
||||
'O': 'object',
|
||||
'M': 'datetime',
|
||||
'm': 'timedelta',
|
||||
'S': 'bytes',
|
||||
'U': 'str',
|
||||
}
|
||||
|
||||
|
||||
def _kind_name(dtype):
|
||||
try:
|
||||
return _kind_to_stem[dtype.kind]
|
||||
except KeyError as e:
|
||||
raise RuntimeError(
|
||||
"internal dtype error, unknown kind {!r}"
|
||||
.format(dtype.kind)
|
||||
) from None
|
||||
|
||||
|
||||
def __str__(dtype):
|
||||
if dtype.fields is not None:
|
||||
return _struct_str(dtype, include_align=True)
|
||||
elif dtype.subdtype:
|
||||
return _subarray_str(dtype)
|
||||
elif issubclass(dtype.type, np.flexible) or not dtype.isnative:
|
||||
return dtype.str
|
||||
else:
|
||||
return dtype.name
|
||||
|
||||
|
||||
def __repr__(dtype):
|
||||
arg_str = _construction_repr(dtype, include_align=False)
|
||||
if dtype.isalignedstruct:
|
||||
arg_str = arg_str + ", align=True"
|
||||
return "dtype({})".format(arg_str)
|
||||
|
||||
|
||||
def _unpack_field(dtype, offset, title=None):
|
||||
"""
|
||||
Helper function to normalize the items in dtype.fields.
|
||||
|
||||
Call as:
|
||||
|
||||
dtype, offset, title = _unpack_field(*dtype.fields[name])
|
||||
"""
|
||||
return dtype, offset, title
|
||||
|
||||
|
||||
def _isunsized(dtype):
|
||||
# PyDataType_ISUNSIZED
|
||||
return dtype.itemsize == 0
|
||||
|
||||
|
||||
def _construction_repr(dtype, include_align=False, short=False):
|
||||
"""
|
||||
Creates a string repr of the dtype, excluding the 'dtype()' part
|
||||
surrounding the object. This object may be a string, a list, or
|
||||
a dict depending on the nature of the dtype. This
|
||||
is the object passed as the first parameter to the dtype
|
||||
constructor, and if no additional constructor parameters are
|
||||
given, will reproduce the exact memory layout.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
short : bool
|
||||
If true, this creates a shorter repr using 'kind' and 'itemsize', instead
|
||||
of the longer type name.
|
||||
|
||||
include_align : bool
|
||||
If true, this includes the 'align=True' parameter
|
||||
inside the struct dtype construction dict when needed. Use this flag
|
||||
if you want a proper repr string without the 'dtype()' part around it.
|
||||
|
||||
If false, this does not preserve the
|
||||
'align=True' parameter or sticky NPY_ALIGNED_STRUCT flag for
|
||||
struct arrays like the regular repr does, because the 'align'
|
||||
flag is not part of first dtype constructor parameter. This
|
||||
mode is intended for a full 'repr', where the 'align=True' is
|
||||
provided as the second parameter.
|
||||
"""
|
||||
if dtype.fields is not None:
|
||||
return _struct_str(dtype, include_align=include_align)
|
||||
elif dtype.subdtype:
|
||||
return _subarray_str(dtype)
|
||||
else:
|
||||
return _scalar_str(dtype, short=short)
|
||||
|
||||
|
||||
def _scalar_str(dtype, short):
|
||||
byteorder = _byte_order_str(dtype)
|
||||
|
||||
if dtype.type == np.bool_:
|
||||
if short:
|
||||
return "'?'"
|
||||
else:
|
||||
return "'bool'"
|
||||
|
||||
elif dtype.type == np.object_:
|
||||
# The object reference may be different sizes on different
|
||||
# platforms, so it should never include the itemsize here.
|
||||
return "'O'"
|
||||
|
||||
elif dtype.type == np.string_:
|
||||
if _isunsized(dtype):
|
||||
return "'S'"
|
||||
else:
|
||||
return "'S%d'" % dtype.itemsize
|
||||
|
||||
elif dtype.type == np.unicode_:
|
||||
if _isunsized(dtype):
|
||||
return "'%sU'" % byteorder
|
||||
else:
|
||||
return "'%sU%d'" % (byteorder, dtype.itemsize / 4)
|
||||
|
||||
# unlike the other types, subclasses of void are preserved - but
|
||||
# historically the repr does not actually reveal the subclass
|
||||
elif issubclass(dtype.type, np.void):
|
||||
if _isunsized(dtype):
|
||||
return "'V'"
|
||||
else:
|
||||
return "'V%d'" % dtype.itemsize
|
||||
|
||||
elif dtype.type == np.datetime64:
|
||||
return "'%sM8%s'" % (byteorder, _datetime_metadata_str(dtype))
|
||||
|
||||
elif dtype.type == np.timedelta64:
|
||||
return "'%sm8%s'" % (byteorder, _datetime_metadata_str(dtype))
|
||||
|
||||
elif np.issubdtype(dtype, np.number):
|
||||
# Short repr with endianness, like '<f8'
|
||||
if short or dtype.byteorder not in ('=', '|'):
|
||||
return "'%s%c%d'" % (byteorder, dtype.kind, dtype.itemsize)
|
||||
|
||||
# Longer repr, like 'float64'
|
||||
else:
|
||||
return "'%s%d'" % (_kind_name(dtype), 8*dtype.itemsize)
|
||||
|
||||
elif dtype.isbuiltin == 2:
|
||||
return dtype.type.__name__
|
||||
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"Internal error: NumPy dtype unrecognized type number")
|
||||
|
||||
|
||||
def _byte_order_str(dtype):
|
||||
""" Normalize byteorder to '<' or '>' """
|
||||
# hack to obtain the native and swapped byte order characters
|
||||
swapped = np.dtype(int).newbyteorder('S')
|
||||
native = swapped.newbyteorder('S')
|
||||
|
||||
byteorder = dtype.byteorder
|
||||
if byteorder == '=':
|
||||
return native.byteorder
|
||||
if byteorder == 'S':
|
||||
# TODO: this path can never be reached
|
||||
return swapped.byteorder
|
||||
elif byteorder == '|':
|
||||
return ''
|
||||
else:
|
||||
return byteorder
|
||||
|
||||
|
||||
def _datetime_metadata_str(dtype):
|
||||
# TODO: this duplicates the C metastr_to_unicode functionality
|
||||
unit, count = np.datetime_data(dtype)
|
||||
if unit == 'generic':
|
||||
return ''
|
||||
elif count == 1:
|
||||
return '[{}]'.format(unit)
|
||||
else:
|
||||
return '[{}{}]'.format(count, unit)
|
||||
|
||||
|
||||
def _struct_dict_str(dtype, includealignedflag):
|
||||
# unpack the fields dictionary into ls
|
||||
names = dtype.names
|
||||
fld_dtypes = []
|
||||
offsets = []
|
||||
titles = []
|
||||
for name in names:
|
||||
fld_dtype, offset, title = _unpack_field(*dtype.fields[name])
|
||||
fld_dtypes.append(fld_dtype)
|
||||
offsets.append(offset)
|
||||
titles.append(title)
|
||||
|
||||
# Build up a string to make the dictionary
|
||||
|
||||
# First, the names
|
||||
ret = "{'names':["
|
||||
ret += ",".join(repr(name) for name in names)
|
||||
|
||||
# Second, the formats
|
||||
ret += "], 'formats':["
|
||||
ret += ",".join(
|
||||
_construction_repr(fld_dtype, short=True) for fld_dtype in fld_dtypes)
|
||||
|
||||
# Third, the offsets
|
||||
ret += "], 'offsets':["
|
||||
ret += ",".join("%d" % offset for offset in offsets)
|
||||
|
||||
# Fourth, the titles
|
||||
if any(title is not None for title in titles):
|
||||
ret += "], 'titles':["
|
||||
ret += ",".join(repr(title) for title in titles)
|
||||
|
||||
# Fifth, the itemsize
|
||||
ret += "], 'itemsize':%d" % dtype.itemsize
|
||||
|
||||
if (includealignedflag and dtype.isalignedstruct):
|
||||
# Finally, the aligned flag
|
||||
ret += ", 'aligned':True}"
|
||||
else:
|
||||
ret += "}"
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def _is_packed(dtype):
|
||||
"""
|
||||
Checks whether the structured data type in 'dtype'
|
||||
has a simple layout, where all the fields are in order,
|
||||
and follow each other with no alignment padding.
|
||||
|
||||
When this returns true, the dtype can be reconstructed
|
||||
from a list of the field names and dtypes with no additional
|
||||
dtype parameters.
|
||||
|
||||
Duplicates the C `is_dtype_struct_simple_unaligned_layout` function.
|
||||
"""
|
||||
total_offset = 0
|
||||
for name in dtype.names:
|
||||
fld_dtype, fld_offset, title = _unpack_field(*dtype.fields[name])
|
||||
if fld_offset != total_offset:
|
||||
return False
|
||||
total_offset += fld_dtype.itemsize
|
||||
if total_offset != dtype.itemsize:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _struct_list_str(dtype):
|
||||
items = []
|
||||
for name in dtype.names:
|
||||
fld_dtype, fld_offset, title = _unpack_field(*dtype.fields[name])
|
||||
|
||||
item = "("
|
||||
if title is not None:
|
||||
item += "({!r}, {!r}), ".format(title, name)
|
||||
else:
|
||||
item += "{!r}, ".format(name)
|
||||
# Special case subarray handling here
|
||||
if fld_dtype.subdtype is not None:
|
||||
base, shape = fld_dtype.subdtype
|
||||
item += "{}, {}".format(
|
||||
_construction_repr(base, short=True),
|
||||
shape
|
||||
)
|
||||
else:
|
||||
item += _construction_repr(fld_dtype, short=True)
|
||||
|
||||
item += ")"
|
||||
items.append(item)
|
||||
|
||||
return "[" + ", ".join(items) + "]"
|
||||
|
||||
|
||||
def _struct_str(dtype, include_align):
|
||||
# The list str representation can't include the 'align=' flag,
|
||||
# so if it is requested and the struct has the aligned flag set,
|
||||
# we must use the dict str instead.
|
||||
if not (include_align and dtype.isalignedstruct) and _is_packed(dtype):
|
||||
sub = _struct_list_str(dtype)
|
||||
|
||||
else:
|
||||
sub = _struct_dict_str(dtype, include_align)
|
||||
|
||||
# If the data type isn't the default, void, show it
|
||||
if dtype.type != np.void:
|
||||
return "({t.__module__}.{t.__name__}, {f})".format(t=dtype.type, f=sub)
|
||||
else:
|
||||
return sub
|
||||
|
||||
|
||||
def _subarray_str(dtype):
|
||||
base, shape = dtype.subdtype
|
||||
return "({}, {})".format(
|
||||
_construction_repr(base, short=True),
|
||||
shape
|
||||
)
|
||||
|
||||
|
||||
def _name_includes_bit_suffix(dtype):
|
||||
if dtype.type == np.object_:
|
||||
# pointer size varies by system, best to omit it
|
||||
return False
|
||||
elif dtype.type == np.bool_:
|
||||
# implied
|
||||
return False
|
||||
elif np.issubdtype(dtype, np.flexible) and _isunsized(dtype):
|
||||
# unspecified
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def _name_get(dtype):
|
||||
# provides dtype.name.__get__, documented as returning a "bit name"
|
||||
|
||||
if dtype.isbuiltin == 2:
|
||||
# user dtypes don't promise to do anything special
|
||||
return dtype.type.__name__
|
||||
|
||||
if issubclass(dtype.type, np.void):
|
||||
# historically, void subclasses preserve their name, eg `record64`
|
||||
name = dtype.type.__name__
|
||||
else:
|
||||
name = _kind_name(dtype)
|
||||
|
||||
# append bit counts
|
||||
if _name_includes_bit_suffix(dtype):
|
||||
name += "{}".format(dtype.itemsize * 8)
|
||||
|
||||
# append metadata to datetimes
|
||||
if dtype.type in (np.datetime64, np.timedelta64):
|
||||
name += _datetime_metadata_str(dtype)
|
||||
|
||||
return name
|
@ -0,0 +1,117 @@
|
||||
"""
|
||||
Conversion from ctypes to dtype.
|
||||
|
||||
In an ideal world, we could achieve this through the PEP3118 buffer protocol,
|
||||
something like::
|
||||
|
||||
def dtype_from_ctypes_type(t):
|
||||
# needed to ensure that the shape of `t` is within memoryview.format
|
||||
class DummyStruct(ctypes.Structure):
|
||||
_fields_ = [('a', t)]
|
||||
|
||||
# empty to avoid memory allocation
|
||||
ctype_0 = (DummyStruct * 0)()
|
||||
mv = memoryview(ctype_0)
|
||||
|
||||
# convert the struct, and slice back out the field
|
||||
return _dtype_from_pep3118(mv.format)['a']
|
||||
|
||||
Unfortunately, this fails because:
|
||||
|
||||
* ctypes cannot handle length-0 arrays with PEP3118 (bpo-32782)
|
||||
* PEP3118 cannot represent unions, but both numpy and ctypes can
|
||||
* ctypes cannot handle big-endian structs with PEP3118 (bpo-32780)
|
||||
"""
|
||||
|
||||
# We delay-import ctypes for distributions that do not include it.
|
||||
# While this module is not used unless the user passes in ctypes
|
||||
# members, it is eagerly imported from numpy/core/__init__.py.
|
||||
import numpy as np
|
||||
|
||||
|
||||
def _from_ctypes_array(t):
|
||||
return np.dtype((dtype_from_ctypes_type(t._type_), (t._length_,)))
|
||||
|
||||
|
||||
def _from_ctypes_structure(t):
|
||||
for item in t._fields_:
|
||||
if len(item) > 2:
|
||||
raise TypeError(
|
||||
"ctypes bitfields have no dtype equivalent")
|
||||
|
||||
if hasattr(t, "_pack_"):
|
||||
import ctypes
|
||||
formats = []
|
||||
offsets = []
|
||||
names = []
|
||||
current_offset = 0
|
||||
for fname, ftyp in t._fields_:
|
||||
names.append(fname)
|
||||
formats.append(dtype_from_ctypes_type(ftyp))
|
||||
# Each type has a default offset, this is platform dependent for some types.
|
||||
effective_pack = min(t._pack_, ctypes.alignment(ftyp))
|
||||
current_offset = ((current_offset + effective_pack - 1) // effective_pack) * effective_pack
|
||||
offsets.append(current_offset)
|
||||
current_offset += ctypes.sizeof(ftyp)
|
||||
|
||||
return np.dtype(dict(
|
||||
formats=formats,
|
||||
offsets=offsets,
|
||||
names=names,
|
||||
itemsize=ctypes.sizeof(t)))
|
||||
else:
|
||||
fields = []
|
||||
for fname, ftyp in t._fields_:
|
||||
fields.append((fname, dtype_from_ctypes_type(ftyp)))
|
||||
|
||||
# by default, ctypes structs are aligned
|
||||
return np.dtype(fields, align=True)
|
||||
|
||||
|
||||
def _from_ctypes_scalar(t):
|
||||
"""
|
||||
Return the dtype type with endianness included if it's the case
|
||||
"""
|
||||
if getattr(t, '__ctype_be__', None) is t:
|
||||
return np.dtype('>' + t._type_)
|
||||
elif getattr(t, '__ctype_le__', None) is t:
|
||||
return np.dtype('<' + t._type_)
|
||||
else:
|
||||
return np.dtype(t._type_)
|
||||
|
||||
|
||||
def _from_ctypes_union(t):
|
||||
import ctypes
|
||||
formats = []
|
||||
offsets = []
|
||||
names = []
|
||||
for fname, ftyp in t._fields_:
|
||||
names.append(fname)
|
||||
formats.append(dtype_from_ctypes_type(ftyp))
|
||||
offsets.append(0) # Union fields are offset to 0
|
||||
|
||||
return np.dtype(dict(
|
||||
formats=formats,
|
||||
offsets=offsets,
|
||||
names=names,
|
||||
itemsize=ctypes.sizeof(t)))
|
||||
|
||||
|
||||
def dtype_from_ctypes_type(t):
|
||||
"""
|
||||
Construct a dtype object from a ctypes type
|
||||
"""
|
||||
import _ctypes
|
||||
if issubclass(t, _ctypes.Array):
|
||||
return _from_ctypes_array(t)
|
||||
elif issubclass(t, _ctypes._Pointer):
|
||||
raise TypeError("ctypes pointers have no dtype equivalent")
|
||||
elif issubclass(t, _ctypes.Structure):
|
||||
return _from_ctypes_structure(t)
|
||||
elif issubclass(t, _ctypes.Union):
|
||||
return _from_ctypes_union(t)
|
||||
elif isinstance(getattr(t, '_type_', None), str):
|
||||
return _from_ctypes_scalar(t)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
"Unknown ctypes type {}".format(t.__name__))
|
@ -0,0 +1,197 @@
|
||||
"""
|
||||
Various richly-typed exceptions, that also help us deal with string formatting
|
||||
in python where it's easier.
|
||||
|
||||
By putting the formatting in `__str__`, we also avoid paying the cost for
|
||||
users who silence the exceptions.
|
||||
"""
|
||||
from numpy.core.overrides import set_module
|
||||
|
||||
def _unpack_tuple(tup):
|
||||
if len(tup) == 1:
|
||||
return tup[0]
|
||||
else:
|
||||
return tup
|
||||
|
||||
|
||||
def _display_as_base(cls):
|
||||
"""
|
||||
A decorator that makes an exception class look like its base.
|
||||
|
||||
We use this to hide subclasses that are implementation details - the user
|
||||
should catch the base type, which is what the traceback will show them.
|
||||
|
||||
Classes decorated with this decorator are subject to removal without a
|
||||
deprecation warning.
|
||||
"""
|
||||
assert issubclass(cls, Exception)
|
||||
cls.__name__ = cls.__base__.__name__
|
||||
return cls
|
||||
|
||||
|
||||
class UFuncTypeError(TypeError):
|
||||
""" Base class for all ufunc exceptions """
|
||||
def __init__(self, ufunc):
|
||||
self.ufunc = ufunc
|
||||
|
||||
|
||||
@_display_as_base
|
||||
class _UFuncBinaryResolutionError(UFuncTypeError):
|
||||
""" Thrown when a binary resolution fails """
|
||||
def __init__(self, ufunc, dtypes):
|
||||
super().__init__(ufunc)
|
||||
self.dtypes = tuple(dtypes)
|
||||
assert len(self.dtypes) == 2
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
"ufunc {!r} cannot use operands with types {!r} and {!r}"
|
||||
).format(
|
||||
self.ufunc.__name__, *self.dtypes
|
||||
)
|
||||
|
||||
|
||||
@_display_as_base
|
||||
class _UFuncNoLoopError(UFuncTypeError):
|
||||
""" Thrown when a ufunc loop cannot be found """
|
||||
def __init__(self, ufunc, dtypes):
|
||||
super().__init__(ufunc)
|
||||
self.dtypes = tuple(dtypes)
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
"ufunc {!r} did not contain a loop with signature matching types "
|
||||
"{!r} -> {!r}"
|
||||
).format(
|
||||
self.ufunc.__name__,
|
||||
_unpack_tuple(self.dtypes[:self.ufunc.nin]),
|
||||
_unpack_tuple(self.dtypes[self.ufunc.nin:])
|
||||
)
|
||||
|
||||
|
||||
@_display_as_base
|
||||
class _UFuncCastingError(UFuncTypeError):
|
||||
def __init__(self, ufunc, casting, from_, to):
|
||||
super().__init__(ufunc)
|
||||
self.casting = casting
|
||||
self.from_ = from_
|
||||
self.to = to
|
||||
|
||||
|
||||
@_display_as_base
|
||||
class _UFuncInputCastingError(_UFuncCastingError):
|
||||
""" Thrown when a ufunc input cannot be casted """
|
||||
def __init__(self, ufunc, casting, from_, to, i):
|
||||
super().__init__(ufunc, casting, from_, to)
|
||||
self.in_i = i
|
||||
|
||||
def __str__(self):
|
||||
# only show the number if more than one input exists
|
||||
i_str = "{} ".format(self.in_i) if self.ufunc.nin != 1 else ""
|
||||
return (
|
||||
"Cannot cast ufunc {!r} input {}from {!r} to {!r} with casting "
|
||||
"rule {!r}"
|
||||
).format(
|
||||
self.ufunc.__name__, i_str, self.from_, self.to, self.casting
|
||||
)
|
||||
|
||||
|
||||
@_display_as_base
|
||||
class _UFuncOutputCastingError(_UFuncCastingError):
|
||||
""" Thrown when a ufunc output cannot be casted """
|
||||
def __init__(self, ufunc, casting, from_, to, i):
|
||||
super().__init__(ufunc, casting, from_, to)
|
||||
self.out_i = i
|
||||
|
||||
def __str__(self):
|
||||
# only show the number if more than one output exists
|
||||
i_str = "{} ".format(self.out_i) if self.ufunc.nout != 1 else ""
|
||||
return (
|
||||
"Cannot cast ufunc {!r} output {}from {!r} to {!r} with casting "
|
||||
"rule {!r}"
|
||||
).format(
|
||||
self.ufunc.__name__, i_str, self.from_, self.to, self.casting
|
||||
)
|
||||
|
||||
|
||||
# Exception used in shares_memory()
|
||||
@set_module('numpy')
|
||||
class TooHardError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
@set_module('numpy')
|
||||
class AxisError(ValueError, IndexError):
|
||||
""" Axis supplied was invalid. """
|
||||
def __init__(self, axis, ndim=None, msg_prefix=None):
|
||||
# single-argument form just delegates to base class
|
||||
if ndim is None and msg_prefix is None:
|
||||
msg = axis
|
||||
|
||||
# do the string formatting here, to save work in the C code
|
||||
else:
|
||||
msg = ("axis {} is out of bounds for array of dimension {}"
|
||||
.format(axis, ndim))
|
||||
if msg_prefix is not None:
|
||||
msg = "{}: {}".format(msg_prefix, msg)
|
||||
|
||||
super().__init__(msg)
|
||||
|
||||
|
||||
@_display_as_base
|
||||
class _ArrayMemoryError(MemoryError):
|
||||
""" Thrown when an array cannot be allocated"""
|
||||
def __init__(self, shape, dtype):
|
||||
self.shape = shape
|
||||
self.dtype = dtype
|
||||
|
||||
@property
|
||||
def _total_size(self):
|
||||
num_bytes = self.dtype.itemsize
|
||||
for dim in self.shape:
|
||||
num_bytes *= dim
|
||||
return num_bytes
|
||||
|
||||
@staticmethod
|
||||
def _size_to_string(num_bytes):
|
||||
""" Convert a number of bytes into a binary size string """
|
||||
|
||||
# https://en.wikipedia.org/wiki/Binary_prefix
|
||||
LOG2_STEP = 10
|
||||
STEP = 1024
|
||||
units = ['bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB']
|
||||
|
||||
unit_i = max(num_bytes.bit_length() - 1, 1) // LOG2_STEP
|
||||
unit_val = 1 << (unit_i * LOG2_STEP)
|
||||
n_units = num_bytes / unit_val
|
||||
del unit_val
|
||||
|
||||
# ensure we pick a unit that is correct after rounding
|
||||
if round(n_units) == STEP:
|
||||
unit_i += 1
|
||||
n_units /= STEP
|
||||
|
||||
# deal with sizes so large that we don't have units for them
|
||||
if unit_i >= len(units):
|
||||
new_unit_i = len(units) - 1
|
||||
n_units *= 1 << ((unit_i - new_unit_i) * LOG2_STEP)
|
||||
unit_i = new_unit_i
|
||||
|
||||
unit_name = units[unit_i]
|
||||
# format with a sensible number of digits
|
||||
if unit_i == 0:
|
||||
# no decimal point on bytes
|
||||
return '{:.0f} {}'.format(n_units, unit_name)
|
||||
elif round(n_units) < 1000:
|
||||
# 3 significant figures, if none are dropped to the left of the .
|
||||
return '{:#.3g} {}'.format(n_units, unit_name)
|
||||
else:
|
||||
# just give all the digits otherwise
|
||||
return '{:#.0f} {}'.format(n_units, unit_name)
|
||||
|
||||
def __str__(self):
|
||||
size_str = self._size_to_string(self._total_size)
|
||||
return (
|
||||
"Unable to allocate {} for an array with shape {} and data type {}"
|
||||
.format(size_str, self.shape, self.dtype)
|
||||
)
|
@ -0,0 +1,910 @@
|
||||
"""
|
||||
A place for internal code
|
||||
|
||||
Some things are more easily handled Python.
|
||||
|
||||
"""
|
||||
import ast
|
||||
import re
|
||||
import sys
|
||||
import platform
|
||||
import warnings
|
||||
|
||||
from .multiarray import dtype, array, ndarray
|
||||
try:
|
||||
import ctypes
|
||||
except ImportError:
|
||||
ctypes = None
|
||||
|
||||
IS_PYPY = platform.python_implementation() == 'PyPy'
|
||||
|
||||
if sys.byteorder == 'little':
|
||||
_nbo = '<'
|
||||
else:
|
||||
_nbo = '>'
|
||||
|
||||
def _makenames_list(adict, align):
|
||||
allfields = []
|
||||
|
||||
for fname, obj in adict.items():
|
||||
n = len(obj)
|
||||
if not isinstance(obj, tuple) or n not in (2, 3):
|
||||
raise ValueError("entry not a 2- or 3- tuple")
|
||||
if n > 2 and obj[2] == fname:
|
||||
continue
|
||||
num = int(obj[1])
|
||||
if num < 0:
|
||||
raise ValueError("invalid offset.")
|
||||
format = dtype(obj[0], align=align)
|
||||
if n > 2:
|
||||
title = obj[2]
|
||||
else:
|
||||
title = None
|
||||
allfields.append((fname, format, num, title))
|
||||
# sort by offsets
|
||||
allfields.sort(key=lambda x: x[2])
|
||||
names = [x[0] for x in allfields]
|
||||
formats = [x[1] for x in allfields]
|
||||
offsets = [x[2] for x in allfields]
|
||||
titles = [x[3] for x in allfields]
|
||||
|
||||
return names, formats, offsets, titles
|
||||
|
||||
# Called in PyArray_DescrConverter function when
|
||||
# a dictionary without "names" and "formats"
|
||||
# fields is used as a data-type descriptor.
|
||||
def _usefields(adict, align):
|
||||
try:
|
||||
names = adict[-1]
|
||||
except KeyError:
|
||||
names = None
|
||||
if names is None:
|
||||
names, formats, offsets, titles = _makenames_list(adict, align)
|
||||
else:
|
||||
formats = []
|
||||
offsets = []
|
||||
titles = []
|
||||
for name in names:
|
||||
res = adict[name]
|
||||
formats.append(res[0])
|
||||
offsets.append(res[1])
|
||||
if len(res) > 2:
|
||||
titles.append(res[2])
|
||||
else:
|
||||
titles.append(None)
|
||||
|
||||
return dtype({"names": names,
|
||||
"formats": formats,
|
||||
"offsets": offsets,
|
||||
"titles": titles}, align)
|
||||
|
||||
|
||||
# construct an array_protocol descriptor list
|
||||
# from the fields attribute of a descriptor
|
||||
# This calls itself recursively but should eventually hit
|
||||
# a descriptor that has no fields and then return
|
||||
# a simple typestring
|
||||
|
||||
def _array_descr(descriptor):
|
||||
fields = descriptor.fields
|
||||
if fields is None:
|
||||
subdtype = descriptor.subdtype
|
||||
if subdtype is None:
|
||||
if descriptor.metadata is None:
|
||||
return descriptor.str
|
||||
else:
|
||||
new = descriptor.metadata.copy()
|
||||
if new:
|
||||
return (descriptor.str, new)
|
||||
else:
|
||||
return descriptor.str
|
||||
else:
|
||||
return (_array_descr(subdtype[0]), subdtype[1])
|
||||
|
||||
names = descriptor.names
|
||||
ordered_fields = [fields[x] + (x,) for x in names]
|
||||
result = []
|
||||
offset = 0
|
||||
for field in ordered_fields:
|
||||
if field[1] > offset:
|
||||
num = field[1] - offset
|
||||
result.append(('', f'|V{num}'))
|
||||
offset += num
|
||||
elif field[1] < offset:
|
||||
raise ValueError(
|
||||
"dtype.descr is not defined for types with overlapping or "
|
||||
"out-of-order fields")
|
||||
if len(field) > 3:
|
||||
name = (field[2], field[3])
|
||||
else:
|
||||
name = field[2]
|
||||
if field[0].subdtype:
|
||||
tup = (name, _array_descr(field[0].subdtype[0]),
|
||||
field[0].subdtype[1])
|
||||
else:
|
||||
tup = (name, _array_descr(field[0]))
|
||||
offset += field[0].itemsize
|
||||
result.append(tup)
|
||||
|
||||
if descriptor.itemsize > offset:
|
||||
num = descriptor.itemsize - offset
|
||||
result.append(('', f'|V{num}'))
|
||||
|
||||
return result
|
||||
|
||||
# Build a new array from the information in a pickle.
|
||||
# Note that the name numpy.core._internal._reconstruct is embedded in
|
||||
# pickles of ndarrays made with NumPy before release 1.0
|
||||
# so don't remove the name here, or you'll
|
||||
# break backward compatibility.
|
||||
def _reconstruct(subtype, shape, dtype):
|
||||
return ndarray.__new__(subtype, shape, dtype)
|
||||
|
||||
|
||||
# format_re was originally from numarray by J. Todd Miller
|
||||
|
||||
format_re = re.compile(r'(?P<order1>[<>|=]?)'
|
||||
r'(?P<repeats> *[(]?[ ,0-9]*[)]? *)'
|
||||
r'(?P<order2>[<>|=]?)'
|
||||
r'(?P<dtype>[A-Za-z0-9.?]*(?:\[[a-zA-Z0-9,.]+\])?)')
|
||||
sep_re = re.compile(r'\s*,\s*')
|
||||
space_re = re.compile(r'\s+$')
|
||||
|
||||
# astr is a string (perhaps comma separated)
|
||||
|
||||
_convorder = {'=': _nbo}
|
||||
|
||||
def _commastring(astr):
|
||||
startindex = 0
|
||||
result = []
|
||||
while startindex < len(astr):
|
||||
mo = format_re.match(astr, pos=startindex)
|
||||
try:
|
||||
(order1, repeats, order2, dtype) = mo.groups()
|
||||
except (TypeError, AttributeError):
|
||||
raise ValueError(
|
||||
f'format number {len(result)+1} of "{astr}" is not recognized'
|
||||
) from None
|
||||
startindex = mo.end()
|
||||
# Separator or ending padding
|
||||
if startindex < len(astr):
|
||||
if space_re.match(astr, pos=startindex):
|
||||
startindex = len(astr)
|
||||
else:
|
||||
mo = sep_re.match(astr, pos=startindex)
|
||||
if not mo:
|
||||
raise ValueError(
|
||||
'format number %d of "%s" is not recognized' %
|
||||
(len(result)+1, astr))
|
||||
startindex = mo.end()
|
||||
|
||||
if order2 == '':
|
||||
order = order1
|
||||
elif order1 == '':
|
||||
order = order2
|
||||
else:
|
||||
order1 = _convorder.get(order1, order1)
|
||||
order2 = _convorder.get(order2, order2)
|
||||
if (order1 != order2):
|
||||
raise ValueError(
|
||||
'inconsistent byte-order specification %s and %s' %
|
||||
(order1, order2))
|
||||
order = order1
|
||||
|
||||
if order in ('|', '=', _nbo):
|
||||
order = ''
|
||||
dtype = order + dtype
|
||||
if (repeats == ''):
|
||||
newitem = dtype
|
||||
else:
|
||||
newitem = (dtype, ast.literal_eval(repeats))
|
||||
result.append(newitem)
|
||||
|
||||
return result
|
||||
|
||||
class dummy_ctype:
|
||||
def __init__(self, cls):
|
||||
self._cls = cls
|
||||
def __mul__(self, other):
|
||||
return self
|
||||
def __call__(self, *other):
|
||||
return self._cls(other)
|
||||
def __eq__(self, other):
|
||||
return self._cls == other._cls
|
||||
def __ne__(self, other):
|
||||
return self._cls != other._cls
|
||||
|
||||
def _getintp_ctype():
|
||||
val = _getintp_ctype.cache
|
||||
if val is not None:
|
||||
return val
|
||||
if ctypes is None:
|
||||
import numpy as np
|
||||
val = dummy_ctype(np.intp)
|
||||
else:
|
||||
char = dtype('p').char
|
||||
if char == 'i':
|
||||
val = ctypes.c_int
|
||||
elif char == 'l':
|
||||
val = ctypes.c_long
|
||||
elif char == 'q':
|
||||
val = ctypes.c_longlong
|
||||
else:
|
||||
val = ctypes.c_long
|
||||
_getintp_ctype.cache = val
|
||||
return val
|
||||
_getintp_ctype.cache = None
|
||||
|
||||
# Used for .ctypes attribute of ndarray
|
||||
|
||||
class _missing_ctypes:
|
||||
def cast(self, num, obj):
|
||||
return num.value
|
||||
|
||||
class c_void_p:
|
||||
def __init__(self, ptr):
|
||||
self.value = ptr
|
||||
|
||||
|
||||
class _ctypes:
|
||||
def __init__(self, array, ptr=None):
|
||||
self._arr = array
|
||||
|
||||
if ctypes:
|
||||
self._ctypes = ctypes
|
||||
self._data = self._ctypes.c_void_p(ptr)
|
||||
else:
|
||||
# fake a pointer-like object that holds onto the reference
|
||||
self._ctypes = _missing_ctypes()
|
||||
self._data = self._ctypes.c_void_p(ptr)
|
||||
self._data._objects = array
|
||||
|
||||
if self._arr.ndim == 0:
|
||||
self._zerod = True
|
||||
else:
|
||||
self._zerod = False
|
||||
|
||||
def data_as(self, obj):
|
||||
"""
|
||||
Return the data pointer cast to a particular c-types object.
|
||||
For example, calling ``self._as_parameter_`` is equivalent to
|
||||
``self.data_as(ctypes.c_void_p)``. Perhaps you want to use the data as a
|
||||
pointer to a ctypes array of floating-point data:
|
||||
``self.data_as(ctypes.POINTER(ctypes.c_double))``.
|
||||
|
||||
The returned pointer will keep a reference to the array.
|
||||
"""
|
||||
# _ctypes.cast function causes a circular reference of self._data in
|
||||
# self._data._objects. Attributes of self._data cannot be released
|
||||
# until gc.collect is called. Make a copy of the pointer first then let
|
||||
# it hold the array reference. This is a workaround to circumvent the
|
||||
# CPython bug https://bugs.python.org/issue12836
|
||||
ptr = self._ctypes.cast(self._data, obj)
|
||||
ptr._arr = self._arr
|
||||
return ptr
|
||||
|
||||
def shape_as(self, obj):
|
||||
"""
|
||||
Return the shape tuple as an array of some other c-types
|
||||
type. For example: ``self.shape_as(ctypes.c_short)``.
|
||||
"""
|
||||
if self._zerod:
|
||||
return None
|
||||
return (obj*self._arr.ndim)(*self._arr.shape)
|
||||
|
||||
def strides_as(self, obj):
|
||||
"""
|
||||
Return the strides tuple as an array of some other
|
||||
c-types type. For example: ``self.strides_as(ctypes.c_longlong)``.
|
||||
"""
|
||||
if self._zerod:
|
||||
return None
|
||||
return (obj*self._arr.ndim)(*self._arr.strides)
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
"""
|
||||
A pointer to the memory area of the array as a Python integer.
|
||||
This memory area may contain data that is not aligned, or not in correct
|
||||
byte-order. The memory area may not even be writeable. The array
|
||||
flags and data-type of this array should be respected when passing this
|
||||
attribute to arbitrary C-code to avoid trouble that can include Python
|
||||
crashing. User Beware! The value of this attribute is exactly the same
|
||||
as ``self._array_interface_['data'][0]``.
|
||||
|
||||
Note that unlike ``data_as``, a reference will not be kept to the array:
|
||||
code like ``ctypes.c_void_p((a + b).ctypes.data)`` will result in a
|
||||
pointer to a deallocated array, and should be spelt
|
||||
``(a + b).ctypes.data_as(ctypes.c_void_p)``
|
||||
"""
|
||||
return self._data.value
|
||||
|
||||
@property
|
||||
def shape(self):
|
||||
"""
|
||||
(c_intp*self.ndim): A ctypes array of length self.ndim where
|
||||
the basetype is the C-integer corresponding to ``dtype('p')`` on this
|
||||
platform. This base-type could be `ctypes.c_int`, `ctypes.c_long`, or
|
||||
`ctypes.c_longlong` depending on the platform.
|
||||
The c_intp type is defined accordingly in `numpy.ctypeslib`.
|
||||
The ctypes array contains the shape of the underlying array.
|
||||
"""
|
||||
return self.shape_as(_getintp_ctype())
|
||||
|
||||
@property
|
||||
def strides(self):
|
||||
"""
|
||||
(c_intp*self.ndim): A ctypes array of length self.ndim where
|
||||
the basetype is the same as for the shape attribute. This ctypes array
|
||||
contains the strides information from the underlying array. This strides
|
||||
information is important for showing how many bytes must be jumped to
|
||||
get to the next element in the array.
|
||||
"""
|
||||
return self.strides_as(_getintp_ctype())
|
||||
|
||||
@property
|
||||
def _as_parameter_(self):
|
||||
"""
|
||||
Overrides the ctypes semi-magic method
|
||||
|
||||
Enables `c_func(some_array.ctypes)`
|
||||
"""
|
||||
return self.data_as(ctypes.c_void_p)
|
||||
|
||||
# Numpy 1.21.0, 2021-05-18
|
||||
|
||||
def get_data(self):
|
||||
"""Deprecated getter for the `_ctypes.data` property.
|
||||
|
||||
.. deprecated:: 1.21
|
||||
"""
|
||||
warnings.warn('"get_data" is deprecated. Use "data" instead',
|
||||
DeprecationWarning, stacklevel=2)
|
||||
return self.data
|
||||
|
||||
def get_shape(self):
|
||||
"""Deprecated getter for the `_ctypes.shape` property.
|
||||
|
||||
.. deprecated:: 1.21
|
||||
"""
|
||||
warnings.warn('"get_shape" is deprecated. Use "shape" instead',
|
||||
DeprecationWarning, stacklevel=2)
|
||||
return self.shape
|
||||
|
||||
def get_strides(self):
|
||||
"""Deprecated getter for the `_ctypes.strides` property.
|
||||
|
||||
.. deprecated:: 1.21
|
||||
"""
|
||||
warnings.warn('"get_strides" is deprecated. Use "strides" instead',
|
||||
DeprecationWarning, stacklevel=2)
|
||||
return self.strides
|
||||
|
||||
def get_as_parameter(self):
|
||||
"""Deprecated getter for the `_ctypes._as_parameter_` property.
|
||||
|
||||
.. deprecated:: 1.21
|
||||
"""
|
||||
warnings.warn(
|
||||
'"get_as_parameter" is deprecated. Use "_as_parameter_" instead',
|
||||
DeprecationWarning, stacklevel=2,
|
||||
)
|
||||
return self._as_parameter_
|
||||
|
||||
|
||||
def _newnames(datatype, order):
|
||||
"""
|
||||
Given a datatype and an order object, return a new names tuple, with the
|
||||
order indicated
|
||||
"""
|
||||
oldnames = datatype.names
|
||||
nameslist = list(oldnames)
|
||||
if isinstance(order, str):
|
||||
order = [order]
|
||||
seen = set()
|
||||
if isinstance(order, (list, tuple)):
|
||||
for name in order:
|
||||
try:
|
||||
nameslist.remove(name)
|
||||
except ValueError:
|
||||
if name in seen:
|
||||
raise ValueError(f"duplicate field name: {name}") from None
|
||||
else:
|
||||
raise ValueError(f"unknown field name: {name}") from None
|
||||
seen.add(name)
|
||||
return tuple(list(order) + nameslist)
|
||||
raise ValueError(f"unsupported order value: {order}")
|
||||
|
||||
def _copy_fields(ary):
|
||||
"""Return copy of structured array with padding between fields removed.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ary : ndarray
|
||||
Structured array from which to remove padding bytes
|
||||
|
||||
Returns
|
||||
-------
|
||||
ary_copy : ndarray
|
||||
Copy of ary with padding bytes removed
|
||||
"""
|
||||
dt = ary.dtype
|
||||
copy_dtype = {'names': dt.names,
|
||||
'formats': [dt.fields[name][0] for name in dt.names]}
|
||||
return array(ary, dtype=copy_dtype, copy=True)
|
||||
|
||||
def _getfield_is_safe(oldtype, newtype, offset):
|
||||
""" Checks safety of getfield for object arrays.
|
||||
|
||||
As in _view_is_safe, we need to check that memory containing objects is not
|
||||
reinterpreted as a non-object datatype and vice versa.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
oldtype : data-type
|
||||
Data type of the original ndarray.
|
||||
newtype : data-type
|
||||
Data type of the field being accessed by ndarray.getfield
|
||||
offset : int
|
||||
Offset of the field being accessed by ndarray.getfield
|
||||
|
||||
Raises
|
||||
------
|
||||
TypeError
|
||||
If the field access is invalid
|
||||
|
||||
"""
|
||||
if newtype.hasobject or oldtype.hasobject:
|
||||
if offset == 0 and newtype == oldtype:
|
||||
return
|
||||
if oldtype.names is not None:
|
||||
for name in oldtype.names:
|
||||
if (oldtype.fields[name][1] == offset and
|
||||
oldtype.fields[name][0] == newtype):
|
||||
return
|
||||
raise TypeError("Cannot get/set field of an object array")
|
||||
return
|
||||
|
||||
def _view_is_safe(oldtype, newtype):
|
||||
""" Checks safety of a view involving object arrays, for example when
|
||||
doing::
|
||||
|
||||
np.zeros(10, dtype=oldtype).view(newtype)
|
||||
|
||||
Parameters
|
||||
----------
|
||||
oldtype : data-type
|
||||
Data type of original ndarray
|
||||
newtype : data-type
|
||||
Data type of the view
|
||||
|
||||
Raises
|
||||
------
|
||||
TypeError
|
||||
If the new type is incompatible with the old type.
|
||||
|
||||
"""
|
||||
|
||||
# if the types are equivalent, there is no problem.
|
||||
# for example: dtype((np.record, 'i4,i4')) == dtype((np.void, 'i4,i4'))
|
||||
if oldtype == newtype:
|
||||
return
|
||||
|
||||
if newtype.hasobject or oldtype.hasobject:
|
||||
raise TypeError("Cannot change data-type for object array.")
|
||||
return
|
||||
|
||||
# Given a string containing a PEP 3118 format specifier,
|
||||
# construct a NumPy dtype
|
||||
|
||||
_pep3118_native_map = {
|
||||
'?': '?',
|
||||
'c': 'S1',
|
||||
'b': 'b',
|
||||
'B': 'B',
|
||||
'h': 'h',
|
||||
'H': 'H',
|
||||
'i': 'i',
|
||||
'I': 'I',
|
||||
'l': 'l',
|
||||
'L': 'L',
|
||||
'q': 'q',
|
||||
'Q': 'Q',
|
||||
'e': 'e',
|
||||
'f': 'f',
|
||||
'd': 'd',
|
||||
'g': 'g',
|
||||
'Zf': 'F',
|
||||
'Zd': 'D',
|
||||
'Zg': 'G',
|
||||
's': 'S',
|
||||
'w': 'U',
|
||||
'O': 'O',
|
||||
'x': 'V', # padding
|
||||
}
|
||||
_pep3118_native_typechars = ''.join(_pep3118_native_map.keys())
|
||||
|
||||
_pep3118_standard_map = {
|
||||
'?': '?',
|
||||
'c': 'S1',
|
||||
'b': 'b',
|
||||
'B': 'B',
|
||||
'h': 'i2',
|
||||
'H': 'u2',
|
||||
'i': 'i4',
|
||||
'I': 'u4',
|
||||
'l': 'i4',
|
||||
'L': 'u4',
|
||||
'q': 'i8',
|
||||
'Q': 'u8',
|
||||
'e': 'f2',
|
||||
'f': 'f',
|
||||
'd': 'd',
|
||||
'Zf': 'F',
|
||||
'Zd': 'D',
|
||||
's': 'S',
|
||||
'w': 'U',
|
||||
'O': 'O',
|
||||
'x': 'V', # padding
|
||||
}
|
||||
_pep3118_standard_typechars = ''.join(_pep3118_standard_map.keys())
|
||||
|
||||
_pep3118_unsupported_map = {
|
||||
'u': 'UCS-2 strings',
|
||||
'&': 'pointers',
|
||||
't': 'bitfields',
|
||||
'X': 'function pointers',
|
||||
}
|
||||
|
||||
class _Stream:
|
||||
def __init__(self, s):
|
||||
self.s = s
|
||||
self.byteorder = '@'
|
||||
|
||||
def advance(self, n):
|
||||
res = self.s[:n]
|
||||
self.s = self.s[n:]
|
||||
return res
|
||||
|
||||
def consume(self, c):
|
||||
if self.s[:len(c)] == c:
|
||||
self.advance(len(c))
|
||||
return True
|
||||
return False
|
||||
|
||||
def consume_until(self, c):
|
||||
if callable(c):
|
||||
i = 0
|
||||
while i < len(self.s) and not c(self.s[i]):
|
||||
i = i + 1
|
||||
return self.advance(i)
|
||||
else:
|
||||
i = self.s.index(c)
|
||||
res = self.advance(i)
|
||||
self.advance(len(c))
|
||||
return res
|
||||
|
||||
@property
|
||||
def next(self):
|
||||
return self.s[0]
|
||||
|
||||
def __bool__(self):
|
||||
return bool(self.s)
|
||||
|
||||
|
||||
def _dtype_from_pep3118(spec):
|
||||
stream = _Stream(spec)
|
||||
dtype, align = __dtype_from_pep3118(stream, is_subdtype=False)
|
||||
return dtype
|
||||
|
||||
def __dtype_from_pep3118(stream, is_subdtype):
|
||||
field_spec = dict(
|
||||
names=[],
|
||||
formats=[],
|
||||
offsets=[],
|
||||
itemsize=0
|
||||
)
|
||||
offset = 0
|
||||
common_alignment = 1
|
||||
is_padding = False
|
||||
|
||||
# Parse spec
|
||||
while stream:
|
||||
value = None
|
||||
|
||||
# End of structure, bail out to upper level
|
||||
if stream.consume('}'):
|
||||
break
|
||||
|
||||
# Sub-arrays (1)
|
||||
shape = None
|
||||
if stream.consume('('):
|
||||
shape = stream.consume_until(')')
|
||||
shape = tuple(map(int, shape.split(',')))
|
||||
|
||||
# Byte order
|
||||
if stream.next in ('@', '=', '<', '>', '^', '!'):
|
||||
byteorder = stream.advance(1)
|
||||
if byteorder == '!':
|
||||
byteorder = '>'
|
||||
stream.byteorder = byteorder
|
||||
|
||||
# Byte order characters also control native vs. standard type sizes
|
||||
if stream.byteorder in ('@', '^'):
|
||||
type_map = _pep3118_native_map
|
||||
type_map_chars = _pep3118_native_typechars
|
||||
else:
|
||||
type_map = _pep3118_standard_map
|
||||
type_map_chars = _pep3118_standard_typechars
|
||||
|
||||
# Item sizes
|
||||
itemsize_str = stream.consume_until(lambda c: not c.isdigit())
|
||||
if itemsize_str:
|
||||
itemsize = int(itemsize_str)
|
||||
else:
|
||||
itemsize = 1
|
||||
|
||||
# Data types
|
||||
is_padding = False
|
||||
|
||||
if stream.consume('T{'):
|
||||
value, align = __dtype_from_pep3118(
|
||||
stream, is_subdtype=True)
|
||||
elif stream.next in type_map_chars:
|
||||
if stream.next == 'Z':
|
||||
typechar = stream.advance(2)
|
||||
else:
|
||||
typechar = stream.advance(1)
|
||||
|
||||
is_padding = (typechar == 'x')
|
||||
dtypechar = type_map[typechar]
|
||||
if dtypechar in 'USV':
|
||||
dtypechar += '%d' % itemsize
|
||||
itemsize = 1
|
||||
numpy_byteorder = {'@': '=', '^': '='}.get(
|
||||
stream.byteorder, stream.byteorder)
|
||||
value = dtype(numpy_byteorder + dtypechar)
|
||||
align = value.alignment
|
||||
elif stream.next in _pep3118_unsupported_map:
|
||||
desc = _pep3118_unsupported_map[stream.next]
|
||||
raise NotImplementedError(
|
||||
"Unrepresentable PEP 3118 data type {!r} ({})"
|
||||
.format(stream.next, desc))
|
||||
else:
|
||||
raise ValueError("Unknown PEP 3118 data type specifier %r" % stream.s)
|
||||
|
||||
#
|
||||
# Native alignment may require padding
|
||||
#
|
||||
# Here we assume that the presence of a '@' character implicitly implies
|
||||
# that the start of the array is *already* aligned.
|
||||
#
|
||||
extra_offset = 0
|
||||
if stream.byteorder == '@':
|
||||
start_padding = (-offset) % align
|
||||
intra_padding = (-value.itemsize) % align
|
||||
|
||||
offset += start_padding
|
||||
|
||||
if intra_padding != 0:
|
||||
if itemsize > 1 or (shape is not None and _prod(shape) > 1):
|
||||
# Inject internal padding to the end of the sub-item
|
||||
value = _add_trailing_padding(value, intra_padding)
|
||||
else:
|
||||
# We can postpone the injection of internal padding,
|
||||
# as the item appears at most once
|
||||
extra_offset += intra_padding
|
||||
|
||||
# Update common alignment
|
||||
common_alignment = _lcm(align, common_alignment)
|
||||
|
||||
# Convert itemsize to sub-array
|
||||
if itemsize != 1:
|
||||
value = dtype((value, (itemsize,)))
|
||||
|
||||
# Sub-arrays (2)
|
||||
if shape is not None:
|
||||
value = dtype((value, shape))
|
||||
|
||||
# Field name
|
||||
if stream.consume(':'):
|
||||
name = stream.consume_until(':')
|
||||
else:
|
||||
name = None
|
||||
|
||||
if not (is_padding and name is None):
|
||||
if name is not None and name in field_spec['names']:
|
||||
raise RuntimeError(f"Duplicate field name '{name}' in PEP3118 format")
|
||||
field_spec['names'].append(name)
|
||||
field_spec['formats'].append(value)
|
||||
field_spec['offsets'].append(offset)
|
||||
|
||||
offset += value.itemsize
|
||||
offset += extra_offset
|
||||
|
||||
field_spec['itemsize'] = offset
|
||||
|
||||
# extra final padding for aligned types
|
||||
if stream.byteorder == '@':
|
||||
field_spec['itemsize'] += (-offset) % common_alignment
|
||||
|
||||
# Check if this was a simple 1-item type, and unwrap it
|
||||
if (field_spec['names'] == [None]
|
||||
and field_spec['offsets'][0] == 0
|
||||
and field_spec['itemsize'] == field_spec['formats'][0].itemsize
|
||||
and not is_subdtype):
|
||||
ret = field_spec['formats'][0]
|
||||
else:
|
||||
_fix_names(field_spec)
|
||||
ret = dtype(field_spec)
|
||||
|
||||
# Finished
|
||||
return ret, common_alignment
|
||||
|
||||
def _fix_names(field_spec):
|
||||
""" Replace names which are None with the next unused f%d name """
|
||||
names = field_spec['names']
|
||||
for i, name in enumerate(names):
|
||||
if name is not None:
|
||||
continue
|
||||
|
||||
j = 0
|
||||
while True:
|
||||
name = f'f{j}'
|
||||
if name not in names:
|
||||
break
|
||||
j = j + 1
|
||||
names[i] = name
|
||||
|
||||
def _add_trailing_padding(value, padding):
|
||||
"""Inject the specified number of padding bytes at the end of a dtype"""
|
||||
if value.fields is None:
|
||||
field_spec = dict(
|
||||
names=['f0'],
|
||||
formats=[value],
|
||||
offsets=[0],
|
||||
itemsize=value.itemsize
|
||||
)
|
||||
else:
|
||||
fields = value.fields
|
||||
names = value.names
|
||||
field_spec = dict(
|
||||
names=names,
|
||||
formats=[fields[name][0] for name in names],
|
||||
offsets=[fields[name][1] for name in names],
|
||||
itemsize=value.itemsize
|
||||
)
|
||||
|
||||
field_spec['itemsize'] += padding
|
||||
return dtype(field_spec)
|
||||
|
||||
def _prod(a):
|
||||
p = 1
|
||||
for x in a:
|
||||
p *= x
|
||||
return p
|
||||
|
||||
def _gcd(a, b):
|
||||
"""Calculate the greatest common divisor of a and b"""
|
||||
while b:
|
||||
a, b = b, a % b
|
||||
return a
|
||||
|
||||
def _lcm(a, b):
|
||||
return a // _gcd(a, b) * b
|
||||
|
||||
def array_ufunc_errmsg_formatter(dummy, ufunc, method, *inputs, **kwargs):
|
||||
""" Format the error message for when __array_ufunc__ gives up. """
|
||||
args_string = ', '.join(['{!r}'.format(arg) for arg in inputs] +
|
||||
['{}={!r}'.format(k, v)
|
||||
for k, v in kwargs.items()])
|
||||
args = inputs + kwargs.get('out', ())
|
||||
types_string = ', '.join(repr(type(arg).__name__) for arg in args)
|
||||
return ('operand type(s) all returned NotImplemented from '
|
||||
'__array_ufunc__({!r}, {!r}, {}): {}'
|
||||
.format(ufunc, method, args_string, types_string))
|
||||
|
||||
|
||||
def array_function_errmsg_formatter(public_api, types):
|
||||
""" Format the error message for when __array_ufunc__ gives up. """
|
||||
func_name = '{}.{}'.format(public_api.__module__, public_api.__name__)
|
||||
return ("no implementation found for '{}' on types that implement "
|
||||
'__array_function__: {}'.format(func_name, list(types)))
|
||||
|
||||
|
||||
def _ufunc_doc_signature_formatter(ufunc):
|
||||
"""
|
||||
Builds a signature string which resembles PEP 457
|
||||
|
||||
This is used to construct the first line of the docstring
|
||||
"""
|
||||
|
||||
# input arguments are simple
|
||||
if ufunc.nin == 1:
|
||||
in_args = 'x'
|
||||
else:
|
||||
in_args = ', '.join(f'x{i+1}' for i in range(ufunc.nin))
|
||||
|
||||
# output arguments are both keyword or positional
|
||||
if ufunc.nout == 0:
|
||||
out_args = ', /, out=()'
|
||||
elif ufunc.nout == 1:
|
||||
out_args = ', /, out=None'
|
||||
else:
|
||||
out_args = '[, {positional}], / [, out={default}]'.format(
|
||||
positional=', '.join(
|
||||
'out{}'.format(i+1) for i in range(ufunc.nout)),
|
||||
default=repr((None,)*ufunc.nout)
|
||||
)
|
||||
|
||||
# keyword only args depend on whether this is a gufunc
|
||||
kwargs = (
|
||||
", casting='same_kind'"
|
||||
", order='K'"
|
||||
", dtype=None"
|
||||
", subok=True"
|
||||
)
|
||||
|
||||
# NOTE: gufuncs may or may not support the `axis` parameter
|
||||
if ufunc.signature is None:
|
||||
kwargs = f", where=True{kwargs}[, signature, extobj]"
|
||||
else:
|
||||
kwargs += "[, signature, extobj, axes, axis]"
|
||||
|
||||
# join all the parts together
|
||||
return '{name}({in_args}{out_args}, *{kwargs})'.format(
|
||||
name=ufunc.__name__,
|
||||
in_args=in_args,
|
||||
out_args=out_args,
|
||||
kwargs=kwargs
|
||||
)
|
||||
|
||||
|
||||
def npy_ctypes_check(cls):
|
||||
# determine if a class comes from ctypes, in order to work around
|
||||
# a bug in the buffer protocol for those objects, bpo-10746
|
||||
try:
|
||||
# ctypes class are new-style, so have an __mro__. This probably fails
|
||||
# for ctypes classes with multiple inheritance.
|
||||
if IS_PYPY:
|
||||
# (..., _ctypes.basics._CData, Bufferable, object)
|
||||
ctype_base = cls.__mro__[-3]
|
||||
else:
|
||||
# # (..., _ctypes._CData, object)
|
||||
ctype_base = cls.__mro__[-2]
|
||||
# right now, they're part of the _ctypes module
|
||||
return '_ctypes' in ctype_base.__module__
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
class recursive:
|
||||
'''
|
||||
A decorator class for recursive nested functions.
|
||||
Naive recursive nested functions hold a reference to themselves:
|
||||
|
||||
def outer(*args):
|
||||
def stringify_leaky(arg0, *arg1):
|
||||
if len(arg1) > 0:
|
||||
return stringify_leaky(*arg1) # <- HERE
|
||||
return str(arg0)
|
||||
stringify_leaky(*args)
|
||||
|
||||
This design pattern creates a reference cycle that is difficult for a
|
||||
garbage collector to resolve. The decorator class prevents the
|
||||
cycle by passing the nested function in as an argument `self`:
|
||||
|
||||
def outer(*args):
|
||||
@recursive
|
||||
def stringify(self, arg0, *arg1):
|
||||
if len(arg1) > 0:
|
||||
return self(*arg1)
|
||||
return str(arg0)
|
||||
stringify(*args)
|
||||
|
||||
'''
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self.func(self, *args, **kwargs)
|
||||
|
@ -0,0 +1,35 @@
|
||||
from typing import Any, TypeVar, Type, overload, Optional, Generic
|
||||
import ctypes as ct
|
||||
|
||||
from numpy import ndarray
|
||||
|
||||
_CastT = TypeVar("_CastT", bound=ct._CanCastTo) # Copied from `ctypes.cast`
|
||||
_CT = TypeVar("_CT", bound=ct._CData)
|
||||
_PT = TypeVar("_PT", bound=Optional[int])
|
||||
|
||||
# TODO: Let the likes of `shape_as` and `strides_as` return `None`
|
||||
# for 0D arrays once we've got shape-support
|
||||
|
||||
class _ctypes(Generic[_PT]):
|
||||
@overload
|
||||
def __new__(cls, array: ndarray[Any, Any], ptr: None = ...) -> _ctypes[None]: ...
|
||||
@overload
|
||||
def __new__(cls, array: ndarray[Any, Any], ptr: _PT) -> _ctypes[_PT]: ...
|
||||
|
||||
# NOTE: In practice `shape` and `strides` return one of the concrete
|
||||
# platform dependant array-types (`c_int`, `c_long` or `c_longlong`)
|
||||
# corresponding to C's `int_ptr_t`, as determined by `_getintp_ctype`
|
||||
# TODO: Hook this in to the mypy plugin so that a more appropiate
|
||||
# `ctypes._SimpleCData[int]` sub-type can be returned
|
||||
@property
|
||||
def data(self) -> _PT: ...
|
||||
@property
|
||||
def shape(self) -> ct.Array[ct.c_int64]: ...
|
||||
@property
|
||||
def strides(self) -> ct.Array[ct.c_int64]: ...
|
||||
@property
|
||||
def _as_parameter_(self) -> ct.c_void_p: ...
|
||||
|
||||
def data_as(self, obj: Type[_CastT]) -> _CastT: ...
|
||||
def shape_as(self, obj: Type[_CT]) -> ct.Array[_CT]: ...
|
||||
def strides_as(self, obj: Type[_CT]) -> ct.Array[_CT]: ...
|
@ -0,0 +1,290 @@
|
||||
"""
|
||||
Array methods which are called by both the C-code for the method
|
||||
and the Python code for the NumPy-namespace function
|
||||
|
||||
"""
|
||||
import warnings
|
||||
from contextlib import nullcontext
|
||||
|
||||
from numpy.core import multiarray as mu
|
||||
from numpy.core import umath as um
|
||||
from numpy.core.multiarray import asanyarray
|
||||
from numpy.core import numerictypes as nt
|
||||
from numpy.core import _exceptions
|
||||
from numpy._globals import _NoValue
|
||||
from numpy.compat import pickle, os_fspath
|
||||
|
||||
# save those O(100) nanoseconds!
|
||||
umr_maximum = um.maximum.reduce
|
||||
umr_minimum = um.minimum.reduce
|
||||
umr_sum = um.add.reduce
|
||||
umr_prod = um.multiply.reduce
|
||||
umr_any = um.logical_or.reduce
|
||||
umr_all = um.logical_and.reduce
|
||||
|
||||
# Complex types to -> (2,)float view for fast-path computation in _var()
|
||||
_complex_to_float = {
|
||||
nt.dtype(nt.csingle) : nt.dtype(nt.single),
|
||||
nt.dtype(nt.cdouble) : nt.dtype(nt.double),
|
||||
}
|
||||
# Special case for windows: ensure double takes precedence
|
||||
if nt.dtype(nt.longdouble) != nt.dtype(nt.double):
|
||||
_complex_to_float.update({
|
||||
nt.dtype(nt.clongdouble) : nt.dtype(nt.longdouble),
|
||||
})
|
||||
|
||||
# avoid keyword arguments to speed up parsing, saves about 15%-20% for very
|
||||
# small reductions
|
||||
def _amax(a, axis=None, out=None, keepdims=False,
|
||||
initial=_NoValue, where=True):
|
||||
return umr_maximum(a, axis, None, out, keepdims, initial, where)
|
||||
|
||||
def _amin(a, axis=None, out=None, keepdims=False,
|
||||
initial=_NoValue, where=True):
|
||||
return umr_minimum(a, axis, None, out, keepdims, initial, where)
|
||||
|
||||
def _sum(a, axis=None, dtype=None, out=None, keepdims=False,
|
||||
initial=_NoValue, where=True):
|
||||
return umr_sum(a, axis, dtype, out, keepdims, initial, where)
|
||||
|
||||
def _prod(a, axis=None, dtype=None, out=None, keepdims=False,
|
||||
initial=_NoValue, where=True):
|
||||
return umr_prod(a, axis, dtype, out, keepdims, initial, where)
|
||||
|
||||
def _any(a, axis=None, dtype=None, out=None, keepdims=False, *, where=True):
|
||||
# Parsing keyword arguments is currently fairly slow, so avoid it for now
|
||||
if where is True:
|
||||
return umr_any(a, axis, dtype, out, keepdims)
|
||||
return umr_any(a, axis, dtype, out, keepdims, where=where)
|
||||
|
||||
def _all(a, axis=None, dtype=None, out=None, keepdims=False, *, where=True):
|
||||
# Parsing keyword arguments is currently fairly slow, so avoid it for now
|
||||
if where is True:
|
||||
return umr_all(a, axis, dtype, out, keepdims)
|
||||
return umr_all(a, axis, dtype, out, keepdims, where=where)
|
||||
|
||||
def _count_reduce_items(arr, axis, keepdims=False, where=True):
|
||||
# fast-path for the default case
|
||||
if where is True:
|
||||
# no boolean mask given, calculate items according to axis
|
||||
if axis is None:
|
||||
axis = tuple(range(arr.ndim))
|
||||
elif not isinstance(axis, tuple):
|
||||
axis = (axis,)
|
||||
items = nt.intp(1)
|
||||
for ax in axis:
|
||||
items *= arr.shape[mu.normalize_axis_index(ax, arr.ndim)]
|
||||
else:
|
||||
# TODO: Optimize case when `where` is broadcast along a non-reduction
|
||||
# axis and full sum is more excessive than needed.
|
||||
|
||||
# guarded to protect circular imports
|
||||
from numpy.lib.stride_tricks import broadcast_to
|
||||
# count True values in (potentially broadcasted) boolean mask
|
||||
items = umr_sum(broadcast_to(where, arr.shape), axis, nt.intp, None,
|
||||
keepdims)
|
||||
return items
|
||||
|
||||
# Numpy 1.17.0, 2019-02-24
|
||||
# Various clip behavior deprecations, marked with _clip_dep as a prefix.
|
||||
|
||||
def _clip_dep_is_scalar_nan(a):
|
||||
# guarded to protect circular imports
|
||||
from numpy.core.fromnumeric import ndim
|
||||
if ndim(a) != 0:
|
||||
return False
|
||||
try:
|
||||
return um.isnan(a)
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
def _clip_dep_is_byte_swapped(a):
|
||||
if isinstance(a, mu.ndarray):
|
||||
return not a.dtype.isnative
|
||||
return False
|
||||
|
||||
def _clip_dep_invoke_with_casting(ufunc, *args, out=None, casting=None, **kwargs):
|
||||
# normal path
|
||||
if casting is not None:
|
||||
return ufunc(*args, out=out, casting=casting, **kwargs)
|
||||
|
||||
# try to deal with broken casting rules
|
||||
try:
|
||||
return ufunc(*args, out=out, **kwargs)
|
||||
except _exceptions._UFuncOutputCastingError as e:
|
||||
# Numpy 1.17.0, 2019-02-24
|
||||
warnings.warn(
|
||||
"Converting the output of clip from {!r} to {!r} is deprecated. "
|
||||
"Pass `casting=\"unsafe\"` explicitly to silence this warning, or "
|
||||
"correct the type of the variables.".format(e.from_, e.to),
|
||||
DeprecationWarning,
|
||||
stacklevel=2
|
||||
)
|
||||
return ufunc(*args, out=out, casting="unsafe", **kwargs)
|
||||
|
||||
def _clip(a, min=None, max=None, out=None, *, casting=None, **kwargs):
|
||||
if min is None and max is None:
|
||||
raise ValueError("One of max or min must be given")
|
||||
|
||||
# Numpy 1.17.0, 2019-02-24
|
||||
# This deprecation probably incurs a substantial slowdown for small arrays,
|
||||
# it will be good to get rid of it.
|
||||
if not _clip_dep_is_byte_swapped(a) and not _clip_dep_is_byte_swapped(out):
|
||||
using_deprecated_nan = False
|
||||
if _clip_dep_is_scalar_nan(min):
|
||||
min = -float('inf')
|
||||
using_deprecated_nan = True
|
||||
if _clip_dep_is_scalar_nan(max):
|
||||
max = float('inf')
|
||||
using_deprecated_nan = True
|
||||
if using_deprecated_nan:
|
||||
warnings.warn(
|
||||
"Passing `np.nan` to mean no clipping in np.clip has always "
|
||||
"been unreliable, and is now deprecated. "
|
||||
"In future, this will always return nan, like it already does "
|
||||
"when min or max are arrays that contain nan. "
|
||||
"To skip a bound, pass either None or an np.inf of an "
|
||||
"appropriate sign.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2
|
||||
)
|
||||
|
||||
if min is None:
|
||||
return _clip_dep_invoke_with_casting(
|
||||
um.minimum, a, max, out=out, casting=casting, **kwargs)
|
||||
elif max is None:
|
||||
return _clip_dep_invoke_with_casting(
|
||||
um.maximum, a, min, out=out, casting=casting, **kwargs)
|
||||
else:
|
||||
return _clip_dep_invoke_with_casting(
|
||||
um.clip, a, min, max, out=out, casting=casting, **kwargs)
|
||||
|
||||
def _mean(a, axis=None, dtype=None, out=None, keepdims=False, *, where=True):
|
||||
arr = asanyarray(a)
|
||||
|
||||
is_float16_result = False
|
||||
|
||||
rcount = _count_reduce_items(arr, axis, keepdims=keepdims, where=where)
|
||||
if rcount == 0 if where is True else umr_any(rcount == 0, axis=None):
|
||||
warnings.warn("Mean of empty slice.", RuntimeWarning, stacklevel=2)
|
||||
|
||||
# Cast bool, unsigned int, and int to float64 by default
|
||||
if dtype is None:
|
||||
if issubclass(arr.dtype.type, (nt.integer, nt.bool_)):
|
||||
dtype = mu.dtype('f8')
|
||||
elif issubclass(arr.dtype.type, nt.float16):
|
||||
dtype = mu.dtype('f4')
|
||||
is_float16_result = True
|
||||
|
||||
ret = umr_sum(arr, axis, dtype, out, keepdims, where=where)
|
||||
if isinstance(ret, mu.ndarray):
|
||||
ret = um.true_divide(
|
||||
ret, rcount, out=ret, casting='unsafe', subok=False)
|
||||
if is_float16_result and out is None:
|
||||
ret = arr.dtype.type(ret)
|
||||
elif hasattr(ret, 'dtype'):
|
||||
if is_float16_result:
|
||||
ret = arr.dtype.type(ret / rcount)
|
||||
else:
|
||||
ret = ret.dtype.type(ret / rcount)
|
||||
else:
|
||||
ret = ret / rcount
|
||||
|
||||
return ret
|
||||
|
||||
def _var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False, *,
|
||||
where=True):
|
||||
arr = asanyarray(a)
|
||||
|
||||
rcount = _count_reduce_items(arr, axis, keepdims=keepdims, where=where)
|
||||
# Make this warning show up on top.
|
||||
if ddof >= rcount if where is True else umr_any(ddof >= rcount, axis=None):
|
||||
warnings.warn("Degrees of freedom <= 0 for slice", RuntimeWarning,
|
||||
stacklevel=2)
|
||||
|
||||
# Cast bool, unsigned int, and int to float64 by default
|
||||
if dtype is None and issubclass(arr.dtype.type, (nt.integer, nt.bool_)):
|
||||
dtype = mu.dtype('f8')
|
||||
|
||||
# Compute the mean.
|
||||
# Note that if dtype is not of inexact type then arraymean will
|
||||
# not be either.
|
||||
arrmean = umr_sum(arr, axis, dtype, keepdims=True, where=where)
|
||||
# The shape of rcount has to match arrmean to not change the shape of out
|
||||
# in broadcasting. Otherwise, it cannot be stored back to arrmean.
|
||||
if rcount.ndim == 0:
|
||||
# fast-path for default case when where is True
|
||||
div = rcount
|
||||
else:
|
||||
# matching rcount to arrmean when where is specified as array
|
||||
div = rcount.reshape(arrmean.shape)
|
||||
if isinstance(arrmean, mu.ndarray):
|
||||
arrmean = um.true_divide(arrmean, div, out=arrmean, casting='unsafe',
|
||||
subok=False)
|
||||
else:
|
||||
arrmean = arrmean.dtype.type(arrmean / rcount)
|
||||
|
||||
# Compute sum of squared deviations from mean
|
||||
# Note that x may not be inexact and that we need it to be an array,
|
||||
# not a scalar.
|
||||
x = asanyarray(arr - arrmean)
|
||||
|
||||
if issubclass(arr.dtype.type, (nt.floating, nt.integer)):
|
||||
x = um.multiply(x, x, out=x)
|
||||
# Fast-paths for built-in complex types
|
||||
elif x.dtype in _complex_to_float:
|
||||
xv = x.view(dtype=(_complex_to_float[x.dtype], (2,)))
|
||||
um.multiply(xv, xv, out=xv)
|
||||
x = um.add(xv[..., 0], xv[..., 1], out=x.real).real
|
||||
# Most general case; includes handling object arrays containing imaginary
|
||||
# numbers and complex types with non-native byteorder
|
||||
else:
|
||||
x = um.multiply(x, um.conjugate(x), out=x).real
|
||||
|
||||
ret = umr_sum(x, axis, dtype, out, keepdims=keepdims, where=where)
|
||||
|
||||
# Compute degrees of freedom and make sure it is not negative.
|
||||
rcount = um.maximum(rcount - ddof, 0)
|
||||
|
||||
# divide by degrees of freedom
|
||||
if isinstance(ret, mu.ndarray):
|
||||
ret = um.true_divide(
|
||||
ret, rcount, out=ret, casting='unsafe', subok=False)
|
||||
elif hasattr(ret, 'dtype'):
|
||||
ret = ret.dtype.type(ret / rcount)
|
||||
else:
|
||||
ret = ret / rcount
|
||||
|
||||
return ret
|
||||
|
||||
def _std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False, *,
|
||||
where=True):
|
||||
ret = _var(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
|
||||
keepdims=keepdims, where=where)
|
||||
|
||||
if isinstance(ret, mu.ndarray):
|
||||
ret = um.sqrt(ret, out=ret)
|
||||
elif hasattr(ret, 'dtype'):
|
||||
ret = ret.dtype.type(um.sqrt(ret))
|
||||
else:
|
||||
ret = um.sqrt(ret)
|
||||
|
||||
return ret
|
||||
|
||||
def _ptp(a, axis=None, out=None, keepdims=False):
|
||||
return um.subtract(
|
||||
umr_maximum(a, axis, None, out, keepdims),
|
||||
umr_minimum(a, axis, None, None, keepdims),
|
||||
out
|
||||
)
|
||||
|
||||
def _dump(self, file, protocol=2):
|
||||
if hasattr(file, 'write'):
|
||||
ctx = nullcontext(file)
|
||||
else:
|
||||
ctx = open(os_fspath(file), "wb")
|
||||
with ctx as f:
|
||||
pickle.dump(self, f, protocol=protocol)
|
||||
|
||||
def _dumps(self, protocol=2):
|
||||
return pickle.dumps(self, protocol=protocol)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,100 @@
|
||||
"""
|
||||
String-handling utilities to avoid locale-dependence.
|
||||
|
||||
Used primarily to generate type name aliases.
|
||||
"""
|
||||
# "import string" is costly to import!
|
||||
# Construct the translation tables directly
|
||||
# "A" = chr(65), "a" = chr(97)
|
||||
_all_chars = [chr(_m) for _m in range(256)]
|
||||
_ascii_upper = _all_chars[65:65+26]
|
||||
_ascii_lower = _all_chars[97:97+26]
|
||||
LOWER_TABLE = "".join(_all_chars[:65] + _ascii_lower + _all_chars[65+26:])
|
||||
UPPER_TABLE = "".join(_all_chars[:97] + _ascii_upper + _all_chars[97+26:])
|
||||
|
||||
|
||||
def english_lower(s):
|
||||
""" Apply English case rules to convert ASCII strings to all lower case.
|
||||
|
||||
This is an internal utility function to replace calls to str.lower() such
|
||||
that we can avoid changing behavior with changing locales. In particular,
|
||||
Turkish has distinct dotted and dotless variants of the Latin letter "I" in
|
||||
both lowercase and uppercase. Thus, "I".lower() != "i" in a "tr" locale.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
s : str
|
||||
|
||||
Returns
|
||||
-------
|
||||
lowered : str
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from numpy.core.numerictypes import english_lower
|
||||
>>> english_lower('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_')
|
||||
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789_'
|
||||
>>> english_lower('')
|
||||
''
|
||||
"""
|
||||
lowered = s.translate(LOWER_TABLE)
|
||||
return lowered
|
||||
|
||||
|
||||
def english_upper(s):
|
||||
""" Apply English case rules to convert ASCII strings to all upper case.
|
||||
|
||||
This is an internal utility function to replace calls to str.upper() such
|
||||
that we can avoid changing behavior with changing locales. In particular,
|
||||
Turkish has distinct dotted and dotless variants of the Latin letter "I" in
|
||||
both lowercase and uppercase. Thus, "i".upper() != "I" in a "tr" locale.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
s : str
|
||||
|
||||
Returns
|
||||
-------
|
||||
uppered : str
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from numpy.core.numerictypes import english_upper
|
||||
>>> english_upper('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_')
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
|
||||
>>> english_upper('')
|
||||
''
|
||||
"""
|
||||
uppered = s.translate(UPPER_TABLE)
|
||||
return uppered
|
||||
|
||||
|
||||
def english_capitalize(s):
|
||||
""" Apply English case rules to convert the first character of an ASCII
|
||||
string to upper case.
|
||||
|
||||
This is an internal utility function to replace calls to str.capitalize()
|
||||
such that we can avoid changing behavior with changing locales.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
s : str
|
||||
|
||||
Returns
|
||||
-------
|
||||
capitalized : str
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from numpy.core.numerictypes import english_capitalize
|
||||
>>> english_capitalize('int8')
|
||||
'Int8'
|
||||
>>> english_capitalize('Int8')
|
||||
'Int8'
|
||||
>>> english_capitalize('')
|
||||
''
|
||||
"""
|
||||
if s:
|
||||
return english_upper(s[0]) + s[1:]
|
||||
else:
|
||||
return s
|
Binary file not shown.
@ -0,0 +1,244 @@
|
||||
"""
|
||||
Due to compatibility, numpy has a very large number of different naming
|
||||
conventions for the scalar types (those subclassing from `numpy.generic`).
|
||||
This file produces a convoluted set of dictionaries mapping names to types,
|
||||
and sometimes other mappings too.
|
||||
|
||||
.. data:: allTypes
|
||||
A dictionary of names to types that will be exposed as attributes through
|
||||
``np.core.numerictypes.*``
|
||||
|
||||
.. data:: sctypeDict
|
||||
Similar to `allTypes`, but maps a broader set of aliases to their types.
|
||||
|
||||
.. data:: sctypes
|
||||
A dictionary keyed by a "type group" string, providing a list of types
|
||||
under that group.
|
||||
|
||||
"""
|
||||
|
||||
from numpy.compat import unicode
|
||||
from numpy.core._string_helpers import english_lower
|
||||
from numpy.core.multiarray import typeinfo, dtype
|
||||
from numpy.core._dtype import _kind_name
|
||||
|
||||
|
||||
sctypeDict = {} # Contains all leaf-node scalar types with aliases
|
||||
allTypes = {} # Collect the types we will add to the module
|
||||
|
||||
|
||||
# separate the actual type info from the abstract base classes
|
||||
_abstract_types = {}
|
||||
_concrete_typeinfo = {}
|
||||
for k, v in typeinfo.items():
|
||||
# make all the keys lowercase too
|
||||
k = english_lower(k)
|
||||
if isinstance(v, type):
|
||||
_abstract_types[k] = v
|
||||
else:
|
||||
_concrete_typeinfo[k] = v
|
||||
|
||||
_concrete_types = {v.type for k, v in _concrete_typeinfo.items()}
|
||||
|
||||
|
||||
def _bits_of(obj):
|
||||
try:
|
||||
info = next(v for v in _concrete_typeinfo.values() if v.type is obj)
|
||||
except StopIteration:
|
||||
if obj in _abstract_types.values():
|
||||
msg = "Cannot count the bits of an abstract type"
|
||||
raise ValueError(msg) from None
|
||||
|
||||
# some third-party type - make a best-guess
|
||||
return dtype(obj).itemsize * 8
|
||||
else:
|
||||
return info.bits
|
||||
|
||||
|
||||
def bitname(obj):
|
||||
"""Return a bit-width name for a given type object"""
|
||||
bits = _bits_of(obj)
|
||||
dt = dtype(obj)
|
||||
char = dt.kind
|
||||
base = _kind_name(dt)
|
||||
|
||||
if base == 'object':
|
||||
bits = 0
|
||||
|
||||
if bits != 0:
|
||||
char = "%s%d" % (char, bits // 8)
|
||||
|
||||
return base, bits, char
|
||||
|
||||
|
||||
def _add_types():
|
||||
for name, info in _concrete_typeinfo.items():
|
||||
# define C-name and insert typenum and typechar references also
|
||||
allTypes[name] = info.type
|
||||
sctypeDict[name] = info.type
|
||||
sctypeDict[info.char] = info.type
|
||||
sctypeDict[info.num] = info.type
|
||||
|
||||
for name, cls in _abstract_types.items():
|
||||
allTypes[name] = cls
|
||||
_add_types()
|
||||
|
||||
# This is the priority order used to assign the bit-sized NPY_INTxx names, which
|
||||
# must match the order in npy_common.h in order for NPY_INTxx and np.intxx to be
|
||||
# consistent.
|
||||
# If two C types have the same size, then the earliest one in this list is used
|
||||
# as the sized name.
|
||||
_int_ctypes = ['long', 'longlong', 'int', 'short', 'byte']
|
||||
_uint_ctypes = list('u' + t for t in _int_ctypes)
|
||||
|
||||
def _add_aliases():
|
||||
for name, info in _concrete_typeinfo.items():
|
||||
# these are handled by _add_integer_aliases
|
||||
if name in _int_ctypes or name in _uint_ctypes:
|
||||
continue
|
||||
|
||||
# insert bit-width version for this class (if relevant)
|
||||
base, bit, char = bitname(info.type)
|
||||
|
||||
myname = "%s%d" % (base, bit)
|
||||
|
||||
# ensure that (c)longdouble does not overwrite the aliases assigned to
|
||||
# (c)double
|
||||
if name in ('longdouble', 'clongdouble') and myname in allTypes:
|
||||
continue
|
||||
|
||||
allTypes[myname] = info.type
|
||||
|
||||
# add mapping for both the bit name and the numarray name
|
||||
sctypeDict[myname] = info.type
|
||||
|
||||
# add forward, reverse, and string mapping to numarray
|
||||
sctypeDict[char] = info.type
|
||||
|
||||
# Add deprecated numeric-style type aliases manually, at some point
|
||||
# we may want to deprecate the lower case "bytes0" version as well.
|
||||
for name in ["Bytes0", "Datetime64", "Str0", "Uint32", "Uint64"]:
|
||||
if english_lower(name) not in allTypes:
|
||||
# Only one of Uint32 or Uint64, aliases of `np.uintp`, was (and is) defined, note that this
|
||||
# is not UInt32/UInt64 (capital i), which is removed.
|
||||
continue
|
||||
allTypes[name] = allTypes[english_lower(name)]
|
||||
sctypeDict[name] = sctypeDict[english_lower(name)]
|
||||
|
||||
_add_aliases()
|
||||
|
||||
def _add_integer_aliases():
|
||||
seen_bits = set()
|
||||
for i_ctype, u_ctype in zip(_int_ctypes, _uint_ctypes):
|
||||
i_info = _concrete_typeinfo[i_ctype]
|
||||
u_info = _concrete_typeinfo[u_ctype]
|
||||
bits = i_info.bits # same for both
|
||||
|
||||
for info, charname, intname in [
|
||||
(i_info,'i%d' % (bits//8,), 'int%d' % bits),
|
||||
(u_info,'u%d' % (bits//8,), 'uint%d' % bits)]:
|
||||
if bits not in seen_bits:
|
||||
# sometimes two different types have the same number of bits
|
||||
# if so, the one iterated over first takes precedence
|
||||
allTypes[intname] = info.type
|
||||
sctypeDict[intname] = info.type
|
||||
sctypeDict[charname] = info.type
|
||||
|
||||
seen_bits.add(bits)
|
||||
|
||||
_add_integer_aliases()
|
||||
|
||||
# We use these later
|
||||
void = allTypes['void']
|
||||
|
||||
#
|
||||
# Rework the Python names (so that float and complex and int are consistent
|
||||
# with Python usage)
|
||||
#
|
||||
def _set_up_aliases():
|
||||
type_pairs = [('complex_', 'cdouble'),
|
||||
('int0', 'intp'),
|
||||
('uint0', 'uintp'),
|
||||
('single', 'float'),
|
||||
('csingle', 'cfloat'),
|
||||
('singlecomplex', 'cfloat'),
|
||||
('float_', 'double'),
|
||||
('intc', 'int'),
|
||||
('uintc', 'uint'),
|
||||
('int_', 'long'),
|
||||
('uint', 'ulong'),
|
||||
('cfloat', 'cdouble'),
|
||||
('longfloat', 'longdouble'),
|
||||
('clongfloat', 'clongdouble'),
|
||||
('longcomplex', 'clongdouble'),
|
||||
('bool_', 'bool'),
|
||||
('bytes_', 'string'),
|
||||
('string_', 'string'),
|
||||
('str_', 'unicode'),
|
||||
('unicode_', 'unicode'),
|
||||
('object_', 'object')]
|
||||
for alias, t in type_pairs:
|
||||
allTypes[alias] = allTypes[t]
|
||||
sctypeDict[alias] = sctypeDict[t]
|
||||
# Remove aliases overriding python types and modules
|
||||
to_remove = ['ulong', 'object', 'int', 'float',
|
||||
'complex', 'bool', 'string', 'datetime', 'timedelta',
|
||||
'bytes', 'str']
|
||||
|
||||
for t in to_remove:
|
||||
try:
|
||||
del allTypes[t]
|
||||
del sctypeDict[t]
|
||||
except KeyError:
|
||||
pass
|
||||
_set_up_aliases()
|
||||
|
||||
|
||||
sctypes = {'int': [],
|
||||
'uint':[],
|
||||
'float':[],
|
||||
'complex':[],
|
||||
'others':[bool, object, bytes, unicode, void]}
|
||||
|
||||
def _add_array_type(typename, bits):
|
||||
try:
|
||||
t = allTypes['%s%d' % (typename, bits)]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
sctypes[typename].append(t)
|
||||
|
||||
def _set_array_types():
|
||||
ibytes = [1, 2, 4, 8, 16, 32, 64]
|
||||
fbytes = [2, 4, 8, 10, 12, 16, 32, 64]
|
||||
for bytes in ibytes:
|
||||
bits = 8*bytes
|
||||
_add_array_type('int', bits)
|
||||
_add_array_type('uint', bits)
|
||||
for bytes in fbytes:
|
||||
bits = 8*bytes
|
||||
_add_array_type('float', bits)
|
||||
_add_array_type('complex', 2*bits)
|
||||
_gi = dtype('p')
|
||||
if _gi.type not in sctypes['int']:
|
||||
indx = 0
|
||||
sz = _gi.itemsize
|
||||
_lst = sctypes['int']
|
||||
while (indx < len(_lst) and sz >= _lst[indx](0).itemsize):
|
||||
indx += 1
|
||||
sctypes['int'].insert(indx, _gi.type)
|
||||
sctypes['uint'].insert(indx, dtype('P').type)
|
||||
_set_array_types()
|
||||
|
||||
|
||||
# Add additional strings to the sctypeDict
|
||||
_toadd = ['int', 'float', 'complex', 'bool', 'object',
|
||||
'str', 'bytes', ('a', 'bytes_')]
|
||||
|
||||
for name in _toadd:
|
||||
if isinstance(name, tuple):
|
||||
sctypeDict[name[0]] = allTypes[name[1]]
|
||||
else:
|
||||
sctypeDict[name] = allTypes['%s_' % name]
|
||||
|
||||
del _toadd, name
|
@ -0,0 +1,19 @@
|
||||
import sys
|
||||
from typing import Dict, Union, Type, List
|
||||
|
||||
from numpy import generic, signedinteger, unsignedinteger, floating, complexfloating
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from typing import TypedDict
|
||||
else:
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
class _SCTypes(TypedDict):
|
||||
int: List[Type[signedinteger]]
|
||||
uint: List[Type[unsignedinteger]]
|
||||
float: List[Type[floating]]
|
||||
complex: List[Type[complexfloating]]
|
||||
others: List[type]
|
||||
|
||||
sctypeDict: Dict[Union[int, str], Type[generic]]
|
||||
sctypes: _SCTypes
|
@ -0,0 +1,446 @@
|
||||
"""
|
||||
Functions for changing global ufunc configuration
|
||||
|
||||
This provides helpers which wrap `umath.geterrobj` and `umath.seterrobj`
|
||||
"""
|
||||
import collections.abc
|
||||
import contextlib
|
||||
|
||||
from .overrides import set_module
|
||||
from .umath import (
|
||||
UFUNC_BUFSIZE_DEFAULT,
|
||||
ERR_IGNORE, ERR_WARN, ERR_RAISE, ERR_CALL, ERR_PRINT, ERR_LOG, ERR_DEFAULT,
|
||||
SHIFT_DIVIDEBYZERO, SHIFT_OVERFLOW, SHIFT_UNDERFLOW, SHIFT_INVALID,
|
||||
)
|
||||
from . import umath
|
||||
|
||||
__all__ = [
|
||||
"seterr", "geterr", "setbufsize", "getbufsize", "seterrcall", "geterrcall",
|
||||
"errstate",
|
||||
]
|
||||
|
||||
_errdict = {"ignore": ERR_IGNORE,
|
||||
"warn": ERR_WARN,
|
||||
"raise": ERR_RAISE,
|
||||
"call": ERR_CALL,
|
||||
"print": ERR_PRINT,
|
||||
"log": ERR_LOG}
|
||||
|
||||
_errdict_rev = {value: key for key, value in _errdict.items()}
|
||||
|
||||
|
||||
@set_module('numpy')
|
||||
def seterr(all=None, divide=None, over=None, under=None, invalid=None):
|
||||
"""
|
||||
Set how floating-point errors are handled.
|
||||
|
||||
Note that operations on integer scalar types (such as `int16`) are
|
||||
handled like floating point, and are affected by these settings.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
all : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
|
||||
Set treatment for all types of floating-point errors at once:
|
||||
|
||||
- ignore: Take no action when the exception occurs.
|
||||
- warn: Print a `RuntimeWarning` (via the Python `warnings` module).
|
||||
- raise: Raise a `FloatingPointError`.
|
||||
- call: Call a function specified using the `seterrcall` function.
|
||||
- print: Print a warning directly to ``stdout``.
|
||||
- log: Record error in a Log object specified by `seterrcall`.
|
||||
|
||||
The default is not to change the current behavior.
|
||||
divide : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
|
||||
Treatment for division by zero.
|
||||
over : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
|
||||
Treatment for floating-point overflow.
|
||||
under : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
|
||||
Treatment for floating-point underflow.
|
||||
invalid : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
|
||||
Treatment for invalid floating-point operation.
|
||||
|
||||
Returns
|
||||
-------
|
||||
old_settings : dict
|
||||
Dictionary containing the old settings.
|
||||
|
||||
See also
|
||||
--------
|
||||
seterrcall : Set a callback function for the 'call' mode.
|
||||
geterr, geterrcall, errstate
|
||||
|
||||
Notes
|
||||
-----
|
||||
The floating-point exceptions are defined in the IEEE 754 standard [1]_:
|
||||
|
||||
- Division by zero: infinite result obtained from finite numbers.
|
||||
- Overflow: result too large to be expressed.
|
||||
- Underflow: result so close to zero that some precision
|
||||
was lost.
|
||||
- Invalid operation: result is not an expressible number, typically
|
||||
indicates that a NaN was produced.
|
||||
|
||||
.. [1] https://en.wikipedia.org/wiki/IEEE_754
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> old_settings = np.seterr(all='ignore') #seterr to known value
|
||||
>>> np.seterr(over='raise')
|
||||
{'divide': 'ignore', 'over': 'ignore', 'under': 'ignore', 'invalid': 'ignore'}
|
||||
>>> np.seterr(**old_settings) # reset to default
|
||||
{'divide': 'ignore', 'over': 'raise', 'under': 'ignore', 'invalid': 'ignore'}
|
||||
|
||||
>>> np.int16(32000) * np.int16(3)
|
||||
30464
|
||||
>>> old_settings = np.seterr(all='warn', over='raise')
|
||||
>>> np.int16(32000) * np.int16(3)
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
FloatingPointError: overflow encountered in short_scalars
|
||||
|
||||
>>> old_settings = np.seterr(all='print')
|
||||
>>> np.geterr()
|
||||
{'divide': 'print', 'over': 'print', 'under': 'print', 'invalid': 'print'}
|
||||
>>> np.int16(32000) * np.int16(3)
|
||||
30464
|
||||
|
||||
"""
|
||||
|
||||
pyvals = umath.geterrobj()
|
||||
old = geterr()
|
||||
|
||||
if divide is None:
|
||||
divide = all or old['divide']
|
||||
if over is None:
|
||||
over = all or old['over']
|
||||
if under is None:
|
||||
under = all or old['under']
|
||||
if invalid is None:
|
||||
invalid = all or old['invalid']
|
||||
|
||||
maskvalue = ((_errdict[divide] << SHIFT_DIVIDEBYZERO) +
|
||||
(_errdict[over] << SHIFT_OVERFLOW) +
|
||||
(_errdict[under] << SHIFT_UNDERFLOW) +
|
||||
(_errdict[invalid] << SHIFT_INVALID))
|
||||
|
||||
pyvals[1] = maskvalue
|
||||
umath.seterrobj(pyvals)
|
||||
return old
|
||||
|
||||
|
||||
@set_module('numpy')
|
||||
def geterr():
|
||||
"""
|
||||
Get the current way of handling floating-point errors.
|
||||
|
||||
Returns
|
||||
-------
|
||||
res : dict
|
||||
A dictionary with keys "divide", "over", "under", and "invalid",
|
||||
whose values are from the strings "ignore", "print", "log", "warn",
|
||||
"raise", and "call". The keys represent possible floating-point
|
||||
exceptions, and the values define how these exceptions are handled.
|
||||
|
||||
See Also
|
||||
--------
|
||||
geterrcall, seterr, seterrcall
|
||||
|
||||
Notes
|
||||
-----
|
||||
For complete documentation of the types of floating-point exceptions and
|
||||
treatment options, see `seterr`.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> np.geterr()
|
||||
{'divide': 'warn', 'over': 'warn', 'under': 'ignore', 'invalid': 'warn'}
|
||||
>>> np.arange(3.) / np.arange(3.)
|
||||
array([nan, 1., 1.])
|
||||
|
||||
>>> oldsettings = np.seterr(all='warn', over='raise')
|
||||
>>> np.geterr()
|
||||
{'divide': 'warn', 'over': 'raise', 'under': 'warn', 'invalid': 'warn'}
|
||||
>>> np.arange(3.) / np.arange(3.)
|
||||
array([nan, 1., 1.])
|
||||
|
||||
"""
|
||||
maskvalue = umath.geterrobj()[1]
|
||||
mask = 7
|
||||
res = {}
|
||||
val = (maskvalue >> SHIFT_DIVIDEBYZERO) & mask
|
||||
res['divide'] = _errdict_rev[val]
|
||||
val = (maskvalue >> SHIFT_OVERFLOW) & mask
|
||||
res['over'] = _errdict_rev[val]
|
||||
val = (maskvalue >> SHIFT_UNDERFLOW) & mask
|
||||
res['under'] = _errdict_rev[val]
|
||||
val = (maskvalue >> SHIFT_INVALID) & mask
|
||||
res['invalid'] = _errdict_rev[val]
|
||||
return res
|
||||
|
||||
|
||||
@set_module('numpy')
|
||||
def setbufsize(size):
|
||||
"""
|
||||
Set the size of the buffer used in ufuncs.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
size : int
|
||||
Size of buffer.
|
||||
|
||||
"""
|
||||
if size > 10e6:
|
||||
raise ValueError("Buffer size, %s, is too big." % size)
|
||||
if size < 5:
|
||||
raise ValueError("Buffer size, %s, is too small." % size)
|
||||
if size % 16 != 0:
|
||||
raise ValueError("Buffer size, %s, is not a multiple of 16." % size)
|
||||
|
||||
pyvals = umath.geterrobj()
|
||||
old = getbufsize()
|
||||
pyvals[0] = size
|
||||
umath.seterrobj(pyvals)
|
||||
return old
|
||||
|
||||
|
||||
@set_module('numpy')
|
||||
def getbufsize():
|
||||
"""
|
||||
Return the size of the buffer used in ufuncs.
|
||||
|
||||
Returns
|
||||
-------
|
||||
getbufsize : int
|
||||
Size of ufunc buffer in bytes.
|
||||
|
||||
"""
|
||||
return umath.geterrobj()[0]
|
||||
|
||||
|
||||
@set_module('numpy')
|
||||
def seterrcall(func):
|
||||
"""
|
||||
Set the floating-point error callback function or log object.
|
||||
|
||||
There are two ways to capture floating-point error messages. The first
|
||||
is to set the error-handler to 'call', using `seterr`. Then, set
|
||||
the function to call using this function.
|
||||
|
||||
The second is to set the error-handler to 'log', using `seterr`.
|
||||
Floating-point errors then trigger a call to the 'write' method of
|
||||
the provided object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
func : callable f(err, flag) or object with write method
|
||||
Function to call upon floating-point errors ('call'-mode) or
|
||||
object whose 'write' method is used to log such message ('log'-mode).
|
||||
|
||||
The call function takes two arguments. The first is a string describing
|
||||
the type of error (such as "divide by zero", "overflow", "underflow",
|
||||
or "invalid value"), and the second is the status flag. The flag is a
|
||||
byte, whose four least-significant bits indicate the type of error, one
|
||||
of "divide", "over", "under", "invalid"::
|
||||
|
||||
[0 0 0 0 divide over under invalid]
|
||||
|
||||
In other words, ``flags = divide + 2*over + 4*under + 8*invalid``.
|
||||
|
||||
If an object is provided, its write method should take one argument,
|
||||
a string.
|
||||
|
||||
Returns
|
||||
-------
|
||||
h : callable, log instance or None
|
||||
The old error handler.
|
||||
|
||||
See Also
|
||||
--------
|
||||
seterr, geterr, geterrcall
|
||||
|
||||
Examples
|
||||
--------
|
||||
Callback upon error:
|
||||
|
||||
>>> def err_handler(type, flag):
|
||||
... print("Floating point error (%s), with flag %s" % (type, flag))
|
||||
...
|
||||
|
||||
>>> saved_handler = np.seterrcall(err_handler)
|
||||
>>> save_err = np.seterr(all='call')
|
||||
|
||||
>>> np.array([1, 2, 3]) / 0.0
|
||||
Floating point error (divide by zero), with flag 1
|
||||
array([inf, inf, inf])
|
||||
|
||||
>>> np.seterrcall(saved_handler)
|
||||
<function err_handler at 0x...>
|
||||
>>> np.seterr(**save_err)
|
||||
{'divide': 'call', 'over': 'call', 'under': 'call', 'invalid': 'call'}
|
||||
|
||||
Log error message:
|
||||
|
||||
>>> class Log:
|
||||
... def write(self, msg):
|
||||
... print("LOG: %s" % msg)
|
||||
...
|
||||
|
||||
>>> log = Log()
|
||||
>>> saved_handler = np.seterrcall(log)
|
||||
>>> save_err = np.seterr(all='log')
|
||||
|
||||
>>> np.array([1, 2, 3]) / 0.0
|
||||
LOG: Warning: divide by zero encountered in true_divide
|
||||
array([inf, inf, inf])
|
||||
|
||||
>>> np.seterrcall(saved_handler)
|
||||
<numpy.core.numeric.Log object at 0x...>
|
||||
>>> np.seterr(**save_err)
|
||||
{'divide': 'log', 'over': 'log', 'under': 'log', 'invalid': 'log'}
|
||||
|
||||
"""
|
||||
if func is not None and not isinstance(func, collections.abc.Callable):
|
||||
if (not hasattr(func, 'write') or
|
||||
not isinstance(func.write, collections.abc.Callable)):
|
||||
raise ValueError("Only callable can be used as callback")
|
||||
pyvals = umath.geterrobj()
|
||||
old = geterrcall()
|
||||
pyvals[2] = func
|
||||
umath.seterrobj(pyvals)
|
||||
return old
|
||||
|
||||
|
||||
@set_module('numpy')
|
||||
def geterrcall():
|
||||
"""
|
||||
Return the current callback function used on floating-point errors.
|
||||
|
||||
When the error handling for a floating-point error (one of "divide",
|
||||
"over", "under", or "invalid") is set to 'call' or 'log', the function
|
||||
that is called or the log instance that is written to is returned by
|
||||
`geterrcall`. This function or log instance has been set with
|
||||
`seterrcall`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
errobj : callable, log instance or None
|
||||
The current error handler. If no handler was set through `seterrcall`,
|
||||
``None`` is returned.
|
||||
|
||||
See Also
|
||||
--------
|
||||
seterrcall, seterr, geterr
|
||||
|
||||
Notes
|
||||
-----
|
||||
For complete documentation of the types of floating-point exceptions and
|
||||
treatment options, see `seterr`.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> np.geterrcall() # we did not yet set a handler, returns None
|
||||
|
||||
>>> oldsettings = np.seterr(all='call')
|
||||
>>> def err_handler(type, flag):
|
||||
... print("Floating point error (%s), with flag %s" % (type, flag))
|
||||
>>> oldhandler = np.seterrcall(err_handler)
|
||||
>>> np.array([1, 2, 3]) / 0.0
|
||||
Floating point error (divide by zero), with flag 1
|
||||
array([inf, inf, inf])
|
||||
|
||||
>>> cur_handler = np.geterrcall()
|
||||
>>> cur_handler is err_handler
|
||||
True
|
||||
|
||||
"""
|
||||
return umath.geterrobj()[2]
|
||||
|
||||
|
||||
class _unspecified:
|
||||
pass
|
||||
|
||||
|
||||
_Unspecified = _unspecified()
|
||||
|
||||
|
||||
@set_module('numpy')
|
||||
class errstate(contextlib.ContextDecorator):
|
||||
"""
|
||||
errstate(**kwargs)
|
||||
|
||||
Context manager for floating-point error handling.
|
||||
|
||||
Using an instance of `errstate` as a context manager allows statements in
|
||||
that context to execute with a known error handling behavior. Upon entering
|
||||
the context the error handling is set with `seterr` and `seterrcall`, and
|
||||
upon exiting it is reset to what it was before.
|
||||
|
||||
.. versionchanged:: 1.17.0
|
||||
`errstate` is also usable as a function decorator, saving
|
||||
a level of indentation if an entire function is wrapped.
|
||||
See :py:class:`contextlib.ContextDecorator` for more information.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
kwargs : {divide, over, under, invalid}
|
||||
Keyword arguments. The valid keywords are the possible floating-point
|
||||
exceptions. Each keyword should have a string value that defines the
|
||||
treatment for the particular error. Possible values are
|
||||
{'ignore', 'warn', 'raise', 'call', 'print', 'log'}.
|
||||
|
||||
See Also
|
||||
--------
|
||||
seterr, geterr, seterrcall, geterrcall
|
||||
|
||||
Notes
|
||||
-----
|
||||
For complete documentation of the types of floating-point exceptions and
|
||||
treatment options, see `seterr`.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> olderr = np.seterr(all='ignore') # Set error handling to known state.
|
||||
|
||||
>>> np.arange(3) / 0.
|
||||
array([nan, inf, inf])
|
||||
>>> with np.errstate(divide='warn'):
|
||||
... np.arange(3) / 0.
|
||||
array([nan, inf, inf])
|
||||
|
||||
>>> np.sqrt(-1)
|
||||
nan
|
||||
>>> with np.errstate(invalid='raise'):
|
||||
... np.sqrt(-1)
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 2, in <module>
|
||||
FloatingPointError: invalid value encountered in sqrt
|
||||
|
||||
Outside the context the error handling behavior has not changed:
|
||||
|
||||
>>> np.geterr()
|
||||
{'divide': 'ignore', 'over': 'ignore', 'under': 'ignore', 'invalid': 'ignore'}
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, *, call=_Unspecified, **kwargs):
|
||||
self.call = call
|
||||
self.kwargs = kwargs
|
||||
|
||||
def __enter__(self):
|
||||
self.oldstate = seterr(**self.kwargs)
|
||||
if self.call is not _Unspecified:
|
||||
self.oldcall = seterrcall(self.call)
|
||||
|
||||
def __exit__(self, *exc_info):
|
||||
seterr(**self.oldstate)
|
||||
if self.call is not _Unspecified:
|
||||
seterrcall(self.oldcall)
|
||||
|
||||
|
||||
def _setdef():
|
||||
defval = [UFUNC_BUFSIZE_DEFAULT, ERR_DEFAULT, None]
|
||||
umath.seterrobj(defval)
|
||||
|
||||
|
||||
# set the default values
|
||||
_setdef()
|
@ -0,0 +1,43 @@
|
||||
import sys
|
||||
from typing import Optional, Union, Callable, Any
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from typing import Literal, Protocol, TypedDict
|
||||
else:
|
||||
from typing_extensions import Literal, Protocol, TypedDict
|
||||
|
||||
_ErrKind = Literal["ignore", "warn", "raise", "call", "print", "log"]
|
||||
_ErrFunc = Callable[[str, int], Any]
|
||||
|
||||
class _SupportsWrite(Protocol):
|
||||
def write(self, __msg: str) -> Any: ...
|
||||
|
||||
class _ErrDict(TypedDict):
|
||||
divide: _ErrKind
|
||||
over: _ErrKind
|
||||
under: _ErrKind
|
||||
invalid: _ErrKind
|
||||
|
||||
class _ErrDictOptional(TypedDict, total=False):
|
||||
all: Optional[_ErrKind]
|
||||
divide: Optional[_ErrKind]
|
||||
over: Optional[_ErrKind]
|
||||
under: Optional[_ErrKind]
|
||||
invalid: Optional[_ErrKind]
|
||||
|
||||
def seterr(
|
||||
all: Optional[_ErrKind] = ...,
|
||||
divide: Optional[_ErrKind] = ...,
|
||||
over: Optional[_ErrKind] = ...,
|
||||
under: Optional[_ErrKind] = ...,
|
||||
invalid: Optional[_ErrKind] = ...,
|
||||
) -> _ErrDict: ...
|
||||
def geterr() -> _ErrDict: ...
|
||||
def setbufsize(size: int) -> int: ...
|
||||
def getbufsize() -> int: ...
|
||||
def seterrcall(
|
||||
func: Union[None, _ErrFunc, _SupportsWrite]
|
||||
) -> Union[None, _ErrFunc, _SupportsWrite]: ...
|
||||
def geterrcall() -> Union[None, _ErrFunc, _SupportsWrite]: ...
|
||||
|
||||
# See `numpy/__init__.pyi` for the `errstate` class
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,147 @@
|
||||
import sys
|
||||
from types import TracebackType
|
||||
from typing import Any, Optional, Callable, Union, Type
|
||||
|
||||
# Using a private class is by no means ideal, but it is simply a consquence
|
||||
# of a `contextlib.context` returning an instance of aformentioned class
|
||||
from contextlib import _GeneratorContextManager
|
||||
|
||||
from numpy import (
|
||||
ndarray,
|
||||
generic,
|
||||
bool_,
|
||||
integer,
|
||||
timedelta64,
|
||||
datetime64,
|
||||
floating,
|
||||
complexfloating,
|
||||
void,
|
||||
str_,
|
||||
bytes_,
|
||||
longdouble,
|
||||
clongdouble,
|
||||
)
|
||||
from numpy.typing import ArrayLike, _CharLike_co, _FloatLike_co
|
||||
|
||||
if sys.version_info > (3, 8):
|
||||
from typing import Literal, TypedDict, SupportsIndex
|
||||
else:
|
||||
from typing_extensions import Literal, TypedDict, SupportsIndex
|
||||
|
||||
_FloatMode = Literal["fixed", "unique", "maxprec", "maxprec_equal"]
|
||||
|
||||
class _FormatDict(TypedDict, total=False):
|
||||
bool: Callable[[bool_], str]
|
||||
int: Callable[[integer[Any]], str]
|
||||
timedelta: Callable[[timedelta64], str]
|
||||
datetime: Callable[[datetime64], str]
|
||||
float: Callable[[floating[Any]], str]
|
||||
longfloat: Callable[[longdouble], str]
|
||||
complexfloat: Callable[[complexfloating[Any, Any]], str]
|
||||
longcomplexfloat: Callable[[clongdouble], str]
|
||||
void: Callable[[void], str]
|
||||
numpystr: Callable[[_CharLike_co], str]
|
||||
object: Callable[[object], str]
|
||||
all: Callable[[object], str]
|
||||
int_kind: Callable[[integer[Any]], str]
|
||||
float_kind: Callable[[floating[Any]], str]
|
||||
complex_kind: Callable[[complexfloating[Any, Any]], str]
|
||||
str_kind: Callable[[_CharLike_co], str]
|
||||
|
||||
class _FormatOptions(TypedDict):
|
||||
precision: int
|
||||
threshold: int
|
||||
edgeitems: int
|
||||
linewidth: int
|
||||
suppress: bool
|
||||
nanstr: str
|
||||
infstr: str
|
||||
formatter: Optional[_FormatDict]
|
||||
sign: Literal["-", "+", " "]
|
||||
floatmode: _FloatMode
|
||||
legacy: Literal[False, "1.13"]
|
||||
|
||||
def set_printoptions(
|
||||
precision: Optional[SupportsIndex] = ...,
|
||||
threshold: Optional[int] = ...,
|
||||
edgeitems: Optional[int] = ...,
|
||||
linewidth: Optional[int] = ...,
|
||||
suppress: Optional[bool] = ...,
|
||||
nanstr: Optional[str] = ...,
|
||||
infstr: Optional[str] = ...,
|
||||
formatter: Optional[_FormatDict] = ...,
|
||||
sign: Optional[Literal["-", "+", " "]] = ...,
|
||||
floatmode: Optional[_FloatMode] = ...,
|
||||
*,
|
||||
legacy: Optional[Literal[False, "1.13"]] = ...
|
||||
) -> None: ...
|
||||
def get_printoptions() -> _FormatOptions: ...
|
||||
def array2string(
|
||||
a: ndarray[Any, Any],
|
||||
max_line_width: Optional[int] = ...,
|
||||
precision: Optional[SupportsIndex] = ...,
|
||||
suppress_small: Optional[bool] = ...,
|
||||
separator: str = ...,
|
||||
prefix: str = ...,
|
||||
# NOTE: With the `style` argument being deprecated,
|
||||
# all arguments between `formatter` and `suffix` are de facto
|
||||
# keyworld-only arguments
|
||||
*,
|
||||
formatter: Optional[_FormatDict] = ...,
|
||||
threshold: Optional[int] = ...,
|
||||
edgeitems: Optional[int] = ...,
|
||||
sign: Optional[Literal["-", "+", " "]] = ...,
|
||||
floatmode: Optional[_FloatMode] = ...,
|
||||
suffix: str = ...,
|
||||
legacy: Optional[Literal[False, "1.13"]] = ...,
|
||||
) -> str: ...
|
||||
def format_float_scientific(
|
||||
x: _FloatLike_co,
|
||||
precision: Optional[int] = ...,
|
||||
unique: bool = ...,
|
||||
trim: Literal["k", ".", "0", "-"] = ...,
|
||||
sign: bool = ...,
|
||||
pad_left: Optional[int] = ...,
|
||||
exp_digits: Optional[int] = ...,
|
||||
min_digits: Optional[int] = ...,
|
||||
) -> str: ...
|
||||
def format_float_positional(
|
||||
x: _FloatLike_co,
|
||||
precision: Optional[int] = ...,
|
||||
unique: bool = ...,
|
||||
fractional: bool = ...,
|
||||
trim: Literal["k", ".", "0", "-"] = ...,
|
||||
sign: bool = ...,
|
||||
pad_left: Optional[int] = ...,
|
||||
pad_right: Optional[int] = ...,
|
||||
min_digits: Optional[int] = ...,
|
||||
) -> str: ...
|
||||
def array_repr(
|
||||
arr: ndarray[Any, Any],
|
||||
max_line_width: Optional[int] = ...,
|
||||
precision: Optional[SupportsIndex] = ...,
|
||||
suppress_small: Optional[bool] = ...,
|
||||
) -> str: ...
|
||||
def array_str(
|
||||
a: ndarray[Any, Any],
|
||||
max_line_width: Optional[int] = ...,
|
||||
precision: Optional[SupportsIndex] = ...,
|
||||
suppress_small: Optional[bool] = ...,
|
||||
) -> str: ...
|
||||
def set_string_function(
|
||||
f: Optional[Callable[[ndarray[Any, Any]], str]], repr: bool = ...
|
||||
) -> None: ...
|
||||
def printoptions(
|
||||
precision: Optional[SupportsIndex] = ...,
|
||||
threshold: Optional[int] = ...,
|
||||
edgeitems: Optional[int] = ...,
|
||||
linewidth: Optional[int] = ...,
|
||||
suppress: Optional[bool] = ...,
|
||||
nanstr: Optional[str] = ...,
|
||||
infstr: Optional[str] = ...,
|
||||
formatter: Optional[_FormatDict] = ...,
|
||||
sign: Optional[Literal["-", "+", " "]] = ...,
|
||||
floatmode: Optional[_FloatMode] = ...,
|
||||
*,
|
||||
legacy: Optional[Literal[False, "1.13"]] = ...
|
||||
) -> _GeneratorContextManager[_FormatOptions]: ...
|
@ -0,0 +1,13 @@
|
||||
"""Simple script to compute the api hash of the current API.
|
||||
|
||||
The API has is defined by numpy_api_order and ufunc_api_order.
|
||||
|
||||
"""
|
||||
from os.path import dirname
|
||||
|
||||
from code_generators.genapi import fullapi_hash
|
||||
from code_generators.numpy_api import full_api
|
||||
|
||||
if __name__ == '__main__':
|
||||
curdir = dirname(__file__)
|
||||
print(fullapi_hash(full_api))
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,142 @@
|
||||
import sys
|
||||
from typing import List, TypeVar, Optional, Any, overload, Union, Tuple, Sequence
|
||||
|
||||
from numpy import (
|
||||
ndarray,
|
||||
dtype,
|
||||
bool_,
|
||||
unsignedinteger,
|
||||
signedinteger,
|
||||
floating,
|
||||
complexfloating,
|
||||
number,
|
||||
_OrderKACF,
|
||||
)
|
||||
from numpy.typing import (
|
||||
_ArrayLikeBool_co,
|
||||
_ArrayLikeUInt_co,
|
||||
_ArrayLikeInt_co,
|
||||
_ArrayLikeFloat_co,
|
||||
_ArrayLikeComplex_co,
|
||||
_DTypeLikeBool,
|
||||
_DTypeLikeUInt,
|
||||
_DTypeLikeInt,
|
||||
_DTypeLikeFloat,
|
||||
_DTypeLikeComplex,
|
||||
_DTypeLikeComplex_co,
|
||||
)
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from typing import Literal
|
||||
else:
|
||||
from typing_extensions import Literal
|
||||
|
||||
_ArrayType = TypeVar(
|
||||
"_ArrayType",
|
||||
bound=ndarray[Any, dtype[Union[bool_, number[Any]]]],
|
||||
)
|
||||
|
||||
_OptimizeKind = Union[
|
||||
None, bool, Literal["greedy", "optimal"], Sequence[Any]
|
||||
]
|
||||
_CastingSafe = Literal["no", "equiv", "safe", "same_kind"]
|
||||
_CastingUnsafe = Literal["unsafe"]
|
||||
|
||||
__all__: List[str]
|
||||
|
||||
# TODO: Properly handle the `casting`-based combinatorics
|
||||
# TODO: We need to evaluate the content `__subscripts` in order
|
||||
# to identify whether or an array or scalar is returned. At a cursory
|
||||
# glance this seems like something that can quite easilly be done with
|
||||
# a mypy plugin.
|
||||
# Something like `is_scalar = bool(__subscripts.partition("->")[-1])`
|
||||
@overload
|
||||
def einsum(
|
||||
__subscripts: str,
|
||||
*operands: _ArrayLikeBool_co,
|
||||
out: None = ...,
|
||||
dtype: Optional[_DTypeLikeBool] = ...,
|
||||
order: _OrderKACF = ...,
|
||||
casting: _CastingSafe = ...,
|
||||
optimize: _OptimizeKind = ...,
|
||||
) -> Any: ...
|
||||
@overload
|
||||
def einsum(
|
||||
__subscripts: str,
|
||||
*operands: _ArrayLikeUInt_co,
|
||||
out: None = ...,
|
||||
dtype: Optional[_DTypeLikeUInt] = ...,
|
||||
order: _OrderKACF = ...,
|
||||
casting: _CastingSafe = ...,
|
||||
optimize: _OptimizeKind = ...,
|
||||
) -> Any: ...
|
||||
@overload
|
||||
def einsum(
|
||||
__subscripts: str,
|
||||
*operands: _ArrayLikeInt_co,
|
||||
out: None = ...,
|
||||
dtype: Optional[_DTypeLikeInt] = ...,
|
||||
order: _OrderKACF = ...,
|
||||
casting: _CastingSafe = ...,
|
||||
optimize: _OptimizeKind = ...,
|
||||
) -> Any: ...
|
||||
@overload
|
||||
def einsum(
|
||||
__subscripts: str,
|
||||
*operands: _ArrayLikeFloat_co,
|
||||
out: None = ...,
|
||||
dtype: Optional[_DTypeLikeFloat] = ...,
|
||||
order: _OrderKACF = ...,
|
||||
casting: _CastingSafe = ...,
|
||||
optimize: _OptimizeKind = ...,
|
||||
) -> Any: ...
|
||||
@overload
|
||||
def einsum(
|
||||
__subscripts: str,
|
||||
*operands: _ArrayLikeComplex_co,
|
||||
out: None = ...,
|
||||
dtype: Optional[_DTypeLikeComplex] = ...,
|
||||
order: _OrderKACF = ...,
|
||||
casting: _CastingSafe = ...,
|
||||
optimize: _OptimizeKind = ...,
|
||||
) -> Any: ...
|
||||
@overload
|
||||
def einsum(
|
||||
__subscripts: str,
|
||||
*operands: Any,
|
||||
casting: _CastingUnsafe,
|
||||
dtype: Optional[_DTypeLikeComplex_co] = ...,
|
||||
out: None = ...,
|
||||
order: _OrderKACF = ...,
|
||||
optimize: _OptimizeKind = ...,
|
||||
) -> Any: ...
|
||||
@overload
|
||||
def einsum(
|
||||
__subscripts: str,
|
||||
*operands: _ArrayLikeComplex_co,
|
||||
out: _ArrayType,
|
||||
dtype: Optional[_DTypeLikeComplex_co] = ...,
|
||||
order: _OrderKACF = ...,
|
||||
casting: _CastingSafe = ...,
|
||||
optimize: _OptimizeKind = ...,
|
||||
) -> _ArrayType: ...
|
||||
@overload
|
||||
def einsum(
|
||||
__subscripts: str,
|
||||
*operands: Any,
|
||||
out: _ArrayType,
|
||||
casting: _CastingUnsafe,
|
||||
dtype: Optional[_DTypeLikeComplex_co] = ...,
|
||||
order: _OrderKACF = ...,
|
||||
optimize: _OptimizeKind = ...,
|
||||
) -> _ArrayType: ...
|
||||
|
||||
# NOTE: `einsum_call` is a hidden kwarg unavailable for public use.
|
||||
# It is therefore excluded from the signatures below.
|
||||
# NOTE: In practice the list consists of a `str` (first element)
|
||||
# and a variable number of integer tuples.
|
||||
def einsum_path(
|
||||
__subscripts: str,
|
||||
*operands: _ArrayLikeComplex_co,
|
||||
optimize: _OptimizeKind = ...,
|
||||
) -> Tuple[List[Any], str]: ...
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,361 @@
|
||||
import sys
|
||||
import datetime as dt
|
||||
from typing import Optional, Union, Sequence, Tuple, Any, overload, TypeVar
|
||||
|
||||
from numpy import (
|
||||
ndarray,
|
||||
number,
|
||||
integer,
|
||||
intp,
|
||||
bool_,
|
||||
generic,
|
||||
_OrderKACF,
|
||||
_OrderACF,
|
||||
_ModeKind,
|
||||
_PartitionKind,
|
||||
_SortKind,
|
||||
_SortSide,
|
||||
)
|
||||
from numpy.typing import (
|
||||
DTypeLike,
|
||||
ArrayLike,
|
||||
_ShapeLike,
|
||||
_Shape,
|
||||
_ArrayLikeBool_co,
|
||||
_ArrayLikeInt_co,
|
||||
_NumberLike_co,
|
||||
)
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from typing import Literal
|
||||
else:
|
||||
from typing_extensions import Literal
|
||||
|
||||
# Various annotations for scalars
|
||||
|
||||
# While dt.datetime and dt.timedelta are not technically part of NumPy,
|
||||
# they are one of the rare few builtin scalars which serve as valid return types.
|
||||
# See https://github.com/numpy/numpy-stubs/pull/67#discussion_r412604113.
|
||||
_ScalarNumpy = Union[generic, dt.datetime, dt.timedelta]
|
||||
_ScalarBuiltin = Union[str, bytes, dt.date, dt.timedelta, bool, int, float, complex]
|
||||
_Scalar = Union[_ScalarBuiltin, _ScalarNumpy]
|
||||
|
||||
# Integers and booleans can generally be used interchangeably
|
||||
_ScalarGeneric = TypeVar("_ScalarGeneric", bound=generic)
|
||||
|
||||
_Number = TypeVar("_Number", bound=number)
|
||||
|
||||
# The signature of take() follows a common theme with its overloads:
|
||||
# 1. A generic comes in; the same generic comes out
|
||||
# 2. A scalar comes in; a generic comes out
|
||||
# 3. An array-like object comes in; some keyword ensures that a generic comes out
|
||||
# 4. An array-like object comes in; an ndarray or generic comes out
|
||||
def take(
|
||||
a: ArrayLike,
|
||||
indices: _ArrayLikeInt_co,
|
||||
axis: Optional[int] = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
mode: _ModeKind = ...,
|
||||
) -> Any: ...
|
||||
|
||||
def reshape(
|
||||
a: ArrayLike,
|
||||
newshape: _ShapeLike,
|
||||
order: _OrderACF = ...,
|
||||
) -> ndarray: ...
|
||||
|
||||
def choose(
|
||||
a: _ArrayLikeInt_co,
|
||||
choices: ArrayLike,
|
||||
out: Optional[ndarray] = ...,
|
||||
mode: _ModeKind = ...,
|
||||
) -> Any: ...
|
||||
|
||||
def repeat(
|
||||
a: ArrayLike,
|
||||
repeats: _ArrayLikeInt_co,
|
||||
axis: Optional[int] = ...,
|
||||
) -> ndarray: ...
|
||||
|
||||
def put(
|
||||
a: ndarray,
|
||||
ind: _ArrayLikeInt_co,
|
||||
v: ArrayLike,
|
||||
mode: _ModeKind = ...,
|
||||
) -> None: ...
|
||||
|
||||
def swapaxes(
|
||||
a: ArrayLike,
|
||||
axis1: int,
|
||||
axis2: int,
|
||||
) -> ndarray: ...
|
||||
|
||||
def transpose(
|
||||
a: ArrayLike,
|
||||
axes: Union[None, Sequence[int], ndarray] = ...
|
||||
) -> ndarray: ...
|
||||
|
||||
def partition(
|
||||
a: ArrayLike,
|
||||
kth: _ArrayLikeInt_co,
|
||||
axis: Optional[int] = ...,
|
||||
kind: _PartitionKind = ...,
|
||||
order: Union[None, str, Sequence[str]] = ...,
|
||||
) -> ndarray: ...
|
||||
|
||||
def argpartition(
|
||||
a: ArrayLike,
|
||||
kth: _ArrayLikeInt_co,
|
||||
axis: Optional[int] = ...,
|
||||
kind: _PartitionKind = ...,
|
||||
order: Union[None, str, Sequence[str]] = ...,
|
||||
) -> Any: ...
|
||||
|
||||
def sort(
|
||||
a: ArrayLike,
|
||||
axis: Optional[int] = ...,
|
||||
kind: Optional[_SortKind] = ...,
|
||||
order: Union[None, str, Sequence[str]] = ...,
|
||||
) -> ndarray: ...
|
||||
|
||||
def argsort(
|
||||
a: ArrayLike,
|
||||
axis: Optional[int] = ...,
|
||||
kind: Optional[_SortKind] = ...,
|
||||
order: Union[None, str, Sequence[str]] = ...,
|
||||
) -> ndarray: ...
|
||||
|
||||
@overload
|
||||
def argmax(
|
||||
a: ArrayLike,
|
||||
axis: None = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
) -> intp: ...
|
||||
@overload
|
||||
def argmax(
|
||||
a: ArrayLike,
|
||||
axis: Optional[int] = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
) -> Any: ...
|
||||
|
||||
@overload
|
||||
def argmin(
|
||||
a: ArrayLike,
|
||||
axis: None = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
) -> intp: ...
|
||||
@overload
|
||||
def argmin(
|
||||
a: ArrayLike,
|
||||
axis: Optional[int] = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
) -> Any: ...
|
||||
|
||||
@overload
|
||||
def searchsorted(
|
||||
a: ArrayLike,
|
||||
v: _Scalar,
|
||||
side: _SortSide = ...,
|
||||
sorter: Optional[_ArrayLikeInt_co] = ..., # 1D int array
|
||||
) -> intp: ...
|
||||
@overload
|
||||
def searchsorted(
|
||||
a: ArrayLike,
|
||||
v: ArrayLike,
|
||||
side: _SortSide = ...,
|
||||
sorter: Optional[_ArrayLikeInt_co] = ..., # 1D int array
|
||||
) -> ndarray: ...
|
||||
|
||||
def resize(
|
||||
a: ArrayLike,
|
||||
new_shape: _ShapeLike,
|
||||
) -> ndarray: ...
|
||||
|
||||
@overload
|
||||
def squeeze(
|
||||
a: _ScalarGeneric,
|
||||
axis: Optional[_ShapeLike] = ...,
|
||||
) -> _ScalarGeneric: ...
|
||||
@overload
|
||||
def squeeze(
|
||||
a: ArrayLike,
|
||||
axis: Optional[_ShapeLike] = ...,
|
||||
) -> ndarray: ...
|
||||
|
||||
def diagonal(
|
||||
a: ArrayLike,
|
||||
offset: int = ...,
|
||||
axis1: int = ...,
|
||||
axis2: int = ..., # >= 2D array
|
||||
) -> ndarray: ...
|
||||
|
||||
def trace(
|
||||
a: ArrayLike, # >= 2D array
|
||||
offset: int = ...,
|
||||
axis1: int = ...,
|
||||
axis2: int = ...,
|
||||
dtype: DTypeLike = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
) -> Any: ...
|
||||
|
||||
def ravel(a: ArrayLike, order: _OrderKACF = ...) -> ndarray: ...
|
||||
|
||||
def nonzero(a: ArrayLike) -> Tuple[ndarray, ...]: ...
|
||||
|
||||
def shape(a: ArrayLike) -> _Shape: ...
|
||||
|
||||
def compress(
|
||||
condition: ArrayLike, # 1D bool array
|
||||
a: ArrayLike,
|
||||
axis: Optional[int] = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
) -> ndarray: ...
|
||||
|
||||
@overload
|
||||
def clip(
|
||||
a: ArrayLike,
|
||||
a_min: ArrayLike,
|
||||
a_max: Optional[ArrayLike],
|
||||
out: Optional[ndarray] = ...,
|
||||
**kwargs: Any,
|
||||
) -> Any: ...
|
||||
@overload
|
||||
def clip(
|
||||
a: ArrayLike,
|
||||
a_min: None,
|
||||
a_max: ArrayLike,
|
||||
out: Optional[ndarray] = ...,
|
||||
**kwargs: Any,
|
||||
) -> Any: ...
|
||||
|
||||
def sum(
|
||||
a: ArrayLike,
|
||||
axis: _ShapeLike = ...,
|
||||
dtype: DTypeLike = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
keepdims: bool = ...,
|
||||
initial: _NumberLike_co = ...,
|
||||
where: _ArrayLikeBool_co = ...,
|
||||
) -> Any: ...
|
||||
|
||||
@overload
|
||||
def all(
|
||||
a: ArrayLike,
|
||||
axis: None = ...,
|
||||
out: None = ...,
|
||||
keepdims: Literal[False] = ...,
|
||||
) -> bool_: ...
|
||||
@overload
|
||||
def all(
|
||||
a: ArrayLike,
|
||||
axis: Optional[_ShapeLike] = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
keepdims: bool = ...,
|
||||
) -> Any: ...
|
||||
|
||||
@overload
|
||||
def any(
|
||||
a: ArrayLike,
|
||||
axis: None = ...,
|
||||
out: None = ...,
|
||||
keepdims: Literal[False] = ...,
|
||||
) -> bool_: ...
|
||||
@overload
|
||||
def any(
|
||||
a: ArrayLike,
|
||||
axis: Optional[_ShapeLike] = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
keepdims: bool = ...,
|
||||
) -> Any: ...
|
||||
|
||||
def cumsum(
|
||||
a: ArrayLike,
|
||||
axis: Optional[int] = ...,
|
||||
dtype: DTypeLike = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
) -> ndarray: ...
|
||||
|
||||
def ptp(
|
||||
a: ArrayLike,
|
||||
axis: Optional[_ShapeLike] = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
keepdims: bool = ...,
|
||||
) -> Any: ...
|
||||
|
||||
def amax(
|
||||
a: ArrayLike,
|
||||
axis: Optional[_ShapeLike] = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
keepdims: bool = ...,
|
||||
initial: _NumberLike_co = ...,
|
||||
where: _ArrayLikeBool_co = ...,
|
||||
) -> Any: ...
|
||||
|
||||
def amin(
|
||||
a: ArrayLike,
|
||||
axis: Optional[_ShapeLike] = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
keepdims: bool = ...,
|
||||
initial: _NumberLike_co = ...,
|
||||
where: _ArrayLikeBool_co = ...,
|
||||
) -> Any: ...
|
||||
|
||||
# TODO: `np.prod()``: For object arrays `initial` does not necessarily
|
||||
# have to be a numerical scalar.
|
||||
# The only requirement is that it is compatible
|
||||
# with the `.__mul__()` method(s) of the passed array's elements.
|
||||
|
||||
# Note that the same situation holds for all wrappers around
|
||||
# `np.ufunc.reduce`, e.g. `np.sum()` (`.__add__()`).
|
||||
def prod(
|
||||
a: ArrayLike,
|
||||
axis: Optional[_ShapeLike] = ...,
|
||||
dtype: DTypeLike = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
keepdims: bool = ...,
|
||||
initial: _NumberLike_co = ...,
|
||||
where: _ArrayLikeBool_co = ...,
|
||||
) -> Any: ...
|
||||
|
||||
def cumprod(
|
||||
a: ArrayLike,
|
||||
axis: Optional[int] = ...,
|
||||
dtype: DTypeLike = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
) -> ndarray: ...
|
||||
|
||||
def ndim(a: ArrayLike) -> int: ...
|
||||
|
||||
def size(a: ArrayLike, axis: Optional[int] = ...) -> int: ...
|
||||
|
||||
def around(
|
||||
a: ArrayLike,
|
||||
decimals: int = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
) -> Any: ...
|
||||
|
||||
def mean(
|
||||
a: ArrayLike,
|
||||
axis: Optional[_ShapeLike] = ...,
|
||||
dtype: DTypeLike = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
keepdims: bool = ...,
|
||||
) -> Any: ...
|
||||
|
||||
def std(
|
||||
a: ArrayLike,
|
||||
axis: Optional[_ShapeLike] = ...,
|
||||
dtype: DTypeLike = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
ddof: int = ...,
|
||||
keepdims: bool = ...,
|
||||
) -> Any: ...
|
||||
|
||||
def var(
|
||||
a: ArrayLike,
|
||||
axis: Optional[_ShapeLike] = ...,
|
||||
dtype: DTypeLike = ...,
|
||||
out: Optional[ndarray] = ...,
|
||||
ddof: int = ...,
|
||||
keepdims: bool = ...,
|
||||
) -> Any: ...
|
@ -0,0 +1,529 @@
|
||||
import functools
|
||||
import warnings
|
||||
import operator
|
||||
import types
|
||||
|
||||
from . import numeric as _nx
|
||||
from .numeric import result_type, NaN, asanyarray, ndim
|
||||
from numpy.core.multiarray import add_docstring
|
||||
from numpy.core import overrides
|
||||
|
||||
__all__ = ['logspace', 'linspace', 'geomspace']
|
||||
|
||||
|
||||
array_function_dispatch = functools.partial(
|
||||
overrides.array_function_dispatch, module='numpy')
|
||||
|
||||
|
||||
def _linspace_dispatcher(start, stop, num=None, endpoint=None, retstep=None,
|
||||
dtype=None, axis=None):
|
||||
return (start, stop)
|
||||
|
||||
|
||||
@array_function_dispatch(_linspace_dispatcher)
|
||||
def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,
|
||||
axis=0):
|
||||
"""
|
||||
Return evenly spaced numbers over a specified interval.
|
||||
|
||||
Returns `num` evenly spaced samples, calculated over the
|
||||
interval [`start`, `stop`].
|
||||
|
||||
The endpoint of the interval can optionally be excluded.
|
||||
|
||||
.. versionchanged:: 1.16.0
|
||||
Non-scalar `start` and `stop` are now supported.
|
||||
|
||||
.. versionchanged:: 1.20.0
|
||||
Values are rounded towards ``-inf`` instead of ``0`` when an
|
||||
integer ``dtype`` is specified. The old behavior can
|
||||
still be obtained with ``np.linspace(start, stop, num).astype(int)``
|
||||
|
||||
Parameters
|
||||
----------
|
||||
start : array_like
|
||||
The starting value of the sequence.
|
||||
stop : array_like
|
||||
The end value of the sequence, unless `endpoint` is set to False.
|
||||
In that case, the sequence consists of all but the last of ``num + 1``
|
||||
evenly spaced samples, so that `stop` is excluded. Note that the step
|
||||
size changes when `endpoint` is False.
|
||||
num : int, optional
|
||||
Number of samples to generate. Default is 50. Must be non-negative.
|
||||
endpoint : bool, optional
|
||||
If True, `stop` is the last sample. Otherwise, it is not included.
|
||||
Default is True.
|
||||
retstep : bool, optional
|
||||
If True, return (`samples`, `step`), where `step` is the spacing
|
||||
between samples.
|
||||
dtype : dtype, optional
|
||||
The type of the output array. If `dtype` is not given, the data type
|
||||
is inferred from `start` and `stop`. The inferred dtype will never be
|
||||
an integer; `float` is chosen even if the arguments would produce an
|
||||
array of integers.
|
||||
|
||||
.. versionadded:: 1.9.0
|
||||
|
||||
axis : int, optional
|
||||
The axis in the result to store the samples. Relevant only if start
|
||||
or stop are array-like. By default (0), the samples will be along a
|
||||
new axis inserted at the beginning. Use -1 to get an axis at the end.
|
||||
|
||||
.. versionadded:: 1.16.0
|
||||
|
||||
Returns
|
||||
-------
|
||||
samples : ndarray
|
||||
There are `num` equally spaced samples in the closed interval
|
||||
``[start, stop]`` or the half-open interval ``[start, stop)``
|
||||
(depending on whether `endpoint` is True or False).
|
||||
step : float, optional
|
||||
Only returned if `retstep` is True
|
||||
|
||||
Size of spacing between samples.
|
||||
|
||||
|
||||
See Also
|
||||
--------
|
||||
arange : Similar to `linspace`, but uses a step size (instead of the
|
||||
number of samples).
|
||||
geomspace : Similar to `linspace`, but with numbers spaced evenly on a log
|
||||
scale (a geometric progression).
|
||||
logspace : Similar to `geomspace`, but with the end points specified as
|
||||
logarithms.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> np.linspace(2.0, 3.0, num=5)
|
||||
array([2. , 2.25, 2.5 , 2.75, 3. ])
|
||||
>>> np.linspace(2.0, 3.0, num=5, endpoint=False)
|
||||
array([2. , 2.2, 2.4, 2.6, 2.8])
|
||||
>>> np.linspace(2.0, 3.0, num=5, retstep=True)
|
||||
(array([2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
|
||||
|
||||
Graphical illustration:
|
||||
|
||||
>>> import matplotlib.pyplot as plt
|
||||
>>> N = 8
|
||||
>>> y = np.zeros(N)
|
||||
>>> x1 = np.linspace(0, 10, N, endpoint=True)
|
||||
>>> x2 = np.linspace(0, 10, N, endpoint=False)
|
||||
>>> plt.plot(x1, y, 'o')
|
||||
[<matplotlib.lines.Line2D object at 0x...>]
|
||||
>>> plt.plot(x2, y + 0.5, 'o')
|
||||
[<matplotlib.lines.Line2D object at 0x...>]
|
||||
>>> plt.ylim([-0.5, 1])
|
||||
(-0.5, 1)
|
||||
>>> plt.show()
|
||||
|
||||
"""
|
||||
num = operator.index(num)
|
||||
if num < 0:
|
||||
raise ValueError("Number of samples, %s, must be non-negative." % num)
|
||||
div = (num - 1) if endpoint else num
|
||||
|
||||
# Convert float/complex array scalars to float, gh-3504
|
||||
# and make sure one can use variables that have an __array_interface__, gh-6634
|
||||
start = asanyarray(start) * 1.0
|
||||
stop = asanyarray(stop) * 1.0
|
||||
|
||||
dt = result_type(start, stop, float(num))
|
||||
if dtype is None:
|
||||
dtype = dt
|
||||
|
||||
delta = stop - start
|
||||
y = _nx.arange(0, num, dtype=dt).reshape((-1,) + (1,) * ndim(delta))
|
||||
# In-place multiplication y *= delta/div is faster, but prevents the multiplicant
|
||||
# from overriding what class is produced, and thus prevents, e.g. use of Quantities,
|
||||
# see gh-7142. Hence, we multiply in place only for standard scalar types.
|
||||
_mult_inplace = _nx.isscalar(delta)
|
||||
if div > 0:
|
||||
step = delta / div
|
||||
if _nx.any(step == 0):
|
||||
# Special handling for denormal numbers, gh-5437
|
||||
y /= div
|
||||
if _mult_inplace:
|
||||
y *= delta
|
||||
else:
|
||||
y = y * delta
|
||||
else:
|
||||
if _mult_inplace:
|
||||
y *= step
|
||||
else:
|
||||
y = y * step
|
||||
else:
|
||||
# sequences with 0 items or 1 item with endpoint=True (i.e. div <= 0)
|
||||
# have an undefined step
|
||||
step = NaN
|
||||
# Multiply with delta to allow possible override of output class.
|
||||
y = y * delta
|
||||
|
||||
y += start
|
||||
|
||||
if endpoint and num > 1:
|
||||
y[-1] = stop
|
||||
|
||||
if axis != 0:
|
||||
y = _nx.moveaxis(y, 0, axis)
|
||||
|
||||
if _nx.issubdtype(dtype, _nx.integer):
|
||||
_nx.floor(y, out=y)
|
||||
|
||||
if retstep:
|
||||
return y.astype(dtype, copy=False), step
|
||||
else:
|
||||
return y.astype(dtype, copy=False)
|
||||
|
||||
|
||||
def _logspace_dispatcher(start, stop, num=None, endpoint=None, base=None,
|
||||
dtype=None, axis=None):
|
||||
return (start, stop)
|
||||
|
||||
|
||||
@array_function_dispatch(_logspace_dispatcher)
|
||||
def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None,
|
||||
axis=0):
|
||||
"""
|
||||
Return numbers spaced evenly on a log scale.
|
||||
|
||||
In linear space, the sequence starts at ``base ** start``
|
||||
(`base` to the power of `start`) and ends with ``base ** stop``
|
||||
(see `endpoint` below).
|
||||
|
||||
.. versionchanged:: 1.16.0
|
||||
Non-scalar `start` and `stop` are now supported.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
start : array_like
|
||||
``base ** start`` is the starting value of the sequence.
|
||||
stop : array_like
|
||||
``base ** stop`` is the final value of the sequence, unless `endpoint`
|
||||
is False. In that case, ``num + 1`` values are spaced over the
|
||||
interval in log-space, of which all but the last (a sequence of
|
||||
length `num`) are returned.
|
||||
num : integer, optional
|
||||
Number of samples to generate. Default is 50.
|
||||
endpoint : boolean, optional
|
||||
If true, `stop` is the last sample. Otherwise, it is not included.
|
||||
Default is True.
|
||||
base : array_like, optional
|
||||
The base of the log space. The step size between the elements in
|
||||
``ln(samples) / ln(base)`` (or ``log_base(samples)``) is uniform.
|
||||
Default is 10.0.
|
||||
dtype : dtype
|
||||
The type of the output array. If `dtype` is not given, the data type
|
||||
is inferred from `start` and `stop`. The inferred type will never be
|
||||
an integer; `float` is chosen even if the arguments would produce an
|
||||
array of integers.
|
||||
axis : int, optional
|
||||
The axis in the result to store the samples. Relevant only if start
|
||||
or stop are array-like. By default (0), the samples will be along a
|
||||
new axis inserted at the beginning. Use -1 to get an axis at the end.
|
||||
|
||||
.. versionadded:: 1.16.0
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
samples : ndarray
|
||||
`num` samples, equally spaced on a log scale.
|
||||
|
||||
See Also
|
||||
--------
|
||||
arange : Similar to linspace, with the step size specified instead of the
|
||||
number of samples. Note that, when used with a float endpoint, the
|
||||
endpoint may or may not be included.
|
||||
linspace : Similar to logspace, but with the samples uniformly distributed
|
||||
in linear space, instead of log space.
|
||||
geomspace : Similar to logspace, but with endpoints specified directly.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Logspace is equivalent to the code
|
||||
|
||||
>>> y = np.linspace(start, stop, num=num, endpoint=endpoint)
|
||||
... # doctest: +SKIP
|
||||
>>> power(base, y).astype(dtype)
|
||||
... # doctest: +SKIP
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> np.logspace(2.0, 3.0, num=4)
|
||||
array([ 100. , 215.443469 , 464.15888336, 1000. ])
|
||||
>>> np.logspace(2.0, 3.0, num=4, endpoint=False)
|
||||
array([100. , 177.827941 , 316.22776602, 562.34132519])
|
||||
>>> np.logspace(2.0, 3.0, num=4, base=2.0)
|
||||
array([4. , 5.0396842 , 6.34960421, 8. ])
|
||||
|
||||
Graphical illustration:
|
||||
|
||||
>>> import matplotlib.pyplot as plt
|
||||
>>> N = 10
|
||||
>>> x1 = np.logspace(0.1, 1, N, endpoint=True)
|
||||
>>> x2 = np.logspace(0.1, 1, N, endpoint=False)
|
||||
>>> y = np.zeros(N)
|
||||
>>> plt.plot(x1, y, 'o')
|
||||
[<matplotlib.lines.Line2D object at 0x...>]
|
||||
>>> plt.plot(x2, y + 0.5, 'o')
|
||||
[<matplotlib.lines.Line2D object at 0x...>]
|
||||
>>> plt.ylim([-0.5, 1])
|
||||
(-0.5, 1)
|
||||
>>> plt.show()
|
||||
|
||||
"""
|
||||
y = linspace(start, stop, num=num, endpoint=endpoint, axis=axis)
|
||||
if dtype is None:
|
||||
return _nx.power(base, y)
|
||||
return _nx.power(base, y).astype(dtype, copy=False)
|
||||
|
||||
|
||||
def _geomspace_dispatcher(start, stop, num=None, endpoint=None, dtype=None,
|
||||
axis=None):
|
||||
return (start, stop)
|
||||
|
||||
|
||||
@array_function_dispatch(_geomspace_dispatcher)
|
||||
def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
|
||||
"""
|
||||
Return numbers spaced evenly on a log scale (a geometric progression).
|
||||
|
||||
This is similar to `logspace`, but with endpoints specified directly.
|
||||
Each output sample is a constant multiple of the previous.
|
||||
|
||||
.. versionchanged:: 1.16.0
|
||||
Non-scalar `start` and `stop` are now supported.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
start : array_like
|
||||
The starting value of the sequence.
|
||||
stop : array_like
|
||||
The final value of the sequence, unless `endpoint` is False.
|
||||
In that case, ``num + 1`` values are spaced over the
|
||||
interval in log-space, of which all but the last (a sequence of
|
||||
length `num`) are returned.
|
||||
num : integer, optional
|
||||
Number of samples to generate. Default is 50.
|
||||
endpoint : boolean, optional
|
||||
If true, `stop` is the last sample. Otherwise, it is not included.
|
||||
Default is True.
|
||||
dtype : dtype
|
||||
The type of the output array. If `dtype` is not given, the data type
|
||||
is inferred from `start` and `stop`. The inferred dtype will never be
|
||||
an integer; `float` is chosen even if the arguments would produce an
|
||||
array of integers.
|
||||
axis : int, optional
|
||||
The axis in the result to store the samples. Relevant only if start
|
||||
or stop are array-like. By default (0), the samples will be along a
|
||||
new axis inserted at the beginning. Use -1 to get an axis at the end.
|
||||
|
||||
.. versionadded:: 1.16.0
|
||||
|
||||
Returns
|
||||
-------
|
||||
samples : ndarray
|
||||
`num` samples, equally spaced on a log scale.
|
||||
|
||||
See Also
|
||||
--------
|
||||
logspace : Similar to geomspace, but with endpoints specified using log
|
||||
and base.
|
||||
linspace : Similar to geomspace, but with arithmetic instead of geometric
|
||||
progression.
|
||||
arange : Similar to linspace, with the step size specified instead of the
|
||||
number of samples.
|
||||
|
||||
Notes
|
||||
-----
|
||||
If the inputs or dtype are complex, the output will follow a logarithmic
|
||||
spiral in the complex plane. (There are an infinite number of spirals
|
||||
passing through two points; the output will follow the shortest such path.)
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> np.geomspace(1, 1000, num=4)
|
||||
array([ 1., 10., 100., 1000.])
|
||||
>>> np.geomspace(1, 1000, num=3, endpoint=False)
|
||||
array([ 1., 10., 100.])
|
||||
>>> np.geomspace(1, 1000, num=4, endpoint=False)
|
||||
array([ 1. , 5.62341325, 31.6227766 , 177.827941 ])
|
||||
>>> np.geomspace(1, 256, num=9)
|
||||
array([ 1., 2., 4., 8., 16., 32., 64., 128., 256.])
|
||||
|
||||
Note that the above may not produce exact integers:
|
||||
|
||||
>>> np.geomspace(1, 256, num=9, dtype=int)
|
||||
array([ 1, 2, 4, 7, 16, 32, 63, 127, 256])
|
||||
>>> np.around(np.geomspace(1, 256, num=9)).astype(int)
|
||||
array([ 1, 2, 4, 8, 16, 32, 64, 128, 256])
|
||||
|
||||
Negative, decreasing, and complex inputs are allowed:
|
||||
|
||||
>>> np.geomspace(1000, 1, num=4)
|
||||
array([1000., 100., 10., 1.])
|
||||
>>> np.geomspace(-1000, -1, num=4)
|
||||
array([-1000., -100., -10., -1.])
|
||||
>>> np.geomspace(1j, 1000j, num=4) # Straight line
|
||||
array([0. +1.j, 0. +10.j, 0. +100.j, 0.+1000.j])
|
||||
>>> np.geomspace(-1+0j, 1+0j, num=5) # Circle
|
||||
array([-1.00000000e+00+1.22464680e-16j, -7.07106781e-01+7.07106781e-01j,
|
||||
6.12323400e-17+1.00000000e+00j, 7.07106781e-01+7.07106781e-01j,
|
||||
1.00000000e+00+0.00000000e+00j])
|
||||
|
||||
Graphical illustration of `endpoint` parameter:
|
||||
|
||||
>>> import matplotlib.pyplot as plt
|
||||
>>> N = 10
|
||||
>>> y = np.zeros(N)
|
||||
>>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=True), y + 1, 'o')
|
||||
[<matplotlib.lines.Line2D object at 0x...>]
|
||||
>>> plt.semilogx(np.geomspace(1, 1000, N, endpoint=False), y + 2, 'o')
|
||||
[<matplotlib.lines.Line2D object at 0x...>]
|
||||
>>> plt.axis([0.5, 2000, 0, 3])
|
||||
[0.5, 2000, 0, 3]
|
||||
>>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both')
|
||||
>>> plt.show()
|
||||
|
||||
"""
|
||||
start = asanyarray(start)
|
||||
stop = asanyarray(stop)
|
||||
if _nx.any(start == 0) or _nx.any(stop == 0):
|
||||
raise ValueError('Geometric sequence cannot include zero')
|
||||
|
||||
dt = result_type(start, stop, float(num), _nx.zeros((), dtype))
|
||||
if dtype is None:
|
||||
dtype = dt
|
||||
else:
|
||||
# complex to dtype('complex128'), for instance
|
||||
dtype = _nx.dtype(dtype)
|
||||
|
||||
# Promote both arguments to the same dtype in case, for instance, one is
|
||||
# complex and another is negative and log would produce NaN otherwise.
|
||||
# Copy since we may change things in-place further down.
|
||||
start = start.astype(dt, copy=True)
|
||||
stop = stop.astype(dt, copy=True)
|
||||
|
||||
out_sign = _nx.ones(_nx.broadcast(start, stop).shape, dt)
|
||||
# Avoid negligible real or imaginary parts in output by rotating to
|
||||
# positive real, calculating, then undoing rotation
|
||||
if _nx.issubdtype(dt, _nx.complexfloating):
|
||||
all_imag = (start.real == 0.) & (stop.real == 0.)
|
||||
if _nx.any(all_imag):
|
||||
start[all_imag] = start[all_imag].imag
|
||||
stop[all_imag] = stop[all_imag].imag
|
||||
out_sign[all_imag] = 1j
|
||||
|
||||
both_negative = (_nx.sign(start) == -1) & (_nx.sign(stop) == -1)
|
||||
if _nx.any(both_negative):
|
||||
_nx.negative(start, out=start, where=both_negative)
|
||||
_nx.negative(stop, out=stop, where=both_negative)
|
||||
_nx.negative(out_sign, out=out_sign, where=both_negative)
|
||||
|
||||
log_start = _nx.log10(start)
|
||||
log_stop = _nx.log10(stop)
|
||||
result = logspace(log_start, log_stop, num=num,
|
||||
endpoint=endpoint, base=10.0, dtype=dtype)
|
||||
|
||||
# Make sure the endpoints match the start and stop arguments. This is
|
||||
# necessary because np.exp(np.log(x)) is not necessarily equal to x.
|
||||
if num > 0:
|
||||
result[0] = start
|
||||
if num > 1 and endpoint:
|
||||
result[-1] = stop
|
||||
|
||||
result = out_sign * result
|
||||
|
||||
if axis != 0:
|
||||
result = _nx.moveaxis(result, 0, axis)
|
||||
|
||||
return result.astype(dtype, copy=False)
|
||||
|
||||
|
||||
def _needs_add_docstring(obj):
|
||||
"""
|
||||
Returns true if the only way to set the docstring of `obj` from python is
|
||||
via add_docstring.
|
||||
|
||||
This function errs on the side of being overly conservative.
|
||||
"""
|
||||
Py_TPFLAGS_HEAPTYPE = 1 << 9
|
||||
|
||||
if isinstance(obj, (types.FunctionType, types.MethodType, property)):
|
||||
return False
|
||||
|
||||
if isinstance(obj, type) and obj.__flags__ & Py_TPFLAGS_HEAPTYPE:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def _add_docstring(obj, doc, warn_on_python):
|
||||
if warn_on_python and not _needs_add_docstring(obj):
|
||||
warnings.warn(
|
||||
"add_newdoc was used on a pure-python object {}. "
|
||||
"Prefer to attach it directly to the source."
|
||||
.format(obj),
|
||||
UserWarning,
|
||||
stacklevel=3)
|
||||
try:
|
||||
add_docstring(obj, doc)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def add_newdoc(place, obj, doc, warn_on_python=True):
|
||||
"""
|
||||
Add documentation to an existing object, typically one defined in C
|
||||
|
||||
The purpose is to allow easier editing of the docstrings without requiring
|
||||
a re-compile. This exists primarily for internal use within numpy itself.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
place : str
|
||||
The absolute name of the module to import from
|
||||
obj : str
|
||||
The name of the object to add documentation to, typically a class or
|
||||
function name
|
||||
doc : {str, Tuple[str, str], List[Tuple[str, str]]}
|
||||
If a string, the documentation to apply to `obj`
|
||||
|
||||
If a tuple, then the first element is interpreted as an attribute of
|
||||
`obj` and the second as the docstring to apply - ``(method, docstring)``
|
||||
|
||||
If a list, then each element of the list should be a tuple of length
|
||||
two - ``[(method1, docstring1), (method2, docstring2), ...]``
|
||||
warn_on_python : bool
|
||||
If True, the default, emit `UserWarning` if this is used to attach
|
||||
documentation to a pure-python object.
|
||||
|
||||
Notes
|
||||
-----
|
||||
This routine never raises an error if the docstring can't be written, but
|
||||
will raise an error if the object being documented does not exist.
|
||||
|
||||
This routine cannot modify read-only docstrings, as appear
|
||||
in new-style classes or built-in functions. Because this
|
||||
routine never raises an error the caller must check manually
|
||||
that the docstrings were changed.
|
||||
|
||||
Since this function grabs the ``char *`` from a c-level str object and puts
|
||||
it into the ``tp_doc`` slot of the type of `obj`, it violates a number of
|
||||
C-API best-practices, by:
|
||||
|
||||
- modifying a `PyTypeObject` after calling `PyType_Ready`
|
||||
- calling `Py_INCREF` on the str and losing the reference, so the str
|
||||
will never be released
|
||||
|
||||
If possible it should be avoided.
|
||||
"""
|
||||
new = getattr(__import__(place, globals(), {}, [obj]), obj)
|
||||
if isinstance(doc, str):
|
||||
_add_docstring(new, doc.strip(), warn_on_python)
|
||||
elif isinstance(doc, tuple):
|
||||
attr, docstring = doc
|
||||
_add_docstring(getattr(new, attr), docstring.strip(), warn_on_python)
|
||||
elif isinstance(doc, list):
|
||||
for attr, docstring in doc:
|
||||
_add_docstring(getattr(new, attr), docstring.strip(), warn_on_python)
|
@ -0,0 +1,55 @@
|
||||
import sys
|
||||
from typing import overload, Tuple, Union, Sequence, Any
|
||||
|
||||
from numpy import ndarray
|
||||
from numpy.typing import ArrayLike, DTypeLike, _SupportsArray, _NumberLike_co
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from typing import SupportsIndex, Literal
|
||||
else:
|
||||
from typing_extensions import SupportsIndex, Literal
|
||||
|
||||
# TODO: wait for support for recursive types
|
||||
_ArrayLikeNested = Sequence[Sequence[Any]]
|
||||
_ArrayLikeNumber = Union[
|
||||
_NumberLike_co, Sequence[_NumberLike_co], ndarray, _SupportsArray, _ArrayLikeNested
|
||||
]
|
||||
@overload
|
||||
def linspace(
|
||||
start: _ArrayLikeNumber,
|
||||
stop: _ArrayLikeNumber,
|
||||
num: SupportsIndex = ...,
|
||||
endpoint: bool = ...,
|
||||
retstep: Literal[False] = ...,
|
||||
dtype: DTypeLike = ...,
|
||||
axis: SupportsIndex = ...,
|
||||
) -> ndarray: ...
|
||||
@overload
|
||||
def linspace(
|
||||
start: _ArrayLikeNumber,
|
||||
stop: _ArrayLikeNumber,
|
||||
num: SupportsIndex = ...,
|
||||
endpoint: bool = ...,
|
||||
retstep: Literal[True] = ...,
|
||||
dtype: DTypeLike = ...,
|
||||
axis: SupportsIndex = ...,
|
||||
) -> Tuple[ndarray, Any]: ...
|
||||
|
||||
def logspace(
|
||||
start: _ArrayLikeNumber,
|
||||
stop: _ArrayLikeNumber,
|
||||
num: SupportsIndex = ...,
|
||||
endpoint: bool = ...,
|
||||
base: _ArrayLikeNumber = ...,
|
||||
dtype: DTypeLike = ...,
|
||||
axis: SupportsIndex = ...,
|
||||
) -> ndarray: ...
|
||||
|
||||
def geomspace(
|
||||
start: _ArrayLikeNumber,
|
||||
stop: _ArrayLikeNumber,
|
||||
num: SupportsIndex = ...,
|
||||
endpoint: bool = ...,
|
||||
dtype: DTypeLike = ...,
|
||||
axis: SupportsIndex = ...,
|
||||
) -> ndarray: ...
|
@ -0,0 +1,239 @@
|
||||
import os
|
||||
import genapi
|
||||
|
||||
from genapi import \
|
||||
TypeApi, GlobalVarApi, FunctionApi, BoolValuesApi
|
||||
|
||||
import numpy_api
|
||||
|
||||
# use annotated api when running under cpychecker
|
||||
h_template = r"""
|
||||
#if defined(_MULTIARRAYMODULE) || defined(WITH_CPYCHECKER_STEALS_REFERENCE_TO_ARG_ATTRIBUTE)
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
npy_bool obval;
|
||||
} PyBoolScalarObject;
|
||||
|
||||
extern NPY_NO_EXPORT PyTypeObject PyArrayMapIter_Type;
|
||||
extern NPY_NO_EXPORT PyTypeObject PyArrayNeighborhoodIter_Type;
|
||||
extern NPY_NO_EXPORT PyBoolScalarObject _PyArrayScalar_BoolValues[2];
|
||||
|
||||
%s
|
||||
|
||||
#else
|
||||
|
||||
#if defined(PY_ARRAY_UNIQUE_SYMBOL)
|
||||
#define PyArray_API PY_ARRAY_UNIQUE_SYMBOL
|
||||
#endif
|
||||
|
||||
#if defined(NO_IMPORT) || defined(NO_IMPORT_ARRAY)
|
||||
extern void **PyArray_API;
|
||||
#else
|
||||
#if defined(PY_ARRAY_UNIQUE_SYMBOL)
|
||||
void **PyArray_API;
|
||||
#else
|
||||
static void **PyArray_API=NULL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
%s
|
||||
|
||||
#if !defined(NO_IMPORT_ARRAY) && !defined(NO_IMPORT)
|
||||
static int
|
||||
_import_array(void)
|
||||
{
|
||||
int st;
|
||||
PyObject *numpy = PyImport_ImportModule("numpy.core._multiarray_umath");
|
||||
PyObject *c_api = NULL;
|
||||
|
||||
if (numpy == NULL) {
|
||||
return -1;
|
||||
}
|
||||
c_api = PyObject_GetAttrString(numpy, "_ARRAY_API");
|
||||
Py_DECREF(numpy);
|
||||
if (c_api == NULL) {
|
||||
PyErr_SetString(PyExc_AttributeError, "_ARRAY_API not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!PyCapsule_CheckExact(c_api)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "_ARRAY_API is not PyCapsule object");
|
||||
Py_DECREF(c_api);
|
||||
return -1;
|
||||
}
|
||||
PyArray_API = (void **)PyCapsule_GetPointer(c_api, NULL);
|
||||
Py_DECREF(c_api);
|
||||
if (PyArray_API == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "_ARRAY_API is NULL pointer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Perform runtime check of C API version */
|
||||
if (NPY_VERSION != PyArray_GetNDArrayCVersion()) {
|
||||
PyErr_Format(PyExc_RuntimeError, "module compiled against "\
|
||||
"ABI version 0x%%x but this version of numpy is 0x%%x", \
|
||||
(int) NPY_VERSION, (int) PyArray_GetNDArrayCVersion());
|
||||
return -1;
|
||||
}
|
||||
if (NPY_FEATURE_VERSION > PyArray_GetNDArrayCFeatureVersion()) {
|
||||
PyErr_Format(PyExc_RuntimeError, "module compiled against "\
|
||||
"API version 0x%%x but this version of numpy is 0x%%x", \
|
||||
(int) NPY_FEATURE_VERSION, (int) PyArray_GetNDArrayCFeatureVersion());
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform runtime check of endianness and check it matches the one set by
|
||||
* the headers (npy_endian.h) as a safeguard
|
||||
*/
|
||||
st = PyArray_GetEndianness();
|
||||
if (st == NPY_CPU_UNKNOWN_ENDIAN) {
|
||||
PyErr_Format(PyExc_RuntimeError, "FATAL: module compiled as unknown endian");
|
||||
return -1;
|
||||
}
|
||||
#if NPY_BYTE_ORDER == NPY_BIG_ENDIAN
|
||||
if (st != NPY_CPU_BIG) {
|
||||
PyErr_Format(PyExc_RuntimeError, "FATAL: module compiled as "\
|
||||
"big endian, but detected different endianness at runtime");
|
||||
return -1;
|
||||
}
|
||||
#elif NPY_BYTE_ORDER == NPY_LITTLE_ENDIAN
|
||||
if (st != NPY_CPU_LITTLE) {
|
||||
PyErr_Format(PyExc_RuntimeError, "FATAL: module compiled as "\
|
||||
"little endian, but detected different endianness at runtime");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define import_array() {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); return NULL; } }
|
||||
|
||||
#define import_array1(ret) {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); return ret; } }
|
||||
|
||||
#define import_array2(msg, ret) {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, msg); return ret; } }
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
"""
|
||||
|
||||
|
||||
c_template = r"""
|
||||
/* These pointers will be stored in the C-object for use in other
|
||||
extension modules
|
||||
*/
|
||||
|
||||
void *PyArray_API[] = {
|
||||
%s
|
||||
};
|
||||
"""
|
||||
|
||||
c_api_header = """
|
||||
===========
|
||||
NumPy C-API
|
||||
===========
|
||||
"""
|
||||
|
||||
def generate_api(output_dir, force=False):
|
||||
basename = 'multiarray_api'
|
||||
|
||||
h_file = os.path.join(output_dir, '__%s.h' % basename)
|
||||
c_file = os.path.join(output_dir, '__%s.c' % basename)
|
||||
d_file = os.path.join(output_dir, '%s.txt' % basename)
|
||||
targets = (h_file, c_file, d_file)
|
||||
|
||||
sources = numpy_api.multiarray_api
|
||||
|
||||
if (not force and not genapi.should_rebuild(targets, [numpy_api.__file__, __file__])):
|
||||
return targets
|
||||
else:
|
||||
do_generate_api(targets, sources)
|
||||
|
||||
return targets
|
||||
|
||||
def do_generate_api(targets, sources):
|
||||
header_file = targets[0]
|
||||
c_file = targets[1]
|
||||
doc_file = targets[2]
|
||||
|
||||
global_vars = sources[0]
|
||||
scalar_bool_values = sources[1]
|
||||
types_api = sources[2]
|
||||
multiarray_funcs = sources[3]
|
||||
|
||||
multiarray_api = sources[:]
|
||||
|
||||
module_list = []
|
||||
extension_list = []
|
||||
init_list = []
|
||||
|
||||
# Check multiarray api indexes
|
||||
multiarray_api_index = genapi.merge_api_dicts(multiarray_api)
|
||||
genapi.check_api_dict(multiarray_api_index)
|
||||
|
||||
numpyapi_list = genapi.get_api_functions('NUMPY_API',
|
||||
multiarray_funcs)
|
||||
|
||||
# FIXME: ordered_funcs_api is unused
|
||||
ordered_funcs_api = genapi.order_dict(multiarray_funcs)
|
||||
|
||||
# Create dict name -> *Api instance
|
||||
api_name = 'PyArray_API'
|
||||
multiarray_api_dict = {}
|
||||
for f in numpyapi_list:
|
||||
name = f.name
|
||||
index = multiarray_funcs[name][0]
|
||||
annotations = multiarray_funcs[name][1:]
|
||||
multiarray_api_dict[f.name] = FunctionApi(f.name, index, annotations,
|
||||
f.return_type,
|
||||
f.args, api_name)
|
||||
|
||||
for name, val in global_vars.items():
|
||||
index, type = val
|
||||
multiarray_api_dict[name] = GlobalVarApi(name, index, type, api_name)
|
||||
|
||||
for name, val in scalar_bool_values.items():
|
||||
index = val[0]
|
||||
multiarray_api_dict[name] = BoolValuesApi(name, index, api_name)
|
||||
|
||||
for name, val in types_api.items():
|
||||
index = val[0]
|
||||
internal_type = None if len(val) == 1 else val[1]
|
||||
multiarray_api_dict[name] = TypeApi(
|
||||
name, index, 'PyTypeObject', api_name, internal_type)
|
||||
|
||||
if len(multiarray_api_dict) != len(multiarray_api_index):
|
||||
keys_dict = set(multiarray_api_dict.keys())
|
||||
keys_index = set(multiarray_api_index.keys())
|
||||
raise AssertionError(
|
||||
"Multiarray API size mismatch - "
|
||||
"index has extra keys {}, dict has extra keys {}"
|
||||
.format(keys_index - keys_dict, keys_dict - keys_index)
|
||||
)
|
||||
|
||||
extension_list = []
|
||||
for name, index in genapi.order_dict(multiarray_api_index):
|
||||
api_item = multiarray_api_dict[name]
|
||||
extension_list.append(api_item.define_from_array_api_string())
|
||||
init_list.append(api_item.array_api_define())
|
||||
module_list.append(api_item.internal_define())
|
||||
|
||||
# Write to header
|
||||
s = h_template % ('\n'.join(module_list), '\n'.join(extension_list))
|
||||
genapi.write_file(header_file, s)
|
||||
|
||||
# Write to c-code
|
||||
s = c_template % ',\n'.join(init_list)
|
||||
genapi.write_file(c_file, s)
|
||||
|
||||
# write to documentation
|
||||
s = c_api_header
|
||||
for func in numpyapi_list:
|
||||
s += func.to_ReST()
|
||||
s += '\n\n'
|
||||
genapi.write_file(doc_file, s)
|
||||
|
||||
return targets
|
@ -0,0 +1,564 @@
|
||||
"""Machine limits for Float32 and Float64 and (long double) if available...
|
||||
|
||||
"""
|
||||
__all__ = ['finfo', 'iinfo']
|
||||
|
||||
import warnings
|
||||
|
||||
from .machar import MachAr
|
||||
from .overrides import set_module
|
||||
from . import numeric
|
||||
from . import numerictypes as ntypes
|
||||
from .numeric import array, inf
|
||||
from .umath import log10, exp2
|
||||
from . import umath
|
||||
|
||||
|
||||
def _fr0(a):
|
||||
"""fix rank-0 --> rank-1"""
|
||||
if a.ndim == 0:
|
||||
a = a.copy()
|
||||
a.shape = (1,)
|
||||
return a
|
||||
|
||||
|
||||
def _fr1(a):
|
||||
"""fix rank > 0 --> rank-0"""
|
||||
if a.size == 1:
|
||||
a = a.copy()
|
||||
a.shape = ()
|
||||
return a
|
||||
|
||||
class MachArLike:
|
||||
""" Object to simulate MachAr instance """
|
||||
|
||||
def __init__(self,
|
||||
ftype,
|
||||
*, eps, epsneg, huge, tiny, ibeta, **kwargs):
|
||||
params = _MACHAR_PARAMS[ftype]
|
||||
float_conv = lambda v: array([v], ftype)
|
||||
float_to_float = lambda v : _fr1(float_conv(v))
|
||||
float_to_str = lambda v: (params['fmt'] % array(_fr0(v)[0], ftype))
|
||||
|
||||
self.title = params['title']
|
||||
# Parameter types same as for discovered MachAr object.
|
||||
self.epsilon = self.eps = float_to_float(eps)
|
||||
self.epsneg = float_to_float(epsneg)
|
||||
self.xmax = self.huge = float_to_float(huge)
|
||||
self.xmin = self.tiny = float_to_float(tiny)
|
||||
self.ibeta = params['itype'](ibeta)
|
||||
self.__dict__.update(kwargs)
|
||||
self.precision = int(-log10(self.eps))
|
||||
self.resolution = float_to_float(float_conv(10) ** (-self.precision))
|
||||
self._str_eps = float_to_str(self.eps)
|
||||
self._str_epsneg = float_to_str(self.epsneg)
|
||||
self._str_xmin = float_to_str(self.xmin)
|
||||
self._str_xmax = float_to_str(self.xmax)
|
||||
self._str_resolution = float_to_str(self.resolution)
|
||||
|
||||
_convert_to_float = {
|
||||
ntypes.csingle: ntypes.single,
|
||||
ntypes.complex_: ntypes.float_,
|
||||
ntypes.clongfloat: ntypes.longfloat
|
||||
}
|
||||
|
||||
# Parameters for creating MachAr / MachAr-like objects
|
||||
_title_fmt = 'numpy {} precision floating point number'
|
||||
_MACHAR_PARAMS = {
|
||||
ntypes.double: dict(
|
||||
itype = ntypes.int64,
|
||||
fmt = '%24.16e',
|
||||
title = _title_fmt.format('double')),
|
||||
ntypes.single: dict(
|
||||
itype = ntypes.int32,
|
||||
fmt = '%15.7e',
|
||||
title = _title_fmt.format('single')),
|
||||
ntypes.longdouble: dict(
|
||||
itype = ntypes.longlong,
|
||||
fmt = '%s',
|
||||
title = _title_fmt.format('long double')),
|
||||
ntypes.half: dict(
|
||||
itype = ntypes.int16,
|
||||
fmt = '%12.5e',
|
||||
title = _title_fmt.format('half'))}
|
||||
|
||||
# Key to identify the floating point type. Key is result of
|
||||
# ftype('-0.1').newbyteorder('<').tobytes()
|
||||
# See:
|
||||
# https://perl5.git.perl.org/perl.git/blob/3118d7d684b56cbeb702af874f4326683c45f045:/Configure
|
||||
_KNOWN_TYPES = {}
|
||||
def _register_type(machar, bytepat):
|
||||
_KNOWN_TYPES[bytepat] = machar
|
||||
_float_ma = {}
|
||||
|
||||
def _register_known_types():
|
||||
# Known parameters for float16
|
||||
# See docstring of MachAr class for description of parameters.
|
||||
f16 = ntypes.float16
|
||||
float16_ma = MachArLike(f16,
|
||||
machep=-10,
|
||||
negep=-11,
|
||||
minexp=-14,
|
||||
maxexp=16,
|
||||
it=10,
|
||||
iexp=5,
|
||||
ibeta=2,
|
||||
irnd=5,
|
||||
ngrd=0,
|
||||
eps=exp2(f16(-10)),
|
||||
epsneg=exp2(f16(-11)),
|
||||
huge=f16(65504),
|
||||
tiny=f16(2 ** -14))
|
||||
_register_type(float16_ma, b'f\xae')
|
||||
_float_ma[16] = float16_ma
|
||||
|
||||
# Known parameters for float32
|
||||
f32 = ntypes.float32
|
||||
float32_ma = MachArLike(f32,
|
||||
machep=-23,
|
||||
negep=-24,
|
||||
minexp=-126,
|
||||
maxexp=128,
|
||||
it=23,
|
||||
iexp=8,
|
||||
ibeta=2,
|
||||
irnd=5,
|
||||
ngrd=0,
|
||||
eps=exp2(f32(-23)),
|
||||
epsneg=exp2(f32(-24)),
|
||||
huge=f32((1 - 2 ** -24) * 2**128),
|
||||
tiny=exp2(f32(-126)))
|
||||
_register_type(float32_ma, b'\xcd\xcc\xcc\xbd')
|
||||
_float_ma[32] = float32_ma
|
||||
|
||||
# Known parameters for float64
|
||||
f64 = ntypes.float64
|
||||
epsneg_f64 = 2.0 ** -53.0
|
||||
tiny_f64 = 2.0 ** -1022.0
|
||||
float64_ma = MachArLike(f64,
|
||||
machep=-52,
|
||||
negep=-53,
|
||||
minexp=-1022,
|
||||
maxexp=1024,
|
||||
it=52,
|
||||
iexp=11,
|
||||
ibeta=2,
|
||||
irnd=5,
|
||||
ngrd=0,
|
||||
eps=2.0 ** -52.0,
|
||||
epsneg=epsneg_f64,
|
||||
huge=(1.0 - epsneg_f64) / tiny_f64 * f64(4),
|
||||
tiny=tiny_f64)
|
||||
_register_type(float64_ma, b'\x9a\x99\x99\x99\x99\x99\xb9\xbf')
|
||||
_float_ma[64] = float64_ma
|
||||
|
||||
# Known parameters for IEEE 754 128-bit binary float
|
||||
ld = ntypes.longdouble
|
||||
epsneg_f128 = exp2(ld(-113))
|
||||
tiny_f128 = exp2(ld(-16382))
|
||||
# Ignore runtime error when this is not f128
|
||||
with numeric.errstate(all='ignore'):
|
||||
huge_f128 = (ld(1) - epsneg_f128) / tiny_f128 * ld(4)
|
||||
float128_ma = MachArLike(ld,
|
||||
machep=-112,
|
||||
negep=-113,
|
||||
minexp=-16382,
|
||||
maxexp=16384,
|
||||
it=112,
|
||||
iexp=15,
|
||||
ibeta=2,
|
||||
irnd=5,
|
||||
ngrd=0,
|
||||
eps=exp2(ld(-112)),
|
||||
epsneg=epsneg_f128,
|
||||
huge=huge_f128,
|
||||
tiny=tiny_f128)
|
||||
# IEEE 754 128-bit binary float
|
||||
_register_type(float128_ma,
|
||||
b'\x9a\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xfb\xbf')
|
||||
_register_type(float128_ma,
|
||||
b'\x9a\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xfb\xbf')
|
||||
_float_ma[128] = float128_ma
|
||||
|
||||
# Known parameters for float80 (Intel 80-bit extended precision)
|
||||
epsneg_f80 = exp2(ld(-64))
|
||||
tiny_f80 = exp2(ld(-16382))
|
||||
# Ignore runtime error when this is not f80
|
||||
with numeric.errstate(all='ignore'):
|
||||
huge_f80 = (ld(1) - epsneg_f80) / tiny_f80 * ld(4)
|
||||
float80_ma = MachArLike(ld,
|
||||
machep=-63,
|
||||
negep=-64,
|
||||
minexp=-16382,
|
||||
maxexp=16384,
|
||||
it=63,
|
||||
iexp=15,
|
||||
ibeta=2,
|
||||
irnd=5,
|
||||
ngrd=0,
|
||||
eps=exp2(ld(-63)),
|
||||
epsneg=epsneg_f80,
|
||||
huge=huge_f80,
|
||||
tiny=tiny_f80)
|
||||
# float80, first 10 bytes containing actual storage
|
||||
_register_type(float80_ma, b'\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xfb\xbf')
|
||||
_float_ma[80] = float80_ma
|
||||
|
||||
# Guessed / known parameters for double double; see:
|
||||
# https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#Double-double_arithmetic
|
||||
# These numbers have the same exponent range as float64, but extended number of
|
||||
# digits in the significand.
|
||||
huge_dd = (umath.nextafter(ld(inf), ld(0))
|
||||
if hasattr(umath, 'nextafter') # Missing on some platforms?
|
||||
else float64_ma.huge)
|
||||
float_dd_ma = MachArLike(ld,
|
||||
machep=-105,
|
||||
negep=-106,
|
||||
minexp=-1022,
|
||||
maxexp=1024,
|
||||
it=105,
|
||||
iexp=11,
|
||||
ibeta=2,
|
||||
irnd=5,
|
||||
ngrd=0,
|
||||
eps=exp2(ld(-105)),
|
||||
epsneg= exp2(ld(-106)),
|
||||
huge=huge_dd,
|
||||
tiny=exp2(ld(-1022)))
|
||||
# double double; low, high order (e.g. PPC 64)
|
||||
_register_type(float_dd_ma,
|
||||
b'\x9a\x99\x99\x99\x99\x99Y<\x9a\x99\x99\x99\x99\x99\xb9\xbf')
|
||||
# double double; high, low order (e.g. PPC 64 le)
|
||||
_register_type(float_dd_ma,
|
||||
b'\x9a\x99\x99\x99\x99\x99\xb9\xbf\x9a\x99\x99\x99\x99\x99Y<')
|
||||
_float_ma['dd'] = float_dd_ma
|
||||
|
||||
|
||||
def _get_machar(ftype):
|
||||
""" Get MachAr instance or MachAr-like instance
|
||||
|
||||
Get parameters for floating point type, by first trying signatures of
|
||||
various known floating point types, then, if none match, attempting to
|
||||
identify parameters by analysis.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ftype : class
|
||||
Numpy floating point type class (e.g. ``np.float64``)
|
||||
|
||||
Returns
|
||||
-------
|
||||
ma_like : instance of :class:`MachAr` or :class:`MachArLike`
|
||||
Object giving floating point parameters for `ftype`.
|
||||
|
||||
Warns
|
||||
-----
|
||||
UserWarning
|
||||
If the binary signature of the float type is not in the dictionary of
|
||||
known float types.
|
||||
"""
|
||||
params = _MACHAR_PARAMS.get(ftype)
|
||||
if params is None:
|
||||
raise ValueError(repr(ftype))
|
||||
# Detect known / suspected types
|
||||
key = ftype('-0.1').newbyteorder('<').tobytes()
|
||||
ma_like = None
|
||||
if ftype == ntypes.longdouble:
|
||||
# Could be 80 bit == 10 byte extended precision, where last bytes can
|
||||
# be random garbage.
|
||||
# Comparing first 10 bytes to pattern first to avoid branching on the
|
||||
# random garbage.
|
||||
ma_like = _KNOWN_TYPES.get(key[:10])
|
||||
if ma_like is None:
|
||||
ma_like = _KNOWN_TYPES.get(key)
|
||||
if ma_like is not None:
|
||||
return ma_like
|
||||
# Fall back to parameter discovery
|
||||
warnings.warn(
|
||||
'Signature {} for {} does not match any known type: '
|
||||
'falling back to type probe function'.format(key, ftype),
|
||||
UserWarning, stacklevel=2)
|
||||
return _discovered_machar(ftype)
|
||||
|
||||
|
||||
def _discovered_machar(ftype):
|
||||
""" Create MachAr instance with found information on float types
|
||||
"""
|
||||
params = _MACHAR_PARAMS[ftype]
|
||||
return MachAr(lambda v: array([v], ftype),
|
||||
lambda v:_fr0(v.astype(params['itype']))[0],
|
||||
lambda v:array(_fr0(v)[0], ftype),
|
||||
lambda v: params['fmt'] % array(_fr0(v)[0], ftype),
|
||||
params['title'])
|
||||
|
||||
|
||||
@set_module('numpy')
|
||||
class finfo:
|
||||
"""
|
||||
finfo(dtype)
|
||||
|
||||
Machine limits for floating point types.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
bits : int
|
||||
The number of bits occupied by the type.
|
||||
eps : float
|
||||
The difference between 1.0 and the next smallest representable float
|
||||
larger than 1.0. For example, for 64-bit binary floats in the IEEE-754
|
||||
standard, ``eps = 2**-52``, approximately 2.22e-16.
|
||||
epsneg : float
|
||||
The difference between 1.0 and the next smallest representable float
|
||||
less than 1.0. For example, for 64-bit binary floats in the IEEE-754
|
||||
standard, ``epsneg = 2**-53``, approximately 1.11e-16.
|
||||
iexp : int
|
||||
The number of bits in the exponent portion of the floating point
|
||||
representation.
|
||||
machar : MachAr
|
||||
The object which calculated these parameters and holds more
|
||||
detailed information.
|
||||
machep : int
|
||||
The exponent that yields `eps`.
|
||||
max : floating point number of the appropriate type
|
||||
The largest representable number.
|
||||
maxexp : int
|
||||
The smallest positive power of the base (2) that causes overflow.
|
||||
min : floating point number of the appropriate type
|
||||
The smallest representable number, typically ``-max``.
|
||||
minexp : int
|
||||
The most negative power of the base (2) consistent with there
|
||||
being no leading 0's in the mantissa.
|
||||
negep : int
|
||||
The exponent that yields `epsneg`.
|
||||
nexp : int
|
||||
The number of bits in the exponent including its sign and bias.
|
||||
nmant : int
|
||||
The number of bits in the mantissa.
|
||||
precision : int
|
||||
The approximate number of decimal digits to which this kind of
|
||||
float is precise.
|
||||
resolution : floating point number of the appropriate type
|
||||
The approximate decimal resolution of this type, i.e.,
|
||||
``10**-precision``.
|
||||
tiny : float
|
||||
The smallest positive floating point number with full precision
|
||||
(see Notes).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
dtype : float, dtype, or instance
|
||||
Kind of floating point data-type about which to get information.
|
||||
|
||||
See Also
|
||||
--------
|
||||
MachAr : The implementation of the tests that produce this information.
|
||||
iinfo : The equivalent for integer data types.
|
||||
spacing : The distance between a value and the nearest adjacent number
|
||||
nextafter : The next floating point value after x1 towards x2
|
||||
|
||||
Notes
|
||||
-----
|
||||
For developers of NumPy: do not instantiate this at the module level.
|
||||
The initial calculation of these parameters is expensive and negatively
|
||||
impacts import times. These objects are cached, so calling ``finfo()``
|
||||
repeatedly inside your functions is not a problem.
|
||||
|
||||
Note that ``tiny`` is not actually the smallest positive representable
|
||||
value in a NumPy floating point type. As in the IEEE-754 standard [1]_,
|
||||
NumPy floating point types make use of subnormal numbers to fill the
|
||||
gap between 0 and ``tiny``. However, subnormal numbers may have
|
||||
significantly reduced precision [2]_.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] IEEE Standard for Floating-Point Arithmetic, IEEE Std 754-2008,
|
||||
pp.1-70, 2008, http://www.doi.org/10.1109/IEEESTD.2008.4610935
|
||||
.. [2] Wikipedia, "Denormal Numbers",
|
||||
https://en.wikipedia.org/wiki/Denormal_number
|
||||
"""
|
||||
|
||||
_finfo_cache = {}
|
||||
|
||||
def __new__(cls, dtype):
|
||||
try:
|
||||
dtype = numeric.dtype(dtype)
|
||||
except TypeError:
|
||||
# In case a float instance was given
|
||||
dtype = numeric.dtype(type(dtype))
|
||||
|
||||
obj = cls._finfo_cache.get(dtype, None)
|
||||
if obj is not None:
|
||||
return obj
|
||||
dtypes = [dtype]
|
||||
newdtype = numeric.obj2sctype(dtype)
|
||||
if newdtype is not dtype:
|
||||
dtypes.append(newdtype)
|
||||
dtype = newdtype
|
||||
if not issubclass(dtype, numeric.inexact):
|
||||
raise ValueError("data type %r not inexact" % (dtype))
|
||||
obj = cls._finfo_cache.get(dtype, None)
|
||||
if obj is not None:
|
||||
return obj
|
||||
if not issubclass(dtype, numeric.floating):
|
||||
newdtype = _convert_to_float[dtype]
|
||||
if newdtype is not dtype:
|
||||
dtypes.append(newdtype)
|
||||
dtype = newdtype
|
||||
obj = cls._finfo_cache.get(dtype, None)
|
||||
if obj is not None:
|
||||
return obj
|
||||
obj = object.__new__(cls)._init(dtype)
|
||||
for dt in dtypes:
|
||||
cls._finfo_cache[dt] = obj
|
||||
return obj
|
||||
|
||||
def _init(self, dtype):
|
||||
self.dtype = numeric.dtype(dtype)
|
||||
machar = _get_machar(dtype)
|
||||
|
||||
for word in ['precision', 'iexp',
|
||||
'maxexp', 'minexp', 'negep',
|
||||
'machep']:
|
||||
setattr(self, word, getattr(machar, word))
|
||||
for word in ['tiny', 'resolution', 'epsneg']:
|
||||
setattr(self, word, getattr(machar, word).flat[0])
|
||||
self.bits = self.dtype.itemsize * 8
|
||||
self.max = machar.huge.flat[0]
|
||||
self.min = -self.max
|
||||
self.eps = machar.eps.flat[0]
|
||||
self.nexp = machar.iexp
|
||||
self.nmant = machar.it
|
||||
self.machar = machar
|
||||
self._str_tiny = machar._str_xmin.strip()
|
||||
self._str_max = machar._str_xmax.strip()
|
||||
self._str_epsneg = machar._str_epsneg.strip()
|
||||
self._str_eps = machar._str_eps.strip()
|
||||
self._str_resolution = machar._str_resolution.strip()
|
||||
return self
|
||||
|
||||
def __str__(self):
|
||||
fmt = (
|
||||
'Machine parameters for %(dtype)s\n'
|
||||
'---------------------------------------------------------------\n'
|
||||
'precision = %(precision)3s resolution = %(_str_resolution)s\n'
|
||||
'machep = %(machep)6s eps = %(_str_eps)s\n'
|
||||
'negep = %(negep)6s epsneg = %(_str_epsneg)s\n'
|
||||
'minexp = %(minexp)6s tiny = %(_str_tiny)s\n'
|
||||
'maxexp = %(maxexp)6s max = %(_str_max)s\n'
|
||||
'nexp = %(nexp)6s min = -max\n'
|
||||
'---------------------------------------------------------------\n'
|
||||
)
|
||||
return fmt % self.__dict__
|
||||
|
||||
def __repr__(self):
|
||||
c = self.__class__.__name__
|
||||
d = self.__dict__.copy()
|
||||
d['klass'] = c
|
||||
return (("%(klass)s(resolution=%(resolution)s, min=-%(_str_max)s,"
|
||||
" max=%(_str_max)s, dtype=%(dtype)s)") % d)
|
||||
|
||||
|
||||
@set_module('numpy')
|
||||
class iinfo:
|
||||
"""
|
||||
iinfo(type)
|
||||
|
||||
Machine limits for integer types.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
bits : int
|
||||
The number of bits occupied by the type.
|
||||
min : int
|
||||
The smallest integer expressible by the type.
|
||||
max : int
|
||||
The largest integer expressible by the type.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
int_type : integer type, dtype, or instance
|
||||
The kind of integer data type to get information about.
|
||||
|
||||
See Also
|
||||
--------
|
||||
finfo : The equivalent for floating point data types.
|
||||
|
||||
Examples
|
||||
--------
|
||||
With types:
|
||||
|
||||
>>> ii16 = np.iinfo(np.int16)
|
||||
>>> ii16.min
|
||||
-32768
|
||||
>>> ii16.max
|
||||
32767
|
||||
>>> ii32 = np.iinfo(np.int32)
|
||||
>>> ii32.min
|
||||
-2147483648
|
||||
>>> ii32.max
|
||||
2147483647
|
||||
|
||||
With instances:
|
||||
|
||||
>>> ii32 = np.iinfo(np.int32(10))
|
||||
>>> ii32.min
|
||||
-2147483648
|
||||
>>> ii32.max
|
||||
2147483647
|
||||
|
||||
"""
|
||||
|
||||
_min_vals = {}
|
||||
_max_vals = {}
|
||||
|
||||
def __init__(self, int_type):
|
||||
try:
|
||||
self.dtype = numeric.dtype(int_type)
|
||||
except TypeError:
|
||||
self.dtype = numeric.dtype(type(int_type))
|
||||
self.kind = self.dtype.kind
|
||||
self.bits = self.dtype.itemsize * 8
|
||||
self.key = "%s%d" % (self.kind, self.bits)
|
||||
if self.kind not in 'iu':
|
||||
raise ValueError("Invalid integer data type %r." % (self.kind,))
|
||||
|
||||
@property
|
||||
def min(self):
|
||||
"""Minimum value of given dtype."""
|
||||
if self.kind == 'u':
|
||||
return 0
|
||||
else:
|
||||
try:
|
||||
val = iinfo._min_vals[self.key]
|
||||
except KeyError:
|
||||
val = int(-(1 << (self.bits-1)))
|
||||
iinfo._min_vals[self.key] = val
|
||||
return val
|
||||
|
||||
@property
|
||||
def max(self):
|
||||
"""Maximum value of given dtype."""
|
||||
try:
|
||||
val = iinfo._max_vals[self.key]
|
||||
except KeyError:
|
||||
if self.kind == 'u':
|
||||
val = int((1 << self.bits) - 1)
|
||||
else:
|
||||
val = int((1 << (self.bits-1)) - 1)
|
||||
iinfo._max_vals[self.key] = val
|
||||
return val
|
||||
|
||||
def __str__(self):
|
||||
"""String representation."""
|
||||
fmt = (
|
||||
'Machine parameters for %(dtype)s\n'
|
||||
'---------------------------------------------------------------\n'
|
||||
'min = %(min)s\n'
|
||||
'max = %(max)s\n'
|
||||
'---------------------------------------------------------------\n'
|
||||
)
|
||||
return fmt % {'dtype': self.dtype, 'min': self.min, 'max': self.max}
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(min=%s, max=%s, dtype=%s)" % (self.__class__.__name__,
|
||||
self.min, self.max, self.dtype)
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,311 @@
|
||||
|
||||
#ifdef _UMATHMODULE
|
||||
|
||||
extern NPY_NO_EXPORT PyTypeObject PyUFunc_Type;
|
||||
|
||||
extern NPY_NO_EXPORT PyTypeObject PyUFunc_Type;
|
||||
|
||||
NPY_NO_EXPORT PyObject * PyUFunc_FromFuncAndData \
|
||||
(PyUFuncGenericFunction *, void **, char *, int, int, int, int, const char *, const char *, int);
|
||||
NPY_NO_EXPORT int PyUFunc_RegisterLoopForType \
|
||||
(PyUFuncObject *, int, PyUFuncGenericFunction, const int *, void *);
|
||||
NPY_NO_EXPORT int PyUFunc_GenericFunction \
|
||||
(PyUFuncObject *NPY_UNUSED(ufunc), PyObject *NPY_UNUSED(args), PyObject *NPY_UNUSED(kwds), PyArrayObject **NPY_UNUSED(op));
|
||||
NPY_NO_EXPORT void PyUFunc_f_f_As_d_d \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_d_d \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_f_f \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_g_g \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_F_F_As_D_D \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_F_F \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_D_D \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_G_G \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_O_O \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_ff_f_As_dd_d \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_ff_f \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_dd_d \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_gg_g \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_FF_F_As_DD_D \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_DD_D \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_FF_F \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_GG_G \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_OO_O \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_O_O_method \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_OO_O_method \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_On_Om \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT int PyUFunc_GetPyValues \
|
||||
(char *, int *, int *, PyObject **);
|
||||
NPY_NO_EXPORT int PyUFunc_checkfperr \
|
||||
(int, PyObject *, int *);
|
||||
NPY_NO_EXPORT void PyUFunc_clearfperr \
|
||||
(void);
|
||||
NPY_NO_EXPORT int PyUFunc_getfperr \
|
||||
(void);
|
||||
NPY_NO_EXPORT int PyUFunc_handlefperr \
|
||||
(int, PyObject *, int, int *);
|
||||
NPY_NO_EXPORT int PyUFunc_ReplaceLoopBySignature \
|
||||
(PyUFuncObject *, PyUFuncGenericFunction, const int *, PyUFuncGenericFunction *);
|
||||
NPY_NO_EXPORT PyObject * PyUFunc_FromFuncAndDataAndSignature \
|
||||
(PyUFuncGenericFunction *, void **, char *, int, int, int, int, const char *, const char *, int, const char *);
|
||||
NPY_NO_EXPORT int PyUFunc_SetUsesArraysAsData \
|
||||
(void **NPY_UNUSED(data), size_t NPY_UNUSED(i));
|
||||
NPY_NO_EXPORT void PyUFunc_e_e \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_e_e_As_f_f \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_e_e_As_d_d \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_ee_e \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_ee_e_As_ff_f \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT void PyUFunc_ee_e_As_dd_d \
|
||||
(char **, npy_intp const *, npy_intp const *, void *);
|
||||
NPY_NO_EXPORT int PyUFunc_DefaultTypeResolver \
|
||||
(PyUFuncObject *, NPY_CASTING, PyArrayObject **, PyObject *, PyArray_Descr **);
|
||||
NPY_NO_EXPORT int PyUFunc_ValidateCasting \
|
||||
(PyUFuncObject *, NPY_CASTING, PyArrayObject **, PyArray_Descr **);
|
||||
NPY_NO_EXPORT int PyUFunc_RegisterLoopForDescr \
|
||||
(PyUFuncObject *, PyArray_Descr *, PyUFuncGenericFunction, PyArray_Descr **, void *);
|
||||
NPY_NO_EXPORT PyObject * PyUFunc_FromFuncAndDataAndSignatureAndIdentity \
|
||||
(PyUFuncGenericFunction *, void **, char *, int, int, int, int, const char *, const char *, const int, const char *, PyObject *);
|
||||
|
||||
#else
|
||||
|
||||
#if defined(PY_UFUNC_UNIQUE_SYMBOL)
|
||||
#define PyUFunc_API PY_UFUNC_UNIQUE_SYMBOL
|
||||
#endif
|
||||
|
||||
#if defined(NO_IMPORT) || defined(NO_IMPORT_UFUNC)
|
||||
extern void **PyUFunc_API;
|
||||
#else
|
||||
#if defined(PY_UFUNC_UNIQUE_SYMBOL)
|
||||
void **PyUFunc_API;
|
||||
#else
|
||||
static void **PyUFunc_API=NULL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define PyUFunc_Type (*(PyTypeObject *)PyUFunc_API[0])
|
||||
#define PyUFunc_FromFuncAndData \
|
||||
(*(PyObject * (*)(PyUFuncGenericFunction *, void **, char *, int, int, int, int, const char *, const char *, int)) \
|
||||
PyUFunc_API[1])
|
||||
#define PyUFunc_RegisterLoopForType \
|
||||
(*(int (*)(PyUFuncObject *, int, PyUFuncGenericFunction, const int *, void *)) \
|
||||
PyUFunc_API[2])
|
||||
#define PyUFunc_GenericFunction \
|
||||
(*(int (*)(PyUFuncObject *NPY_UNUSED(ufunc), PyObject *NPY_UNUSED(args), PyObject *NPY_UNUSED(kwds), PyArrayObject **NPY_UNUSED(op))) \
|
||||
PyUFunc_API[3])
|
||||
#define PyUFunc_f_f_As_d_d \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[4])
|
||||
#define PyUFunc_d_d \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[5])
|
||||
#define PyUFunc_f_f \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[6])
|
||||
#define PyUFunc_g_g \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[7])
|
||||
#define PyUFunc_F_F_As_D_D \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[8])
|
||||
#define PyUFunc_F_F \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[9])
|
||||
#define PyUFunc_D_D \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[10])
|
||||
#define PyUFunc_G_G \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[11])
|
||||
#define PyUFunc_O_O \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[12])
|
||||
#define PyUFunc_ff_f_As_dd_d \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[13])
|
||||
#define PyUFunc_ff_f \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[14])
|
||||
#define PyUFunc_dd_d \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[15])
|
||||
#define PyUFunc_gg_g \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[16])
|
||||
#define PyUFunc_FF_F_As_DD_D \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[17])
|
||||
#define PyUFunc_DD_D \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[18])
|
||||
#define PyUFunc_FF_F \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[19])
|
||||
#define PyUFunc_GG_G \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[20])
|
||||
#define PyUFunc_OO_O \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[21])
|
||||
#define PyUFunc_O_O_method \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[22])
|
||||
#define PyUFunc_OO_O_method \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[23])
|
||||
#define PyUFunc_On_Om \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[24])
|
||||
#define PyUFunc_GetPyValues \
|
||||
(*(int (*)(char *, int *, int *, PyObject **)) \
|
||||
PyUFunc_API[25])
|
||||
#define PyUFunc_checkfperr \
|
||||
(*(int (*)(int, PyObject *, int *)) \
|
||||
PyUFunc_API[26])
|
||||
#define PyUFunc_clearfperr \
|
||||
(*(void (*)(void)) \
|
||||
PyUFunc_API[27])
|
||||
#define PyUFunc_getfperr \
|
||||
(*(int (*)(void)) \
|
||||
PyUFunc_API[28])
|
||||
#define PyUFunc_handlefperr \
|
||||
(*(int (*)(int, PyObject *, int, int *)) \
|
||||
PyUFunc_API[29])
|
||||
#define PyUFunc_ReplaceLoopBySignature \
|
||||
(*(int (*)(PyUFuncObject *, PyUFuncGenericFunction, const int *, PyUFuncGenericFunction *)) \
|
||||
PyUFunc_API[30])
|
||||
#define PyUFunc_FromFuncAndDataAndSignature \
|
||||
(*(PyObject * (*)(PyUFuncGenericFunction *, void **, char *, int, int, int, int, const char *, const char *, int, const char *)) \
|
||||
PyUFunc_API[31])
|
||||
#define PyUFunc_SetUsesArraysAsData \
|
||||
(*(int (*)(void **NPY_UNUSED(data), size_t NPY_UNUSED(i))) \
|
||||
PyUFunc_API[32])
|
||||
#define PyUFunc_e_e \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[33])
|
||||
#define PyUFunc_e_e_As_f_f \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[34])
|
||||
#define PyUFunc_e_e_As_d_d \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[35])
|
||||
#define PyUFunc_ee_e \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[36])
|
||||
#define PyUFunc_ee_e_As_ff_f \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[37])
|
||||
#define PyUFunc_ee_e_As_dd_d \
|
||||
(*(void (*)(char **, npy_intp const *, npy_intp const *, void *)) \
|
||||
PyUFunc_API[38])
|
||||
#define PyUFunc_DefaultTypeResolver \
|
||||
(*(int (*)(PyUFuncObject *, NPY_CASTING, PyArrayObject **, PyObject *, PyArray_Descr **)) \
|
||||
PyUFunc_API[39])
|
||||
#define PyUFunc_ValidateCasting \
|
||||
(*(int (*)(PyUFuncObject *, NPY_CASTING, PyArrayObject **, PyArray_Descr **)) \
|
||||
PyUFunc_API[40])
|
||||
#define PyUFunc_RegisterLoopForDescr \
|
||||
(*(int (*)(PyUFuncObject *, PyArray_Descr *, PyUFuncGenericFunction, PyArray_Descr **, void *)) \
|
||||
PyUFunc_API[41])
|
||||
#define PyUFunc_FromFuncAndDataAndSignatureAndIdentity \
|
||||
(*(PyObject * (*)(PyUFuncGenericFunction *, void **, char *, int, int, int, int, const char *, const char *, const int, const char *, PyObject *)) \
|
||||
PyUFunc_API[42])
|
||||
|
||||
static NPY_INLINE int
|
||||
_import_umath(void)
|
||||
{
|
||||
PyObject *numpy = PyImport_ImportModule("numpy.core._multiarray_umath");
|
||||
PyObject *c_api = NULL;
|
||||
|
||||
if (numpy == NULL) {
|
||||
PyErr_SetString(PyExc_ImportError,
|
||||
"numpy.core._multiarray_umath failed to import");
|
||||
return -1;
|
||||
}
|
||||
c_api = PyObject_GetAttrString(numpy, "_UFUNC_API");
|
||||
Py_DECREF(numpy);
|
||||
if (c_api == NULL) {
|
||||
PyErr_SetString(PyExc_AttributeError, "_UFUNC_API not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!PyCapsule_CheckExact(c_api)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is not PyCapsule object");
|
||||
Py_DECREF(c_api);
|
||||
return -1;
|
||||
}
|
||||
PyUFunc_API = (void **)PyCapsule_GetPointer(c_api, NULL);
|
||||
Py_DECREF(c_api);
|
||||
if (PyUFunc_API == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is NULL pointer");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define import_umath() \
|
||||
do {\
|
||||
UFUNC_NOFPE\
|
||||
if (_import_umath() < 0) {\
|
||||
PyErr_Print();\
|
||||
PyErr_SetString(PyExc_ImportError,\
|
||||
"numpy.core.umath failed to import");\
|
||||
return NULL;\
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
#define import_umath1(ret) \
|
||||
do {\
|
||||
UFUNC_NOFPE\
|
||||
if (_import_umath() < 0) {\
|
||||
PyErr_Print();\
|
||||
PyErr_SetString(PyExc_ImportError,\
|
||||
"numpy.core.umath failed to import");\
|
||||
return ret;\
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
#define import_umath2(ret, msg) \
|
||||
do {\
|
||||
UFUNC_NOFPE\
|
||||
if (_import_umath() < 0) {\
|
||||
PyErr_Print();\
|
||||
PyErr_SetString(PyExc_ImportError, msg);\
|
||||
return ret;\
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
#define import_ufunc() \
|
||||
do {\
|
||||
UFUNC_NOFPE\
|
||||
if (_import_umath() < 0) {\
|
||||
PyErr_Print();\
|
||||
PyErr_SetString(PyExc_ImportError,\
|
||||
"numpy.core.umath failed to import");\
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
#endif
|
@ -0,0 +1,90 @@
|
||||
#ifndef _NPY_INCLUDE_NEIGHBORHOOD_IMP
|
||||
#error You should not include this header directly
|
||||
#endif
|
||||
/*
|
||||
* Private API (here for inline)
|
||||
*/
|
||||
static NPY_INLINE int
|
||||
_PyArrayNeighborhoodIter_IncrCoord(PyArrayNeighborhoodIterObject* iter);
|
||||
|
||||
/*
|
||||
* Update to next item of the iterator
|
||||
*
|
||||
* Note: this simply increment the coordinates vector, last dimension
|
||||
* incremented first , i.e, for dimension 3
|
||||
* ...
|
||||
* -1, -1, -1
|
||||
* -1, -1, 0
|
||||
* -1, -1, 1
|
||||
* ....
|
||||
* -1, 0, -1
|
||||
* -1, 0, 0
|
||||
* ....
|
||||
* 0, -1, -1
|
||||
* 0, -1, 0
|
||||
* ....
|
||||
*/
|
||||
#define _UPDATE_COORD_ITER(c) \
|
||||
wb = iter->coordinates[c] < iter->bounds[c][1]; \
|
||||
if (wb) { \
|
||||
iter->coordinates[c] += 1; \
|
||||
return 0; \
|
||||
} \
|
||||
else { \
|
||||
iter->coordinates[c] = iter->bounds[c][0]; \
|
||||
}
|
||||
|
||||
static NPY_INLINE int
|
||||
_PyArrayNeighborhoodIter_IncrCoord(PyArrayNeighborhoodIterObject* iter)
|
||||
{
|
||||
npy_intp i, wb;
|
||||
|
||||
for (i = iter->nd - 1; i >= 0; --i) {
|
||||
_UPDATE_COORD_ITER(i)
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Version optimized for 2d arrays, manual loop unrolling
|
||||
*/
|
||||
static NPY_INLINE int
|
||||
_PyArrayNeighborhoodIter_IncrCoord2D(PyArrayNeighborhoodIterObject* iter)
|
||||
{
|
||||
npy_intp wb;
|
||||
|
||||
_UPDATE_COORD_ITER(1)
|
||||
_UPDATE_COORD_ITER(0)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#undef _UPDATE_COORD_ITER
|
||||
|
||||
/*
|
||||
* Advance to the next neighbour
|
||||
*/
|
||||
static NPY_INLINE int
|
||||
PyArrayNeighborhoodIter_Next(PyArrayNeighborhoodIterObject* iter)
|
||||
{
|
||||
_PyArrayNeighborhoodIter_IncrCoord (iter);
|
||||
iter->dataptr = iter->translate((PyArrayIterObject*)iter, iter->coordinates);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset functions
|
||||
*/
|
||||
static NPY_INLINE int
|
||||
PyArrayNeighborhoodIter_Reset(PyArrayNeighborhoodIterObject* iter)
|
||||
{
|
||||
npy_intp i;
|
||||
|
||||
for (i = 0; i < iter->nd; ++i) {
|
||||
iter->coordinates[i] = iter->bounds[i][0];
|
||||
}
|
||||
iter->dataptr = iter->translate((PyArrayIterObject*)iter, iter->coordinates);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
#define NPY_SIZEOF_SHORT SIZEOF_SHORT
|
||||
#define NPY_SIZEOF_INT SIZEOF_INT
|
||||
#define NPY_SIZEOF_LONG SIZEOF_LONG
|
||||
#define NPY_SIZEOF_FLOAT 4
|
||||
#define NPY_SIZEOF_COMPLEX_FLOAT 8
|
||||
#define NPY_SIZEOF_DOUBLE 8
|
||||
#define NPY_SIZEOF_COMPLEX_DOUBLE 16
|
||||
#define NPY_SIZEOF_LONGDOUBLE 8
|
||||
#define NPY_SIZEOF_COMPLEX_LONGDOUBLE 16
|
||||
#define NPY_SIZEOF_PY_INTPTR_T 8
|
||||
#define NPY_SIZEOF_OFF_T 4
|
||||
#define NPY_SIZEOF_PY_LONG_LONG 8
|
||||
#define NPY_SIZEOF_LONGLONG 8
|
||||
#define NPY_NO_SIGNAL 1
|
||||
#define NPY_NO_SMP 0
|
||||
#define NPY_HAVE_DECL_ISNAN
|
||||
#define NPY_HAVE_DECL_ISINF
|
||||
#define NPY_HAVE_DECL_SIGNBIT
|
||||
#define NPY_HAVE_DECL_ISFINITE
|
||||
#define NPY_USE_C99_COMPLEX 1
|
||||
#define NPY_RELAXED_STRIDES_CHECKING 1
|
||||
#define NPY_USE_C99_FORMATS 1
|
||||
#define NPY_VISIBILITY_HIDDEN
|
||||
#define NPY_ABI_VERSION 0x01000009
|
||||
#define NPY_API_VERSION 0x0000000E
|
||||
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue