Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/numpy/core/getlimits.py : 85%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Machine limits for Float32 and Float64 and (long double) if available...
3"""
4__all__ = ['finfo', 'iinfo']
6import warnings
8from .machar import MachAr
9from .overrides import set_module
10from . import numeric
11from . import numerictypes as ntypes
12from .numeric import array, inf
13from .umath import log10, exp2
14from . import umath
17def _fr0(a):
18 """fix rank-0 --> rank-1"""
19 if a.ndim == 0:
20 a = a.copy()
21 a.shape = (1,)
22 return a
25def _fr1(a):
26 """fix rank > 0 --> rank-0"""
27 if a.size == 1:
28 a = a.copy()
29 a.shape = ()
30 return a
32class MachArLike:
33 """ Object to simulate MachAr instance """
35 def __init__(self,
36 ftype,
37 *, eps, epsneg, huge, tiny, ibeta, **kwargs):
38 params = _MACHAR_PARAMS[ftype]
39 float_conv = lambda v: array([v], ftype)
40 float_to_float = lambda v : _fr1(float_conv(v))
41 float_to_str = lambda v: (params['fmt'] % array(_fr0(v)[0], ftype))
43 self.title = params['title']
44 # Parameter types same as for discovered MachAr object.
45 self.epsilon = self.eps = float_to_float(eps)
46 self.epsneg = float_to_float(epsneg)
47 self.xmax = self.huge = float_to_float(huge)
48 self.xmin = self.tiny = float_to_float(tiny)
49 self.ibeta = params['itype'](ibeta)
50 self.__dict__.update(kwargs)
51 self.precision = int(-log10(self.eps))
52 self.resolution = float_to_float(float_conv(10) ** (-self.precision))
53 self._str_eps = float_to_str(self.eps)
54 self._str_epsneg = float_to_str(self.epsneg)
55 self._str_xmin = float_to_str(self.xmin)
56 self._str_xmax = float_to_str(self.xmax)
57 self._str_resolution = float_to_str(self.resolution)
59_convert_to_float = {
60 ntypes.csingle: ntypes.single,
61 ntypes.complex_: ntypes.float_,
62 ntypes.clongfloat: ntypes.longfloat
63 }
65# Parameters for creating MachAr / MachAr-like objects
66_title_fmt = 'numpy {} precision floating point number'
67_MACHAR_PARAMS = {
68 ntypes.double: dict(
69 itype = ntypes.int64,
70 fmt = '%24.16e',
71 title = _title_fmt.format('double')),
72 ntypes.single: dict(
73 itype = ntypes.int32,
74 fmt = '%15.7e',
75 title = _title_fmt.format('single')),
76 ntypes.longdouble: dict(
77 itype = ntypes.longlong,
78 fmt = '%s',
79 title = _title_fmt.format('long double')),
80 ntypes.half: dict(
81 itype = ntypes.int16,
82 fmt = '%12.5e',
83 title = _title_fmt.format('half'))}
85# Key to identify the floating point type. Key is result of
86# ftype('-0.1').newbyteorder('<').tobytes()
87# See:
88# https://perl5.git.perl.org/perl.git/blob/3118d7d684b56cbeb702af874f4326683c45f045:/Configure
89_KNOWN_TYPES = {}
90def _register_type(machar, bytepat):
91 _KNOWN_TYPES[bytepat] = machar
92_float_ma = {}
94def _register_known_types():
95 # Known parameters for float16
96 # See docstring of MachAr class for description of parameters.
97 f16 = ntypes.float16
98 float16_ma = MachArLike(f16,
99 machep=-10,
100 negep=-11,
101 minexp=-14,
102 maxexp=16,
103 it=10,
104 iexp=5,
105 ibeta=2,
106 irnd=5,
107 ngrd=0,
108 eps=exp2(f16(-10)),
109 epsneg=exp2(f16(-11)),
110 huge=f16(65504),
111 tiny=f16(2 ** -14))
112 _register_type(float16_ma, b'f\xae')
113 _float_ma[16] = float16_ma
115 # Known parameters for float32
116 f32 = ntypes.float32
117 float32_ma = MachArLike(f32,
118 machep=-23,
119 negep=-24,
120 minexp=-126,
121 maxexp=128,
122 it=23,
123 iexp=8,
124 ibeta=2,
125 irnd=5,
126 ngrd=0,
127 eps=exp2(f32(-23)),
128 epsneg=exp2(f32(-24)),
129 huge=f32((1 - 2 ** -24) * 2**128),
130 tiny=exp2(f32(-126)))
131 _register_type(float32_ma, b'\xcd\xcc\xcc\xbd')
132 _float_ma[32] = float32_ma
134 # Known parameters for float64
135 f64 = ntypes.float64
136 epsneg_f64 = 2.0 ** -53.0
137 tiny_f64 = 2.0 ** -1022.0
138 float64_ma = MachArLike(f64,
139 machep=-52,
140 negep=-53,
141 minexp=-1022,
142 maxexp=1024,
143 it=52,
144 iexp=11,
145 ibeta=2,
146 irnd=5,
147 ngrd=0,
148 eps=2.0 ** -52.0,
149 epsneg=epsneg_f64,
150 huge=(1.0 - epsneg_f64) / tiny_f64 * f64(4),
151 tiny=tiny_f64)
152 _register_type(float64_ma, b'\x9a\x99\x99\x99\x99\x99\xb9\xbf')
153 _float_ma[64] = float64_ma
155 # Known parameters for IEEE 754 128-bit binary float
156 ld = ntypes.longdouble
157 epsneg_f128 = exp2(ld(-113))
158 tiny_f128 = exp2(ld(-16382))
159 # Ignore runtime error when this is not f128
160 with numeric.errstate(all='ignore'):
161 huge_f128 = (ld(1) - epsneg_f128) / tiny_f128 * ld(4)
162 float128_ma = MachArLike(ld,
163 machep=-112,
164 negep=-113,
165 minexp=-16382,
166 maxexp=16384,
167 it=112,
168 iexp=15,
169 ibeta=2,
170 irnd=5,
171 ngrd=0,
172 eps=exp2(ld(-112)),
173 epsneg=epsneg_f128,
174 huge=huge_f128,
175 tiny=tiny_f128)
176 # IEEE 754 128-bit binary float
177 _register_type(float128_ma,
178 b'\x9a\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xfb\xbf')
179 _register_type(float128_ma,
180 b'\x9a\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xfb\xbf')
181 _float_ma[128] = float128_ma
183 # Known parameters for float80 (Intel 80-bit extended precision)
184 epsneg_f80 = exp2(ld(-64))
185 tiny_f80 = exp2(ld(-16382))
186 # Ignore runtime error when this is not f80
187 with numeric.errstate(all='ignore'):
188 huge_f80 = (ld(1) - epsneg_f80) / tiny_f80 * ld(4)
189 float80_ma = MachArLike(ld,
190 machep=-63,
191 negep=-64,
192 minexp=-16382,
193 maxexp=16384,
194 it=63,
195 iexp=15,
196 ibeta=2,
197 irnd=5,
198 ngrd=0,
199 eps=exp2(ld(-63)),
200 epsneg=epsneg_f80,
201 huge=huge_f80,
202 tiny=tiny_f80)
203 # float80, first 10 bytes containing actual storage
204 _register_type(float80_ma, b'\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xfb\xbf')
205 _float_ma[80] = float80_ma
207 # Guessed / known parameters for double double; see:
208 # https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#Double-double_arithmetic
209 # These numbers have the same exponent range as float64, but extended number of
210 # digits in the significand.
211 huge_dd = (umath.nextafter(ld(inf), ld(0))
212 if hasattr(umath, 'nextafter') # Missing on some platforms?
213 else float64_ma.huge)
214 float_dd_ma = MachArLike(ld,
215 machep=-105,
216 negep=-106,
217 minexp=-1022,
218 maxexp=1024,
219 it=105,
220 iexp=11,
221 ibeta=2,
222 irnd=5,
223 ngrd=0,
224 eps=exp2(ld(-105)),
225 epsneg= exp2(ld(-106)),
226 huge=huge_dd,
227 tiny=exp2(ld(-1022)))
228 # double double; low, high order (e.g. PPC 64)
229 _register_type(float_dd_ma,
230 b'\x9a\x99\x99\x99\x99\x99Y<\x9a\x99\x99\x99\x99\x99\xb9\xbf')
231 # double double; high, low order (e.g. PPC 64 le)
232 _register_type(float_dd_ma,
233 b'\x9a\x99\x99\x99\x99\x99\xb9\xbf\x9a\x99\x99\x99\x99\x99Y<')
234 _float_ma['dd'] = float_dd_ma
237def _get_machar(ftype):
238 """ Get MachAr instance or MachAr-like instance
240 Get parameters for floating point type, by first trying signatures of
241 various known floating point types, then, if none match, attempting to
242 identify parameters by analysis.
244 Parameters
245 ----------
246 ftype : class
247 Numpy floating point type class (e.g. ``np.float64``)
249 Returns
250 -------
251 ma_like : instance of :class:`MachAr` or :class:`MachArLike`
252 Object giving floating point parameters for `ftype`.
254 Warns
255 -----
256 UserWarning
257 If the binary signature of the float type is not in the dictionary of
258 known float types.
259 """
260 params = _MACHAR_PARAMS.get(ftype)
261 if params is None:
262 raise ValueError(repr(ftype))
263 # Detect known / suspected types
264 key = ftype('-0.1').newbyteorder('<').tobytes()
265 ma_like = _KNOWN_TYPES.get(key)
266 # Could be 80 bit == 10 byte extended precision, where last bytes can be
267 # random garbage. Try comparing first 10 bytes to pattern.
268 if ma_like is None and ftype == ntypes.longdouble:
269 ma_like = _KNOWN_TYPES.get(key[:10])
270 if ma_like is not None:
271 return ma_like
272 # Fall back to parameter discovery
273 warnings.warn(
274 'Signature {} for {} does not match any known type: '
275 'falling back to type probe function'.format(key, ftype),
276 UserWarning, stacklevel=2)
277 return _discovered_machar(ftype)
280def _discovered_machar(ftype):
281 """ Create MachAr instance with found information on float types
282 """
283 params = _MACHAR_PARAMS[ftype]
284 return MachAr(lambda v: array([v], ftype),
285 lambda v:_fr0(v.astype(params['itype']))[0],
286 lambda v:array(_fr0(v)[0], ftype),
287 lambda v: params['fmt'] % array(_fr0(v)[0], ftype),
288 params['title'])
291@set_module('numpy')
292class finfo:
293 """
294 finfo(dtype)
296 Machine limits for floating point types.
298 Attributes
299 ----------
300 bits : int
301 The number of bits occupied by the type.
302 eps : float
303 The difference between 1.0 and the next smallest representable float
304 larger than 1.0. For example, for 64-bit binary floats in the IEEE-754
305 standard, ``eps = 2**-52``, approximately 2.22e-16.
306 epsneg : float
307 The difference between 1.0 and the next smallest representable float
308 less than 1.0. For example, for 64-bit binary floats in the IEEE-754
309 standard, ``epsneg = 2**-53``, approximately 1.11e-16.
310 iexp : int
311 The number of bits in the exponent portion of the floating point
312 representation.
313 machar : MachAr
314 The object which calculated these parameters and holds more
315 detailed information.
316 machep : int
317 The exponent that yields `eps`.
318 max : floating point number of the appropriate type
319 The largest representable number.
320 maxexp : int
321 The smallest positive power of the base (2) that causes overflow.
322 min : floating point number of the appropriate type
323 The smallest representable number, typically ``-max``.
324 minexp : int
325 The most negative power of the base (2) consistent with there
326 being no leading 0's in the mantissa.
327 negep : int
328 The exponent that yields `epsneg`.
329 nexp : int
330 The number of bits in the exponent including its sign and bias.
331 nmant : int
332 The number of bits in the mantissa.
333 precision : int
334 The approximate number of decimal digits to which this kind of
335 float is precise.
336 resolution : floating point number of the appropriate type
337 The approximate decimal resolution of this type, i.e.,
338 ``10**-precision``.
339 tiny : float
340 The smallest positive usable number. Type of `tiny` is an
341 appropriate floating point type.
343 Parameters
344 ----------
345 dtype : float, dtype, or instance
346 Kind of floating point data-type about which to get information.
348 See Also
349 --------
350 MachAr : The implementation of the tests that produce this information.
351 iinfo : The equivalent for integer data types.
352 spacing : The distance between a value and the nearest adjacent number
353 nextafter : The next floating point value after x1 towards x2
355 Notes
356 -----
357 For developers of NumPy: do not instantiate this at the module level.
358 The initial calculation of these parameters is expensive and negatively
359 impacts import times. These objects are cached, so calling ``finfo()``
360 repeatedly inside your functions is not a problem.
362 """
364 _finfo_cache = {}
366 def __new__(cls, dtype):
367 try:
368 dtype = numeric.dtype(dtype)
369 except TypeError:
370 # In case a float instance was given
371 dtype = numeric.dtype(type(dtype))
373 obj = cls._finfo_cache.get(dtype, None)
374 if obj is not None:
375 return obj
376 dtypes = [dtype]
377 newdtype = numeric.obj2sctype(dtype)
378 if newdtype is not dtype:
379 dtypes.append(newdtype)
380 dtype = newdtype
381 if not issubclass(dtype, numeric.inexact):
382 raise ValueError("data type %r not inexact" % (dtype))
383 obj = cls._finfo_cache.get(dtype, None)
384 if obj is not None:
385 return obj
386 if not issubclass(dtype, numeric.floating):
387 newdtype = _convert_to_float[dtype]
388 if newdtype is not dtype:
389 dtypes.append(newdtype)
390 dtype = newdtype
391 obj = cls._finfo_cache.get(dtype, None)
392 if obj is not None:
393 return obj
394 obj = object.__new__(cls)._init(dtype)
395 for dt in dtypes:
396 cls._finfo_cache[dt] = obj
397 return obj
399 def _init(self, dtype):
400 self.dtype = numeric.dtype(dtype)
401 machar = _get_machar(dtype)
403 for word in ['precision', 'iexp',
404 'maxexp', 'minexp', 'negep',
405 'machep']:
406 setattr(self, word, getattr(machar, word))
407 for word in ['tiny', 'resolution', 'epsneg']:
408 setattr(self, word, getattr(machar, word).flat[0])
409 self.bits = self.dtype.itemsize * 8
410 self.max = machar.huge.flat[0]
411 self.min = -self.max
412 self.eps = machar.eps.flat[0]
413 self.nexp = machar.iexp
414 self.nmant = machar.it
415 self.machar = machar
416 self._str_tiny = machar._str_xmin.strip()
417 self._str_max = machar._str_xmax.strip()
418 self._str_epsneg = machar._str_epsneg.strip()
419 self._str_eps = machar._str_eps.strip()
420 self._str_resolution = machar._str_resolution.strip()
421 return self
423 def __str__(self):
424 fmt = (
425 'Machine parameters for %(dtype)s\n'
426 '---------------------------------------------------------------\n'
427 'precision = %(precision)3s resolution = %(_str_resolution)s\n'
428 'machep = %(machep)6s eps = %(_str_eps)s\n'
429 'negep = %(negep)6s epsneg = %(_str_epsneg)s\n'
430 'minexp = %(minexp)6s tiny = %(_str_tiny)s\n'
431 'maxexp = %(maxexp)6s max = %(_str_max)s\n'
432 'nexp = %(nexp)6s min = -max\n'
433 '---------------------------------------------------------------\n'
434 )
435 return fmt % self.__dict__
437 def __repr__(self):
438 c = self.__class__.__name__
439 d = self.__dict__.copy()
440 d['klass'] = c
441 return (("%(klass)s(resolution=%(resolution)s, min=-%(_str_max)s,"
442 " max=%(_str_max)s, dtype=%(dtype)s)") % d)
445@set_module('numpy')
446class iinfo:
447 """
448 iinfo(type)
450 Machine limits for integer types.
452 Attributes
453 ----------
454 bits : int
455 The number of bits occupied by the type.
456 min : int
457 The smallest integer expressible by the type.
458 max : int
459 The largest integer expressible by the type.
461 Parameters
462 ----------
463 int_type : integer type, dtype, or instance
464 The kind of integer data type to get information about.
466 See Also
467 --------
468 finfo : The equivalent for floating point data types.
470 Examples
471 --------
472 With types:
474 >>> ii16 = np.iinfo(np.int16)
475 >>> ii16.min
476 -32768
477 >>> ii16.max
478 32767
479 >>> ii32 = np.iinfo(np.int32)
480 >>> ii32.min
481 -2147483648
482 >>> ii32.max
483 2147483647
485 With instances:
487 >>> ii32 = np.iinfo(np.int32(10))
488 >>> ii32.min
489 -2147483648
490 >>> ii32.max
491 2147483647
493 """
495 _min_vals = {}
496 _max_vals = {}
498 def __init__(self, int_type):
499 try:
500 self.dtype = numeric.dtype(int_type)
501 except TypeError:
502 self.dtype = numeric.dtype(type(int_type))
503 self.kind = self.dtype.kind
504 self.bits = self.dtype.itemsize * 8
505 self.key = "%s%d" % (self.kind, self.bits)
506 if self.kind not in 'iu':
507 raise ValueError("Invalid integer data type %r." % (self.kind,))
509 @property
510 def min(self):
511 """Minimum value of given dtype."""
512 if self.kind == 'u':
513 return 0
514 else:
515 try:
516 val = iinfo._min_vals[self.key]
517 except KeyError:
518 val = int(-(1 << (self.bits-1)))
519 iinfo._min_vals[self.key] = val
520 return val
522 @property
523 def max(self):
524 """Maximum value of given dtype."""
525 try:
526 val = iinfo._max_vals[self.key]
527 except KeyError:
528 if self.kind == 'u':
529 val = int((1 << self.bits) - 1)
530 else:
531 val = int((1 << (self.bits-1)) - 1)
532 iinfo._max_vals[self.key] = val
533 return val
535 def __str__(self):
536 """String representation."""
537 fmt = (
538 'Machine parameters for %(dtype)s\n'
539 '---------------------------------------------------------------\n'
540 'min = %(min)s\n'
541 'max = %(max)s\n'
542 '---------------------------------------------------------------\n'
543 )
544 return fmt % {'dtype': self.dtype, 'min': self.min, 'max': self.max}
546 def __repr__(self):
547 return "%s(min=%s, max=%s, dtype=%s)" % (self.__class__.__name__,
548 self.min, self.max, self.dtype)