getlimits.py 25 KB

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