diff options
-rw-r--r-- | cppawk-cons.1 | 166 | ||||
-rw-r--r-- | cppawk-include/cons-priv.h | 44 | ||||
-rw-r--r-- | testcases-cons | 24 |
3 files changed, 222 insertions, 12 deletions
diff --git a/cppawk-cons.1 b/cppawk-cons.1 index a4d766d..fa286b9 100644 --- a/cppawk-cons.1 +++ b/cppawk-cons.1 @@ -493,6 +493,17 @@ or it is to be understood as a variable that was not assigned, and therefore evaluates to the undefined value. +In this library, whenever the input to a function is a list, it +is required to be a proper list unless otherwise noted. +A proper list is terminated by the specific atom +.B nil +rather than some other atom. If a library function which requires +proper lists detects an improper list, execution will terminate +with a diagnostic. + +Other input conditions are diagnosed, such as a negative argument where a +non-negative integer is expected. + .SS Macro \fInil\fP .bk .B Syntax: @@ -1600,6 +1611,161 @@ returns a list similar to butlast(list(1, 2, 3), 15) -> nil .ft R +.SS Function \fIreverse\fP +.bk +Syntax: + +.ft B + reverse(\fIx\fP) +.ft R + +The +.B reverse +function returns the reverse of list +.IR x : +a list containing the same items as +.I x +but in the opposite order. + +.SS Function \fIiota\fP +.bk +Syntax: + +.ft B + iota(\fIx\fP, \fIy\fP[, \fId\fP]) +.ft R + +The +.B iota +function produces a list of numbers starting from +.I x +and ending in +.IR y . + +The optional +.I d +argument (delta) specifies the increment step size between +consecutive numbers. It defaults to one, if +.I y +is greater than +.IR x , +negative one otherwise. + +When the value of +.I y +is surpassed, the production stops. If the value of +.I y +occurs, it is included in the list. The value +.I y +being surpassed means that the next value of the sequence +lies on the other side of +.I y +compared to the previous value of the sequence. That +next value is excluded from the sequence, and the +sequence terminates. + +If +.I x +is greater than +.IR y , +then a descending sequence is generated, if the value of +.I d +is negative. + +In all other situations, the following requirements apply: + +If +.IB x " == " +.IR y , +then +.B iota +returns +.BI list( x ) +regardless of the value of +.IR d . + +Furthermore, +.B iota +function returns the empty list +.B nil +in the following situations: + +The +.B iota +function unconditionally returns the empty list +.B nil +in the following situations: + +.IP 1. +.BR d " == " +.BR 0 . + +.IP 2. +.BR x " <= " y " && " d " <" +.BR 0 . + +.IP 3. +.BR x " > " y " && " d " >" +.BR 0 . +.PP + +To ensure maximum accuracy when fractional range limits and/or delta are used, +the successive values of the sequence are calculated by by a +multiplication-and-displacement calculation relative to an internal counter +which increments in steps of 1 starting from 0, not by repeatedly accumulating +the value of +.I d . + +That is to say, for example, +.B "iota(2.5, 10, 0.3)" +collects the initial value of 2.5 into the output list, and then +subsequent values are produced by the calculation +.B "i * 0.3 + 2.5" +for values of the internal variable +.I i +being 1, 2, ... and not by initializing an accumulator to 1, and then +repeatedly adding 0.3 to that accumulator. + +The test for whether the value of +.I y +occurs in the sequence (and is therefore included) uses the +.B == +operator and therefore absolute floating-point precision. Depending +on the choices of +.I x +and +.IR d , +a value that is very close to +.I y +may be attained, which is not recognized as equal. If all three values +.IR x , +.I y +and +.I d +have exact representations in the floating-point system, and the +difference between +.I x +and +.I y +is a multiple of +.I d +then +.I y +will be attained. + +.B Examples: + +.ft B + iota(1, 1) -> (1) + iota(1, 3) -> (1 2 3) + iota(1, -1) -> (1 0 -1) + iota(1, 3, 0.25) -> (1 1.25 1.5 1.75 2 2.25 2.5 2.75 3) + iota(3, 1, -0.25) -> (3 2.75 2.5 2.25 2 1.75 1.5 1.25 1) + iota(1, 3, -1) -> nil + iota(2.5, 2.5, 0) -> (2.5) + iota(2.5, 2.5, -1) -> (2.5) +.ft R + .SH "SEE ALSO" cppawk(1) diff --git a/cppawk-include/cons-priv.h b/cppawk-include/cons-priv.h index 55790d1..97d410d 100644 --- a/cppawk-include/cons-priv.h +++ b/cppawk-include/cons-priv.h @@ -786,23 +786,43 @@ function __butlast(__lst, __n, return (__i in __circbuf) ? __list_end(__circbuf[__i]) : __nil } -function __iota(__from, __to, __step, - __i, __out) +function __iota(__from, __to, __delta, + __out, __i, __val) { __out = __list_begin(); if (__from < __to) { - if (!__present(__step)) - __step = 1 - if (__step > 0) - for (__i = __from; __i <= __to; __i += __step) - __out = __list_add(__out, __i) + if (!__present(__delta)) + __delta = 1 + + if (__delta <= 0) + return __nil; + + __i = 0 + __val = __from + + while (__val <= __to) { + __out = __list_add(__out, __val) + __i++ + __val = __from + (__i * __delta) + } + } else if (__from > __to) { + if (!__present(__delta)) + __delta = -1 + + if (__delta >= 0) + return __nil; + + __i = 0 + __val = __from + + while (__val >= __to) { + __out = __list_add(__out, __val) + __i++ + __val = __from + (__i * __delta) + } } else { - if (!__present(__step)) - __step = -1 - if (__step < 0) - for (__i = __from; __i >= __to; __i += __step) - __out = __list_add(__out, __i) + return __list(__from) } return __list_end(__out) diff --git a/testcases-cons b/testcases-cons index 6b7751d..9962970 100644 --- a/testcases-cons +++ b/testcases-cons @@ -649,3 +649,27 @@ nil 3 (1) nil +-- +35: +$cppawk ' +#include <cons.h> + +BEGIN { + print sexp(iota(1, 1)) + print sexp(iota(1, 3)) + print sexp(iota(1, -1)) + print sexp(iota(1, 3, 0.25)) + print sexp(iota(3, 1, -0.25)) + print sexp(iota(1, 3, -1)) + print sexp(iota(2.5, 2.5, 0)) + print sexp(iota(2.5, 2.5, -1)) +}' +: +(1) +(1 2 3) +(1 0 -1) +(1 1.25 1.5 1.75 2 2.25 2.5 2.75 3) +(3 2.75 2.5 2.25 2 1.75 1.5 1.25 1) +nil +(2.5) +(2.5) |