Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/ml_dtypes/_finfo.py: 98%
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
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
1# Copyright 2023 The ml_dtypes Authors.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
15# pyrefly: ignore-errors
17"""Overload of numpy.finfo to handle dtypes defined in ml_dtypes."""
19from ml_dtypes._ml_dtypes_ext import bcomplex32
20from ml_dtypes._ml_dtypes_ext import bfloat16
21from ml_dtypes._ml_dtypes_ext import complex32
22from ml_dtypes._ml_dtypes_ext import float4_e2m1fn
23from ml_dtypes._ml_dtypes_ext import float6_e2m3fn
24from ml_dtypes._ml_dtypes_ext import float6_e3m2fn
25from ml_dtypes._ml_dtypes_ext import float8_e3m4
26from ml_dtypes._ml_dtypes_ext import float8_e4m3
27from ml_dtypes._ml_dtypes_ext import float8_e4m3b11fnuz
28from ml_dtypes._ml_dtypes_ext import float8_e4m3fn
29from ml_dtypes._ml_dtypes_ext import float8_e4m3fnuz
30from ml_dtypes._ml_dtypes_ext import float8_e5m2
31from ml_dtypes._ml_dtypes_ext import float8_e5m2fnuz
32from ml_dtypes._ml_dtypes_ext import float8_e8m0fnu
33import numpy as np
35_bfloat16_dtype = np.dtype(bfloat16)
36_float4_e2m1fn_dtype = np.dtype(float4_e2m1fn)
37_float6_e2m3fn_dtype = np.dtype(float6_e2m3fn)
38_float6_e3m2fn_dtype = np.dtype(float6_e3m2fn)
39_float8_e3m4_dtype = np.dtype(float8_e3m4)
40_float8_e4m3_dtype = np.dtype(float8_e4m3)
41_float8_e4m3b11fnuz_dtype = np.dtype(float8_e4m3b11fnuz)
42_float8_e4m3fn_dtype = np.dtype(float8_e4m3fn)
43_float8_e4m3fnuz_dtype = np.dtype(float8_e4m3fnuz)
44_float8_e5m2_dtype = np.dtype(float8_e5m2)
45_float8_e5m2fnuz_dtype = np.dtype(float8_e5m2fnuz)
46_float8_e8m0fnu_dtype = np.dtype(float8_e8m0fnu)
47_bcomplex32_dtype = np.dtype(bcomplex32)
48_complex32_dtype = np.dtype(complex32)
51class _Bfloat16MachArLike:
53 def __init__(self):
54 smallest_normal = float.fromhex("0x1p-126")
55 self.smallest_normal = bfloat16(smallest_normal)
56 smallest_subnormal = float.fromhex("0x1p-133")
57 self.smallest_subnormal = bfloat16(smallest_subnormal)
60class _Float4E2m1fnMachArLike:
62 def __init__(self):
63 smallest_normal = float.fromhex("0x1p0")
64 self.smallest_normal = float4_e2m1fn(smallest_normal)
65 smallest_subnormal = float.fromhex("0x0.8p0")
66 self.smallest_subnormal = float4_e2m1fn(smallest_subnormal)
69class _Float6E2m3fnMachArLike:
71 def __init__(self):
72 smallest_normal = float.fromhex("0x1p0")
73 self.smallest_normal = float6_e2m3fn(smallest_normal)
74 smallest_subnormal = float.fromhex("0x0.2p0")
75 self.smallest_subnormal = float6_e2m3fn(smallest_subnormal)
78class _Float6E3m2fnMachArLike:
80 def __init__(self):
81 smallest_normal = float.fromhex("0x1p-2")
82 self.smallest_normal = float6_e3m2fn(smallest_normal)
83 smallest_subnormal = float.fromhex("0x0.4p-2")
84 self.smallest_subnormal = float6_e3m2fn(smallest_subnormal)
87class _Float8E3m4MachArLike:
89 def __init__(self):
90 smallest_normal = float.fromhex("0x1p-2")
91 self.smallest_normal = float8_e3m4(smallest_normal)
92 smallest_subnormal = float.fromhex("0x0.1p-2")
93 self.smallest_subnormal = float8_e3m4(smallest_subnormal)
96class _Float8E4m3MachArLike:
98 def __init__(self):
99 smallest_normal = float.fromhex("0x1p-6")
100 self.smallest_normal = float8_e4m3(smallest_normal)
101 smallest_subnormal = float.fromhex("0x0.2p-6")
102 self.smallest_subnormal = float8_e4m3(smallest_subnormal)
105class _Float8E4m3b11fnuzMachArLike:
107 def __init__(self):
108 smallest_normal = float.fromhex("0x1p-10")
109 self.smallest_normal = float8_e4m3b11fnuz(smallest_normal)
110 smallest_subnormal = float.fromhex("0x1p-13")
111 self.smallest_subnormal = float8_e4m3b11fnuz(smallest_subnormal)
114class _Float8E4m3fnMachArLike:
116 def __init__(self):
117 smallest_normal = float.fromhex("0x1p-6")
118 self.smallest_normal = float8_e4m3fn(smallest_normal)
119 smallest_subnormal = float.fromhex("0x1p-9")
120 self.smallest_subnormal = float8_e4m3fn(smallest_subnormal)
123class _Float8E4m3fnuzMachArLike:
125 def __init__(self):
126 smallest_normal = float.fromhex("0x1p-7")
127 self.smallest_normal = float8_e4m3fnuz(smallest_normal)
128 smallest_subnormal = float.fromhex("0x1p-10")
129 self.smallest_subnormal = float8_e4m3fnuz(smallest_subnormal)
132class _Float8E5m2MachArLike:
134 def __init__(self):
135 smallest_normal = float.fromhex("0x1p-14")
136 self.smallest_normal = float8_e5m2(smallest_normal)
137 smallest_subnormal = float.fromhex("0x1p-16")
138 self.smallest_subnormal = float8_e5m2(smallest_subnormal)
141class _Float8E5m2fnuzMachArLike:
143 def __init__(self):
144 smallest_normal = float.fromhex("0x1p-15")
145 self.smallest_normal = float8_e5m2fnuz(smallest_normal)
146 smallest_subnormal = float.fromhex("0x1p-17")
147 self.smallest_subnormal = float8_e5m2fnuz(smallest_subnormal)
150class _Float8E8m0fnuMachArLike:
152 def __init__(self):
153 smallest_normal = float.fromhex("0x1p-127")
154 self.smallest_normal = float8_e8m0fnu(smallest_normal)
155 smallest_subnormal = float.fromhex("0x1p-127")
156 self.smallest_subnormal = float8_e8m0fnu(smallest_subnormal)
159class finfo(np.finfo): # pylint: disable=invalid-name,missing-class-docstring
160 __doc__ = np.finfo.__doc__
162 @staticmethod
163 def _bfloat16_finfo():
164 def float_to_str(f):
165 return "%12.4e" % float(f)
167 tiny = float.fromhex("0x1p-126")
168 resolution = 0.01
169 eps = float.fromhex("0x1p-7")
170 epsneg = float.fromhex("0x1p-8")
171 max_ = float.fromhex("0x1.FEp127")
173 obj = object.__new__(np.finfo)
174 obj.dtype = _bfloat16_dtype
175 obj.bits = 16
176 obj.eps = bfloat16(eps)
177 obj.epsneg = bfloat16(epsneg)
178 obj.machep = -7
179 obj.negep = -8
180 obj.max = bfloat16(max_)
181 obj.min = bfloat16(-max_)
182 obj.nexp = 8
183 obj.nmant = 7
184 obj.iexp = obj.nexp
185 obj.maxexp = 128
186 obj.minexp = -126
187 obj.precision = 2
188 obj.resolution = bfloat16(resolution)
189 # pylint: disable=protected-access
190 obj._machar = _Bfloat16MachArLike()
191 if not hasattr(obj, "tiny"):
192 obj.tiny = bfloat16(tiny)
193 if not hasattr(obj, "smallest_normal"):
194 obj.smallest_normal = obj._machar.smallest_normal
195 obj.smallest_subnormal = obj._machar.smallest_subnormal
197 obj._str_tiny = float_to_str(tiny)
198 obj._str_smallest_normal = float_to_str(tiny)
199 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
200 obj._str_max = float_to_str(max_)
201 obj._str_epsneg = float_to_str(epsneg)
202 obj._str_eps = float_to_str(eps)
203 obj._str_resolution = float_to_str(resolution)
204 # pylint: enable=protected-access
205 return obj
207 @staticmethod
208 def _float4_e2m1fn_finfo():
209 eps = float.fromhex("0x0.8p0") # 0.5
210 max_ = float.fromhex("0x1.8p2") # 6.0
212 obj = object.__new__(np.finfo)
213 obj.dtype = _float4_e2m1fn_dtype
214 obj.bits = 4
215 obj.eps = eps
216 obj.epsneg = eps
217 obj.machep = -1
218 obj.negep = -1
219 obj.max = float4_e2m1fn(max_)
220 obj.min = float4_e2m1fn(-max_)
221 obj.nexp = 2
222 obj.nmant = 1
223 obj.iexp = obj.nexp
224 obj.maxexp = 3
225 obj.minexp = 0
226 obj.precision = 0
227 obj.resolution = float4_e2m1fn(1.0)
228 # pylint: disable=protected-access
229 obj._machar = _Float4E2m1fnMachArLike()
230 tiny = obj._machar.smallest_normal
231 if not hasattr(obj, "tiny"):
232 obj.tiny = tiny
233 if not hasattr(obj, "smallest_normal"):
234 obj.smallest_normal = tiny
235 obj.smallest_subnormal = obj._machar.smallest_subnormal
237 float_to_str = str
238 obj._str_tiny = float_to_str(tiny)
239 obj._str_smallest_normal = float_to_str(tiny)
240 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
241 obj._str_max = float_to_str(obj.max)
242 obj._str_epsneg = float_to_str(obj.epsneg)
243 obj._str_eps = float_to_str(obj.eps)
244 obj._str_resolution = float_to_str(obj.resolution)
245 # pylint: enable=protected-access
246 return obj
248 @staticmethod
249 def _float6_e2m3fn_finfo():
250 eps = float.fromhex("0x0.2p0") # 0.125
251 max_ = float.fromhex("0x1.Ep2") # 7.5
253 obj = object.__new__(np.finfo)
254 obj.dtype = _float6_e2m3fn_dtype
255 obj.bits = 6
256 obj.eps = eps
257 obj.epsneg = eps
258 obj.machep = -3
259 obj.negep = -3
260 obj.max = float6_e2m3fn(max_)
261 obj.min = float6_e2m3fn(-max_)
262 obj.nexp = 2
263 obj.nmant = 3
264 obj.iexp = obj.nexp
265 obj.maxexp = 3
266 obj.minexp = 0
267 obj.precision = 0
268 obj.resolution = float6_e2m3fn(1.0)
269 # pylint: disable=protected-access
270 obj._machar = _Float6E2m3fnMachArLike()
271 tiny = obj._machar.smallest_normal
272 if not hasattr(obj, "tiny"):
273 obj.tiny = tiny
274 if not hasattr(obj, "smallest_normal"):
275 obj.smallest_normal = tiny
276 obj.smallest_subnormal = obj._machar.smallest_subnormal
278 float_to_str = str
279 obj._str_tiny = float_to_str(tiny)
280 obj._str_smallest_normal = float_to_str(tiny)
281 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
282 obj._str_max = float_to_str(obj.max)
283 obj._str_epsneg = float_to_str(obj.epsneg)
284 obj._str_eps = float_to_str(obj.eps)
285 obj._str_resolution = float_to_str(obj.resolution)
286 # pylint: enable=protected-access
287 return obj
289 @staticmethod
290 def _float6_e3m2fn_finfo():
291 eps = float.fromhex("0x1p-2") # 0.25
292 max_ = float.fromhex("0x1.Cp4") # 28
294 obj = object.__new__(np.finfo)
295 obj.dtype = _float6_e3m2fn_dtype
296 obj.bits = 6
297 obj.eps = eps
298 obj.epsneg = eps / 2
299 obj.machep = -2
300 obj.negep = -3
301 obj.max = float6_e3m2fn(max_)
302 obj.min = float6_e3m2fn(-max_)
303 obj.nexp = 3
304 obj.nmant = 2
305 obj.iexp = obj.nexp
306 obj.maxexp = 5
307 obj.minexp = -2
308 obj.precision = 0
309 obj.resolution = float6_e3m2fn(1.0)
310 # pylint: disable=protected-access
311 obj._machar = _Float6E3m2fnMachArLike()
312 tiny = obj._machar.smallest_normal
313 if not hasattr(obj, "tiny"):
314 obj.tiny = tiny
315 if not hasattr(obj, "smallest_normal"):
316 obj.smallest_normal = tiny
317 obj.smallest_subnormal = obj._machar.smallest_subnormal
319 float_to_str = str
320 obj._str_tiny = float_to_str(tiny)
321 obj._str_smallest_normal = float_to_str(tiny)
322 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
323 obj._str_max = float_to_str(obj.max)
324 obj._str_epsneg = float_to_str(obj.epsneg)
325 obj._str_eps = float_to_str(obj.eps)
326 obj._str_resolution = float_to_str(obj.resolution)
327 # pylint: enable=protected-access
328 return obj
330 @staticmethod
331 def _float8_e3m4_finfo():
332 def float_to_str(f):
333 return "%6.2e" % float(f)
335 tiny = float.fromhex("0x1p-2") # 1/4 min normal
336 resolution = 0.1
337 eps = float.fromhex("0x1p-4") # 1/16
338 epsneg = float.fromhex("0x1p-5") # 1/32
339 max_ = float.fromhex("0x1.Fp3") # 15.5 max normal
341 obj = object.__new__(np.finfo)
342 obj.dtype = _float8_e3m4_dtype
343 obj.bits = 8
344 obj.eps = float8_e3m4(eps)
345 obj.epsneg = float8_e3m4(epsneg)
346 obj.machep = -4
347 obj.negep = -5
348 obj.max = float8_e3m4(max_)
349 obj.min = float8_e3m4(-max_)
350 obj.nexp = 3
351 obj.nmant = 4
352 obj.iexp = obj.nexp
353 obj.maxexp = 4
354 obj.minexp = -2
355 obj.precision = 1
356 obj.resolution = float8_e3m4(resolution)
357 # pylint: disable=protected-access
358 obj._machar = _Float8E3m4MachArLike()
359 if not hasattr(obj, "tiny"):
360 obj.tiny = float8_e3m4(tiny)
361 if not hasattr(obj, "smallest_normal"):
362 obj.smallest_normal = obj._machar.smallest_normal
363 obj.smallest_subnormal = obj._machar.smallest_subnormal
365 obj._str_tiny = float_to_str(tiny)
366 obj._str_smallest_normal = float_to_str(tiny)
367 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
368 obj._str_max = float_to_str(max_)
369 obj._str_epsneg = float_to_str(epsneg)
370 obj._str_eps = float_to_str(eps)
371 obj._str_resolution = float_to_str(resolution)
372 # pylint: enable=protected-access
373 return obj
375 @staticmethod
376 def _float8_e4m3_finfo():
377 def float_to_str(f):
378 return "%6.2e" % float(f)
380 tiny = float.fromhex("0x1p-6") # 1/64 min normal
381 resolution = 0.1
382 eps = float.fromhex("0x1p-3") # 1/8
383 epsneg = float.fromhex("0x1p-4") # 1/16
384 max_ = float.fromhex("0x1.Ep7") # 240 max normal
386 obj = object.__new__(np.finfo)
387 obj.dtype = _float8_e4m3_dtype
388 obj.bits = 8
389 obj.eps = float8_e4m3(eps)
390 obj.epsneg = float8_e4m3(epsneg)
391 obj.machep = -3
392 obj.negep = -4
393 obj.max = float8_e4m3(max_)
394 obj.min = float8_e4m3(-max_)
395 obj.nexp = 4
396 obj.nmant = 3
397 obj.iexp = obj.nexp
398 obj.maxexp = 8
399 obj.minexp = -6
400 obj.precision = 1
401 obj.resolution = float8_e4m3(resolution)
402 # pylint: disable=protected-access
403 obj._machar = _Float8E4m3MachArLike()
404 if not hasattr(obj, "tiny"):
405 obj.tiny = float8_e4m3(tiny)
406 if not hasattr(obj, "smallest_normal"):
407 obj.smallest_normal = obj._machar.smallest_normal
408 obj.smallest_subnormal = obj._machar.smallest_subnormal
410 obj._str_tiny = float_to_str(tiny)
411 obj._str_smallest_normal = float_to_str(tiny)
412 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
413 obj._str_max = float_to_str(max_)
414 obj._str_epsneg = float_to_str(epsneg)
415 obj._str_eps = float_to_str(eps)
416 obj._str_resolution = float_to_str(resolution)
417 # pylint: enable=protected-access
418 return obj
420 @staticmethod
421 def _float8_e4m3b11fnuz_finfo():
422 def float_to_str(f):
423 return "%6.2e" % float(f)
425 tiny = float.fromhex("0x1p-10")
426 resolution = 0.1
427 eps = float.fromhex("0x1p-3")
428 epsneg = float.fromhex("0x1p-4")
429 max_ = float.fromhex("0x1.Ep4")
431 obj = object.__new__(np.finfo)
432 obj.dtype = _float8_e4m3b11fnuz_dtype
433 obj.bits = 8
434 obj.eps = float8_e4m3b11fnuz(eps)
435 obj.epsneg = float8_e4m3b11fnuz(epsneg)
436 obj.machep = -3
437 obj.negep = -4
438 obj.max = float8_e4m3b11fnuz(max_)
439 obj.min = float8_e4m3b11fnuz(-max_)
440 obj.nexp = 4
441 obj.nmant = 3
442 obj.iexp = obj.nexp
443 obj.maxexp = 5
444 obj.minexp = -10
445 obj.precision = 1
446 obj.resolution = float8_e4m3b11fnuz(resolution)
447 # pylint: disable=protected-access
448 obj._machar = _Float8E4m3b11fnuzMachArLike()
449 if not hasattr(obj, "tiny"):
450 obj.tiny = float8_e4m3b11fnuz(tiny)
451 if not hasattr(obj, "smallest_normal"):
452 obj.smallest_normal = obj._machar.smallest_normal
453 obj.smallest_subnormal = obj._machar.smallest_subnormal
455 obj._str_tiny = float_to_str(tiny)
456 obj._str_smallest_normal = float_to_str(tiny)
457 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
458 obj._str_max = float_to_str(max_)
459 obj._str_epsneg = float_to_str(epsneg)
460 obj._str_eps = float_to_str(eps)
461 obj._str_resolution = float_to_str(resolution)
462 # pylint: enable=protected-access
463 return obj
465 @staticmethod
466 def _float8_e4m3fn_finfo():
467 def float_to_str(f):
468 return "%6.2e" % float(f)
470 tiny = float.fromhex("0x1p-6")
471 resolution = 0.1
472 eps = float.fromhex("0x1p-3")
473 epsneg = float.fromhex("0x1p-4")
474 max_ = float.fromhex("0x1.Cp8")
476 obj = object.__new__(np.finfo)
477 obj.dtype = _float8_e4m3fn_dtype
478 obj.bits = 8
479 obj.eps = float8_e4m3fn(eps)
480 obj.epsneg = float8_e4m3fn(epsneg)
481 obj.machep = -3
482 obj.negep = -4
483 obj.max = float8_e4m3fn(max_)
484 obj.min = float8_e4m3fn(-max_)
485 obj.nexp = 4
486 obj.nmant = 3
487 obj.iexp = obj.nexp
488 obj.maxexp = 9
489 obj.minexp = -6
490 obj.precision = 1
491 obj.resolution = float8_e4m3fn(resolution)
492 # pylint: disable=protected-access
493 obj._machar = _Float8E4m3fnMachArLike()
494 if not hasattr(obj, "tiny"):
495 obj.tiny = float8_e4m3fn(tiny)
496 if not hasattr(obj, "smallest_normal"):
497 obj.smallest_normal = obj._machar.smallest_normal
498 obj.smallest_subnormal = obj._machar.smallest_subnormal
500 obj._str_tiny = float_to_str(tiny)
501 obj._str_smallest_normal = float_to_str(tiny)
502 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
503 obj._str_max = float_to_str(max_)
504 obj._str_epsneg = float_to_str(epsneg)
505 obj._str_eps = float_to_str(eps)
506 obj._str_resolution = float_to_str(resolution)
507 # pylint: enable=protected-access
508 return obj
510 @staticmethod
511 def _float8_e4m3fnuz_finfo():
512 def float_to_str(f):
513 return "%6.2e" % float(f)
515 tiny = float.fromhex("0x1p-7")
516 resolution = 0.1
517 eps = float.fromhex("0x1p-3")
518 epsneg = float.fromhex("0x1p-4")
519 max_ = float.fromhex("0x1.Ep7")
521 obj = object.__new__(np.finfo)
522 obj.dtype = _float8_e4m3fnuz_dtype
523 obj.bits = 8
524 obj.eps = float8_e4m3fnuz(eps)
525 obj.epsneg = float8_e4m3fnuz(epsneg)
526 obj.machep = -3
527 obj.negep = -4
528 obj.max = float8_e4m3fnuz(max_)
529 obj.min = float8_e4m3fnuz(-max_)
530 obj.nexp = 4
531 obj.nmant = 3
532 obj.iexp = obj.nexp
533 obj.maxexp = 8
534 obj.minexp = -7
535 obj.precision = 1
536 obj.resolution = float8_e4m3fnuz(resolution)
537 # pylint: disable=protected-access
538 obj._machar = _Float8E4m3fnuzMachArLike()
539 if not hasattr(obj, "tiny"):
540 obj.tiny = float8_e4m3fnuz(tiny)
541 if not hasattr(obj, "smallest_normal"):
542 obj.smallest_normal = obj._machar.smallest_normal
543 obj.smallest_subnormal = obj._machar.smallest_subnormal
545 obj._str_tiny = float_to_str(tiny)
546 obj._str_smallest_normal = float_to_str(tiny)
547 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
548 obj._str_max = float_to_str(max_)
549 obj._str_epsneg = float_to_str(epsneg)
550 obj._str_eps = float_to_str(eps)
551 obj._str_resolution = float_to_str(resolution)
552 # pylint: enable=protected-access
553 return obj
555 @staticmethod
556 def _float8_e5m2_finfo():
557 def float_to_str(f):
558 return "%6.2e" % float(f)
560 tiny = float.fromhex("0x1p-14")
561 resolution = 0.1
562 eps = float.fromhex("0x1p-2")
563 epsneg = float.fromhex("0x1p-3")
564 max_ = float.fromhex("0x1.Cp15")
566 obj = object.__new__(np.finfo)
567 obj.dtype = _float8_e5m2_dtype
568 obj.bits = 8
569 obj.eps = float8_e5m2(eps)
570 obj.epsneg = float8_e5m2(epsneg)
571 obj.machep = -2
572 obj.negep = -3
573 obj.max = float8_e5m2(max_)
574 obj.min = float8_e5m2(-max_)
575 obj.nexp = 5
576 obj.nmant = 2
577 obj.iexp = obj.nexp
578 obj.maxexp = 16
579 obj.minexp = -14
580 obj.precision = 1
581 obj.resolution = float8_e5m2(resolution)
582 # pylint: disable=protected-access
583 obj._machar = _Float8E5m2MachArLike()
584 if not hasattr(obj, "tiny"):
585 obj.tiny = float8_e5m2(tiny)
586 if not hasattr(obj, "smallest_normal"):
587 obj.smallest_normal = obj._machar.smallest_normal
588 obj.smallest_subnormal = obj._machar.smallest_subnormal
590 obj._str_tiny = float_to_str(tiny)
591 obj._str_smallest_normal = float_to_str(tiny)
592 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
593 obj._str_max = float_to_str(max_)
594 obj._str_epsneg = float_to_str(epsneg)
595 obj._str_eps = float_to_str(eps)
596 obj._str_resolution = float_to_str(resolution)
597 # pylint: enable=protected-access
598 return obj
600 @staticmethod
601 def _float8_e5m2fnuz_finfo():
602 def float_to_str(f):
603 return "%6.2e" % float(f)
605 tiny = float.fromhex("0x1p-15")
606 resolution = 0.1
607 eps = float.fromhex("0x1p-2")
608 epsneg = float.fromhex("0x1p-3")
609 max_ = float.fromhex("0x1.Cp15")
611 obj = object.__new__(np.finfo)
612 obj.dtype = _float8_e5m2fnuz_dtype
613 obj.bits = 8
614 obj.eps = float8_e5m2fnuz(eps)
615 obj.epsneg = float8_e5m2fnuz(epsneg)
616 obj.machep = -2
617 obj.negep = -3
618 obj.max = float8_e5m2fnuz(max_)
619 obj.min = float8_e5m2fnuz(-max_)
620 obj.nexp = 5
621 obj.nmant = 2
622 obj.iexp = obj.nexp
623 obj.maxexp = 16
624 obj.minexp = -15
625 obj.precision = 1
626 obj.resolution = float8_e5m2fnuz(resolution)
627 # pylint: disable=protected-access
628 obj._machar = _Float8E5m2fnuzMachArLike()
629 if not hasattr(obj, "tiny"):
630 obj.tiny = float8_e5m2fnuz(tiny)
631 if not hasattr(obj, "smallest_normal"):
632 obj.smallest_normal = obj._machar.smallest_normal
633 obj.smallest_subnormal = obj._machar.smallest_subnormal
635 obj._str_tiny = float_to_str(tiny)
636 obj._str_smallest_normal = float_to_str(tiny)
637 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
638 obj._str_max = float_to_str(max_)
639 obj._str_epsneg = float_to_str(epsneg)
640 obj._str_eps = float_to_str(eps)
641 obj._str_resolution = float_to_str(resolution)
642 # pylint: enable=protected-access
643 return obj
645 @staticmethod
646 def _float8_e8m0fnu_finfo():
647 def float_to_str(f):
648 return "%6.2e" % float(f)
650 tiny = float.fromhex("0x1p-127")
651 resolution = 0.1
652 eps = float.fromhex("0x1p+0")
653 epsneg = float.fromhex("0x1p-1")
654 max_ = float.fromhex("0x1p+127")
656 obj = object.__new__(np.finfo)
657 obj.dtype = _float8_e8m0fnu_dtype
658 obj.bits = 8
659 obj.eps = float8_e8m0fnu(eps)
660 obj.epsneg = float8_e8m0fnu(epsneg)
661 obj.machep = 0
662 obj.negep = -1
663 obj.max = float8_e8m0fnu(max_)
664 obj.min = float8_e8m0fnu(tiny)
665 obj.nexp = 8
666 obj.nmant = 0
667 obj.iexp = obj.nexp
668 obj.maxexp = 128
669 obj.minexp = -127
670 obj.precision = 1
671 obj.resolution = float8_e8m0fnu(resolution)
672 # pylint: disable=protected-access
673 obj._machar = _Float8E8m0fnuMachArLike()
674 if not hasattr(obj, "tiny"):
675 obj.tiny = float8_e8m0fnu(tiny)
676 if not hasattr(obj, "smallest_normal"):
677 obj.smallest_normal = obj._machar.smallest_normal
678 obj.smallest_subnormal = obj._machar.smallest_subnormal
680 obj._str_tiny = float_to_str(tiny)
681 obj._str_smallest_normal = float_to_str(tiny)
682 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
683 obj._str_max = float_to_str(max_)
684 obj._str_epsneg = float_to_str(epsneg)
685 obj._str_eps = float_to_str(eps)
686 obj._str_resolution = float_to_str(resolution)
687 # pylint: enable=protected-access
688 return obj
690 _finfo_type_map = {
691 _bfloat16_dtype: _bfloat16_finfo,
692 _float4_e2m1fn_dtype: _float4_e2m1fn_finfo,
693 _float6_e2m3fn_dtype: _float6_e2m3fn_finfo,
694 _float6_e3m2fn_dtype: _float6_e3m2fn_finfo,
695 _float8_e3m4_dtype: _float8_e3m4_finfo,
696 _float8_e4m3_dtype: _float8_e4m3_finfo,
697 _float8_e4m3fn_dtype: _float8_e4m3fn_finfo,
698 _float8_e4m3fnuz_dtype: _float8_e4m3fnuz_finfo,
699 _float8_e4m3b11fnuz_dtype: _float8_e4m3b11fnuz_finfo,
700 _float8_e5m2_dtype: _float8_e5m2_finfo,
701 _float8_e5m2fnuz_dtype: _float8_e5m2fnuz_finfo,
702 _float8_e8m0fnu_dtype: _float8_e8m0fnu_finfo,
703 _bcomplex32_dtype: _bfloat16_finfo,
704 }
705 _finfo_name_map = {t.name: t for t in _finfo_type_map}
706 _finfo_cache = {
707 t: init_fn.__func__() # pytype: disable=attribute-error
708 for t, init_fn in _finfo_type_map.items()
709 }
710 _finfo_cache[_complex32_dtype] = np.finfo(np.float16)
712 def __new__(cls, dtype):
713 # Check for dtype attribute in order to handle finfo(arr), as required by
714 # the Python Array API standard.
715 if hasattr(dtype, "dtype") and isinstance(dtype.dtype, np.dtype):
716 dtype = dtype.dtype
718 if isinstance(dtype, str):
719 key = cls._finfo_name_map.get(dtype)
720 elif isinstance(dtype, np.dtype):
721 key = dtype
722 else:
723 key = np.dtype(dtype)
724 i = cls._finfo_cache.get(key)
725 if i is not None:
726 return i
727 return super().__new__(cls, dtype)