0

I find myself using the Java function Math.ulp() from time
to time. It has an implementation based on unpacking
a float number, and doing some bit shuffling. How would one

bootstrap ulp() from ISO core standard arithmetic
functions only in Prolog? Here are some test cases:

?- X is -pi, 'Math':ulp(X, Y).
X = -3.141592653589793, Y = 4.440892098500626E-16.

?- 'Math':ulp(1.0E10, X).
X = 1.9073486328125E-6.

Edit 28.10.2022:
I was able to bootstrap the function in SWI-Prolog, as follows,
agrees on the two examples, for positive floating point values only:

ulp(X, Y) :- Y is nexttoward(X, 1.7976931348623157E+308) - X.

?- X is pi, ulp(X, Y).
X = 3.141592653589793,
Y = 4.440892098500626e-16.

?- ulp(1.0E10, X).
X = 1.9073486328125e-6.

But many Prolog systems don't have nexttoward/2.
So I am again left with a bootstrapping problem.

Rúben Dias
  • 336
  • 2
  • 9
  • Where are you running this ulp/2 procedure ?. My gprolog instance does not have it. – gusbro Oct 28 '22 at 18:30
  • I just call Java Math.upl() from within a Java Prolog. – Rúben Dias Oct 28 '22 at 18:30
  • Then you probably just have to derive the actual scale used for the number provided. Check on any IEEE floating point resources. Once you have the scale and the number of bits for the mantissa you can compute the ulp – gusbro Oct 28 '22 at 18:46
  • A solution for nexttoward/2, how to implement it when its not there, in any ISO core standard Prolog or maybe with some minor extras, would be also fine. – Rúben Dias Oct 28 '22 at 19:27

1 Answers1

0

After having a look at this code:
https://github.com/jcoreio/ulp/blob/master/lib/index.js

I tried this Prolog realization, for positive floating point values only:

nextup(X, R) :- 
    Y is X*(1+epsilon),
    C is (X+Y)/2,
    (X < C, C < Y -> R=C; R=Y).

ulp2(X, Y) :- nextup(X, H), Y is H - X.

Seems to be ok:

?- between(1, 1000000, N), X is float(N+2^52), ulp(X,A), ulp2(X,B), A=\=B.
false.
Rúben Dias
  • 336
  • 2
  • 9