@@ -236,9 +236,9 @@ def checkValue(cls, value: Union[int, Iterable[int]], ctxt: Optional[_NetworkCon
236
236
237
237
238
238
class FloatImmediate (Immediate [Union [float , Iterable [float ]], _ImmediateType ]):
239
- typeFraction : int #: int: Represents the number of bits reserved for the fraction part
240
- typeExponent : int #: int: Represents the number of bits reserved for the exponent part
241
- signed : bool #: bool : Represents whether the underlying float is signed or unsigned (should be removed)
239
+ # FIXME: check typeFraction vs typeMantissa
240
+ typeFraction : int #: int: Represents the number of bits reserved for the fraction part
241
+ typeExponent : int #: int : Represents the number of bits reserved for the exponent part
242
242
243
243
@_classproperty
244
244
def typeExponentMax (cls ) -> int :
@@ -250,7 +250,6 @@ def typeExponentOffset(cls) -> int:
250
250
# The offset added to the exponent
251
251
return 2 ** (cls .typeExponent - 1 ) - 1
252
252
253
- # ADEQUINO: This is a ugly workaround for FP, works for bfloat16 and fp32 because bfloat16 is a truncated fp32
254
253
@classmethod
255
254
def partialOrderUpcast (cls , otherCls : Type [Immediate ]) -> bool :
256
255
if issubclass (otherCls , FloatImmediate ):
@@ -277,92 +276,29 @@ def checkValue(cls, value: Union[float, Iterable[float]], ctxt: Optional[_Networ
277
276
else :
278
277
raise Exception ("Immediate type not recognized." )
279
278
279
+ # The exponent bias for FP64 is 2**(11-1)-1 as the exponent has 11 bits.
280
+ DOUBLE_MIN_EXP = - 1023
281
+
280
282
for val in _val_list :
281
- # Zero (and subnormals, not implemented) are special cases
282
- if (val == 0 ):
283
+
284
+ # Extract mantissa, exponent, and sign.
285
+ # Also bring mantissa and exponent to IEEE754 compliant form for non-denormals.
286
+ mantissa , exponent = math .frexp (val )
287
+ sign = True if mantissa < 0 else False
288
+ mantissa = - mantissa * 2 if sign else mantissa * 2
289
+ exponent -= 1
290
+
291
+ # Check if the number is finite, nonzero and not denormal, otherwise skip the check.
292
+ if not (math .isfinite (val ) and val != 0 and exponent > DOUBLE_MIN_EXP ):
283
293
continue
284
- # Make the value positive
285
- if (val < 0 ):
286
- val = val * - 1
287
-
288
- # Separate Integer and Fraction of immediate
289
- fraction , integer = math .modf (val )
290
-
291
- # Binarylist for the mantissa
292
- binarylist = []
293
- f = fraction
294
-
295
- # Fraction binarization, fails if nbits required > n bits mantissa.
296
- # If integer part of immediate is 0, we start counting mantissa bits after we find the first 1 bit.
297
- if (int (integer ) > 0 ):
298
- for i in range (cls .typeFraction ):
299
- f = f * 2
300
- f , fint = math .modf (f )
301
- binarylist .append (str (int (fint )))
302
- if f == 0 :
303
- break
304
- elif i == (cls .typeFraction - 1 ):
305
- return False
306
- else :
307
- flag = 0
308
- count = cls .typeFraction + 1
309
- while (count ):
310
- f = f * 2
311
- f , fint = math .modf (f )
312
- binarylist .append (str (int (fint )))
313
- if int (fint ) == 1 and flag == 0 :
314
- flag = 1
315
- if f == 0 :
316
- break
317
- if flag == 1 :
318
- count = count - 1
319
- if (count == 0 ):
320
- return False
321
-
322
- # Float exponent part
323
- # It's equal to the length of the integer part minus 1, if the integer part is not zero.
324
- # Otherwise, it's minus the number of 0 bits before the first 1 bit in the fraction representation + 1
325
- exponent = 0
326
- if (int (bin (int (integer ))[2 :]) == 0 ):
327
- for b in binarylist :
328
- exponent = exponent - 1
329
- if b == '1' :
330
- break
331
- else :
332
- exponent = len (str (bin (int (integer ))[2 :])) - 1
333
-
334
- # Check if exponent is representable in n_exponent bits
335
- true_exponent = int (bin (cls .typeExponentOffset + exponent )[2 :])
294
+
295
+ # Check if exponent is representable.
336
296
if (cls .typeExponentOffset + exponent ) > cls .typeExponentMax or (cls .typeExponentOffset + exponent ) < 0 :
337
297
return False
338
-
339
- # Append bits to head of mantissa, if integer part is not in scientific notion
340
- binarylist2 = []
341
- if len (str (bin (int (integer ))[2 :])) > 1 :
342
- for digit in str (bin (int (integer ))[3 :]):
343
- binarylist2 .append ((digit ))
344
-
345
- # If integer part is zero, trim the mantissa bits that have been used to calculate the exponent part
346
- if (int (integer ) > 0 ):
347
- finalbinaryfraction = binarylist2 + binarylist
348
- else :
349
- finalbinaryfraction = binarylist
350
- while (finalbinaryfraction [0 ] == '0' ):
351
- finalbinaryfraction .pop (0 )
352
- finalbinaryfraction .pop (0 )
353
-
354
- # Fix mantissa size
355
- if ((cls .typeFraction - len (finalbinaryfraction )) > 0 ):
356
- finalbinaryfraction += ['0' ] * (cls .typeFraction - len (finalbinaryfraction ))
357
- if (len (finalbinaryfraction ) > cls .typeFraction ):
358
- finalbinaryfraction = finalbinaryfraction [:cls .typeFraction ]
359
-
360
- # Check if the value in binary float represent the immediate value
361
- exponent_part = 2 ** exponent
362
- mantissa_part = 1
363
- for (i , m ) in enumerate (finalbinaryfraction ):
364
- mantissa_part = mantissa_part + 2 ** (- (i + 1 )) * int (m )
365
- if (exponent_part * mantissa_part != val ):
298
+
299
+ # Check if mantissa is representable. Implicit assumption is that cls.typeFraction < 52 (like in FP64)
300
+ truncated_mantissa = 1 + math .floor ((2 ** cls .typeFraction ) * (mantissa - 1 )) / (2 ** cls .typeFraction )
301
+ if math .fabs (truncated_mantissa - mantissa ) > 0.0 :
366
302
return False
367
303
368
304
return True
0 commit comments