summaryrefslogtreecommitdiff
path: root/numpy/core/getlimits.py
diff options
context:
space:
mode:
authorAllan Haldane <allan.haldane@gmail.com>2018-09-30 19:43:23 -0400
committerAllan Haldane <allan.haldane@gmail.com>2018-10-09 23:11:26 -0400
commit78e105182759b582818cb0f661052e9d812c8478 (patch)
tree630757b0af1d87b9df963509c317163debe98b07 /numpy/core/getlimits.py
parent072c90ea848c753b7e8b7c42d2e359f53dfd0085 (diff)
downloadnumpy-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.py381
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):