Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

A little Reminder: rdiv is a Constructor and an Operator at the same time!

238 views
Skip to first unread message

burs...@gmail.com

unread,
Jul 3, 2017, 5:14:04 PM7/3/17
to
Dear All,

If you want rational arithmetic(*), and you do the following:

?- A is 4 rdiv 1/3.
A = 1.3333333333333333.

This is anyway wrong. What you need to do is:

?- A is (4 rdiv 1) rdiv 3.
A = 4 rdiv 3.

Richard O'Keefe idea is already realized, you don't need to do anything anymore, since rdiv/2 is not only a constructor but also an operation, you can do the following, try it for yourself with SWI-Prolog:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.5.8)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- X is (1 rdiv 4) rdiv (1 rdiv 2).
X = 1 rdiv 2.

?- X is (1 rdiv 2) rdiv (1 rdiv 4).
X = 2.

So if you use rdiv/2 instead of (/)/2 you program runs rationals and not floats. I don't see any possility to merge rdiv/2 and (/)/2 into one operator, this is impossible I guess. Now putting side by side the division and the power operator, we could require:

Datatype Approach:
============
datatype division power
float: (/)/2 (^)/2
rational: (rdiv)/2 (^)/2 /* name clash */

But we run into the problem that (^)/2 for floats is not the same as (^)/2 for rationals, we would need two different operators. When I posted this feature request, I might have had this idea. Meanwhile I have abandoned the above schema in favor of another schema.

The new schema is based on different contexts and not on different datatypes, the advantage is that I don't need a (rdiv)/2 operator anymore:

Context Approach:
============
context division power
float: (/)/2 (^)/2
rational: (/)/2 (^)/2

So I must appologize, since I issued a datatype feature request, whereby in the end I implemented myself a context feature, much later after I have issued this feature request here. I implemented the context feature via my new library(groebner/generic).

The advantages of the context approach is as follows:

Typing rdiv/2 is unnatural, its very clumsy, its much easier to type (/)/2.
Programs can be easily moved from one context into anthor, we do not need to replace (/)/2 by (rdiv)/2.
The context approach is also followed by CLP(Q), in CLP(Q) we do not need to write { X = Y rdiv Z } instead we write naturally { X = Y / Z }, right?

Hope this helps!

(*)
https://github.com/SWI-Prolog/swipl-devel/issues/185

infr...@gmail.com

unread,
Jul 4, 2017, 8:34:12 AM7/4/17
to
On Tuesday, 4 July 2017 07:14:04 UTC+10, burs...@gmail.com wrote:

> ?- X is (1 rdiv 2) rdiv (1 rdiv 4).
> X = 2.
>

I've gone for this approach:

?- X is (1R // 2) // (1R // 4).
X = 2.

where the 'R' denotes a rational constructor. I don't need the rdiv operator.



burs...@gmail.com

unread,
Jul 4, 2017, 8:46:17 AM7/4/17
to
Hi,

Dissmissed. The (//)/2 is anyway out of discussion
here, since it is defined via truncate or floor. The
easiest definitions are X//Y = truncate(X/Y) and
X div Y = floor(X/Y).

You possibly want this type invariant:
X is Y//Z, integer(X).
X is Y div Z, integer(X).

BTW: There is no problem to extend the (//)/2 or (div)/2
to a larger range of arguments, check this out:

Jekejeke Prolog 2, Runtime Library 1.2.2
(c) 1985-2017, XLOG Technologies GmbH, Switzerland

/* with integer arguments */
?- X is 100//3.
X = 33

/* with float arguments */
?- X is 10.0//0.3.
X = 33

What I then would expect (but I didn't realize rational
numbers in the standard is/2 yet, i.e. the datatype
approach) is the following:

/* with rational number arguments */
?- X is (100 rdiv 10)//(3 rdiv 10)
X = 33

For SWI-Prolog we could raise a further feature request
issue, extend (//)/2 on floats and rational numbers.
So far the behaviour is as follows:

?- X is 100//3.
X = 33.

?- X is 10.0//0.3.
ERROR: Type error: `integer' expected, found `10.0' (a float)
ERROR: In:
ERROR: [8] _4258 is 10.0//0.3
ERROR: [7] <user>

?- X is (100 rdiv 10)//(3 rdiv 10).
ERROR: Type error: `integer' expected, found `3 rdiv 10' (a rational)
ERROR: In:
ERROR: [8] _6262 is 100 rdiv 10//(3 rdiv 10)
ERROR: [7] <user>

infr...@gmail.com

unread,
Jul 4, 2017, 8:59:20 AM7/4/17
to
Yes, I went the datatype approach, so:

?- X is 100R // 3.
X = 100/3

As you say, for floats too:

?- X is 10.0 // 0.3.
X = 33

burs...@gmail.com

unread,
Jul 4, 2017, 10:15:10 AM7/4/17
to
But 100/3 =\= 3, so it doesn't make much sense.
You know you want for example this identity:

X = (X // Y)*Y+(X rem Y)

Here is the extension of floats to rem, its nearly
the same as the % Operator in Java, which also
works for float:

Jekejeke Prolog 2, Runtime Library 1.2.2
(c) 1985-2017, XLOG Technologies GmbH, Switzerland

?- X is 100 rem 3.
X = 1

?- X is 10.0 rem 0.3.
X = 0.10000000000000037

Now you can check whether the law holds, we compute
the difference between X and (X // Y)*Y+(X rem Y):

?- D is 100-(100 // 3)*3-(100 rem 3).
D = 0

?- D is 10.0-(10.0 // 0.3)*0.3-(10.0 rem 0.3).
D = -7.216449660063518E-16

For floats we get nearly zero, something around eps.
What is rem/2 doing in your _R world?

(*)
"In C and C++, the remainder operator accepts only integral operands, but in the Java programming language, it also accepts floating-point operands.

The remainder operation for operands that are integers after binary numeric promotion (§5.6.2) produces a result value such that (a/b)*b+(a%b) is equal to a."
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.3

"The result of a floating-point remainder operation as computed by the % operator is not the same as that produced by the remainder operation defined by IEEE 754. The IEEE 754 remainder operation computes the remainder from a rounding division, not a truncating division, and so its behavior is not analogous to that of the usual integer remainder operator. Instead, the Java programming language defines % on floating-point operations to behave in a manner analogous to that of the integer remainder operator; this may be compared with the C library function fmod. The IEEE 754 remainder operation may be computed by the library routine Math.IEEEremainder. "

burs...@gmail.com

unread,
Jul 4, 2017, 10:21:13 AM7/4/17
to
Also missing:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.5.8)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- X is 100 rem 3.
X = 1.

?- X is 10.0 rem 0.3.
ERROR: Type error: `integer' expected, found `10.0' (a float)
ERROR: In:
ERROR: [8] _4258 is 10.0 rem 0.3
ERROR: [7] <user>

burs...@gmail.com

unread,
Jul 4, 2017, 10:26:33 AM7/4/17
to
Corr.:
But truncate(100/3) =\= 33, so it doesn't make much sense.

Am Dienstag, 4. Juli 2017 16:15:10 UTC+2 schrieb burs...@gmail.com:

burs...@gmail.com

unread,
Jul 4, 2017, 10:29:03 AM7/4/17
to
Now you got me confused:

Corr.:
But 100/3 =\= 33, so it doesn't make much sense.

Andrew Davison

unread,
Jul 4, 2017, 6:05:48 PM7/4/17
to
Seems I confused myself. Disregard.

Ulrich Neumerkel

unread,
Jul 5, 2017, 5:14:31 AM7/5/17
to
infr...@gmail.com writes:
>Yes, I went the datatype approach, so:
>
>?- X is 100R // 3.
> X = 100/3

The syntax 100R is an interesting extension since
100R cannot occur in valid Prolog text.

The answer, however, is invalid.

What system is this?

burs...@gmail.com

unread,
Jul 5, 2017, 5:37:37 AM7/5/17
to
Because it is a capital suffix. Without changing
the tokenizer it would give:

100 R

But the parser wouldn't accept it as an
abstract Prolog term.

So it would be safe to introduce this extension.

Mostowski Collapse

unread,
Jan 24, 2020, 6:21:10 PM1/24/20
to
SWI Prolog isn't focused. They try to harass me:

Some harrassement by SWI-Prolog discourse.
The harassers are Jan W. and EricGT:
https://gist.github.com/jburse/18fb0eaf776078f075b8124d72fc8755#gistcomment-3153171

But they miss most of the action. There is a funny
bug in the rational numbers of SWI-Prolog, which
affects both (/)/2 and (^)/2. Can you spot the error?

Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.15)

?- X is 1/(13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2)).
X = 1 rdiv 3.

?- Y is 13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2), X is 1/Y.
Y = 3,
X = 0.3333333333333333.

?- X is (13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2))^(-1).
X = 1 rdiv 3.

?- Y is 13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2), X is Y^(-1).
Y = 3,
X = 0.3333333333333333.

https://github.com/SWI-Prolog/swipl-devel/issues/538

Mostowski Collapse

unread,
Jan 24, 2020, 6:35:01 PM1/24/20
to
The first bug can be fixed, if we leave (/)/2 untouched
and use rdiv/2 in case we want rational number division.

The expected outcome is then for (/)/2:

?- X is 1/(13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2)).
X = 0.3333333333333333.

?- Y is 13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2), X is 1/Y.
Y = 3,
X = 0.3333333333333333.

And the expected outcome is then for rdiv/2:

?- X is 1 rdiv (13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2)).
X = 1 rdiv 3.

?- Y is 13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2), X is 1 rdiv Y.
Y = 3,
X = 1 rdiv 3.

So we reach consistency in that we don't
try some hidden type overloading.

Mostowski Collapse

unread,
Jan 24, 2020, 6:38:09 PM1/24/20
to
For the second bug, I dont know exactly what goes
wrong. We have already two operators (**)/2

and (^)/2. We could reserve (**)/2, so that this
operator only returns float:

?- X is (13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2))**(-1).
X = 0.3333333333333333.

?- Y is 13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2), X is Y**(-1).
Y = 3,
X = 0.3333333333333333.

And (^)/2 would always try rational numbers:

?- X is (13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2))^(-1).
X = 1 rdiv 3.

?- Y is 13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2), X is Y^(-1).
Y = 3,
X = 1 rdiv 3.

So I guess this deserves a remark here:

https://github.com/SWI-Prolog/swipl-devel/issues/185

Mostowski Collapse

unread,
Jan 25, 2020, 7:20:56 AM1/25/20
to
Guess I didn't post extensively about an
idea from december 2019. Its a new and old
idea at the same time. Here is a rought sketch:

The idea from december 2019 has a slight Logtalk flavor.
I think I posted already about it on comp.lang.prolog,
not sure. You would solve this problem object oriented:

?- X is 1 rdiv 3, number(X).
%%% should say true and not false

Basically you can view number/1 as a method invocation
with the Pythonesk convention, that self is at the first
argument position.

If you then realize number/1 for a class of rational
numbers, you can then return true. What I was not
sure about, until december 2019, how to deal with

fallback to numbers or any other type, how to have
default behaviour. But I now got an idea how to have
an object oriented (is)/2 that would do the job.

If you also make an object oriented comparator
then you could also solve this problem to some
extend, not yet sure:

?- sort([2 rdiv 7, 1 rdiv 3], X).
%%% Should say X = [2 rdiv 7, 1 rdiv 3]
%%% and not X = [1 rdiv 3, 2 rdiv 7].

Object Orientation is also the basis in Julia Programming
Language for such stuff. Well Julia Programming language
has even more than Object Orientation, they have a

multi-dispatch language.

Mostowski Collapse

unread,
Jan 25, 2020, 7:33:00 AM1/25/20
to
So I am somehow enjoying the benefit of a late
adopter. Leaving making mistakes to others.
But I am not yet shure how when whether my december

2019 will work, and whether I have enough time
to realize it. But I could do so in directly
adopting also new stuff from SWI-Prolog,

which got already sketched here:

Improved support for rational numbers
https://github.com/SWI-Prolog/swipl-devel/issues/539

Looks like there is some inflow from former
BNR Prolog, which has also some interval
arithmetic, like here:

CLP(BNR)
https://github.com/ridgeworks/clpBNR_pl

But I could also have the luck on my side,
since my system only feature CLP(FD) and CLP(B)
but not yet any CLP(Q) or CLP(R).

Maybe should provide some of these...

Julio Di Egidio

unread,
Jan 25, 2020, 8:05:19 AM1/25/20
to
On Saturday, 25 January 2020 00:21:10 UTC+1, Mostowski Collapse wrote:
>
> SWI Prolog isn't focused. They try to harass me:

They try to harass you?? LOL.

> Some harrassement by SWI-Prolog discourse.
> The harassers are Jan W. and EricGT:
> <https://gist.github.com/jburse/18fb0eaf776078f075b8124d72fc8755#gistcomment-3153171>
>
> But they miss most of the action. There is a funny
> bug in the rational numbers of SWI-Prolog, which
> affects both (/)/2 and (^)/2. Can you spot the error?
>
> Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.15)
>
> ?- X is 1/(13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2)).
> X = 1 rdiv 3.
>
> ?- Y is 13 rdiv 4 - (1 rdiv 2)*(1 rdiv 2), X is 1/Y.
> Y = 3,
> X = 0.3333333333333333.

The first one looks fine, the second one would work as well if the Y
returned was 3 rdiv 1, instead it is automatically converted to integer.
Rather, a consistent as well as mathematically correct approach would be
to convert operands to (eventually) rational in mixed operations, and not
down-convert them afterwards.

HTH (but you try and tell them),

Julio

Mostowski Collapse

unread,
Jan 26, 2020, 7:13:57 PM1/26/20
to
Orthographically incorrect scolding.

"Using screen shots and images"

But screenshot in english is written in one word.
Plural is screenshots. See also:

https://en.wikipedia.org/wiki/Screenshot

Mostowski Collapse

unread,
Jan 26, 2020, 7:15:16 PM1/26/20
to

Mostowski Collapse

unread,
Jan 26, 2020, 7:18:47 PM1/26/20
to
I think in the past a screen dump used a lot
of memory, but a screenshot usually generates
some PNG or GIF, and doesn't use a lot

memory, especially if the content is line
drawing or text. This is because PNG and GIF
do compress pictures:

PNG is designed to be:
Well compressed: both indexed-color and truecolor images are
compressed as effectively as in any other widely used lossless
format, and in most cases more effectively.
https://tools.ietf.org/html/rfc2083

Using JPG with quality less than 100% on
the other hand is not recommended, unless
you have some picture on your screen,

then it might be less noticable, that
JPG is not lossless.

Mostowski Collapse

unread,
Feb 1, 2020, 3:12:12 PM2/1/20
to
Ok, I am grinding the stone. A last try,
I don't want to be at war with Jan W., so
that the messenger always gets killed.

Now towards EricGT, maybe somebody young?

I don’t think its a guidance. Somebody is
shouting at me, and then you tryed to add
some reasonable response to it.

And please stop using screenshots

If you want to make it a guidance remove
this thread, and write a proper guidance
please that explicitly adresses everybody,
and doesn’t personally address me.

This would help the community much more
than giving bad example of harassement.

It wouldn’t cost you much time to bring
it in a proper form. You already corrected
the spelling error, and it seems you are
anyway keen on writing wiki like stuff and
somehow talented.

Dont subject to the dark side of the force.

Mostowski Collapse

unread,
Feb 1, 2020, 9:38:05 PM2/1/20
to
Jan W. made a sorting test.

?- trat(1 000 000).
% 1 inferences, 2.741 CPU in 2.741 seconds (100% CPU, 0 Lips)
true.

?- tfloat(1 000 000).
% 0 inferences, 1.366 CPU in 1.366 seconds (100% CPU, 0 Lips)
true.

The relative difference from 1.366 seconds to 2.741
seconds is more than 100%. The premium fee
for exactness.

At the moment I don’t know whether 100% is good
or bad, and whether Henrici is applicable or whether
there are other methods to make comparison faster.

Here its also considered an unfortunate situation:
“multiplication will take more than linear time”
https://cs.stackexchange.com/questions/6266/comparing-rational-numbers

And this guy is more optimistic:
Bill Dubuque, continued fractions
https://math.stackexchange.com/a/14314/4414

Kin Taylk CalocaleurlgurrIzzly NONturnEYEmation

unread,
Feb 2, 2020, 12:03:50 AM2/2/20
to
What is the reasonable response to some individual with no history of providing benefit now coming forward and requesting the forbid of Your action as-if Your action understood to be forbiddable as-if their derogatory kill of Your activity supported by some inherent moral condemnation due to You manifest as their satisfying power because You harmed not helped the benefit ?

Answer : fukc You asshole .

As in : do something worthwhile once in Your life jerk before demonstrating the nature of Your activity by launching Your demure-because-You-mediocre-at-best rampage of activity-killing insult .

As in : Your only activity is to kill the activity of others who are not killers ; yer the good but them the evil ?

fuk off .

~~~ kintalken ~~~

Mostowski Collapse

unread,
Feb 2, 2020, 7:33:41 AM2/2/20
to
Yeah of course the good, the bad and the ugly.
https://www.youtube.com/watch?v=h1PfrmCGFnk

Make your choice. LoL

Mostowski Collapse

unread,
Feb 2, 2020, 7:42:02 AM2/2/20
to
So what will be the future of SWI Rationals?
This was my old testing code:

horner(N, R) :-
horner(N, 0, R).

horner(1, S, R) :- !,
R is 1+(-1 rdiv 2)*(-1 rdiv 2)*S.
horner(N, S, R) :-
M is N-1,
H is 1+(-1 rdiv 2)*(((-1 rdiv 2)-M) rdiv N)*S,
horner(M, H, R).

The new testing code according to Jan W. (02.02.2020) is:

horner(N, R) :-
horner(N, 0, R).

horner(1, S, R) :- !,
R is 1+(-1/2)*(-1/2)*S.
horner(N, S, R) :-
M is N-1,
H is 1+(-1/2)*(((-1/2)-M)/N)*S,
horner(M, H, R).

It might run faster, not because the switch
from (/)/2 to (rdiv)/2. But if rational number
literals are moved around,

the re-normalization step might be omitted.
I don't know whether the old SWI had a re-normalizartion
step between (is)/2 calls, but what could

do for me, re-test on my machine when its available.
I know the old figurse before the new rational
numbers, which was proposed on GitHub:

> Improved support for rational numbers
> https://github.com/SWI-Prolog/swipl-devel/issues/539

And can then compare with my old timings.

Mostowski Collapse

unread,
Feb 2, 2020, 7:51:04 AM2/2/20
to
Its a strange way to compute sqrt(2)
approximation, you can also use it for

correctness check, like check whether you get
this here. I hope I didn't delete some digit:

Its a strange way to compute sqrt(2):

?- horner(100,X), Y is float(X).
X = 22506280506048041472675379598885135569
33772436904539887974113033493227786869015
3259936903 rdiv 159143435651131725489722319
40698266883214596825515126958094847260581
103904401068017057792,
Y = 1.414213562373095.

Well its not so strange, even Wolfram Alpha
knows about it, use x=1 here in Taylor Expansion
and follow a Horner Schema:

series (1+x)^(1/2)
https://www.wolframalpha.com/input/?i=series+%281%2Bx%29^%281%2F2%29

Disclaimer, I hope its really this, the
code I had was not very well documented.

Mostowski Collapse

unread,
Feb 2, 2020, 7:59:57 AM2/2/20
to
In Java, for my system, could introduce
rational number literals via such a class:

https://introcs.cs.princeton.edu/java/92symbolic/BigRational.java.html

Would also make the class derive from java.lang.Number
So that the Prolog predicate number/1 goes for free.
But I am hesitant to do so. First of all the

numerator and denominator are both fixed to BigNumber,
could not represent smaller rational numbers more compact,
so we would need a more complex implementation.

Basically I would like a Prolog implementation
of the rational numbers itself, so that also could
more easily experimentwith Henrici algorithm etc.. etc..

But I am not yet there having a Prolog implementation.
Similar like BigRational is an object oriented class,
I am envisioning some object oriented solution

under the hood in my Prolog system. I wrote
"Logtalk inspired" somewhere. Well not really,
I would more use my usual ISO module based object

orientation, to arrive at it. But the late binding
involved in this rewrap should not slow down the
normal arithmetic. I am not yet there...

Working on it.

Mostowski Collapse

unread,
Feb 2, 2020, 8:08:43 AM2/2/20
to
What I was deliberating was whether
java.lang.Number can be used as a marker,
and combined with my SkelCompound. But this

doesn't work since java.lang.Number is
not an interface. Could be a design flaw
of Java that there is nowhere such an interface.

They dont have the same design flaw for
Strings, there is at least this interface:

https://docs.oracle.com/javase/7/docs/api/java/lang/CharSequence.html

Which allows customizing strings. But customizing
numbers in Jave is a little bit annoying.

Basically could try some new NumberCompound
class, to allow all kind of composite numbers
like rationals, complex, etc..

But the if Number is assumed to be ground, cant
use patterns anymore, which will kill my idea
to do the number methods in Prolog itself.

I could not anymore pack, unpack, share or
even copy for assert and otherwise, Prolog
style so easily.

Mostowski Collapse

unread,
Feb 2, 2020, 11:35:16 AM2/2/20
to
Easy to remember palindrom day! LoL

Am Sonntag, 2. Februar 2020 13:42:02 UTC+1 schrieb Mostowski Collapse:

Mostowski Collapse

unread,
Feb 6, 2020, 7:50:45 AM2/6/20
to
It is possible to review new takes on rational numbers
by paper only, without some hands on. What helps
is this compilation:

Author: Joachim Schimpf, 2020
http://eclipseclp.org/wiki/Prolog/Rationals

My favorite test case, that I am waiting for to get
some hands on experience with the new SWI-Prolog
rationals, is this exampke.

The example makes use of unification and switches
between intensional and extensional use of rational
numbers:

/* Fibonacci Algorithm,
https://en.wikipedia.org/wiki/Egyptian_fraction */
egyptian(1 rdiv X,[1 rdiv X]) :- !.
egyptian(X rdiv Y,[1 rdiv Z|E]) :-
Z is (Y+X-1)//X,
T is (X rdiv Y)-(1 rdiv Z),
egyptian(T, E).

Here are some example runs. I don't know whether
its really desired that the float number case fails,
but thats the current status quo:

Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.21)

?- egyptian(4 rdiv 13,X).
X = [1 rdiv 4, 1 rdiv 18, 1 rdiv 468].
?- egyptian(1.5,X).
false.

But there is an interesting twist, we can also
use YAP indexing to code the example. YAP indexing
can help in structure sharing:

egyptian(H,[H]) :- H = 1 rdiv X, !.
egyptian(H,[1 rdiv Z|E]) :- H = X rdiv Y,
Z is (Y+X-1)//X,
T is H-(1 rdiv Z),
egyptian(T, E).

A few months ago there was a long discussion
about YAP indexing on SWI discourse. So I started
making a separate documentation about it

for my Prolog system:

Indexable Conditions (YAP Indexing)
http://www.jekejeke.ch/idatab/doclet/prod/en/docs/05_run/10_docu/02_reference/07_theories/01_kernel/06_sharing.html

Now looking at the YAP indexing version of
egyptian/2, this triggered some new ideas about
doing rational numbers inside a Prolog system.

The ideas are a little chaotic still, but I guess
will do a write-up soon.

Mostowski Collapse

unread,
Feb 7, 2020, 7:39:54 AM2/7/20
to
Interesting twist, if you would like to
be compatible with Microsoft Excel,
you would possibly require 0**0 gives NaN.

Microsoft Excel treats =0^0 as #NUM!.
https://en.wikipedia.org/wiki/Zero_to_the_power_of_zero#IEEE_floating-point_standard

Just a quick check what some Prolog systems
currently do. SWI-Prolog:

Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.21-1-g58fb90ecb)

?- X is 0**0.
X = 1.
?- X is 0^0.
X = 1.

ECLiPSe Prolog started with “-L iso_strict”
command line options

Version 7.0 #52 (x86_64_nt), Mon Feb 3 23:59 2020

[eclipse 1]: X is 0**0.
X = 1.0
Yes (0.00s cpu)
[eclipse 2]: X is 0^0.
X = 1
Yes (0.00s cpu)

Mostowski Collapse

unread,
Feb 7, 2020, 1:22:12 PM2/7/20
to
This is also a nice brain teaser. Converting
back and forthing between IEEE 754. First
checking that negative zero is a

different object from positive zero.

[eclipse 9]: 0.0 = -0.0.
No (0.00s cpu)

Now here comes the brain teaser:

[eclipse 10]: X is rational(-0.0), Y is float(X).
X = 0_1
Y = 0.0
Yes (0.00s cpu)

Mostowski Collapse

unread,
Feb 8, 2020, 10:30:21 AM2/8/20
to
Sometimes I really wonder, whether this IEEE 754
stuff has some benefit. I mean as it is currently
done for SWI-Prolog only some constants are

added, like -0.0, NaN, Inf, etc.. But usually
a Prolog system can simply model them by atoms,
and with good multi-argument indexing,

you can write your logic nevertheless. Wouldn't
it be more useful to add completely new datatypes
like float32 or decimal?

Mostowski Collapse

unread,
Feb 8, 2020, 10:34:43 AM2/8/20
to

In Java there is a function ulp(). I have ported
it to Prolog. You can then compute x+ulp(x) or
x-ulp(x). It don’t whether this is exactly

nextUp() or nextDown(). Maybe there are problems
with half rounding. I have extended it to float32
and BigDecimals, types available in my Prolog

system, but not in ISO core standard:

ulp: integer -> integer
ulp: float -> float (should be both float32 and float64, have to check)
ulp: decimal -> decimal
http://www.jekejeke.ch/idatab/doclet/prod/en/docs/15_min/10_docu/02_reference/07_theory/04_misc/01_elementary.html

ulp is acronym for “unit of least precision”.
This is not an absolute notion like epsilon
which is a constant, but a relative notion,

its a function that takes an argument. The
Java version can also deal with NaN and
consorts, but I do not support this in

the ALU (Arithmetic Logic Unit) of my Prolog
system and subequently also not for the ported
Prolog function. Here are some sample runs:

Jekejeke Prolog 4, Runtime Library 1.4.2 (January 21, 2020)

/* ISO core float = float64 */
?- X is 34.543, Y is X-ulp(X), Z is X+ulp(X).
X = 34.543,
Y = 34.54299999999999,
Z = 34.543000000000006
/* float32 */
?- X is 0f34.543, Y is X-ulp(X), Z is X+ulp(X).
X = 0f34.543,
Y = 0f34.542995,
Z = 0f34.543003
/* decimal */
?- X is 0d34.543, Y is X-ulp(X), Z is X+ulp(X).
X = 0d34.543,
Y = 0d34.542,
Z = 0d34.544

If there are problems with half rounding, have to
think, not sure. Then I might also explicit nextUp()
and nextDown() functions.

Mostowski Collapse

unread,
Feb 8, 2020, 10:48:13 AM2/8/20
to
We can also do some further dry paper review.
Here is another source from ECLiPSe Prolog that
SWI-Prolog is attracted to, or lets say those

currently working on it:

Author: Joachim Schimpf, 2009
http://eclipseclp.org/Specs/core_update_float.html

the proposal doesn't feature a function ulp().
Although ulp() is not only Java, its also some
other programming languages.

Whether its really IEEE 754 I don't know.
The latest would be 2019.

Joachim Schimpf

unread,
Feb 8, 2020, 2:31:55 PM2/8/20
to
On 08/02/2020 15:48, Mostowski Collapse wrote:
> We can also do some further dry paper review.
> Here is another source from ECLiPSe Prolog that
> SWI-Prolog is attracted to, or lets say those
>
> currently working on it:
>
> Author: Joachim Schimpf, 2009
> http://eclipseclp.org/Specs/core_update_float.html
>
> the proposal doesn't feature a function ulp().

It proposes the nexttoward/2 function instead:
http://eclipseclp.org/Specs/core_update_float.html#nexttoward
http://eclipseclp.org/doc/bips/kernel/arithmetic/nexttoward-3.html

Cheers,
Joachim

Mostowski Collapse

unread,
Feb 8, 2020, 4:09:59 PM2/8/20
to

It seems that since Java 1.8, they also home nextUp()
and nextDown(). And interstingly its bootstrapped from
some lowlevel ops, that work on float bit patterns.

You can check the source of Math.java. Its not that
difficult to realize. You don’t need some control
flags and instruct the FPU.

Mostowski Collapse

unread,
Feb 8, 2020, 4:12:56 PM2/8/20
to
It could be that the Java nextAfter() is the
binary nexttoward/2. Not sure.

Mostowski Collapse

unread,
Feb 8, 2020, 4:14:33 PM2/8/20
to
Corr.:
Since Java 1.6 resp. Java 1.8.

Am Samstag, 8. Februar 2020 22:09:59 UTC+1 schrieb Mostowski Collapse:

Mostowski Collapse

unread,
Feb 9, 2020, 8:50:51 AM2/9/20
to
Interestingly there are some disbelievers, that
interval arithmetic is not a matter of simply
changeing the rounding mode. Rounding mode only

applies locally on each operation, doesn't serve
you globally as a interval calculator, for
a full expression. Just try for example:

Try this here with isL/2 and isR/2,
or some data variation of it. This should
already switch lower and upper bound:

?- X = 0.05, Y = 0.049999999999999996, Z is -(X+Y).

Unfortunately I can not give full proof
of it, i.e. running it on a computer.
Need to figure out how to run SoftFloat 3e

in OpenJDK. Meanwhile, some demonstration
could be conducted with BigDecimal. I have
also BigDecimals with rounding, but only

with HALF_EVEN so far:

?- new_context(3,C), mp_add(0d5.02,0d5.02,C,X).
C = 0r75d40605,
X = 0d10.0
?- new_context(3,C), mp_add(0d5.03,0d5.03,C,X).
C = 0r75d40605,
X = 0d10.1

But here is already a prototype of a new
predictae new_context/3, which also accepts a
rounding mode. I get this here:

/* BigDecimal.ROUND_CEILING*/
?- new_context(3,2,C), mp_add(0d5.02,0d5.02,C,X).
C = 0r330e4c04,
X = 0d10.1
/* BigDecimal.ROUND_FLOOR */
?- new_context(3,3,C), mp_add(0d5.02,0d5.02,C,X).
C = 0r95cabfcc,
X = 0d10.0

Advantage of using a MathContext. The thingy is re-entrant,
no problems for multi-threading. Well you could try
a thread local round_mode flag. But nevertheless,

no assumption whatever of some state, that controls
evaluation. Pure functional realization, with the help
of value objects (immutable objects) like MathContext

that are passed around.

Mostowski Collapse

unread,
Feb 9, 2020, 9:39:58 AM2/9/20
to
Ok, its possible to play around with ECLiPSe Prolog,
and show what happens:

Version 7.0 #52 (x86_64_nt), Mon Feb 3 23:59 2020

[eclipse 1]: X is breal(0.5), Y is breal(0.049999999999999996), Z is -(X+Y).

X = 0.5__0.5
Y = 0.049999999999999996__0.049999999999999996
Z = -0.55__-0.54999999999999993
Yes (0.00s cpu)

Note, the values are breal-ed, not the expression.
If I breal the expression, nothing happens:

[eclipse 2]: X is 0.5, Y is 0.049999999999999996, Z is breal(-(X+Y)).

X = 0.5
Y = 0.049999999999999996
Z = -0.55__-0.55
Yes (0.00s cpu)

So breal is a simple injection X --> X__X. And there
is a typo in the documentation. I cannot verify what
is the documentation here:

/* what the documentation says */
?- X is breal(pi).
X = 3.1415926535897927__3.1415926535897936

What I get:

/* what I get */
[eclipse 3]: X is breal(pi).
X = 3.1415926535897931__3.1415926535897931

Mostowski Collapse

unread,
Feb 9, 2020, 9:44:38 AM2/9/20
to

Joachim Schimpf

unread,
Feb 9, 2020, 11:53:56 AM2/9/20
to
On 09/02/2020 14:44, Mostowski Collapse wrote:
> The documentation error is here:
> http://eclipseclp.org/doc/bips/kernel/typetest/breal-1.html

>> So breal is a simple injection X --> X__X. And there
>> is a typo in the documentation. I cannot verify what
>> is the documentation here:
>>
>> /* what the documentation says */
>> ?- X is breal(pi).
>> X = 3.1415926535897927__3.1415926535897936
>>
>> What I get:
>>
>> /* what I get */
>> [eclipse 3]: X is breal(pi).
>> X = 3.1415926535897931__3.1415926535897931


Thank you, the documentation is indeed wrong here: the pi/0
function returns a float, and the breal/1 function does *not*
do any "fuzzifying" when converting floats to breal intervals.
It cannot, because it doesn't known how inaccurate the float is.

When converting directly from an accurate type (such as integer
or rational) the outward rounding *is* indeed done, giving an
interval that includes the accurate value:

?- X is breal(1_10). % rational
X = 0.099999999999999992__0.10000000000000002

?- X is breal(9999999999999999).
X = 9999999999999998.0__10000000000000002.0


But to get correct results from interval arithmetic, all your
input values must be correct intervals to start with.

For example:

?- T is 1/10, One is T+T+T+T+T+T+T+T+T+T. % float arithmetic
T = 0.1
One = 0.99999999999999989
Yes (0.00s cpu)

?- T is breal(1)/10, One is T+T+T+T+T+T+T+T+T+T. % interval arithmetic
T = 0.099999999999999992__0.1
One = 0.99999999999999978__1.0000000000000007
Yes (0.00s cpu)


Cheers,
Joachim

Mostowski Collapse

unread,
Feb 9, 2020, 11:58:03 AM2/9/20
to
Thanks!

Mostowski Collapse

unread,
Feb 10, 2020, 4:32:32 AM2/10/20
to
Some musing about BigFloat. Ok, currently CLP(BNR) is
just fuzzying up and down by 1 ULP, blindly it seems.
And then for example CLP(BNR) uses:

% Z := X + Y (add)
+([Xl,Xh], [Yl,Yh], [Zl,Zh]) :-
Zl isL Xl+Yl, Zh isH Xh+Yh. % Z := [Xl+Yl, Xh+Yh].

https://github.com/ridgeworks/clpBNR_pl/blob/master/src/ia_primitives.pl

This would give probably a much larger interval
than what ECLiPSe Prolog does. Assuming ECLiPSe
Prolog has access to more accurate rounding.

But SWI-Prolog would have the option to incorporate
BigFloat from GMP. This would even allow to select
the number of bits one wants to have. Maybe I can find

a Java library for BigFloat. BigDecimal is standard
in Java, but doesn’t have trigonometric functions.
BigFloat is not standard in Java. Maybe slower than

FPU, on the other hand you could go arbitrary
precision, something that ECLiPSe Prolog might
missing. Not sure.

Mostowski Collapse

unread,
Feb 10, 2020, 4:37:46 AM2/10/20
to
Here they show computing e to 200 bits:

$ ./sample
Sum is 2.7182818284590452353602874713526624977572470936999595749669131

https://www.mpfr.org/sample.html

For BigFloat I could invent a new number
prefix in my system. Not yet sure how to do.
In BigDecimal its simple, you can encode the

number of "bits" which is rather the number
of digits in the number representation itself.
So for example these here are different decimal

numbers in my system, carrying different scales.
I use the prefix "0d" for BigDecimal:

0d1.0

0d1.0000

Maybe represent BigFloat with "0p" prefix. But
since the radix is binary, not sure how to
have the scale available in number printing.

What would be also great, if could develop
algorithms that work on both number systems
BigDecimal and BigFloat, they are only different

in radix, BigDecimal has radix b=10, and BigFloat
has radix b=2. So there could be a lot of
commonality among them.

Such radix stuff is also part of IEEE 754, but
I didn't have a look yet. Not sure what is
theirin. Just musing.

Mostowski Collapse

unread,
Feb 10, 2020, 4:46:06 AM2/10/20
to
BigDecimals also belong to the IEEE 754 family:

Decimal32 floating point is a relatively new
decimal floating-point format, formally introduced
in the 2008 version of IEEE 754 as well as
with ISO/IEC/IEEE 60559:2011.
https://en.wikipedia.org/wiki/Decimal32_floating-point_format

Java typically has them as BID. Since BigDecimal
is bootstrapped from BigInteger. But since they
are just ADT (Abstract Data Types) realized via
Object Orientation, this is an implementation detail.

"In one representation method, based on binary
integer decimal (BID), the significand is represented
as binary coded positive integer. The other,
alternative, representation method is based
on densely packed decimal (DPD) for most of
the significand (except the most significant digit)."

Mostowski Collapse

unread,
Feb 10, 2020, 4:47:05 AM2/10/20
to
I guess BigFloats can be also bootstrapped
from BigInteger. The differents is only in
meaning of the scale.

Mostowski Collapse

unread,
Feb 10, 2020, 4:50:12 AM2/10/20
to
Because of this, I was thinking of
something drastic. We have rationals
as Prolog compounds rdiv(A,B), ok this

is going away in SWI-Prolog. But we
could maybe have BigDecimal and BigFloat
as these Prolog compounds:

decimal(unscaled,scale).

binary(unscaled,scale).

Just abandon reference datatype here, and
make something contrarian to what seems
to happen with rdiv/2.

LoL

Mostowski Collapse

unread,
Feb 11, 2020, 3:57:14 PM2/11/20
to
Toying around with new BigDecimal rounding. Unfortunately
I don't have yet float32 or float64 rounding. But can
simulate float64 via decimal with 17 digits.

Decimals behaves slightly different. Here is what
float64 does, from ECLiPSe Prolog:

[eclipse 3]: T is atan(breal(1)), PI is T+T+T+T.
T = 0.78539816339744817__0.78539816339744839
PI = 3.1415926535897922__3.141592653589794
Yes (0.00s cpu)

[eclipse 4]: T is atan(breal(1)), PI is 4*T.
T = 0.78539816339744817__0.78539816339744839
PI = 3.1415926535897927__3.1415926535897936
Yes (0.00s cpu)

And here is what decimal with 17 digits precision
would do. This is from my modules library(decimal/scale)
and library(decimal/arith), plus some new code:

?- T is breal(0d0.78539816339744817,0d0.78539816339744839), PI is T+T+T+T.
T = breal(0d0.78539816339744817, 0d0.78539816339744839),
PI = breal(0d3.1415926535897925, 0d3.1415926535897936)

?- T is breal(0d0.78539816339744817,0d0.78539816339744839), PI is 0d4*T.
T = breal(0d0.78539816339744817, 0d0.78539816339744839),
PI = breal(0d3.1415926535897926, 0d3.1415926535897936)

In both cases multiplication is more tight.

R Kym Horsell

unread,
Feb 11, 2020, 5:14:45 PM2/11/20
to
Mostowski Collapse <burs...@gmail.com> wrote:
> Toying around with new BigDecimal rounding. Unfortunately
> I don't have yet float32 or float64 rounding. But can
> simulate float64 via decimal with 17 digits.

The underlying base of the arithmetric can make a big diff.
I'm fairly sure this is covered in the classic Knuth volumes.
His "Mix" conceptual machine was binary & decimal (like
"many" Big Irons were back in the day :) and I think I remember
did some of his error analysis of it.

> Decimals behaves slightly different. Here is what
> float64 does, from ECLiPSe Prolog:
>
> [eclipse 3]: T is atan(breal(1)), PI is T+T+T+T.
> T = 0.78539816339744817__0.78539816339744839
> PI = 3.1415926535897922__3.141592653589794
> Yes (0.00s cpu)
>
> [eclipse 4]: T is atan(breal(1)), PI is 4*T.
> T = 0.78539816339744817__0.78539816339744839
> PI = 3.1415926535897927__3.1415926535897936
> Yes (0.00s cpu)
...

Mostowski Collapse

unread,
Feb 11, 2020, 6:54:29 PM2/11/20
to
The difference I noticed was this obvious
one. I couldn't run Joachim Schimpf example,

because with BigDecimal, I would get:

?- T is breal(1)/10.
0.1__0.1

So I switched to the pi/4 example, which is
I guess inexact in both binary and decimal
float numbers.

BTW, you can model BigDecimal and BigFloat
as rational numbers. Ingnoring for the moment
the fact that BigDecimal supports negatve scale:

decimal(U,S) == rdiv(U,10^S)

binary(U,S) == rdiv(U,2^S).

Mostowski Collapse

unread,
Feb 11, 2020, 6:55:08 PM2/11/20
to
Corr.:

?- T is breal(1)/10.
T = 0.1__0.1

Mostowski Collapse

unread,
Feb 11, 2020, 7:15:33 PM2/11/20
to
In finance (insurance, banking, etc..) you might
prefer decimals over binary. Since you can represent
cents exactly, and subsequently they also add

up exactly. In Java BigDecimals are also used in
the interface to SQL databases. Many SQL database
feature quite big decimals, for example you

could declare:

foo DECIMAL(20,8)

possibly eating up 128 bits. But the difference
to DECIMAL(20,8) and what can be also done with
BigDecimal. DECIMAL(20,8) is a fixnum, that is

the period is at a fixed position. But what
Java BigDecimal also can do is floating
position. This is also seen in my example,

just count the significant digits:

?- T is breal(0d0.78539816339744817,0d0.78539816339744839), PI is 0d4*T.
T = breal(0d0.78539816339744817, 0d0.78539816339744839),
PI = breal(0d3.1415926535897926, 0d3.1415926535897936)


0d0.78539816339744817
12345678901234567

0d3.1415926535897926
1 2345678901234567

The period moved. So BigDecimal can do both
fixed point and floating point. There are separate
methods for both. Its a little tricky to figure

out how floating point for BigDecimal works, but
it can do so. Basically have operations that act
like computing with some extended precision and

then rounding to a lower precision, making
the period move, since the scale can get smaller,
in favor of the mantissa.

Mostowski Collapse

unread,
Feb 11, 2020, 7:17:55 PM2/11/20
to
the period moves, since the scale can get smaller,
in favor of a smaller mantissa, to stay in sync
with the size constraint of the floating point

number, that is modelled.

Mostowski Collapse

unread,
Feb 12, 2020, 6:57:30 AM2/12/20
to
If we are at it, could CLP(FD) also suppport this?

% Fractions puzzle - a problem with a non-integer constraint.
% Find 9 distinct non-zero digits that satisfy:
% A D G
% -- + -- + -- == 1
% BC EF HI

fractions(Digits) :-
Digits = [A,B,C,D,E,F,G,H,I],
Digits #:: 1..9,

A/(10*B+C) + D/(10*E+F) + G/(10*H+I) $= 1,
alldifferent(Digits),

labeling(Digits).

http://www.eclipseclp.org/doc/bips/lib/ic/index.html

Mostowski Collapse

unread,
Feb 12, 2020, 7:11:58 AM2/12/20
to
Aloha!

nasa/FPRoCK is a new @GitHub repo by @NASA
FPRoCk is a software library for checking
satisfiability of a set of mixed real and
floating-point constraints. If this set

of constraints has at least one solution,
it returns one of the solutions, otherwise…
https://github.com/nasa/FPRoCK

and also something still active:

COLIBRI is a library (COnstraint LIBrary for
veRIfication) developed at CEA LIST and used
for verification or test data generation
purposes since 2000, using the techniques of
constraint programming.
http://smtcomp.sourceforge.net/2018/systemDescriptions/COLIBRI.pdf

Mostowski Collapse

unread,
Feb 12, 2020, 1:37:08 PM2/12/20
to
Interestingly you can also extend GCD and LCM to
rational numbers. Here is a prototype:

?- X is 13 rdiv 6, Y is 3 rdiv 4, Z is gcd(X,Y).
X = rat(13, 6),
Y = rat(3, 4),
Z = rat(1, 12)

?- X is 13 rdiv 6, Y is 3 rdiv 4, Z is lcm(X,Y).
X = rat(13, 6),
Y = rat(3, 4),
Z = rat(39, 2)

Credits:
https://math.stackexchange.com/questions/151081/gcd-of-rationals

Am Montag, 3. Juli 2017 23:14:04 UTC+2 schrieb Mostowski Collapse:
> Dear All,
>
> If you want rational arithmetic(*), and you do the following:
>
> ?- A is 4 rdiv 1/3.
> A = 1.3333333333333333.
>
> This is anyway wrong. What you need to do is:
>
> ?- A is (4 rdiv 1) rdiv 3.
> A = 4 rdiv 3.
>
> Richard O'Keefe idea is already realized, you don't need to do anything anymore, since rdiv/2 is not only a constructor but also an operation, you can do the following, try it for yourself with SWI-Prolog:
>
> Welcome to SWI-Prolog (threaded, 64 bits, version 7.5.8)
> SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
>
> ?- X is (1 rdiv 4) rdiv (1 rdiv 2).
> X = 1 rdiv 2.
>
> ?- X is (1 rdiv 2) rdiv (1 rdiv 4).
> X = 2.
>
> So if you use rdiv/2 instead of (/)/2 you program runs rationals and not floats. I don't see any possility to merge rdiv/2 and (/)/2 into one operator, this is impossible I guess. Now putting side by side the division and the power operator, we could require:
>
> Datatype Approach:
> ============
> datatype division power
> float: (/)/2 (^)/2
> rational: (rdiv)/2 (^)/2 /* name clash */
>
> But we run into the problem that (^)/2 for floats is not the same as (^)/2 for rationals, we would need two different operators. When I posted this feature request, I might have had this idea. Meanwhile I have abandoned the above schema in favor of another schema.
>
> The new schema is based on different contexts and not on different datatypes, the advantage is that I don't need a (rdiv)/2 operator anymore:
>
> Context Approach:
> ============
> context division power
> float: (/)/2 (^)/2
> rational: (/)/2 (^)/2
>
> So I must appologize, since I issued a datatype feature request, whereby in the end I implemented myself a context feature, much later after I have issued this feature request here. I implemented the context feature via my new library(groebner/generic).
>
> The advantages of the context approach is as follows:
>
> Typing rdiv/2 is unnatural, its very clumsy, its much easier to type (/)/2.
> Programs can be easily moved from one context into anthor, we do not need to replace (/)/2 by (rdiv)/2.
> The context approach is also followed by CLP(Q), in CLP(Q) we do not need to write { X = Y rdiv Z } instead we write naturally { X = Y / Z }, right?
>
> Hope this helps!
>
> (*)
> https://github.com/SWI-Prolog/swipl-devel/issues/185

Mostowski Collapse

unread,
Feb 12, 2020, 3:00:09 PM2/12/20
to
Currently skimming through all the evaluable functions
I have, and deliberating whether could be extended to
rational numbers.

Functions that are required by ISO core standard to
return a float somehow fall short. For example truncate/1
is not a good idea to consider for rational number support.

truncate/1 has anyway some problems in that it doesn't
return some integer type. What is missing in ISO core
standard is a kind of evaluable function that

corresponds to the (int) or (long) type case, which
in Java when applied to float does a truncate and
type change. But the evaluable function integer/1

can come to the rescue. Its has some support. I was
testing this here:

?- X is integer(3.1415).
X = 3

I could figure out the following support:

System Available
GNU Prolog No
Ciao Prolog Yes
YAP Prolog Yes
SICStus Prolog Yes
ECLiPSe Prolog No
SWI-Prolog Yes
Jekejeke Prolog Yes

Mostowski Collapse

unread,
Feb 12, 2020, 3:04:07 PM2/12/20
to
Since ECLiPSe Prolog is not on the list,
it doesn't work:

[eclipse 1]: X is integer(6283_2000).
arithmetic exception in integer(6283_2000, X)
Abort

On the other hand it seems that SWI-Prolog
does it correctly:

Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.21)

?- X is integer(6283 rdiv 2000).
X = 3.

?- X is integer((- 6283) rdiv 2000).
X = -3.

Interesting twist, the misterious function fix/1 in
ECLiPSe Prolog does it, I didn't find a documentation,
but experimenting shows now:

[eclipse 3]: X is fix(6283_2000).
X = 3
Yes (0.00s cpu)

[eclipse 4]: X is fix(-6283_2000).
X = -3
Yes (0.00s cpu)

Mostowski Collapse

unread,
Feb 12, 2020, 3:15:28 PM2/12/20
to
Some Prolog systems map truncate/1 to integer,
but the result is rather nonsense, when the
Prolog system doesn't have big nums:

GNU Prolog 1.4.5

?- X is truncate(314153141531415314.0).
X = 314153141531415296

?- X is truncate(3141531415314153141.0).
X = 835688406100459008

?- X is truncate(31415314153141531415.0).
X = 0

So the approach that truncate/1 returns a float
is much better:

[eclipse 7]: X is truncate(314153141531415314.0).
X = 3.141531415314153e+17
Yes (0.00s cpu)

[eclipse 8]: X is truncate(3141531415314153141.0).
X = 3.141531415314153e+18
Yes (0.00s cpu)

[eclipse 9]: X is truncate(31415314153141531415.0).
X = 3.1415314153141531e+19

What does fix/1 or integer/1 do?

[eclipse 10]: X is fix(314153141531415314.0).
X = 314153141531415296
Yes (0.00s cpu)

[eclipse 11]: X is fix(3141531415314153141.0).
X = 3141531415314152960
Yes (0.00s cpu)

[eclipse 12]: X is fix(31415314153141531415.0).
X = 31415314153141530624
Yes (0.00s cpu)

Respectively:

Jekejeke Prolog 4, Runtime Library 1.4.2 (January 21, 2020)

?- X is integer(314153141531415314.0).
X = 314153141531415296

?- X is integer(3141531415314153141.0).
X = 3141531415314152960

?- X is integer(31415314153141531415.0).
X = 31415314153141530624

Mostowski Collapse

unread,
Feb 12, 2020, 3:36:56 PM2/12/20
to
Ok, where there is integer/1 resp fix/1 evaluable
function on rational numbers, there can be also rem/2
evaluable function on rational numbers.

First for integers, rem/2 does work:

[eclipse 10]: X is 7, Y is 3, Z is X rem Y.
X = 7
Y = 3
Z = 1
Yes (0.00s cpu)
[eclipse 11]: X is -7, Y is 3, Z is X rem Y.
X = -7
Y = 3
Z = -1
Yes (0.00s cpu)

Unfortunately rem/2 doesn't apply to rational number
in ECLiPSe Prolog:

[eclipse 12]: X is 7_2, Y is 3_2, Z is X rem Y.
type error in rem(7_2, 3_2, _491)
Abort

But rem/2 is also definable for rational numbers. Just
use the obvious:

[eclipse 15]: X is 7_2, Y is 3_2, Z is X-fix(X/Y)*Y.
X = 7_2
Y = 3_2
Z = 1_2
Yes (0.00s cpu)
[eclipse 16]: X is -7_2, Y is 3_2, Z is X-fix(X/Y)*Y.
X = -7_2
Y = 3_2
Z = -1_2
Yes (0.00s cpu)

mod/2 can also be realized.

Mostowski Collapse

unread,
Feb 12, 2020, 3:38:45 PM2/12/20
to
SWI-Prolog also refuses rem/2 resp mod/2 on rational numbers:

?- X is 7 rdiv 2, Y is 3 rdiv 2, Z is X rem Y.
ERROR: Type error: `integer' expected, found `7 rdiv 2' (a rational)

?- X is 7 rdiv 2, Y is 3 rdiv 2, Z is X mod Y.
ERROR: Type error: `integer' expected, found `7 rdiv 2' (a rational)

Mostowski Collapse

unread,
Feb 12, 2020, 4:34:57 PM2/12/20
to
Ok, there is a precedent of GCD for rational
numbers in Prolog:

/* LONG.PL : Arbitrary precision rational arithmetic package.
Copyright (C) 1981 - R.A.O'Keefe.
http://www.picat-lang.org/bprolog/publib/long.html

Am Mittwoch, 12. Februar 2020 19:37:08 UTC+1 schrieb Mostowski Collapse:

Joachim Schimpf

unread,
Feb 12, 2020, 6:38:07 PM2/12/20
to
On 12/02/2020 20:04, Mostowski Collapse wrote:
> Since ECLiPSe Prolog is not on the list,
> it doesn't work:
>
> [eclipse 1]: X is integer(6283_2000).
> arithmetic exception in integer(6283_2000, X)
> Abort

The integer/1 function is not standardised.
In some systems it does the same as standardised truncate/1.

In (native) ECLiPSe it is a pure type conversion without rounding, see
http://www.eclipseclp.org/doc/bips/kernel/arithmetic/integer-2.html .
It exists because in (native) ECLiPSe the rounding functions
floor/1, ceiling/1, round/1, truncate/1 return the argument type,
without attempting type conversion.


>
> On the other hand it seems that SWI-Prolog
> does it correctly:
>
> Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.21)
>
> ?- X is integer(6283 rdiv 2000).
> X = 3.
>
> ?- X is integer((- 6283) rdiv 2000).
> X = -3.

This is the same as what truncate/1 does.


>
> Interesting twist, the misterious function fix/1 in
> ECLiPSe Prolog does it, I didn't find a documentation,

It's deprecated, see
http://www.eclipseclp.org/doc/bips/kernel/arithmetic/fix-2.html


Cheers,
Joachim

j4n bur53

unread,
Feb 13, 2020, 3:46:01 AM2/13/20
to
Was using ECLiPSe Prolog without some -L option.
Do I need to import some module, to get integer/1
evaluable function visible?

Joachim Schimpf schrieb:

Mostowski Collapse

unread,
Feb 13, 2020, 5:36:01 AM2/13/20
to
Ok I see, its there but not working like
in SWI-Prolog, and not a true substitute for fix/1:

[eclipse 1]: X is integer(5_1).
X = 5
Yes (0.00s cpu)

[eclipse 2]: X is integer(11_2).
arithmetic exception in integer(11_2, X)
Abort

On the other hand both fix/1 and SWI-Prolog integer/1:

ECLiPSe Prolog:

[eclipse 3]: X is fix(5_1).
X = 5
Yes (0.00s cpu)

[eclipse 4]: X is fix(11_2).
X = 5
Yes (0.00s cpu)

SWI-Prolog (small problem now, SWI-Prolog does round):

Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.21)

?- X is integer(5 rdiv 1).
X = 5.

?- X is integer(11 rdiv 2).
X = 6.

On the other hand, for example YAP doesn't do round:

YAP 6.3.3 (i686-mingw32): Sun Jan 20 18:27:56 GMTST 2013

?- X is integer(5 rdiv 1).
X = 5

?- X is integer(11 rdiv 2).
X = 5

What the hell...

Mostowski Collapse

unread,
Feb 13, 2020, 6:26:14 AM2/13/20
to
Its seems that Ulrich Neumerkel has problems grapsing
the FPU semantics. Lets make an example:

/* with FPU semantics */
?- X is truncate(3.0E100).
X = 3.0E100

/* with big num semantics */
?- X is integer(3.0e100).
X = 299999999999999985344178410670684
7048562051886831693752693714362110399
5064698733443536124752361947136

Or lets inspect the source code. My latest
revision, for the FPU semantics, reads as follows:

private static Number truncate(Number m) {
} else if (m instanceof Double) {
double d = m.doubleValue();
return TermAtomic.makeDouble(
(d < 0 ? Math.ceil(d) : Math.floor(d)));

I had a slightly different code, but I guess
this code is more efficient.

Mostowski Collapse

unread,
Feb 13, 2020, 6:34:34 AM2/13/20
to
Brain teaser for Ulrich Neumerkel. Which one
uses more memory? The float or the int result?

Which one is faster in later evaluation steps?
The float or the int result?

Why does ECLiPSe Prolog and Jekejeke Prolog
have FPU semnatics?

Mostowski Collapse

unread,
Feb 13, 2020, 7:22:04 AM2/13/20
to
Oho, after all these years. There are still
bugs in my system. In ECLiPSe Prolog I get:

[eclipse 1]: X is round(3.0E100).
X = 3e+100
Yes (0.00s cpu)

My old version of my system:

Jekejeke Prolog 4, Laufzeitbibliothek 1.4.2

?- X is round(3.0E100).
X = 9.223372036854776E18

My new version of my system:

Jekejeke Prolog 4, Runtime Library 1.4.3

?- X is round(3.0E100).
X = 3.0E100

LoL

Mostowski Collapse

unread,
Feb 13, 2020, 7:57:21 AM2/13/20
to
Understanding floats is the most challenging
thing it seems for Prologers, especially bureaucrats
like Ulrich Neumerkel which seem to lack

mathematical immagination. But again
again a floating point is only:

binary(U,S) = rdiv(U,2^S)

Or more precisely, taking into account
negative scale:

binary(U,S) = rdiv(U*2^-min(0,S),2^max(0,S))

Brain teaser II, is there some loss, if we
truncate to float instead to integer result?
Obviously not, check yourself, nothing is lost:

[eclipse 1]: X is truncate(3.0E100).
X = 3e+100
Yes (0.00s cpu)

[eclipse 2]: X is fix(truncate(3.0E100)).
X = 29999999999999998534417841067068470485
620518868316937526937143621103995064698733
443536124752361947136
Yes (0.00s cpu)

[eclipse 3]: X is fix(3.0E100).
X = 29999999999999998534417841067068470485
620518868316937526937143621103995064698733
443536124752361947136
Yes (0.00s cpu)

You only get loss later, if you use float add
etc... Its the same like change sign, which does
also not some rounding and which confused the

new comer on SWI-Prolog discourse. But you can
control this, by either using truncate/1 or
integer/1, in those Prolog systems that have both.

By choosing early float or integer, you can
control later what the operations do. Its similar
like breal/1 example, only without interval.

A Prolog system that cannot control this, will
unnecessarely promote integers, where its not
necessary. Using float/1 after the truncate/1

is also a waste of resources, because you have
an unncessary big num intermediate result. A float
number that is large carries the exact same

information as its big num counterpart, it only
does so in a much more compact form. This should be
in fact not much a brain teaser.

Mostowski Collapse

unread,
Feb 13, 2020, 8:26:35 AM2/13/20
to
The big num representation would not
blow up, if big nums had some representation
that would account for low bit zeros.

But many big num representations don't
do that. Because this would again blow
up the representation, extra info

would be needed. The GMP bignums seem
only to have a possily over allocated
array:

typedef struct
{
int _mp_alloc; /* Number of *limbs* allocated and pointed
to by the _mp_d field. */
int _mp_size; /* abs(_mp_size) is the number of limbs the
last field points to. If _mp_size is
negative this is a negative number. */
mp_limb_t *_mp_d; /* Pointer to the limbs. */
} __mpz_struct;

If you convert 3.0E100 to such a big
num, you will have a lot memory bytes
filled with zeros. You can see that here:

?- X is integer(3.0E100), atom_integer(Y,2,X).
X = 2999999999999999853441784106706847048562
05188683169375269371436211039950646987334435
36124752361947136,

Y = '1101101101110100000111011100001011111001001
010011101100000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000'

LoL

Mostowski Collapse

unread,
Feb 13, 2020, 9:29:21 AM2/13/20
to
Maybe the brain cancer is caused because
Ulrich Neumerkel confuses real numbers with
floating points numbers.

Also the gibberish around CLP(FD) is beyond
comprehension. Even with CLP(FD) you will
never be able to represent a real

number on the computer, all you can
do is anyway work with floating point numbers,
or solve these few cases where a symbolic

solution is possible.

Mostowski Collapse

unread,
Feb 13, 2020, 9:35:15 AM2/13/20
to
With floating point or fixed point numbers.
Which are both in effect subsets of the

rational numbers. Which are countable,
whereas the real numbers are uncountable.

Mostowski Collapse

unread,
Feb 13, 2020, 4:44:30 PM2/13/20
to
This is also a nice discrepancy. BigNum to float, i.e. the float/1
evaluable function. Should it use HALF_EVEN?

With HALF_EVEN:

SICStus 4.5.1 (x86_64-win32-nt-4)
?- X is truncate(float(3*10^23)).
X = 300000000000000008388608

Jekejeke Prolog 4, Runtime Library 1.4.2
?- X is integer(float(3*10^23)).
X = 300000000000000008388608

Without HALF_EVEN:

YAP 6.3.3 (i686-mingw32)
?- X is truncate(float(3*10^23)).
X = 299999999999999974834176

SWI-Prolog (threaded, 64 bits, version 8.1.21)
?- X is truncate(float(3*10^23)).
X = 299999999999999974834176.

Mostowski Collapse

unread,
Feb 13, 2020, 4:46:10 PM2/13/20
to
Now I am a little disappointed, for
ECLiPSe Prolog I get:

[eclipse 3]: X is fix(float(3*10^23)).
X = 299999999999999974834176
Yes (0.00s cpu)

Mostowski Collapse

unread,
Feb 13, 2020, 5:22:12 PM2/13/20
to
commercial rounding is also fun.

Without Commercial Rounding:

SICStus 4.5.1 (x86_64-win32-nt-4)
?- X is round(-0.5).
X = 0

Version 7.0 #52 (x86_64_nt)
[eclipse 7]: X is round(-0.5).
X = -0.0

With Commercial Rounding:

SWI-Prolog (threaded, 64 bits, version 8.1.21)
?- X is round(-0.5).
X = -1.

Jekejeke Prolog 4, Runtime Library 1.4.2
?- X is round(-0.5).
X = -1.0

Mostowski Collapse

unread,
Feb 13, 2020, 6:19:57 PM2/13/20
to
Was checking whether rationalize uses a
relative threshold or an absolute threshold.

My guess for SWI-Prolog the threshold is
absolute. Otherwise 1/3 and 1/(3*2^32) would
have similar rationalization:

But this is not the case:

?- X is 1/(3*2^32), Y is rationalize(X).
X = 7.761021455128987e-11,
Y = 1 rdiv 12884895744.

If it were a relative error aka ULP, it could
return 1 rdiv 12884901888.

Moreover I get a bomb in the other Prolog system:

[eclipse 6]: X is 1/(3*2^32), Y is rationalize(X).
Fatal signal (signal=8)
Segmentation violation - possible reasons are:
- a faulty external C function
- certain operations on circular terms
- machine stack overflow
- an internal error in ECLiPSe
ECLiPSe may have become unstable, restart recommended
Abort

Mostowski Collapse

unread,
Feb 14, 2020, 10:10:46 AM2/14/20
to
Thats also a funny bug:

YAP 6.3.3 (i686-mingw32)
?- X is 3*2^32.
X = 12884901888
?- X is 1 rdiv (3*2^32).
%%% hangs

Mostowski Collapse

unread,
Feb 14, 2020, 10:33:05 AM2/14/20
to
Here is a new approach to rational numbers
in our Prolog system:

Preview: New module "ratio" for Prolog rational numbers. (Jekejeke)
https://gist.github.com/jburse/13b6f57c6e043a12befda681868f55ea#gistcomment-3177068

We managed to extend the rational numbers
to these evaluable functions:

gcd/3
lcm/3
(//)/3
(rem)/3
(div)/3
(mod)/3

There is a new approach involves multi-argument
indexing and rational numbers are optional. Each
module can decided whether it imports library(

arithmetic/ratio) or not. We are still battling a
4-fold performance degradation in ordinary numbers
when rational numbers are enabled.

We do attribute this degradation not only to the
fact that there is one multi-argument indexing
in front of every arithmetic function and predicate

now. There are also other factors such that the
arithmetic functions are now predicates and are
therefore bridged while evaluating. We might

introduce a clause format, so that we can define
evaluables more directly.

Mostowski Collapse

unread,
Feb 14, 2020, 4:31:44 PM2/14/20
to
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 evaluable functions float_integer_part/1 and
float_fractional_part/2 do not refer to this

section. They refer to the external decimal representation.

Am Dienstag, 11. Februar 2020 23:14:45 UTC+1 schrieb Kym Horsell:
> Mostowski Collapse <burs...@gmail.com> wrote:
> > Toying around with new BigDecimal rounding. Unfortunately
> > I don't have yet float32 or float64 rounding. But can
> > simulate float64 via decimal with 17 digits.
>
> The underlying base of the arithmetric can make a big diff.
> I'm fairly sure this is covered in the classic Knuth volumes.
> His "Mix" conceptual machine was binary & decimal (like
> "many" Big Irons were back in the day :) and I think I remember
> did some of his error analysis of it.
>
> > Decimals behaves slightly different. Here is what
> > float64 does, from ECLiPSe Prolog:
> >
> > [eclipse 3]: T is atan(breal(1)), PI is T+T+T+T.
> > T = 0.78539816339744817__0.78539816339744839
> > PI = 3.1415926535897922__3.141592653589794
> > Yes (0.00s cpu)
> >

Mostowski Collapse

unread,
Feb 14, 2020, 4:39:43 PM2/14/20
to
Since float_integer_part/1 and float_fractional_part/2
are pretty useless to access floating point numbers,
I just introduced these little helpers:

- fp_exponent(X):
If X is a number then the function returns its exponent.
- fp_mantissa(X):
If X is a number then the function returns its mantissa.
- fp_radix(X):
If X is a number then the function returns its radix.

These little helpers can do magic. At least I
can already do a rational/1 evaluable function
for my new rational numbers. Here are some

example runs:

/* integer*/
?- X is rational(31415).
X = 31415

/* float32 */
?- X is rational(0f3.1415).
X = rat(6588203, 2097152)

/* float64 */
?- X is rational(3.1415).
X = rat(7074029114692207, 2251799813685248)

/* decimal */
?- X is rational(0d3.1415).
X = rat(6283, 2000)

Cool!

Mostowski Collapse

unread,
Feb 15, 2020, 11:48:20 AM2/15/20
to
Ok, SWI-Prolog 8.1.22 is out. Thats sporty!
I like that! So what are the remaining
work areas?

- Type Checks I: I guess I need to rename my
rational/1 to ratnum/1. Currently SWI-Prolog
says this here (was already there in 8.1.21):

?- rational(8).
true.

But I want also a predicate that tells me
that denominator is a unit.

- Rational API: Lets see what is missing on
our side, rational/3, numerator/2 and
denominator/2. The nice thing about

keeping our compound approach. All the
non-compound approach that has ratnums as
objects will work in our system,

since the non-compound approach needs
a rational API, and we simply can provide
it as well.

- Type Check II: atomic, number and friends.
I guess in our case we also need to change
compound. Basically we could add these

predicates to our library(arithmetic/ratio),
and override them there. Not yet sure whether
maybe put into a separate module.

The end result will be possibly not the
same as in SWI-Prolog. To be consequential
would need to override functor/3, arg/3,

=../2 etc.. as well.

- Sorting/Aggregates: I had the idea to introduce an
arithmetic_compare/3 but I don't like the name,
so I guess I will go for number_compare/3. And

then allow for a comparator parameter in sort
and friends. Again the end result will be possibly
not the same as in SWI-Prolog. Even SICStus Prolog

does have rat/2 and not the new SWI-Prolog ratnum
objects.

- Complex Numbers: Why not do complex numbers as well,
while we are at it. It would suffer from the
same performance penality we are still observing,

and besides that there is also the issue of
ordering of the multi-index rules. Maybe should
study how Julia programming language

solves the issue.

- Interval Artithmetic: Why not do interval arithmetic
as well, while are at it. For issues see
complex numbers.

Mostowski Collapse

unread,
Feb 17, 2020, 9:00:51 AM2/17/20
to
One sanity check, does tail recursion still work.
I made a little test with this code:

:- use_module(library(arithmetic/ratio)). /* only needed in my system */
count(N) :- N =< 0, !.
count(N) :- M is N-1, count(M).

I think there is some potential, but I don't
know how to realize it yet. I get this result
in SWI-Prolog:

SWI-Prolog (threaded, 64 bits, version 8.1.22)

?- time(count(10000000)).
% 20,000,001 inferences, 1.340 CPU in 1.359 seconds (99% CPU, 14927646 Lips)
true.

?- time(count(10000000r3)).
% 6,666,669 inferences, 3.245 CPU in 3.337 seconds (97% CPU, 2054341 Lips)
true

So a factor of 2x between natural number call
and rational number call. In my system its
much slower, but the factor is smaller ca. 1x:

Jekejeke Prolog 4, Runtime Library 1.4.3

?- time(count(10000000)).
% Up 15,020 ms, GC 132 ms, Threads 14,771 ms (Current 02/17/20 14:58:37)
Yes

?- time(count(rat(10000000,3))).
% Up 16,396 ms, GC 142 ms, Threads 16,118 ms (Current 02/17/20 14:58:57)
Yes

Thats something interesting.

Mostowski Collapse

unread,
Feb 17, 2020, 9:04:38 AM2/17/20
to
Maybe I also get a higher factor, if
the dispatch overhead were lower. Need
to really investigate in making the

dispatch overhead disappear.

Mostowski Collapse

unread,
Feb 18, 2020, 6:52:18 AM2/18/20
to
So experimented with a suitable infix operator
for rational numbers. What was quite disappointing,
I could not force 'r' to omit spaces around it:

?- X is 4 rdiv 6.
X = 4 r 6

Even my flags sys_nspl (no space left) and sys_nspr
(no space right) couldn't do anything, since also
token aliasing is prevented while term writing,

and 4 and r would alias, since tokens for this
purpose are defined much more lax than what the Prolog
syntax says. This is to be open for future extensions,

like radix=36 which would consume a letter 'r'.

Mostowski Collapse

unread,
Feb 18, 2020, 6:55:06 AM2/18/20
to
So I have ultimately opted for operator # to
represent rational numbers. This operator has
the advantage that it doesn’t need spaces around

when used with numbers, and its the same operator
as in Coq theorem prover rational number theory.
https://coq.inria.fr/library/Coq.QArith.QArith_base.html

In my system it now works as follows (preview):

Jekejeke Prolog 4, Runtime Library 1.4.3

?- X is 4 rdiv 6.
X = 2#3
?- X = 0x111#0x11111.
X = 273#69905

SWI-Prolog cannot do the radix thingy:

SWI-Prolog (threaded, 64 bits, version 8.1.22)

?- X is 4 rdiv 6.
X = 2r3.
?- X = 0x111r11111.
ERROR: Syntax error: Operator expected

But I guess having hex, binary, octal rational
numbers is not extremly important. I didn’t check
yet ECLiPSe, I only remember that LISP allowed

hex etc… See also:
http://www.lispworks.com/documentation/lw50/CLHS/Body/02_cbab.htm

Mostowski Collapse

unread,
Feb 18, 2020, 9:03:21 AM2/18/20
to
Some clarification, its an operator and
not a number syntax extension. Its effectively
defined as (maybe should change to 55 like Coq?):

:- op(100,xfx,#).

I also thought about some clash. But if I
remember well there is no clash with CLP(FD),
‘#’ is only used unary:

?- set_prolog_flag(clpfd_monotonic, true).
true.
?- #(X) #= #(Y) + #(Z).
#(Y)+ #(Z)#= #(X).

https://www.swi-prolog.org/pldoc/man?section=clpfd-monotonicity

The only binary operator clash is in SICStus Prolog
where it is used as xor, but corrigendum of ISO Prolog
says xor and not #.

Another clash is in CLP(B) where the operator is
used for xor. Don’t know yet what to do with the
CLP(B) clash.

Mostowski Collapse

unread,
Feb 18, 2020, 9:16:53 AM2/18/20
to
Nope, its not anymore a problem in SICStus:
xor(X,Y) since release 4.3, ISO
https://sicstus.sics.se/sicstus/docs/latest4/html/sicstus.html/ref_002dari_002daex.html#ref_002dari_002daex

Nice!

Mostowski Collapse

unread,
Feb 18, 2020, 9:46:15 AM2/18/20
to
Oho, radix 36 is still available:

SWI-Prolog (threaded, 64 bits, version 8.1.22)

?- X = 36'rrr.
X = 35991.

Using letter r might challenge token tooling.
Might also explain why radixed numbers and rational
numbers dont work together when the letter r

is used as a numerator denominator separator.

Mostowski Collapse

unread,
Feb 18, 2020, 12:12:03 PM2/18/20
to
The CLP(B) issue could be solved, by simply
removing (#)/2 from CLP(B). Its anyway redundant:

Expr =\= Expr disequality (same as #)
https://www.swi-prolog.org/pldoc/man?section=clpb

Mostowski Collapse

unread,
Feb 18, 2020, 5:00:56 PM2/18/20
to
One more glitch in the matrix. SWI-Prologs
implementation of rational numbers challenges
ECLiPSe Prologs implementation of rational

numbers. In ECLiPSe Prolog rational numbers
are not normalized towards ordinary integers.
So ECLiPSe Prolog has the option

to do the following:

ECLiPSe Version 7.0 #52 (x86_64_nt)

[eclipse 1]: X is 2_1^(-5).
X = 1_32
Yes (0.00s cpu)

[eclipse 2]: X is 2^(-5).
X = 0.03125
Yes (0.00s cpu)

Now I think this SWI-Prolog behaviour is wrong:

SWI-Prolog (threaded, 64 bits, version 8.1.22)

?- X is 2r1^(-5).
X = 0.03125.

Mostowski Collapse

unread,
Feb 18, 2020, 5:02:55 PM2/18/20
to
In my system I can solve the problem.
First of all without rational numbers,
negative exponent is anyway not allowed

for (^)/2, namely I get:

?- X is 2^(-5).
Error: Argument should be positive or 0.
is/2

And when rational numbers are present,
I get as expected:

?- use_module(library(arithmetic/ratio)).
% 1 consults and 0 unloads in 64 ms.
Yes

?- X is 2^(-5).
X = 1#32

I sill have the option to use the other
power operator, if I desire a float result:

?- X is 2**(-5).
X = 0.03125

Mostowski Collapse

unread,
Feb 18, 2020, 5:10:59 PM2/18/20
to
Here is a number where it matters,
where the rational number result is
more exact:

[eclipse 3]: X is 10_1^(-5).
X = 1_100000
Yes (0.00s cpu)

[eclipse 4]: X is 10^(-5).
X = 1.0000000000000006e-5
Yes (0.00s cpu)

Mostowski Collapse

unread,
Feb 19, 2020, 3:35:40 AM2/19/20
to
This flag doesn’t solve the problem:

set_prolog_flag(prefer_rationals, true)

In ECLiPSe Prolog I have rationals and floats side by side:

ECLiPSe Version 7.0 #52 (x86_64_nt)

[eclipse 1]: X is 2_1^(-5).
X = 1_32
Yes (0.00s cpu)

[eclipse 2]: X is 2^(-5).
X = 0.03125
Yes (0.00s cpu)

With the SWI-Prolog flag I still dont
get float and rational side by side:

SWI-Prolog (threaded, 64 bits, version 8.1.22)

?- set_prolog_flag(prefer_rationals, true).
true.

?- X is 2^(-5).
X = 1r32.

?- X is 2**(-5).
X = 1r32.

The flag also affects (**)/2.

Mostowski Collapse

unread,
Feb 19, 2020, 3:43:23 AM2/19/20
to

Maybe a third flag value inbetween
prefer_rationals=true and
prefer_rationals=false would do?

Mostowski Collapse

unread,
Feb 19, 2020, 5:57:03 AM2/19/20
to
I don't think the matter has something
to do with ISO core standard. Its rather
an accident that (^)/2 went into the

ISO core standard. I don't find any reference
to rational numbers in connection (^)/2.

But one will need all the float operations for
interval arithmetic. If interval arithmetic
is implemented with flags. How would one retain

something like:

?- current_prolog_flag(float_rounding, Safe),
set_prolog_flag(float_rounding, Mode),
X is Y**Z,
set_prolog_flag(float_rounding, Safe).

Changing the the prefer_rationals flag as well
each time? Or inserting float/1 conversions
each time. It can make things slower.

j4n bur53

unread,
Feb 19, 2020, 6:10:17 AM2/19/20
to
Here is more evidence that (^)/2 wasn't
conceived with rational numbers in mind:

"Provide a "raise to integer power" operation which
result is the same type as its left operand and which
in the case of integral left operands is limited to
non-negative right operands. Whether this is
called (^)/2 or something else is less important;
there are arguments either way."

An Elementary Prolog Library - DRAFT 19, February 2015
http://www.cs.otago.ac.nz/staffpriv/ok/pllib.htm

Rational numbers in mind have two departures:

- The result is not strictly the type of the left
argument, in case of 2^(-5) the result goes from
left argument integer, to result rational number.
- The exponent is not non-negative, in case of
2^(-5) we have a negative right argument

Plus the rational number view of (^)/2 has the
benefit that it could complement (**)/2, which could
keep the float number view.

Mostowski Collapse schrieb:

Mostowski Collapse

unread,
Feb 22, 2020, 2:02:00 PM2/22/20
to
Whats the hardest part of rational numbers?
Some challenge is surely this identity:

/* for any X and Y, Y =\= 0 and X/Y in float range */

float(X rdiv Y) =:= X/Y

Ether float/1 might defect or (/)/2 might
defect or both. My system is no better,

but I havent released the new rational number
support yet. Here is what can go wrong:

SWI-Prolog (threaded, 64 bits, version 8.1.22)

?- X is 363692165478669/6325070415853456823515
4795849661658452986453051294411986531674383571
9811149985459037376199066991014047459618325990
0372230931523043306046152094168748148078435047
4195086426987926395908669404130106637427399522
7328339256273385702164683181572986403623613565
0314266011211548510419206725953204130822734645
187695728365866909171712.

?- X is float(363692165478669 rdiv 63250704158
5345682351547958496616584529864530512944119865
3167438357198111499854590373761990669910140474
5961832599003722309315230433060461520941687481
4807843504741950864269879263959086694041301066
3742739952273283392562733857021646831815729864
0362361356503142660112115485104192067259532041
30822734645187695728365866909171712).
X = 5.750009747987844e-308.

A tamer goal could be to only have this
axiom satisfied, for rational/1 output:

/* for any X and Y, Y =\= 0 and X/Y in float range,
and XrY result from rational(F) for some float */

float(X rdiv Y) =:= X/Y

Am Montag, 3. Juli 2017 23:14:04 UTC+2 schrieb Mostowski Collapse:
> Dear All,
>
> If you want rational arithmetic(*), and you do the following:
>
> ?- A is 4 rdiv 1/3.
> A = 1.3333333333333333.
>
> This is anyway wrong. What you need to do is:
>
> ?- A is (4 rdiv 1) rdiv 3.
> A = 4 rdiv 3.
>
> Richard O'Keefe idea is already realized, you don't need to do anything anymore, since rdiv/2 is not only a constructor but also an operation, you can do the following, try it for yourself with SWI-Prolog:
>
> Welcome to SWI-Prolog (threaded, 64 bits, version 7.5.8)
> SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
>
> ?- X is (1 rdiv 4) rdiv (1 rdiv 2).
> X = 1 rdiv 2.
>
> ?- X is (1 rdiv 2) rdiv (1 rdiv 4).
> X = 2.
>
> So if you use rdiv/2 instead of (/)/2 you program runs rationals and not floats. I don't see any possility to merge rdiv/2 and (/)/2 into one operator, this is impossible I guess. Now putting side by side the division and the power operator, we could require:
>
> Datatype Approach:
> ============
> datatype division power
> float: (/)/2 (^)/2
> rational: (rdiv)/2 (^)/2 /* name clash */
>
> But we run into the problem that (^)/2 for floats is not the same as (^)/2 for rationals, we would need two different operators. When I posted this feature request, I might have had this idea. Meanwhile I have abandoned the above schema in favor of another schema.
>
> The new schema is based on different contexts and not on different datatypes, the advantage is that I don't need a (rdiv)/2 operator anymore:
>
> Context Approach:
> ============
> context division power
> float: (/)/2 (^)/2
> rational: (/)/2 (^)/2
>
> So I must appologize, since I issued a datatype feature request, whereby in the end I implemented myself a context feature, much later after I have issued this feature request here. I implemented the context feature via my new library(groebner/generic).
>
> The advantages of the context approach is as follows:
>
> Typing rdiv/2 is unnatural, its very clumsy, its much easier to type (/)/2.
> Programs can be easily moved from one context into anthor, we do not need to replace (/)/2 by (rdiv)/2.
> The context approach is also followed by CLP(Q), in CLP(Q) we do not need to write { X = Y rdiv Z } instead we write naturally { X = Y / Z }, right?
>
> Hope this helps!
>
> (*)
> https://github.com/SWI-Prolog/swipl-devel/issues/185

Mostowski Collapse

unread,
Feb 27, 2020, 4:25:42 AM2/27/20
to
SWI-Prologs new rational numbers require changes
in the Prolog interpreter, down to the SWI-Prolog
specific garbage collector.

My current realization of rational numbers, not
yet published, doesn't need that yet, since it
uses traditional Prolog terms.

Nevertheless something similar might happen in
the future. I already changed some of the ALU
infrastructure a little bit. The word "number"

has now two meanings (the choice if strict
is a little arbitrary, might change in the
future or not needed anymore):

type_error.number=Argument should be a
Java number, found %1$s.
type_error.strict=Argument should be a
Prolog number, found %1$s.

The Java number is a the Java class Number under
the hood. The Prolog number are all Java class Number
derived classes that are knowingly used as

numbers so far in the Prolog interpreter. Rational
numbers could become a Java class Number derived
class, but there are a lot of hurdles to

yet be solved. I am not yet sure whether a plugable
framework is possible somehow. Problem is really
sorting and friends, which gets simpler if

rational numbers are not compounds but Java numbers.
It is loading more messages.
0 new messages