_type_aliases.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. """
  2. Due to compatibility, numpy has a very large number of different naming
  3. conventions for the scalar types (those subclassing from `numpy.generic`).
  4. This file produces a convoluted set of dictionaries mapping names to types,
  5. and sometimes other mappings too.
  6. .. data:: allTypes
  7. A dictionary of names to types that will be exposed as attributes through
  8. ``np.core.numerictypes.*``
  9. .. data:: sctypeDict
  10. Similar to `allTypes`, but maps a broader set of aliases to their types.
  11. .. data:: sctypeNA
  12. NumArray-compatible names for the scalar types. Contains not only
  13. ``name: type`` mappings, but ``char: name`` mappings too.
  14. .. deprecated:: 1.16
  15. .. data:: sctypes
  16. A dictionary keyed by a "type group" string, providing a list of types
  17. under that group.
  18. """
  19. import warnings
  20. from numpy.compat import unicode
  21. from numpy._globals import VisibleDeprecationWarning
  22. from numpy.core._string_helpers import english_lower, english_capitalize
  23. from numpy.core.multiarray import typeinfo, dtype
  24. from numpy.core._dtype import _kind_name
  25. sctypeDict = {} # Contains all leaf-node scalar types with aliases
  26. class TypeNADict(dict):
  27. def __getitem__(self, key):
  28. # 2018-06-24, 1.16
  29. warnings.warn('sctypeNA and typeNA will be removed in v1.18 '
  30. 'of numpy', VisibleDeprecationWarning, stacklevel=2)
  31. return dict.__getitem__(self, key)
  32. def get(self, key, default=None):
  33. # 2018-06-24, 1.16
  34. warnings.warn('sctypeNA and typeNA will be removed in v1.18 '
  35. 'of numpy', VisibleDeprecationWarning, stacklevel=2)
  36. return dict.get(self, key, default)
  37. sctypeNA = TypeNADict() # Contails all leaf-node types -> numarray type equivalences
  38. allTypes = {} # Collect the types we will add to the module
  39. # separate the actual type info from the abstract base classes
  40. _abstract_types = {}
  41. _concrete_typeinfo = {}
  42. for k, v in typeinfo.items():
  43. # make all the keys lowercase too
  44. k = english_lower(k)
  45. if isinstance(v, type):
  46. _abstract_types[k] = v
  47. else:
  48. _concrete_typeinfo[k] = v
  49. _concrete_types = {v.type for k, v in _concrete_typeinfo.items()}
  50. def _bits_of(obj):
  51. try:
  52. info = next(v for v in _concrete_typeinfo.values() if v.type is obj)
  53. except StopIteration:
  54. if obj in _abstract_types.values():
  55. raise ValueError("Cannot count the bits of an abstract type")
  56. # some third-party type - make a best-guess
  57. return dtype(obj).itemsize * 8
  58. else:
  59. return info.bits
  60. def bitname(obj):
  61. """Return a bit-width name for a given type object"""
  62. bits = _bits_of(obj)
  63. dt = dtype(obj)
  64. char = dt.kind
  65. base = _kind_name(dt)
  66. if base == 'object':
  67. bits = 0
  68. if bits != 0:
  69. char = "%s%d" % (char, bits // 8)
  70. return base, bits, char
  71. def _add_types():
  72. for name, info in _concrete_typeinfo.items():
  73. # define C-name and insert typenum and typechar references also
  74. allTypes[name] = info.type
  75. sctypeDict[name] = info.type
  76. sctypeDict[info.char] = info.type
  77. sctypeDict[info.num] = info.type
  78. for name, cls in _abstract_types.items():
  79. allTypes[name] = cls
  80. _add_types()
  81. # This is the priority order used to assign the bit-sized NPY_INTxx names, which
  82. # must match the order in npy_common.h in order for NPY_INTxx and np.intxx to be
  83. # consistent.
  84. # If two C types have the same size, then the earliest one in this list is used
  85. # as the sized name.
  86. _int_ctypes = ['long', 'longlong', 'int', 'short', 'byte']
  87. _uint_ctypes = list('u' + t for t in _int_ctypes)
  88. def _add_aliases():
  89. for name, info in _concrete_typeinfo.items():
  90. # these are handled by _add_integer_aliases
  91. if name in _int_ctypes or name in _uint_ctypes:
  92. continue
  93. # insert bit-width version for this class (if relevant)
  94. base, bit, char = bitname(info.type)
  95. myname = "%s%d" % (base, bit)
  96. # ensure that (c)longdouble does not overwrite the aliases assigned to
  97. # (c)double
  98. if name in ('longdouble', 'clongdouble') and myname in allTypes:
  99. continue
  100. base_capitalize = english_capitalize(base)
  101. if base == 'complex':
  102. na_name = '%s%d' % (base_capitalize, bit//2)
  103. elif base == 'bool':
  104. na_name = base_capitalize
  105. else:
  106. na_name = "%s%d" % (base_capitalize, bit)
  107. allTypes[myname] = info.type
  108. # add mapping for both the bit name and the numarray name
  109. sctypeDict[myname] = info.type
  110. sctypeDict[na_name] = info.type
  111. # add forward, reverse, and string mapping to numarray
  112. sctypeNA[na_name] = info.type
  113. sctypeNA[info.type] = na_name
  114. sctypeNA[info.char] = na_name
  115. sctypeDict[char] = info.type
  116. sctypeNA[char] = na_name
  117. _add_aliases()
  118. def _add_integer_aliases():
  119. seen_bits = set()
  120. for i_ctype, u_ctype in zip(_int_ctypes, _uint_ctypes):
  121. i_info = _concrete_typeinfo[i_ctype]
  122. u_info = _concrete_typeinfo[u_ctype]
  123. bits = i_info.bits # same for both
  124. for info, charname, intname, Intname in [
  125. (i_info,'i%d' % (bits//8,), 'int%d' % bits, 'Int%d' % bits),
  126. (u_info,'u%d' % (bits//8,), 'uint%d' % bits, 'UInt%d' % bits)]:
  127. if bits not in seen_bits:
  128. # sometimes two different types have the same number of bits
  129. # if so, the one iterated over first takes precedence
  130. allTypes[intname] = info.type
  131. sctypeDict[intname] = info.type
  132. sctypeDict[Intname] = info.type
  133. sctypeDict[charname] = info.type
  134. sctypeNA[Intname] = info.type
  135. sctypeNA[charname] = info.type
  136. sctypeNA[info.type] = Intname
  137. sctypeNA[info.char] = Intname
  138. seen_bits.add(bits)
  139. _add_integer_aliases()
  140. # We use these later
  141. void = allTypes['void']
  142. #
  143. # Rework the Python names (so that float and complex and int are consistent
  144. # with Python usage)
  145. #
  146. def _set_up_aliases():
  147. type_pairs = [('complex_', 'cdouble'),
  148. ('int0', 'intp'),
  149. ('uint0', 'uintp'),
  150. ('single', 'float'),
  151. ('csingle', 'cfloat'),
  152. ('singlecomplex', 'cfloat'),
  153. ('float_', 'double'),
  154. ('intc', 'int'),
  155. ('uintc', 'uint'),
  156. ('int_', 'long'),
  157. ('uint', 'ulong'),
  158. ('cfloat', 'cdouble'),
  159. ('longfloat', 'longdouble'),
  160. ('clongfloat', 'clongdouble'),
  161. ('longcomplex', 'clongdouble'),
  162. ('bool_', 'bool'),
  163. ('bytes_', 'string'),
  164. ('string_', 'string'),
  165. ('str_', 'unicode'),
  166. ('unicode_', 'unicode'),
  167. ('object_', 'object')]
  168. for alias, t in type_pairs:
  169. allTypes[alias] = allTypes[t]
  170. sctypeDict[alias] = sctypeDict[t]
  171. # Remove aliases overriding python types and modules
  172. to_remove = ['ulong', 'object', 'int', 'float',
  173. 'complex', 'bool', 'string', 'datetime', 'timedelta',
  174. 'bytes', 'str']
  175. for t in to_remove:
  176. try:
  177. del allTypes[t]
  178. del sctypeDict[t]
  179. except KeyError:
  180. pass
  181. _set_up_aliases()
  182. sctypes = {'int': [],
  183. 'uint':[],
  184. 'float':[],
  185. 'complex':[],
  186. 'others':[bool, object, bytes, unicode, void]}
  187. def _add_array_type(typename, bits):
  188. try:
  189. t = allTypes['%s%d' % (typename, bits)]
  190. except KeyError:
  191. pass
  192. else:
  193. sctypes[typename].append(t)
  194. def _set_array_types():
  195. ibytes = [1, 2, 4, 8, 16, 32, 64]
  196. fbytes = [2, 4, 8, 10, 12, 16, 32, 64]
  197. for bytes in ibytes:
  198. bits = 8*bytes
  199. _add_array_type('int', bits)
  200. _add_array_type('uint', bits)
  201. for bytes in fbytes:
  202. bits = 8*bytes
  203. _add_array_type('float', bits)
  204. _add_array_type('complex', 2*bits)
  205. _gi = dtype('p')
  206. if _gi.type not in sctypes['int']:
  207. indx = 0
  208. sz = _gi.itemsize
  209. _lst = sctypes['int']
  210. while (indx < len(_lst) and sz >= _lst[indx](0).itemsize):
  211. indx += 1
  212. sctypes['int'].insert(indx, _gi.type)
  213. sctypes['uint'].insert(indx, dtype('P').type)
  214. _set_array_types()
  215. # Add additional strings to the sctypeDict
  216. _toadd = ['int', 'float', 'complex', 'bool', 'object',
  217. 'str', 'bytes', ('a', 'bytes_')]
  218. for name in _toadd:
  219. if isinstance(name, tuple):
  220. sctypeDict[name[0]] = allTypes[name[1]]
  221. else:
  222. sctypeDict[name] = allTypes['%s_' % name]
  223. del _toadd, name