Proper handling of denormal floats in ISO-Prolog

193 views Asked by At

Denormal floats are something special:

floating point number classification and representation

What does the ISO-Prolog standard say on how these should be handled?

It is clear to me that raising a evaluation_error(underflow) exception whenever these denormals occur is a proper way of dealing with them, but this incurs additional costs—each float produced must be checked.

But what about the "flush denormals to zero" (FTZ) and "treat denormals as zero" (DAZ) operating modes that many processors offer? Can Prolog implementations use these, and, if so, how do they do that properly?

Does (1) documenting the use of these operating modes, (2) ensuring that denormals are flushed to zero of the same sign (FTZ), and (3) ensuring that denormals are treated as zero of the same sign (DAZ) suffice? Help please!

3

There are 3 answers

0
false On BEST ANSWER

Don't skip them. Yet, short answer from ISO/IEC 13211-1:1995 9.1.4.2 Floating point result function:

It shall be implementation defined whether a processor
chooses round(x) or underflow when 0 < |x| < fminN.

But first, let's call them subnormals. The obsolete (at least according to LIA 1:2012) notion denormal was (in retrospect) not very helpful as it suggested some de-viant, de-structive properties. And no: they are not special as you suggest. To see this, consider the number line of real numbers. Numbers that can be represented exactly are marked and get closer and closer to each other when approaching zero (from both sides). Subnormal are those that are closest to zero. The distance between them and zero is the same as the distance between the smallest normal numbers. That's their anomaly (or denormaly so to speak). If you remove now those subnormals you get a gigantic gap that causes even more numerical anomalies. It's like you scratch away on a ruler the markings next to zero and then use this broken ruler for measuring1. So in absence of subnormals the remaining numbers are not normal as one might believe but rather abnormal, prone to even more errors.

If you do not like to read Kahan on the subject which I nevertheless suggest, may I refer you to Gustafson's The end of error which explains subnormals much better than I do.

In 13211-1 there is the possibility to exclude subnormals but this is just for compatibility with very RISCy, outdated architectures.

So much for formal conformity. In the long term some Unum-style, CLP(BNR)-esque, Prolog IV-ish approach might be promising.


 1) That is, if you are rounding to zero. In case you produce exceptions/continuation values instead better numerical properties will hold as long as such exceptions do not occur.

0
jschimpf On

In section 7.1.3 the ISO-Prolog standard defines the set F as the set of numbers that your chosen floating-point format can represent. This set may or may not include denormalized values, both choices are allowed.

When a computation result is (absolutely) greater than zero and smaller than the smallest normalized value, you have the choice between

  • rounding to a value representable in F
  • raising an underflow exception

According to section 9.1.4.2, this choice is implementation defined, i.e. you have to document it.

0
AudioBubble On

This is a little test case to see whether your Prolog system can return subnormals as result of arithmetic (no flush-to-zero, ~FTZ):

/* SWI-Prolog */
?- X is 2.2250738585072011e-308 - 2.2250738585072012e-308.
X = -5.0e-324.
/* Jekejeke Prolog */
?- X is 2.2250738585072011e-308 - 2.2250738585072012e-308.
X = -4.9E-324

And this is a new addition in APIs, not the same across Prolog systems, showing argument passing of subnormals (no denormals-are-zero, ~DAZ):

/* SWI-Prolog */
?- X is 2.2250738585072011e-308 - 2.2250738585072012e-308, 
float_parts(X,M,B,E).
X = -5.0e-324,
M = -0.5,
B = 2,
E = -1073.
/* Jekejeke Prolog */
?- X is 2.2250738585072011e-308 - 2.2250738585072012e-308, 
sys_float_mantissa(X,M), sys_float_exponent(X,E), sys_float_radix(X,R).
X = -4.9E-324,
M = -1,
E = -1074,
R = 2

The result is from MacBook Air 2019.