From 5a601ec59173ba8f0be5df6b0db5f86b6f3f6ec5 Mon Sep 17 00:00:00 2001 From: akr Date: Tue, 14 Oct 2014 22:24:34 +0000 Subject: * 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47923 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- enum.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'enum.c') diff --git a/enum.c b/enum.c index b6bcd5cc71..205664f88a 100644 --- a/enum.c +++ b/enum.c @@ -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; -- cgit v1.2.3