diff options
author | Allan Haldane <allan.haldane@gmail.com> | 2018-09-30 19:43:23 -0400 |
---|---|---|
committer | Allan Haldane <allan.haldane@gmail.com> | 2018-10-09 23:11:26 -0400 |
commit | 78e105182759b582818cb0f661052e9d812c8478 (patch) | |
tree | 630757b0af1d87b9df963509c317163debe98b07 /numpy/core/getlimits.py | |
parent | 072c90ea848c753b7e8b7c42d2e359f53dfd0085 (diff) | |
download | numpy-78e105182759b582818cb0f661052e9d812c8478.tar.gz |
MAINT: delay initialization of getlimits (circular imports)
getlimits previously called numpy code before all of numpy was loaded,
which often causes circular import issues. This delays getlimits init.
Fixes #12063
Diffstat (limited to 'numpy/core/getlimits.py')
-rw-r--r-- | numpy/core/getlimits.py | 381 |
1 files changed, 184 insertions, 197 deletions
diff --git a/numpy/core/getlimits.py b/numpy/core/getlimits.py index 0e3c58793..63e2c5db9 100644 --- a/numpy/core/getlimits.py +++ b/numpy/core/getlimits.py @@ -30,35 +30,6 @@ def _fr1(a): a.shape = () return a - -_convert_to_float = { - ntypes.csingle: ntypes.single, - ntypes.complex_: ntypes.float_, - ntypes.clongfloat: ntypes.longfloat - } - - -# Parameters for creating MachAr / MachAr-like objects -_title_fmt = 'numpy {} precision floating point number' -_MACHAR_PARAMS = { - ntypes.double: dict( - itype = ntypes.int64, - fmt = '%24.16e', - title = _title_fmt.format('double')), - ntypes.single: dict( - itype = ntypes.int32, - fmt = '%15.7e', - title = _title_fmt.format('single')), - ntypes.longdouble: dict( - itype = ntypes.longlong, - fmt = '%s', - title = _title_fmt.format('long double')), - ntypes.half: dict( - itype = ntypes.int16, - fmt = '%12.5e', - title = _title_fmt.format('half'))} - - class MachArLike(object): """ Object to simulate MachAr instance """ @@ -68,8 +39,8 @@ class MachArLike(object): params = _MACHAR_PARAMS[ftype] float_conv = lambda v: array([v], ftype) float_to_float = lambda v : _fr1(float_conv(v)) - self._float_to_str = lambda v: (params['fmt'] % - array(_fr0(v)[0], ftype)) + float_to_str = lambda v: (params['fmt'] % array(_fr0(v)[0], ftype)) + self.title = params['title'] # Parameter types same as for discovered MachAr object. self.epsilon = self.eps = float_to_float(kwargs.pop('eps')) @@ -80,172 +51,188 @@ class MachArLike(object): self.__dict__.update(kwargs) self.precision = int(-log10(self.eps)) self.resolution = float_to_float(float_conv(10) ** (-self.precision)) - - # Properties below to delay need for float_to_str, and thus avoid circular - # imports during early numpy module loading. - # See: https://github.com/numpy/numpy/pull/8983#discussion_r115838683 - - @property - def _str_eps(self): - return self._float_to_str(self.eps) - - @property - def _str_epsneg(self): - return self._float_to_str(self.epsneg) - - @property - def _str_xmin(self): - return self._float_to_str(self.xmin) - - @property - def _str_xmax(self): - return self._float_to_str(self.xmax) - - @property - def _str_resolution(self): - return self._float_to_str(self.resolution) - - -# Known parameters for float16 -# See docstring of MachAr class for description of parameters. -_f16 = ntypes.float16 -_float16_ma = MachArLike(_f16, - machep=-10, - negep=-11, - minexp=-14, - maxexp=16, - it=10, - iexp=5, - ibeta=2, - irnd=5, - ngrd=0, - eps=exp2(_f16(-10)), - epsneg=exp2(_f16(-11)), - huge=_f16(65504), - tiny=_f16(2 ** -14)) - -# Known parameters for float32 -_f32 = ntypes.float32 -_float32_ma = MachArLike(_f32, - machep=-23, - negep=-24, - minexp=-126, - maxexp=128, - it=23, - iexp=8, - ibeta=2, - irnd=5, - ngrd=0, - eps=exp2(_f32(-23)), - epsneg=exp2(_f32(-24)), - huge=_f32((1 - 2 ** -24) * 2**128), - tiny=exp2(_f32(-126))) - -# Known parameters for float64 -_f64 = ntypes.float64 -_epsneg_f64 = 2.0 ** -53.0 -_tiny_f64 = 2.0 ** -1022.0 -_float64_ma = MachArLike(_f64, - machep=-52, - negep=-53, - minexp=-1022, - maxexp=1024, - it=52, - iexp=11, - ibeta=2, - irnd=5, - ngrd=0, - eps=2.0 ** -52.0, - epsneg=_epsneg_f64, - huge=(1.0 - _epsneg_f64) / _tiny_f64 * _f64(4), - tiny=_tiny_f64) - -# Known parameters for IEEE 754 128-bit binary float -_ld = ntypes.longdouble -_epsneg_f128 = exp2(_ld(-113)) -_tiny_f128 = exp2(_ld(-16382)) -# Ignore runtime error when this is not f128 -with numeric.errstate(all='ignore'): - _huge_f128 = (_ld(1) - _epsneg_f128) / _tiny_f128 * _ld(4) -_float128_ma = MachArLike(_ld, - machep=-112, - negep=-113, - minexp=-16382, - maxexp=16384, - it=112, - iexp=15, - ibeta=2, - irnd=5, - ngrd=0, - eps=exp2(_ld(-112)), - epsneg=_epsneg_f128, - huge=_huge_f128, - tiny=_tiny_f128) - -# Known parameters for float80 (Intel 80-bit extended precision) -_epsneg_f80 = exp2(_ld(-64)) -_tiny_f80 = exp2(_ld(-16382)) -# Ignore runtime error when this is not f80 -with numeric.errstate(all='ignore'): - _huge_f80 = (_ld(1) - _epsneg_f80) / _tiny_f80 * _ld(4) -_float80_ma = MachArLike(_ld, - machep=-63, - negep=-64, - minexp=-16382, - maxexp=16384, - it=63, - iexp=15, - ibeta=2, - irnd=5, - ngrd=0, - eps=exp2(_ld(-63)), - epsneg=_epsneg_f80, - huge=_huge_f80, - tiny=_tiny_f80) - -# Guessed / known parameters for double double; see: -# https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#Double-double_arithmetic -# These numbers have the same exponent range as float64, but extended number of -# digits in the significand. -_huge_dd = (umath.nextafter(_ld(inf), _ld(0)) - if hasattr(umath, 'nextafter') # Missing on some platforms? - else _float64_ma.huge) -_float_dd_ma = MachArLike(_ld, - machep=-105, - negep=-106, - minexp=-1022, - maxexp=1024, - it=105, - iexp=11, - ibeta=2, - irnd=5, - ngrd=0, - eps=exp2(_ld(-105)), - epsneg= exp2(_ld(-106)), - huge=_huge_dd, - tiny=exp2(_ld(-1022))) - - -# Key to identify the floating point type. Key is result of -# ftype('-0.1').newbyteorder('<').tobytes() -# See: -# https://perl5.git.perl.org/perl.git/blob/3118d7d684b56cbeb702af874f4326683c45f045:/Configure -_KNOWN_TYPES = { - b'\x9a\x99\x99\x99\x99\x99\xb9\xbf' : _float64_ma, - b'\xcd\xcc\xcc\xbd' : _float32_ma, - b'f\xae' : _float16_ma, - # float80, first 10 bytes containing actual storage - b'\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xfb\xbf' : _float80_ma, - # double double; low, high order (e.g. PPC 64) - b'\x9a\x99\x99\x99\x99\x99Y<\x9a\x99\x99\x99\x99\x99\xb9\xbf' : - _float_dd_ma, - # double double; high, low order (e.g. PPC 64 le) - b'\x9a\x99\x99\x99\x99\x99\xb9\xbf\x9a\x99\x99\x99\x99\x99Y<' : - _float_dd_ma, - # IEEE 754 128-bit binary float - b'\x9a\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xfb\xbf' : - _float128_ma, -} + self._str_eps = float_to_str(self.eps) + self._str_epsneg = float_to_str(self.epsneg) + self._str_xmin = float_to_str(self.xmin) + self._str_xmax = float_to_str(self.xmax) + self._str_resolution = float_to_str(self.resolution) + +def _init_getlimits(): + + global _convert_to_float, _title_fmt, _MACHAR_PARAMS + _convert_to_float = { + ntypes.csingle: ntypes.single, + ntypes.complex_: ntypes.float_, + ntypes.clongfloat: ntypes.longfloat + } + + # Parameters for creating MachAr / MachAr-like objects + _title_fmt = 'numpy {} precision floating point number' + _MACHAR_PARAMS = { + ntypes.double: dict( + itype = ntypes.int64, + fmt = '%24.16e', + title = _title_fmt.format('double')), + ntypes.single: dict( + itype = ntypes.int32, + fmt = '%15.7e', + title = _title_fmt.format('single')), + ntypes.longdouble: dict( + itype = ntypes.longlong, + fmt = '%s', + title = _title_fmt.format('long double')), + ntypes.half: dict( + itype = ntypes.int16, + fmt = '%12.5e', + title = _title_fmt.format('half'))} + + # Known parameters for float16 + # See docstring of MachAr class for description of parameters. + global _f16, _float16_ma + _f16 = ntypes.float16 + _float16_ma = MachArLike(_f16, + machep=-10, + negep=-11, + minexp=-14, + maxexp=16, + it=10, + iexp=5, + ibeta=2, + irnd=5, + ngrd=0, + eps=exp2(_f16(-10)), + epsneg=exp2(_f16(-11)), + huge=_f16(65504), + tiny=_f16(2 ** -14)) + + # Known parameters for float32 + global _f32, _float32_ma + _f32 = ntypes.float32 + _float32_ma = MachArLike(_f32, + machep=-23, + negep=-24, + minexp=-126, + maxexp=128, + it=23, + iexp=8, + ibeta=2, + irnd=5, + ngrd=0, + eps=exp2(_f32(-23)), + epsneg=exp2(_f32(-24)), + huge=_f32((1 - 2 ** -24) * 2**128), + tiny=exp2(_f32(-126))) + + # Known parameters for float64 + global _f64, _epsned_f64, _tiny_f64, _float64_ma + _f64 = ntypes.float64 + _epsneg_f64 = 2.0 ** -53.0 + _tiny_f64 = 2.0 ** -1022.0 + _float64_ma = MachArLike(_f64, + machep=-52, + negep=-53, + minexp=-1022, + maxexp=1024, + it=52, + iexp=11, + ibeta=2, + irnd=5, + ngrd=0, + eps=2.0 ** -52.0, + epsneg=_epsneg_f64, + huge=(1.0 - _epsneg_f64) / _tiny_f64 * _f64(4), + tiny=_tiny_f64) + + # Known parameters for IEEE 754 128-bit binary float + global _ld, _epsneg, _tiny_f128, _huge_f128, _float128_ma + _ld = ntypes.longdouble + _epsneg_f128 = exp2(_ld(-113)) + _tiny_f128 = exp2(_ld(-16382)) + # Ignore runtime error when this is not f128 + with numeric.errstate(all='ignore'): + _huge_f128 = (_ld(1) - _epsneg_f128) / _tiny_f128 * _ld(4) + _float128_ma = MachArLike(_ld, + machep=-112, + negep=-113, + minexp=-16382, + maxexp=16384, + it=112, + iexp=15, + ibeta=2, + irnd=5, + ngrd=0, + eps=exp2(_ld(-112)), + epsneg=_epsneg_f128, + huge=_huge_f128, + tiny=_tiny_f128) + + # Known parameters for float80 (Intel 80-bit extended precision) + global _epsned_f80, _tiny_f80, _huge_f80, _float80_ma + _epsneg_f80 = exp2(_ld(-64)) + _tiny_f80 = exp2(_ld(-16382)) + # Ignore runtime error when this is not f80 + with numeric.errstate(all='ignore'): + _huge_f80 = (_ld(1) - _epsneg_f80) / _tiny_f80 * _ld(4) + _float80_ma = MachArLike(_ld, + machep=-63, + negep=-64, + minexp=-16382, + maxexp=16384, + it=63, + iexp=15, + ibeta=2, + irnd=5, + ngrd=0, + eps=exp2(_ld(-63)), + epsneg=_epsneg_f80, + huge=_huge_f80, + tiny=_tiny_f80) + + # Guessed / known parameters for double double; see: + # https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#Double-double_arithmetic + # These numbers have the same exponent range as float64, but extended number of + # digits in the significand. + global _huge_dd, _float_dd_ma + _huge_dd = (umath.nextafter(_ld(inf), _ld(0)) + if hasattr(umath, 'nextafter') # Missing on some platforms? + else _float64_ma.huge) + _float_dd_ma = MachArLike(_ld, + machep=-105, + negep=-106, + minexp=-1022, + maxexp=1024, + it=105, + iexp=11, + ibeta=2, + irnd=5, + ngrd=0, + eps=exp2(_ld(-105)), + epsneg= exp2(_ld(-106)), + huge=_huge_dd, + tiny=exp2(_ld(-1022))) + + + global _KNOWN_TYPES + # Key to identify the floating point type. Key is result of + # ftype('-0.1').newbyteorder('<').tobytes() + # See: + # https://perl5.git.perl.org/perl.git/blob/3118d7d684b56cbeb702af874f4326683c45f045:/Configure + _KNOWN_TYPES = { + b'\x9a\x99\x99\x99\x99\x99\xb9\xbf' : _float64_ma, + b'\xcd\xcc\xcc\xbd' : _float32_ma, + b'f\xae' : _float16_ma, + # float80, first 10 bytes containing actual storage + b'\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xfb\xbf' : _float80_ma, + # double double; low, high order (e.g. PPC 64) + b'\x9a\x99\x99\x99\x99\x99Y<\x9a\x99\x99\x99\x99\x99\xb9\xbf' : + _float_dd_ma, + # double double; high, low order (e.g. PPC 64 le) + b'\x9a\x99\x99\x99\x99\x99\xb9\xbf\x9a\x99\x99\x99\x99\x99Y<' : + _float_dd_ma, + # IEEE 754 128-bit binary float + b'\x9a\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\xfb\xbf' : + _float128_ma, + } def _get_machar(ftype): |