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