1 | % (c) 2009-2024 Lehrstuhl fuer Softwaretechnik und Programmiersprachen, | |
2 | % Heinrich Heine Universitaet Duesseldorf | |
3 | % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html | |
4 | ||
5 | % This module contains arithmetic that also supports the symbol inf | |
6 | % The operator infis/2 can be used analogously to the standard Prolog operator is/2. | |
7 | % Currently supported arithmetic operations are +, -, *, min, max | |
8 | ||
9 | :- module(inf_arith, [infis/2,infless/2, | |
10 | infgreaterequal/2, infgreater/2, infdec/2, infinc/2, infdec_if_positive/2, infmin/3, infmax/3, | |
11 | block_inf_greater/2, block_inf_greater_equal/2 | |
12 | ]). | |
13 | ||
14 | :- use_module(module_information). | |
15 | :- module_info(group,kernel). | |
16 | :- module_info(description,'This module contains arithmetic that also supports the symbol inf.'). | |
17 | ||
18 | :- use_module(self_check). | |
19 | ||
20 | :- op( 700, xfx, infis). | |
21 | ||
22 | Res infis Expr :- infis2(Expr,R), R=Res. | |
23 | ||
24 | ||
25 | :- assert_must_succeed(( infis(R,22+inf), R==inf )). | |
26 | :- assert_must_succeed(( infis(R,22+21), R==43 )). | |
27 | :- assert_must_succeed(( infis(R,-(22+21)*(-1)), R==43 )). | |
28 | :- assert_must_succeed(( infis(R,(-inf)+21), R==(-inf) )). | |
29 | :- assert_must_succeed(( infis(R,22+(-inf)), R==(-inf) )). | |
30 | :- assert_must_succeed(( infis(R,22-(-inf)), R==inf )). | |
31 | :- assert_must_succeed(( infis(R,22-21), R==1 )). | |
32 | :- assert_must_succeed(( infis(R,(-inf)-21), R==(-inf) )). | |
33 | :- assert_must_succeed(( infis(R,inf-21), R==inf )). | |
34 | :- assert_must_succeed(( infis(R,22*inf), R==inf )). | |
35 | :- assert_must_succeed(( infis(R,inf//22), R==inf )). | |
36 | :- assert_must_succeed(( infis(R,inf//(-22)), R==(-inf) )). | |
37 | :- assert_must_succeed(( infis(R,(-44)//22), R==(-2) )). | |
38 | ||
39 | ||
40 | infis2(A, A) :- number(A),!. | |
41 | infis2(inf, inf). | |
42 | infis2(-A, Res) :- infis2(A,Ac), infnegate(Ac,Res). | |
43 | infis2(A+B, Res) :- infis2(A,Ac), infis2(B,Bc), infadd(Ac,Bc,Res). | |
44 | infis2(A-B, Res) :- infis2(A,Ac), infis2(-B,Bc), infadd(Ac,Bc,Res). | |
45 | infis2(A*B, Res) :- infis2(A,Ac), infis2(B,Bc), infmult(Ac,Bc,Res). | |
46 | infis2(A//B, Res) :- infis2(A,Ac), infis2(B,Bc), infdiv(Ac,Bc,Res). | |
47 | infis2(min(A,B), Res) :- | |
48 | infis2(A,Ac), infis2(B,Bc), infmin(Ac,Bc,Res). | |
49 | infis2(max(A,B), Res) :- | |
50 | infis2(A,Ac), infis2(B,Bc), infmax(Ac,Bc,Res). | |
51 | ||
52 | :- assert_must_succeed(( infisnegative(-2) )). | |
53 | :- assert_must_succeed(( infisnegative(-inf) )). | |
54 | :- assert_must_fail(( infisnegative(inf) )). | |
55 | :- assert_must_fail(( infisnegative(0) )). | |
56 | ||
57 | infisnegative(-inf) :- !. | |
58 | infisnegative(inf) :- !,fail. | |
59 | infisnegative(X) :- X<0. | |
60 | ||
61 | infnegate(inf,-inf) :- !. | |
62 | infnegate(-inf,inf) :- !. | |
63 | infnegate(A,B) :- B is -A. | |
64 | ||
65 | :- assert_must_succeed(( infadd(22,inf,R), R==inf )). | |
66 | :- assert_must_succeed(( infadd(22,21,R), R==43 )). | |
67 | :- assert_must_succeed(( infadd((-inf),21,R), R==(-inf) )). | |
68 | infadd(A,B,R) :- | |
69 | ( infisnegative(A) -> | |
70 | infnegate(A,Apos), | |
71 | ( infisnegative(B) -> | |
72 | infnegate(B,Bpos), | |
73 | infadd(Apos,Bpos,Rneg), | |
74 | infnegate(Rneg,R) | |
75 | ; | |
76 | infsub2(B,Apos,R)) | |
77 | ; | |
78 | ( infisnegative(B) -> | |
79 | infnegate(B,Bpos), | |
80 | infsub2(A,Bpos,R) | |
81 | ; | |
82 | infadd2(A,B,R))). | |
83 | infadd2(inf,_,inf) :- !. | |
84 | infadd2(_,inf,inf) :- !. | |
85 | infadd2(A,B,R) :- R is A+B. | |
86 | ||
87 | % don't know what is inf - inf | |
88 | infsub2(inf,B,inf) :- !, B \== inf. | |
89 | infsub2(_,inf,-inf) :- !. | |
90 | infsub2(A,B,R) :- R is A-B. | |
91 | ||
92 | infmult(A,B,R) :- | |
93 | ( infisnegative(A) -> | |
94 | infnegate(A,Aneg), | |
95 | infmult(Aneg,B,Rneg), | |
96 | infnegate(Rneg,R) | |
97 | ; infisnegative(B) -> | |
98 | infnegate(B,Bneg), | |
99 | infmult(A,Bneg,Rneg), | |
100 | infnegate(Rneg,R) | |
101 | ; | |
102 | infmult2(A,B,R)). | |
103 | infmult2(inf,_,inf) :- !. | |
104 | infmult2(_,inf,inf) :- !. | |
105 | infmult2(A,B,R) :- R is A*B. | |
106 | ||
107 | infdiv(A,B,R) :- | |
108 | ( infisnegative(A) -> | |
109 | infnegate(A,Aneg), | |
110 | infdiv(Aneg,B,Rneg), | |
111 | infnegate(Rneg,R) | |
112 | ; infisnegative(B) -> | |
113 | infnegate(B,Bneg), | |
114 | infdiv(A,Bneg,Rneg), | |
115 | infnegate(Rneg,R) | |
116 | ; | |
117 | infdiv2(A,B,R)). | |
118 | infdiv2(inf,B,inf) :- !,B \== inf. | |
119 | infdiv2(_,inf,0) :- !. | |
120 | infdiv2(A,B,R) :- R is A//B. | |
121 | ||
122 | :- assert_must_succeed( infgreaterequal(inf,inf)). | |
123 | :- assert_must_succeed( infgreaterequal(inf,100)). | |
124 | :- assert_must_succeed( infgreaterequal(2000,100)). | |
125 | :- assert_must_fail( infgreaterequal(2000,inf)). | |
126 | :- assert_must_fail( infgreaterequal(1999,2000)). | |
127 | :- assert_must_fail( infgreaterequal(1999,inf_overflow)). | |
128 | :- assert_must_fail( infgreaterequal(inf_overflow,inf)). | |
129 | :- assert_must_succeed( infgreaterequal(inf,inf_overflow)). | |
130 | :- assert_must_succeed( infgreaterequal(inf_overflow,2000)). | |
131 | :- assert_must_succeed( infgreaterequal(inf_overflow,inf_overflow)). | |
132 | infgreaterequal(A,B) :- (A=B -> true ; infgreater(A,B)). | |
133 | ||
134 | infgreater(A,B) :- infless(B,A). | |
135 | infless(inf,_) :- !,fail. | |
136 | infless(inf_overflow,X) :- !, X=inf. | |
137 | infless(_,-inf) :- !,fail. | |
138 | infless(-inf,_X) :- !. | |
139 | infless(_X,inf) :- !. | |
140 | infless(_X,inf_overflow) :- !. %_X=fail caught above | |
141 | infless(A,B) :- A<B. | |
142 | ||
143 | :- assert_must_succeed(( infmax(22,inf,R), R==inf )). | |
144 | :- assert_must_succeed(( infmax(22,21,R), R==22 )). | |
145 | :- assert_must_succeed(( infmax((-inf),21,R), R==21 )). | |
146 | :- assert_must_succeed(( infmax((-inf),inf,R), R==inf )). | |
147 | ||
148 | infmax(A,B,R) :- | |
149 | (infgreater(A,B) -> A=R ; B=R). | |
150 | ||
151 | ||
152 | :- assert_must_succeed(( infmin(22,inf,R), R==22 )). | |
153 | :- assert_must_succeed(( infmin(22,21,R), R==21 )). | |
154 | :- assert_must_succeed(( infmin((-inf),21,R), R==(-inf) )). | |
155 | :- assert_must_succeed(( infmin((-inf),inf,R), R==(-inf) )). | |
156 | infmin(A,B,R) :- | |
157 | (infless(A,B) -> A=R ; B=R). | |
158 | ||
159 | :- assert_must_succeed(( infdec(inf,R), R==inf )). | |
160 | :- assert_must_succeed(( infdec(3,R), R==2 )). | |
161 | :- assert_must_succeed(( infdec(-inf,R), R==(-inf) )). | |
162 | infdec(inf,R) :- !, R = inf. | |
163 | infdec(inf_overflow,R) :- !, R = inf_overflow. | |
164 | infdec(-inf,R) :- !, R = -inf. | |
165 | infdec(N,N1) :- N1 is N-1. | |
166 | ||
167 | :- assert_must_succeed(( infinc(inf,R), R==inf )). | |
168 | :- assert_must_succeed(( infinc(3,R), R==4 )). | |
169 | :- assert_must_succeed(( infinc(-inf,R), R==(-inf) )). | |
170 | infinc(inf,R) :- !, R = inf. | |
171 | infinc(inf_overflow,R) :- !, R = inf_overflow. | |
172 | infinc(-inf,R) :- !, R = -inf. | |
173 | infinc(N,N1) :- N1 is N+1. | |
174 | ||
175 | :- assert_must_succeed(( infdec_if_positive(inf,R), R==inf )). | |
176 | :- assert_must_succeed(( infdec_if_positive(3,R), R==2 )). | |
177 | :- assert_must_fail(infdec_if_positive((-inf),_)). | |
178 | :- assert_must_fail(infdec_if_positive((-2),(-3))). | |
179 | infdec_if_positive(inf,R) :- !, R = inf. | |
180 | infdec_if_positive(inf_overflow,R) :- !, R = inf_overflow. | |
181 | infdec_if_positive(-inf,_) :- !, fail. | |
182 | infdec_if_positive(N,N1) :- N>0, N1 is N-1. | |
183 | ||
184 | % ------------------------ blocking versions -------------------- | |
185 | ||
186 | ||
187 | :- block block_inf_greater_equal(-,?), block_inf_greater_equal(?,-). | |
188 | block_inf_greater_equal(X,Y) :- infgreaterequal(X,Y). | |
189 | ||
190 | ||
191 | :- block block_inf_greater(-,?), block_inf_greater(?,-). | |
192 | block_inf_greater(X,Y) :- infgreater(X,Y). |