1"""

2 This file is separate from ``_add_newdocs.py`` so that it can be mocked out by

3 our sphinx ``conf.py`` during doc builds, where we want to avoid showing

4 platform-dependent information.

5"""

6 import sys

7 import os

8 from numpy.core import dtype

9 from numpy.core import numerictypes as _numerictypes

10 from numpy.core.function_base import add_newdoc

11

12##############################################################################

13#

14# Documentation for concrete scalar classes

15#

16##############################################################################

17

18 def numeric_type_aliases(aliases):

19 def type_aliases_gen():

20 for alias, doc in aliases:

21 try:

22 alias_type = getattr(_numerictypes, alias)

23 except AttributeError:

24 # The set of aliases that actually exist varies between platforms

25 pass

26 else:

27 yield (alias_type, alias, doc)

28 return list(type_aliases_gen())

29

30

31 possible_aliases = numeric_type_aliases([

32 ('int8', '8-bit signed integer (``-128`` to ``127``)'),

33 ('int16', '16-bit signed integer (``-32_768`` to ``32_767``)'),

34 ('int32', '32-bit signed integer (``-2_147_483_648`` to ``2_147_483_647``)'),

35 ('int64', '64-bit signed integer (``-9_223_372_036_854_775_808`` to ``9_223_372_036_854_775_807``)'),

36 ('intp', 'Signed integer large enough to fit pointer, compatible with C ``intptr_t``'),

37 ('uint8', '8-bit unsigned integer (``0`` to ``255``)'),

38 ('uint16', '16-bit unsigned integer (``0`` to ``65_535``)'),

39 ('uint32', '32-bit unsigned integer (``0`` to ``4_294_967_295``)'),

40 ('uint64', '64-bit unsigned integer (``0`` to ``18_446_744_073_709_551_615``)'),

41 ('uintp', 'Unsigned integer large enough to fit pointer, compatible with C ``uintptr_t``'),

42 ('float16', '16-bit-precision floating-point number type: sign bit, 5 bits exponent, 10 bits mantissa'),

43 ('float32', '32-bit-precision floating-point number type: sign bit, 8 bits exponent, 23 bits mantissa'),

44 ('float64', '64-bit precision floating-point number type: sign bit, 11 bits exponent, 52 bits mantissa'),

45 ('float96', '96-bit extended-precision floating-point number type'),

46 ('float128', '128-bit extended-precision floating-point number type'),

47 ('complex64', 'Complex number type composed of 2 32-bit-precision floating-point numbers'),

48 ('complex128', 'Complex number type composed of 2 64-bit-precision floating-point numbers'),

49 ('complex192', 'Complex number type composed of 2 96-bit extended-precision floating-point numbers'),

50 ('complex256', 'Complex number type composed of 2 128-bit extended-precision floating-point numbers'),

51 ])

52

53

54 def _get_platform_and_machine():

55 try:

56 system, _, _, _, machine = os.uname()

57 except AttributeError:

58 system = sys.platform

59 if system == 'win32':

60 machine = os.environ.get('PROCESSOR_ARCHITEW6432', '') \

61 or os.environ.get('PROCESSOR_ARCHITECTURE', '')

62 else:

63 machine = 'unknown'

64 return system, machine

65

66

67_system, _machine = _get_platform_and_machine()

68_doc_alias_string = f":Alias on this platform ({_system} {_machine}):"

69

70

71 def add_newdoc_for_scalar_type(obj, fixed_aliases, doc):

72 # note: `:field: value` is rST syntax which renders as field lists.

73 o = getattr(_numerictypes, obj)

74

75 character_code = dtype(o).char

76 canonical_name_doc = "" if obj == o.__name__ else \

77 f":Canonical name: `numpy.{obj}`\n "

78 if fixed_aliases:

79 alias_doc = ''.join(f":Alias: `numpy.{alias}`\n "

80 for alias in fixed_aliases)

81 else:

82 alias_doc = ''

83 alias_doc += ''.join(f"{_doc_alias_string} `numpy.{alias}`: {doc}.\n "

84 for (alias_type, alias, doc) in possible_aliases if alias_type is o)

85

86 docstring = f"""

87 {doc.strip()}

88

89 :Character code: ``'{character_code}'``

90 {canonical_name_doc}{alias_doc}

91 """

92

93 add_newdoc('numpy.core.numerictypes', obj, docstring)

94

95

96 add_newdoc_for_scalar_type('bool_', ['bool8'],

97 """

98 Boolean type (True or False), stored as a byte.

99

100 .. warning::

101

102 The :class:`bool_` type is not a subclass of the :class:`int_` type

103 (the :class:`bool_` is not even a number type). This is different

104 than Python's default implementation of :class:`bool` as a

105 sub-class of :class:`int`.

106 """)

107

108 add_newdoc_for_scalar_type('byte', [],

109 """

110 Signed integer type, compatible with C ``char``.

111 """)

112

113 add_newdoc_for_scalar_type('short', [],

114 """

115 Signed integer type, compatible with C ``short``.

116 """)

117

118 add_newdoc_for_scalar_type('intc', [],

119 """

120 Signed integer type, compatible with C ``int``.

121 """)

122

123 add_newdoc_for_scalar_type('int_', [],

124 """

125 Signed integer type, compatible with Python `int` and C ``long``.

126 """)

127

128 add_newdoc_for_scalar_type('longlong', [],

129 """

130 Signed integer type, compatible with C ``long long``.

131 """)

132

133 add_newdoc_for_scalar_type('ubyte', [],

134 """

135 Unsigned integer type, compatible with C ``unsigned char``.

136 """)

137

138 add_newdoc_for_scalar_type('ushort', [],

139 """

140 Unsigned integer type, compatible with C ``unsigned short``.

141 """)

142

143 add_newdoc_for_scalar_type('uintc', [],

144 """

145 Unsigned integer type, compatible with C ``unsigned int``.

146 """)

147

148 add_newdoc_for_scalar_type('uint', [],

149 """

150 Unsigned integer type, compatible with C ``unsigned long``.

151 """)

152

153 add_newdoc_for_scalar_type('ulonglong', [],

154 """

155 Signed integer type, compatible with C ``unsigned long long``.

156 """)

157

158 add_newdoc_for_scalar_type('half', [],

159 """

160 Half-precision floating-point number type.

161 """)

162

163 add_newdoc_for_scalar_type('single', [],

164 """

165 Single-precision floating-point number type, compatible with C ``float``.

166 """)

167

168 add_newdoc_for_scalar_type('double', ['float_'],

169 """

170 Double-precision floating-point number type, compatible with Python `float`

171 and C ``double``.

172 """)

173

174 add_newdoc_for_scalar_type('longdouble', ['longfloat'],

175 """

176 Extended-precision floating-point number type, compatible with C

177 ``long double`` but not necessarily with IEEE 754 quadruple-precision.

178 """)

179

180 add_newdoc_for_scalar_type('csingle', ['singlecomplex'],

181 """

182 Complex number type composed of two single-precision floating-point

183 numbers.

184 """)

185

186 add_newdoc_for_scalar_type('cdouble', ['cfloat', 'complex_'],

187 """

188 Complex number type composed of two double-precision floating-point

189 numbers, compatible with Python `complex`.

190 """)

191

192 add_newdoc_for_scalar_type('clongdouble', ['clongfloat', 'longcomplex'],

193 """

194 Complex number type composed of two extended-precision floating-point

195 numbers.

196 """)

197

198 add_newdoc_for_scalar_type('object_', [],

199 """

200 Any Python object.

201 """)

202

203 add_newdoc_for_scalar_type('str_', ['unicode_'],

204 r"""

205 A unicode string.

206

207 When used in arrays, this type strips trailing null codepoints.

208

209 Unlike the builtin `str`, this supports the :ref:`python:bufferobjects`, exposing its

210 contents as UCS4:

211

212 >>> m = memoryview(np.str_("abc"))

213 >>> m.format

214 '3w'

215 >>> m.tobytes()

216 b'a\x00\x00\x00b\x00\x00\x00c\x00\x00\x00'

217 """)

218

219 add_newdoc_for_scalar_type('bytes_', ['string_'],

220 r"""

221 A byte string.

222

223 When used in arrays, this type strips trailing null bytes.

224 """)

225

226 add_newdoc_for_scalar_type('void', [],

227 r"""

228 np.void(length_or_data, /, dtype=None)

229

230 Create a new structured or unstructured void scalar.

231

232 Parameters

233 ----------

234 length_or_data : int, array-like, bytes-like, object

235 One of multiple meanings (see notes). The length or

236 bytes data of an unstructured void. Or alternatively,

237 the data to be stored in the new scalar when `dtype`

238 is provided.

239 This can be an array-like, in which case an array may

240 be returned.

241 dtype : dtype, optional

242 If provided the dtype of the new scalar. This dtype must

243 be "void" dtype (i.e. a structured or unstructured void,

244 see also :ref:`defining-structured-types`).

245

246 ..versionadded:: 1.24

247

248 Notes

249 -----

250 For historical reasons and because void scalars can represent both

251 arbitrary byte data and structured dtypes, the void constructor

252 has three calling conventions:

253

254 1. ``np.void(5)`` creates a ``dtype="V5"`` scalar filled with five

255 ``\0`` bytes. The 5 can be a Python or NumPy integer.

256 2. ``np.void(b"bytes-like")`` creates a void scalar from the byte string.

257 The dtype itemsize will match the byte string length, here ``"V10"``.

258 3. When a ``dtype=`` is passed the call is rougly the same as an

259 array creation. However, a void scalar rather than array is returned.

260

261 Please see the examples which show all three different conventions.

262

263 Examples

264 --------

265 >>> np.void(5)

266 void(b'\x00\x00\x00\x00\x00')

267 >>> np.void(b'abcd')

268 void(b'\x61\x62\x63\x64')

269 >>> np.void((5, 3.2, "eggs"), dtype="i,d,S5")

270 (5, 3.2, b'eggs') # looks like a tuple, but is `np.void`

271 >>> np.void(3, dtype=[('x', np.int8), ('y', np.int8)])

272 (3, 3) # looks like a tuple, but is `np.void`

273

274 """)

275

276 add_newdoc_for_scalar_type('datetime64', [],

277 """

278 If created from a 64-bit integer, it represents an offset from

279 ``1970-01-01T00:00:00``.

280 If created from string, the string can be in ISO 8601 date

281 or datetime format.

282

283 >>> np.datetime64(10, 'Y')

284 numpy.datetime64('1980')

285 >>> np.datetime64('1980', 'Y')

286 numpy.datetime64('1980')

287 >>> np.datetime64(10, 'D')

288 numpy.datetime64('1970-01-11')

289

290 See :ref:`arrays.datetime` for more information.

291 """)

292

293 add_newdoc_for_scalar_type('timedelta64', [],

294 """

295 A timedelta stored as a 64-bit integer.

296

297 See :ref:`arrays.datetime` for more information.

298 """)

299

300 add_newdoc('numpy.core.numerictypes', "integer", ('is_integer',

301 """

302 integer.is_integer() -> bool

303

304 Return ``True`` if the number is finite with integral value.

305

306 .. versionadded:: 1.22

307

308 Examples

309 --------

310 >>> np.int64(-2).is_integer()

311 True

312 >>> np.uint32(5).is_integer()

313 True

314 """))

315

316# TODO: work out how to put this on the base class, np.floating

317 for float_name in ('half', 'single', 'double', 'longdouble'):

318 add_newdoc('numpy.core.numerictypes', float_name, ('as_integer_ratio',

319 """

320 {ftype}.as_integer_ratio() -> (int, int)

321

322 Return a pair of integers, whose ratio is exactly equal to the original

323 floating point number, and with a positive denominator.

324 Raise `OverflowError` on infinities and a `ValueError` on NaNs.

325

326 >>> np.{ftype}(10.0).as_integer_ratio()

327 (10, 1)

328 >>> np.{ftype}(0.0).as_integer_ratio()

329 (0, 1)

330 >>> np.{ftype}(-.25).as_integer_ratio()

331 (-1, 4)

332 """.format(ftype=float_name)))

333

334 add_newdoc('numpy.core.numerictypes', float_name, ('is_integer',

335 f"""

336 {float_name}.is_integer() -> bool

337

338 Return ``True`` if the floating point number is finite with integral

339 value, and ``False`` otherwise.

340

341 .. versionadded:: 1.22

342

343 Examples

344 --------

345 >>> np.{float_name}(-2.0).is_integer()

346 True

347 >>> np.{float_name}(3.2).is_integer()

348 False

349 """))

350

351 for int_name in ('int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32',

352 'int64', 'uint64', 'int64', 'uint64', 'int64', 'uint64'):

353 # Add negative examples for signed cases by checking typecode

354 add_newdoc('numpy.core.numerictypes', int_name, ('bit_count',

355 f"""

356 {int_name}.bit_count() -> int

357

358 Computes the number of 1-bits in the absolute value of the input.

359 Analogous to the builtin `int.bit_count` or ``popcount`` in C++.

360

361 Examples

362 --------

363 >>> np.{int_name}(127).bit_count()

364 7""" +

365 (f"""

366 >>> np.{int_name}(-127).bit_count()

367 7

368 """ if dtype(int_name).char.islower() else "")))