Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
getlimits.py463 linesDownload Raw Back to _core
1"""Machine limits for Float32 and Float64 and (long double) if available...
2
3"""
4__all__ = ['finfo', 'iinfo']
5
6import math
7import types
8import warnings
9from functools import cached_property
10
11from numpy._utils import set_module
12
13from . import numeric, numerictypes as ntypes
14from ._multiarray_umath import _populate_finfo_constants
15
16
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
23
24
25def _fr1(a):
26    """fix rank > 0 --> rank-0"""
27    if a.size == 1:
28        a = a.copy()
29        a.shape = ()
30    return a
31
32
33_convert_to_float = {
34    ntypes.csingle: ntypes.single,
35    ntypes.complex128: ntypes.float64,
36    ntypes.clongdouble: ntypes.longdouble
37    }
38
39# Parameters for creating MachAr / MachAr-like objects
40_title_fmt = 'numpy {} precision floating point number'
41_MACHAR_PARAMS = {
42    ntypes.double: {
43        'itype': ntypes.int64,
44        'fmt': '%24.16e',
45        'title': _title_fmt.format('double')},
46    ntypes.single: {
47        'itype': ntypes.int32,
48        'fmt': '%15.7e',
49        'title': _title_fmt.format('single')},
50    ntypes.longdouble: {
51        'itype': ntypes.longlong,
52        'fmt': '%s',
53        'title': _title_fmt.format('long double')},
54    ntypes.half: {
55        'itype': ntypes.int16,
56        'fmt': '%12.5e',
57        'title': _title_fmt.format('half')}}
58
59
60@set_module('numpy')
61class finfo:
62    """
63    finfo(dtype)
64
65    Machine limits for floating point types.
66
67    Attributes
68    ----------
69    bits : int
70        The number of bits occupied by the type.
71    dtype : dtype
72        Returns the dtype for which `finfo` returns information. For complex
73        input, the returned dtype is the associated ``float*`` dtype for its
74        real and complex components.
75    eps : float
76        The difference between 1.0 and the next smallest representable float
77        larger than 1.0. For example, for 64-bit binary floats in the IEEE-754
78        standard, ``eps = 2**-52``, approximately 2.22e-16.
79    epsneg : float
80        The difference between 1.0 and the next smallest representable float
81        less than 1.0. For example, for 64-bit binary floats in the IEEE-754
82        standard, ``epsneg = 2**-53``, approximately 1.11e-16.
83    iexp : int
84        The number of bits in the exponent portion of the floating point
85        representation.
86    machep : int
87        The exponent that yields `eps`.
88    max : floating point number of the appropriate type
89        The largest representable number.
90    maxexp : int
91        The smallest positive power of the base (2) that causes overflow.
92        Corresponds to the C standard MAX_EXP.
93    min : floating point number of the appropriate type
94        The smallest representable number, typically ``-max``.
95    minexp : int
96        The most negative power of the base (2) consistent with there
97        being no leading 0's in the mantissa. Corresponds to the C
98        standard MIN_EXP - 1.
99    negep : int
100        The exponent that yields `epsneg`.
101    nexp : int
102        The number of bits in the exponent including its sign and bias.
103    nmant : int
104        The number of explicit bits in the mantissa (excluding the implicit
105        leading bit for normalized numbers).
106    precision : int
107        The approximate number of decimal digits to which this kind of
108        float is precise.
109    resolution : floating point number of the appropriate type
110        The approximate decimal resolution of this type, i.e.,
111        ``10**-precision``.
112    tiny : float
113        An alias for `smallest_normal`, kept for backwards compatibility.
114    smallest_normal : float
115        The smallest positive floating point number with 1 as leading bit in
116        the mantissa following IEEE-754 (see Notes).
117    smallest_subnormal : float
118        The smallest positive floating point number with 0 as leading bit in
119        the mantissa following IEEE-754.
120
121    Parameters
122    ----------
123    dtype : float, dtype, or instance
124        Kind of floating point or complex floating point
125        data-type about which to get information.
126
127    See Also
128    --------
129    iinfo : The equivalent for integer data types.
130    spacing : The distance between a value and the nearest adjacent number
131    nextafter : The next floating point value after x1 towards x2
132
133    Notes
134    -----
135    For developers of NumPy: do not instantiate this at the module level.
136    The initial calculation of these parameters is expensive and negatively
137    impacts import times.  These objects are cached, so calling ``finfo()``
138    repeatedly inside your functions is not a problem.
139
140    Note that ``smallest_normal`` is not actually the smallest positive
141    representable value in a NumPy floating point type. As in the IEEE-754
142    standard [1]_, NumPy floating point types make use of subnormal numbers to
143    fill the gap between 0 and ``smallest_normal``. However, subnormal numbers
144    may have significantly reduced precision [2]_.
145
146    For ``longdouble``, the representation varies across platforms. On most
147    platforms it is IEEE 754 binary128 (quad precision) or binary64-extended
148    (80-bit extended precision). On PowerPC systems, it may use the IBM
149    double-double format (a pair of float64 values), which has special
150    characteristics for precision and range.
151
152    This function can also be used for complex data types as well. If used,
153    the output will be the same as the corresponding real float type
154    (e.g. numpy.finfo(numpy.csingle) is the same as numpy.finfo(numpy.single)).
155    However, the output is true for the real and imaginary components.
156
157    References
158    ----------
159    .. [1] IEEE Standard for Floating-Point Arithmetic, IEEE Std 754-2008,
160           pp.1-70, 2008, https://doi.org/10.1109/IEEESTD.2008.4610935
161    .. [2] Wikipedia, "Denormal Numbers",
162           https://en.wikipedia.org/wiki/Denormal_number
163
164    Examples
165    --------
166    >>> import numpy as np
167    >>> np.finfo(np.float64).dtype
168    dtype('float64')
169    >>> np.finfo(np.complex64).dtype
170    dtype('float32')
171
172    """
173
174    _finfo_cache = {}
175
176    __class_getitem__ = classmethod(types.GenericAlias)
177
178    def __new__(cls, dtype):
179        try:
180            obj = cls._finfo_cache.get(dtype)  # most common path
181            if obj is not None:
182                return obj
183        except TypeError:
184            pass
185
186        if dtype is None:
187            # Deprecated in NumPy 1.25, 2023-01-16
188            warnings.warn(
189                "finfo() dtype cannot be None. This behavior will "
190                "raise an error in the future. (Deprecated in NumPy 1.25)",
191                DeprecationWarning,
192                stacklevel=2
193            )
194
195        try:
196            dtype = numeric.dtype(dtype)
197        except TypeError:
198            # In case a float instance was given
199            dtype = numeric.dtype(type(dtype))
200
201        obj = cls._finfo_cache.get(dtype)
202        if obj is not None:
203            return obj
204        dtypes = [dtype]
205        newdtype = ntypes.obj2sctype(dtype)
206        if newdtype is not dtype:
207            dtypes.append(newdtype)
208            dtype = newdtype
209        if not issubclass(dtype, numeric.inexact):
210            raise ValueError(f"data type {dtype!r} not inexact")
211        obj = cls._finfo_cache.get(dtype)
212        if obj is not None:
213            return obj
214        if not issubclass(dtype, numeric.floating):
215            newdtype = _convert_to_float[dtype]
216            if newdtype is not dtype:
217                # dtype changed, for example from complex128 to float64
218                dtypes.append(newdtype)
219                dtype = newdtype
220
221                obj = cls._finfo_cache.get(dtype, None)
222                if obj is not None:
223                    # the original dtype was not in the cache, but the new
224                    # dtype is in the cache. we add the original dtypes to
225                    # the cache and return the result
226                    for dt in dtypes:
227                        cls._finfo_cache[dt] = obj
228                    return obj
229        obj = object.__new__(cls)._init(dtype)
230        for dt in dtypes:
231            cls._finfo_cache[dt] = obj
232        return obj
233
234    def _init(self, dtype):
235        self.dtype = numeric.dtype(dtype)
236        self.bits = self.dtype.itemsize * 8
237        self._fmt = None
238        self._repr = None
239        _populate_finfo_constants(self, self.dtype)
240        return self
241
242    @cached_property
243    def epsneg(self):
244        # Assume typical floating point logic.  Could also use nextafter.
245        return self.eps / self._radix
246
247    @cached_property
248    def resolution(self):
249        return self.dtype.type(10)**-self.precision
250
251    @cached_property
252    def machep(self):
253        return int(math.log2(self.eps))
254
255    @cached_property
256    def negep(self):
257        return int(math.log2(self.epsneg))
258
259    @cached_property
260    def nexp(self):
261        # considering all ones (inf/nan) and all zeros (subnormal/zero)
262        return math.ceil(math.log2(self.maxexp - self.minexp + 2))
263
264    @cached_property
265    def iexp(self):
266        # Calculate exponent bits from it's range:
267        return math.ceil(math.log2(self.maxexp - self.minexp))
268
269    def __str__(self):
270        if (fmt := getattr(self, "_fmt", None)) is not None:
271            return fmt
272
273        def get_str(name, pad=None):
274            if (val := getattr(self, name, None)) is None:
275                return "<undefined>"
276            if pad is not None:
277                s = str(val).ljust(pad)
278            return str(val)
279
280        precision = get_str("precision", 3)
281        machep = get_str("machep", 6)
282        negep = get_str("negep", 6)
283        minexp = get_str("minexp", 6)
284        maxexp = get_str("maxexp", 6)
285        resolution = get_str("resolution")
286        eps = get_str("eps")
287        epsneg = get_str("epsneg")
288        tiny = get_str("tiny")
289        smallest_normal = get_str("smallest_normal")
290        smallest_subnormal = get_str("smallest_subnormal")
291        nexp = get_str("nexp", 6)
292        max_ = get_str("max")
293        if hasattr(self, "min") and hasattr(self, "max") and -self.min == self.max:
294            min_ = "-max"
295        else:
296            min_ = get_str("min")
297
298        fmt = (
299            f'Machine parameters for {self.dtype}\n'
300            f'---------------------------------------------------------------\n'
301            f'precision = {precision}   resolution = {resolution}\n'
302            f'machep = {machep}   eps =        {eps}\n'
303            f'negep =  {negep}   epsneg =     {epsneg}\n'
304            f'minexp = {minexp}   tiny =       {tiny}\n'
305            f'maxexp = {maxexp}   max =        {max_}\n'
306            f'nexp =   {nexp}   min =        {min_}\n'
307            f'smallest_normal = {smallest_normal}   '
308            f'smallest_subnormal = {smallest_subnormal}\n'
309            f'---------------------------------------------------------------\n'
310        )
311        self._fmt = fmt
312        return fmt
313
314    def __repr__(self):
315        if (repr_str := getattr(self, "_repr", None)) is not None:
316            return repr_str
317
318        c = self.__class__.__name__
319
320        # Use precision+1 digits in exponential notation
321        fmt_str = _MACHAR_PARAMS.get(self.dtype.type, {}).get('fmt', '%s')
322        if fmt_str != '%s' and hasattr(self, 'max') and hasattr(self, 'min'):
323            max_str = (fmt_str % self.max).strip()
324            min_str = (fmt_str % self.min).strip()
325        else:
326            max_str = str(self.max)
327            min_str = str(self.min)
328
329        resolution_str = str(self.resolution)
330
331        repr_str = (f"{c}(resolution={resolution_str}, min={min_str},"
332                    f" max={max_str}, dtype={self.dtype})")
333        self._repr = repr_str
334        return repr_str
335
336    @cached_property
337    def tiny(self):
338        """Return the value for tiny, alias of smallest_normal.
339
340        Returns
341        -------
342        tiny : float
343            Value for the smallest normal, alias of smallest_normal.
344
345        Warns
346        -----
347        UserWarning
348            If the calculated value for the smallest normal is requested for
349            double-double.
350        """
351        return self.smallest_normal
352
353
354@set_module('numpy')
355class iinfo:
356    """
357    iinfo(type)
358
359    Machine limits for integer types.
360
361    Attributes
362    ----------
363    bits : int
364        The number of bits occupied by the type.
365    dtype : dtype
366        Returns the dtype for which `iinfo` returns information.
367    min : int
368        The smallest integer expressible by the type.
369    max : int
370        The largest integer expressible by the type.
371
372    Parameters
373    ----------
374    int_type : integer type, dtype, or instance
375        The kind of integer data type to get information about.
376
377    See Also
378    --------
379    finfo : The equivalent for floating point data types.
380
381    Examples
382    --------
383    With types:
384
385    >>> import numpy as np
386    >>> ii16 = np.iinfo(np.int16)
387    >>> ii16.min
388    -32768
389    >>> ii16.max
390    32767
391    >>> ii32 = np.iinfo(np.int32)
392    >>> ii32.min
393    -2147483648
394    >>> ii32.max
395    2147483647
396
397    With instances:
398
399    >>> ii32 = np.iinfo(np.int32(10))
400    >>> ii32.min
401    -2147483648
402    >>> ii32.max
403    2147483647
404
405    """
406
407    _min_vals = {}
408    _max_vals = {}
409
410    __class_getitem__ = classmethod(types.GenericAlias)
411
412    def __init__(self, int_type):
413        try:
414            self.dtype = numeric.dtype(int_type)
415        except TypeError:
416            self.dtype = numeric.dtype(type(int_type))
417        self.kind = self.dtype.kind
418        self.bits = self.dtype.itemsize * 8
419        self.key = "%s%d" % (self.kind, self.bits)
420        if self.kind not in 'iu':
421            raise ValueError(f"Invalid integer data type {self.kind!r}.")
422
423    @property
424    def min(self):
425        """Minimum value of given dtype."""
426        if self.kind == 'u':
427            return 0
428        else:
429            try:
430                val = iinfo._min_vals[self.key]
431            except KeyError:
432                val = int(-(1 << (self.bits - 1)))
433                iinfo._min_vals[self.key] = val
434            return val
435
436    @property
437    def max(self):
438        """Maximum value of given dtype."""
439        try:
440            val = iinfo._max_vals[self.key]
441        except KeyError:
442            if self.kind == 'u':
443                val = int((1 << self.bits) - 1)
444            else:
445                val = int((1 << (self.bits - 1)) - 1)
446            iinfo._max_vals[self.key] = val
447        return val
448
449    def __str__(self):
450        """String representation."""
451        fmt = (
452            'Machine parameters for %(dtype)s\n'
453            '---------------------------------------------------------------\n'
454            'min = %(min)s\n'
455            'max = %(max)s\n'
456            '---------------------------------------------------------------\n'
457            )
458        return fmt % {'dtype': self.dtype, 'min': self.min, 'max': self.max}
459
460    def __repr__(self):
461        return "%s(min=%s, max=%s, dtype=%s)" % (self.__class__.__name__,
462                                    self.min, self.max, self.dtype)
463 
codekingpro/portable-devtools · Team Ai