Again I don’t want to polute other threads. Interestingly
unums did never appear in the SWI-Prolog forum, although
Ulrich Neumerkel got interested in them in the past.
One could use a different mindset to realize CR_XXX operations
that don’t need any flags? I find an approach by the Go Programming
language which returns for its elementary operations an Accuracy:
x = 1000 (0x.fap+10, prec = 64, acc = Exact)
y = 2.718281828 (0x.adf85458248cd8p+2, prec = 53, acc = Exact)
z = 1002.718282 (0x.faadf854p+10, prec = 32, acc = Below)
https://pkg.go.dev/math/big#example-Float.Add
The above is a mixed operation, with two different argument precisions
and even a different result precision. But I guess it would also work
with setting all precisions to binary p=53. The big.Float datatype
uses a binary radix, i.e. r=2. With such an API there willl be no
need for flags and subsequently no problem with multi-threading.
You need to be able to stash the accuracy somewhere, it needs
at least 2 bits. They somehow store it in the big.Float type after
performing an operation. A little nasty, their big.Float is mutable it
seems, and not immutable as one would expect:
const (
Below Accuracy = -1
Exact Accuracy = 0
Above Accuracy = +1
)
I don’t know what Below and Above means, towards and away
from zero, or towards and away minus infinity? And what their
rounding of the operations is? It seems the rounding mode can
be also specified in the big.Float, in the value holder for an
operation. And the Accuracy is an indicator that works relative
to the exact none rounded result. I guess one can reconstruct
a little interval from it rather straight forward?
Edit 24.10.2022
Oops, possibly not relevant to clpBNR, since it uses coarse
intervals when leaving rational numbers and switching to floats,
controlled by max_rational_size_action and max_rational_size:
lower_bound_val_(real,L,IL) :- % rround outward (if float)
Lv is L, Lv\= 1.0Inf,
(rational(Lv) -> IL=Lv ; IL is nexttoward(Lv,-1.0Inf)).
upper_bound_val_(real,H,IH) :- % round outward (if float)
Hv is H, Hv\= -1.0Inf,
(rational(Hv) -> IH=Hv ; IH is nexttoward(Hv,1.0Inf)).
Anyway, with some Accuracy bits, one would need to have a database
for irrational numbers such as π refered symbolically in the code by “pi”,
so that we know whether the floating point value is above or below
the real value, and we could construct a finer interval. Are finer intervals
worth the pain? If they would come practically for “free” in the corresponding
operations, there could be maybe some benefit. The Accuracy can possibly
be reduced to one bit only, by returning always the lower interval end in
the inexact case, reducing the effort for Accuracy representation to a single
bit, the ubit and we arrive at unums. But then we loose the information
what was the preferred floating point value according to the rounding mode.