diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | enum.c | 19 |
2 files changed, 26 insertions, 1 deletions
@@ -1,3 +1,11 @@ +Wed Oct 15 07:21:09 2014 Tanaka Akira <akr@fsij.org> + + * enum.c: min(n) drops elements bigger than the n-th maximum element. + (struct nmin_data): New field to record the n-th maximumelement, limit + (nmin_filter): Update limit field. + (nmin_i): Drop too big eleents. + (nmin_run): Initialize limit field. + Wed Oct 15 07:00:14 2014 Eric Wong <e@80x24.org> * test/ruby/test_optimization.rb (test_string_size): new test @@ -1110,6 +1110,7 @@ struct nmin_data { long bufmax; long curlen; VALUE buf; + VALUE limit; int (*cmpfunc)(const void *, const void *, void *); int rev; /* max if 1 */ int by; /* min_by if 1 */ @@ -1221,17 +1222,32 @@ nmin_filter(struct nmin_data *data) data->curlen = data->n; rb_ary_resize(data->buf, data->n * eltsize); + data->limit = RARRAY_PTR(data->buf)[(data->n-1)*eltsize]; } static VALUE nmin_i(VALUE i, VALUE *_data, int argc, VALUE *argv) { struct nmin_data *data = (struct nmin_data *)_data; + VALUE cmpv; ENUM_WANT_SVALUE(); if (data->by) - rb_ary_push(data->buf, rb_yield(i)); + cmpv = rb_yield(i); + else + cmpv = i; + + if (data->limit != Qundef) { + int c = data->cmpfunc(&cmpv, &data->limit, data); + if (data->rev) + c = -c; + if (c > 0) + return Qnil; + } + + if (data->by) + rb_ary_push(data->buf, cmpv); rb_ary_push(data->buf, i); data->curlen++; @@ -1259,6 +1275,7 @@ nmin_run(VALUE obj, VALUE num, int by, int rev) data.bufmax = data.n * 4; data.curlen = 0; data.buf = rb_ary_tmp_new(data.bufmax * (by ? 2 : 1)); + data.limit = Qundef; data.cmpfunc = by ? nmin_cmp : rb_block_given_p() ? nmin_block_cmp : nmin_cmp; |