Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/numpy/_core/getlimits.py: 31%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

176 statements  

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)