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

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"""
2Machine arithmetics - determine the parameters of the
3floating-point arithmetic system
5Author: Pearu Peterson, September 2003
7"""
8__all__ = ['MachAr']
10from numpy.core.fromnumeric import any
11from numpy.core._ufunc_config import errstate
12from numpy.core.overrides import set_module
14# Need to speed this up...especially for longfloat
16@set_module('numpy')
17class MachAr:
18 """
19 Diagnosing machine parameters.
21 Attributes
22 ----------
23 ibeta : int
24 Radix in which numbers are represented.
25 it : int
26 Number of base-`ibeta` digits in the floating point mantissa M.
27 machep : int
28 Exponent of the smallest (most negative) power of `ibeta` that,
29 added to 1.0, gives something different from 1.0
30 eps : float
31 Floating-point number ``beta**machep`` (floating point precision)
32 negep : int
33 Exponent of the smallest power of `ibeta` that, subtracted
34 from 1.0, gives something different from 1.0.
35 epsneg : float
36 Floating-point number ``beta**negep``.
37 iexp : int
38 Number of bits in the exponent (including its sign and bias).
39 minexp : int
40 Smallest (most negative) power of `ibeta` consistent with there
41 being no leading zeros in the mantissa.
42 xmin : float
43 Floating point number ``beta**minexp`` (the smallest [in
44 magnitude] usable floating value).
45 maxexp : int
46 Smallest (positive) power of `ibeta` that causes overflow.
47 xmax : float
48 ``(1-epsneg) * beta**maxexp`` (the largest [in magnitude]
49 usable floating value).
50 irnd : int
51 In ``range(6)``, information on what kind of rounding is done
52 in addition, and on how underflow is handled.
53 ngrd : int
54 Number of 'guard digits' used when truncating the product
55 of two mantissas to fit the representation.
56 epsilon : float
57 Same as `eps`.
58 tiny : float
59 Same as `xmin`.
60 huge : float
61 Same as `xmax`.
62 precision : float
63 ``- int(-log10(eps))``
64 resolution : float
65 ``- 10**(-precision)``
67 Parameters
68 ----------
69 float_conv : function, optional
70 Function that converts an integer or integer array to a float
71 or float array. Default is `float`.
72 int_conv : function, optional
73 Function that converts a float or float array to an integer or
74 integer array. Default is `int`.
75 float_to_float : function, optional
76 Function that converts a float array to float. Default is `float`.
77 Note that this does not seem to do anything useful in the current
78 implementation.
79 float_to_str : function, optional
80 Function that converts a single float to a string. Default is
81 ``lambda v:'%24.16e' %v``.
82 title : str, optional
83 Title that is printed in the string representation of `MachAr`.
85 See Also
86 --------
87 finfo : Machine limits for floating point types.
88 iinfo : Machine limits for integer types.
90 References
91 ----------
92 .. [1] Press, Teukolsky, Vetterling and Flannery,
93 "Numerical Recipes in C++," 2nd ed,
94 Cambridge University Press, 2002, p. 31.
96 """
98 def __init__(self, float_conv=float,int_conv=int,
99 float_to_float=float,
100 float_to_str=lambda v:'%24.16e' % v,
101 title='Python floating point number'):
102 """
104 float_conv - convert integer to float (array)
105 int_conv - convert float (array) to integer
106 float_to_float - convert float array to float
107 float_to_str - convert array float to str
108 title - description of used floating point numbers
110 """
111 # We ignore all errors here because we are purposely triggering
112 # underflow to detect the properties of the runninng arch.
113 with errstate(under='ignore'):
114 self._do_init(float_conv, int_conv, float_to_float, float_to_str, title)
116 def _do_init(self, float_conv, int_conv, float_to_float, float_to_str, title):
117 max_iterN = 10000
118 msg = "Did not converge after %d tries with %s"
119 one = float_conv(1)
120 two = one + one
121 zero = one - one
123 # Do we really need to do this? Aren't they 2 and 2.0?
124 # Determine ibeta and beta
125 a = one
126 for _ in range(max_iterN):
127 a = a + a
128 temp = a + one
129 temp1 = temp - a
130 if any(temp1 - one != zero):
131 break
132 else:
133 raise RuntimeError(msg % (_, one.dtype))
134 b = one
135 for _ in range(max_iterN):
136 b = b + b
137 temp = a + b
138 itemp = int_conv(temp-a)
139 if any(itemp != 0):
140 break
141 else:
142 raise RuntimeError(msg % (_, one.dtype))
143 ibeta = itemp
144 beta = float_conv(ibeta)
146 # Determine it and irnd
147 it = -1
148 b = one
149 for _ in range(max_iterN):
150 it = it + 1
151 b = b * beta
152 temp = b + one
153 temp1 = temp - b
154 if any(temp1 - one != zero):
155 break
156 else:
157 raise RuntimeError(msg % (_, one.dtype))
159 betah = beta / two
160 a = one
161 for _ in range(max_iterN):
162 a = a + a
163 temp = a + one
164 temp1 = temp - a
165 if any(temp1 - one != zero):
166 break
167 else:
168 raise RuntimeError(msg % (_, one.dtype))
169 temp = a + betah
170 irnd = 0
171 if any(temp-a != zero):
172 irnd = 1
173 tempa = a + beta
174 temp = tempa + betah
175 if irnd == 0 and any(temp-tempa != zero):
176 irnd = 2
178 # Determine negep and epsneg
179 negep = it + 3
180 betain = one / beta
181 a = one
182 for i in range(negep):
183 a = a * betain
184 b = a
185 for _ in range(max_iterN):
186 temp = one - a
187 if any(temp-one != zero):
188 break
189 a = a * beta
190 negep = negep - 1
191 # Prevent infinite loop on PPC with gcc 4.0:
192 if negep < 0:
193 raise RuntimeError("could not determine machine tolerance "
194 "for 'negep', locals() -> %s" % (locals()))
195 else:
196 raise RuntimeError(msg % (_, one.dtype))
197 negep = -negep
198 epsneg = a
200 # Determine machep and eps
201 machep = - it - 3
202 a = b
204 for _ in range(max_iterN):
205 temp = one + a
206 if any(temp-one != zero):
207 break
208 a = a * beta
209 machep = machep + 1
210 else:
211 raise RuntimeError(msg % (_, one.dtype))
212 eps = a
214 # Determine ngrd
215 ngrd = 0
216 temp = one + eps
217 if irnd == 0 and any(temp*one - one != zero):
218 ngrd = 1
220 # Determine iexp
221 i = 0
222 k = 1
223 z = betain
224 t = one + eps
225 nxres = 0
226 for _ in range(max_iterN):
227 y = z
228 z = y*y
229 a = z*one # Check here for underflow
230 temp = z*t
231 if any(a+a == zero) or any(abs(z) >= y):
232 break
233 temp1 = temp * betain
234 if any(temp1*beta == z):
235 break
236 i = i + 1
237 k = k + k
238 else:
239 raise RuntimeError(msg % (_, one.dtype))
240 if ibeta != 10:
241 iexp = i + 1
242 mx = k + k
243 else:
244 iexp = 2
245 iz = ibeta
246 while k >= iz:
247 iz = iz * ibeta
248 iexp = iexp + 1
249 mx = iz + iz - 1
251 # Determine minexp and xmin
252 for _ in range(max_iterN):
253 xmin = y
254 y = y * betain
255 a = y * one
256 temp = y * t
257 if any((a + a) != zero) and any(abs(y) < xmin):
258 k = k + 1
259 temp1 = temp * betain
260 if any(temp1*beta == y) and any(temp != y):
261 nxres = 3
262 xmin = y
263 break
264 else:
265 break
266 else:
267 raise RuntimeError(msg % (_, one.dtype))
268 minexp = -k
270 # Determine maxexp, xmax
271 if mx <= k + k - 3 and ibeta != 10:
272 mx = mx + mx
273 iexp = iexp + 1
274 maxexp = mx + minexp
275 irnd = irnd + nxres
276 if irnd >= 2:
277 maxexp = maxexp - 2
278 i = maxexp + minexp
279 if ibeta == 2 and not i:
280 maxexp = maxexp - 1
281 if i > 20:
282 maxexp = maxexp - 1
283 if any(a != y):
284 maxexp = maxexp - 2
285 xmax = one - epsneg
286 if any(xmax*one != xmax):
287 xmax = one - beta*epsneg
288 xmax = xmax / (xmin*beta*beta*beta)
289 i = maxexp + minexp + 3
290 for j in range(i):
291 if ibeta == 2:
292 xmax = xmax + xmax
293 else:
294 xmax = xmax * beta
296 self.ibeta = ibeta
297 self.it = it
298 self.negep = negep
299 self.epsneg = float_to_float(epsneg)
300 self._str_epsneg = float_to_str(epsneg)
301 self.machep = machep
302 self.eps = float_to_float(eps)
303 self._str_eps = float_to_str(eps)
304 self.ngrd = ngrd
305 self.iexp = iexp
306 self.minexp = minexp
307 self.xmin = float_to_float(xmin)
308 self._str_xmin = float_to_str(xmin)
309 self.maxexp = maxexp
310 self.xmax = float_to_float(xmax)
311 self._str_xmax = float_to_str(xmax)
312 self.irnd = irnd
314 self.title = title
315 # Commonly used parameters
316 self.epsilon = self.eps
317 self.tiny = self.xmin
318 self.huge = self.xmax
320 import math
321 self.precision = int(-math.log10(float_to_float(self.eps)))
322 ten = two + two + two + two + two
323 resolution = ten ** (-self.precision)
324 self.resolution = float_to_float(resolution)
325 self._str_resolution = float_to_str(resolution)
327 def __str__(self):
328 fmt = (
329 'Machine parameters for %(title)s\n'
330 '---------------------------------------------------------------------\n'
331 'ibeta=%(ibeta)s it=%(it)s iexp=%(iexp)s ngrd=%(ngrd)s irnd=%(irnd)s\n'
332 'machep=%(machep)s eps=%(_str_eps)s (beta**machep == epsilon)\n'
333 'negep =%(negep)s epsneg=%(_str_epsneg)s (beta**epsneg)\n'
334 'minexp=%(minexp)s xmin=%(_str_xmin)s (beta**minexp == tiny)\n'
335 'maxexp=%(maxexp)s xmax=%(_str_xmax)s ((1-epsneg)*beta**maxexp == huge)\n'
336 '---------------------------------------------------------------------\n'
337 )
338 return fmt % self.__dict__
341if __name__ == '__main__':
342 print(MachAr())