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