diff options
-rw-r--r-- | arith.c | 104 | ||||
-rw-r--r-- | txr.1 | 119 |
2 files changed, 207 insertions, 16 deletions
@@ -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) @@ -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 *) |