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

7.. data:: allTypes

8 A dictionary of names to types that will be exposed as attributes through

9 ``np.core.numerictypes.*``

10

11.. data:: sctypeDict

12 Similar to `allTypes`, but maps a broader set of aliases to their types.

13

14.. data:: sctypes

15 A dictionary keyed by a "type group" string, providing a list of types

16 under that group.

17

18"""

19

20 from numpy.compat import unicode

21 from numpy.core._string_helpers import english_lower

22 from numpy.core.multiarray import typeinfo, dtype

23 from numpy.core._dtype import _kind_name

24

25

26 sctypeDict = {} # Contains all leaf-node scalar types with aliases

27 allTypes = {} # Collect the types we will add to the module

28

29

30# separate the actual type info from the abstract base classes

31_abstract_types = {}

32_concrete_typeinfo = {}

33 for k, v in typeinfo.items():

34 # make all the keys lowercase too

35 k = english_lower(k)

36 if isinstance(v, type):

37 _abstract_types[k] = v

38 else:

39 _concrete_typeinfo[k] = v

40

41_concrete_types = {v.type for k, v in _concrete_typeinfo.items()}

42

43

44 def _bits_of(obj):

45 try:

46 info = next(v for v in _concrete_typeinfo.values() if v.type is obj)

47 except StopIteration:

48 if obj in _abstract_types.values():

49 msg = "Cannot count the bits of an abstract type"

50 raise ValueError(msg) from None

51

52 # some third-party type - make a best-guess

53 return dtype(obj).itemsize * 8

54 else:

55 return info.bits

56

57

58 def bitname(obj):

59 """Return a bit-width name for a given type object"""

60 bits = _bits_of(obj)

61 dt = dtype(obj)

62 char = dt.kind

63 base = _kind_name(dt)

64

65 if base == 'object':

66 bits = 0

67

68 if bits != 0:

69 char = "%s%d" % (char, bits // 8)

70

71 return base, bits, char

72

73

74 def _add_types():

75 for name, info in _concrete_typeinfo.items():

76 # define C-name and insert typenum and typechar references also

77 allTypes[name] = info.type

78 sctypeDict[name] = info.type

79 sctypeDict[info.char] = info.type

80 sctypeDict[info.num] = info.type

81

82 for name, cls in _abstract_types.items():

83 allTypes[name] = cls

84_add_types()

85

86# This is the priority order used to assign the bit-sized NPY_INTxx names, which

87# must match the order in npy_common.h in order for NPY_INTxx and np.intxx to be

88# consistent.

89# If two C types have the same size, then the earliest one in this list is used

90# as the sized name.

91_int_ctypes = ['long', 'longlong', 'int', 'short', 'byte']

92_uint_ctypes = list('u' + t for t in _int_ctypes)

93

94 def _add_aliases():

95 for name, info in _concrete_typeinfo.items():

96 # these are handled by _add_integer_aliases

97 if name in _int_ctypes or name in _uint_ctypes:

98 continue

99

100 # insert bit-width version for this class (if relevant)

101 base, bit, char = bitname(info.type)

102

103 myname = "%s%d" % (base, bit)

104

105 # ensure that (c)longdouble does not overwrite the aliases assigned to

106 # (c)double

107 if name in ('longdouble', 'clongdouble') and myname in allTypes:

108 continue

109

110 # Add to the main namespace if desired:

111 if bit != 0 and base != "bool":

112 allTypes[myname] = info.type

113

114 # add forward, reverse, and string mapping to numarray

115 sctypeDict[char] = info.type

116

117 # add mapping for both the bit name

118 sctypeDict[myname] = info.type

119

120

121_add_aliases()

122

123 def _add_integer_aliases():

124 seen_bits = set()

125 for i_ctype, u_ctype in zip(_int_ctypes, _uint_ctypes):

126 i_info = _concrete_typeinfo[i_ctype]

127 u_info = _concrete_typeinfo[u_ctype]

128 bits = i_info.bits # same for both

129

130 for info, charname, intname in [

131 (i_info,'i%d' % (bits//8,), 'int%d' % bits),

132 (u_info,'u%d' % (bits//8,), 'uint%d' % bits)]:

133 if bits not in seen_bits:

134 # sometimes two different types have the same number of bits

135 # if so, the one iterated over first takes precedence

136 allTypes[intname] = info.type

137 sctypeDict[intname] = info.type

138 sctypeDict[charname] = info.type

139

140 seen_bits.add(bits)

141

142_add_integer_aliases()

143

144# We use these later

145 void = allTypes['void']

146

147#

148# Rework the Python names (so that float and complex and int are consistent

149# with Python usage)

150#

151 def _set_up_aliases():

152 type_pairs = [('complex_', 'cdouble'),

153 ('single', 'float'),

154 ('csingle', 'cfloat'),

155 ('singlecomplex', 'cfloat'),

156 ('float_', 'double'),

157 ('intc', 'int'),

158 ('uintc', 'uint'),

159 ('int_', 'long'),

160 ('uint', 'ulong'),

161 ('cfloat', 'cdouble'),

162 ('longfloat', 'longdouble'),

163 ('clongfloat', 'clongdouble'),

164 ('longcomplex', 'clongdouble'),

165 ('bool_', 'bool'),

166 ('bytes_', 'string'),

167 ('string_', 'string'),

168 ('str_', 'unicode'),

169 ('unicode_', 'unicode'),

170 ('object_', 'object')]

171 for alias, t in type_pairs:

172 allTypes[alias] = allTypes[t]

173 sctypeDict[alias] = sctypeDict[t]

174 # Remove aliases overriding python types and modules

175 to_remove = ['object', 'int', 'float',

176 'complex', 'bool', 'string', 'datetime', 'timedelta',

177 'bytes', 'str']

178

179 for t in to_remove:

180 try:

181 del allTypes[t]

182 del sctypeDict[t]

183 except KeyError:

184 pass

185

186 # Additional aliases in sctypeDict that should not be exposed as attributes

187 attrs_to_remove = ['ulong']

188

189 for t in attrs_to_remove:

190 try:

191 del allTypes[t]

192 except KeyError:

193 pass

194_set_up_aliases()

195

196

197 sctypes = {'int': [],

198 'uint':[],

199 'float':[],

200 'complex':[],

201 'others':[bool, object, bytes, unicode, void]}

202

203 def _add_array_type(typename, bits):

204 try:

205 t = allTypes['%s%d' % (typename, bits)]

206 except KeyError:

207 pass

208 else:

209 sctypes[typename].append(t)

210

211 def _set_array_types():

212 ibytes = [1, 2, 4, 8, 16, 32, 64]

213 fbytes = [2, 4, 8, 10, 12, 16, 32, 64]

214 for bytes in ibytes:

215 bits = 8*bytes

216 _add_array_type('int', bits)

217 _add_array_type('uint', bits)

218 for bytes in fbytes:

219 bits = 8*bytes

220 _add_array_type('float', bits)

221 _add_array_type('complex', 2*bits)

222 _gi = dtype('p')

223 if _gi.type not in sctypes['int']:

224 indx = 0

225 sz = _gi.itemsize

226 _lst = sctypes['int']

227 while (indx < len(_lst) and sz >= _lst[indx](0).itemsize):

228 indx += 1

229 sctypes['int'].insert(indx, _gi.type)

230 sctypes['uint'].insert(indx, dtype('P').type)

231_set_array_types()

232

233

234# Add additional strings to the sctypeDict

235_toadd = ['int', 'float', 'complex', 'bool', 'object',

236 'str', 'bytes', ('a', 'bytes_'),

237 ('int0', 'intp'), ('uint0', 'uintp')]

238

239 for name in _toadd:

240 if isinstance(name, tuple):

241 sctypeDict[name[0]] = allTypes[name[1]]

242 else:

243 sctypeDict[name] = allTypes['%s_' % name]

244

245 del _toadd, name