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