ciao-lang / ciao

Ciao is a modern Prolog implementation that builds up from a logic-based simple kernel designed to be portable, extensible, and modular.
https://ciao-lang.org
GNU Lesser General Public License v3.0
272 stars 21 forks source link

Missing or wrong rounding in (**)/2 #75

Closed Jean-Luc-Picard-2021 closed 2 years ago

Jean-Luc-Picard-2021 commented 2 years ago

Looks like some rounding is missing in (**)/2. I get this result (tested in Ciao Playground):

/* Ciao Playground 1.21.0 */
?- Z is 51**10.
Z = 119042423827613000.0 ? 

But I guess HALF_EVEN would give this result:

/* ECLiPSe Prolog 7.0.61 */
?- X is 51**10.
X = 1.1904242382761301e+17
jfmc commented 2 years ago

Same on a non-WASM target:

?-  Z is 51**10.
Z = 119042423827613010.0 ? 

Maybe this is a WASM or emscripten issue?

Jean-Luc-Picard-2021 commented 2 years ago

Typo "Samo on" --> "Different on". I don't know whether its a printing problem of WASM. Didn't investigate any further. But ECLiPSe Prolog is correct:

To judge that ECLiPSe Prolog is correct, one needs to think in binary representation. We find, using a precise float to bigint conversion:

?- X is integer(1.1904242382761301E17).
X = 119042423827613008.

?- X is integer(1.19042423827613E17).
X = 119042423827612992.

Now which one is closer?

?- X is 119042423827613001-119042423827613008.
X = -7.

?- X is 119042423827613001-119042423827612992.
X = 9.

So 1.1904242382761301E17 is the correct float.

Jean-Luc-Picard-2021 commented 2 years ago

Warning, possibly this ticket can be closed. Its not necessarily a display problem. For example many Math.pow(double,double) implementations cannot do the problem correctly.

They cannot or do not round to the theoretical optimum, they have inherently a higher error than only one Unit in the last place (ULP). So a certain error is to expect. You see this here:

/* Dogelog Player, JavaScript */
?- X is 51**10.
X = 1.19042423827613E17.

?- X is float(51^10).
X = 119042423827613010.0.

In the above the (**)/2 is Math.pow(double,double) and the (^)/2 is exact bigint exponentiation. I took the pair (51,10) from a list of pairs where (**)/2 and (^)/2 often disagree

based on Math.pow(double,double) typically being weak.

jfmc commented 2 years ago

Thanks. I think that this issue must be related to WASM/emscripten. The playground uses exactly the same C sources for wasm and the native targets. Ciao reports the same result as ECLIPSE when run natively and the same result as dogelog (or JS console) when run via WASM.