getlimits.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. """Machine limits for Float32 and Float64 and (long double) if available...
  2. """
  3. __all__ = ['finfo', 'iinfo']
  4. import types
  5. import warnings
  6. from .._utils import set_module
  7. from ._machar import MachAr
  8. from . import numeric
  9. from . import numerictypes as ntypes
  10. from .numeric import array, inf, nan
  11. from .umath import log10, exp2, nextafter, isnan
  12. def _fr0(a):
  13. """fix rank-0 --> rank-1"""
  14. if a.ndim == 0:
  15. a = a.copy()
  16. a.shape = (1,)
  17. return a
  18. def _fr1(a):
  19. """fix rank > 0 --> rank-0"""
  20. if a.size == 1:
  21. a = a.copy()
  22. a.shape = ()
  23. return a
  24. class MachArLike:
  25. """ Object to simulate MachAr instance """
  26. def __init__(self, ftype, *, eps, epsneg, huge, tiny,
  27. ibeta, smallest_subnormal=None, **kwargs):
  28. self.params = _MACHAR_PARAMS[ftype]
  29. self.ftype = ftype
  30. self.title = self.params['title']
  31. # Parameter types same as for discovered MachAr object.
  32. if not smallest_subnormal:
  33. self._smallest_subnormal = nextafter(
  34. self.ftype(0), self.ftype(1), dtype=self.ftype)
  35. else:
  36. self._smallest_subnormal = smallest_subnormal
  37. self.epsilon = self.eps = self._float_to_float(eps)
  38. self.epsneg = self._float_to_float(epsneg)
  39. self.xmax = self.huge = self._float_to_float(huge)
  40. self.xmin = self._float_to_float(tiny)
  41. self.smallest_normal = self.tiny = self._float_to_float(tiny)
  42. self.ibeta = self.params['itype'](ibeta)
  43. self.__dict__.update(kwargs)
  44. self.precision = int(-log10(self.eps))
  45. self.resolution = self._float_to_float(
  46. self._float_conv(10) ** (-self.precision))
  47. self._str_eps = self._float_to_str(self.eps)
  48. self._str_epsneg = self._float_to_str(self.epsneg)
  49. self._str_xmin = self._float_to_str(self.xmin)
  50. self._str_xmax = self._float_to_str(self.xmax)
  51. self._str_resolution = self._float_to_str(self.resolution)
  52. self._str_smallest_normal = self._float_to_str(self.xmin)
  53. @property
  54. def smallest_subnormal(self):
  55. """Return the value for the smallest subnormal.
  56. Returns
  57. -------
  58. smallest_subnormal : float
  59. value for the smallest subnormal.
  60. Warns
  61. -----
  62. UserWarning
  63. If the calculated value for the smallest subnormal is zero.
  64. """
  65. # Check that the calculated value is not zero, in case it raises a
  66. # warning.
  67. value = self._smallest_subnormal
  68. if self.ftype(0) == value:
  69. warnings.warn(
  70. 'The value of the smallest subnormal for {} type '
  71. 'is zero.'.format(self.ftype), UserWarning, stacklevel=2)
  72. return self._float_to_float(value)
  73. @property
  74. def _str_smallest_subnormal(self):
  75. """Return the string representation of the smallest subnormal."""
  76. return self._float_to_str(self.smallest_subnormal)
  77. def _float_to_float(self, value):
  78. """Converts float to float.
  79. Parameters
  80. ----------
  81. value : float
  82. value to be converted.
  83. """
  84. return _fr1(self._float_conv(value))
  85. def _float_conv(self, value):
  86. """Converts float to conv.
  87. Parameters
  88. ----------
  89. value : float
  90. value to be converted.
  91. """
  92. return array([value], self.ftype)
  93. def _float_to_str(self, value):
  94. """Converts float to str.
  95. Parameters
  96. ----------
  97. value : float
  98. value to be converted.
  99. """
  100. return self.params['fmt'] % array(_fr0(value)[0], self.ftype)
  101. _convert_to_float = {
  102. ntypes.csingle: ntypes.single,
  103. ntypes.complex128: ntypes.float64,
  104. ntypes.clongdouble: ntypes.longdouble
  105. }
  106. # Parameters for creating MachAr / MachAr-like objects
  107. _title_fmt = 'numpy {} precision floating point number'
  108. _MACHAR_PARAMS = {
  109. ntypes.double: dict(
  110. itype = ntypes.int64,
  111. fmt = '%24.16e',
  112. title = _title_fmt.format('double')),
  113. ntypes.single: dict(
  114. itype = ntypes.int32,
  115. fmt = '%15.7e',
  116. title = _title_fmt.format('single')),
  117. ntypes.longdouble: dict(
  118. itype = ntypes.longlong,
  119. fmt = '%s',
  120. title = _title_fmt.format('long double')),
  121. ntypes.half: dict(
  122. itype = ntypes.int16,
  123. fmt = '%12.5e',
  124. title = _title_fmt.format('half'))}
  125. # Key to identify the floating point type. Key is result of
  126. #
  127. # ftype = np.longdouble # or float64, float32, etc.
  128. # v = (ftype(-1.0) / ftype(10.0))
  129. # v.view(v.dtype.newbyteorder('<')).tobytes()
  130. #
  131. # Uses division to work around deficiencies in strtold on some platforms.
  132. # See:
  133. # https://perl5.git.perl.org/perl.git/blob/3118d7d684b56cbeb702af874f4326683c45f045:/Configure
  134. _KNOWN_TYPES = {}
  135. def _register_type(machar, bytepat):
  136. _KNOWN_TYPES[bytepat] = machar
  137. _float_ma = {}
  138. def _register_known_types():
  139. # Known parameters for float16
  140. # See docstring of MachAr class for description of parameters.
  141. f16 = ntypes.float16
  142. float16_ma = MachArLike(f16,
  143. machep=-10,
  144. negep=-11,
  145. minexp=-14,
  146. maxexp=16,
  147. it=10,
  148. iexp=5,
  149. ibeta=2,
  150. irnd=5,
  151. ngrd=0,
  152. eps=exp2(f16(-10)),
  153. epsneg=exp2(f16(-11)),
  154. huge=f16(65504),
  155. tiny=f16(2 ** -14))
  156. _register_type(float16_ma, b'f\xae')
  157. _float_ma[16] = float16_ma
  158. # Known parameters for float32
  159. f32 = ntypes.float32
  160. float32_ma = MachArLike(f32,
  161. machep=-23,
  162. negep=-24,
  163. minexp=-126,
  164. maxexp=128,
  165. it=23,
  166. iexp=8,
  167. ibeta=2,
  168. irnd=5,
  169. ngrd=0,
  170. eps=exp2(f32(-23)),
  171. epsneg=exp2(f32(-24)),
  172. huge=f32((1 - 2 ** -24) * 2**128),
  173. tiny=exp2(f32(-126)))
  174. _register_type(float32_ma, b'\xcd\xcc\xcc\xbd')
  175. _float_ma[32] = float32_ma
  176. # Known parameters for float64
  177. f64 = ntypes.float64
  178. epsneg_f64 = 2.0 ** -53.0
  179. tiny_f64 = 2.0 ** -1022.0
  180. float64_ma = MachArLike(f64,
  181. machep=-52,
  182. negep=-53,
  183. minexp=-1022,
  184. maxexp=1024,
  185. it=52,
  186. iexp=11,
  187. ibeta=2,
  188. irnd=5,
  189. ngrd=0,
  190. eps=2.0 ** -52.0,
  191. epsneg=epsneg_f64,
  192. huge=(1.0 - epsneg_f64) / tiny_f64 * f64(4),
  193. tiny=tiny_f64)
  194. _register_type(float64_ma, b'\x9a\x99\x99\x99\x99\x99\xb9\xbf')
  195. _float_ma[64] = float64_ma
  196. # Known parameters for IEEE 754 128-bit binary float
  197. ld = ntypes.longdouble
  198. epsneg_f128 = exp2(ld(-113))
  199. tiny_f128 = exp2(ld(-16382))
  200. # Ignore runtime error when this is not f128
  201. with numeric.errstate(all='ignore'):
  202. huge_f128 = (ld(1) - epsneg_f128) / tiny_f128 * ld(4)
  203. float128_ma = MachArLike(ld,
  204. machep=-112,
  205. negep=-113,
  206. minexp=-16382,
  207. maxexp=16384,
  208. it=112,
  209. iexp=15,
  210. ibeta=2,
  211. irnd=5,
  212. ngrd=0,
  213. eps=exp2(ld(-112)),
  214. epsneg=epsneg_f128,
  215. huge=huge_f128,
  216. tiny=tiny_f128)
  217. # IEEE 754 128-bit binary float
  218. _register_type(float128_ma,
  219. b'\x9a\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xfb\xbf')
  220. _float_ma[128] = float128_ma
  221. # Known parameters for float80 (Intel 80-bit extended precision)
  222. epsneg_f80 = exp2(ld(-64))
  223. tiny_f80 = exp2(ld(-16382))
  224. # Ignore runtime error when this is not f80
  225. with numeric.errstate(all='ignore'):
  226. huge_f80 = (ld(1) - epsneg_f80) / tiny_f80 * ld(4)
  227. float80_ma = MachArLike(ld,
  228. machep=-63,
  229. negep=-64,
  230. minexp=-16382,
  231. maxexp=16384,
  232. it=63,
  233. iexp=15,
  234. ibeta=2,
  235. irnd=5,
  236. ngrd=0,
  237. eps=exp2(ld(-63)),
  238. epsneg=epsneg_f80,
  239. huge=huge_f80,
  240. tiny=tiny_f80)
  241. # float80, first 10 bytes containing actual storage
  242. _register_type(float80_ma, b'\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xfb\xbf')
  243. _float_ma[80] = float80_ma
  244. # Guessed / known parameters for double double; see:
  245. # https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#Double-double_arithmetic
  246. # These numbers have the same exponent range as float64, but extended
  247. # number of digits in the significand.
  248. huge_dd = nextafter(ld(inf), ld(0), dtype=ld)
  249. # As the smallest_normal in double double is so hard to calculate we set
  250. # it to NaN.
  251. smallest_normal_dd = nan
  252. # Leave the same value for the smallest subnormal as double
  253. smallest_subnormal_dd = ld(nextafter(0., 1.))
  254. float_dd_ma = MachArLike(ld,
  255. machep=-105,
  256. negep=-106,
  257. minexp=-1022,
  258. maxexp=1024,
  259. it=105,
  260. iexp=11,
  261. ibeta=2,
  262. irnd=5,
  263. ngrd=0,
  264. eps=exp2(ld(-105)),
  265. epsneg=exp2(ld(-106)),
  266. huge=huge_dd,
  267. tiny=smallest_normal_dd,
  268. smallest_subnormal=smallest_subnormal_dd)
  269. # double double; low, high order (e.g. PPC 64)
  270. _register_type(float_dd_ma,
  271. b'\x9a\x99\x99\x99\x99\x99Y<\x9a\x99\x99\x99\x99\x99\xb9\xbf')
  272. # double double; high, low order (e.g. PPC 64 le)
  273. _register_type(float_dd_ma,
  274. b'\x9a\x99\x99\x99\x99\x99\xb9\xbf\x9a\x99\x99\x99\x99\x99Y<')
  275. _float_ma['dd'] = float_dd_ma
  276. def _get_machar(ftype):
  277. """ Get MachAr instance or MachAr-like instance
  278. Get parameters for floating point type, by first trying signatures of
  279. various known floating point types, then, if none match, attempting to
  280. identify parameters by analysis.
  281. Parameters
  282. ----------
  283. ftype : class
  284. Numpy floating point type class (e.g. ``np.float64``)
  285. Returns
  286. -------
  287. ma_like : instance of :class:`MachAr` or :class:`MachArLike`
  288. Object giving floating point parameters for `ftype`.
  289. Warns
  290. -----
  291. UserWarning
  292. If the binary signature of the float type is not in the dictionary of
  293. known float types.
  294. """
  295. params = _MACHAR_PARAMS.get(ftype)
  296. if params is None:
  297. raise ValueError(repr(ftype))
  298. # Detect known / suspected types
  299. # ftype(-1.0) / ftype(10.0) is better than ftype('-0.1') because stold
  300. # may be deficient
  301. key = (ftype(-1.0) / ftype(10.))
  302. key = key.view(key.dtype.newbyteorder("<")).tobytes()
  303. ma_like = None
  304. if ftype == ntypes.longdouble:
  305. # Could be 80 bit == 10 byte extended precision, where last bytes can
  306. # be random garbage.
  307. # Comparing first 10 bytes to pattern first to avoid branching on the
  308. # random garbage.
  309. ma_like = _KNOWN_TYPES.get(key[:10])
  310. if ma_like is None:
  311. # see if the full key is known.
  312. ma_like = _KNOWN_TYPES.get(key)
  313. if ma_like is None and len(key) == 16:
  314. # machine limits could be f80 masquerading as np.float128,
  315. # find all keys with length 16 and make new dict, but make the keys
  316. # only 10 bytes long, the last bytes can be random garbage
  317. _kt = {k[:10]: v for k, v in _KNOWN_TYPES.items() if len(k) == 16}
  318. ma_like = _kt.get(key[:10])
  319. if ma_like is not None:
  320. return ma_like
  321. # Fall back to parameter discovery
  322. warnings.warn(
  323. f'Signature {key} for {ftype} does not match any known type: '
  324. 'falling back to type probe function.\n'
  325. 'This warnings indicates broken support for the dtype!',
  326. UserWarning, stacklevel=2)
  327. return _discovered_machar(ftype)
  328. def _discovered_machar(ftype):
  329. """ Create MachAr instance with found information on float types
  330. TODO: MachAr should be retired completely ideally. We currently only
  331. ever use it system with broken longdouble (valgrind, WSL).
  332. """
  333. params = _MACHAR_PARAMS[ftype]
  334. return MachAr(lambda v: array([v], ftype),
  335. lambda v: _fr0(v.astype(params['itype']))[0],
  336. lambda v: array(_fr0(v)[0], ftype),
  337. lambda v: params['fmt'] % array(_fr0(v)[0], ftype),
  338. params['title'])
  339. @set_module('numpy')
  340. class finfo:
  341. """
  342. finfo(dtype)
  343. Machine limits for floating point types.
  344. Attributes
  345. ----------
  346. bits : int
  347. The number of bits occupied by the type.
  348. dtype : dtype
  349. Returns the dtype for which `finfo` returns information. For complex
  350. input, the returned dtype is the associated ``float*`` dtype for its
  351. real and complex components.
  352. eps : float
  353. The difference between 1.0 and the next smallest representable float
  354. larger than 1.0. For example, for 64-bit binary floats in the IEEE-754
  355. standard, ``eps = 2**-52``, approximately 2.22e-16.
  356. epsneg : float
  357. The difference between 1.0 and the next smallest representable float
  358. less than 1.0. For example, for 64-bit binary floats in the IEEE-754
  359. standard, ``epsneg = 2**-53``, approximately 1.11e-16.
  360. iexp : int
  361. The number of bits in the exponent portion of the floating point
  362. representation.
  363. machep : int
  364. The exponent that yields `eps`.
  365. max : floating point number of the appropriate type
  366. The largest representable number.
  367. maxexp : int
  368. The smallest positive power of the base (2) that causes overflow.
  369. min : floating point number of the appropriate type
  370. The smallest representable number, typically ``-max``.
  371. minexp : int
  372. The most negative power of the base (2) consistent with there
  373. being no leading 0's in the mantissa.
  374. negep : int
  375. The exponent that yields `epsneg`.
  376. nexp : int
  377. The number of bits in the exponent including its sign and bias.
  378. nmant : int
  379. The number of bits in the mantissa.
  380. precision : int
  381. The approximate number of decimal digits to which this kind of
  382. float is precise.
  383. resolution : floating point number of the appropriate type
  384. The approximate decimal resolution of this type, i.e.,
  385. ``10**-precision``.
  386. tiny : float
  387. An alias for `smallest_normal`, kept for backwards compatibility.
  388. smallest_normal : float
  389. The smallest positive floating point number with 1 as leading bit in
  390. the mantissa following IEEE-754 (see Notes).
  391. smallest_subnormal : float
  392. The smallest positive floating point number with 0 as leading bit in
  393. the mantissa following IEEE-754.
  394. Parameters
  395. ----------
  396. dtype : float, dtype, or instance
  397. Kind of floating point or complex floating point
  398. data-type about which to get information.
  399. See Also
  400. --------
  401. iinfo : The equivalent for integer data types.
  402. spacing : The distance between a value and the nearest adjacent number
  403. nextafter : The next floating point value after x1 towards x2
  404. Notes
  405. -----
  406. For developers of NumPy: do not instantiate this at the module level.
  407. The initial calculation of these parameters is expensive and negatively
  408. impacts import times. These objects are cached, so calling ``finfo()``
  409. repeatedly inside your functions is not a problem.
  410. Note that ``smallest_normal`` is not actually the smallest positive
  411. representable value in a NumPy floating point type. As in the IEEE-754
  412. standard [1]_, NumPy floating point types make use of subnormal numbers to
  413. fill the gap between 0 and ``smallest_normal``. However, subnormal numbers
  414. may have significantly reduced precision [2]_.
  415. This function can also be used for complex data types as well. If used,
  416. the output will be the same as the corresponding real float type
  417. (e.g. numpy.finfo(numpy.csingle) is the same as numpy.finfo(numpy.single)).
  418. However, the output is true for the real and imaginary components.
  419. References
  420. ----------
  421. .. [1] IEEE Standard for Floating-Point Arithmetic, IEEE Std 754-2008,
  422. pp.1-70, 2008, https://doi.org/10.1109/IEEESTD.2008.4610935
  423. .. [2] Wikipedia, "Denormal Numbers",
  424. https://en.wikipedia.org/wiki/Denormal_number
  425. Examples
  426. --------
  427. >>> import numpy as np
  428. >>> np.finfo(np.float64).dtype
  429. dtype('float64')
  430. >>> np.finfo(np.complex64).dtype
  431. dtype('float32')
  432. """
  433. _finfo_cache = {}
  434. __class_getitem__ = classmethod(types.GenericAlias)
  435. def __new__(cls, dtype):
  436. try:
  437. obj = cls._finfo_cache.get(dtype) # most common path
  438. if obj is not None:
  439. return obj
  440. except TypeError:
  441. pass
  442. if dtype is None:
  443. # Deprecated in NumPy 1.25, 2023-01-16
  444. warnings.warn(
  445. "finfo() dtype cannot be None. This behavior will "
  446. "raise an error in the future. (Deprecated in NumPy 1.25)",
  447. DeprecationWarning,
  448. stacklevel=2
  449. )
  450. try:
  451. dtype = numeric.dtype(dtype)
  452. except TypeError:
  453. # In case a float instance was given
  454. dtype = numeric.dtype(type(dtype))
  455. obj = cls._finfo_cache.get(dtype)
  456. if obj is not None:
  457. return obj
  458. dtypes = [dtype]
  459. newdtype = ntypes.obj2sctype(dtype)
  460. if newdtype is not dtype:
  461. dtypes.append(newdtype)
  462. dtype = newdtype
  463. if not issubclass(dtype, numeric.inexact):
  464. raise ValueError("data type %r not inexact" % (dtype))
  465. obj = cls._finfo_cache.get(dtype)
  466. if obj is not None:
  467. return obj
  468. if not issubclass(dtype, numeric.floating):
  469. newdtype = _convert_to_float[dtype]
  470. if newdtype is not dtype:
  471. # dtype changed, for example from complex128 to float64
  472. dtypes.append(newdtype)
  473. dtype = newdtype
  474. obj = cls._finfo_cache.get(dtype, None)
  475. if obj is not None:
  476. # the original dtype was not in the cache, but the new
  477. # dtype is in the cache. we add the original dtypes to
  478. # the cache and return the result
  479. for dt in dtypes:
  480. cls._finfo_cache[dt] = obj
  481. return obj
  482. obj = object.__new__(cls)._init(dtype)
  483. for dt in dtypes:
  484. cls._finfo_cache[dt] = obj
  485. return obj
  486. def _init(self, dtype):
  487. self.dtype = numeric.dtype(dtype)
  488. machar = _get_machar(dtype)
  489. for word in ['precision', 'iexp',
  490. 'maxexp', 'minexp', 'negep',
  491. 'machep']:
  492. setattr(self, word, getattr(machar, word))
  493. for word in ['resolution', 'epsneg', 'smallest_subnormal']:
  494. setattr(self, word, getattr(machar, word).flat[0])
  495. self.bits = self.dtype.itemsize * 8
  496. self.max = machar.huge.flat[0]
  497. self.min = -self.max
  498. self.eps = machar.eps.flat[0]
  499. self.nexp = machar.iexp
  500. self.nmant = machar.it
  501. self._machar = machar
  502. self._str_tiny = machar._str_xmin.strip()
  503. self._str_max = machar._str_xmax.strip()
  504. self._str_epsneg = machar._str_epsneg.strip()
  505. self._str_eps = machar._str_eps.strip()
  506. self._str_resolution = machar._str_resolution.strip()
  507. self._str_smallest_normal = machar._str_smallest_normal.strip()
  508. self._str_smallest_subnormal = machar._str_smallest_subnormal.strip()
  509. return self
  510. def __str__(self):
  511. fmt = (
  512. 'Machine parameters for %(dtype)s\n'
  513. '---------------------------------------------------------------\n'
  514. 'precision = %(precision)3s resolution = %(_str_resolution)s\n'
  515. 'machep = %(machep)6s eps = %(_str_eps)s\n'
  516. 'negep = %(negep)6s epsneg = %(_str_epsneg)s\n'
  517. 'minexp = %(minexp)6s tiny = %(_str_tiny)s\n'
  518. 'maxexp = %(maxexp)6s max = %(_str_max)s\n'
  519. 'nexp = %(nexp)6s min = -max\n'
  520. 'smallest_normal = %(_str_smallest_normal)s '
  521. 'smallest_subnormal = %(_str_smallest_subnormal)s\n'
  522. '---------------------------------------------------------------\n'
  523. )
  524. return fmt % self.__dict__
  525. def __repr__(self):
  526. c = self.__class__.__name__
  527. d = self.__dict__.copy()
  528. d['klass'] = c
  529. return (("%(klass)s(resolution=%(resolution)s, min=-%(_str_max)s,"
  530. " max=%(_str_max)s, dtype=%(dtype)s)") % d)
  531. @property
  532. def smallest_normal(self):
  533. """Return the value for the smallest normal.
  534. Returns
  535. -------
  536. smallest_normal : float
  537. Value for the smallest normal.
  538. Warns
  539. -----
  540. UserWarning
  541. If the calculated value for the smallest normal is requested for
  542. double-double.
  543. """
  544. # This check is necessary because the value for smallest_normal is
  545. # platform dependent for longdouble types.
  546. if isnan(self._machar.smallest_normal.flat[0]):
  547. warnings.warn(
  548. 'The value of smallest normal is undefined for double double',
  549. UserWarning, stacklevel=2)
  550. return self._machar.smallest_normal.flat[0]
  551. @property
  552. def tiny(self):
  553. """Return the value for tiny, alias of smallest_normal.
  554. Returns
  555. -------
  556. tiny : float
  557. Value for the smallest normal, alias of smallest_normal.
  558. Warns
  559. -----
  560. UserWarning
  561. If the calculated value for the smallest normal is requested for
  562. double-double.
  563. """
  564. return self.smallest_normal
  565. @set_module('numpy')
  566. class iinfo:
  567. """
  568. iinfo(type)
  569. Machine limits for integer types.
  570. Attributes
  571. ----------
  572. bits : int
  573. The number of bits occupied by the type.
  574. dtype : dtype
  575. Returns the dtype for which `iinfo` returns information.
  576. min : int
  577. The smallest integer expressible by the type.
  578. max : int
  579. The largest integer expressible by the type.
  580. Parameters
  581. ----------
  582. int_type : integer type, dtype, or instance
  583. The kind of integer data type to get information about.
  584. See Also
  585. --------
  586. finfo : The equivalent for floating point data types.
  587. Examples
  588. --------
  589. With types:
  590. >>> import numpy as np
  591. >>> ii16 = np.iinfo(np.int16)
  592. >>> ii16.min
  593. -32768
  594. >>> ii16.max
  595. 32767
  596. >>> ii32 = np.iinfo(np.int32)
  597. >>> ii32.min
  598. -2147483648
  599. >>> ii32.max
  600. 2147483647
  601. With instances:
  602. >>> ii32 = np.iinfo(np.int32(10))
  603. >>> ii32.min
  604. -2147483648
  605. >>> ii32.max
  606. 2147483647
  607. """
  608. _min_vals = {}
  609. _max_vals = {}
  610. __class_getitem__ = classmethod(types.GenericAlias)
  611. def __init__(self, int_type):
  612. try:
  613. self.dtype = numeric.dtype(int_type)
  614. except TypeError:
  615. self.dtype = numeric.dtype(type(int_type))
  616. self.kind = self.dtype.kind
  617. self.bits = self.dtype.itemsize * 8
  618. self.key = "%s%d" % (self.kind, self.bits)
  619. if self.kind not in 'iu':
  620. raise ValueError("Invalid integer data type %r." % (self.kind,))
  621. @property
  622. def min(self):
  623. """Minimum value of given dtype."""
  624. if self.kind == 'u':
  625. return 0
  626. else:
  627. try:
  628. val = iinfo._min_vals[self.key]
  629. except KeyError:
  630. val = int(-(1 << (self.bits-1)))
  631. iinfo._min_vals[self.key] = val
  632. return val
  633. @property
  634. def max(self):
  635. """Maximum value of given dtype."""
  636. try:
  637. val = iinfo._max_vals[self.key]
  638. except KeyError:
  639. if self.kind == 'u':
  640. val = int((1 << self.bits) - 1)
  641. else:
  642. val = int((1 << (self.bits-1)) - 1)
  643. iinfo._max_vals[self.key] = val
  644. return val
  645. def __str__(self):
  646. """String representation."""
  647. fmt = (
  648. 'Machine parameters for %(dtype)s\n'
  649. '---------------------------------------------------------------\n'
  650. 'min = %(min)s\n'
  651. 'max = %(max)s\n'
  652. '---------------------------------------------------------------\n'
  653. )
  654. return fmt % {'dtype': self.dtype, 'min': self.min, 'max': self.max}
  655. def __repr__(self):
  656. return "%s(min=%s, max=%s, dtype=%s)" % (self.__class__.__name__,
  657. self.min, self.max, self.dtype)