690 lines
18 KiB
Python
690 lines
18 KiB
Python
"""
|
|
numerictypes: Define the numeric type objects
|
|
|
|
This module is designed so "from numerictypes import \\*" is safe.
|
|
Exported symbols include:
|
|
|
|
Dictionary with all registered number types (including aliases):
|
|
sctypeDict
|
|
|
|
Type objects (not all will be available, depends on platform):
|
|
see variable sctypes for which ones you have
|
|
|
|
Bit-width names
|
|
|
|
int8 int16 int32 int64 int128
|
|
uint8 uint16 uint32 uint64 uint128
|
|
float16 float32 float64 float96 float128 float256
|
|
complex32 complex64 complex128 complex192 complex256 complex512
|
|
datetime64 timedelta64
|
|
|
|
c-based names
|
|
|
|
bool_
|
|
|
|
object_
|
|
|
|
void, str_, unicode_
|
|
|
|
byte, ubyte,
|
|
short, ushort
|
|
intc, uintc,
|
|
intp, uintp,
|
|
int_, uint,
|
|
longlong, ulonglong,
|
|
|
|
single, csingle,
|
|
float_, complex_,
|
|
longfloat, clongfloat,
|
|
|
|
As part of the type-hierarchy: xx -- is bit-width
|
|
|
|
generic
|
|
+-> bool_ (kind=b)
|
|
+-> number
|
|
| +-> integer
|
|
| | +-> signedinteger (intxx) (kind=i)
|
|
| | | byte
|
|
| | | short
|
|
| | | intc
|
|
| | | intp
|
|
| | | int_
|
|
| | | longlong
|
|
| | \\-> unsignedinteger (uintxx) (kind=u)
|
|
| | ubyte
|
|
| | ushort
|
|
| | uintc
|
|
| | uintp
|
|
| | uint_
|
|
| | ulonglong
|
|
| +-> inexact
|
|
| +-> floating (floatxx) (kind=f)
|
|
| | half
|
|
| | single
|
|
| | float_ (double)
|
|
| | longfloat
|
|
| \\-> complexfloating (complexxx) (kind=c)
|
|
| csingle (singlecomplex)
|
|
| complex_ (cfloat, cdouble)
|
|
| clongfloat (longcomplex)
|
|
+-> flexible
|
|
| +-> character
|
|
| | str_ (string_, bytes_) (kind=S) [Python 2]
|
|
| | unicode_ (kind=U) [Python 2]
|
|
| |
|
|
| | bytes_ (string_) (kind=S) [Python 3]
|
|
| | str_ (unicode_) (kind=U) [Python 3]
|
|
| |
|
|
| \\-> void (kind=V)
|
|
\\-> object_ (not used much) (kind=O)
|
|
|
|
"""
|
|
import numbers
|
|
import warnings
|
|
|
|
from .multiarray import (
|
|
ndarray, array, dtype, datetime_data, datetime_as_string,
|
|
busday_offset, busday_count, is_busday, busdaycalendar
|
|
)
|
|
from .._utils import set_module
|
|
|
|
# we add more at the bottom
|
|
__all__ = ['sctypeDict', 'sctypes',
|
|
'ScalarType', 'obj2sctype', 'cast', 'nbytes', 'sctype2char',
|
|
'maximum_sctype', 'issctype', 'typecodes', 'find_common_type',
|
|
'issubdtype', 'datetime_data', 'datetime_as_string',
|
|
'busday_offset', 'busday_count', 'is_busday', 'busdaycalendar',
|
|
]
|
|
|
|
# we don't need all these imports, but we need to keep them for compatibility
|
|
# for users using np.core.numerictypes.UPPER_TABLE
|
|
from ._string_helpers import (
|
|
english_lower, english_upper, english_capitalize, LOWER_TABLE, UPPER_TABLE
|
|
)
|
|
|
|
from ._type_aliases import (
|
|
sctypeDict,
|
|
allTypes,
|
|
bitname,
|
|
sctypes,
|
|
_concrete_types,
|
|
_concrete_typeinfo,
|
|
_bits_of,
|
|
)
|
|
from ._dtype import _kind_name
|
|
|
|
# we don't export these for import *, but we do want them accessible
|
|
# as numerictypes.bool, etc.
|
|
from builtins import bool, int, float, complex, object, str, bytes
|
|
from numpy.compat import long, unicode
|
|
|
|
|
|
# We use this later
|
|
generic = allTypes['generic']
|
|
|
|
genericTypeRank = ['bool', 'int8', 'uint8', 'int16', 'uint16',
|
|
'int32', 'uint32', 'int64', 'uint64', 'int128',
|
|
'uint128', 'float16',
|
|
'float32', 'float64', 'float80', 'float96', 'float128',
|
|
'float256',
|
|
'complex32', 'complex64', 'complex128', 'complex160',
|
|
'complex192', 'complex256', 'complex512', 'object']
|
|
|
|
@set_module('numpy')
|
|
def maximum_sctype(t):
|
|
"""
|
|
Return the scalar type of highest precision of the same kind as the input.
|
|
|
|
Parameters
|
|
----------
|
|
t : dtype or dtype specifier
|
|
The input data type. This can be a `dtype` object or an object that
|
|
is convertible to a `dtype`.
|
|
|
|
Returns
|
|
-------
|
|
out : dtype
|
|
The highest precision data type of the same kind (`dtype.kind`) as `t`.
|
|
|
|
See Also
|
|
--------
|
|
obj2sctype, mintypecode, sctype2char
|
|
dtype
|
|
|
|
Examples
|
|
--------
|
|
>>> np.maximum_sctype(int)
|
|
<class 'numpy.int64'>
|
|
>>> np.maximum_sctype(np.uint8)
|
|
<class 'numpy.uint64'>
|
|
>>> np.maximum_sctype(complex)
|
|
<class 'numpy.complex256'> # may vary
|
|
|
|
>>> np.maximum_sctype(str)
|
|
<class 'numpy.str_'>
|
|
|
|
>>> np.maximum_sctype('i2')
|
|
<class 'numpy.int64'>
|
|
>>> np.maximum_sctype('f4')
|
|
<class 'numpy.float128'> # may vary
|
|
|
|
"""
|
|
g = obj2sctype(t)
|
|
if g is None:
|
|
return t
|
|
t = g
|
|
base = _kind_name(dtype(t))
|
|
if base in sctypes:
|
|
return sctypes[base][-1]
|
|
else:
|
|
return t
|
|
|
|
|
|
@set_module('numpy')
|
|
def issctype(rep):
|
|
"""
|
|
Determines whether the given object represents a scalar data-type.
|
|
|
|
Parameters
|
|
----------
|
|
rep : any
|
|
If `rep` is an instance of a scalar dtype, True is returned. If not,
|
|
False is returned.
|
|
|
|
Returns
|
|
-------
|
|
out : bool
|
|
Boolean result of check whether `rep` is a scalar dtype.
|
|
|
|
See Also
|
|
--------
|
|
issubsctype, issubdtype, obj2sctype, sctype2char
|
|
|
|
Examples
|
|
--------
|
|
>>> np.issctype(np.int32)
|
|
True
|
|
>>> np.issctype(list)
|
|
False
|
|
>>> np.issctype(1.1)
|
|
False
|
|
|
|
Strings are also a scalar type:
|
|
|
|
>>> np.issctype(np.dtype('str'))
|
|
True
|
|
|
|
"""
|
|
if not isinstance(rep, (type, dtype)):
|
|
return False
|
|
try:
|
|
res = obj2sctype(rep)
|
|
if res and res != object_:
|
|
return True
|
|
return False
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
@set_module('numpy')
|
|
def obj2sctype(rep, default=None):
|
|
"""
|
|
Return the scalar dtype or NumPy equivalent of Python type of an object.
|
|
|
|
Parameters
|
|
----------
|
|
rep : any
|
|
The object of which the type is returned.
|
|
default : any, optional
|
|
If given, this is returned for objects whose types can not be
|
|
determined. If not given, None is returned for those objects.
|
|
|
|
Returns
|
|
-------
|
|
dtype : dtype or Python type
|
|
The data type of `rep`.
|
|
|
|
See Also
|
|
--------
|
|
sctype2char, issctype, issubsctype, issubdtype, maximum_sctype
|
|
|
|
Examples
|
|
--------
|
|
>>> np.obj2sctype(np.int32)
|
|
<class 'numpy.int32'>
|
|
>>> np.obj2sctype(np.array([1., 2.]))
|
|
<class 'numpy.float64'>
|
|
>>> np.obj2sctype(np.array([1.j]))
|
|
<class 'numpy.complex128'>
|
|
|
|
>>> np.obj2sctype(dict)
|
|
<class 'numpy.object_'>
|
|
>>> np.obj2sctype('string')
|
|
|
|
>>> np.obj2sctype(1, default=list)
|
|
<class 'list'>
|
|
|
|
"""
|
|
# prevent abstract classes being upcast
|
|
if isinstance(rep, type) and issubclass(rep, generic):
|
|
return rep
|
|
# extract dtype from arrays
|
|
if isinstance(rep, ndarray):
|
|
return rep.dtype.type
|
|
# fall back on dtype to convert
|
|
try:
|
|
res = dtype(rep)
|
|
except Exception:
|
|
return default
|
|
else:
|
|
return res.type
|
|
|
|
|
|
@set_module('numpy')
|
|
def issubclass_(arg1, arg2):
|
|
"""
|
|
Determine if a class is a subclass of a second class.
|
|
|
|
`issubclass_` is equivalent to the Python built-in ``issubclass``,
|
|
except that it returns False instead of raising a TypeError if one
|
|
of the arguments is not a class.
|
|
|
|
Parameters
|
|
----------
|
|
arg1 : class
|
|
Input class. True is returned if `arg1` is a subclass of `arg2`.
|
|
arg2 : class or tuple of classes.
|
|
Input class. If a tuple of classes, True is returned if `arg1` is a
|
|
subclass of any of the tuple elements.
|
|
|
|
Returns
|
|
-------
|
|
out : bool
|
|
Whether `arg1` is a subclass of `arg2` or not.
|
|
|
|
See Also
|
|
--------
|
|
issubsctype, issubdtype, issctype
|
|
|
|
Examples
|
|
--------
|
|
>>> np.issubclass_(np.int32, int)
|
|
False
|
|
>>> np.issubclass_(np.int32, float)
|
|
False
|
|
>>> np.issubclass_(np.float64, float)
|
|
True
|
|
|
|
"""
|
|
try:
|
|
return issubclass(arg1, arg2)
|
|
except TypeError:
|
|
return False
|
|
|
|
|
|
@set_module('numpy')
|
|
def issubsctype(arg1, arg2):
|
|
"""
|
|
Determine if the first argument is a subclass of the second argument.
|
|
|
|
Parameters
|
|
----------
|
|
arg1, arg2 : dtype or dtype specifier
|
|
Data-types.
|
|
|
|
Returns
|
|
-------
|
|
out : bool
|
|
The result.
|
|
|
|
See Also
|
|
--------
|
|
issctype, issubdtype, obj2sctype
|
|
|
|
Examples
|
|
--------
|
|
>>> np.issubsctype('S8', str)
|
|
False
|
|
>>> np.issubsctype(np.array([1]), int)
|
|
True
|
|
>>> np.issubsctype(np.array([1]), float)
|
|
False
|
|
|
|
"""
|
|
return issubclass(obj2sctype(arg1), obj2sctype(arg2))
|
|
|
|
|
|
@set_module('numpy')
|
|
def issubdtype(arg1, arg2):
|
|
r"""
|
|
Returns True if first argument is a typecode lower/equal in type hierarchy.
|
|
|
|
This is like the builtin :func:`issubclass`, but for `dtype`\ s.
|
|
|
|
Parameters
|
|
----------
|
|
arg1, arg2 : dtype_like
|
|
`dtype` or object coercible to one
|
|
|
|
Returns
|
|
-------
|
|
out : bool
|
|
|
|
See Also
|
|
--------
|
|
:ref:`arrays.scalars` : Overview of the numpy type hierarchy.
|
|
issubsctype, issubclass_
|
|
|
|
Examples
|
|
--------
|
|
`issubdtype` can be used to check the type of arrays:
|
|
|
|
>>> ints = np.array([1, 2, 3], dtype=np.int32)
|
|
>>> np.issubdtype(ints.dtype, np.integer)
|
|
True
|
|
>>> np.issubdtype(ints.dtype, np.floating)
|
|
False
|
|
|
|
>>> floats = np.array([1, 2, 3], dtype=np.float32)
|
|
>>> np.issubdtype(floats.dtype, np.integer)
|
|
False
|
|
>>> np.issubdtype(floats.dtype, np.floating)
|
|
True
|
|
|
|
Similar types of different sizes are not subdtypes of each other:
|
|
|
|
>>> np.issubdtype(np.float64, np.float32)
|
|
False
|
|
>>> np.issubdtype(np.float32, np.float64)
|
|
False
|
|
|
|
but both are subtypes of `floating`:
|
|
|
|
>>> np.issubdtype(np.float64, np.floating)
|
|
True
|
|
>>> np.issubdtype(np.float32, np.floating)
|
|
True
|
|
|
|
For convenience, dtype-like objects are allowed too:
|
|
|
|
>>> np.issubdtype('S1', np.string_)
|
|
True
|
|
>>> np.issubdtype('i4', np.signedinteger)
|
|
True
|
|
|
|
"""
|
|
if not issubclass_(arg1, generic):
|
|
arg1 = dtype(arg1).type
|
|
if not issubclass_(arg2, generic):
|
|
arg2 = dtype(arg2).type
|
|
|
|
return issubclass(arg1, arg2)
|
|
|
|
|
|
# This dictionary allows look up based on any alias for an array data-type
|
|
class _typedict(dict):
|
|
"""
|
|
Base object for a dictionary for look-up with any alias for an array dtype.
|
|
|
|
Instances of `_typedict` can not be used as dictionaries directly,
|
|
first they have to be populated.
|
|
|
|
"""
|
|
|
|
def __getitem__(self, obj):
|
|
return dict.__getitem__(self, obj2sctype(obj))
|
|
|
|
nbytes = _typedict()
|
|
_alignment = _typedict()
|
|
_maxvals = _typedict()
|
|
_minvals = _typedict()
|
|
def _construct_lookups():
|
|
for name, info in _concrete_typeinfo.items():
|
|
obj = info.type
|
|
nbytes[obj] = info.bits // 8
|
|
_alignment[obj] = info.alignment
|
|
if len(info) > 5:
|
|
_maxvals[obj] = info.max
|
|
_minvals[obj] = info.min
|
|
else:
|
|
_maxvals[obj] = None
|
|
_minvals[obj] = None
|
|
|
|
_construct_lookups()
|
|
|
|
|
|
@set_module('numpy')
|
|
def sctype2char(sctype):
|
|
"""
|
|
Return the string representation of a scalar dtype.
|
|
|
|
Parameters
|
|
----------
|
|
sctype : scalar dtype or object
|
|
If a scalar dtype, the corresponding string character is
|
|
returned. If an object, `sctype2char` tries to infer its scalar type
|
|
and then return the corresponding string character.
|
|
|
|
Returns
|
|
-------
|
|
typechar : str
|
|
The string character corresponding to the scalar type.
|
|
|
|
Raises
|
|
------
|
|
ValueError
|
|
If `sctype` is an object for which the type can not be inferred.
|
|
|
|
See Also
|
|
--------
|
|
obj2sctype, issctype, issubsctype, mintypecode
|
|
|
|
Examples
|
|
--------
|
|
>>> for sctype in [np.int32, np.double, np.complex_, np.string_, np.ndarray]:
|
|
... print(np.sctype2char(sctype))
|
|
l # may vary
|
|
d
|
|
D
|
|
S
|
|
O
|
|
|
|
>>> x = np.array([1., 2-1.j])
|
|
>>> np.sctype2char(x)
|
|
'D'
|
|
>>> np.sctype2char(list)
|
|
'O'
|
|
|
|
"""
|
|
sctype = obj2sctype(sctype)
|
|
if sctype is None:
|
|
raise ValueError("unrecognized type")
|
|
if sctype not in _concrete_types:
|
|
# for compatibility
|
|
raise KeyError(sctype)
|
|
return dtype(sctype).char
|
|
|
|
# Create dictionary of casting functions that wrap sequences
|
|
# indexed by type or type character
|
|
cast = _typedict()
|
|
for key in _concrete_types:
|
|
cast[key] = lambda x, k=key: array(x, copy=False).astype(k)
|
|
|
|
|
|
def _scalar_type_key(typ):
|
|
"""A ``key`` function for `sorted`."""
|
|
dt = dtype(typ)
|
|
return (dt.kind.lower(), dt.itemsize)
|
|
|
|
|
|
ScalarType = [int, float, complex, bool, bytes, str, memoryview]
|
|
ScalarType += sorted(_concrete_types, key=_scalar_type_key)
|
|
ScalarType = tuple(ScalarType)
|
|
|
|
|
|
# Now add the types we've determined to this module
|
|
for key in allTypes:
|
|
globals()[key] = allTypes[key]
|
|
__all__.append(key)
|
|
|
|
del key
|
|
|
|
typecodes = {'Character':'c',
|
|
'Integer':'bhilqp',
|
|
'UnsignedInteger':'BHILQP',
|
|
'Float':'efdg',
|
|
'Complex':'FDG',
|
|
'AllInteger':'bBhHiIlLqQpP',
|
|
'AllFloat':'efdgFDG',
|
|
'Datetime': 'Mm',
|
|
'All':'?bhilqpBHILQPefdgFDGSUVOMm'}
|
|
|
|
# backwards compatibility --- deprecated name
|
|
# Formal deprecation: Numpy 1.20.0, 2020-10-19 (see numpy/__init__.py)
|
|
typeDict = sctypeDict
|
|
|
|
# b -> boolean
|
|
# u -> unsigned integer
|
|
# i -> signed integer
|
|
# f -> floating point
|
|
# c -> complex
|
|
# M -> datetime
|
|
# m -> timedelta
|
|
# S -> string
|
|
# U -> Unicode string
|
|
# V -> record
|
|
# O -> Python object
|
|
_kind_list = ['b', 'u', 'i', 'f', 'c', 'S', 'U', 'V', 'O', 'M', 'm']
|
|
|
|
__test_types = '?'+typecodes['AllInteger'][:-2]+typecodes['AllFloat']+'O'
|
|
__len_test_types = len(__test_types)
|
|
|
|
# Keep incrementing until a common type both can be coerced to
|
|
# is found. Otherwise, return None
|
|
def _find_common_coerce(a, b):
|
|
if a > b:
|
|
return a
|
|
try:
|
|
thisind = __test_types.index(a.char)
|
|
except ValueError:
|
|
return None
|
|
return _can_coerce_all([a, b], start=thisind)
|
|
|
|
# Find a data-type that all data-types in a list can be coerced to
|
|
def _can_coerce_all(dtypelist, start=0):
|
|
N = len(dtypelist)
|
|
if N == 0:
|
|
return None
|
|
if N == 1:
|
|
return dtypelist[0]
|
|
thisind = start
|
|
while thisind < __len_test_types:
|
|
newdtype = dtype(__test_types[thisind])
|
|
numcoerce = len([x for x in dtypelist if newdtype >= x])
|
|
if numcoerce == N:
|
|
return newdtype
|
|
thisind += 1
|
|
return None
|
|
|
|
def _register_types():
|
|
numbers.Integral.register(integer)
|
|
numbers.Complex.register(inexact)
|
|
numbers.Real.register(floating)
|
|
numbers.Number.register(number)
|
|
|
|
_register_types()
|
|
|
|
|
|
@set_module('numpy')
|
|
def find_common_type(array_types, scalar_types):
|
|
"""
|
|
Determine common type following standard coercion rules.
|
|
|
|
.. deprecated:: NumPy 1.25
|
|
|
|
This function is deprecated, use `numpy.promote_types` or
|
|
`numpy.result_type` instead. To achieve semantics for the
|
|
`scalar_types` argument, use `numpy.result_type` and pass the Python
|
|
values `0`, `0.0`, or `0j`.
|
|
This will give the same results in almost all cases.
|
|
More information and rare exception can be found in the
|
|
`NumPy 1.25 release notes <https://numpy.org/devdocs/release/1.25.0-notes.html>`_.
|
|
|
|
Parameters
|
|
----------
|
|
array_types : sequence
|
|
A list of dtypes or dtype convertible objects representing arrays.
|
|
scalar_types : sequence
|
|
A list of dtypes or dtype convertible objects representing scalars.
|
|
|
|
Returns
|
|
-------
|
|
datatype : dtype
|
|
The common data type, which is the maximum of `array_types` ignoring
|
|
`scalar_types`, unless the maximum of `scalar_types` is of a
|
|
different kind (`dtype.kind`). If the kind is not understood, then
|
|
None is returned.
|
|
|
|
See Also
|
|
--------
|
|
dtype, common_type, can_cast, mintypecode
|
|
|
|
Examples
|
|
--------
|
|
>>> np.find_common_type([], [np.int64, np.float32, complex])
|
|
dtype('complex128')
|
|
>>> np.find_common_type([np.int64, np.float32], [])
|
|
dtype('float64')
|
|
|
|
The standard casting rules ensure that a scalar cannot up-cast an
|
|
array unless the scalar is of a fundamentally different kind of data
|
|
(i.e. under a different hierarchy in the data type hierarchy) then
|
|
the array:
|
|
|
|
>>> np.find_common_type([np.float32], [np.int64, np.float64])
|
|
dtype('float32')
|
|
|
|
Complex is of a different type, so it up-casts the float in the
|
|
`array_types` argument:
|
|
|
|
>>> np.find_common_type([np.float32], [complex])
|
|
dtype('complex128')
|
|
|
|
Type specifier strings are convertible to dtypes and can therefore
|
|
be used instead of dtypes:
|
|
|
|
>>> np.find_common_type(['f4', 'f4', 'i4'], ['c8'])
|
|
dtype('complex128')
|
|
|
|
"""
|
|
# Deprecated 2022-11-07, NumPy 1.25
|
|
warnings.warn(
|
|
"np.find_common_type is deprecated. Please use `np.result_type` "
|
|
"or `np.promote_types`.\n"
|
|
"See https://numpy.org/devdocs/release/1.25.0-notes.html and the "
|
|
"docs for more information. (Deprecated NumPy 1.25)",
|
|
DeprecationWarning, stacklevel=2)
|
|
|
|
array_types = [dtype(x) for x in array_types]
|
|
scalar_types = [dtype(x) for x in scalar_types]
|
|
|
|
maxa = _can_coerce_all(array_types)
|
|
maxsc = _can_coerce_all(scalar_types)
|
|
|
|
if maxa is None:
|
|
return maxsc
|
|
|
|
if maxsc is None:
|
|
return maxa
|
|
|
|
try:
|
|
index_a = _kind_list.index(maxa.kind)
|
|
index_sc = _kind_list.index(maxsc.kind)
|
|
except ValueError:
|
|
return None
|
|
|
|
if index_sc > index_a:
|
|
return _find_common_coerce(maxsc, maxa)
|
|
else:
|
|
return maxa
|