Ruby  2.5.0dev(2017-10-22revision60238)
enum.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  enum.c -
4 
5  $Author$
6  created at: Fri Oct 1 15:15:19 JST 1993
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9 
10 **********************************************************************/
11 
12 #include "internal.h"
13 #include "ruby/util.h"
14 #include "id.h"
15 #include "symbol.h"
16 
17 #include <assert.h>
18 
20 
21 static ID id_next;
22 static ID id_div;
23 
24 #define id_each idEach
25 #define id_eqq idEqq
26 #define id_cmp idCmp
27 #define id_lshift idLTLT
28 #define id_call idCall
29 #define id_size idSize
30 
31 VALUE
33 {
34  if (argc == 0) return Qnil;
35  if (argc == 1) return argv[0];
36  return rb_ary_new4(argc, argv);
37 }
38 
39 #define ENUM_WANT_SVALUE() do { \
40  i = rb_enum_values_pack(argc, argv); \
41 } while (0)
42 
43 static VALUE
44 enum_yield(int argc, VALUE ary)
45 {
46  if (argc > 1)
47  return rb_yield_force_blockarg(ary);
48  if (argc == 1)
49  return rb_yield(ary);
50  return rb_yield_values2(0, 0);
51 }
52 
53 static VALUE
54 enum_yield_array(VALUE ary)
55 {
56  long len = RARRAY_LEN(ary);
57 
58  if (len > 1)
59  return rb_yield_force_blockarg(ary);
60  if (len == 1)
61  return rb_yield(RARRAY_AREF(ary, 0));
62  return rb_yield_values2(0, 0);
63 }
64 
65 static VALUE
66 grep_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
67 {
68  struct MEMO *memo = MEMO_CAST(args);
70 
71  if (RTEST(rb_funcallv(memo->v1, id_eqq, 1, &i)) == RTEST(memo->u3.value)) {
72  rb_ary_push(memo->v2, i);
73  }
74  return Qnil;
75 }
76 
77 static VALUE
78 grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
79 {
80  struct MEMO *memo = MEMO_CAST(args);
82 
83  if (RTEST(rb_funcallv(memo->v1, id_eqq, 1, &i)) == RTEST(memo->u3.value)) {
84  rb_ary_push(memo->v2, enum_yield(argc, i));
85  }
86  return Qnil;
87 }
88 
89 /*
90  * call-seq:
91  * enum.grep(pattern) -> array
92  * enum.grep(pattern) { |obj| block } -> array
93  *
94  * Returns an array of every element in <i>enum</i> for which
95  * <code>Pattern === element</code>. If the optional <em>block</em> is
96  * supplied, each matching element is passed to it, and the block's
97  * result is stored in the output array.
98  *
99  * (1..100).grep 38..44 #=> [38, 39, 40, 41, 42, 43, 44]
100  * c = IO.constants
101  * c.grep(/SEEK/) #=> [:SEEK_SET, :SEEK_CUR, :SEEK_END]
102  * res = c.grep(/SEEK/) { |v| IO.const_get(v) }
103  * res #=> [0, 1, 2]
104  *
105  */
106 
107 static VALUE
108 enum_grep(VALUE obj, VALUE pat)
109 {
110  VALUE ary = rb_ary_new();
111  struct MEMO *memo = MEMO_NEW(pat, ary, Qtrue);
112 
113  rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)memo);
114 
115  return ary;
116 }
117 
118 /*
119  * call-seq:
120  * enum.grep_v(pattern) -> array
121  * enum.grep_v(pattern) { |obj| block } -> array
122  *
123  * Inverted version of Enumerable#grep.
124  * Returns an array of every element in <i>enum</i> for which
125  * not <code>Pattern === element</code>.
126  *
127  * (1..10).grep_v 2..5 #=> [1, 6, 7, 8, 9, 10]
128  * res =(1..10).grep_v(2..5) { |v| v * 2 }
129  * res #=> [2, 12, 14, 16, 18, 20]
130  *
131  */
132 
133 static VALUE
134 enum_grep_v(VALUE obj, VALUE pat)
135 {
136  VALUE ary = rb_ary_new();
137  struct MEMO *memo = MEMO_NEW(pat, ary, Qfalse);
138 
139  rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)memo);
140 
141  return ary;
142 }
143 
144 static VALUE
145 count_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
146 {
147  struct MEMO *memo = MEMO_CAST(memop);
148 
150 
151  if (rb_equal(i, memo->v1)) {
152  memo->u3.cnt++;
153  }
154  return Qnil;
155 }
156 
157 static VALUE
158 count_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
159 {
160  struct MEMO *memo = MEMO_CAST(memop);
161 
162  if (RTEST(rb_yield_values2(argc, argv))) {
163  memo->u3.cnt++;
164  }
165  return Qnil;
166 }
167 
168 static VALUE
169 count_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
170 {
171  struct MEMO *memo = MEMO_CAST(memop);
172 
173  memo->u3.cnt++;
174  return Qnil;
175 }
176 
177 /*
178  * call-seq:
179  * enum.count -> int
180  * enum.count(item) -> int
181  * enum.count { |obj| block } -> int
182  *
183  * Returns the number of items in +enum+ through enumeration.
184  * If an argument is given, the number of items in +enum+ that
185  * are equal to +item+ are counted. If a block is given, it
186  * counts the number of elements yielding a true value.
187  *
188  * ary = [1, 2, 4, 2]
189  * ary.count #=> 4
190  * ary.count(2) #=> 2
191  * ary.count{ |x| x%2==0 } #=> 3
192  *
193  */
194 
195 static VALUE
196 enum_count(int argc, VALUE *argv, VALUE obj)
197 {
198  VALUE item = Qnil;
199  struct MEMO *memo;
201 
202  if (argc == 0) {
203  if (rb_block_given_p()) {
204  func = count_iter_i;
205  }
206  else {
207  func = count_all_i;
208  }
209  }
210  else {
211  rb_scan_args(argc, argv, "1", &item);
212  if (rb_block_given_p()) {
213  rb_warn("given block not used");
214  }
215  func = count_i;
216  }
217 
218  memo = MEMO_NEW(item, 0, 0);
219  rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
220  return INT2NUM(memo->u3.cnt);
221 }
222 
223 static VALUE
224 find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
225 {
227 
228  if (RTEST(enum_yield(argc, i))) {
229  struct MEMO *memo = MEMO_CAST(memop);
230  MEMO_V1_SET(memo, i);
231  memo->u3.cnt = 1;
232  rb_iter_break();
233  }
234  return Qnil;
235 }
236 
237 /*
238  * call-seq:
239  * enum.detect(ifnone = nil) { |obj| block } -> obj or nil
240  * enum.find(ifnone = nil) { |obj| block } -> obj or nil
241  * enum.detect(ifnone = nil) -> an_enumerator
242  * enum.find(ifnone = nil) -> an_enumerator
243  *
244  * Passes each entry in <i>enum</i> to <em>block</em>. Returns the
245  * first for which <em>block</em> is not false. If no
246  * object matches, calls <i>ifnone</i> and returns its result when it
247  * is specified, or returns <code>nil</code> otherwise.
248  *
249  * If no block is given, an enumerator is returned instead.
250  *
251  * (1..100).detect => #<Enumerator: 1..100:detect>
252  * (1..100).find => #<Enumerator: 1..100:find>
253  *
254  * (1..10).detect { |i| i % 5 == 0 and i % 7 == 0 } #=> nil
255  * (1..10).find { |i| i % 5 == 0 and i % 7 == 0 } #=> nil
256  * (1..100).detect { |i| i % 5 == 0 and i % 7 == 0 } #=> 35
257  * (1..100).find { |i| i % 5 == 0 and i % 7 == 0 } #=> 35
258  *
259  */
260 
261 static VALUE
262 enum_find(int argc, VALUE *argv, VALUE obj)
263 {
264  struct MEMO *memo;
265  VALUE if_none;
266 
267  rb_scan_args(argc, argv, "01", &if_none);
268  RETURN_ENUMERATOR(obj, argc, argv);
269  memo = MEMO_NEW(Qundef, 0, 0);
270  rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
271  if (memo->u3.cnt) {
272  return memo->v1;
273  }
274  if (!NIL_P(if_none)) {
275  return rb_funcallv(if_none, id_call, 0, 0);
276  }
277  return Qnil;
278 }
279 
280 static VALUE
281 find_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
282 {
283  struct MEMO *memo = MEMO_CAST(memop);
284 
286 
287  if (rb_equal(i, memo->v2)) {
288  MEMO_V1_SET(memo, UINT2NUM(memo->u3.cnt));
289  rb_iter_break();
290  }
291  memo->u3.cnt++;
292  return Qnil;
293 }
294 
295 static VALUE
296 find_index_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
297 {
298  struct MEMO *memo = MEMO_CAST(memop);
299 
300  if (RTEST(rb_yield_values2(argc, argv))) {
301  MEMO_V1_SET(memo, UINT2NUM(memo->u3.cnt));
302  rb_iter_break();
303  }
304  memo->u3.cnt++;
305  return Qnil;
306 }
307 
308 /*
309  * call-seq:
310  * enum.find_index(value) -> int or nil
311  * enum.find_index { |obj| block } -> int or nil
312  * enum.find_index -> an_enumerator
313  *
314  * Compares each entry in <i>enum</i> with <em>value</em> or passes
315  * to <em>block</em>. Returns the index for the first for which the
316  * evaluated value is non-false. If no object matches, returns
317  * <code>nil</code>
318  *
319  * If neither block nor argument is given, an enumerator is returned instead.
320  *
321  * (1..10).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> nil
322  * (1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> 34
323  * (1..100).find_index(50) #=> 49
324  *
325  */
326 
327 static VALUE
328 enum_find_index(int argc, VALUE *argv, VALUE obj)
329 {
330  struct MEMO *memo; /* [return value, current index, ] */
331  VALUE condition_value = Qnil;
333 
334  if (argc == 0) {
335  RETURN_ENUMERATOR(obj, 0, 0);
336  func = find_index_iter_i;
337  }
338  else {
339  rb_scan_args(argc, argv, "1", &condition_value);
340  if (rb_block_given_p()) {
341  rb_warn("given block not used");
342  }
343  func = find_index_i;
344  }
345 
346  memo = MEMO_NEW(Qnil, condition_value, 0);
347  rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
348  return memo->v1;
349 }
350 
351 static VALUE
352 find_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
353 {
355 
356  if (RTEST(enum_yield(argc, i))) {
357  rb_ary_push(ary, i);
358  }
359  return Qnil;
360 }
361 
362 static VALUE
363 enum_size(VALUE self, VALUE args, VALUE eobj)
364 {
365  return rb_check_funcall_default(self, id_size, 0, 0, Qnil);
366 }
367 
368 static long
369 limit_by_enum_size(VALUE obj, long n)
370 {
371  unsigned long limit;
372  VALUE size = rb_check_funcall(obj, id_size, 0, 0);
373  if (!FIXNUM_P(size)) return n;
374  limit = FIX2ULONG(size);
375  return ((unsigned long)n > limit) ? (long)limit : n;
376 }
377 
378 static int
379 enum_size_over_p(VALUE obj, long n)
380 {
381  VALUE size = rb_check_funcall(obj, id_size, 0, 0);
382  if (!FIXNUM_P(size)) return 0;
383  return ((unsigned long)n > FIX2ULONG(size));
384 }
385 
386 /*
387  * call-seq:
388  * enum.find_all { |obj| block } -> array
389  * enum.select { |obj| block } -> array
390  * enum.find_all -> an_enumerator
391  * enum.select -> an_enumerator
392  *
393  * Returns an array containing all elements of +enum+
394  * for which the given +block+ returns a true value.
395  *
396  * If no block is given, an Enumerator is returned instead.
397  *
398  *
399  * (1..10).find_all { |i| i % 3 == 0 } #=> [3, 6, 9]
400  *
401  * [1,2,3,4,5].select { |num| num.even? } #=> [2, 4]
402  *
403  * See also Enumerable#reject.
404  */
405 
406 static VALUE
407 enum_find_all(VALUE obj)
408 {
409  VALUE ary;
410 
411  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
412 
413  ary = rb_ary_new();
414  rb_block_call(obj, id_each, 0, 0, find_all_i, ary);
415 
416  return ary;
417 }
418 
419 static VALUE
420 reject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
421 {
423 
424  if (!RTEST(enum_yield(argc, i))) {
425  rb_ary_push(ary, i);
426  }
427  return Qnil;
428 }
429 
430 /*
431  * call-seq:
432  * enum.reject { |obj| block } -> array
433  * enum.reject -> an_enumerator
434  *
435  * Returns an array for all elements of +enum+ for which the given
436  * +block+ returns <code>false</code>.
437  *
438  * If no block is given, an Enumerator is returned instead.
439  *
440  * (1..10).reject { |i| i % 3 == 0 } #=> [1, 2, 4, 5, 7, 8, 10]
441  *
442  * [1, 2, 3, 4, 5].reject { |num| num.even? } #=> [1, 3, 5]
443  *
444  * See also Enumerable#find_all.
445  */
446 
447 static VALUE
448 enum_reject(VALUE obj)
449 {
450  VALUE ary;
451 
452  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
453 
454  ary = rb_ary_new();
455  rb_block_call(obj, id_each, 0, 0, reject_i, ary);
456 
457  return ary;
458 }
459 
460 static VALUE
461 collect_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
462 {
464 
465  return Qnil;
466 }
467 
468 static VALUE
469 collect_all(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
470 {
473 
474  return Qnil;
475 }
476 
477 /*
478  * call-seq:
479  * enum.collect { |obj| block } -> array
480  * enum.map { |obj| block } -> array
481  * enum.collect -> an_enumerator
482  * enum.map -> an_enumerator
483  *
484  * Returns a new array with the results of running <em>block</em> once
485  * for every element in <i>enum</i>.
486  *
487  * If no block is given, an enumerator is returned instead.
488  *
489  * (1..4).map { |i| i*i } #=> [1, 4, 9, 16]
490  * (1..4).collect { "cat" } #=> ["cat", "cat", "cat", "cat"]
491  *
492  */
493 
494 static VALUE
495 enum_collect(VALUE obj)
496 {
497  VALUE ary;
498  int min_argc, max_argc;
499 
500  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
501 
502  ary = rb_ary_new();
503  min_argc = rb_block_min_max_arity(&max_argc);
504  rb_lambda_call(obj, id_each, 0, 0, collect_i, min_argc, max_argc, ary);
505 
506  return ary;
507 }
508 
509 static VALUE
510 flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
511 {
512  VALUE tmp;
513 
514  i = rb_yield_values2(argc, argv);
515  tmp = rb_check_array_type(i);
516 
517  if (NIL_P(tmp)) {
518  rb_ary_push(ary, i);
519  }
520  else {
521  rb_ary_concat(ary, tmp);
522  }
523  return Qnil;
524 }
525 
526 /*
527  * call-seq:
528  * enum.flat_map { |obj| block } -> array
529  * enum.collect_concat { |obj| block } -> array
530  * enum.flat_map -> an_enumerator
531  * enum.collect_concat -> an_enumerator
532  *
533  * Returns a new array with the concatenated results of running
534  * <em>block</em> once for every element in <i>enum</i>.
535  *
536  * If no block is given, an enumerator is returned instead.
537  *
538  * [1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4]
539  * [[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100]
540  *
541  */
542 
543 static VALUE
544 enum_flat_map(VALUE obj)
545 {
546  VALUE ary;
547 
548  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
549 
550  ary = rb_ary_new();
551  rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);
552 
553  return ary;
554 }
555 
556 /*
557  * call-seq:
558  * enum.to_a(*args) -> array
559  * enum.entries(*args) -> array
560  *
561  * Returns an array containing the items in <i>enum</i>.
562  *
563  * (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7]
564  * { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a #=> [["a", 1], ["b", 2], ["c", 3]]
565  *
566  * require 'prime'
567  * Prime.entries 10 #=> [2, 3, 5, 7]
568  */
569 static VALUE
570 enum_to_a(int argc, VALUE *argv, VALUE obj)
571 {
572  VALUE ary = rb_ary_new();
573 
574  rb_block_call(obj, id_each, argc, argv, collect_all, ary);
575  OBJ_INFECT(ary, obj);
576 
577  return ary;
578 }
579 
580 static VALUE
581 enum_to_h_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
582 {
583  VALUE key_value_pair;
586  key_value_pair = rb_check_array_type(i);
587  if (NIL_P(key_value_pair)) {
588  rb_raise(rb_eTypeError, "wrong element type %s (expected array)",
590  }
591  if (RARRAY_LEN(key_value_pair) != 2) {
592  rb_raise(rb_eArgError, "element has wrong array length (expected 2, was %ld)",
593  RARRAY_LEN(key_value_pair));
594  }
595  rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
596  return Qnil;
597 }
598 
599 /*
600  * call-seq:
601  * enum.to_h(*args) -> hash
602  *
603  * Returns the result of interpreting <i>enum</i> as a list of
604  * <tt>[key, value]</tt> pairs.
605  *
606  * %i[hello world].each_with_index.to_h
607  * # => {:hello => 0, :world => 1}
608  */
609 
610 static VALUE
611 enum_to_h(int argc, VALUE *argv, VALUE obj)
612 {
613  VALUE hash = rb_hash_new();
614  rb_block_call(obj, id_each, argc, argv, enum_to_h_i, hash);
615  OBJ_INFECT(hash, obj);
616  return hash;
617 }
618 
619 static VALUE
620 inject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
621 {
622  struct MEMO *memo = MEMO_CAST(p);
623 
625 
626  if (memo->v1 == Qundef) {
627  MEMO_V1_SET(memo, i);
628  }
629  else {
630  MEMO_V1_SET(memo, rb_yield_values(2, memo->v1, i));
631  }
632  return Qnil;
633 }
634 
635 static VALUE
636 inject_op_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
637 {
638  struct MEMO *memo = MEMO_CAST(p);
639  VALUE name;
640 
642 
643  if (memo->v1 == Qundef) {
644  MEMO_V1_SET(memo, i);
645  }
646  else if (SYMBOL_P(name = memo->u3.value)) {
647  const ID mid = SYM2ID(name);
648  MEMO_V1_SET(memo, rb_funcallv(memo->v1, mid, 1, &i));
649  }
650  else {
651  VALUE args[2];
652  args[0] = name;
653  args[1] = i;
654  MEMO_V1_SET(memo, rb_f_send(numberof(args), args, memo->v1));
655  }
656  return Qnil;
657 }
658 
659 static VALUE
660 ary_inject_op(VALUE ary, VALUE init, VALUE op)
661 {
662  ID id;
663  VALUE v, e;
664  long i, n;
665 
666  if (RARRAY_LEN(ary) == 0)
667  return init == Qundef ? Qnil : init;
668 
669  if (init == Qundef) {
670  v = RARRAY_AREF(ary, 0);
671  i = 1;
672  if (RARRAY_LEN(ary) == 1)
673  return v;
674  }
675  else {
676  v = init;
677  i = 0;
678  }
679 
680  id = SYM2ID(op);
681  if (id == idPLUS) {
682  if (RB_INTEGER_TYPE_P(v) &&
685  n = 0;
686  for (; i < RARRAY_LEN(ary); i++) {
687  e = RARRAY_AREF(ary, i);
688  if (FIXNUM_P(e)) {
689  n += FIX2LONG(e); /* should not overflow long type */
690  if (!FIXABLE(n)) {
691  v = rb_big_plus(LONG2NUM(n), v);
692  n = 0;
693  }
694  }
695  else if (RB_TYPE_P(e, T_BIGNUM))
696  v = rb_big_plus(e, v);
697  else
698  goto not_integer;
699  }
700  if (n != 0)
701  v = rb_fix_plus(LONG2FIX(n), v);
702  return v;
703 
704  not_integer:
705  if (n != 0)
706  v = rb_fix_plus(LONG2FIX(n), v);
707  }
708  }
709  for (; i < RARRAY_LEN(ary); i++) {
710  v = rb_funcallv_public(v, id, 1, &RARRAY_CONST_PTR(ary)[i]);
711  }
712  return v;
713 }
714 
715 /*
716  * call-seq:
717  * enum.inject(initial, sym) -> obj
718  * enum.inject(sym) -> obj
719  * enum.inject(initial) { |memo, obj| block } -> obj
720  * enum.inject { |memo, obj| block } -> obj
721  * enum.reduce(initial, sym) -> obj
722  * enum.reduce(sym) -> obj
723  * enum.reduce(initial) { |memo, obj| block } -> obj
724  * enum.reduce { |memo, obj| block } -> obj
725  *
726  * Combines all elements of <i>enum</i> by applying a binary
727  * operation, specified by a block or a symbol that names a
728  * method or operator.
729  *
730  * The <i>inject</i> and <i>reduce</i> methods are aliases. There
731  * is no performance benefit to either.
732  *
733  * If you specify a block, then for each element in <i>enum</i>
734  * the block is passed an accumulator value (<i>memo</i>) and the element.
735  * If you specify a symbol instead, then each element in the collection
736  * will be passed to the named method of <i>memo</i>.
737  * In either case, the result becomes the new value for <i>memo</i>.
738  * At the end of the iteration, the final value of <i>memo</i> is the
739  * return value for the method.
740  *
741  * If you do not explicitly specify an <i>initial</i> value for <i>memo</i>,
742  * then the first element of collection is used as the initial value
743  * of <i>memo</i>.
744  *
745  *
746  * # Sum some numbers
747  * (5..10).reduce(:+) #=> 45
748  * # Same using a block and inject
749  * (5..10).inject { |sum, n| sum + n } #=> 45
750  * # Multiply some numbers
751  * (5..10).reduce(1, :*) #=> 151200
752  * # Same using a block
753  * (5..10).inject(1) { |product, n| product * n } #=> 151200
754  * # find the longest word
755  * longest = %w{ cat sheep bear }.inject do |memo, word|
756  * memo.length > word.length ? memo : word
757  * end
758  * longest #=> "sheep"
759  *
760  */
761 static VALUE
762 enum_inject(int argc, VALUE *argv, VALUE obj)
763 {
764  struct MEMO *memo;
765  VALUE init, op;
766  rb_block_call_func *iter = inject_i;
767  ID id;
768 
769  switch (rb_scan_args(argc, argv, "02", &init, &op)) {
770  case 0:
771  init = Qundef;
772  break;
773  case 1:
774  if (rb_block_given_p()) {
775  break;
776  }
777  id = rb_check_id(&init);
778  op = id ? ID2SYM(id) : init;
779  init = Qundef;
780  iter = inject_op_i;
781  break;
782  case 2:
783  if (rb_block_given_p()) {
784  rb_warning("given block not used");
785  }
786  id = rb_check_id(&op);
787  if (id) op = ID2SYM(id);
788  iter = inject_op_i;
789  break;
790  }
791 
792  if (iter == inject_op_i &&
793  SYMBOL_P(op) &&
794  RB_TYPE_P(obj, T_ARRAY) &&
796  return ary_inject_op(obj, init, op);
797  }
798 
799  memo = MEMO_NEW(init, Qnil, op);
800  rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
801  if (memo->v1 == Qundef) return Qnil;
802  return memo->v1;
803 }
804 
805 static VALUE
806 partition_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arys))
807 {
808  struct MEMO *memo = MEMO_CAST(arys);
809  VALUE ary;
811 
812  if (RTEST(enum_yield(argc, i))) {
813  ary = memo->v1;
814  }
815  else {
816  ary = memo->v2;
817  }
818  rb_ary_push(ary, i);
819  return Qnil;
820 }
821 
822 /*
823  * call-seq:
824  * enum.partition { |obj| block } -> [ true_array, false_array ]
825  * enum.partition -> an_enumerator
826  *
827  * Returns two arrays, the first containing the elements of
828  * <i>enum</i> for which the block evaluates to true, the second
829  * containing the rest.
830  *
831  * If no block is given, an enumerator is returned instead.
832  *
833  * (1..6).partition { |v| v.even? } #=> [[2, 4, 6], [1, 3, 5]]
834  *
835  */
836 
837 static VALUE
838 enum_partition(VALUE obj)
839 {
840  struct MEMO *memo;
841 
842  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
843 
844  memo = MEMO_NEW(rb_ary_new(), rb_ary_new(), 0);
845  rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);
846 
847  return rb_assoc_new(memo->v1, memo->v2);
848 }
849 
850 static VALUE
851 group_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
852 {
853  VALUE group;
854  VALUE values;
855 
857 
858  group = enum_yield(argc, i);
859  values = rb_hash_aref(hash, group);
860  if (!RB_TYPE_P(values, T_ARRAY)) {
861  values = rb_ary_new3(1, i);
862  rb_hash_aset(hash, group, values);
863  }
864  else {
865  rb_ary_push(values, i);
866  }
867  return Qnil;
868 }
869 
870 /*
871  * call-seq:
872  * enum.group_by { |obj| block } -> a_hash
873  * enum.group_by -> an_enumerator
874  *
875  * Groups the collection by result of the block. Returns a hash where the
876  * keys are the evaluated result from the block and the values are
877  * arrays of elements in the collection that correspond to the key.
878  *
879  * If no block is given an enumerator is returned.
880  *
881  * (1..6).group_by { |i| i%3 } #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
882  *
883  */
884 
885 static VALUE
886 enum_group_by(VALUE obj)
887 {
888  VALUE hash;
889 
890  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
891 
892  hash = rb_hash_new();
893  rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
894  OBJ_INFECT(hash, obj);
895 
896  return hash;
897 }
898 
899 static VALUE
900 first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))
901 {
902  struct MEMO *memo = MEMO_CAST(params);
904 
905  MEMO_V1_SET(memo, i);
906  rb_iter_break();
907 
908  UNREACHABLE;
909 }
910 
911 static VALUE enum_take(VALUE obj, VALUE n);
912 
913 /*
914  * call-seq:
915  * enum.first -> obj or nil
916  * enum.first(n) -> an_array
917  *
918  * Returns the first element, or the first +n+ elements, of the enumerable.
919  * If the enumerable is empty, the first form returns <code>nil</code>, and the
920  * second form returns an empty array.
921  *
922  * %w[foo bar baz].first #=> "foo"
923  * %w[foo bar baz].first(2) #=> ["foo", "bar"]
924  * %w[foo bar baz].first(10) #=> ["foo", "bar", "baz"]
925  * [].first #=> nil
926  * [].first(10) #=> []
927  *
928  */
929 
930 static VALUE
931 enum_first(int argc, VALUE *argv, VALUE obj)
932 {
933  struct MEMO *memo;
934  rb_check_arity(argc, 0, 1);
935  if (argc > 0) {
936  return enum_take(obj, argv[0]);
937  }
938  else {
939  memo = MEMO_NEW(Qnil, 0, 0);
940  rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
941  return memo->v1;
942  }
943 }
944 
945 
946 /*
947  * call-seq:
948  * enum.sort -> array
949  * enum.sort { |a, b| block } -> array
950  *
951  * Returns an array containing the items in <i>enum</i> sorted.
952  *
953  * Comparisons for the sort will be done using the items' own
954  * <code><=></code> operator or using an optional code block.
955  *
956  * The block must implement a comparison between +a+ and +b+ and return
957  * an integer less than 0 when +b+ follows +a+, +0+ when +a+ and +b+
958  * are equivalent, or an integer greater than 0 when +a+ follows +b+.
959  *
960  * The result is not guaranteed to be stable. When the comparison of two
961  * elements returns +0+, the order of the elements is unpredictable.
962  *
963  * %w(rhea kea flea).sort #=> ["flea", "kea", "rhea"]
964  * (1..10).sort { |a, b| b <=> a } #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
965  *
966  * See also Enumerable#sort_by. It implements a Schwartzian transform
967  * which is useful when key computation or comparison is expensive.
968  */
969 
970 static VALUE
971 enum_sort(VALUE obj)
972 {
973  return rb_ary_sort_bang(enum_to_a(0, 0, obj));
974 }
975 
976 #define SORT_BY_BUFSIZE 16
977 struct sort_by_data {
978  const VALUE ary;
979  const VALUE buf;
980  long n;
981 };
982 
983 static VALUE
984 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
985 {
986  struct sort_by_data *data = (struct sort_by_data *)&MEMO_CAST(_data)->v1;
987  VALUE ary = data->ary;
988  VALUE v;
989 
991 
992  v = enum_yield(argc, i);
993 
994  if (RBASIC(ary)->klass) {
995  rb_raise(rb_eRuntimeError, "sort_by reentered");
996  }
997  if (RARRAY_LEN(data->buf) != SORT_BY_BUFSIZE*2) {
998  rb_raise(rb_eRuntimeError, "sort_by reentered");
999  }
1000 
1001  RARRAY_ASET(data->buf, data->n*2, v);
1002  RARRAY_ASET(data->buf, data->n*2+1, i);
1003  data->n++;
1004  if (data->n == SORT_BY_BUFSIZE) {
1005  rb_ary_concat(ary, data->buf);
1006  data->n = 0;
1007  }
1008  return Qnil;
1009 }
1010 
1011 static int
1012 sort_by_cmp(const void *ap, const void *bp, void *data)
1013 {
1014  struct cmp_opt_data cmp_opt = { 0, 0 };
1015  VALUE a;
1016  VALUE b;
1017  VALUE ary = (VALUE)data;
1018 
1019  if (RBASIC(ary)->klass) {
1020  rb_raise(rb_eRuntimeError, "sort_by reentered");
1021  }
1022 
1023  a = *(VALUE *)ap;
1024  b = *(VALUE *)bp;
1025 
1026  return OPTIMIZED_CMP(a, b, cmp_opt);
1027 }
1028 
1029 /*
1030  * call-seq:
1031  * enum.sort_by { |obj| block } -> array
1032  * enum.sort_by -> an_enumerator
1033  *
1034  * Sorts <i>enum</i> using a set of keys generated by mapping the
1035  * values in <i>enum</i> through the given block.
1036  *
1037  * The result is not guaranteed to be stable. When two keys are equal,
1038  * the order of the corresponding elements is unpredictable.
1039  *
1040  * If no block is given, an enumerator is returned instead.
1041  *
1042  * %w{apple pear fig}.sort_by { |word| word.length }
1043  * #=> ["fig", "pear", "apple"]
1044  *
1045  * The current implementation of <code>sort_by</code> generates an
1046  * array of tuples containing the original collection element and the
1047  * mapped value. This makes <code>sort_by</code> fairly expensive when
1048  * the keysets are simple.
1049  *
1050  * require 'benchmark'
1051  *
1052  * a = (1..100000).map { rand(100000) }
1053  *
1054  * Benchmark.bm(10) do |b|
1055  * b.report("Sort") { a.sort }
1056  * b.report("Sort by") { a.sort_by { |a| a } }
1057  * end
1058  *
1059  * <em>produces:</em>
1060  *
1061  * user system total real
1062  * Sort 0.180000 0.000000 0.180000 ( 0.175469)
1063  * Sort by 1.980000 0.040000 2.020000 ( 2.013586)
1064  *
1065  * However, consider the case where comparing the keys is a non-trivial
1066  * operation. The following code sorts some files on modification time
1067  * using the basic <code>sort</code> method.
1068  *
1069  * files = Dir["*"]
1070  * sorted = files.sort { |a, b| File.new(a).mtime <=> File.new(b).mtime }
1071  * sorted #=> ["mon", "tues", "wed", "thurs"]
1072  *
1073  * This sort is inefficient: it generates two new <code>File</code>
1074  * objects during every comparison. A slightly better technique is to
1075  * use the <code>Kernel#test</code> method to generate the modification
1076  * times directly.
1077  *
1078  * files = Dir["*"]
1079  * sorted = files.sort { |a, b|
1080  * test(?M, a) <=> test(?M, b)
1081  * }
1082  * sorted #=> ["mon", "tues", "wed", "thurs"]
1083  *
1084  * This still generates many unnecessary <code>Time</code> objects. A
1085  * more efficient technique is to cache the sort keys (modification
1086  * times in this case) before the sort. Perl users often call this
1087  * approach a Schwartzian transform, after Randal Schwartz. We
1088  * construct a temporary array, where each element is an array
1089  * containing our sort key along with the filename. We sort this array,
1090  * and then extract the filename from the result.
1091  *
1092  * sorted = Dir["*"].collect { |f|
1093  * [test(?M, f), f]
1094  * }.sort.collect { |f| f[1] }
1095  * sorted #=> ["mon", "tues", "wed", "thurs"]
1096  *
1097  * This is exactly what <code>sort_by</code> does internally.
1098  *
1099  * sorted = Dir["*"].sort_by { |f| test(?M, f) }
1100  * sorted #=> ["mon", "tues", "wed", "thurs"]
1101  */
1102 
1103 static VALUE
1104 enum_sort_by(VALUE obj)
1105 {
1106  VALUE ary, buf;
1107  struct MEMO *memo;
1108  long i;
1109  struct sort_by_data *data;
1110 
1111  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1112 
1113  if (RB_TYPE_P(obj, T_ARRAY) && RARRAY_LEN(obj) <= LONG_MAX/2) {
1114  ary = rb_ary_new2(RARRAY_LEN(obj)*2);
1115  }
1116  else {
1117  ary = rb_ary_new();
1118  }
1119  RBASIC_CLEAR_CLASS(ary);
1121  rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
1122  memo = MEMO_NEW(0, 0, 0);
1123  OBJ_INFECT(memo, obj);
1124  data = (struct sort_by_data *)&memo->v1;
1125  RB_OBJ_WRITE(memo, &data->ary, ary);
1126  RB_OBJ_WRITE(memo, &data->buf, buf);
1127  data->n = 0;
1128  rb_block_call(obj, id_each, 0, 0, sort_by_i, (VALUE)memo);
1129  ary = data->ary;
1130  buf = data->buf;
1131  if (data->n) {
1132  rb_ary_resize(buf, data->n*2);
1133  rb_ary_concat(ary, buf);
1134  }
1135  if (RARRAY_LEN(ary) > 2) {
1136  RARRAY_PTR_USE(ary, ptr,
1137  ruby_qsort(ptr, RARRAY_LEN(ary)/2, 2*sizeof(VALUE),
1138  sort_by_cmp, (void *)ary));
1139  }
1140  if (RBASIC(ary)->klass) {
1141  rb_raise(rb_eRuntimeError, "sort_by reentered");
1142  }
1143  for (i=1; i<RARRAY_LEN(ary); i+=2) {
1144  RARRAY_ASET(ary, i/2, RARRAY_AREF(ary, i));
1145  }
1146  rb_ary_resize(ary, RARRAY_LEN(ary)/2);
1148  OBJ_INFECT(ary, memo);
1149 
1150  return ary;
1151 }
1152 
1153 #define ENUMFUNC(name) rb_block_given_p() ? name##_iter_i : name##_i
1154 
1155 #define DEFINE_ENUMFUNCS(name) \
1156 static VALUE enum_##name##_func(VALUE result, struct MEMO *memo); \
1157 \
1158 static VALUE \
1159 name##_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1160 { \
1161  return enum_##name##_func(rb_enum_values_pack(argc, argv), MEMO_CAST(memo)); \
1162 } \
1163 \
1164 static VALUE \
1165 name##_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1166 { \
1167  return enum_##name##_func(rb_yield_values2(argc, argv), MEMO_CAST(memo)); \
1168 } \
1169 \
1170 static VALUE \
1171 enum_##name##_func(VALUE result, struct MEMO *memo)
1172 
1174 {
1175  if (!RTEST(result)) {
1176  MEMO_V1_SET(memo, Qfalse);
1177  rb_iter_break();
1178  }
1179  return Qnil;
1180 }
1181 
1182 /*
1183  * call-seq:
1184  * enum.all? [{ |obj| block } ] -> true or false
1185  *
1186  * Passes each element of the collection to the given block. The method
1187  * returns <code>true</code> if the block never returns
1188  * <code>false</code> or <code>nil</code>. If the block is not given,
1189  * Ruby adds an implicit block of <code>{ |obj| obj }</code> which will
1190  * cause #all? to return +true+ when none of the collection members are
1191  * +false+ or +nil+.
1192  *
1193  * %w[ant bear cat].all? { |word| word.length >= 3 } #=> true
1194  * %w[ant bear cat].all? { |word| word.length >= 4 } #=> false
1195  * [nil, true, 99].all? #=> false
1196  * [].all? #=> true
1197  *
1198  */
1199 
1200 static VALUE
1201 enum_all(VALUE obj)
1202 {
1203  struct MEMO *memo = MEMO_NEW(Qtrue, 0, 0);
1204  rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
1205  return memo->v1;
1206 }
1207 
1209 {
1210  if (RTEST(result)) {
1211  MEMO_V1_SET(memo, Qtrue);
1212  rb_iter_break();
1213  }
1214  return Qnil;
1215 }
1216 
1217 /*
1218  * call-seq:
1219  * enum.any? [{ |obj| block }] -> true or false
1220  *
1221  * Passes each element of the collection to the given block. The method
1222  * returns <code>true</code> if the block ever returns a value other
1223  * than <code>false</code> or <code>nil</code>. If the block is not
1224  * given, Ruby adds an implicit block of <code>{ |obj| obj }</code> that
1225  * will cause #any? to return +true+ if at least one of the collection
1226  * members is not +false+ or +nil+.
1227  *
1228  * %w[ant bear cat].any? { |word| word.length >= 3 } #=> true
1229  * %w[ant bear cat].any? { |word| word.length >= 4 } #=> true
1230  * [nil, true, 99].any? #=> true
1231  * [].any? #=> false
1232  *
1233  */
1234 
1235 static VALUE
1236 enum_any(VALUE obj)
1237 {
1238  struct MEMO *memo = MEMO_NEW(Qfalse, 0, 0);
1239  rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
1240  return memo->v1;
1241 }
1242 
1244 {
1245  if (RTEST(result)) {
1246  if (memo->v1 == Qundef) {
1247  MEMO_V1_SET(memo, Qtrue);
1248  }
1249  else if (memo->v1 == Qtrue) {
1250  MEMO_V1_SET(memo, Qfalse);
1251  rb_iter_break();
1252  }
1253  }
1254  return Qnil;
1255 }
1256 
1257 struct nmin_data {
1258  long n;
1259  long bufmax;
1260  long curlen;
1263  int (*cmpfunc)(const void *, const void *, void *);
1264  int rev; /* max if 1 */
1265  int by; /* min_by if 1 */
1266  const char *method;
1267 };
1268 
1269 static VALUE
1270 cmpint_reenter_check(struct nmin_data *data, VALUE val)
1271 {
1272  if (RBASIC(data->buf)->klass) {
1273  rb_raise(rb_eRuntimeError, "%s reentered", data->method);
1274  }
1275  return val;
1276 }
1277 
1278 static int
1279 nmin_cmp(const void *ap, const void *bp, void *_data)
1280 {
1281  struct cmp_opt_data cmp_opt = { 0, 0 };
1282  struct nmin_data *data = (struct nmin_data *)_data;
1283  VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
1284 #define rb_cmpint(cmp, a, b) rb_cmpint(cmpint_reenter_check(data, (cmp)), a, b)
1285  return OPTIMIZED_CMP(a, b, cmp_opt);
1286 #undef rb_cmpint
1287 }
1288 
1289 static int
1290 nmin_block_cmp(const void *ap, const void *bp, void *_data)
1291 {
1292  struct nmin_data *data = (struct nmin_data *)_data;
1293  VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
1294  VALUE cmp = rb_yield_values(2, a, b);
1295  cmpint_reenter_check(data, cmp);
1296  return rb_cmpint(cmp, a, b);
1297 }
1298 
1299 static void
1300 nmin_filter(struct nmin_data *data)
1301 {
1302  long n;
1303  VALUE *beg;
1304  int eltsize;
1305  long numelts;
1306 
1307  long left, right;
1308  long store_index;
1309 
1310  long i, j;
1311 
1312  if (data->curlen <= data->n)
1313  return;
1314 
1315  n = data->n;
1316  beg = RARRAY_PTR(data->buf);
1317  eltsize = data->by ? 2 : 1;
1318  numelts = data->curlen;
1319 
1320  left = 0;
1321  right = numelts-1;
1322 
1323 #define GETPTR(i) (beg+(i)*eltsize)
1324 
1325 #define SWAP(i, j) do { \
1326  VALUE tmp[2]; \
1327  memcpy(tmp, GETPTR(i), sizeof(VALUE)*eltsize); \
1328  memcpy(GETPTR(i), GETPTR(j), sizeof(VALUE)*eltsize); \
1329  memcpy(GETPTR(j), tmp, sizeof(VALUE)*eltsize); \
1330 } while (0)
1331 
1332  while (1) {
1333  long pivot_index = left + (right-left)/2;
1334  long num_pivots = 1;
1335 
1336  SWAP(pivot_index, right);
1337  pivot_index = right;
1338 
1339  store_index = left;
1340  i = left;
1341  while (i <= right-num_pivots) {
1342  int c = data->cmpfunc(GETPTR(i), GETPTR(pivot_index), data);
1343  if (data->rev)
1344  c = -c;
1345  if (c == 0) {
1346  SWAP(i, right-num_pivots);
1347  num_pivots++;
1348  continue;
1349  }
1350  if (c < 0) {
1351  SWAP(i, store_index);
1352  store_index++;
1353  }
1354  i++;
1355  }
1356  j = store_index;
1357  for (i = right; right-num_pivots < i; i--) {
1358  if (i <= j)
1359  break;
1360  SWAP(j, i);
1361  j++;
1362  }
1363 
1364  if (store_index <= n && n <= store_index+num_pivots)
1365  break;
1366 
1367  if (n < store_index) {
1368  right = store_index-1;
1369  }
1370  else {
1371  left = store_index+num_pivots;
1372  }
1373  }
1374 #undef GETPTR
1375 #undef SWAP
1376 
1377  data->limit = RARRAY_PTR(data->buf)[store_index*eltsize]; /* the last pivot */
1378  data->curlen = data->n;
1379  rb_ary_resize(data->buf, data->n * eltsize);
1380 }
1381 
1382 static VALUE
1383 nmin_i(VALUE i, VALUE *_data, int argc, VALUE *argv)
1384 {
1385  struct nmin_data *data = (struct nmin_data *)_data;
1386  VALUE cmpv;
1387 
1388  ENUM_WANT_SVALUE();
1389 
1390  if (data->by)
1391  cmpv = enum_yield(argc, i);
1392  else
1393  cmpv = i;
1394 
1395  if (data->limit != Qundef) {
1396  int c = data->cmpfunc(&cmpv, &data->limit, data);
1397  if (data->rev)
1398  c = -c;
1399  if (c >= 0)
1400  return Qnil;
1401  }
1402 
1403  if (data->by)
1404  rb_ary_push(data->buf, cmpv);
1405  rb_ary_push(data->buf, i);
1406 
1407  data->curlen++;
1408 
1409  if (data->curlen == data->bufmax) {
1410  nmin_filter(data);
1411  }
1412 
1413  return Qnil;
1414 }
1415 
1416 VALUE
1417 rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary)
1418 {
1419  VALUE result;
1420  struct nmin_data data;
1421 
1422  data.n = NUM2LONG(num);
1423  if (data.n < 0)
1424  rb_raise(rb_eArgError, "negative size (%ld)", data.n);
1425  if (data.n == 0)
1426  return rb_ary_new2(0);
1427  if (LONG_MAX/4/(by ? 2 : 1) < data.n)
1428  rb_raise(rb_eArgError, "too big size");
1429  data.bufmax = data.n * 4;
1430  data.curlen = 0;
1431  data.buf = rb_ary_tmp_new(data.bufmax * (by ? 2 : 1));
1432  data.limit = Qundef;
1433  data.cmpfunc = by ? nmin_cmp :
1434  rb_block_given_p() ? nmin_block_cmp :
1435  nmin_cmp;
1436  data.rev = rev;
1437  data.by = by;
1438  data.method = rev ? (by ? "max_by" : "max")
1439  : (by ? "min_by" : "min");
1440  if (ary) {
1441  long i;
1442  for (i = 0; i < RARRAY_LEN(obj); i++) {
1443  VALUE args[1];
1444  args[0] = RARRAY_AREF(obj, i);
1445  nmin_i(obj, (VALUE*)&data, 1, args);
1446  }
1447  }
1448  else {
1449  rb_block_call(obj, id_each, 0, 0, nmin_i, (VALUE)&data);
1450  }
1451  nmin_filter(&data);
1452  result = data.buf;
1453  if (by) {
1454  long i;
1455  ruby_qsort(RARRAY_PTR(result),
1456  RARRAY_LEN(result)/2,
1457  sizeof(VALUE)*2,
1458  data.cmpfunc, (void *)&data);
1459  for (i=1; i<RARRAY_LEN(result); i+=2) {
1460  RARRAY_PTR(result)[i/2] = RARRAY_PTR(result)[i];
1461  }
1462  rb_ary_resize(result, RARRAY_LEN(result)/2);
1463  }
1464  else {
1465  ruby_qsort(RARRAY_PTR(result), RARRAY_LEN(result), sizeof(VALUE),
1466  data.cmpfunc, (void *)&data);
1467  }
1468  if (rev) {
1469  rb_ary_reverse(result);
1470  }
1471  RBASIC_SET_CLASS(result, rb_cArray);
1472  return result;
1473 
1474 }
1475 
1476 /*
1477  * call-seq:
1478  * enum.one? [{ |obj| block }] -> true or false
1479  *
1480  * Passes each element of the collection to the given block. The method
1481  * returns <code>true</code> if the block returns <code>true</code>
1482  * exactly once. If the block is not given, <code>one?</code> will return
1483  * <code>true</code> only if exactly one of the collection members is
1484  * true.
1485  *
1486  * %w{ant bear cat}.one? { |word| word.length == 4 } #=> true
1487  * %w{ant bear cat}.one? { |word| word.length > 4 } #=> false
1488  * %w{ant bear cat}.one? { |word| word.length < 4 } #=> false
1489  * [ nil, true, 99 ].one? #=> false
1490  * [ nil, true, false ].one? #=> true
1491  *
1492  */
1493 static VALUE
1494 enum_one(VALUE obj)
1495 {
1496  struct MEMO *memo = MEMO_NEW(Qundef, 0, 0);
1497  VALUE result;
1498 
1499  rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
1500  result = memo->v1;
1501  if (result == Qundef) return Qfalse;
1502  return result;
1503 }
1504 
1506 {
1507  if (RTEST(result)) {
1508  MEMO_V1_SET(memo, Qfalse);
1509  rb_iter_break();
1510  }
1511  return Qnil;
1512 }
1513 
1514 /*
1515  * call-seq:
1516  * enum.none? [{ |obj| block }] -> true or false
1517  *
1518  * Passes each element of the collection to the given block. The method
1519  * returns <code>true</code> if the block never returns <code>true</code>
1520  * for all elements. If the block is not given, <code>none?</code> will return
1521  * <code>true</code> only if none of the collection members is true.
1522  *
1523  * %w{ant bear cat}.none? { |word| word.length == 5 } #=> true
1524  * %w{ant bear cat}.none? { |word| word.length >= 4 } #=> false
1525  * [].none? #=> true
1526  * [nil].none? #=> true
1527  * [nil, false].none? #=> true
1528  * [nil, false, true].none? #=> false
1529  */
1530 static VALUE
1531 enum_none(VALUE obj)
1532 {
1533  struct MEMO *memo = MEMO_NEW(Qtrue, 0, 0);
1534  rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
1535  return memo->v1;
1536 }
1537 
1538 struct min_t {
1540  struct cmp_opt_data cmp_opt;
1541 };
1542 
1543 static VALUE
1544 min_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1545 {
1546  struct min_t *memo = MEMO_FOR(struct min_t, args);
1547 
1548  ENUM_WANT_SVALUE();
1549 
1550  if (memo->min == Qundef) {
1551  memo->min = i;
1552  }
1553  else {
1554  if (OPTIMIZED_CMP(i, memo->min, memo->cmp_opt) < 0) {
1555  memo->min = i;
1556  }
1557  }
1558  return Qnil;
1559 }
1560 
1561 static VALUE
1562 min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1563 {
1564  VALUE cmp;
1565  struct min_t *memo = MEMO_FOR(struct min_t, args);
1566 
1567  ENUM_WANT_SVALUE();
1568 
1569  if (memo->min == Qundef) {
1570  memo->min = i;
1571  }
1572  else {
1573  cmp = rb_yield_values(2, i, memo->min);
1574  if (rb_cmpint(cmp, i, memo->min) < 0) {
1575  memo->min = i;
1576  }
1577  }
1578  return Qnil;
1579 }
1580 
1581 
1582 /*
1583  * call-seq:
1584  * enum.min -> obj
1585  * enum.min { |a, b| block } -> obj
1586  * enum.min(n) -> array
1587  * enum.min(n) { |a, b| block } -> array
1588  *
1589  * Returns the object in _enum_ with the minimum value. The
1590  * first form assumes all objects implement <code>Comparable</code>;
1591  * the second uses the block to return <em>a <=> b</em>.
1592  *
1593  * a = %w(albatross dog horse)
1594  * a.min #=> "albatross"
1595  * a.min { |a, b| a.length <=> b.length } #=> "dog"
1596  *
1597  * If the +n+ argument is given, minimum +n+ elements are returned
1598  * as a sorted array.
1599  *
1600  * a = %w[albatross dog horse]
1601  * a.min(2) #=> ["albatross", "dog"]
1602  * a.min(2) {|a, b| a.length <=> b.length } #=> ["dog", "horse"]
1603  * [5, 1, 3, 4, 2].min(3) #=> [1, 2, 3]
1604  */
1605 
1606 static VALUE
1607 enum_min(int argc, VALUE *argv, VALUE obj)
1608 {
1609  VALUE memo;
1610  struct min_t *m = NEW_CMP_OPT_MEMO(struct min_t, memo);
1611  VALUE result;
1612  VALUE num;
1613 
1614  rb_scan_args(argc, argv, "01", &num);
1615 
1616  if (!NIL_P(num))
1617  return rb_nmin_run(obj, num, 0, 0, 0);
1618 
1619  m->min = Qundef;
1620  m->cmp_opt.opt_methods = 0;
1621  m->cmp_opt.opt_inited = 0;
1622  if (rb_block_given_p()) {
1623  rb_block_call(obj, id_each, 0, 0, min_ii, memo);
1624  }
1625  else {
1626  rb_block_call(obj, id_each, 0, 0, min_i, memo);
1627  }
1628  result = m->min;
1629  if (result == Qundef) return Qnil;
1630  return result;
1631 }
1632 
1633 struct max_t {
1635  struct cmp_opt_data cmp_opt;
1636 };
1637 
1638 static VALUE
1639 max_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1640 {
1641  struct max_t *memo = MEMO_FOR(struct max_t, args);
1642 
1643  ENUM_WANT_SVALUE();
1644 
1645  if (memo->max == Qundef) {
1646  memo->max = i;
1647  }
1648  else {
1649  if (OPTIMIZED_CMP(i, memo->max, memo->cmp_opt) > 0) {
1650  memo->max = i;
1651  }
1652  }
1653  return Qnil;
1654 }
1655 
1656 static VALUE
1657 max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1658 {
1659  struct max_t *memo = MEMO_FOR(struct max_t, args);
1660  VALUE cmp;
1661 
1662  ENUM_WANT_SVALUE();
1663 
1664  if (memo->max == Qundef) {
1665  memo->max = i;
1666  }
1667  else {
1668  cmp = rb_yield_values(2, i, memo->max);
1669  if (rb_cmpint(cmp, i, memo->max) > 0) {
1670  memo->max = i;
1671  }
1672  }
1673  return Qnil;
1674 }
1675 
1676 /*
1677  * call-seq:
1678  * enum.max -> obj
1679  * enum.max { |a, b| block } -> obj
1680  * enum.max(n) -> array
1681  * enum.max(n) { |a, b| block } -> array
1682  *
1683  * Returns the object in _enum_ with the maximum value. The
1684  * first form assumes all objects implement <code>Comparable</code>;
1685  * the second uses the block to return <em>a <=> b</em>.
1686  *
1687  * a = %w(albatross dog horse)
1688  * a.max #=> "horse"
1689  * a.max { |a, b| a.length <=> b.length } #=> "albatross"
1690  *
1691  * If the +n+ argument is given, maximum +n+ elements are returned
1692  * as an array, sorted in descending order.
1693  *
1694  * a = %w[albatross dog horse]
1695  * a.max(2) #=> ["horse", "dog"]
1696  * a.max(2) {|a, b| a.length <=> b.length } #=> ["albatross", "horse"]
1697  * [5, 1, 3, 4, 2].max(3) #=> [5, 4, 3]
1698  */
1699 
1700 static VALUE
1701 enum_max(int argc, VALUE *argv, VALUE obj)
1702 {
1703  VALUE memo;
1704  struct max_t *m = NEW_CMP_OPT_MEMO(struct max_t, memo);
1705  VALUE result;
1706  VALUE num;
1707 
1708  rb_scan_args(argc, argv, "01", &num);
1709 
1710  if (!NIL_P(num))
1711  return rb_nmin_run(obj, num, 0, 1, 0);
1712 
1713  m->max = Qundef;
1714  m->cmp_opt.opt_methods = 0;
1715  m->cmp_opt.opt_inited = 0;
1716  if (rb_block_given_p()) {
1717  rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)memo);
1718  }
1719  else {
1720  rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)memo);
1721  }
1722  result = m->max;
1723  if (result == Qundef) return Qnil;
1724  return result;
1725 }
1726 
1727 struct minmax_t {
1731  struct cmp_opt_data cmp_opt;
1732 };
1733 
1734 static void
1735 minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo)
1736 {
1737  int n;
1738 
1739  if (memo->min == Qundef) {
1740  memo->min = i;
1741  memo->max = j;
1742  }
1743  else {
1744  n = OPTIMIZED_CMP(i, memo->min, memo->cmp_opt);
1745  if (n < 0) {
1746  memo->min = i;
1747  }
1748  n = OPTIMIZED_CMP(j, memo->max, memo->cmp_opt);
1749  if (n > 0) {
1750  memo->max = j;
1751  }
1752  }
1753 }
1754 
1755 static VALUE
1756 minmax_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
1757 {
1758  struct minmax_t *memo = MEMO_FOR(struct minmax_t, _memo);
1759  int n;
1760  VALUE j;
1761 
1762  ENUM_WANT_SVALUE();
1763 
1764  if (memo->last == Qundef) {
1765  memo->last = i;
1766  return Qnil;
1767  }
1768  j = memo->last;
1769  memo->last = Qundef;
1770 
1771  n = OPTIMIZED_CMP(j, i, memo->cmp_opt);
1772  if (n == 0)
1773  i = j;
1774  else if (n < 0) {
1775  VALUE tmp;
1776  tmp = i;
1777  i = j;
1778  j = tmp;
1779  }
1780 
1781  minmax_i_update(i, j, memo);
1782 
1783  return Qnil;
1784 }
1785 
1786 static void
1787 minmax_ii_update(VALUE i, VALUE j, struct minmax_t *memo)
1788 {
1789  int n;
1790 
1791  if (memo->min == Qundef) {
1792  memo->min = i;
1793  memo->max = j;
1794  }
1795  else {
1796  n = rb_cmpint(rb_yield_values(2, i, memo->min), i, memo->min);
1797  if (n < 0) {
1798  memo->min = i;
1799  }
1800  n = rb_cmpint(rb_yield_values(2, j, memo->max), j, memo->max);
1801  if (n > 0) {
1802  memo->max = j;
1803  }
1804  }
1805 }
1806 
1807 static VALUE
1808 minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
1809 {
1810  struct minmax_t *memo = MEMO_FOR(struct minmax_t, _memo);
1811  int n;
1812  VALUE j;
1813 
1814  ENUM_WANT_SVALUE();
1815 
1816  if (memo->last == Qundef) {
1817  memo->last = i;
1818  return Qnil;
1819  }
1820  j = memo->last;
1821  memo->last = Qundef;
1822 
1823  n = rb_cmpint(rb_yield_values(2, j, i), j, i);
1824  if (n == 0)
1825  i = j;
1826  else if (n < 0) {
1827  VALUE tmp;
1828  tmp = i;
1829  i = j;
1830  j = tmp;
1831  }
1832 
1833  minmax_ii_update(i, j, memo);
1834 
1835  return Qnil;
1836 }
1837 
1838 /*
1839  * call-seq:
1840  * enum.minmax -> [min, max]
1841  * enum.minmax { |a, b| block } -> [min, max]
1842  *
1843  * Returns a two element array which contains the minimum and the
1844  * maximum value in the enumerable. The first form assumes all
1845  * objects implement <code>Comparable</code>; the second uses the
1846  * block to return <em>a <=> b</em>.
1847  *
1848  * a = %w(albatross dog horse)
1849  * a.minmax #=> ["albatross", "horse"]
1850  * a.minmax { |a, b| a.length <=> b.length } #=> ["dog", "albatross"]
1851  */
1852 
1853 static VALUE
1854 enum_minmax(VALUE obj)
1855 {
1856  VALUE memo;
1857  struct minmax_t *m = NEW_CMP_OPT_MEMO(struct minmax_t, memo);
1858 
1859  m->min = Qundef;
1860  m->last = Qundef;
1861  m->cmp_opt.opt_methods = 0;
1862  m->cmp_opt.opt_inited = 0;
1863  if (rb_block_given_p()) {
1864  rb_block_call(obj, id_each, 0, 0, minmax_ii, memo);
1865  if (m->last != Qundef)
1866  minmax_ii_update(m->last, m->last, m);
1867  }
1868  else {
1869  rb_block_call(obj, id_each, 0, 0, minmax_i, memo);
1870  if (m->last != Qundef)
1871  minmax_i_update(m->last, m->last, m);
1872  }
1873  if (m->min != Qundef) {
1874  return rb_assoc_new(m->min, m->max);
1875  }
1876  return rb_assoc_new(Qnil, Qnil);
1877 }
1878 
1879 static VALUE
1880 min_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1881 {
1882  struct cmp_opt_data cmp_opt = { 0, 0 };
1883  struct MEMO *memo = MEMO_CAST(args);
1884  VALUE v;
1885 
1886  ENUM_WANT_SVALUE();
1887 
1888  v = enum_yield(argc, i);
1889  if (memo->v1 == Qundef) {
1890  MEMO_V1_SET(memo, v);
1891  MEMO_V2_SET(memo, i);
1892  }
1893  else if (OPTIMIZED_CMP(v, memo->v1, cmp_opt) < 0) {
1894  MEMO_V1_SET(memo, v);
1895  MEMO_V2_SET(memo, i);
1896  }
1897  return Qnil;
1898 }
1899 
1900 /*
1901  * call-seq:
1902  * enum.min_by {|obj| block } -> obj
1903  * enum.min_by -> an_enumerator
1904  * enum.min_by(n) {|obj| block } -> array
1905  * enum.min_by(n) -> an_enumerator
1906  *
1907  * Returns the object in <i>enum</i> that gives the minimum
1908  * value from the given block.
1909  *
1910  * If no block is given, an enumerator is returned instead.
1911  *
1912  * a = %w(albatross dog horse)
1913  * a.min_by { |x| x.length } #=> "dog"
1914  *
1915  * If the +n+ argument is given, minimum +n+ elements are returned
1916  * as an array. These +n+ elements are sorted by the value from the
1917  * given block.
1918  *
1919  * a = %w[albatross dog horse]
1920  * p a.min_by(2) {|x| x.length } #=> ["dog", "horse"]
1921  */
1922 
1923 static VALUE
1924 enum_min_by(int argc, VALUE *argv, VALUE obj)
1925 {
1926  struct MEMO *memo;
1927  VALUE num;
1928 
1929  rb_scan_args(argc, argv, "01", &num);
1930 
1931  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
1932 
1933  if (!NIL_P(num))
1934  return rb_nmin_run(obj, num, 1, 0, 0);
1935 
1936  memo = MEMO_NEW(Qundef, Qnil, 0);
1937  rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
1938  return memo->v2;
1939 }
1940 
1941 static VALUE
1942 max_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1943 {
1944  struct cmp_opt_data cmp_opt = { 0, 0 };
1945  struct MEMO *memo = MEMO_CAST(args);
1946  VALUE v;
1947 
1948  ENUM_WANT_SVALUE();
1949 
1950  v = enum_yield(argc, i);
1951  if (memo->v1 == Qundef) {
1952  MEMO_V1_SET(memo, v);
1953  MEMO_V2_SET(memo, i);
1954  }
1955  else if (OPTIMIZED_CMP(v, memo->v1, cmp_opt) > 0) {
1956  MEMO_V1_SET(memo, v);
1957  MEMO_V2_SET(memo, i);
1958  }
1959  return Qnil;
1960 }
1961 
1962 /*
1963  * call-seq:
1964  * enum.max_by {|obj| block } -> obj
1965  * enum.max_by -> an_enumerator
1966  * enum.max_by(n) {|obj| block } -> obj
1967  * enum.max_by(n) -> an_enumerator
1968  *
1969  * Returns the object in <i>enum</i> that gives the maximum
1970  * value from the given block.
1971  *
1972  * If no block is given, an enumerator is returned instead.
1973  *
1974  * a = %w(albatross dog horse)
1975  * a.max_by { |x| x.length } #=> "albatross"
1976  *
1977  * If the +n+ argument is given, maximum +n+ elements are returned
1978  * as an array. These +n+ elements are sorted by the value from the
1979  * given block, in descending order.
1980  *
1981  * a = %w[albatross dog horse]
1982  * a.max_by(2) {|x| x.length } #=> ["albatross", "horse"]
1983  *
1984  * enum.max_by(n) can be used to implement weighted random sampling.
1985  * Following example implements and use Enumerable#wsample.
1986  *
1987  * module Enumerable
1988  * # weighted random sampling.
1989  * #
1990  * # Pavlos S. Efraimidis, Paul G. Spirakis
1991  * # Weighted random sampling with a reservoir
1992  * # Information Processing Letters
1993  * # Volume 97, Issue 5 (16 March 2006)
1994  * def wsample(n)
1995  * self.max_by(n) {|v| rand ** (1.0/yield(v)) }
1996  * end
1997  * end
1998  * e = (-20..20).to_a*10000
1999  * a = e.wsample(20000) {|x|
2000  * Math.exp(-(x/5.0)**2) # normal distribution
2001  * }
2002  * # a is 20000 samples from e.
2003  * p a.length #=> 20000
2004  * h = a.group_by {|x| x }
2005  * -10.upto(10) {|x| puts "*" * (h[x].length/30.0).to_i if h[x] }
2006  * #=> *
2007  * # ***
2008  * # ******
2009  * # ***********
2010  * # ******************
2011  * # *****************************
2012  * # *****************************************
2013  * # ****************************************************
2014  * # ***************************************************************
2015  * # ********************************************************************
2016  * # ***********************************************************************
2017  * # ***********************************************************************
2018  * # **************************************************************
2019  * # ****************************************************
2020  * # ***************************************
2021  * # ***************************
2022  * # ******************
2023  * # ***********
2024  * # *******
2025  * # ***
2026  * # *
2027  *
2028  */
2029 
2030 static VALUE
2031 enum_max_by(int argc, VALUE *argv, VALUE obj)
2032 {
2033  struct MEMO *memo;
2034  VALUE num;
2035 
2036  rb_scan_args(argc, argv, "01", &num);
2037 
2038  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
2039 
2040  if (!NIL_P(num))
2041  return rb_nmin_run(obj, num, 1, 1, 0);
2042 
2043  memo = MEMO_NEW(Qundef, Qnil, 0);
2044  rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
2045  return memo->v2;
2046 }
2047 
2048 struct minmax_by_t {
2055 };
2056 
2057 static void
2058 minmax_by_i_update(VALUE v1, VALUE v2, VALUE i1, VALUE i2, struct minmax_by_t *memo)
2059 {
2060  struct cmp_opt_data cmp_opt = { 0, 0 };
2061 
2062  if (memo->min_bv == Qundef) {
2063  memo->min_bv = v1;
2064  memo->max_bv = v2;
2065  memo->min = i1;
2066  memo->max = i2;
2067  }
2068  else {
2069  if (OPTIMIZED_CMP(v1, memo->min_bv, cmp_opt) < 0) {
2070  memo->min_bv = v1;
2071  memo->min = i1;
2072  }
2073  if (OPTIMIZED_CMP(v2, memo->max_bv, cmp_opt) > 0) {
2074  memo->max_bv = v2;
2075  memo->max = i2;
2076  }
2077  }
2078 }
2079 
2080 static VALUE
2081 minmax_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
2082 {
2083  struct cmp_opt_data cmp_opt = { 0, 0 };
2084  struct minmax_by_t *memo = MEMO_FOR(struct minmax_by_t, _memo);
2085  VALUE vi, vj, j;
2086  int n;
2087 
2088  ENUM_WANT_SVALUE();
2089 
2090  vi = enum_yield(argc, i);
2091 
2092  if (memo->last_bv == Qundef) {
2093  memo->last_bv = vi;
2094  memo->last = i;
2095  return Qnil;
2096  }
2097  vj = memo->last_bv;
2098  j = memo->last;
2099  memo->last_bv = Qundef;
2100 
2101  n = OPTIMIZED_CMP(vj, vi, cmp_opt);
2102  if (n == 0) {
2103  i = j;
2104  vi = vj;
2105  }
2106  else if (n < 0) {
2107  VALUE tmp;
2108  tmp = i;
2109  i = j;
2110  j = tmp;
2111  tmp = vi;
2112  vi = vj;
2113  vj = tmp;
2114  }
2115 
2116  minmax_by_i_update(vi, vj, i, j, memo);
2117 
2118  return Qnil;
2119 }
2120 
2121 /*
2122  * call-seq:
2123  * enum.minmax_by { |obj| block } -> [min, max]
2124  * enum.minmax_by -> an_enumerator
2125  *
2126  * Returns a two element array containing the objects in
2127  * <i>enum</i> that correspond to the minimum and maximum values respectively
2128  * from the given block.
2129  *
2130  * If no block is given, an enumerator is returned instead.
2131  *
2132  * a = %w(albatross dog horse)
2133  * a.minmax_by { |x| x.length } #=> ["dog", "albatross"]
2134  */
2135 
2136 static VALUE
2137 enum_minmax_by(VALUE obj)
2138 {
2139  VALUE memo;
2140  struct minmax_by_t *m = NEW_MEMO_FOR(struct minmax_by_t, memo);
2141 
2142  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
2143 
2144  m->min_bv = Qundef;
2145  m->max_bv = Qundef;
2146  m->min = Qnil;
2147  m->max = Qnil;
2148  m->last_bv = Qundef;
2149  m->last = Qundef;
2150  rb_block_call(obj, id_each, 0, 0, minmax_by_i, memo);
2151  if (m->last_bv != Qundef)
2152  minmax_by_i_update(m->last_bv, m->last_bv, m->last, m->last, m);
2153  m = MEMO_FOR(struct minmax_by_t, memo);
2154  return rb_assoc_new(m->min, m->max);
2155 }
2156 
2157 static VALUE
2158 member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args))
2159 {
2160  struct MEMO *memo = MEMO_CAST(args);
2161 
2162  if (rb_equal(rb_enum_values_pack(argc, argv), memo->v1)) {
2163  MEMO_V2_SET(memo, Qtrue);
2164  rb_iter_break();
2165  }
2166  return Qnil;
2167 }
2168 
2169 /*
2170  * call-seq:
2171  * enum.include?(obj) -> true or false
2172  * enum.member?(obj) -> true or false
2173  *
2174  * Returns <code>true</code> if any member of <i>enum</i> equals
2175  * <i>obj</i>. Equality is tested using <code>==</code>.
2176  *
2177  * IO.constants.include? :SEEK_SET #=> true
2178  * IO.constants.include? :SEEK_NO_FURTHER #=> false
2179  * IO.constants.member? :SEEK_SET #=> true
2180  * IO.constants.member? :SEEK_NO_FURTHER #=> false
2181  *
2182  */
2183 
2184 static VALUE
2185 enum_member(VALUE obj, VALUE val)
2186 {
2187  struct MEMO *memo = MEMO_NEW(val, Qfalse, 0);
2188 
2189  rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
2190  return memo->v2;
2191 }
2192 
2193 static VALUE
2194 each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
2195 {
2196  long n = MEMO_CAST(memo)->u3.cnt++;
2197 
2198  return rb_yield_values(2, rb_enum_values_pack(argc, argv), INT2NUM(n));
2199 }
2200 
2201 /*
2202  * call-seq:
2203  * enum.each_with_index(*args) { |obj, i| block } -> enum
2204  * enum.each_with_index(*args) -> an_enumerator
2205  *
2206  * Calls <em>block</em> with two arguments, the item and its index,
2207  * for each item in <i>enum</i>. Given arguments are passed through
2208  * to #each().
2209  *
2210  * If no block is given, an enumerator is returned instead.
2211  *
2212  * hash = Hash.new
2213  * %w(cat dog wombat).each_with_index { |item, index|
2214  * hash[item] = index
2215  * }
2216  * hash #=> {"cat"=>0, "dog"=>1, "wombat"=>2}
2217  *
2218  */
2219 
2220 static VALUE
2221 enum_each_with_index(int argc, VALUE *argv, VALUE obj)
2222 {
2223  struct MEMO *memo;
2224 
2225  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
2226 
2227  memo = MEMO_NEW(0, 0, 0);
2228  rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo);
2229  return obj;
2230 }
2231 
2232 
2233 /*
2234  * call-seq:
2235  * enum.reverse_each(*args) { |item| block } -> enum
2236  * enum.reverse_each(*args) -> an_enumerator
2237  *
2238  * Builds a temporary array and traverses that array in reverse order.
2239  *
2240  * If no block is given, an enumerator is returned instead.
2241  *
2242  * (1..3).reverse_each { |v| p v }
2243  *
2244  * produces:
2245  *
2246  * 3
2247  * 2
2248  * 1
2249  */
2250 
2251 static VALUE
2252 enum_reverse_each(int argc, VALUE *argv, VALUE obj)
2253 {
2254  VALUE ary;
2255  long i;
2256 
2257  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
2258 
2259  ary = enum_to_a(argc, argv, obj);
2260 
2261  for (i = RARRAY_LEN(ary); --i >= 0; ) {
2262  rb_yield(RARRAY_AREF(ary, i));
2263  }
2264 
2265  return obj;
2266 }
2267 
2268 
2269 static VALUE
2270 each_val_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
2271 {
2272  ENUM_WANT_SVALUE();
2273  enum_yield(argc, i);
2274  return Qnil;
2275 }
2276 
2277 /*
2278  * call-seq:
2279  * enum.each_entry { |obj| block } -> enum
2280  * enum.each_entry -> an_enumerator
2281  *
2282  * Calls <i>block</i> once for each element in +self+, passing that
2283  * element as a parameter, converting multiple values from yield to an
2284  * array.
2285  *
2286  * If no block is given, an enumerator is returned instead.
2287  *
2288  * class Foo
2289  * include Enumerable
2290  * def each
2291  * yield 1
2292  * yield 1, 2
2293  * yield
2294  * end
2295  * end
2296  * Foo.new.each_entry{ |o| p o }
2297  *
2298  * produces:
2299  *
2300  * 1
2301  * [1, 2]
2302  * nil
2303  *
2304  */
2305 
2306 static VALUE
2307 enum_each_entry(int argc, VALUE *argv, VALUE obj)
2308 {
2309  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
2310  rb_block_call(obj, id_each, argc, argv, each_val_i, 0);
2311  return obj;
2312 }
2313 
2314 static VALUE
2315 add_int(VALUE x, long n)
2316 {
2317  const VALUE y = LONG2NUM(n);
2318  if (RB_INTEGER_TYPE_P(x)) return rb_int_plus(x, y);
2319  return rb_funcallv(x, '+', 1, &y);
2320 }
2321 
2322 static VALUE
2323 div_int(VALUE x, long n)
2324 {
2325  const VALUE y = LONG2NUM(n);
2326  if (RB_INTEGER_TYPE_P(x)) return rb_int_idiv(x, y);
2327  return rb_funcallv(x, id_div, 1, &y);
2328 }
2329 
2330 #define dont_recycle_block_arg(arity) ((arity) == 1 || (arity) < 0)
2331 
2332 static VALUE
2333 each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, m))
2334 {
2335  struct MEMO *memo = MEMO_CAST(m);
2336  VALUE ary = memo->v1;
2337  VALUE v = Qnil;
2338  long size = memo->u3.cnt;
2339  ENUM_WANT_SVALUE();
2340 
2341  rb_ary_push(ary, i);
2342 
2343  if (RARRAY_LEN(ary) == size) {
2344  v = rb_yield(ary);
2345 
2346  if (memo->v2) {
2347  MEMO_V1_SET(memo, rb_ary_new2(size));
2348  }
2349  else {
2350  rb_ary_clear(ary);
2351  }
2352  }
2353 
2354  return v;
2355 }
2356 
2357 static VALUE
2358 enum_each_slice_size(VALUE obj, VALUE args, VALUE eobj)
2359 {
2360  VALUE n, size;
2361  long slice_size = NUM2LONG(RARRAY_AREF(args, 0));
2362  if (slice_size <= 0) rb_raise(rb_eArgError, "invalid slice size");
2363 
2364  size = enum_size(obj, 0, 0);
2365  if (size == Qnil) return Qnil;
2366 
2367  n = add_int(size, slice_size-1);
2368  return div_int(n, slice_size);
2369 }
2370 
2371 /*
2372  * call-seq:
2373  * enum.each_slice(n) { ... } -> nil
2374  * enum.each_slice(n) -> an_enumerator
2375  *
2376  * Iterates the given block for each slice of <n> elements. If no
2377  * block is given, returns an enumerator.
2378  *
2379  * (1..10).each_slice(3) { |a| p a }
2380  * # outputs below
2381  * [1, 2, 3]
2382  * [4, 5, 6]
2383  * [7, 8, 9]
2384  * [10]
2385  *
2386  */
2387 static VALUE
2388 enum_each_slice(VALUE obj, VALUE n)
2389 {
2390  long size = NUM2LONG(n);
2391  VALUE ary;
2392  struct MEMO *memo;
2393  int arity;
2394 
2395  if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
2396  RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_slice_size);
2397  size = limit_by_enum_size(obj, size);
2398  ary = rb_ary_new2(size);
2399  arity = rb_block_arity();
2400  memo = MEMO_NEW(ary, dont_recycle_block_arg(arity), size);
2401  rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
2402  ary = memo->v1;
2403  if (RARRAY_LEN(ary) > 0) rb_yield(ary);
2404 
2405  return Qnil;
2406 }
2407 
2408 static VALUE
2409 each_cons_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2410 {
2411  struct MEMO *memo = MEMO_CAST(args);
2412  VALUE ary = memo->v1;
2413  VALUE v = Qnil;
2414  long size = memo->u3.cnt;
2415  ENUM_WANT_SVALUE();
2416 
2417  if (RARRAY_LEN(ary) == size) {
2418  rb_ary_shift(ary);
2419  }
2420  rb_ary_push(ary, i);
2421  if (RARRAY_LEN(ary) == size) {
2422  if (memo->v2) {
2423  ary = rb_ary_dup(ary);
2424  }
2425  v = rb_yield(ary);
2426  }
2427  return v;
2428 }
2429 
2430 static VALUE
2431 enum_each_cons_size(VALUE obj, VALUE args, VALUE eobj)
2432 {
2433  struct cmp_opt_data cmp_opt = { 0, 0 };
2434  const VALUE zero = LONG2FIX(0);
2435  VALUE n, size;
2436  long cons_size = NUM2LONG(RARRAY_AREF(args, 0));
2437  if (cons_size <= 0) rb_raise(rb_eArgError, "invalid size");
2438 
2439  size = enum_size(obj, 0, 0);
2440  if (size == Qnil) return Qnil;
2441 
2442  n = add_int(size, 1 - cons_size);
2443  return (OPTIMIZED_CMP(n, zero, cmp_opt) == -1) ? zero : n;
2444 }
2445 
2446 /*
2447  * call-seq:
2448  * enum.each_cons(n) { ... } -> nil
2449  * enum.each_cons(n) -> an_enumerator
2450  *
2451  * Iterates the given block for each array of consecutive <n>
2452  * elements. If no block is given, returns an enumerator.
2453  *
2454  * e.g.:
2455  * (1..10).each_cons(3) { |a| p a }
2456  * # outputs below
2457  * [1, 2, 3]
2458  * [2, 3, 4]
2459  * [3, 4, 5]
2460  * [4, 5, 6]
2461  * [5, 6, 7]
2462  * [6, 7, 8]
2463  * [7, 8, 9]
2464  * [8, 9, 10]
2465  *
2466  */
2467 static VALUE
2468 enum_each_cons(VALUE obj, VALUE n)
2469 {
2470  long size = NUM2LONG(n);
2471  struct MEMO *memo;
2472  int arity;
2473 
2474  if (size <= 0) rb_raise(rb_eArgError, "invalid size");
2475  RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size);
2476  arity = rb_block_arity();
2477  if (enum_size_over_p(obj, size)) return Qnil;
2478  memo = MEMO_NEW(rb_ary_new2(size), dont_recycle_block_arg(arity), size);
2479  rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo);
2480 
2481  return Qnil;
2482 }
2483 
2484 static VALUE
2485 each_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
2486 {
2487  ENUM_WANT_SVALUE();
2488  return rb_yield_values(2, i, memo);
2489 }
2490 
2491 /*
2492  * call-seq:
2493  * enum.each_with_object(obj) { |(*args), memo_obj| ... } -> obj
2494  * enum.each_with_object(obj) -> an_enumerator
2495  *
2496  * Iterates the given block for each element with an arbitrary
2497  * object given, and returns the initially given object.
2498  *
2499  * If no block is given, returns an enumerator.
2500  *
2501  * evens = (1..10).each_with_object([]) { |i, a| a << i*2 }
2502  * #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
2503  *
2504  */
2505 static VALUE
2506 enum_each_with_object(VALUE obj, VALUE memo)
2507 {
2508  RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enum_size);
2509 
2510  rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);
2511 
2512  return memo;
2513 }
2514 
2515 static VALUE
2516 zip_ary(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
2517 {
2518  struct MEMO *memo = (struct MEMO *)memoval;
2519  VALUE result = memo->v1;
2520  VALUE args = memo->v2;
2521  long n = memo->u3.cnt++;
2522  VALUE tmp;
2523  int i;
2524 
2525  tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
2526  rb_ary_store(tmp, 0, rb_enum_values_pack(argc, argv));
2527  for (i=0; i<RARRAY_LEN(args); i++) {
2528  VALUE e = RARRAY_AREF(args, i);
2529 
2530  if (RARRAY_LEN(e) <= n) {
2531  rb_ary_push(tmp, Qnil);
2532  }
2533  else {
2534  rb_ary_push(tmp, RARRAY_AREF(e, n));
2535  }
2536  }
2537  if (NIL_P(result)) {
2538  enum_yield_array(tmp);
2539  }
2540  else {
2541  rb_ary_push(result, tmp);
2542  }
2543 
2544  RB_GC_GUARD(args);
2545 
2546  return Qnil;
2547 }
2548 
2549 static VALUE
2550 call_next(VALUE *v)
2551 {
2552  return v[0] = rb_funcallv(v[1], id_next, 0, 0);
2553 }
2554 
2555 static VALUE
2556 call_stop(VALUE *v)
2557 {
2558  return v[0] = Qundef;
2559 }
2560 
2561 static VALUE
2562 zip_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
2563 {
2564  struct MEMO *memo = (struct MEMO *)memoval;
2565  VALUE result = memo->v1;
2566  VALUE args = memo->v2;
2567  VALUE tmp;
2568  int i;
2569 
2570  tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
2571  rb_ary_store(tmp, 0, rb_enum_values_pack(argc, argv));
2572  for (i=0; i<RARRAY_LEN(args); i++) {
2573  if (NIL_P(RARRAY_AREF(args, i))) {
2574  rb_ary_push(tmp, Qnil);
2575  }
2576  else {
2577  VALUE v[2];
2578 
2579  v[1] = RARRAY_AREF(args, i);
2580  rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, (VALUE)0);
2581  if (v[0] == Qundef) {
2582  RARRAY_ASET(args, i, Qnil);
2583  v[0] = Qnil;
2584  }
2585  rb_ary_push(tmp, v[0]);
2586  }
2587  }
2588  if (NIL_P(result)) {
2589  enum_yield_array(tmp);
2590  }
2591  else {
2592  rb_ary_push(result, tmp);
2593  }
2594 
2595  RB_GC_GUARD(args);
2596 
2597  return Qnil;
2598 }
2599 
2600 /*
2601  * call-seq:
2602  * enum.zip(arg, ...) -> an_array_of_array
2603  * enum.zip(arg, ...) { |arr| block } -> nil
2604  *
2605  * Takes one element from <i>enum</i> and merges corresponding
2606  * elements from each <i>args</i>. This generates a sequence of
2607  * <em>n</em>-element arrays, where <em>n</em> is one more than the
2608  * count of arguments. The length of the resulting sequence will be
2609  * <code>enum#size</code>. If the size of any argument is less than
2610  * <code>enum#size</code>, <code>nil</code> values are supplied. If
2611  * a block is given, it is invoked for each output array, otherwise
2612  * an array of arrays is returned.
2613  *
2614  * a = [ 4, 5, 6 ]
2615  * b = [ 7, 8, 9 ]
2616  *
2617  * a.zip(b) #=> [[4, 7], [5, 8], [6, 9]]
2618  * [1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
2619  * [1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
2620  * a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
2621  *
2622  * c = []
2623  * a.zip(b) { |x, y| c << x + y } #=> nil
2624  * c #=> [11, 13, 15]
2625  *
2626  */
2627 
2628 static VALUE
2629 enum_zip(int argc, VALUE *argv, VALUE obj)
2630 {
2631  int i;
2632  ID conv;
2633  struct MEMO *memo;
2634  VALUE result = Qnil;
2635  VALUE args = rb_ary_new4(argc, argv);
2636  int allary = TRUE;
2637 
2638  argv = RARRAY_PTR(args);
2639  for (i=0; i<argc; i++) {
2640  VALUE ary = rb_check_array_type(argv[i]);
2641  if (NIL_P(ary)) {
2642  allary = FALSE;
2643  break;
2644  }
2645  argv[i] = ary;
2646  }
2647  if (!allary) {
2648  static const VALUE sym_each = STATIC_ID2SYM(id_each);
2649  CONST_ID(conv, "to_enum");
2650  for (i=0; i<argc; i++) {
2651  if (!rb_respond_to(argv[i], id_each)) {
2652  rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
2653  rb_obj_class(argv[i]));
2654  }
2655  argv[i] = rb_funcallv(argv[i], conv, 1, &sym_each);
2656  }
2657  }
2658  if (!rb_block_given_p()) {
2659  result = rb_ary_new();
2660  }
2661 
2662  /* TODO: use NODE_DOT2 as memo(v, v, -) */
2663  memo = MEMO_NEW(result, args, 0);
2664  rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
2665 
2666  return result;
2667 }
2668 
2669 static VALUE
2670 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2671 {
2672  struct MEMO *memo = MEMO_CAST(args);
2673  rb_ary_push(memo->v1, rb_enum_values_pack(argc, argv));
2674  if (--memo->u3.cnt == 0) rb_iter_break();
2675  return Qnil;
2676 }
2677 
2678 /*
2679  * call-seq:
2680  * enum.take(n) -> array
2681  *
2682  * Returns first n elements from <i>enum</i>.
2683  *
2684  * a = [1, 2, 3, 4, 5, 0]
2685  * a.take(3) #=> [1, 2, 3]
2686  * a.take(30) #=> [1, 2, 3, 4, 5, 0]
2687  *
2688  */
2689 
2690 static VALUE
2691 enum_take(VALUE obj, VALUE n)
2692 {
2693  struct MEMO *memo;
2694  VALUE result;
2695  long len = NUM2LONG(n);
2696 
2697  if (len < 0) {
2698  rb_raise(rb_eArgError, "attempt to take negative size");
2699  }
2700 
2701  if (len == 0) return rb_ary_new2(0);
2702  result = rb_ary_new2(len);
2703  memo = MEMO_NEW(result, 0, len);
2704  rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)memo);
2705  return result;
2706 }
2707 
2708 
2709 static VALUE
2710 take_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
2711 {
2712  if (!RTEST(rb_yield_values2(argc, argv))) rb_iter_break();
2713  rb_ary_push(ary, rb_enum_values_pack(argc, argv));
2714  return Qnil;
2715 }
2716 
2717 /*
2718  * call-seq:
2719  * enum.take_while { |obj| block } -> array
2720  * enum.take_while -> an_enumerator
2721  *
2722  * Passes elements to the block until the block returns +nil+ or +false+,
2723  * then stops iterating and returns an array of all prior elements.
2724  *
2725  * If no block is given, an enumerator is returned instead.
2726  *
2727  * a = [1, 2, 3, 4, 5, 0]
2728  * a.take_while { |i| i < 3 } #=> [1, 2]
2729  *
2730  */
2731 
2732 static VALUE
2733 enum_take_while(VALUE obj)
2734 {
2735  VALUE ary;
2736 
2737  RETURN_ENUMERATOR(obj, 0, 0);
2738  ary = rb_ary_new();
2739  rb_block_call(obj, id_each, 0, 0, take_while_i, ary);
2740  return ary;
2741 }
2742 
2743 static VALUE
2744 drop_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2745 {
2746  struct MEMO *memo = MEMO_CAST(args);
2747  if (memo->u3.cnt == 0) {
2748  rb_ary_push(memo->v1, rb_enum_values_pack(argc, argv));
2749  }
2750  else {
2751  memo->u3.cnt--;
2752  }
2753  return Qnil;
2754 }
2755 
2756 /*
2757  * call-seq:
2758  * enum.drop(n) -> array
2759  *
2760  * Drops first n elements from <i>enum</i>, and returns rest elements
2761  * in an array.
2762  *
2763  * a = [1, 2, 3, 4, 5, 0]
2764  * a.drop(3) #=> [4, 5, 0]
2765  *
2766  */
2767 
2768 static VALUE
2769 enum_drop(VALUE obj, VALUE n)
2770 {
2771  VALUE result;
2772  struct MEMO *memo;
2773  long len = NUM2LONG(n);
2774 
2775  if (len < 0) {
2776  rb_raise(rb_eArgError, "attempt to drop negative size");
2777  }
2778 
2779  result = rb_ary_new();
2780  memo = MEMO_NEW(result, 0, len);
2781  rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)memo);
2782  return result;
2783 }
2784 
2785 
2786 static VALUE
2787 drop_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2788 {
2789  struct MEMO *memo = MEMO_CAST(args);
2790  ENUM_WANT_SVALUE();
2791 
2792  if (!memo->u3.state && !RTEST(enum_yield(argc, i))) {
2793  memo->u3.state = TRUE;
2794  }
2795  if (memo->u3.state) {
2796  rb_ary_push(memo->v1, i);
2797  }
2798  return Qnil;
2799 }
2800 
2801 /*
2802  * call-seq:
2803  * enum.drop_while { |obj| block } -> array
2804  * enum.drop_while -> an_enumerator
2805  *
2806  * Drops elements up to, but not including, the first element for
2807  * which the block returns +nil+ or +false+ and returns an array
2808  * containing the remaining elements.
2809  *
2810  * If no block is given, an enumerator is returned instead.
2811  *
2812  * a = [1, 2, 3, 4, 5, 0]
2813  * a.drop_while { |i| i < 3 } #=> [3, 4, 5, 0]
2814  *
2815  */
2816 
2817 static VALUE
2818 enum_drop_while(VALUE obj)
2819 {
2820  VALUE result;
2821  struct MEMO *memo;
2822 
2823  RETURN_ENUMERATOR(obj, 0, 0);
2824  result = rb_ary_new();
2825  memo = MEMO_NEW(result, 0, FALSE);
2826  rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)memo);
2827  return result;
2828 }
2829 
2830 static VALUE
2831 cycle_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
2832 {
2833  ENUM_WANT_SVALUE();
2834 
2835  rb_ary_push(ary, argc > 1 ? i : rb_ary_new_from_values(argc, argv));
2836  enum_yield(argc, i);
2837  return Qnil;
2838 }
2839 
2840 static VALUE
2841 enum_cycle_size(VALUE self, VALUE args, VALUE eobj)
2842 {
2843  long mul;
2844  VALUE n = Qnil;
2845  VALUE size = enum_size(self, args, 0);
2846 
2847  if (size == Qnil) return Qnil;
2848 
2849  if (args && (RARRAY_LEN(args) > 0)) {
2850  n = RARRAY_AREF(args, 0);
2851  }
2852  if (n == Qnil) return DBL2NUM(INFINITY);
2853  mul = NUM2LONG(n);
2854  if (mul <= 0) return INT2FIX(0);
2855  n = LONG2FIX(mul);
2856  return rb_funcallv(size, '*', 1, &n);
2857 }
2858 
2859 /*
2860  * call-seq:
2861  * enum.cycle(n=nil) { |obj| block } -> nil
2862  * enum.cycle(n=nil) -> an_enumerator
2863  *
2864  * Calls <i>block</i> for each element of <i>enum</i> repeatedly _n_
2865  * times or forever if none or +nil+ is given. If a non-positive
2866  * number is given or the collection is empty, does nothing. Returns
2867  * +nil+ if the loop has finished without getting interrupted.
2868  *
2869  * Enumerable#cycle saves elements in an internal array so changes
2870  * to <i>enum</i> after the first pass have no effect.
2871  *
2872  * If no block is given, an enumerator is returned instead.
2873  *
2874  * a = ["a", "b", "c"]
2875  * a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever.
2876  * a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c.
2877  *
2878  */
2879 
2880 static VALUE
2881 enum_cycle(int argc, VALUE *argv, VALUE obj)
2882 {
2883  VALUE ary;
2884  VALUE nv = Qnil;
2885  long n, i, len;
2886 
2887  rb_scan_args(argc, argv, "01", &nv);
2888 
2889  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_cycle_size);
2890  if (NIL_P(nv)) {
2891  n = -1;
2892  }
2893  else {
2894  n = NUM2LONG(nv);
2895  if (n <= 0) return Qnil;
2896  }
2897  ary = rb_ary_new();
2898  RBASIC_CLEAR_CLASS(ary);
2899  rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
2900  len = RARRAY_LEN(ary);
2901  if (len == 0) return Qnil;
2902  while (n < 0 || 0 < --n) {
2903  for (i=0; i<len; i++) {
2904  enum_yield_array(RARRAY_AREF(ary, i));
2905  }
2906  }
2907  return Qnil;
2908 }
2909 
2910 struct chunk_arg {
2915 };
2916 
2917 static VALUE
2918 chunk_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
2919 {
2920  struct chunk_arg *argp = MEMO_FOR(struct chunk_arg, _argp);
2921  VALUE v, s;
2922  VALUE alone = ID2SYM(rb_intern("_alone"));
2923  VALUE separator = ID2SYM(rb_intern("_separator"));
2924 
2925  ENUM_WANT_SVALUE();
2926 
2927  v = rb_funcallv(argp->categorize, id_call, 1, &i);
2928 
2929  if (v == alone) {
2930  if (!NIL_P(argp->prev_value)) {
2931  s = rb_assoc_new(argp->prev_value, argp->prev_elts);
2932  rb_funcallv(argp->yielder, id_lshift, 1, &s);
2933  argp->prev_value = argp->prev_elts = Qnil;
2934  }
2935  v = rb_assoc_new(v, rb_ary_new3(1, i));
2936  rb_funcallv(argp->yielder, id_lshift, 1, &v);
2937  }
2938  else if (NIL_P(v) || v == separator) {
2939  if (!NIL_P(argp->prev_value)) {
2940  v = rb_assoc_new(argp->prev_value, argp->prev_elts);
2941  rb_funcallv(argp->yielder, id_lshift, 1, &v);
2942  argp->prev_value = argp->prev_elts = Qnil;
2943  }
2944  }
2945  else if (SYMBOL_P(v) && (s = rb_sym2str(v), RSTRING_PTR(s)[0] == '_')) {
2946  rb_raise(rb_eRuntimeError, "symbols beginning with an underscore are reserved");
2947  }
2948  else {
2949  if (NIL_P(argp->prev_value)) {
2950  argp->prev_value = v;
2951  argp->prev_elts = rb_ary_new3(1, i);
2952  }
2953  else {
2954  if (rb_equal(argp->prev_value, v)) {
2955  rb_ary_push(argp->prev_elts, i);
2956  }
2957  else {
2958  s = rb_assoc_new(argp->prev_value, argp->prev_elts);
2959  rb_funcallv(argp->yielder, id_lshift, 1, &s);
2960  argp->prev_value = v;
2961  argp->prev_elts = rb_ary_new3(1, i);
2962  }
2963  }
2964  }
2965  return Qnil;
2966 }
2967 
2968 static VALUE
2970 {
2971  VALUE enumerable;
2972  VALUE arg;
2973  struct chunk_arg *memo = NEW_MEMO_FOR(struct chunk_arg, arg);
2974 
2975  enumerable = rb_ivar_get(enumerator, rb_intern("chunk_enumerable"));
2976  memo->categorize = rb_ivar_get(enumerator, rb_intern("chunk_categorize"));
2977  memo->prev_value = Qnil;
2978  memo->prev_elts = Qnil;
2979  memo->yielder = yielder;
2980 
2981  rb_block_call(enumerable, id_each, 0, 0, chunk_ii, arg);
2982  memo = MEMO_FOR(struct chunk_arg, arg);
2983  if (!NIL_P(memo->prev_elts)) {
2984  arg = rb_assoc_new(memo->prev_value, memo->prev_elts);
2985  rb_funcallv(memo->yielder, id_lshift, 1, &arg);
2986  }
2987  return Qnil;
2988 }
2989 
2990 /*
2991  * call-seq:
2992  * enum.chunk { |elt| ... } -> an_enumerator
2993  *
2994  * Enumerates over the items, chunking them together based on the return
2995  * value of the block.
2996  *
2997  * Consecutive elements which return the same block value are chunked together.
2998  *
2999  * For example, consecutive even numbers and odd numbers can be
3000  * chunked as follows.
3001  *
3002  * [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk { |n|
3003  * n.even?
3004  * }.each { |even, ary|
3005  * p [even, ary]
3006  * }
3007  * #=> [false, [3, 1]]
3008  * # [true, [4]]
3009  * # [false, [1, 5, 9]]
3010  * # [true, [2, 6]]
3011  * # [false, [5, 3, 5]]
3012  *
3013  * This method is especially useful for sorted series of elements.
3014  * The following example counts words for each initial letter.
3015  *
3016  * open("/usr/share/dict/words", "r:iso-8859-1") { |f|
3017  * f.chunk { |line| line.ord }.each { |ch, lines| p [ch.chr, lines.length] }
3018  * }
3019  * #=> ["\n", 1]
3020  * # ["A", 1327]
3021  * # ["B", 1372]
3022  * # ["C", 1507]
3023  * # ["D", 791]
3024  * # ...
3025  *
3026  * The following key values have special meaning:
3027  * - +nil+ and +:_separator+ specifies that the elements should be dropped.
3028  * - +:_alone+ specifies that the element should be chunked by itself.
3029  *
3030  * Any other symbols that begin with an underscore will raise an error:
3031  *
3032  * items.chunk { |item| :_underscore }
3033  * #=> RuntimeError: symbols beginning with an underscore are reserved
3034  *
3035  * +nil+ and +:_separator+ can be used to ignore some elements.
3036  *
3037  * For example, the sequence of hyphens in svn log can be eliminated as follows:
3038  *
3039  * sep = "-"*72 + "\n"
3040  * IO.popen("svn log README") { |f|
3041  * f.chunk { |line|
3042  * line != sep || nil
3043  * }.each { |_, lines|
3044  * pp lines
3045  * }
3046  * }
3047  * #=> ["r20018 | knu | 2008-10-29 13:20:42 +0900 (Wed, 29 Oct 2008) | 2 lines\n",
3048  * # "\n",
3049  * # "* README, README.ja: Update the portability section.\n",
3050  * # "\n"]
3051  * # ["r16725 | knu | 2008-05-31 23:34:23 +0900 (Sat, 31 May 2008) | 2 lines\n",
3052  * # "\n",
3053  * # "* README, README.ja: Add a note about default C flags.\n",
3054  * # "\n"]
3055  * # ...
3056  *
3057  * Paragraphs separated by empty lines can be parsed as follows:
3058  *
3059  * File.foreach("README").chunk { |line|
3060  * /\A\s*\z/ !~ line || nil
3061  * }.each { |_, lines|
3062  * pp lines
3063  * }
3064  *
3065  * +:_alone+ can be used to force items into their own chunk.
3066  * For example, you can put lines that contain a URL by themselves,
3067  * and chunk the rest of the lines together, like this:
3068  *
3069  * pattern = /http/
3070  * open(filename) { |f|
3071  * f.chunk { |line| line =~ pattern ? :_alone : true }.each { |key, lines|
3072  * pp lines
3073  * }
3074  * }
3075  *
3076  * If no block is given, an enumerator to `chunk` is returned instead.
3077  */
3078 static VALUE
3079 enum_chunk(VALUE enumerable)
3080 {
3081  VALUE enumerator;
3082 
3083  RETURN_SIZED_ENUMERATOR(enumerable, 0, 0, enum_size);
3084 
3085  enumerator = rb_obj_alloc(rb_cEnumerator);
3086  rb_ivar_set(enumerator, rb_intern("chunk_enumerable"), enumerable);
3087  rb_ivar_set(enumerator, rb_intern("chunk_categorize"), rb_block_proc());
3088  rb_block_call(enumerator, idInitialize, 0, 0, chunk_i, enumerator);
3089  return enumerator;
3090 }
3091 
3092 
3098 };
3099 
3100 static VALUE
3101 slicebefore_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
3102 {
3103  struct slicebefore_arg *argp = MEMO_FOR(struct slicebefore_arg, _argp);
3104  VALUE header_p;
3105 
3106  ENUM_WANT_SVALUE();
3107 
3108  if (!NIL_P(argp->sep_pat))
3109  header_p = rb_funcallv(argp->sep_pat, id_eqq, 1, &i);
3110  else
3111  header_p = rb_funcallv(argp->sep_pred, id_call, 1, &i);
3112  if (RTEST(header_p)) {
3113  if (!NIL_P(argp->prev_elts))
3114  rb_funcallv(argp->yielder, id_lshift, 1, &argp->prev_elts);
3115  argp->prev_elts = rb_ary_new3(1, i);
3116  }
3117  else {
3118  if (NIL_P(argp->prev_elts))
3119  argp->prev_elts = rb_ary_new3(1, i);
3120  else
3121  rb_ary_push(argp->prev_elts, i);
3122  }
3123 
3124  return Qnil;
3125 }
3126 
3127 static VALUE
3129 {
3130  VALUE enumerable;
3131  VALUE arg;
3132  struct slicebefore_arg *memo = NEW_MEMO_FOR(struct slicebefore_arg, arg);
3133 
3134  enumerable = rb_ivar_get(enumerator, rb_intern("slicebefore_enumerable"));
3135  memo->sep_pred = rb_attr_get(enumerator, rb_intern("slicebefore_sep_pred"));
3136  memo->sep_pat = NIL_P(memo->sep_pred) ? rb_ivar_get(enumerator, rb_intern("slicebefore_sep_pat")) : Qnil;
3137  memo->prev_elts = Qnil;
3138  memo->yielder = yielder;
3139 
3140  rb_block_call(enumerable, id_each, 0, 0, slicebefore_ii, arg);
3141  memo = MEMO_FOR(struct slicebefore_arg, arg);
3142  if (!NIL_P(memo->prev_elts))
3143  rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
3144  return Qnil;
3145 }
3146 
3147 /*
3148  * call-seq:
3149  * enum.slice_before(pattern) -> an_enumerator
3150  * enum.slice_before { |elt| bool } -> an_enumerator
3151  *
3152  * Creates an enumerator for each chunked elements.
3153  * The beginnings of chunks are defined by _pattern_ and the block.
3154 
3155  * If <code>_pattern_ === _elt_</code> returns <code>true</code> or the block
3156  * returns <code>true</code> for the element, the element is beginning of a
3157  * chunk.
3158 
3159  * The <code>===</code> and _block_ is called from the first element to the last
3160  * element of _enum_. The result for the first element is ignored.
3161 
3162  * The result enumerator yields the chunked elements as an array.
3163  * So +each+ method can be called as follows:
3164  *
3165  * enum.slice_before(pattern).each { |ary| ... }
3166  * enum.slice_before { |elt| bool }.each { |ary| ... }
3167  *
3168  * Other methods of the Enumerator class and Enumerable module,
3169  * such as +to_a+, +map+, etc., are also usable.
3170  *
3171  * For example, iteration over ChangeLog entries can be implemented as
3172  * follows:
3173  *
3174  * # iterate over ChangeLog entries.
3175  * open("ChangeLog") { |f|
3176  * f.slice_before(/\A\S/).each { |e| pp e }
3177  * }
3178  *
3179  * # same as above. block is used instead of pattern argument.
3180  * open("ChangeLog") { |f|
3181  * f.slice_before { |line| /\A\S/ === line }.each { |e| pp e }
3182  * }
3183  *
3184  *
3185  * "svn proplist -R" produces multiline output for each file.
3186  * They can be chunked as follows:
3187  *
3188  * IO.popen([{"LC_ALL"=>"C"}, "svn", "proplist", "-R"]) { |f|
3189  * f.lines.slice_before(/\AProp/).each { |lines| p lines }
3190  * }
3191  * #=> ["Properties on '.':\n", " svn:ignore\n", " svk:merge\n"]
3192  * # ["Properties on 'goruby.c':\n", " svn:eol-style\n"]
3193  * # ["Properties on 'complex.c':\n", " svn:mime-type\n", " svn:eol-style\n"]
3194  * # ["Properties on 'regparse.c':\n", " svn:eol-style\n"]
3195  * # ...
3196  *
3197  * If the block needs to maintain state over multiple elements,
3198  * local variables can be used.
3199  * For example, three or more consecutive increasing numbers can be squashed
3200  * as follows (see +chunk_while+ for a better way):
3201  *
3202  * a = [0, 2, 3, 4, 6, 7, 9]
3203  * prev = a[0]
3204  * p a.slice_before { |e|
3205  * prev, prev2 = e, prev
3206  * prev2 + 1 != e
3207  * }.map { |es|
3208  * es.length <= 2 ? es.join(",") : "#{es.first}-#{es.last}"
3209  * }.join(",")
3210  * #=> "0,2-4,6,7,9"
3211  *
3212  * However local variables should be used carefully
3213  * if the result enumerator is enumerated twice or more.
3214  * The local variables should be initialized for each enumeration.
3215  * Enumerator.new can be used to do it.
3216  *
3217  * # Word wrapping. This assumes all characters have same width.
3218  * def wordwrap(words, maxwidth)
3219  * Enumerator.new {|y|
3220  * # cols is initialized in Enumerator.new.
3221  * cols = 0
3222  * words.slice_before { |w|
3223  * cols += 1 if cols != 0
3224  * cols += w.length
3225  * if maxwidth < cols
3226  * cols = w.length
3227  * true
3228  * else
3229  * false
3230  * end
3231  * }.each {|ws| y.yield ws }
3232  * }
3233  * end
3234  * text = (1..20).to_a.join(" ")
3235  * enum = wordwrap(text.split(/\s+/), 10)
3236  * puts "-"*10
3237  * enum.each { |ws| puts ws.join(" ") } # first enumeration.
3238  * puts "-"*10
3239  * enum.each { |ws| puts ws.join(" ") } # second enumeration generates same result as the first.
3240  * puts "-"*10
3241  * #=> ----------
3242  * # 1 2 3 4 5
3243  * # 6 7 8 9 10
3244  * # 11 12 13
3245  * # 14 15 16
3246  * # 17 18 19
3247  * # 20
3248  * # ----------
3249  * # 1 2 3 4 5
3250  * # 6 7 8 9 10
3251  * # 11 12 13
3252  * # 14 15 16
3253  * # 17 18 19
3254  * # 20
3255  * # ----------
3256  *
3257  * mbox contains series of mails which start with Unix From line.
3258  * So each mail can be extracted by slice before Unix From line.
3259  *
3260  * # parse mbox
3261  * open("mbox") { |f|
3262  * f.slice_before { |line|
3263  * line.start_with? "From "
3264  * }.each { |mail|
3265  * unix_from = mail.shift
3266  * i = mail.index("\n")
3267  * header = mail[0...i]
3268  * body = mail[(i+1)..-1]
3269  * body.pop if body.last == "\n"
3270  * fields = header.slice_before { |line| !" \t".include?(line[0]) }.to_a
3271  * p unix_from
3272  * pp fields
3273  * pp body
3274  * }
3275  * }
3276  *
3277  * # split mails in mbox (slice before Unix From line after an empty line)
3278  * open("mbox") { |f|
3279  * emp = true
3280  * f.slice_before { |line|
3281  * prevemp = emp
3282  * emp = line == "\n"
3283  * prevemp && line.start_with?("From ")
3284  * }.each { |mail|
3285  * mail.pop if mail.last == "\n"
3286  * pp mail
3287  * }
3288  * }
3289  *
3290  */
3291 static VALUE
3292 enum_slice_before(int argc, VALUE *argv, VALUE enumerable)
3293 {
3294  VALUE enumerator;
3295 
3296  if (rb_block_given_p()) {
3297  if (argc != 0)
3298  rb_error_arity(argc, 0, 0);
3299  enumerator = rb_obj_alloc(rb_cEnumerator);
3300  rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pred"), rb_block_proc());
3301  }
3302  else {
3303  VALUE sep_pat;
3304  rb_scan_args(argc, argv, "1", &sep_pat);
3305  enumerator = rb_obj_alloc(rb_cEnumerator);
3306  rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pat"), sep_pat);
3307  }
3308  rb_ivar_set(enumerator, rb_intern("slicebefore_enumerable"), enumerable);
3309  rb_block_call(enumerator, idInitialize, 0, 0, slicebefore_i, enumerator);
3310  return enumerator;
3311 }
3312 
3313 
3319 };
3320 
3321 static VALUE
3322 sliceafter_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
3323 {
3324 #define UPDATE_MEMO ((void)(memo = MEMO_FOR(struct sliceafter_arg, _memo)))
3325  struct sliceafter_arg *memo;
3326  int split_p;
3327  UPDATE_MEMO;
3328 
3329  ENUM_WANT_SVALUE();
3330 
3331  if (NIL_P(memo->prev_elts)) {
3332  memo->prev_elts = rb_ary_new3(1, i);
3333  }
3334  else {
3335  rb_ary_push(memo->prev_elts, i);
3336  }
3337 
3338  if (NIL_P(memo->pred)) {
3339  split_p = RTEST(rb_funcallv(memo->pat, id_eqq, 1, &i));
3340  UPDATE_MEMO;
3341  }
3342  else {
3343  split_p = RTEST(rb_funcallv(memo->pred, id_call, 1, &i));
3344  UPDATE_MEMO;
3345  }
3346 
3347  if (split_p) {
3348  rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
3349  UPDATE_MEMO;
3350  memo->prev_elts = Qnil;
3351  }
3352 
3353  return Qnil;
3354 #undef UPDATE_MEMO
3355 }
3356 
3357 static VALUE
3359 {
3360  VALUE enumerable;
3361  VALUE arg;
3362  struct sliceafter_arg *memo = NEW_MEMO_FOR(struct sliceafter_arg, arg);
3363 
3364  enumerable = rb_ivar_get(enumerator, rb_intern("sliceafter_enum"));
3365  memo->pat = rb_ivar_get(enumerator, rb_intern("sliceafter_pat"));
3366  memo->pred = rb_attr_get(enumerator, rb_intern("sliceafter_pred"));
3367  memo->prev_elts = Qnil;
3368  memo->yielder = yielder;
3369 
3370  rb_block_call(enumerable, id_each, 0, 0, sliceafter_ii, arg);
3371  memo = MEMO_FOR(struct sliceafter_arg, arg);
3372  if (!NIL_P(memo->prev_elts))
3373  rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
3374  return Qnil;
3375 }
3376 
3377 /*
3378  * call-seq:
3379  * enum.slice_after(pattern) -> an_enumerator
3380  * enum.slice_after { |elt| bool } -> an_enumerator
3381  *
3382  * Creates an enumerator for each chunked elements.
3383  * The ends of chunks are defined by _pattern_ and the block.
3384  *
3385  * If <code>_pattern_ === _elt_</code> returns <code>true</code> or the block
3386  * returns <code>true</code> for the element, the element is end of a
3387  * chunk.
3388  *
3389  * The <code>===</code> and _block_ is called from the first element to the last
3390  * element of _enum_.
3391  *
3392  * The result enumerator yields the chunked elements as an array.
3393  * So +each+ method can be called as follows:
3394  *
3395  * enum.slice_after(pattern).each { |ary| ... }
3396  * enum.slice_after { |elt| bool }.each { |ary| ... }
3397  *
3398  * Other methods of the Enumerator class and Enumerable module,
3399  * such as +map+, etc., are also usable.
3400  *
3401  * For example, continuation lines (lines end with backslash) can be
3402  * concatenated as follows:
3403  *
3404  * lines = ["foo\n", "bar\\\n", "baz\n", "\n", "qux\n"]
3405  * e = lines.slice_after(/(?<!\\)\n\z/)
3406  * p e.to_a
3407  * #=> [["foo\n"], ["bar\\\n", "baz\n"], ["\n"], ["qux\n"]]
3408  * p e.map {|ll| ll[0...-1].map {|l| l.sub(/\\\n\z/, "") }.join + ll.last }
3409  * #=>["foo\n", "barbaz\n", "\n", "qux\n"]
3410  *
3411  */
3412 
3413 static VALUE
3414 enum_slice_after(int argc, VALUE *argv, VALUE enumerable)
3415 {
3416  VALUE enumerator;
3417  VALUE pat = Qnil, pred = Qnil;
3418 
3419  if (rb_block_given_p()) {
3420  if (0 < argc)
3421  rb_raise(rb_eArgError, "both pattern and block are given");
3422  pred = rb_block_proc();
3423  }
3424  else {
3425  rb_scan_args(argc, argv, "1", &pat);
3426  }
3427 
3428  enumerator = rb_obj_alloc(rb_cEnumerator);
3429  rb_ivar_set(enumerator, rb_intern("sliceafter_enum"), enumerable);
3430  rb_ivar_set(enumerator, rb_intern("sliceafter_pat"), pat);
3431  rb_ivar_set(enumerator, rb_intern("sliceafter_pred"), pred);
3432 
3433  rb_block_call(enumerator, idInitialize, 0, 0, sliceafter_i, enumerator);
3434  return enumerator;
3435 }
3436 
3442  int inverted; /* 0 for slice_when and 1 for chunk_while. */
3443 };
3444 
3445 static VALUE
3446 slicewhen_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
3447 {
3448 #define UPDATE_MEMO ((void)(memo = MEMO_FOR(struct slicewhen_arg, _memo)))
3449  struct slicewhen_arg *memo;
3450  int split_p;
3451  UPDATE_MEMO;
3452 
3453  ENUM_WANT_SVALUE();
3454 
3455  if (memo->prev_elt == Qundef) {
3456  /* The first element */
3457  memo->prev_elt = i;
3458  memo->prev_elts = rb_ary_new3(1, i);
3459  }
3460  else {
3461  VALUE args[2];
3462  args[0] = memo->prev_elt;
3463  args[1] = i;
3464  split_p = RTEST(rb_funcallv(memo->pred, id_call, 2, args));
3465  UPDATE_MEMO;
3466 
3467  if (memo->inverted)
3468  split_p = !split_p;
3469 
3470  if (split_p) {
3471  rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
3472  UPDATE_MEMO;
3473  memo->prev_elts = rb_ary_new3(1, i);
3474  }
3475  else {
3476  rb_ary_push(memo->prev_elts, i);
3477  }
3478 
3479  memo->prev_elt = i;
3480  }
3481 
3482  return Qnil;
3483 #undef UPDATE_MEMO
3484 }
3485 
3486 static VALUE
3488 {
3489  VALUE enumerable;
3490  VALUE arg;
3491  struct slicewhen_arg *memo =
3493 
3494  enumerable = rb_ivar_get(enumerator, rb_intern("slicewhen_enum"));
3495  memo->pred = rb_attr_get(enumerator, rb_intern("slicewhen_pred"));
3496  memo->prev_elt = Qundef;
3497  memo->prev_elts = Qnil;
3498  memo->yielder = yielder;
3499  memo->inverted = RTEST(rb_attr_get(enumerator, rb_intern("slicewhen_inverted")));
3500 
3501  rb_block_call(enumerable, id_each, 0, 0, slicewhen_ii, arg);
3502  memo = MEMO_FOR(struct slicewhen_arg, arg);
3503  if (!NIL_P(memo->prev_elts))
3504  rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
3505  return Qnil;
3506 }
3507 
3508 /*
3509  * call-seq:
3510  * enum.slice_when {|elt_before, elt_after| bool } -> an_enumerator
3511  *
3512  * Creates an enumerator for each chunked elements.
3513  * The beginnings of chunks are defined by the block.
3514  *
3515  * This method split each chunk using adjacent elements,
3516  * _elt_before_ and _elt_after_,
3517  * in the receiver enumerator.
3518  * This method split chunks between _elt_before_ and _elt_after_ where
3519  * the block returns <code>true</code>.
3520  *
3521  * The block is called the length of the receiver enumerator minus one.
3522  *
3523  * The result enumerator yields the chunked elements as an array.
3524  * So +each+ method can be called as follows:
3525  *
3526  * enum.slice_when { |elt_before, elt_after| bool }.each { |ary| ... }
3527  *
3528  * Other methods of the Enumerator class and Enumerable module,
3529  * such as +to_a+, +map+, etc., are also usable.
3530  *
3531  * For example, one-by-one increasing subsequence can be chunked as follows:
3532  *
3533  * a = [1,2,4,9,10,11,12,15,16,19,20,21]
3534  * b = a.slice_when {|i, j| i+1 != j }
3535  * p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
3536  * c = b.map {|a| a.length < 3 ? a : "#{a.first}-#{a.last}" }
3537  * p c #=> [[1, 2], [4], "9-12", [15, 16], "19-21"]
3538  * d = c.join(",")
3539  * p d #=> "1,2,4,9-12,15,16,19-21"
3540  *
3541  * Near elements (threshold: 6) in sorted array can be chunked as follows:
3542  *
3543  * a = [3, 11, 14, 25, 28, 29, 29, 41, 55, 57]
3544  * p a.slice_when {|i, j| 6 < j - i }.to_a
3545  * #=> [[3], [11, 14], [25, 28, 29, 29], [41], [55, 57]]
3546  *
3547  * Increasing (non-decreasing) subsequence can be chunked as follows:
3548  *
3549  * a = [0, 9, 2, 2, 3, 2, 7, 5, 9, 5]
3550  * p a.slice_when {|i, j| i > j }.to_a
3551  * #=> [[0, 9], [2, 2, 3], [2, 7], [5, 9], [5]]
3552  *
3553  * Adjacent evens and odds can be chunked as follows:
3554  * (Enumerable#chunk is another way to do it.)
3555  *
3556  * a = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]
3557  * p a.slice_when {|i, j| i.even? != j.even? }.to_a
3558  * #=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]
3559  *
3560  * Paragraphs (non-empty lines with trailing empty lines) can be chunked as follows:
3561  * (See Enumerable#chunk to ignore empty lines.)
3562  *
3563  * lines = ["foo\n", "bar\n", "\n", "baz\n", "qux\n"]
3564  * p lines.slice_when {|l1, l2| /\A\s*\z/ =~ l1 && /\S/ =~ l2 }.to_a
3565  * #=> [["foo\n", "bar\n", "\n"], ["baz\n", "qux\n"]]
3566  *
3567  * Enumerable#chunk_while does the same, except splitting when the block
3568  * returns <code>false</code> instead of <code>true</code>.
3569  */
3570 static VALUE
3571 enum_slice_when(VALUE enumerable)
3572 {
3573  VALUE enumerator;
3574  VALUE pred;
3575 
3576  pred = rb_block_proc();
3577 
3578  enumerator = rb_obj_alloc(rb_cEnumerator);
3579  rb_ivar_set(enumerator, rb_intern("slicewhen_enum"), enumerable);
3580  rb_ivar_set(enumerator, rb_intern("slicewhen_pred"), pred);
3581  rb_ivar_set(enumerator, rb_intern("slicewhen_inverted"), Qfalse);
3582 
3583  rb_block_call(enumerator, idInitialize, 0, 0, slicewhen_i, enumerator);
3584  return enumerator;
3585 }
3586 
3587 /*
3588  * call-seq:
3589  * enum.chunk_while {|elt_before, elt_after| bool } -> an_enumerator
3590  *
3591  * Creates an enumerator for each chunked elements.
3592  * The beginnings of chunks are defined by the block.
3593  *
3594  * This method split each chunk using adjacent elements,
3595  * _elt_before_ and _elt_after_,
3596  * in the receiver enumerator.
3597  * This method split chunks between _elt_before_ and _elt_after_ where
3598  * the block returns <code>false</code>.
3599  *
3600  * The block is called the length of the receiver enumerator minus one.
3601  *
3602  * The result enumerator yields the chunked elements as an array.
3603  * So +each+ method can be called as follows:
3604  *
3605  * enum.chunk_while { |elt_before, elt_after| bool }.each { |ary| ... }
3606  *
3607  * Other methods of the Enumerator class and Enumerable module,
3608  * such as +to_a+, +map+, etc., are also usable.
3609  *
3610  * For example, one-by-one increasing subsequence can be chunked as follows:
3611  *
3612  * a = [1,2,4,9,10,11,12,15,16,19,20,21]
3613  * b = a.chunk_while {|i, j| i+1 == j }
3614  * p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
3615  * c = b.map {|a| a.length < 3 ? a : "#{a.first}-#{a.last}" }
3616  * p c #=> [[1, 2], [4], "9-12", [15, 16], "19-21"]
3617  * d = c.join(",")
3618  * p d #=> "1,2,4,9-12,15,16,19-21"
3619  *
3620  * Increasing (non-decreasing) subsequence can be chunked as follows:
3621  *
3622  * a = [0, 9, 2, 2, 3, 2, 7, 5, 9, 5]
3623  * p a.chunk_while {|i, j| i <= j }.to_a
3624  * #=> [[0, 9], [2, 2, 3], [2, 7], [5, 9], [5]]
3625  *
3626  * Adjacent evens and odds can be chunked as follows:
3627  * (Enumerable#chunk is another way to do it.)
3628  *
3629  * a = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]
3630  * p a.chunk_while {|i, j| i.even? == j.even? }.to_a
3631  * #=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]
3632  *
3633  * Enumerable#slice_when does the same, except splitting when the block
3634  * returns <code>true</code> instead of <code>false</code>.
3635  */
3636 static VALUE
3637 enum_chunk_while(VALUE enumerable)
3638 {
3639  VALUE enumerator;
3640  VALUE pred;
3641 
3642  pred = rb_block_proc();
3643 
3644  enumerator = rb_obj_alloc(rb_cEnumerator);
3645  rb_ivar_set(enumerator, rb_intern("slicewhen_enum"), enumerable);
3646  rb_ivar_set(enumerator, rb_intern("slicewhen_pred"), pred);
3647  rb_ivar_set(enumerator, rb_intern("slicewhen_inverted"), Qtrue);
3648 
3649  rb_block_call(enumerator, idInitialize, 0, 0, slicewhen_i, enumerator);
3650  return enumerator;
3651 }
3652 
3654  VALUE v, r;
3655  long n;
3656  double f, c;
3659 };
3660 
3661 static void
3662 sum_iter(VALUE i, struct enum_sum_memo *memo)
3663 {
3664  const int unused = (assert(memo != NULL), 0);
3665 
3666  long n = memo->n;
3667  VALUE v = memo->v;
3668  VALUE r = memo->r;
3669  double f = memo->f;
3670  double c = memo->c;
3671 
3672  if (memo->block_given)
3673  i = rb_yield(i);
3674 
3675  if (memo->float_value)
3676  goto float_value;
3677 
3678  if (FIXNUM_P(v) || RB_TYPE_P(v, T_BIGNUM) || RB_TYPE_P(v, T_RATIONAL)) {
3679  if (FIXNUM_P(i)) {
3680  n += FIX2LONG(i); /* should not overflow long type */
3681  if (!FIXABLE(n)) {
3682  v = rb_big_plus(LONG2NUM(n), v);
3683  n = 0;
3684  }
3685  }
3686  else if (RB_TYPE_P(i, T_BIGNUM))
3687  v = rb_big_plus(i, v);
3688  else if (RB_TYPE_P(i, T_RATIONAL)) {
3689  if (r == Qundef)
3690  r = i;
3691  else
3692  r = rb_rational_plus(r, i);
3693  }
3694  else {
3695  if (n != 0) {
3696  v = rb_fix_plus(LONG2FIX(n), v);
3697  n = 0;
3698  }
3699  if (r != Qundef) {
3700  /* r can be an Integer when mathn is loaded */
3701  if (FIXNUM_P(r))
3702  v = rb_fix_plus(r, v);
3703  else if (RB_TYPE_P(r, T_BIGNUM))
3704  v = rb_big_plus(r, v);
3705  else
3706  v = rb_rational_plus(r, v);
3707  r = Qundef;
3708  }
3709  if (RB_FLOAT_TYPE_P(i)) {
3710  f = NUM2DBL(v);
3711  c = 0.0;
3712  memo->float_value = 1;
3713  goto float_value;
3714  }
3715  else
3716  goto some_value;
3717  }
3718  }
3719  else if (RB_FLOAT_TYPE_P(v)) {
3720  /*
3721  * Kahan-Babuska balancing compensated summation algorithm
3722  * See http://link.springer.com/article/10.1007/s00607-005-0139-x
3723  */
3724  double x, t;
3725 
3726  float_value:
3727  if (RB_FLOAT_TYPE_P(i))
3728  x = RFLOAT_VALUE(i);
3729  else if (FIXNUM_P(i))
3730  x = FIX2LONG(i);
3731  else if (RB_TYPE_P(i, T_BIGNUM))
3732  x = rb_big2dbl(i);
3733  else if (RB_TYPE_P(i, T_RATIONAL))
3734  x = rb_num2dbl(i);
3735  else {
3736  v = DBL2NUM(f);
3737  memo->float_value = 0;
3738  goto some_value;
3739  }
3740 
3741  t = f + x;
3742  if (fabs(f) >= fabs(x))
3743  c += ((f - t) + x);
3744  else
3745  c += ((x - t) + f);
3746  f = t;
3747  }
3748  else {
3749  some_value:
3750  v = rb_funcallv(v, idPLUS, 1, &i);
3751  }
3752 
3753  memo->v = v;
3754  memo->n = n;
3755  memo->r = r;
3756  memo->f = f;
3757  memo->c = c;
3758  (void)unused;
3759 }
3760 
3761 static VALUE
3762 enum_sum_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
3763 {
3764  ENUM_WANT_SVALUE();
3765  sum_iter(i, (struct enum_sum_memo *) args);
3766  return Qnil;
3767 }
3768 
3769 static int
3770 hash_sum_i(VALUE key, VALUE value, VALUE arg)
3771 {
3772  sum_iter(rb_assoc_new(key, value), (struct enum_sum_memo *) arg);
3773  return ST_CONTINUE;
3774 }
3775 
3776 static void
3777 hash_sum(VALUE hash, struct enum_sum_memo *memo)
3778 {
3779  assert(RB_TYPE_P(hash, T_HASH));
3780  assert(memo != NULL);
3781 
3782  rb_hash_foreach(hash, hash_sum_i, (VALUE)memo);
3783 }
3784 
3785 static VALUE
3786 int_range_sum(VALUE beg, VALUE end, int excl, VALUE init)
3787 {
3788  if (excl) {
3789  if (FIXNUM_P(end))
3790  end = LONG2FIX(FIX2LONG(end) - 1);
3791  else
3792  end = rb_big_minus(end, LONG2FIX(1));
3793  }
3794 
3795  if (rb_int_ge(end, beg)) {
3796  VALUE a;
3797  a = rb_int_plus(rb_int_minus(end, beg), LONG2FIX(1));
3798  a = rb_int_mul(a, rb_int_plus(end, beg));
3799  a = rb_int_idiv(a, LONG2FIX(2));
3800  return rb_int_plus(init, a);
3801  }
3802 
3803  return init;
3804 }
3805 
3806 /*
3807  * call-seq:
3808  * enum.sum(init=0) -> number
3809  * enum.sum(init=0) {|e| expr } -> number
3810  *
3811  * Returns the sum of elements in an Enumerable.
3812  *
3813  * If a block is given, the block is applied to each element
3814  * before addition.
3815  *
3816  * If <i>enum</i> is empty, it returns <i>init</i>.
3817  *
3818  * For example:
3819  *
3820  * { 1 => 10, 2 => 20 }.sum {|k, v| k * v } #=> 50
3821  * (1..10).sum #=> 55
3822  * (1..10).sum {|v| v * 2 } #=> 110
3823  * [Object.new].each.sum #=> TypeError
3824  *
3825  * This method can be used for non-numeric objects by
3826  * explicit <i>init</i> argument.
3827  *
3828  * { 1 => 10, 2 => 20 }.sum([]) #=> [1, 10, 2, 20]
3829  * "a\nb\nc".each_line.lazy.map(&:chomp).sum("") #=> "abc"
3830  *
3831  * Enumerable#sum method may not respect method redefinition of "+"
3832  * methods such as Integer#+.
3833  */
3834 static VALUE
3835 enum_sum(int argc, VALUE* argv, VALUE obj)
3836 {
3837  struct enum_sum_memo memo;
3838  VALUE beg, end;
3839  int excl;
3840 
3841  if (rb_scan_args(argc, argv, "01", &memo.v) == 0)
3842  memo.v = LONG2FIX(0);
3843 
3844  memo.block_given = rb_block_given_p();
3845 
3846  memo.n = 0;
3847  memo.r = Qundef;
3848 
3849  if ((memo.float_value = RB_FLOAT_TYPE_P(memo.v))) {
3850  memo.f = RFLOAT_VALUE(memo.v);
3851  memo.c = 0.0;
3852  }
3853 
3854  if (RTEST(rb_range_values(obj, &beg, &end, &excl))) {
3855  if (!memo.block_given && !memo.float_value &&
3856  (FIXNUM_P(beg) || RB_TYPE_P(beg, T_BIGNUM)) &&
3857  (FIXNUM_P(end) || RB_TYPE_P(end, T_BIGNUM))) {
3858  return int_range_sum(beg, end, excl, memo.v);
3859  }
3860  }
3861 
3862  if (RB_TYPE_P(obj, T_HASH) &&
3864  hash_sum(obj, &memo);
3865  else
3866  rb_block_call(obj, id_each, 0, 0, enum_sum_i, (VALUE)&memo);
3867 
3868  if (memo.float_value) {
3869  return DBL2NUM(memo.f + memo.c);
3870  }
3871  else {
3872  if (memo.n != 0)
3873  memo.v = rb_fix_plus(LONG2FIX(memo.n), memo.v);
3874  if (memo.r != Qundef) {
3875  /* r can be an Integer when mathn is loaded */
3876  if (FIXNUM_P(memo.r))
3877  memo.v = rb_fix_plus(memo.r, memo.v);
3878  else if (RB_TYPE_P(memo.r, T_BIGNUM))
3879  memo.v = rb_big_plus(memo.r, memo.v);
3880  else
3881  memo.v = rb_rational_plus(memo.r, memo.v);
3882  }
3883  return memo.v;
3884  }
3885 }
3886 
3887 static VALUE
3888 uniq_func(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
3889 {
3890  ENUM_WANT_SVALUE();
3891  rb_hash_add_new_element(hash, i, i);
3892  return Qnil;
3893 }
3894 
3895 static VALUE
3896 uniq_iter(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
3897 {
3898  ENUM_WANT_SVALUE();
3899  rb_hash_add_new_element(hash, rb_yield_values2(argc, argv), i);
3900  return Qnil;
3901 }
3902 
3903 /*
3904  * call-seq:
3905  * enum.uniq -> new_ary
3906  * enum.uniq { |item| ... } -> new_ary
3907  *
3908  * Returns a new array by removing duplicate values in +self+.
3909  *
3910  * See also Array#uniq.
3911  */
3912 
3913 static VALUE
3914 enum_uniq(VALUE obj)
3915 {
3916  VALUE hash, ret;
3917  rb_block_call_func *const func =
3918  rb_block_given_p() ? uniq_iter : uniq_func;
3919 
3920  hash = rb_obj_hide(rb_hash_new());
3921  rb_block_call(obj, id_each, 0, 0, func, hash);
3922  ret = rb_hash_values(hash);
3923  rb_hash_clear(hash);
3924  return ret;
3925 }
3926 
3927 /*
3928  * The <code>Enumerable</code> mixin provides collection classes with
3929  * several traversal and searching methods, and with the ability to
3930  * sort. The class must provide a method <code>each</code>, which
3931  * yields successive members of the collection. If
3932  * <code>Enumerable#max</code>, <code>#min</code>, or
3933  * <code>#sort</code> is used, the objects in the collection must also
3934  * implement a meaningful <code><=></code> operator, as these methods
3935  * rely on an ordering between members of the collection.
3936  */
3937 
3938 void
3940 {
3941 #undef rb_intern
3942 #define rb_intern(str) rb_intern_const(str)
3943 
3944  rb_mEnumerable = rb_define_module("Enumerable");
3945 
3946  rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
3947  rb_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
3948  rb_define_method(rb_mEnumerable, "to_h", enum_to_h, -1);
3949 
3950  rb_define_method(rb_mEnumerable, "sort", enum_sort, 0);
3951  rb_define_method(rb_mEnumerable, "sort_by", enum_sort_by, 0);
3952  rb_define_method(rb_mEnumerable, "grep", enum_grep, 1);
3953  rb_define_method(rb_mEnumerable, "grep_v", enum_grep_v, 1);
3954  rb_define_method(rb_mEnumerable, "count", enum_count, -1);
3955  rb_define_method(rb_mEnumerable, "find", enum_find, -1);
3956  rb_define_method(rb_mEnumerable, "detect", enum_find, -1);
3957  rb_define_method(rb_mEnumerable, "find_index", enum_find_index, -1);
3958  rb_define_method(rb_mEnumerable, "find_all", enum_find_all, 0);
3959  rb_define_method(rb_mEnumerable, "select", enum_find_all, 0);
3960  rb_define_method(rb_mEnumerable, "reject", enum_reject, 0);
3961  rb_define_method(rb_mEnumerable, "collect", enum_collect, 0);
3962  rb_define_method(rb_mEnumerable, "map", enum_collect, 0);
3963  rb_define_method(rb_mEnumerable, "flat_map", enum_flat_map, 0);
3964  rb_define_method(rb_mEnumerable, "collect_concat", enum_flat_map, 0);
3965  rb_define_method(rb_mEnumerable, "inject", enum_inject, -1);
3966  rb_define_method(rb_mEnumerable, "reduce", enum_inject, -1);
3967  rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
3968  rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
3969  rb_define_method(rb_mEnumerable, "first", enum_first, -1);
3970  rb_define_method(rb_mEnumerable, "all?", enum_all, 0);
3971  rb_define_method(rb_mEnumerable, "any?", enum_any, 0);
3972  rb_define_method(rb_mEnumerable, "one?", enum_one, 0);
3973  rb_define_method(rb_mEnumerable, "none?", enum_none, 0);
3974  rb_define_method(rb_mEnumerable, "min", enum_min, -1);
3975  rb_define_method(rb_mEnumerable, "max", enum_max, -1);
3976  rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
3977  rb_define_method(rb_mEnumerable, "min_by", enum_min_by, -1);
3978  rb_define_method(rb_mEnumerable, "max_by", enum_max_by, -1);
3979  rb_define_method(rb_mEnumerable, "minmax_by", enum_minmax_by, 0);
3980  rb_define_method(rb_mEnumerable, "member?", enum_member, 1);
3981  rb_define_method(rb_mEnumerable, "include?", enum_member, 1);
3982  rb_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, -1);
3983  rb_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1);
3984  rb_define_method(rb_mEnumerable, "each_entry", enum_each_entry, -1);
3985  rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
3986  rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
3987  rb_define_method(rb_mEnumerable, "each_with_object", enum_each_with_object, 1);
3988  rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
3989  rb_define_method(rb_mEnumerable, "take", enum_take, 1);
3990  rb_define_method(rb_mEnumerable, "take_while", enum_take_while, 0);
3991  rb_define_method(rb_mEnumerable, "drop", enum_drop, 1);
3992  rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
3993  rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
3994  rb_define_method(rb_mEnumerable, "chunk", enum_chunk, 0);
3995  rb_define_method(rb_mEnumerable, "slice_before", enum_slice_before, -1);
3996  rb_define_method(rb_mEnumerable, "slice_after", enum_slice_after, -1);
3997  rb_define_method(rb_mEnumerable, "slice_when", enum_slice_when, 0);
3998  rb_define_method(rb_mEnumerable, "chunk_while", enum_chunk_while, 0);
3999  rb_define_method(rb_mEnumerable, "sum", enum_sum, -1);
4000  rb_define_method(rb_mEnumerable, "uniq", enum_uniq, 0);
4001 
4002  id_next = rb_intern("next");
4003  id_div = rb_intern("div");
4004 }
#define NEW_PARTIAL_MEMO_FOR(type, value, member)
Definition: internal.h:970
VALUE rb_int_plus(VALUE x, VALUE y)
Definition: numeric.c:3519
#define id_lshift
Definition: enum.c:27
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:1469
int(* cmpfunc)(const void *, const void *, void *)
Definition: enum.c:1263
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
Definition: symbol.c:915
#define MEMO_FOR(type, value)
Definition: internal.h:967
void rb_warn(const char *fmt,...)
Definition: error.c:246
#define RARRAY_LEN(a)
Definition: ruby.h:1019
#define rb_intern(str)
#define FALSE
Definition: nkf.h:174
#define id_each
Definition: enum.c:24
#define INT2NUM(x)
Definition: ruby.h:1538
const VALUE v2
Definition: internal.h:949
int rb_block_min_max_arity(int *max)
Definition: proc.c:1070
VALUE rb_yield_values(int n,...)
Definition: vm_eval.c:985
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:835
VALUE rb_yield_force_blockarg(VALUE values)
Definition: vm_eval.c:1026
#define NEW_MEMO_FOR(type, value)
Definition: internal.h:968
#define CLASS_OF(v)
Definition: ruby.h:453
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
#define Qtrue
Definition: ruby.h:437
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:1019
int rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:3150
Definition: st.h:99
const int id
Definition: nkf.c:209
VALUE rb_big_plus(VALUE x, VALUE y)
Definition: bignum.c:5772
#define MEMO_CAST(m)
Definition: internal.h:961
#define T_RATIONAL
Definition: ruby.h:509
#define rb_check_arity
Definition: intern.h:298
#define UNREACHABLE
Definition: ruby.h:46
VALUE sep_pred
Definition: enum.c:3094
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Definition: range.c:979
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:924
VALUE prev_elts
Definition: enum.c:3440
#define SYM2ID(x)
Definition: ruby.h:384
VALUE yielder
Definition: enum.c:3097
const char * method
Definition: enum.c:1266
VALUE yielder
Definition: enum.c:3318
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:544
VALUE rb_int_minus(VALUE x, VALUE y)
Definition: numeric.c:3558
long bufmax
Definition: enum.c:1259
VALUE rb_cEnumerator
Definition: enumerator.c:103
struct cmp_opt_data cmp_opt
Definition: enum.c:1731
#define RBASIC_SET_CLASS(obj, cls)
Definition: internal.h:1471
VALUE rb_int_mul(VALUE x, VALUE y)
Definition: numeric.c:3608
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1210
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3501
#define OPTIMIZED_CMP(a, b, data)
Definition: internal.h:1004
long cnt
Definition: internal.h:951
#define DEFINE_ENUMFUNCS(name)
Definition: enum.c:1155
#define RB_GC_GUARD(v)
Definition: ruby.h:552
Definition: id.h:83
#define T_HASH
Definition: ruby.h:499
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
Definition: object.c:2121
VALUE yielder
Definition: enum.c:3441
int by
Definition: enum.c:1265
VALUE(* func)(ANYARGS)
Definition: internal.h:954
union MEMO::@80 u3
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
struct cmp_opt_data cmp_opt
Definition: enum.c:1635
#define T_ARRAY
Definition: ruby.h:498
double rb_big2dbl(VALUE x)
Definition: bignum.c:5270
VALUE max
Definition: enum.c:2052
VALUE max
Definition: enum.c:1729
VALUE yielder
Definition: enum.c:2914
#define MEMO_NEW(a, b, c)
Definition: internal.h:963
double f
Definition: enum.c:3656
#define FIXNUM_P(f)
Definition: ruby.h:365
VALUE last
Definition: enum.c:1730
VALUE buf
Definition: enum.c:1261
VALUE rb_rescue2(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:895
#define NUM2DBL(x)
Definition: ruby.h:743
#define FIX2ULONG(x)
Definition: ruby.h:364
#define rb_ary_new2
Definition: intern.h:90
#define MEMO_V2_SET(m, v)
Definition: internal.h:959
VALUE rb_eArgError
Definition: error.c:802
void Init_Enumerable(void)
Definition: enum.c:3939
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1851
void rb_hash_foreach(VALUE hash, int(*func)(ANYARGS), VALUE farg)
Definition: hash.c:385
#define ENUM_WANT_SVALUE()
Definition: enum.c:39
VALUE prev_value
Definition: enum.c:2912
#define RBASIC_SET_CLASS_RAW(obj, cls)
Definition: internal.h:1470
VALUE rb_obj_class(VALUE)
call-seq: obj.class -> class
Definition: object.c:277
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
ID id_next
Definition: eventids1.c:72
unsigned int opt_inited
Definition: internal.h:991
const VALUE buf
Definition: enum.c:979
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
Definition: ruby.h:1853
void rb_iter_break(void)
Definition: vm.c:1491
VALUE rb_int_idiv(VALUE x, VALUE y)
Definition: numeric.c:3753
long n
Definition: enum.c:980
int inverted
Definition: enum.c:3442
#define dont_recycle_block_arg(arity)
Definition: enum.c:2330
VALUE rb_equal(VALUE, VALUE)
call-seq: obj === other -> true or false
Definition: object.c:126
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1616
#define val
VALUE rb_int_ge(VALUE x, VALUE y)
Definition: numeric.c:4175
#define id_size
Definition: enum.c:29
VALUE rb_ary_new(void)
Definition: array.c:499
#define UINT2NUM(x)
Definition: ruby.h:1539
VALUE pat
Definition: enum.c:3315
VALUE pred
Definition: enum.c:3316
#define NIL_P(v)
Definition: ruby.h:451
#define SORT_BY_BUFSIZE
Definition: enum.c:976
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:815
MEMO.
Definition: internal.h:945
int argc
Definition: ruby.c:187
#define Qfalse
Definition: ruby.h:436
#define T_BIGNUM
Definition: ruby.h:501
#define LONG_MAX
Definition: ruby.h:189
#define rb_ary_new4
Definition: intern.h:92
VALUE rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary)
Definition: enum.c:1417
#define numberof(array)
Definition: etc.c:618
long n
Definition: enum.c:3655
double c
Definition: enum.c:3656
#define SWAP(i, j)
int block_given
Definition: enum.c:3657
VALUE rb_big_minus(VALUE x, VALUE y)
Definition: bignum.c:5801
VALUE rb_funcallv_public(VALUE, ID, int, const VALUE *)
Calls a method.
Definition: vm_eval.c:820
VALUE rb_yield(VALUE)
Definition: vm_eval.c:973
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:1021
#define GETPTR(i)
#define TRUE
Definition: nkf.h:175
VALUE rb_mEnumerable
Definition: enum.c:19
VALUE categorize
Definition: enum.c:2911
#define RARRAY_PTR_USE(ary, ptr_name, expr)
Definition: ruby.h:1026
#define MEMO_V1_SET(m, v)
Definition: internal.h:958
int rb_obj_respond_to(VALUE, ID, int)
Definition: vm_method.c:1984
VALUE rb_hash_values(VALUE hash)
Definition: hash.c:2175
VALUE rb_hash_new(void)
Definition: hash.c:424
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1908
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1315
VALUE sep_pat
Definition: enum.c:3095
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:639
#define PRIsVALUE
Definition: ruby.h:135
VALUE rb_fix_plus(VALUE x, VALUE y)
Definition: numeric.c:3513
unsigned long ID
Definition: ruby.h:86
VALUE min_bv
Definition: enum.c:2049
int rb_block_arity(void)
Definition: proc.c:1036
long state
Definition: internal.h:952
#define Qnil
Definition: ruby.h:438
VALUE rb_eStopIteration
Definition: enumerator.c:109
VALUE max
Definition: enum.c:1634
unsigned long VALUE
Definition: ruby.h:85
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
VALUE rb_hash_clear(VALUE hash)
Definition: hash.c:1519
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
Definition: intern.h:234
#define RBASIC(obj)
Definition: ruby.h:1197
RUBY_EXTERN VALUE rb_cInteger
Definition: ruby.h:1912
VALUE rb_eTypeError
Definition: error.c:801
VALUE rb_f_send(int argc, VALUE *argv, VALUE recv)
Definition: vm_eval.c:933
#define rb_ary_new3
Definition: intern.h:91
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:389
#define rb_cmpint(cmp, a, b)
VALUE r
Definition: enum.c:3654
#define INFINITY
Definition: missing.h:149
#define ENUMFUNC(name)
Definition: enum.c:1153
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition: object.c:72
VALUE limit
Definition: enum.c:1262
#define FIXABLE(f)
Definition: ruby.h:368
#define RB_FLOAT_TYPE_P(obj)
Definition: ruby.h:523
Definition: enum.c:1633
#define LONG2NUM(x)
Definition: ruby.h:1573
#define rb_funcallv
Definition: console.c:21
VALUE max_bv
Definition: enum.c:2050
const VALUE ary
Definition: enum.c:978
const char * rb_builtin_class_name(VALUE x)
Definition: error.c:684
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1994
register unsigned int len
Definition: zonetab.h:51
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
Definition: array.c:538
VALUE last_bv
Definition: enum.c:2053
VALUE prev_elts
Definition: enum.c:3096
#define RSTRING_PTR(str)
Definition: ruby.h:975
struct cmp_opt_data cmp_opt
Definition: enum.c:1540
VALUE rb_rational_plus(VALUE self, VALUE other)
Definition: rational.c:767
#define RB_OBJ_WRITE(a, slot, b)
Definition: eval_intern.h:175
VALUE rb_ary_resize(VALUE ary, long len)
expands or shrinks ary to len elements.
Definition: array.c:1648
#define RARRAY_ASET(a, i, v)
Definition: ruby.h:1034
Definition: enum.c:1538
#define RFLOAT_VALUE(v)
Definition: ruby.h:933
int size
Definition: encoding.c:57
VALUE rb_yield_values2(int n, const VALUE *argv)
Definition: vm_eval.c:1007
#define f
#define INT2FIX(i)
Definition: ruby.h:232
VALUE rb_enum_values_pack(int argc, const VALUE *argv)
Definition: enum.c:32
#define RARRAY_AREF(a, i)
Definition: ruby.h:1033
const VALUE v1
Definition: internal.h:948
#define NEW_CMP_OPT_MEMO(type, value)
Definition: internal.h:994
#define mul(x, y)
Definition: date_strftime.c:25
VALUE rb_block_proc(void)
Definition: proc.c:780
VALUE rb_eRuntimeError
Definition: error.c:800
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:651
VALUE min
Definition: enum.c:2051
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:831
void rb_error_arity(int argc, int min, int max)
#define RARRAY_PTR(a)
Definition: ruby.h:1041
#define LONG2FIX(i)
Definition: ruby.h:234
unsigned int opt_methods
Definition: internal.h:990
#define RTEST(v)
Definition: ruby.h:450
void rb_thread_check_ints(void)
Definition: thread.c:1219
void rb_warning(const char *fmt,...)
Definition: error.c:267
#define STATIC_ID2SYM(id)
Definition: symbol.h:18
#define OBJ_INFECT(x, s)
Definition: ruby.h:1302
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:1879
long curlen
Definition: enum.c:1260
#define UPDATE_MEMO
VALUE rb_ary_sort_bang(VALUE ary)
Definition: array.c:2465
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1930
#define assert
Definition: ruby_assert.h:37
VALUE rb_cArray
Definition: array.c:26
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:3703
VALUE rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t bl_proc, int min_argc, int max_argc, VALUE data2)
Definition: vm_eval.c:1194
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:238
double rb_num2dbl(VALUE)
Converts a Numeric object to double.
Definition: object.c:3524
const char * name
Definition: nkf.c:208
#define ID2SYM(x)
Definition: ruby.h:383
int float_value
Definition: enum.c:3658
VALUE rb_ary_reverse(VALUE ary)
Definition: array.c:2224
VALUE prev_elts
Definition: enum.c:2913
VALUE prev_elt
Definition: enum.c:3439
#define CONST_ID(var, str)
Definition: ruby.h:1743
VALUE rb_define_module(const char *name)
Definition: class.c:768
#define SYMBOL_P(x)
Definition: ruby.h:382
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
#define NULL
Definition: _sdbm.c:102
#define FIX2LONG(x)
Definition: ruby.h:363
#define Qundef
Definition: ruby.h:439
VALUE rb_check_funcall_default(VALUE, ID, int, const VALUE *, VALUE)
Definition: vm_eval.c:395
int rev
Definition: enum.c:1264
VALUE min
Definition: enum.c:1539
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
const VALUE value
Definition: internal.h:953
VALUE min
Definition: enum.c:1728
#define bp()
Definition: vm_debug.h:25
VALUE last
Definition: enum.c:2054
#define NUM2LONG(x)
Definition: ruby.h:648
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1224
#define id_call
Definition: enum.c:28
#define id_eqq
Definition: enum.c:25
char ** argv
Definition: ruby.c:188
#define DBL2NUM(dbl)
Definition: ruby.h:934
VALUE pred
Definition: enum.c:3438
VALUE prev_elts
Definition: enum.c:3317
long n
Definition: enum.c:1258
#define rb_sym2str(sym)
Definition: console.c:107
VALUE v
Definition: enum.c:3654