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"""Overload of numpy.finfo to handle dtypes defined in ml_dtypes."""
17from ml_dtypes._ml_dtypes_ext import bfloat16
18from ml_dtypes._ml_dtypes_ext import float4_e2m1fn
19from ml_dtypes._ml_dtypes_ext import float6_e2m3fn
20from ml_dtypes._ml_dtypes_ext import float6_e3m2fn
21from ml_dtypes._ml_dtypes_ext import float8_e3m4
22from ml_dtypes._ml_dtypes_ext import float8_e4m3
23from ml_dtypes._ml_dtypes_ext import float8_e4m3b11fnuz
24from ml_dtypes._ml_dtypes_ext import float8_e4m3fn
25from ml_dtypes._ml_dtypes_ext import float8_e4m3fnuz
26from ml_dtypes._ml_dtypes_ext import float8_e5m2
27from ml_dtypes._ml_dtypes_ext import float8_e5m2fnuz
28from ml_dtypes._ml_dtypes_ext import float8_e8m0fnu
29import numpy as np
31_bfloat16_dtype = np.dtype(bfloat16)
32_float4_e2m1fn_dtype = np.dtype(float4_e2m1fn)
33_float6_e2m3fn_dtype = np.dtype(float6_e2m3fn)
34_float6_e3m2fn_dtype = np.dtype(float6_e3m2fn)
35_float8_e3m4_dtype = np.dtype(float8_e3m4)
36_float8_e4m3_dtype = np.dtype(float8_e4m3)
37_float8_e4m3b11fnuz_dtype = np.dtype(float8_e4m3b11fnuz)
38_float8_e4m3fn_dtype = np.dtype(float8_e4m3fn)
39_float8_e4m3fnuz_dtype = np.dtype(float8_e4m3fnuz)
40_float8_e5m2_dtype = np.dtype(float8_e5m2)
41_float8_e5m2fnuz_dtype = np.dtype(float8_e5m2fnuz)
42_float8_e8m0fnu_dtype = np.dtype(float8_e8m0fnu)
45class _Bfloat16MachArLike:
47 def __init__(self):
48 smallest_normal = float.fromhex("0x1p-126")
49 self.smallest_normal = bfloat16(smallest_normal)
50 smallest_subnormal = float.fromhex("0x1p-133")
51 self.smallest_subnormal = bfloat16(smallest_subnormal)
54class _Float4E2m1fnMachArLike:
56 def __init__(self):
57 smallest_normal = float.fromhex("0x1p0")
58 self.smallest_normal = float4_e2m1fn(smallest_normal)
59 smallest_subnormal = float.fromhex("0x0.8p0")
60 self.smallest_subnormal = float4_e2m1fn(smallest_subnormal)
63class _Float6E2m3fnMachArLike:
65 def __init__(self):
66 smallest_normal = float.fromhex("0x1p0")
67 self.smallest_normal = float6_e2m3fn(smallest_normal)
68 smallest_subnormal = float.fromhex("0x0.2p0")
69 self.smallest_subnormal = float6_e2m3fn(smallest_subnormal)
72class _Float6E3m2fnMachArLike:
74 def __init__(self):
75 smallest_normal = float.fromhex("0x1p-2")
76 self.smallest_normal = float6_e3m2fn(smallest_normal)
77 smallest_subnormal = float.fromhex("0x0.4p-2")
78 self.smallest_subnormal = float6_e3m2fn(smallest_subnormal)
81class _Float8E3m4MachArLike:
83 def __init__(self):
84 smallest_normal = float.fromhex("0x1p-2")
85 self.smallest_normal = float8_e3m4(smallest_normal)
86 smallest_subnormal = float.fromhex("0x0.1p-2")
87 self.smallest_subnormal = float8_e3m4(smallest_subnormal)
90class _Float8E4m3MachArLike:
92 def __init__(self):
93 smallest_normal = float.fromhex("0x1p-6")
94 self.smallest_normal = float8_e4m3(smallest_normal)
95 smallest_subnormal = float.fromhex("0x0.2p-6")
96 self.smallest_subnormal = float8_e4m3(smallest_subnormal)
99class _Float8E4m3b11fnuzMachArLike:
101 def __init__(self):
102 smallest_normal = float.fromhex("0x1p-10")
103 self.smallest_normal = float8_e4m3b11fnuz(smallest_normal)
104 smallest_subnormal = float.fromhex("0x1p-13")
105 self.smallest_subnormal = float8_e4m3b11fnuz(smallest_subnormal)
108class _Float8E4m3fnMachArLike:
110 def __init__(self):
111 smallest_normal = float.fromhex("0x1p-6")
112 self.smallest_normal = float8_e4m3fn(smallest_normal)
113 smallest_subnormal = float.fromhex("0x1p-9")
114 self.smallest_subnormal = float8_e4m3fn(smallest_subnormal)
117class _Float8E4m3fnuzMachArLike:
119 def __init__(self):
120 smallest_normal = float.fromhex("0x1p-7")
121 self.smallest_normal = float8_e4m3fnuz(smallest_normal)
122 smallest_subnormal = float.fromhex("0x1p-10")
123 self.smallest_subnormal = float8_e4m3fnuz(smallest_subnormal)
126class _Float8E5m2MachArLike:
128 def __init__(self):
129 smallest_normal = float.fromhex("0x1p-14")
130 self.smallest_normal = float8_e5m2(smallest_normal)
131 smallest_subnormal = float.fromhex("0x1p-16")
132 self.smallest_subnormal = float8_e5m2(smallest_subnormal)
135class _Float8E5m2fnuzMachArLike:
137 def __init__(self):
138 smallest_normal = float.fromhex("0x1p-15")
139 self.smallest_normal = float8_e5m2fnuz(smallest_normal)
140 smallest_subnormal = float.fromhex("0x1p-17")
141 self.smallest_subnormal = float8_e5m2fnuz(smallest_subnormal)
144class _Float8E8m0fnuMachArLike:
146 def __init__(self):
147 smallest_normal = float.fromhex("0x1p-127")
148 self.smallest_normal = float8_e8m0fnu(smallest_normal)
149 smallest_subnormal = float.fromhex("0x1p-127")
150 self.smallest_subnormal = float8_e8m0fnu(smallest_subnormal)
153class finfo(np.finfo): # pylint: disable=invalid-name,missing-class-docstring
154 __doc__ = np.finfo.__doc__
156 @staticmethod
157 def _bfloat16_finfo():
158 def float_to_str(f):
159 return "%12.4e" % float(f)
161 tiny = float.fromhex("0x1p-126")
162 resolution = 0.01
163 eps = float.fromhex("0x1p-7")
164 epsneg = float.fromhex("0x1p-8")
165 max_ = float.fromhex("0x1.FEp127")
167 obj = object.__new__(np.finfo)
168 obj.dtype = _bfloat16_dtype
169 obj.bits = 16
170 obj.eps = bfloat16(eps)
171 obj.epsneg = bfloat16(epsneg)
172 obj.machep = -7
173 obj.negep = -8
174 obj.max = bfloat16(max_)
175 obj.min = bfloat16(-max_)
176 obj.nexp = 8
177 obj.nmant = 7
178 obj.iexp = obj.nexp
179 obj.maxexp = 128
180 obj.minexp = -126
181 obj.precision = 2
182 obj.resolution = bfloat16(resolution)
183 # pylint: disable=protected-access
184 obj._machar = _Bfloat16MachArLike()
185 if not hasattr(obj, "tiny"):
186 obj.tiny = bfloat16(tiny)
187 if not hasattr(obj, "smallest_normal"):
188 obj.smallest_normal = obj._machar.smallest_normal
189 obj.smallest_subnormal = obj._machar.smallest_subnormal
191 obj._str_tiny = float_to_str(tiny)
192 obj._str_smallest_normal = float_to_str(tiny)
193 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
194 obj._str_max = float_to_str(max_)
195 obj._str_epsneg = float_to_str(epsneg)
196 obj._str_eps = float_to_str(eps)
197 obj._str_resolution = float_to_str(resolution)
198 # pylint: enable=protected-access
199 return obj
201 @staticmethod
202 def _float4_e2m1fn_finfo():
203 eps = float.fromhex("0x0.8p0") # 0.5
204 max_ = float.fromhex("0x1.8p2") # 6.0
206 obj = object.__new__(np.finfo)
207 obj.dtype = _float4_e2m1fn_dtype
208 obj.bits = 4
209 obj.eps = eps
210 obj.epsneg = eps
211 obj.machep = -1
212 obj.negep = -1
213 obj.max = float4_e2m1fn(max_)
214 obj.min = float4_e2m1fn(-max_)
215 obj.nexp = 2
216 obj.nmant = 1
217 obj.iexp = obj.nexp
218 obj.maxexp = 3
219 obj.minexp = 0
220 obj.precision = 0
221 obj.resolution = float4_e2m1fn(1.0)
222 # pylint: disable=protected-access
223 obj._machar = _Float4E2m1fnMachArLike()
224 tiny = obj._machar.smallest_normal
225 if not hasattr(obj, "tiny"):
226 obj.tiny = tiny
227 if not hasattr(obj, "smallest_normal"):
228 obj.smallest_normal = tiny
229 obj.smallest_subnormal = obj._machar.smallest_subnormal
231 float_to_str = str
232 obj._str_tiny = float_to_str(tiny)
233 obj._str_smallest_normal = float_to_str(tiny)
234 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
235 obj._str_max = float_to_str(obj.max)
236 obj._str_epsneg = float_to_str(obj.epsneg)
237 obj._str_eps = float_to_str(obj.eps)
238 obj._str_resolution = float_to_str(obj.resolution)
239 # pylint: enable=protected-access
240 return obj
242 @staticmethod
243 def _float6_e2m3fn_finfo():
244 eps = float.fromhex("0x0.2p0") # 0.125
245 max_ = float.fromhex("0x1.Ep2") # 7.5
247 obj = object.__new__(np.finfo)
248 obj.dtype = _float6_e2m3fn_dtype
249 obj.bits = 6
250 obj.eps = eps
251 obj.epsneg = eps
252 obj.machep = -3
253 obj.negep = -3
254 obj.max = float6_e2m3fn(max_)
255 obj.min = float6_e2m3fn(-max_)
256 obj.nexp = 2
257 obj.nmant = 3
258 obj.iexp = obj.nexp
259 obj.maxexp = 3
260 obj.minexp = 0
261 obj.precision = 0
262 obj.resolution = float6_e2m3fn(1.0)
263 # pylint: disable=protected-access
264 obj._machar = _Float6E2m3fnMachArLike()
265 tiny = obj._machar.smallest_normal
266 if not hasattr(obj, "tiny"):
267 obj.tiny = tiny
268 if not hasattr(obj, "smallest_normal"):
269 obj.smallest_normal = tiny
270 obj.smallest_subnormal = obj._machar.smallest_subnormal
272 float_to_str = str
273 obj._str_tiny = float_to_str(tiny)
274 obj._str_smallest_normal = float_to_str(tiny)
275 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
276 obj._str_max = float_to_str(obj.max)
277 obj._str_epsneg = float_to_str(obj.epsneg)
278 obj._str_eps = float_to_str(obj.eps)
279 obj._str_resolution = float_to_str(obj.resolution)
280 # pylint: enable=protected-access
281 return obj
283 @staticmethod
284 def _float6_e3m2fn_finfo():
285 eps = float.fromhex("0x1p-2") # 0.25
286 max_ = float.fromhex("0x1.Cp4") # 28
288 obj = object.__new__(np.finfo)
289 obj.dtype = _float6_e3m2fn_dtype
290 obj.bits = 6
291 obj.eps = eps
292 obj.epsneg = eps / 2
293 obj.machep = -2
294 obj.negep = -3
295 obj.max = float6_e3m2fn(max_)
296 obj.min = float6_e3m2fn(-max_)
297 obj.nexp = 3
298 obj.nmant = 2
299 obj.iexp = obj.nexp
300 obj.maxexp = 5
301 obj.minexp = -2
302 obj.precision = 0
303 obj.resolution = float6_e3m2fn(1.0)
304 # pylint: disable=protected-access
305 obj._machar = _Float6E3m2fnMachArLike()
306 tiny = obj._machar.smallest_normal
307 if not hasattr(obj, "tiny"):
308 obj.tiny = tiny
309 if not hasattr(obj, "smallest_normal"):
310 obj.smallest_normal = tiny
311 obj.smallest_subnormal = obj._machar.smallest_subnormal
313 float_to_str = str
314 obj._str_tiny = float_to_str(tiny)
315 obj._str_smallest_normal = float_to_str(tiny)
316 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
317 obj._str_max = float_to_str(obj.max)
318 obj._str_epsneg = float_to_str(obj.epsneg)
319 obj._str_eps = float_to_str(obj.eps)
320 obj._str_resolution = float_to_str(obj.resolution)
321 # pylint: enable=protected-access
322 return obj
324 @staticmethod
325 def _float8_e3m4_finfo():
326 def float_to_str(f):
327 return "%6.2e" % float(f)
329 tiny = float.fromhex("0x1p-2") # 1/4 min normal
330 resolution = 0.1
331 eps = float.fromhex("0x1p-4") # 1/16
332 epsneg = float.fromhex("0x1p-5") # 1/32
333 max_ = float.fromhex("0x1.Fp3") # 15.5 max normal
335 obj = object.__new__(np.finfo)
336 obj.dtype = _float8_e3m4_dtype
337 obj.bits = 8
338 obj.eps = float8_e3m4(eps)
339 obj.epsneg = float8_e3m4(epsneg)
340 obj.machep = -4
341 obj.negep = -5
342 obj.max = float8_e3m4(max_)
343 obj.min = float8_e3m4(-max_)
344 obj.nexp = 3
345 obj.nmant = 4
346 obj.iexp = obj.nexp
347 obj.maxexp = 4
348 obj.minexp = -2
349 obj.precision = 1
350 obj.resolution = float8_e3m4(resolution)
351 # pylint: disable=protected-access
352 obj._machar = _Float8E3m4MachArLike()
353 if not hasattr(obj, "tiny"):
354 obj.tiny = float8_e3m4(tiny)
355 if not hasattr(obj, "smallest_normal"):
356 obj.smallest_normal = obj._machar.smallest_normal
357 obj.smallest_subnormal = obj._machar.smallest_subnormal
359 obj._str_tiny = float_to_str(tiny)
360 obj._str_smallest_normal = float_to_str(tiny)
361 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
362 obj._str_max = float_to_str(max_)
363 obj._str_epsneg = float_to_str(epsneg)
364 obj._str_eps = float_to_str(eps)
365 obj._str_resolution = float_to_str(resolution)
366 # pylint: enable=protected-access
367 return obj
369 @staticmethod
370 def _float8_e4m3_finfo():
371 def float_to_str(f):
372 return "%6.2e" % float(f)
374 tiny = float.fromhex("0x1p-6") # 1/64 min normal
375 resolution = 0.1
376 eps = float.fromhex("0x1p-3") # 1/8
377 epsneg = float.fromhex("0x1p-4") # 1/16
378 max_ = float.fromhex("0x1.Ep7") # 240 max normal
380 obj = object.__new__(np.finfo)
381 obj.dtype = _float8_e4m3_dtype
382 obj.bits = 8
383 obj.eps = float8_e4m3(eps)
384 obj.epsneg = float8_e4m3(epsneg)
385 obj.machep = -3
386 obj.negep = -4
387 obj.max = float8_e4m3(max_)
388 obj.min = float8_e4m3(-max_)
389 obj.nexp = 4
390 obj.nmant = 3
391 obj.iexp = obj.nexp
392 obj.maxexp = 8
393 obj.minexp = -6
394 obj.precision = 1
395 obj.resolution = float8_e4m3(resolution)
396 # pylint: disable=protected-access
397 obj._machar = _Float8E4m3MachArLike()
398 if not hasattr(obj, "tiny"):
399 obj.tiny = float8_e4m3(tiny)
400 if not hasattr(obj, "smallest_normal"):
401 obj.smallest_normal = obj._machar.smallest_normal
402 obj.smallest_subnormal = obj._machar.smallest_subnormal
404 obj._str_tiny = float_to_str(tiny)
405 obj._str_smallest_normal = float_to_str(tiny)
406 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
407 obj._str_max = float_to_str(max_)
408 obj._str_epsneg = float_to_str(epsneg)
409 obj._str_eps = float_to_str(eps)
410 obj._str_resolution = float_to_str(resolution)
411 # pylint: enable=protected-access
412 return obj
414 @staticmethod
415 def _float8_e4m3b11fnuz_finfo():
416 def float_to_str(f):
417 return "%6.2e" % float(f)
419 tiny = float.fromhex("0x1p-10")
420 resolution = 0.1
421 eps = float.fromhex("0x1p-3")
422 epsneg = float.fromhex("0x1p-4")
423 max_ = float.fromhex("0x1.Ep4")
425 obj = object.__new__(np.finfo)
426 obj.dtype = _float8_e4m3b11fnuz_dtype
427 obj.bits = 8
428 obj.eps = float8_e4m3b11fnuz(eps)
429 obj.epsneg = float8_e4m3b11fnuz(epsneg)
430 obj.machep = -3
431 obj.negep = -4
432 obj.max = float8_e4m3b11fnuz(max_)
433 obj.min = float8_e4m3b11fnuz(-max_)
434 obj.nexp = 4
435 obj.nmant = 3
436 obj.iexp = obj.nexp
437 obj.maxexp = 5
438 obj.minexp = -10
439 obj.precision = 1
440 obj.resolution = float8_e4m3b11fnuz(resolution)
441 # pylint: disable=protected-access
442 obj._machar = _Float8E4m3b11fnuzMachArLike()
443 if not hasattr(obj, "tiny"):
444 obj.tiny = float8_e4m3b11fnuz(tiny)
445 if not hasattr(obj, "smallest_normal"):
446 obj.smallest_normal = obj._machar.smallest_normal
447 obj.smallest_subnormal = obj._machar.smallest_subnormal
449 obj._str_tiny = float_to_str(tiny)
450 obj._str_smallest_normal = float_to_str(tiny)
451 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
452 obj._str_max = float_to_str(max_)
453 obj._str_epsneg = float_to_str(epsneg)
454 obj._str_eps = float_to_str(eps)
455 obj._str_resolution = float_to_str(resolution)
456 # pylint: enable=protected-access
457 return obj
459 @staticmethod
460 def _float8_e4m3fn_finfo():
461 def float_to_str(f):
462 return "%6.2e" % float(f)
464 tiny = float.fromhex("0x1p-6")
465 resolution = 0.1
466 eps = float.fromhex("0x1p-3")
467 epsneg = float.fromhex("0x1p-4")
468 max_ = float.fromhex("0x1.Cp8")
470 obj = object.__new__(np.finfo)
471 obj.dtype = _float8_e4m3fn_dtype
472 obj.bits = 8
473 obj.eps = float8_e4m3fn(eps)
474 obj.epsneg = float8_e4m3fn(epsneg)
475 obj.machep = -3
476 obj.negep = -4
477 obj.max = float8_e4m3fn(max_)
478 obj.min = float8_e4m3fn(-max_)
479 obj.nexp = 4
480 obj.nmant = 3
481 obj.iexp = obj.nexp
482 obj.maxexp = 9
483 obj.minexp = -6
484 obj.precision = 1
485 obj.resolution = float8_e4m3fn(resolution)
486 # pylint: disable=protected-access
487 obj._machar = _Float8E4m3fnMachArLike()
488 if not hasattr(obj, "tiny"):
489 obj.tiny = float8_e4m3fn(tiny)
490 if not hasattr(obj, "smallest_normal"):
491 obj.smallest_normal = obj._machar.smallest_normal
492 obj.smallest_subnormal = obj._machar.smallest_subnormal
494 obj._str_tiny = float_to_str(tiny)
495 obj._str_smallest_normal = float_to_str(tiny)
496 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
497 obj._str_max = float_to_str(max_)
498 obj._str_epsneg = float_to_str(epsneg)
499 obj._str_eps = float_to_str(eps)
500 obj._str_resolution = float_to_str(resolution)
501 # pylint: enable=protected-access
502 return obj
504 @staticmethod
505 def _float8_e4m3fnuz_finfo():
506 def float_to_str(f):
507 return "%6.2e" % float(f)
509 tiny = float.fromhex("0x1p-7")
510 resolution = 0.1
511 eps = float.fromhex("0x1p-3")
512 epsneg = float.fromhex("0x1p-4")
513 max_ = float.fromhex("0x1.Ep7")
515 obj = object.__new__(np.finfo)
516 obj.dtype = _float8_e4m3fnuz_dtype
517 obj.bits = 8
518 obj.eps = float8_e4m3fnuz(eps)
519 obj.epsneg = float8_e4m3fnuz(epsneg)
520 obj.machep = -3
521 obj.negep = -4
522 obj.max = float8_e4m3fnuz(max_)
523 obj.min = float8_e4m3fnuz(-max_)
524 obj.nexp = 4
525 obj.nmant = 3
526 obj.iexp = obj.nexp
527 obj.maxexp = 8
528 obj.minexp = -7
529 obj.precision = 1
530 obj.resolution = float8_e4m3fnuz(resolution)
531 # pylint: disable=protected-access
532 obj._machar = _Float8E4m3fnuzMachArLike()
533 if not hasattr(obj, "tiny"):
534 obj.tiny = float8_e4m3fnuz(tiny)
535 if not hasattr(obj, "smallest_normal"):
536 obj.smallest_normal = obj._machar.smallest_normal
537 obj.smallest_subnormal = obj._machar.smallest_subnormal
539 obj._str_tiny = float_to_str(tiny)
540 obj._str_smallest_normal = float_to_str(tiny)
541 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
542 obj._str_max = float_to_str(max_)
543 obj._str_epsneg = float_to_str(epsneg)
544 obj._str_eps = float_to_str(eps)
545 obj._str_resolution = float_to_str(resolution)
546 # pylint: enable=protected-access
547 return obj
549 @staticmethod
550 def _float8_e5m2_finfo():
551 def float_to_str(f):
552 return "%6.2e" % float(f)
554 tiny = float.fromhex("0x1p-14")
555 resolution = 0.1
556 eps = float.fromhex("0x1p-2")
557 epsneg = float.fromhex("0x1p-3")
558 max_ = float.fromhex("0x1.Cp15")
560 obj = object.__new__(np.finfo)
561 obj.dtype = _float8_e5m2_dtype
562 obj.bits = 8
563 obj.eps = float8_e5m2(eps)
564 obj.epsneg = float8_e5m2(epsneg)
565 obj.machep = -2
566 obj.negep = -3
567 obj.max = float8_e5m2(max_)
568 obj.min = float8_e5m2(-max_)
569 obj.nexp = 5
570 obj.nmant = 2
571 obj.iexp = obj.nexp
572 obj.maxexp = 16
573 obj.minexp = -14
574 obj.precision = 1
575 obj.resolution = float8_e5m2(resolution)
576 # pylint: disable=protected-access
577 obj._machar = _Float8E5m2MachArLike()
578 if not hasattr(obj, "tiny"):
579 obj.tiny = float8_e5m2(tiny)
580 if not hasattr(obj, "smallest_normal"):
581 obj.smallest_normal = obj._machar.smallest_normal
582 obj.smallest_subnormal = obj._machar.smallest_subnormal
584 obj._str_tiny = float_to_str(tiny)
585 obj._str_smallest_normal = float_to_str(tiny)
586 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
587 obj._str_max = float_to_str(max_)
588 obj._str_epsneg = float_to_str(epsneg)
589 obj._str_eps = float_to_str(eps)
590 obj._str_resolution = float_to_str(resolution)
591 # pylint: enable=protected-access
592 return obj
594 @staticmethod
595 def _float8_e5m2fnuz_finfo():
596 def float_to_str(f):
597 return "%6.2e" % float(f)
599 tiny = float.fromhex("0x1p-15")
600 resolution = 0.1
601 eps = float.fromhex("0x1p-2")
602 epsneg = float.fromhex("0x1p-3")
603 max_ = float.fromhex("0x1.Cp15")
605 obj = object.__new__(np.finfo)
606 obj.dtype = _float8_e5m2fnuz_dtype
607 obj.bits = 8
608 obj.eps = float8_e5m2fnuz(eps)
609 obj.epsneg = float8_e5m2fnuz(epsneg)
610 obj.machep = -2
611 obj.negep = -3
612 obj.max = float8_e5m2fnuz(max_)
613 obj.min = float8_e5m2fnuz(-max_)
614 obj.nexp = 5
615 obj.nmant = 2
616 obj.iexp = obj.nexp
617 obj.maxexp = 16
618 obj.minexp = -15
619 obj.precision = 1
620 obj.resolution = float8_e5m2fnuz(resolution)
621 # pylint: disable=protected-access
622 obj._machar = _Float8E5m2fnuzMachArLike()
623 if not hasattr(obj, "tiny"):
624 obj.tiny = float8_e5m2fnuz(tiny)
625 if not hasattr(obj, "smallest_normal"):
626 obj.smallest_normal = obj._machar.smallest_normal
627 obj.smallest_subnormal = obj._machar.smallest_subnormal
629 obj._str_tiny = float_to_str(tiny)
630 obj._str_smallest_normal = float_to_str(tiny)
631 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
632 obj._str_max = float_to_str(max_)
633 obj._str_epsneg = float_to_str(epsneg)
634 obj._str_eps = float_to_str(eps)
635 obj._str_resolution = float_to_str(resolution)
636 # pylint: enable=protected-access
637 return obj
639 @staticmethod
640 def _float8_e8m0fnu_finfo():
641 def float_to_str(f):
642 return "%6.2e" % float(f)
644 tiny = float.fromhex("0x1p-127")
645 resolution = 0.1
646 eps = float.fromhex("0x1p+0")
647 epsneg = float.fromhex("0x1p-1")
648 max_ = float.fromhex("0x1p+127")
650 obj = object.__new__(np.finfo)
651 obj.dtype = _float8_e8m0fnu_dtype
652 obj.bits = 8
653 obj.eps = float8_e8m0fnu(eps)
654 obj.epsneg = float8_e8m0fnu(epsneg)
655 obj.machep = 0
656 obj.negep = -1
657 obj.max = float8_e8m0fnu(max_)
658 obj.min = float8_e8m0fnu(tiny)
659 obj.nexp = 8
660 obj.nmant = 0
661 obj.iexp = obj.nexp
662 obj.maxexp = 128
663 obj.minexp = -127
664 obj.precision = 1
665 obj.resolution = float8_e8m0fnu(resolution)
666 # pylint: disable=protected-access
667 obj._machar = _Float8E8m0fnuMachArLike()
668 if not hasattr(obj, "tiny"):
669 obj.tiny = float8_e8m0fnu(tiny)
670 if not hasattr(obj, "smallest_normal"):
671 obj.smallest_normal = obj._machar.smallest_normal
672 obj.smallest_subnormal = obj._machar.smallest_subnormal
674 obj._str_tiny = float_to_str(tiny)
675 obj._str_smallest_normal = float_to_str(tiny)
676 obj._str_smallest_subnormal = float_to_str(obj.smallest_subnormal)
677 obj._str_max = float_to_str(max_)
678 obj._str_epsneg = float_to_str(epsneg)
679 obj._str_eps = float_to_str(eps)
680 obj._str_resolution = float_to_str(resolution)
681 # pylint: enable=protected-access
682 return obj
684 _finfo_type_map = {
685 _bfloat16_dtype: _bfloat16_finfo,
686 _float4_e2m1fn_dtype: _float4_e2m1fn_finfo,
687 _float6_e2m3fn_dtype: _float6_e2m3fn_finfo,
688 _float6_e3m2fn_dtype: _float6_e3m2fn_finfo,
689 _float8_e3m4_dtype: _float8_e3m4_finfo,
690 _float8_e4m3_dtype: _float8_e4m3_finfo,
691 _float8_e4m3fn_dtype: _float8_e4m3fn_finfo,
692 _float8_e4m3fnuz_dtype: _float8_e4m3fnuz_finfo,
693 _float8_e4m3b11fnuz_dtype: _float8_e4m3b11fnuz_finfo,
694 _float8_e5m2_dtype: _float8_e5m2_finfo,
695 _float8_e5m2fnuz_dtype: _float8_e5m2fnuz_finfo,
696 _float8_e8m0fnu_dtype: _float8_e8m0fnu_finfo,
697 }
698 _finfo_name_map = {t.name: t for t in _finfo_type_map}
699 _finfo_cache = {
700 t: init_fn.__func__() # pytype: disable=attribute-error
701 for t, init_fn in _finfo_type_map.items()
702 }
704 def __new__(cls, dtype):
705 if isinstance(dtype, str):
706 key = cls._finfo_name_map.get(dtype)
707 elif isinstance(dtype, np.dtype):
708 key = dtype
709 else:
710 key = np.dtype(dtype)
711 i = cls._finfo_cache.get(key)
712 if i is not None:
713 return i
714 return super().__new__(cls, dtype)