1"""
2This file is separate from ``_add_newdocs.py`` so that it can be mocked out by
3our sphinx ``conf.py`` during doc builds, where we want to avoid showing
4platform-dependent information.
5"""
6import os
7import sys
8
9from numpy._core import dtype, numerictypes as _numerictypes
10from numpy._core.function_base import add_newdoc
11
12##############################################################################
13#
14# Documentation for concrete scalar classes
15#
16##############################################################################
17
18def 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
31possible_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
54def _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# docstring prefix that cpython uses to populate `__text_signature__`
71_ARGUMENT_CLINIC_TEMPLATE = """{name}{signature}
72--
73
74{docstring}"""
75
76def add_newdoc_for_scalar_type(name: str, text_signature: str, doc: str) -> None:
77 # note: `:field: value` is rST syntax which renders as field lists.
78 cls = getattr(_numerictypes, name)
79 module = cls.__module__
80
81 lines_extra = [
82 "", # blank line after main doc
83 f":Character code: ``{dtype(cls).char!r}``",
84 ]
85
86 if name != cls.__name__:
87 lines_extra.append(f":Canonical name: `{module}.{name}`")
88
89 lines_extra.extend(
90 f"{_doc_alias_string} `{module}.{alias}`: {doc}."
91 for alias_type, alias, doc in possible_aliases
92 if alias_type is cls
93 )
94
95 docstring = _ARGUMENT_CLINIC_TEMPLATE.format(
96 name=cls.__name__, # must match the class name
97 signature=text_signature,
98 docstring="\n".join([doc.strip(), *lines_extra]),
99 )
100 add_newdoc('numpy._core.numerictypes', name, docstring)
101
102
103for bool_name in ('bool', 'bool_'):
104 add_newdoc_for_scalar_type(bool_name, '(value=False, /)', """
105Boolean type (True or False), stored as a byte.
106
107.. warning::
108
109 The :class:`bool` type is not a subclass of the :class:`int_` type
110 (the :class:`bool` is not even a number type). This is different
111 than Python's default implementation of :class:`bool` as a
112 sub-class of :class:`int`.
113""")
114
115add_newdoc_for_scalar_type('byte', '(value=0, /)', """
116Signed integer type, compatible with C ``char``.
117""")
118
119add_newdoc_for_scalar_type('short', '(value=0, /)', """
120Signed integer type, compatible with C ``short``.
121""")
122
123add_newdoc_for_scalar_type('intc', '(value=0, /)', """
124Signed integer type, compatible with C ``int``.
125""")
126
127add_newdoc_for_scalar_type('long', '(value=0, /)', """
128Signed integer type, compatible with C ``long``.
129""")
130
131# TODO: These docs probably need an if to highlight the default rather than
132# the C-types (and be correct).
133add_newdoc_for_scalar_type('int_', '(value=0, /)', """
134Default signed integer type, 64bit on 64bit systems and 32bit on 32bit systems.
135""")
136
137add_newdoc_for_scalar_type('longlong', '(value=0, /)', """
138Signed integer type, compatible with C ``long long``.
139""")
140
141add_newdoc_for_scalar_type('ubyte', '(value=0, /)', """
142Unsigned integer type, compatible with C ``unsigned char``.
143""")
144
145add_newdoc_for_scalar_type('ushort', '(value=0, /)', """
146Unsigned integer type, compatible with C ``unsigned short``.
147""")
148
149add_newdoc_for_scalar_type('uintc', '(value=0, /)', """
150Unsigned integer type, compatible with C ``unsigned int``.
151""")
152
153add_newdoc_for_scalar_type('uint', '(value=0, /)', """
154Unsigned signed integer type, 64bit on 64bit systems and 32bit on 32bit systems.
155""")
156
157add_newdoc_for_scalar_type('ulong', '(value=0, /)', """
158Unsigned integer type, compatible with C ``unsigned long``.
159""")
160
161add_newdoc_for_scalar_type('ulonglong', '(value=0, /)', """
162Unsigned integer type, compatible with C ``unsigned long long``.
163""")
164
165add_newdoc_for_scalar_type('half', '(value=0, /)', """
166Half-precision floating-point number type.
167""")
168
169add_newdoc_for_scalar_type('single', '(value=0, /)', """
170Single-precision floating-point number type, compatible with C ``float``.
171""")
172
173add_newdoc_for_scalar_type('double', '(value=0, /)', """
174Double-precision floating-point number type, compatible with Python :class:`float` and C ``double``.
175""")
176
177add_newdoc_for_scalar_type('longdouble', '(value=0, /)', """
178Extended-precision floating-point number type, compatible with C ``long double``
179but not necessarily with IEEE 754 quadruple-precision.
180""")
181
182add_newdoc_for_scalar_type('csingle', '(real=0, imag=0, /)', """
183Complex number type composed of two single-precision floating-point numbers.
184""")
185
186add_newdoc_for_scalar_type('cdouble', '(real=0, imag=0, /)', """
187Complex number type composed of two double-precision floating-point numbers,
188compatible with Python :class:`complex`.
189""")
190
191add_newdoc_for_scalar_type('clongdouble', '(real=0, imag=0, /)', """
192Complex number type composed of two extended-precision floating-point numbers.
193""")
194
195add_newdoc_for_scalar_type('object_', '(value=None, /)', """
196Any Python object.
197""")
198
199add_newdoc_for_scalar_type('str_', '(value="", /, *args, **kwargs)', r"""
200A unicode string.
201
202This type strips trailing null codepoints.
203
204>>> s = np.str_("abc\x00")
205>>> s
206'abc'
207
208Unlike the builtin :class:`str`, this supports the
209:ref:`python:bufferobjects`, exposing its contents as UCS4:
210
211>>> m = memoryview(np.str_("abc"))
212>>> m.format
213'3w'
214>>> m.tobytes()
215b'a\x00\x00\x00b\x00\x00\x00c\x00\x00\x00'
216""")
217
218add_newdoc_for_scalar_type('bytes_', '(value="", /, *args, **kwargs)', r"""
219A byte string.
220
221When used in arrays, this type strips trailing null bytes.
222""")
223
224add_newdoc_for_scalar_type('void', '(length_or_data, /, dtype=None)', r"""
225np.void(length_or_data, /, dtype=None)
226
227Create a new structured or unstructured void scalar.
228
229Parameters
230----------
231length_or_data : int, array-like, bytes-like, object
232 One of multiple meanings (see notes). The length or
233 bytes data of an unstructured void. Or alternatively,
234 the data to be stored in the new scalar when `dtype`
235 is provided.
236 This can be an array-like, in which case an array may
237 be returned.
238dtype : dtype, optional
239 If provided the dtype of the new scalar. This dtype must
240 be "void" dtype (i.e. a structured or unstructured void,
241 see also :ref:`defining-structured-types`).
242
243 .. versionadded:: 1.24
244
245Notes
246-----
247For historical reasons and because void scalars can represent both
248arbitrary byte data and structured dtypes, the void constructor
249has three calling conventions:
250
2511. ``np.void(5)`` creates a ``dtype="V5"`` scalar filled with five
252 ``\0`` bytes. The 5 can be a Python or NumPy integer.
2532. ``np.void(b"bytes-like")`` creates a void scalar from the byte string.
254 The dtype itemsize will match the byte string length, here ``"V10"``.
2553. When a ``dtype=`` is passed the call is roughly the same as an
256 array creation. However, a void scalar rather than array is returned.
257
258Please see the examples which show all three different conventions.
259
260Examples
261--------
262>>> np.void(5)
263np.void(b'\x00\x00\x00\x00\x00')
264>>> np.void(b'abcd')
265np.void(b'\x61\x62\x63\x64')
266>>> np.void((3.2, b'eggs'), dtype="d,S5")
267np.void((3.2, b'eggs'), dtype=[('f0', '<f8'), ('f1', 'S5')])
268>>> np.void(3, dtype=[('x', np.int8), ('y', np.int8)])
269np.void((3, 3), dtype=[('x', 'i1'), ('y', 'i1')])
270""")
271
272add_newdoc_for_scalar_type('datetime64', '(value=None, /, *args)', """
273If created from a 64-bit integer, it represents an offset from ``1970-01-01T00:00:00``.
274If created from string, the string can be in ISO 8601 date or datetime format.
275
276When parsing a string to create a datetime object, if the string contains
277a trailing timezone (A 'Z' or a timezone offset), the timezone will be
278dropped and a User Warning is given.
279
280Datetime64 objects should be considered to be UTC and therefore have an
281offset of +0000.
282
283>>> np.datetime64(10, 'Y')
284np.datetime64('1980')
285>>> np.datetime64('1980', 'Y')
286np.datetime64('1980')
287>>> np.datetime64(10, 'D')
288np.datetime64('1970-01-11')
289
290See :ref:`arrays.datetime` for more information.
291""")
292
293add_newdoc_for_scalar_type('timedelta64', '(value=0, /, *args)', """
294A timedelta stored as a 64-bit integer.
295
296See :ref:`arrays.datetime` for more information.
297""")
298
299add_newdoc('numpy._core.numerictypes', "integer", ('is_integer',
300 """
301 is_integer($self, /)
302 --
303
304 integer.is_integer() -> bool
305
306 Return ``True`` if the number is finite with integral value.
307
308 .. versionadded:: 1.22
309
310 Examples
311 --------
312 >>> import numpy as np
313 >>> np.int64(-2).is_integer()
314 True
315 >>> np.uint32(5).is_integer()
316 True
317 """))
318
319# TODO: work out how to put this on the base class, np.floating
320for float_name in ('half', 'single', 'double', 'longdouble'):
321 add_newdoc('numpy._core.numerictypes', float_name, ('as_integer_ratio',
322 f"""
323 as_integer_ratio($self, /)
324 --
325
326 {float_name}.as_integer_ratio() -> (int, int)
327
328 Return a pair of integers, whose ratio is exactly equal to the original
329 floating point number, and with a positive denominator.
330 Raise `OverflowError` on infinities and a `ValueError` on NaNs.
331
332 >>> np.{float_name}(10.0).as_integer_ratio()
333 (10, 1)
334 >>> np.{float_name}(0.0).as_integer_ratio()
335 (0, 1)
336 >>> np.{float_name}(-.25).as_integer_ratio()
337 (-1, 4)
338 """))
339
340 add_newdoc('numpy._core.numerictypes', float_name, ('is_integer',
341 f"""
342 is_integer($self, /)
343 --
344
345 {float_name}.is_integer() -> bool
346
347 Return ``True`` if the floating point number is finite with integral
348 value, and ``False`` otherwise.
349
350 .. versionadded:: 1.22
351
352 Examples
353 --------
354 >>> np.{float_name}(-2.0).is_integer()
355 True
356 >>> np.{float_name}(3.2).is_integer()
357 False
358 """))
359
360for int_name in ('int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32',
361 'int64', 'uint64', 'int64', 'uint64', 'int64', 'uint64',
362 'longlong', 'ulonglong'):
363 # Add negative examples for signed cases by checking typecode
364 add_newdoc('numpy._core.numerictypes', int_name, ('bit_count',
365 f"""
366 bit_count($self, /)
367 --
368
369 {int_name}.bit_count() -> int
370
371 Computes the number of 1-bits in the absolute value of the input.
372 Analogous to the builtin `int.bit_count` or ``popcount`` in C++.
373
374 Examples
375 --------
376 >>> np.{int_name}(127).bit_count()
377 7""" +
378 (f"""
379 >>> np.{int_name}(-127).bit_count()
380 7
381 """ if dtype(int_name).char.islower() else "")))