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