# Comparisons¶

## General¶

### Syntax¶

x[scomparison_pri]:= x[>scomparison_pri] cmp x[>scomparison_pri]
x[scomparison_pri]:= x[>scomparison_pri] "not" cmp x[>scomparison_pri]
x[scomparison_pri]:= x[>scomparison_pri] "\not" cmp x[>scomparison_pri]


### Description¶

Felix provides a very large set of comparison operators. A collection of TeX operators are used for defined comparisons along with the usual ascii art symbols.

In addition there is a large collection of TeX operators which are not currently used and are available for overloading by the user.

All comparisons can be negated by prefixing the comparison operator with not.

a < b
a not < b


## Equivalences¶

### Syntax¶

cmp := "=="
cmp := "!="
cmp := "\ne"
cmp := "\neq"


### Semantics¶

class Eq[t] {
virtual fun == : t * t -> bool;
virtual fun != (x:t,y:t):bool => not (x == y);

axiom reflex(x:t): x == x;
axiom sym(x:t, y:t): (x == y) == (y == x);
axiom trans(x:t, y:t, z:t): x == y and y == z implies x == z;

fun eq(x:t, y:t)=> x == y;
fun ne(x:t, y:t)=> x != y;
fun \ne(x:t, y:t)=> x != y;
fun \neq(x:t, y:t)=> x != y;
}


### Description¶

An equivalence relation is a reflexive, symmetric, transitive comparison. The prototypical equivalence relation is equality. Felix uses C’s == operator for equality and supplies the negated forms !=, ne and neq as as well.

### Generic Equality¶

Felix provides a generic function _eq which generates an equality relation for non-array tuples and records, and delegates to == for arrays, sums, pointers, polymorphic variants and nominal types.

It is based on the bound value type and generates and unbound expanded comparison which is subsequently bound, therefore it depends on the names _eq and ==.

The generated function is given the bound name __eq. The compiler checks for this function and uses it if already defined, thereby avoiding duplicate definitions.

[NOTE: It should work for unions and polymorphic variants too, but is not implemented]

println\$ _eq ((a=1, b=2) , (a=1, b=2));


## Partial Orders¶

### Syntax¶

cmp := "\subset"      // $$\subset$$
cmp := "\supset"      // $$\supset$$
cmp := "\subseteq"    // $$\subseteq$$
cmp := "\subseteqq"   // $$\subseteqq$$
cmp := "\supseteq"    // $$\supseteq$$
cmp := "\supseteqq"   // $$\supseteqq$$

cmp := "\nsubseteq"   // $$\nsubseteq$$
cmp := "\nsubseteqq"  // $$\nsubseteqq$$
cmp := "\nsupseteq"   // $$\nsupseteq$$
cmp := "\nsupseteqq"  // $$\nsupseteqq$$

cmp := "\subsetneq"   // $$\subsetneq$$
cmp := "\subsetneqq"  // $$\subsetneqq$$
cmp := "\supsetneq"   // $$\supsetneq$$
cmp := "\supsetneqq"  // $$\supsetneqq$$


### Semantics¶

class Pord[t]{
inherit Eq[t];
virtual fun \subset: t * t -> bool;
virtual fun \supset(x:t,y:t):bool =>y \subset x;
virtual fun \subseteq(x:t,y:t):bool => x \subset y or x == y;
virtual fun \supseteq(x:t,y:t):bool => x \supset y or x == y;

fun \subseteqq(x:t,y:t):bool => x \subseteq y;
fun \supseteqq(x:t,y:t):bool => x \supseteq y;

fun \nsubseteq(x:t,y:t):bool => not (x \subseteq y);
fun \nsupseteq(x:t,y:t):bool => not (x \supseteq y);
fun \nsubseteqq(x:t,y:t):bool => not (x \subseteq y);
fun \nsupseteqq(x:t,y:t):bool => not (x \supseteq y);

fun \supsetneq(x:t,y:t):bool => x \supset y;
fun \supsetneqq(x:t,y:t):bool => x \supset y;
fun \supsetneq(x:t,y:t):bool => x \supset y;
fun \supsetneqq(x:t,y:t):bool => x \supset y;

axiom trans(x:t, y:t, z:t): \subset(x,y) and \subset(y,z) implies \subset(x,z);
axiom antisym(x:t, y:t): \subset(x,y) or \subset(y,x) or x == y;
axiom reflex(x:t, y:t): \subseteq(x,y) and \subseteq(y,x) implies x == y;
}


### Description¶

An improper (non-strict) partial order is a reflexive, transitive, anti-symmetric comparison. Proper (strict) partial orders are irreflexive. The prototypical partial order is the subset relation. In type theory, subtype relations are also partial orders.

## Total Orders¶

### Syntax¶

cmp := "<"          // $$<$$

cmp := "\lt"        // $$\lt$$
cmp := "\lneq"      // $$\lneq$$
cmp := "\lneqq"     // $$\lneqq$$

cmp := "<="         // $$<=$$
cmp := "\le"        // $$\le$$
cmp := "\leq"       // $$\leq$$
cmp := "\leqq"      // $$\leqq$$

cmp := ">"          // $$>$$
cmp := "\gt"        // $$\gt$$
cmp := "\gneq"      // $$\gneq$$
cmp := "\gneqq"     // $$\gneqq$$

cmp := ">="         // $$>=$$
cmp := "\ge"        // $$\ge$$
cmp := "\geq"       // $$\geq$$
cmp := "\geqq"      // $$\geqq$$

cmp := "\nless"     // $$\nless$$
cmp := "\nleq"      // $$\nleq$$
cmp := "\nleqq"     // $$\nleqq$$
cmp := "\ngtr"      // $$\ngtr$$
cmp := "\ngeq"      // $$\ngeq$$
cmp := "\ngeqq"     // $$\ngeqq$$


### Semantics¶

class Tord[t]{
inherit Eq[t];
// defined in terms of <, argument order swap, and boolean negation

// less
virtual fun < : t * t -> bool;
fun lt (x:t,y:t): bool=> x < y;
fun \lt (x:t,y:t): bool=> x < y;
fun \lneq (x:t,y:t): bool=> x < y;
fun \lneqq (x:t,y:t): bool=> x < y;

axiom trans(x:t, y:t, z:t): x < y and y < z implies x < z;
axiom antisym(x:t, y:t): x < y or y < x or x == y;
axiom reflex(x:t, y:t): x < y and y <= x implies x == y;
axiom totality(x:t, y:t): x <= y or y <= x;

// greater
fun >(x:t,y:t):bool => y < x;
fun gt(x:t,y:t):bool => y < x;
fun \gt(x:t,y:t):bool => y < x;
fun \gneq(x:t,y:t):bool => y < x;
fun \gneqq(x:t,y:t):bool => y < x;

// less equal
fun <= (x:t,y:t):bool => not (y < x);
fun le (x:t,y:t):bool => not (y < x);
fun \le (x:t,y:t):bool => not (y < x);
fun \leq (x:t,y:t):bool => not (y < x);
fun \leqq (x:t,y:t):bool => not (y < x);
fun \leqslant (x:t,y:t):bool => not (y < x);

// greater equal
fun >= (x:t,y:t):bool => not (x < y);
fun ge (x:t,y:t):bool => not (x < y);
fun \ge (x:t,y:t):bool => not (x < y);
fun \geq (x:t,y:t):bool => not (x < y);
fun \geqq (x:t,y:t):bool => not (x < y);
fun \geqslant (x:t,y:t):bool => not (x < y);

// negated, strike-through
fun \ngtr (x:t,y:t):bool => not (x < y);
fun \nless (x:t,y:t):bool => not (x < y);

fun \ngeq (x:t,y:t):bool => x < y;
fun \ngeqq (x:t,y:t):bool => x < y;
fun \ngeqslant (x:t,y:t):bool => x < y;

fun \nleq (x:t,y:t):bool => not (x <= y);
fun \nleqq (x:t,y:t):bool => not (x <= y);
fun \nleqslant (x:t,y:t):bool => not (x <= y);

// maxima and minima
fun max(x:t,y:t):t=> if x < y then y else x endif;
fun \vee(x:t,y:t) => max (x,y);

fun min(x:t,y:t):t => if x < y then x else y endif;
fun \wedge(x:t,y:t):t => min (x,y);

}


### Description¶

An improper (non-strict) total, or linear order, is an anti-symmtric, transitive relation with the connex property.

operator numeric semantics
==, \eq equality
!=, \ne inequality
<, \lt less than
<=, \le less or equal
>, \gt greater than
>=, \ge greater or equal