?- pack_install(clpBNR,[url('https://github.com/ridgeworks/clpBNR.git')]).
% Cloning into '/Users/rworkman/.local/share/swi-prolog/pack/clpBNR'...
Verify package status (anonymously)
at "https://www.swi-prolog.org/pack/query" Y/n?
% Contacting server at https://www.swi-prolog.org/pack/query ... ok
But then I get on my Windows 10 machine with SWI-Prolog 8.5.4:
?- pack_install(clpBNR,[url('https://github.com/ridgeworks/clpBNR.git')]).
Create directory for packages
(1) * c:/users/foobar/appdata/local/swi-prolog/pack
(2) c:/programdata/swi-prolog/pack
(3) Cancel
Your choice?
% Cloning into 'c:/users/foobar/appdata/local/swi-prolog/pack/clpBNR'...
Verify package status (anonymously)
at "https://www.swi-prolog.org/pack/query" Y/n?
% Contacting server at https://www.swi-prolog.org/pack/query ...
ERROR: http_reply `'https://www.swi-prolog.org/pack/query'' does not exist
I don’t know much about clpBNR internals. Java delivers a
function ulp(), which can be turned into a Prolog evaluable
function ulp/1 and then gives me:
?- X is 2.3.
X = 2.3.
?- X is 2.3+ulp(2.3).
X = 2.3000000000000003.
?- X is 2.3-ulp(2.3).
X = 2.2999999999999994.
Didn’t check yet cos/1 evaluable function, either in ECLiPSe Prolog nor
clpBNR, whether ulp/1 can be used to simulate their interval calculation, by
simply adding a boundary via the ulp/1 evaluable function,
which then would give me an easy explanation. The static method ulp() is
from the Java class Math. I don’t find this function in SWI-Prolog.
Edit 22.03.2022:
The evaluable function ulp/1 seems to be also able to simulate your
fuzzing for integral floats. I get in SWI-Prolog:
Yes, clpBNR just uses the Prolog arithmetic function nexttoward/2 for this purpose, so
?- Y is nexttoward(2.3,inf).
Y = 2.3000000000000003.
?- Z is nexttoward(2.3,-inf).
Z = 2.2999999999999994.
is the right answer (fix required for {X==2.3}).
There is no ulp function in SWIP but you could build one with nexttoward.
There’s also bounded_number/3; one of its modes will generate the lower and upper bound guaranteed to contain a floating point value:
?- bounded_number(L,H,2.3).
L = 2.2999999999999994,
H = 2.3000000000000003.
?- bounded_number(L,H,1000.0).
L = 999.9999999999999,
H = 1000.0000000000001.
?- set_prolog_flag(float_overflow, infinity).
true.
?- X is inf, Y is nexttoward(1000,X).
X = 1.0Inf,
Y = 1000.0000000000001.
In this case it might be better if this flag is not required. Using the default flag, any Inf being the result of evaluating a (sub)expression causes a float overflow. Only the inf/0 function is hacked to avoid that.