1/***
2  @groupdef stdlib.compare Comparison Builtins
3
4  These builtins implement comparison operations.
5*/
6
7/** @group stdlib.compare Return if \a x is less than \a y */
8function     bool: '<'(    $T: x,    $T: y);
9/** @group stdlib.compare Return if \a x is less than \a y */
10function var bool: '<'(var $T: x,var $T: y);
11/** @group stdlib.compare Weak comparison: true iff either \a x or \a y is absent, or both
12  occur and the value of \a x is less than the value of \a y. */
13function var bool: '<'(var opt int: x, var opt int: y) = absent(x) \/ absent(y) \/ deopt(x) < deopt(y);
14/** @group stdlib.compare Weak comparison: true iff either \a x or \a y is absent, or both
15  occur and the value of \a x is less than the value of \a y. */
16function bool: '<'(opt int: x, opt int: y) = absent(x) \/ absent(y) \/ deopt(x) < deopt(y);
17/** @group stdlib.arithmetic Weak comparison: true iff either \a x or \a y is absent, or both
18  occur and the value of \a x is less than the value of \a y. */
19function var bool: '<'(var opt float: x, var opt float: y) = absent(x) \/ absent(y) \/ deopt(x) < deopt(y);
20/** @group stdlib.arithmetic Weak comparison: true iff either \a x or \a y is absent, or both
21  occur and the value of \a x is less than the value of \a y. */
22function bool: '<'(opt float: x, opt float: y) = absent(x) \/ absent(y) \/ deopt(x) < deopt(y);
23
24/** @group stdlib.compare Return if \a x is greater than \a y */
25function     bool: '>'(    $T: x,    $T: y);
26/** @group stdlib.compare Return if \a x is greater than \a y */
27function var bool: '>'(var $T: x,var $T: y);
28/** @group stdlib.compare Weak comparison: true iff either \a x or \a y is absent, or both
29  occur and the value of \a x is greater than the value of \a y. */
30function var bool: '>'(var opt int: x, var opt int: y) = absent(x) \/ absent(y) \/ deopt(x) > deopt(y);
31/** @group stdlib.compare Weak comparison: true iff either \a x or \a y is absent, or both
32  occur and the value of \a x is greater than the value of \a y. */
33function bool: '>'(opt int: x, opt int: y) = absent(x) \/ absent(y) \/ deopt(x) > deopt(y);
34/** @group stdlib.arithmetic Weak comparison: true iff either \a x or \a y is absent, or both
35  occur and the value of \a x is greater than the value of \a y. */
36function var bool: '>'(var opt float: x, var opt float: y) = absent(x) \/ absent(y) \/ deopt(x) > deopt(y);
37/** @group stdlib.arithmetic Weak comparison: true iff either \a x or \a y is absent, or both
38  occur and the value of \a x is greater than the value of \a y. */
39function bool: '>'(opt float: x, opt float: y) = absent(x) \/ absent(y) \/ deopt(x) > deopt(y);
40
41/** @group stdlib.compare Return if \a x is less than or equal to \a y */
42function     bool: '<='(    $T: x,    $T: y);
43/** @group stdlib.compare Return if \a x is less than or equal to \a y */
44function var bool: '<='(var $T: x, var $T: y);
45/** @group stdlib.compare Weak comparison: true iff either \a x or \a y is absent, or both
46  occur and the value of \a x is less than or equal to the value of \a y. */
47function var bool: '<='(var opt int: x, var opt int: y) = absent(x) \/ absent(y) \/ deopt(x) <= deopt(y);
48/** @group stdlib.compare Weak comparison: true iff either \a x or \a y is absent, or both
49  occur and the value of \a x is less than or equal to the value of \a y. */
50function bool: '<='(opt int: x, opt int: y) = absent(x) \/ absent(y) \/ deopt(x) <= deopt(y);
51/** @group stdlib.arithmetic Weak comparison: true iff either \a x or \a y is absent, or both
52  occur and the value of \a x is less than or equal to the value of \a y. */
53function var bool: '<='(var opt float: x, var opt float: y) = absent(x) \/ absent(y) \/ deopt(x) <= deopt(y);
54/** @group stdlib.arithmetic Weak comparison: true iff either \a x or \a y is absent, or both
55  occur and the value of \a x is less than or equal to the value of \a y. */
56function bool: '<='(opt float: x, opt float: y) = absent(x) \/ absent(y) \/ deopt(x) <= deopt(y);
57
58/** @group stdlib.compare Return if \a x is greater than or equal to \a y */
59function     bool: '>='(    $T: x,    $T: y);
60/** @group stdlib.compare Return if \a x is greater than or equal to \a y */
61function var bool: '>='(var $T: x,var $T: y);
62/** @group stdlib.compare Weak comparison: true iff either \a x or \a y is absent, or both
63  occur and the value of \a x is greater than or equal to the value of \a y. */
64function var bool: '>='(var opt int: x, var opt int: y) = absent(x) \/ absent(y) \/ deopt(x) >= deopt(y);
65/** @group stdlib.compare Weak comparison: true iff either \a x or \a y is absent, or both
66  occur and the value of \a x is greater than or equal to the value of \a y. */
67function bool: '>='(opt int: x, opt int: y) = absent(x) \/ absent(y) \/ deopt(x) >= deopt(y);
68/** @group stdlib.arithmetic Weak comparison: true iff either \a x or \a y is absent, or both
69  occur and the value of \a x is greater than or equal to the value of \a y. */
70function var bool: '>='(var opt float: x, var opt float: y) = absent(x) \/ absent(y) \/ deopt(x) >= deopt(y);
71/** @group stdlib.arithmetic Weak comparison: true iff either \a x or \a y is absent, or both
72  occur and the value of \a x is greater than or equal to the value of \a y. */
73function bool: '>='(opt float: x, opt float: y) = absent(x) \/ absent(y) \/ deopt(x) >= deopt(y);
74
75/** @group stdlib.compare Return if \a x is equal to \a y */
76function     bool: '='(    $T: x,    $T: y);
77/** @group stdlib.compare Return if \a x is equal to \a y */
78function     bool: '='(opt $T: x, opt $T: y) =
79  absent(x) /\ absent(y) \/ occurs(x) /\ occurs(y) /\ deopt(x) = deopt(y);
80/** @group stdlib.compare Return if \a x is equal to \a y */
81function var bool: '='(var $T: x,var $T: y);
82/** @group stdlib.compare Return if \a x is equal to \a y */
83function var bool: '='(var opt $T: x,var opt $T: y);
84
85/** @group stdlib.compare Return if \a x is not equal to \a y */
86function     bool: '!='(    $T: x,     $T: y);
87/** @group stdlib.compare Return if \a x is not equal to \a y */
88function     bool: '!='(opt $T: x, opt $T: y) = not (x = y);
89/** @group stdlib.compare Return if \a x is not equal to \a y */
90function var bool: '!='(var $T: x, var $T: y);
91/** @group stdlib.compare Return if \a x is not equal to \a y */
92function var bool: '!='(var opt $T: x, var opt $T: y);
93
94% Special case comparison operators for integer variable and float constant
95function var bool: '<='(var int: x, float: y) = (x <= floor(y));
96function var bool: '>='(var int: x, float: y) = (x >= ceil(y));
97function var bool: '<='(float: x, var int: y) = (y >= ceil(x));
98function var bool: '>='(float: x, var int: y) = (y <= floor(x));
99
100function var bool: '<'(var int: x, float: y) = (x <= ceil(y)-1);
101function var bool: '>'(float: x, var int: y) = (y <= ceil(x)-1);
102function var bool: '>'(var int: x, float: y) = (x >= floor(y)+1);
103function var bool: '<'(float: x, var int: y) = (y >= floor(x)+1);
104
105function var bool: '='(var int: x, float: y) =
106  if ceil(y)=floor(y) then x=ceil(y) else false endif;
107function var bool: '='(float: x, var int: y) =
108  if ceil(x)=floor(x) then y=ceil(x) else false endif;
109
110function var bool: '!='(var int: x, float: y) =
111  if ceil(y)=floor(y) then x != ceil(y) else true endif;
112function var bool: '!='(float: x, var int: y) =
113  if ceil(x)=floor(x) then y != ceil(x) else true endif;
114
115function bool: '<='(int: x, float: y) = (x <= floor(y));
116function bool: '>='(int: x, float: y) = (x >= ceil(y));
117function bool: '<='(float: x, int: y) = (y >= ceil(x));
118function bool: '>='(float: x, int: y) = (y <= floor(x));
119
120function bool: '<'(int: x, float: y) = (x <= ceil(y)-1);
121function bool: '>'(float: x, int: y) = (y <= ceil(x)-1);
122function bool: '>'(int: x, float: y) = (x >= floor(y)+1);
123function bool: '<'(float: x, int: y) = (y >= floor(x)+1);
124
125function bool: '='(int: x, float: y) =
126  if ceil(y)=floor(y) then x=ceil(y) else false endif;
127function bool: '='(float: x, int: y) =
128  if ceil(x)=floor(x) then y=ceil(x) else false endif;
129
130function bool: '!='(int: x, float: y) =
131  if ceil(y)=floor(y) then x != ceil(y) else true endif;
132function bool: '!='(float: x, int: y) =
133  if ceil(x)=floor(x) then y != ceil(x) else true endif;
134
135
136/** @group stdlib.compare Return if array \a x is lexicographically smaller than array \a y */
137function     bool: '<'(array[$U] of     $T: x,array[$U] of     $T: y);
138/** @group stdlib.compare Return if array \a x is lexicographically smaller than array \a y */
139function var bool: '<'(array[$U] of var $T: x,array[$U] of var $T: y);
140/** @group stdlib.compare Return if array \a x is lexicographically greater than array \a y */
141function     bool: '>'(array[$U] of     $T: x,array[$U] of     $T: y);
142/** @group stdlib.compare Return if array \a x is lexicographically greater than array \a y */
143function var bool: '>'(array[$U] of var $T: x,array[$U] of var $T: y);
144/** @group stdlib.compare Return if array \a x is lexicographically smaller than or equal to array \a y */
145function     bool: '<='(array[$U] of     $T: x,array[$U] of     $T: y);
146/** @group stdlib.compare Return if array \a x is lexicographically smaller than or equal to array \a y */
147function var bool: '<='(array[$U] of var $T: x,array[$U] of var $T: y);
148/** @group stdlib.compare Return if array \a x is lexicographically greater than or equal to array \a y */
149function     bool: '>='(array[$U] of     $T: x,array[$U] of     $T: y);
150function var bool: '>='(array[$U] of var $T: x,array[$U] of var $T: y);
151
152/** @group stdlib.compare Return if array \a x is equal to array \a y */
153function     bool: '='(array[$T] of     int: x,array[$T] of     int: y) =
154    let {
155        array[int] of int: xx = array1d(x);
156        array[int] of int: yy = array1d(y);
157    } in
158    assert(index_sets_agree(x,y), "array index sets do not match",
159      forall (i in index_set(xx)) (xx[i]=yy[i])
160    );
161
162/** @group stdlib.compare Return if array \a x is equal to array \a y */
163function var bool: '='(array[$T] of var int: x,array[$T] of var int: y) =
164    let {
165        array[int] of var int: xx = array1d(x);
166        array[int] of var int: yy = array1d(y);
167    } in
168    assert(index_sets_agree(x,y), "array index sets do not match",
169      forall (i in index_set(xx)) (xx[i]=yy[i])
170    );
171
172/** @group stdlib.compare Return if array \a x is equal to array \a y */
173function     bool: '='(array[$T] of     bool: x,array[$T] of     bool: y) =
174    let {
175        array[int] of bool: xx = array1d(x);
176        array[int] of bool: yy = array1d(y);
177    } in
178    assert(index_sets_agree(x,y), "array index sets do not match",
179      forall (i in index_set(xx)) (xx[i]=yy[i])
180    );
181
182/** @group stdlib.compare Return if array \a x is equal to array \a y */
183function var bool: '='(array[$T] of var bool: x,array[$T] of var bool: y) =
184    let {
185        array[int] of var bool: xx = array1d(x);
186        array[int] of var bool: yy = array1d(y);
187    } in
188    assert(index_sets_agree(x,y), "array index sets do not match",
189      forall (i in index_set(xx)) (xx[i]=yy[i])
190    );
191
192/** @group stdlib.compare Return if array \a x is equal to array \a y */
193function     bool: '='(array[$T] of     set of int: x,array[$T] of     set of int: y) =
194    let {
195        array[int] of set of int: xx = array1d(x);
196        array[int] of set of int: yy = array1d(y);
197    } in
198    assert(index_sets_agree(x,y), "array index sets do not match",
199      forall (i in index_set(xx)) (xx[i]=yy[i])
200    );
201
202/** @group stdlib.compare Return if array \a x is equal to array \a y */
203function var bool: '='(array[$T] of var set of int: x,array[$T] of var set of int: y) =
204    let {
205        array[int] of var set of int: xx = array1d(x);
206        array[int] of var set of int: yy = array1d(y);
207    } in
208    assert(index_sets_agree(x,y), "array index sets do not match",
209      forall (i in index_set(xx)) (xx[i]=yy[i])
210    );
211
212/** @group stdlib.compare Return if array \a x is equal to array \a y */
213function     bool: '='(array[$T] of     float: x,array[$T] of     float: y) =
214    let {
215        array[int] of float: xx = array1d(x);
216        array[int] of float: yy = array1d(y);
217    } in
218    assert(index_sets_agree(x,y), "array index sets do not match",
219      forall (i in index_set(xx)) (xx[i]=yy[i])
220    );
221
222/** @group stdlib.compare Return if array \a x is equal to array \a y */
223function var bool: '='(array[$T] of var float: x,array[$T] of var float: y) =
224    let {
225        array[int] of var float: xx = array1d(x);
226        array[int] of var float: yy = array1d(y);
227    } in
228    assert(index_sets_agree(x,y), "array index sets do not match",
229      forall (i in index_set(xx)) (xx[i]=yy[i])
230    );
231
232/** @group stdlib.compare Return if array \a x is not equal to array \a y */
233function     bool: '!='(array[$T] of     int: x,array[$T] of     int: y) =
234    let {
235        array[int] of int: xx = array1d(x);
236        array[int] of int: yy = array1d(y);
237    } in
238    assert(index_sets_agree(x,y), "array index sets do not match",
239      exists (i in index_set(xx)) (xx[i]!=yy[i])
240    );
241
242/** @group stdlib.compare Return if array \a x is not equal to array \a y */
243function var bool: '!='(array[$T] of var int: x,array[$T] of var int: y) =
244    let {
245        array[int] of var int: xx = array1d(x);
246        array[int] of var int: yy = array1d(y);
247    } in
248    assert(index_sets_agree(x,y), "array index sets do not match",
249      exists (i in index_set(xx)) (xx[i]!=yy[i])
250    );
251
252/** @group stdlib.compare Return if array \a x is not equal to array \a y */
253function     bool: '!='(array[$T] of     bool: x,array[$T] of     bool: y) =
254    let {
255        array[int] of bool: xx = array1d(x);
256        array[int] of bool: yy = array1d(y);
257    } in
258    assert(index_sets_agree(x,y), "array index sets do not match",
259      exists (i in index_set(xx)) (xx[i]!=yy[i])
260    );
261
262/** @group stdlib.compare Return if array \a x is not equal to array \a y */
263function var bool: '!='(array[$T] of var bool: x,array[$T] of var bool: y) =
264    let {
265        array[int] of var bool: xx = array1d(x);
266        array[int] of var bool: yy = array1d(y);
267    } in
268    assert(index_sets_agree(x,y), "array index sets do not match",
269      exists (i in index_set(xx)) (xx[i]!=yy[i])
270    );
271
272/** @group stdlib.compare Return if array \a x is not equal to array \a y */
273function     bool: '!='(array[$T] of     set of int: x,array[$T] of     set of int: y) =
274    let {
275        array[int] of set of int: xx = array1d(x);
276        array[int] of set of int: yy = array1d(y);
277    } in
278    assert(index_sets_agree(x,y), "array index sets do not match",
279      exists (i in index_set(xx)) (xx[i]!=yy[i])
280    );
281
282/** @group stdlib.compare Return if array \a x is not equal to array \a y */
283function var bool: '!='(array[$T] of var set of int: x,array[$T] of var set of int: y) =
284    let {
285        array[int] of var set of int: xx = array1d(x);
286        array[int] of var set of int: yy = array1d(y);
287    } in
288    assert(index_sets_agree(x,y), "array index sets do not match",
289      exists (i in index_set(xx)) (xx[i]!=yy[i])
290    );
291
292/** @group stdlib.compare Return if array \a x is not equal to array \a y */
293function     bool: '!='(array[$T] of     float: x,array[$T] of     float: y) =
294    let {
295        array[int] of float: xx = array1d(x);
296        array[int] of float: yy = array1d(y);
297    } in
298    assert(index_sets_agree(x,y), "array index sets do not match",
299      exists (i in index_set(xx)) (xx[i]!=yy[i])
300    );
301
302/** @group stdlib.compare Return if array \a x is not equal to array \a y */
303function var bool: '!='(array[$T] of var float: x,array[$T] of var float: y) =
304    let {
305        array[int] of var float: xx = array1d(x);
306        array[int] of var float: yy = array1d(y);
307    } in
308    assert(index_sets_agree(x,y), "array index sets do not match",
309      exists (i in index_set(xx)) (xx[i]!=yy[i])
310    );
311