summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arith.c104
-rw-r--r--txr.1119
2 files changed, 207 insertions, 16 deletions
diff --git a/arith.c b/arith.c
index e805b9de..88e6db13 100644
--- a/arith.c
+++ b/arith.c
@@ -1898,6 +1898,62 @@ val pppred(val num)
return minus(num, three);
}
+static val seq_lt(val self, val aseq, val bseq)
+{
+ seq_iter_t ita, itb;
+ seq_iter_init(self, &ita, aseq);
+ seq_iter_init(self, &itb, bseq);
+
+ for (;;) {
+ val aelem, belem;
+ switch (seq_peek(&ita, &aelem) << 1 | seq_peek(&itb, &belem)) {
+ case 0:
+ return nil;
+ case 1:
+ return t;
+ case 2:
+ return nil;
+ case 3:
+ if (lt(aelem, belem))
+ return t;
+ if (!numeq(aelem, belem))
+ return nil;
+ seq_geti(&ita);
+ seq_geti(&itb);
+ break;
+ default:
+ internal_error("bad return value from iterator peek");
+ }
+ }
+}
+
+static val seq_le(val self, val aseq, val bseq)
+{
+ seq_iter_t ita, itb;
+ seq_iter_init(self, &ita, aseq);
+ seq_iter_init(self, &itb, bseq);
+
+ for (;;) {
+ val aelem, belem;
+ switch (seq_peek(&ita, &aelem) << 1 | seq_peek(&itb, &belem)) {
+ case 0:
+ return t;
+ case 1:
+ return t;
+ case 2:
+ return nil;
+ case 3:
+ if (!le(aelem, belem))
+ return nil;
+ seq_geti(&ita);
+ seq_geti(&itb);
+ break;
+ default:
+ internal_error("bad return value from iterator peek");
+ }
+ }
+}
+
val gt(val anum, val bnum)
{
val self = gt_s;
@@ -1956,9 +2012,9 @@ tail:
case TYPE_PAIR(FLNUM, COBJ):
case TYPE_PAIR(RNG, COBJ):
return do_binary_method(self, lt_s, bnum, anum);
+ default:
+ return seq_lt(self, bnum, anum);
}
-
- invalid_ops(self, anum, bnum);
}
val lt(val anum, val bnum)
@@ -2019,9 +2075,9 @@ tail:
case TYPE_PAIR(FLNUM, COBJ):
case TYPE_PAIR(RNG, COBJ):
return do_binary_method(self, gt_s, bnum, anum);
+ default:
+ return seq_lt(self, anum, bnum);
}
-
- invalid_ops(self, anum, bnum);
}
val ge(val anum, val bnum)
@@ -2087,9 +2143,9 @@ tail:
case TYPE_PAIR(FLNUM, COBJ):
case TYPE_PAIR(RNG, COBJ):
return do_binary_method(self, le_s, bnum, anum);
+ default:
+ return seq_le(self, bnum, anum);
}
-
- invalid_ops(self, anum, bnum);
}
val le(val anum, val bnum)
@@ -2155,9 +2211,39 @@ tail:
case TYPE_PAIR(FLNUM, COBJ):
case TYPE_PAIR(RNG, COBJ):
return do_binary_method(self, ge_s, bnum, anum);
+ default:
+ return seq_le(self, anum, bnum);
}
+}
- invalid_ops(self, anum, bnum);
+static val seq_numeq(val self, val aseq, val bseq)
+{
+ seq_iter_t ita, itb;
+ seq_iter_init(self, &ita, aseq);
+ seq_iter_init(self, &itb, bseq);
+
+ if (ita.inf.kind == SEQ_VECLIKE && itb.inf.kind == SEQ_VECLIKE) {
+ if (length(aseq) != length(bseq))
+ return nil;
+ }
+
+ for (;;) {
+ val aelem, belem;
+ switch (seq_peek(&ita, &aelem) + seq_peek(&itb, &belem)) {
+ case 0:
+ return t;
+ case 1:
+ return nil;
+ case 2:
+ if (!numeq(aelem, belem))
+ return nil;
+ seq_geti(&ita);
+ seq_geti(&itb);
+ break;
+ default:
+ internal_error("bad return value from iterator peek");
+ }
+ }
}
val numeq(val anum, val bnum)
@@ -2208,9 +2294,9 @@ tail:
case TYPE_PAIR(FLNUM, COBJ):
case TYPE_PAIR(RNG, COBJ):
return do_binary_method(self, self, bnum, anum);
+ default:
+ return seq_numeq(self, anum, bnum);
}
-
- invalid_ops(self, anum, bnum);
}
val expt(val anum, val bnum)
diff --git a/txr.1 b/txr.1
index 404da89a..ea70cf2f 100644
--- a/txr.1
+++ b/txr.1
@@ -39394,15 +39394,17 @@ subtract 2 and 3 from their argument.
.coNP Functions @, > @, < @, >= @ <= and @ =
.synb
-.mets (> < number << number *)
-.mets (> < number << number *)
-.mets (>= < number << number *)
-.mets (<= < number << number *)
-.mets (= < number << number *)
+.mets (> < object << object *)
+.mets (< < object << object *)
+.mets (>= < object << object *)
+.mets (<= < object << object *)
+.mets (= < object << object *)
.syne
.desc
-These relational functions compare characters and numbers for numeric equality
-or inequality. The arguments must be one or more numbers or characters.
+These relational functions compare characters, numbers ranges and sequences of
+characters or numbers for numeric equality or inequality. The arguments must be
+one or more numbers, characters, ranges, or sequences of these objects,
+or, recursively, of sequences.
If just one argument is given, then these functions all return
.codn t .
@@ -39446,6 +39448,109 @@ and if that comparison succeeds, then in the second comparison,
will be converted to integer so that it can be compared to
.metn integer .
+Ranges may only be compared with ranges. Corresponding
+fields of ranges are compared for equality by
+.code =
+such that
+.code "#R(0 1)"
+and
+.code "#R(0 1.0)"
+are reported as equal.
+The inequality comparisons are lexicographic, such that the
+.code from
+field of the range is considered more major than the
+.code to
+field. For example the inequalities
+.code "(< #R(1 2) #R(2 0))"
+and
+.code "(< #R(1 2) #R(1 3))"
+hold.
+
+Sequences may only be compared with sequences, but
+mixtures of any kinds of sequences may be compared:
+lists with vectors, vectors with strings, and so on.
+
+The
+.code =
+function considers a pair of sequences of unequal length
+to be unequal, reporting
+.codn nil .
+Sequences are equal if they have the same length
+and their corresponding elements are recursively
+equal under the
+.code =
+function.
+
+The inequality functions treat sequences lexicographically.
+A pair of sequences is compared by comparing corresponding
+elements. The
+.code <
+function tests each successive pair of corresponding
+elements recursively using the
+.code <
+function. If this recursive comparison reports
+.codn t ,
+then the function immediately returns
+.code t
+without considering any more pairs of elements.
+Otherwise the same pair of elements is compared again
+using the
+.code =
+function. If that reports false, then the function reports false without
+considering any more pairs of elements. Otherwise processing continues with the
+next pair, if any. If all corresponding elements are equal, but the right
+sequence is longer,
+.code <
+returns
+.codn t ,
+otherwise the function reports
+.codn nil .
+The
+.code <=
+function tests each successive pair of corresponding
+elements recursively using the
+.code <=
+function. If this returns
+.code nil
+then the function returns
+.code nil
+without considering any more pairs. Otherwise processing continues
+with the next pair, if any.
+If all corresponding elements satisfy the test, but the
+left sequence is longer, then
+.code nil
+is returned. Otherwise
+.code t
+is returned.
+
+The inequality relations exhibit symmetry, which means that
+the functions
+.code >
+and
+.code >=
+functions are equivalent, respectively, to
+.code <
+and
+.code <=
+with the order of the argument values reversed. For instance, the expression
+.code "(< a b c)"
+is equivalent to
+.code "(> c b a)"
+except for the difference in evaluation order of the
+.codn a ,
+.code b
+and
+.code c
+operands themselves. Any semantic description of
+.code <
+or
+.code <=
+applies, respectively, also to
+.code >
+or
+.code >=
+with the appropriate adjustment for argument order reversal.
+
.coNP Function @ /=
.synb
.mets (/= << number *)