5

I was looking through the SICStus manual's syntax description and there is a definition of "float". However, there is no indication of what the implementation of "float" actually is. IEEE single or double precision? Maybe even a BigDecimal?

In SWI Prolog (or at least SWISH), the "float" seems to be IEEE double precision, as can be determined via:

planck_float(P) :-
   planck_float_descent(1.0,P).

planck_float_descent(X,P) :-
   Xhalf is X / 2.0, Xtest is 1.0 + Xhalf, Xtest =\= 1.0, !,
   write(Xhalf),writeln(Xtest),
   planck_float_descent(Xhalf,P).
planck_float_descent(P,P) :-
   Xhalf is P / 2.0, Xtest is 1.0 + Xhalf, Xtest == 1.0,
   writeln(P).

?- planck_float(P).
P = 2.220446049250313e-16

2.22e-16 being the last value that, added to 1.0 still yields something larger than 1.0 sounds about right for IEEE 64-bit floating point arithmetic.

What implementation do other Prologs have?

Update many years later

Better code:

efloat(C,E) :- 
   Cf is 1.0 * C, float(Cf), 
   erecur(Cf,1.0,E).
erecur(C,X,E) :- 
   Xhalf is X / 2.0, 
   Xtest is C + Xhalf, Xtest \= C, !,
   format("~e/2.0 = ~20f\n",[Xhalf,Xtest]),
   erecur(C,Xhalf,E).
erecur(C,X,X) :-
   Xhalf is X / 2.0, 
   Xtest is C + Xhalf,
   Xtest = C, 
   format("~e",[X]).

Then:

?- efloat(1,X). 
X = 2.220446049250313e-16.
David Tonhofer
  • 14,559
  • 5
  • 55
  • 51
  • 2
    Does [SICStus Prolog Arithmetic](https://sicstus.sics.se/sicstus/docs/3.12.8/html/sicstus/Arithmetic.html) answer the question? It states that the *float* is the same as a *C double*, which means it's [Double-precision floating-point format](http://en.wikipedia.org/wiki/Double-precision_floating-point_format). It also explicitly states the range of values. – lurker Dec 26 '14 at 01:25
  • 2
    SWI Prolog also declares that it uses [C-type double](http://www.swi-prolog.org/pldoc/man?section=arith). Good enough for me for now -- although this kicks the can down the road. I have been told about the utility of being 'compliant to ISO Prolog'. Well, they should have specified "a correctly implemented IEEE 754 (and no messing) underlies Prolog floating point operations". Java [specifies this in detail](http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.2.3) (but then [still gets it wrong](http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf), if I understand well). Oh well. – David Tonhofer Dec 26 '14 at 13:15
  • Yeah, not sure which is worse: specifying and violating, or not specifying at all. And even worse: not documenting what is actually done for a specific implementation, in either case. – lurker Dec 26 '14 at 13:43
  • @lurker: SICStus specifies everything, and conforms. – false Dec 27 '14 at 00:29
  • @false, indeed, my intention wasn't to imply a fault with SICStus, but to agree with the OP regarding lack of such consistency across the various languages and implementations. – lurker Dec 27 '14 at 01:58
  • 1
    @DavidTonhofer: Thank you for this excellent reference. Do you know if there is some follow-up to it? After all, it was last modified 2004. – false Dec 30 '14 at 00:09
  • 1
    @false Hi, sorry for the late reply. I do not know of any direct followup. The [home page of Prof. Kahan](http://www.cs.berkeley.edu/~wkahan/) lists quite a few papers ... but this is not really my speciality. He's [still active and angry](http://www.cs.berkeley.edu/~wkahan/Hdlbrg2.pdf) though. Maybe drop him a mail? If nothing else, one of the research team can point you to something. Regards. – David Tonhofer Jan 01 '15 at 18:02
  • 1
    @DavidTonhofer: I am reading through his home page and try to figure out what it all means. What disturbes me most is that 1mo there does not seem to be a single programming language to his liking, 2do the "condemnation" of reproducibility on page 3 of How Java hurts – false Jan 01 '15 at 19:46
  • @DavidTonhofer: In any case: Happy new year! – false Jan 01 '15 at 19:52
  • @false Thanks. To you too! Yes there is tons of cleanup work to do in proglangs yet; we are still medieval everywhere. He means (p. 16): _"Linguistically legislated exact reproducibility is unenforceable"_, i.e. You ain't gonna get it due to market pressures. The effect of demanding it: _"When Exact Reproducibility of floating-point becomes too burdensome to implementors whose first priority is high speed, they will jettison Exact Reproducibility and, for lack of sound guidance, they will most likely abandon Predictability along with it. That’s what Gosling’s Loose Numerics amounts to..."_ – David Tonhofer Jan 01 '15 at 20:08

3 Answers3

7

The documentation of SICStus 4.3.1 reads:

The range of floats is the one provided by the C double type, typically [4.9e-324, 1.8e+308] (plus or minus). In case of overflow or division by zero, an evaluation error exception will be raised. Floats are represented by 64 bits and they conform to the IEEE 754 standard.

Together with the declaration of ISO conformance, this does not leave anything open. Note that "the IEEE 754 standard" alone without any further qualification does not say much, as it might mean minifloats, decimals, and various modes. Also, exception handling vs continuation values and other recommendations make things much more complex and by no means easy.

The ISO Prolog standard requires to produce Prolog-exceptions ("traps" in IEEE parlance) in all cases. There is no provision of continuation values like NaN, +∞ and the like. At first cursory sight this suggests that those values are entirely incompatible to ISO Prolog. However, subclause 5.5 defines the possible extensions to the standard. There is in particular the following subclause which permits the introduction of continuation values.

5.5.10 Evaluable functors

A processor may support one or more additional evaluable
functors (9) as an implementation specific feature. A
processor may support the value of an expression being a
value of an additional type instead of an exceptional value.

NOTE - A program that makes no use of extensions should
not rely on catching errors from procedures that evaluate their
arguments (such as is/2, 8.6.1) unless it is executed in strictly
conforming mode (5.1 e).

This note reveals the intention behind: In strictly conforming mode all those extensions are absent and only Prolog-exceptions are signaled. How precisely an extension should look like is by far not clear. The proposal by @jschimpf contains some interesting points, but it does not take into account the intention of William Kahan's documents. In particular, IEEE-exception-flags are missing completely (or a corresponding better scoped functionality), which renders NaNs next to useless. The other two proper algebraic completions are not there. (Further, that proposal dates from 2009 and has not taken into account Cor.2:2012.)

ISO Prolog does only provide a framework for floating points (see ISO/IEC 13211-1:1995 7.1.3 Floating point), both binary, decimal and even any positive even base (radix) would fit. In the 1980s, some systems (e.g., C-Prolog) used to have floats with a precision a bit lower than single precision IEEE floats. In 32 bits both the Prolog tag and the float was squeezed (with a smaller mantissa), while actual computations were carried out in double precision, the good olde, no longer valid, C default. I believe that that representation fits into ISO, too. ISO Prolog requires at least 6 decimal digits. However, I am unaware of current systems using anything else than binary IEEE double precision.

Floats in ISO Prolog are based essentially on the ISO LIA standards ("language independent arithmetics") ISO/IEC 10967-1:1995, which in the meantime has been replaced by ISO/IEC 10967-1:2012 which is compatible with ISO/IEC/IEEE 60559:2011, vulgo IEEE 754-2008.

Note that IEEE and LIA serve different purposes: IEEE is about floats and only a few functions, whereas LIA includes more functions, integer arithmetics and complex numbers, too.

To give you an idea, how floating point operations are currently implemented in various Prolog systems, consider the goal

X is 0** -1, write_canonical(X).

which should produce an evaluation_error(undefined). Three systems conform (IF, SICStus, Prolog IV), and the other systems are all different except for two.

0, (+inf), Infinity.0, inf.0, 0.Inf, inf, inf

is produced respectively by

SWI, YAP, Minerva, XSB, Ciao, B, GNU

As all those outputs constitute valid Prolog text (some need an infix .), they are all invalid extensions since they redefine the meaning of existing Prolog syntax.

false
  • 10,264
  • 13
  • 101
  • 209
  • 1
    Long story short: ISO Prolog and IEEE 754 have conflicting requirements. You can find some discussions of the issues at http://eclipseclp.org/Specs/core_update_float.html – jschimpf Dec 28 '14 at 11:30
  • @jschimpf: Can you give one example how they conflict? – false Dec 28 '14 at 12:28
  • 1
    @false Thumbs up for that detailed answer. You seem to actually be working on at least one Prolog implementation. Now, when saying "Together with the declaration of ISO conformance, this does not leave anything open" you imply that 100% of the specification comes via ISO Prolog conformance, because evidently the SICStus text leaves practically everything open (and restricts itself to 64 bit floats, too). Plus the text uses ` typically`. – David Tonhofer Dec 28 '14 at 17:00
  • @DavidTonhofer: I am still reading your link (in between festivities) about how Java supposedly hurts everyone. One point is for sure: in ISO-Prolog `C is (F-32)*(5/9).` is essentially the same as `C is (F-32)*5/9.` - safe for the latter could overflow on a `bounded` `integer`. – false Dec 28 '14 at 17:25
  • 2
    @DavidTonhofer: As for SICStus, the current manual comes from [Quintus](https://quintus.sics.se/isl/quintus/html/quintus/ref-ari-ove.html#ref-ari-ove) which was merged with SICStus at [4.0](https://sicstus.sics.se/sicstus/docs/4.0.0/html/sicstus/ref_002dari_002dove.html#ref_002dari_002dove). But it seems this formulation survived from [3.12](https://sicstus.sics.se/sicstus/docs/3.12.11/html/sicstus/Arithmetic.html#Arithmetic). It sounds to me a bit like: should your platform support a different `double` type, we will not emulate IEEE, but simply stick to what we get there. – false Dec 28 '14 at 17:48
  • 2
    @DavidTonhofer: Have you looked at [unums](http://en.wikipedia.org/wiki/Unum_%28number_format%29) recently? – false May 27 '15 at 11:30
  • Thanks @false This is interesting indeed. Hopefully someone will do the unum hardware. – David Tonhofer Jun 06 '15 at 16:02
  • @DavidTonhofer: Given all the claims about their algebraic properties, I would be happy with a C-lib already. – false Jun 06 '15 at 18:48
1

What you call planck_float is usually called epsilon. Many Prolog systems have a constant for this value, so that it doesn't need to be calculated.

The constant was suggested in N208:

9.7.3.1 Description epsilon evaluates to the
distance from 1.0 to the next largest floating point
number, an implementation defined value.
https://www.complang.tuwien.ac.at/ulrich/iso-prolog/N208

Many Prolog systems support this constant which can tell you what the default float type means. For example GNU Prolog gives me:

GNU Prolog 1.4.5 (64 bits)
| ?- X is epsilon.
X = 2.2204460492503131e-016

This doesn't mean that a Prolog system only might have one float data type. It is also possible that a Prolog system supports multiple float types. For example in Jekejeke Prolog it is possible to use 32-bit floats denoted by the prefix 0f:

Jekejeke Prolog 3, Runtime Library 1.3.6
?- X is epsilon.
X = 2.220446049250313E-16
?- X is epsilon32.
X = 0f1.1920929E-7
1

Actually there is more to say about floats in Prolog. According to ISO core standard, section 7.1.3 Floating Point, different radix are allowed for internal representation.

So a Prolog system could use radix=2 or radix=10. There is only one constraint, the Prolog system should allow at least 6 digits of precision. In secton 7.1.3 Floating Point we find:

r^p-1 >= 10^6

r is the radix and p is the width of the mantissa. There are other constraints in the same section. The notions integer part and float part of a number (not to be confused with the functions)

do not refer to this section. They refer to the external decimal representation in 6.1.2 Abstract term Syntax of the ISO core standard which fixes the radix to 10.

  • `float_integer_part/1` and `float_fractional_part/1` nether refer to "the external decimal representation" nor do they depend on the concrete radix. – false Feb 15 '20 at 14:15
  • `float_integer/fractional_part/1` are defined in 9.1.1 as intpartP, fractpartP which in turn are defined in 9.1.4 as intpartF(x) = signF(x) * ⌊|x|⌋ and fractpartF(x) = x - intpartF(x). Thus there is no reference to 6.1 whatsoever. – false Feb 15 '20 at 17:26
  • They are different: `float_integer_part/1` is F→F whereas `truncate/1` is F→I∪{`int_overflow`}. – false Feb 15 '20 at 17:31
  • Pretty all systems conform here, including ECLiPSe -L iso – false Feb 15 '20 at 17:36
  • But anyway, my edited answer doesn't refer to these things. I only wanted to make clear that 6.1.2 doesn't deliver much information about the internals of floats, its rather 7.1.3. And the good news there is a notion of radix. –  Feb 15 '20 at 17:36
  • My system and ECLiPSe Prolog (withoiut -L iso) option, are a little inconsistent in the handling of the float semantics (floor(6) gives integer, but floor(6.0) gives float). While working on interval arithmetic, might improve on this. –  Feb 15 '20 at 17:58
  • Also floor : I -> I or floor : I -> F is missing in the ISO standard. There are some gaps, which most Prolog systems close. –  Feb 15 '20 at 18:02