Ruby  3.4.0dev (2024-11-05 revision 348a53415339076afc4a02fcd09f3ae36e9c4c61)
enum.c (348a53415339076afc4a02fcd09f3ae36e9c4c61)
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 "id.h"
13 #include "internal.h"
14 #include "internal/compar.h"
15 #include "internal/enum.h"
16 #include "internal/hash.h"
17 #include "internal/imemo.h"
18 #include "internal/numeric.h"
19 #include "internal/object.h"
20 #include "internal/proc.h"
21 #include "internal/rational.h"
22 #include "internal/re.h"
23 #include "ruby/util.h"
24 #include "ruby_assert.h"
25 #include "symbol.h"
26 
28 
29 static ID id_next;
30 static ID id__alone;
31 static ID id__separator;
32 static ID id_chunk_categorize;
33 static ID id_chunk_enumerable;
34 static ID id_sliceafter_enum;
35 static ID id_sliceafter_pat;
36 static ID id_sliceafter_pred;
37 static ID id_slicebefore_enumerable;
38 static ID id_slicebefore_sep_pat;
39 static ID id_slicebefore_sep_pred;
40 static ID id_slicewhen_enum;
41 static ID id_slicewhen_inverted;
42 static ID id_slicewhen_pred;
43 
44 #define id_div idDiv
45 #define id_each idEach
46 #define id_eqq idEqq
47 #define id_cmp idCmp
48 #define id_lshift idLTLT
49 #define id_call idCall
50 #define id_size idSize
51 
52 VALUE
53 rb_enum_values_pack(int argc, const VALUE *argv)
54 {
55  if (argc == 0) return Qnil;
56  if (argc == 1) return argv[0];
57  return rb_ary_new4(argc, argv);
58 }
59 
60 #define ENUM_WANT_SVALUE() do { \
61  i = rb_enum_values_pack(argc, argv); \
62 } while (0)
63 
64 static VALUE
65 enum_yield(int argc, VALUE ary)
66 {
67  if (argc > 1)
68  return rb_yield_force_blockarg(ary);
69  if (argc == 1)
70  return rb_yield(ary);
71  return rb_yield_values2(0, 0);
72 }
73 
74 static VALUE
75 enum_yield_array(VALUE ary)
76 {
77  long len = RARRAY_LEN(ary);
78 
79  if (len > 1)
80  return rb_yield_force_blockarg(ary);
81  if (len == 1)
82  return rb_yield(RARRAY_AREF(ary, 0));
83  return rb_yield_values2(0, 0);
84 }
85 
86 static VALUE
87 grep_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
88 {
89  struct MEMO *memo = MEMO_CAST(args);
90  ENUM_WANT_SVALUE();
91 
92  if (RTEST(rb_funcallv(memo->v1, id_eqq, 1, &i)) == RTEST(memo->u3.value)) {
93  rb_ary_push(memo->v2, i);
94  }
95  return Qnil;
96 }
97 
98 static VALUE
99 grep_regexp_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
100 {
101  struct MEMO *memo = MEMO_CAST(args);
102  VALUE converted_element, match;
103  ENUM_WANT_SVALUE();
104 
105  /* In case element can't be converted to a Symbol or String: not a match (don't raise) */
106  converted_element = SYMBOL_P(i) ? i : rb_check_string_type(i);
107  match = NIL_P(converted_element) ? Qfalse : rb_reg_match_p(memo->v1, i, 0);
108  if (match == memo->u3.value) {
109  rb_ary_push(memo->v2, i);
110  }
111  return Qnil;
112 }
113 
114 static VALUE
115 grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
116 {
117  struct MEMO *memo = MEMO_CAST(args);
118  ENUM_WANT_SVALUE();
119 
120  if (RTEST(rb_funcallv(memo->v1, id_eqq, 1, &i)) == RTEST(memo->u3.value)) {
121  rb_ary_push(memo->v2, enum_yield(argc, i));
122  }
123  return Qnil;
124 }
125 
126 static VALUE
127 enum_grep0(VALUE obj, VALUE pat, VALUE test)
128 {
129  VALUE ary = rb_ary_new();
130  struct MEMO *memo = MEMO_NEW(pat, ary, test);
132  if (rb_block_given_p()) {
133  fn = grep_iter_i;
134  }
135  else if (RB_TYPE_P(pat, T_REGEXP) &&
136  LIKELY(rb_method_basic_definition_p(CLASS_OF(pat), idEqq))) {
137  fn = grep_regexp_i;
138  }
139  else {
140  fn = grep_i;
141  }
142  rb_block_call(obj, id_each, 0, 0, fn, (VALUE)memo);
143 
144  return ary;
145 }
146 
147 /*
148  * call-seq:
149  * grep(pattern) -> array
150  * grep(pattern) {|element| ... } -> array
151  *
152  * Returns an array of objects based elements of +self+ that match the given pattern.
153  *
154  * With no block given, returns an array containing each element
155  * for which <tt>pattern === element</tt> is +true+:
156  *
157  * a = ['foo', 'bar', 'car', 'moo']
158  * a.grep(/ar/) # => ["bar", "car"]
159  * (1..10).grep(3..8) # => [3, 4, 5, 6, 7, 8]
160  * ['a', 'b', 0, 1].grep(Integer) # => [0, 1]
161  *
162  * With a block given,
163  * calls the block with each matching element and returns an array containing each
164  * object returned by the block:
165  *
166  * a = ['foo', 'bar', 'car', 'moo']
167  * a.grep(/ar/) {|element| element.upcase } # => ["BAR", "CAR"]
168  *
169  * Related: #grep_v.
170  */
171 
172 static VALUE
173 enum_grep(VALUE obj, VALUE pat)
174 {
175  return enum_grep0(obj, pat, Qtrue);
176 }
177 
178 /*
179  * call-seq:
180  * grep_v(pattern) -> array
181  * grep_v(pattern) {|element| ... } -> array
182  *
183  * Returns an array of objects based on elements of +self+
184  * that <em>don't</em> match the given pattern.
185  *
186  * With no block given, returns an array containing each element
187  * for which <tt>pattern === element</tt> is +false+:
188  *
189  * a = ['foo', 'bar', 'car', 'moo']
190  * a.grep_v(/ar/) # => ["foo", "moo"]
191  * (1..10).grep_v(3..8) # => [1, 2, 9, 10]
192  * ['a', 'b', 0, 1].grep_v(Integer) # => ["a", "b"]
193  *
194  * With a block given,
195  * calls the block with each non-matching element and returns an array containing each
196  * object returned by the block:
197  *
198  * a = ['foo', 'bar', 'car', 'moo']
199  * a.grep_v(/ar/) {|element| element.upcase } # => ["FOO", "MOO"]
200  *
201  * Related: #grep.
202  */
203 
204 static VALUE
205 enum_grep_v(VALUE obj, VALUE pat)
206 {
207  return enum_grep0(obj, pat, Qfalse);
208 }
209 
210 #define COUNT_BIGNUM IMEMO_FL_USER0
211 #define MEMO_V3_SET(m, v) RB_OBJ_WRITE((m), &(m)->u3.value, (v))
212 
213 static void
214 imemo_count_up(struct MEMO *memo)
215 {
216  if (memo->flags & COUNT_BIGNUM) {
217  MEMO_V3_SET(memo, rb_int_succ(memo->u3.value));
218  }
219  else if (++memo->u3.cnt == 0) {
220  /* overflow */
221  unsigned long buf[2] = {0, 1};
222  MEMO_V3_SET(memo, rb_big_unpack(buf, 2));
223  memo->flags |= COUNT_BIGNUM;
224  }
225 }
226 
227 static VALUE
228 imemo_count_value(struct MEMO *memo)
229 {
230  if (memo->flags & COUNT_BIGNUM) {
231  return memo->u3.value;
232  }
233  else {
234  return ULONG2NUM(memo->u3.cnt);
235  }
236 }
237 
238 static VALUE
239 count_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
240 {
241  struct MEMO *memo = MEMO_CAST(memop);
242 
243  ENUM_WANT_SVALUE();
244 
245  if (rb_equal(i, memo->v1)) {
246  imemo_count_up(memo);
247  }
248  return Qnil;
249 }
250 
251 static VALUE
252 count_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
253 {
254  struct MEMO *memo = MEMO_CAST(memop);
255 
256  if (RTEST(rb_yield_values2(argc, argv))) {
257  imemo_count_up(memo);
258  }
259  return Qnil;
260 }
261 
262 static VALUE
263 count_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
264 {
265  struct MEMO *memo = MEMO_CAST(memop);
266 
267  imemo_count_up(memo);
268  return Qnil;
269 }
270 
271 /*
272  * call-seq:
273  * count -> integer
274  * count(object) -> integer
275  * count {|element| ... } -> integer
276  *
277  * Returns the count of elements, based on an argument or block criterion, if given.
278  *
279  * With no argument and no block given, returns the number of elements:
280  *
281  * [0, 1, 2].count # => 3
282  * {foo: 0, bar: 1, baz: 2}.count # => 3
283  *
284  * With argument +object+ given,
285  * returns the number of elements that are <tt>==</tt> to +object+:
286  *
287  * [0, 1, 2, 1].count(1) # => 2
288  *
289  * With a block given, calls the block with each element
290  * and returns the number of elements for which the block returns a truthy value:
291  *
292  * [0, 1, 2, 3].count {|element| element < 2} # => 2
293  * {foo: 0, bar: 1, baz: 2}.count {|key, value| value < 2} # => 2
294  *
295  */
296 
297 static VALUE
298 enum_count(int argc, VALUE *argv, VALUE obj)
299 {
300  VALUE item = Qnil;
301  struct MEMO *memo;
302  rb_block_call_func *func;
303 
304  if (argc == 0) {
305  if (rb_block_given_p()) {
306  func = count_iter_i;
307  }
308  else {
309  func = count_all_i;
310  }
311  }
312  else {
313  rb_scan_args(argc, argv, "1", &item);
314  if (rb_block_given_p()) {
315  rb_warn("given block not used");
316  }
317  func = count_i;
318  }
319 
320  memo = MEMO_NEW(item, 0, 0);
321  rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
322  return imemo_count_value(memo);
323 }
324 
325 NORETURN(static void found(VALUE i, VALUE memop));
326 static void
327 found(VALUE i, VALUE memop) {
328  struct MEMO *memo = MEMO_CAST(memop);
329  MEMO_V1_SET(memo, i);
330  memo->u3.cnt = 1;
331  rb_iter_break();
332 }
333 
334 static VALUE
335 find_i_fast(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
336 {
337  if (RTEST(rb_yield_values2(argc, argv))) {
338  ENUM_WANT_SVALUE();
339  found(i, memop);
340  }
341  return Qnil;
342 }
343 
344 static VALUE
345 find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
346 {
347  ENUM_WANT_SVALUE();
348 
349  if (RTEST(enum_yield(argc, i))) {
350  found(i, memop);
351  }
352  return Qnil;
353 }
354 
355 /*
356  * call-seq:
357  * find(if_none_proc = nil) {|element| ... } -> object or nil
358  * find(if_none_proc = nil) -> enumerator
359  *
360  * Returns the first element for which the block returns a truthy value.
361  *
362  * With a block given, calls the block with successive elements of the collection;
363  * returns the first element for which the block returns a truthy value:
364  *
365  * (0..9).find {|element| element > 2} # => 3
366  *
367  * If no such element is found, calls +if_none_proc+ and returns its return value.
368  *
369  * (0..9).find(proc {false}) {|element| element > 12} # => false
370  * {foo: 0, bar: 1, baz: 2}.find {|key, value| key.start_with?('b') } # => [:bar, 1]
371  * {foo: 0, bar: 1, baz: 2}.find(proc {[]}) {|key, value| key.start_with?('c') } # => []
372  *
373  * With no block given, returns an Enumerator.
374  *
375  */
376 static VALUE
377 enum_find(int argc, VALUE *argv, VALUE obj)
378 {
379  struct MEMO *memo;
380  VALUE if_none;
381 
382  if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
383  RETURN_ENUMERATOR(obj, argc, argv);
384  memo = MEMO_NEW(Qundef, 0, 0);
385  if (rb_block_pair_yield_optimizable())
386  rb_block_call2(obj, id_each, 0, 0, find_i_fast, (VALUE)memo, RB_BLOCK_NO_USE_PACKED_ARGS);
387  else
388  rb_block_call2(obj, id_each, 0, 0, find_i, (VALUE)memo, RB_BLOCK_NO_USE_PACKED_ARGS);
389  if (memo->u3.cnt) {
390  return memo->v1;
391  }
392  if (!NIL_P(if_none)) {
393  return rb_funcallv(if_none, id_call, 0, 0);
394  }
395  return Qnil;
396 }
397 
398 static VALUE
399 find_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
400 {
401  struct MEMO *memo = MEMO_CAST(memop);
402 
403  ENUM_WANT_SVALUE();
404 
405  if (rb_equal(i, memo->v2)) {
406  MEMO_V1_SET(memo, imemo_count_value(memo));
407  rb_iter_break();
408  }
409  imemo_count_up(memo);
410  return Qnil;
411 }
412 
413 static VALUE
414 find_index_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
415 {
416  struct MEMO *memo = MEMO_CAST(memop);
417 
418  if (RTEST(rb_yield_values2(argc, argv))) {
419  MEMO_V1_SET(memo, imemo_count_value(memo));
420  rb_iter_break();
421  }
422  imemo_count_up(memo);
423  return Qnil;
424 }
425 
426 /*
427  * call-seq:
428  * find_index(object) -> integer or nil
429  * find_index {|element| ... } -> integer or nil
430  * find_index -> enumerator
431  *
432  * Returns the index of the first element that meets a specified criterion,
433  * or +nil+ if no such element is found.
434  *
435  * With argument +object+ given,
436  * returns the index of the first element that is <tt>==</tt> +object+:
437  *
438  * ['a', 'b', 'c', 'b'].find_index('b') # => 1
439  *
440  * With a block given, calls the block with successive elements;
441  * returns the first element for which the block returns a truthy value:
442  *
443  * ['a', 'b', 'c', 'b'].find_index {|element| element.start_with?('b') } # => 1
444  * {foo: 0, bar: 1, baz: 2}.find_index {|key, value| value > 1 } # => 2
445  *
446  * With no argument and no block given, returns an Enumerator.
447  *
448  */
449 
450 static VALUE
451 enum_find_index(int argc, VALUE *argv, VALUE obj)
452 {
453  struct MEMO *memo; /* [return value, current index, ] */
454  VALUE condition_value = Qnil;
455  rb_block_call_func *func;
456 
457  if (argc == 0) {
458  RETURN_ENUMERATOR(obj, 0, 0);
459  func = find_index_iter_i;
460  }
461  else {
462  rb_scan_args(argc, argv, "1", &condition_value);
463  if (rb_block_given_p()) {
464  rb_warn("given block not used");
465  }
466  func = find_index_i;
467  }
468 
469  memo = MEMO_NEW(Qnil, condition_value, 0);
470  rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
471  return memo->v1;
472 }
473 
474 static VALUE
475 find_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
476 {
477  ENUM_WANT_SVALUE();
478 
479  if (RTEST(enum_yield(argc, i))) {
480  rb_ary_push(ary, i);
481  }
482  return Qnil;
483 }
484 
485 static VALUE
486 enum_size(VALUE self, VALUE args, VALUE eobj)
487 {
488  return rb_check_funcall_default(self, id_size, 0, 0, Qnil);
489 }
490 
491 static long
492 limit_by_enum_size(VALUE obj, long n)
493 {
494  unsigned long limit;
495  VALUE size = rb_check_funcall(obj, id_size, 0, 0);
496  if (!FIXNUM_P(size)) return n;
497  limit = FIX2ULONG(size);
498  return ((unsigned long)n > limit) ? (long)limit : n;
499 }
500 
501 static int
502 enum_size_over_p(VALUE obj, long n)
503 {
504  VALUE size = rb_check_funcall(obj, id_size, 0, 0);
505  if (!FIXNUM_P(size)) return 0;
506  return ((unsigned long)n > FIX2ULONG(size));
507 }
508 
509 /*
510  * call-seq:
511  * select {|element| ... } -> array
512  * select -> enumerator
513  *
514  * Returns an array containing elements selected by the block.
515  *
516  * With a block given, calls the block with successive elements;
517  * returns an array of those elements for which the block returns a truthy value:
518  *
519  * (0..9).select {|element| element % 3 == 0 } # => [0, 3, 6, 9]
520  * a = {foo: 0, bar: 1, baz: 2}.select {|key, value| key.start_with?('b') }
521  * a # => {:bar=>1, :baz=>2}
522  *
523  * With no block given, returns an Enumerator.
524  *
525  * Related: #reject.
526  */
527 static VALUE
528 enum_find_all(VALUE obj)
529 {
530  VALUE ary;
531 
532  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
533 
534  ary = rb_ary_new();
535  rb_block_call(obj, id_each, 0, 0, find_all_i, ary);
536 
537  return ary;
538 }
539 
540 static VALUE
541 filter_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
542 {
543  i = rb_yield_values2(argc, argv);
544 
545  if (RTEST(i)) {
546  rb_ary_push(ary, i);
547  }
548 
549  return Qnil;
550 }
551 
552 /*
553  * call-seq:
554  * filter_map {|element| ... } -> array
555  * filter_map -> enumerator
556  *
557  * Returns an array containing truthy elements returned by the block.
558  *
559  * With a block given, calls the block with successive elements;
560  * returns an array containing each truthy value returned by the block:
561  *
562  * (0..9).filter_map {|i| i * 2 if i.even? } # => [0, 4, 8, 12, 16]
563  * {foo: 0, bar: 1, baz: 2}.filter_map {|key, value| key if value.even? } # => [:foo, :baz]
564  *
565  * When no block given, returns an Enumerator.
566  *
567  */
568 static VALUE
569 enum_filter_map(VALUE obj)
570 {
571  VALUE ary;
572 
573  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
574 
575  ary = rb_ary_new();
576  rb_block_call(obj, id_each, 0, 0, filter_map_i, ary);
577 
578  return ary;
579 }
580 
581 
582 static VALUE
583 reject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
584 {
585  ENUM_WANT_SVALUE();
586 
587  if (!RTEST(enum_yield(argc, i))) {
588  rb_ary_push(ary, i);
589  }
590  return Qnil;
591 }
592 
593 /*
594  * call-seq:
595  * reject {|element| ... } -> array
596  * reject -> enumerator
597  *
598  * Returns an array of objects rejected by the block.
599  *
600  * With a block given, calls the block with successive elements;
601  * returns an array of those elements for which the block returns +nil+ or +false+:
602  *
603  * (0..9).reject {|i| i * 2 if i.even? } # => [1, 3, 5, 7, 9]
604  * {foo: 0, bar: 1, baz: 2}.reject {|key, value| key if value.odd? } # => {:foo=>0, :baz=>2}
605  *
606  * When no block given, returns an Enumerator.
607  *
608  * Related: #select.
609  */
610 
611 static VALUE
612 enum_reject(VALUE obj)
613 {
614  VALUE ary;
615 
616  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
617 
618  ary = rb_ary_new();
619  rb_block_call(obj, id_each, 0, 0, reject_i, ary);
620 
621  return ary;
622 }
623 
624 static VALUE
625 collect_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
626 {
627  rb_ary_push(ary, rb_yield_values2(argc, argv));
628 
629  return Qnil;
630 }
631 
632 static VALUE
633 collect_all(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
634 {
635  rb_ary_push(ary, rb_enum_values_pack(argc, argv));
636 
637  return Qnil;
638 }
639 
640 /*
641  * call-seq:
642  * map {|element| ... } -> array
643  * map -> enumerator
644  *
645  * Returns an array of objects returned by the block.
646  *
647  * With a block given, calls the block with successive elements;
648  * returns an array of the objects returned by the block:
649  *
650  * (0..4).map {|i| i*i } # => [0, 1, 4, 9, 16]
651  * {foo: 0, bar: 1, baz: 2}.map {|key, value| value*2} # => [0, 2, 4]
652  *
653  * With no block given, returns an Enumerator.
654  *
655  */
656 static VALUE
657 enum_collect(VALUE obj)
658 {
659  VALUE ary;
660  int min_argc, max_argc;
661 
662  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
663 
664  ary = rb_ary_new();
665  min_argc = rb_block_min_max_arity(&max_argc);
666  rb_lambda_call(obj, id_each, 0, 0, collect_i, min_argc, max_argc, ary);
667 
668  return ary;
669 }
670 
671 static VALUE
672 flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
673 {
674  VALUE tmp;
675 
676  i = rb_yield_values2(argc, argv);
677  tmp = rb_check_array_type(i);
678 
679  if (NIL_P(tmp)) {
680  rb_ary_push(ary, i);
681  }
682  else {
683  rb_ary_concat(ary, tmp);
684  }
685  return Qnil;
686 }
687 
688 /*
689  * call-seq:
690  * flat_map {|element| ... } -> array
691  * flat_map -> enumerator
692  *
693  * Returns an array of flattened objects returned by the block.
694  *
695  * With a block given, calls the block with successive elements;
696  * returns a flattened array of objects returned by the block:
697  *
698  * [0, 1, 2, 3].flat_map {|element| -element } # => [0, -1, -2, -3]
699  * [0, 1, 2, 3].flat_map {|element| [element, -element] } # => [0, 0, 1, -1, 2, -2, 3, -3]
700  * [[0, 1], [2, 3]].flat_map {|e| e + [100] } # => [0, 1, 100, 2, 3, 100]
701  * {foo: 0, bar: 1, baz: 2}.flat_map {|key, value| [key, value] } # => [:foo, 0, :bar, 1, :baz, 2]
702  *
703  * With no block given, returns an Enumerator.
704  *
705  * Alias: #collect_concat.
706  */
707 static VALUE
708 enum_flat_map(VALUE obj)
709 {
710  VALUE ary;
711 
712  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
713 
714  ary = rb_ary_new();
715  rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);
716 
717  return ary;
718 }
719 
720 /*
721  * call-seq:
722  * to_a(*args) -> array
723  *
724  * Returns an array containing the items in +self+:
725  *
726  * (0..4).to_a # => [0, 1, 2, 3, 4]
727  *
728  */
729 static VALUE
730 enum_to_a(int argc, VALUE *argv, VALUE obj)
731 {
732  VALUE ary = rb_ary_new();
733 
734  rb_block_call_kw(obj, id_each, argc, argv, collect_all, ary, RB_PASS_CALLED_KEYWORDS);
735 
736  return ary;
737 }
738 
739 static VALUE
740 enum_hashify_into(VALUE obj, int argc, const VALUE *argv, rb_block_call_func *iter, VALUE hash)
741 {
742  rb_block_call(obj, id_each, argc, argv, iter, hash);
743  return hash;
744 }
745 
746 static VALUE
747 enum_hashify(VALUE obj, int argc, const VALUE *argv, rb_block_call_func *iter)
748 {
749  return enum_hashify_into(obj, argc, argv, iter, rb_hash_new());
750 }
751 
752 static VALUE
753 enum_to_h_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
754 {
755  ENUM_WANT_SVALUE();
756  return rb_hash_set_pair(hash, i);
757 }
758 
759 static VALUE
760 enum_to_h_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
761 {
762  return rb_hash_set_pair(hash, rb_yield_values2(argc, argv));
763 }
764 
765 /*
766  * call-seq:
767  * to_h(*args) -> hash
768  * to_h(*args) {|element| ... } -> hash
769  *
770  * When +self+ consists of 2-element arrays,
771  * returns a hash each of whose entries is the key-value pair
772  * formed from one of those arrays:
773  *
774  * [[:foo, 0], [:bar, 1], [:baz, 2]].to_h # => {:foo=>0, :bar=>1, :baz=>2}
775  *
776  * When a block is given, the block is called with each element of +self+;
777  * the block should return a 2-element array which becomes a key-value pair
778  * in the returned hash:
779  *
780  * (0..3).to_h {|i| [i, i ** 2]} # => {0=>0, 1=>1, 2=>4, 3=>9}
781  *
782  * Raises an exception if an element of +self+ is not a 2-element array,
783  * and a block is not passed.
784  */
785 
786 static VALUE
787 enum_to_h(int argc, VALUE *argv, VALUE obj)
788 {
789  rb_block_call_func *iter = rb_block_given_p() ? enum_to_h_ii : enum_to_h_i;
790  return enum_hashify(obj, argc, argv, iter);
791 }
792 
793 static VALUE
794 inject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
795 {
796  struct MEMO *memo = MEMO_CAST(p);
797 
798  ENUM_WANT_SVALUE();
799 
800  if (UNDEF_P(memo->v1)) {
801  MEMO_V1_SET(memo, i);
802  }
803  else {
804  MEMO_V1_SET(memo, rb_yield_values(2, memo->v1, i));
805  }
806  return Qnil;
807 }
808 
809 static VALUE
810 inject_op_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
811 {
812  struct MEMO *memo = MEMO_CAST(p);
813  VALUE name;
814 
815  ENUM_WANT_SVALUE();
816 
817  if (UNDEF_P(memo->v1)) {
818  MEMO_V1_SET(memo, i);
819  }
820  else if (SYMBOL_P(name = memo->u3.value)) {
821  const ID mid = SYM2ID(name);
822  MEMO_V1_SET(memo, rb_funcallv_public(memo->v1, mid, 1, &i));
823  }
824  else {
825  VALUE args[2];
826  args[0] = name;
827  args[1] = i;
828  MEMO_V1_SET(memo, rb_f_send(numberof(args), args, memo->v1));
829  }
830  return Qnil;
831 }
832 
833 static VALUE
834 ary_inject_op(VALUE ary, VALUE init, VALUE op)
835 {
836  ID id;
837  VALUE v, e;
838  long i, n;
839 
840  if (RARRAY_LEN(ary) == 0)
841  return UNDEF_P(init) ? Qnil : init;
842 
843  if (UNDEF_P(init)) {
844  v = RARRAY_AREF(ary, 0);
845  i = 1;
846  if (RARRAY_LEN(ary) == 1)
847  return v;
848  }
849  else {
850  v = init;
851  i = 0;
852  }
853 
854  id = SYM2ID(op);
855  if (id == idPLUS) {
856  if (RB_INTEGER_TYPE_P(v) &&
858  rb_obj_respond_to(v, idPLUS, FALSE)) {
859  n = 0;
860  for (; i < RARRAY_LEN(ary); i++) {
861  e = RARRAY_AREF(ary, i);
862  if (FIXNUM_P(e)) {
863  n += FIX2LONG(e); /* should not overflow long type */
864  if (!FIXABLE(n)) {
865  v = rb_big_plus(LONG2NUM(n), v);
866  n = 0;
867  }
868  }
869  else if (RB_BIGNUM_TYPE_P(e))
870  v = rb_big_plus(e, v);
871  else
872  goto not_integer;
873  }
874  if (n != 0)
875  v = rb_fix_plus(LONG2FIX(n), v);
876  return v;
877 
878  not_integer:
879  if (n != 0)
880  v = rb_fix_plus(LONG2FIX(n), v);
881  }
882  }
883  for (; i < RARRAY_LEN(ary); i++) {
884  VALUE arg = RARRAY_AREF(ary, i);
885  v = rb_funcallv_public(v, id, 1, &arg);
886  }
887  return v;
888 }
889 
890 /*
891  * call-seq:
892  * inject(symbol) -> object
893  * inject(initial_value, symbol) -> object
894  * inject {|memo, value| ... } -> object
895  * inject(initial_value) {|memo, value| ... } -> object
896  *
897  * Returns the result of applying a reducer to an initial value and
898  * the first element of the Enumerable. It then takes the result and applies the
899  * function to it and the second element of the collection, and so on. The
900  * return value is the result returned by the final call to the function.
901  *
902  * You can think of
903  *
904  * [ a, b, c, d ].inject(i) { |r, v| fn(r, v) }
905  *
906  * as being
907  *
908  * fn(fn(fn(fn(i, a), b), c), d)
909  *
910  * In a way the +inject+ function _injects_ the function
911  * between the elements of the enumerable.
912  *
913  * +inject+ is aliased as +reduce+. You use it when you want to
914  * _reduce_ a collection to a single value.
915  *
916  * <b>The Calling Sequences</b>
917  *
918  * Let's start with the most verbose:
919  *
920  * enum.inject(initial_value) do |result, next_value|
921  * # do something with +result+ and +next_value+
922  * # the value returned by the block becomes the
923  * # value passed in to the next iteration
924  * # as +result+
925  * end
926  *
927  * For example:
928  *
929  * product = [ 2, 3, 4 ].inject(1) do |result, next_value|
930  * result * next_value
931  * end
932  * product #=> 24
933  *
934  * When this runs, the block is first called with +1+ (the initial value) and
935  * +2+ (the first element of the array). The block returns <tt>1*2</tt>, so on
936  * the next iteration the block is called with +2+ (the previous result) and
937  * +3+. The block returns +6+, and is called one last time with +6+ and +4+.
938  * The result of the block, +24+ becomes the value returned by +inject+. This
939  * code returns the product of the elements in the enumerable.
940  *
941  * <b>First Shortcut: Default Initial value</b>
942  *
943  * In the case of the previous example, the initial value, +1+, wasn't really
944  * necessary: the calculation of the product of a list of numbers is self-contained.
945  *
946  * In these circumstances, you can omit the +initial_value+ parameter. +inject+
947  * will then initially call the block with the first element of the collection
948  * as the +result+ parameter and the second element as the +next_value+.
949  *
950  * [ 2, 3, 4 ].inject do |result, next_value|
951  * result * next_value
952  * end
953  *
954  * This shortcut is convenient, but can only be used when the block produces a result
955  * which can be passed back to it as a first parameter.
956  *
957  * Here's an example where that's not the case: it returns a hash where the keys are words
958  * and the values are the number of occurrences of that word in the enumerable.
959  *
960  * freqs = File.read("README.md")
961  * .scan(/\w{2,}/)
962  * .reduce(Hash.new(0)) do |counts, word|
963  * counts[word] += 1
964  * counts
965  * end
966  * freqs #=> {"Actions"=>4,
967  * "Status"=>5,
968  * "MinGW"=>3,
969  * "https"=>27,
970  * "github"=>10,
971  * "com"=>15, ...
972  *
973  * Note that the last line of the block is just the word +counts+. This ensures the
974  * return value of the block is the result that's being calculated.
975  *
976  * <b>Second Shortcut: a Reducer function</b>
977  *
978  * A <i>reducer function</i> is a function that takes a partial result and the next value,
979  * returning the next partial result. The block that is given to +inject+ is a reducer.
980  *
981  * You can also write a reducer as a function and pass the name of that function
982  * (as a symbol) to +inject+. However, for this to work, the function
983  *
984  * 1. Must be defined on the type of the result value
985  * 2. Must accept a single parameter, the next value in the collection, and
986  * 3. Must return an updated result which will also implement the function.
987  *
988  * Here's an example that adds elements to a string. The two calls invoke the functions
989  * String#concat and String#+ on the result so far, passing it the next value.
990  *
991  * s = [ "cat", " ", "dog" ].inject("", :concat)
992  * s #=> "cat dog"
993  * s = [ "cat", " ", "dog" ].inject("The result is:", :+)
994  * s #=> "The result is: cat dog"
995  *
996  * Here's a more complex example when the result object maintains
997  * state of a different type to the enumerable elements.
998  *
999  * class Turtle
1000  *
1001  * def initialize
1002  * @x = @y = 0
1003  * end
1004  *
1005  * def move(dir)
1006  * case dir
1007  * when "n" then @y += 1
1008  * when "s" then @y -= 1
1009  * when "e" then @x += 1
1010  * when "w" then @x -= 1
1011  * end
1012  * self
1013  * end
1014  * end
1015  *
1016  * position = "nnneesw".chars.reduce(Turtle.new, :move)
1017  * position #=>> #<Turtle:0x00000001052f4698 @y=2, @x=1>
1018  *
1019  * <b>Third Shortcut: Reducer With no Initial Value</b>
1020  *
1021  * If your reducer returns a value that it can accept as a parameter, then you
1022  * don't have to pass in an initial value. Here <tt>:*</tt> is the name of the
1023  * _times_ function:
1024  *
1025  * product = [ 2, 3, 4 ].inject(:*)
1026  * product # => 24
1027  *
1028  * String concatenation again:
1029  *
1030  * s = [ "cat", " ", "dog" ].inject(:+)
1031  * s #=> "cat dog"
1032  *
1033  * And an example that converts a hash to an array of two-element subarrays.
1034  *
1035  * nested = {foo: 0, bar: 1}.inject([], :push)
1036  * nested # => [[:foo, 0], [:bar, 1]]
1037  *
1038  *
1039  */
1040 static VALUE
1041 enum_inject(int argc, VALUE *argv, VALUE obj)
1042 {
1043  struct MEMO *memo;
1044  VALUE init, op;
1045  rb_block_call_func *iter = inject_i;
1046  ID id;
1047  int num_args;
1048 
1049  if (rb_block_given_p()) {
1050  num_args = rb_scan_args(argc, argv, "02", &init, &op);
1051  }
1052  else {
1053  num_args = rb_scan_args(argc, argv, "11", &init, &op);
1054  }
1055 
1056  switch (num_args) {
1057  case 0:
1058  init = Qundef;
1059  break;
1060  case 1:
1061  if (rb_block_given_p()) {
1062  break;
1063  }
1064  id = rb_check_id(&init);
1065  op = id ? ID2SYM(id) : init;
1066  init = Qundef;
1067  iter = inject_op_i;
1068  break;
1069  case 2:
1070  if (rb_block_given_p()) {
1071  rb_warning("given block not used");
1072  }
1073  id = rb_check_id(&op);
1074  if (id) op = ID2SYM(id);
1075  iter = inject_op_i;
1076  break;
1077  }
1078 
1079  if (iter == inject_op_i &&
1080  SYMBOL_P(op) &&
1081  RB_TYPE_P(obj, T_ARRAY) &&
1082  rb_method_basic_definition_p(CLASS_OF(obj), id_each)) {
1083  return ary_inject_op(obj, init, op);
1084  }
1085 
1086  memo = MEMO_NEW(init, Qnil, op);
1087  rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
1088  if (UNDEF_P(memo->v1)) return Qnil;
1089  return memo->v1;
1090 }
1091 
1092 static VALUE
1093 partition_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arys))
1094 {
1095  struct MEMO *memo = MEMO_CAST(arys);
1096  VALUE ary;
1097  ENUM_WANT_SVALUE();
1098 
1099  if (RTEST(enum_yield(argc, i))) {
1100  ary = memo->v1;
1101  }
1102  else {
1103  ary = memo->v2;
1104  }
1105  rb_ary_push(ary, i);
1106  return Qnil;
1107 }
1108 
1109 /*
1110  * call-seq:
1111  * partition {|element| ... } -> [true_array, false_array]
1112  * partition -> enumerator
1113  *
1114  * With a block given, returns an array of two arrays:
1115  *
1116  * - The first having those elements for which the block returns a truthy value.
1117  * - The other having all other elements.
1118  *
1119  * Examples:
1120  *
1121  * p = (1..4).partition {|i| i.even? }
1122  * p # => [[2, 4], [1, 3]]
1123  * p = ('a'..'d').partition {|c| c < 'c' }
1124  * p # => [["a", "b"], ["c", "d"]]
1125  * h = {foo: 0, bar: 1, baz: 2, bat: 3}
1126  * p = h.partition {|key, value| key.start_with?('b') }
1127  * p # => [[[:bar, 1], [:baz, 2], [:bat, 3]], [[:foo, 0]]]
1128  * p = h.partition {|key, value| value < 2 }
1129  * p # => [[[:foo, 0], [:bar, 1]], [[:baz, 2], [:bat, 3]]]
1130  *
1131  * With no block given, returns an Enumerator.
1132  *
1133  * Related: Enumerable#group_by.
1134  *
1135  */
1136 
1137 static VALUE
1138 enum_partition(VALUE obj)
1139 {
1140  struct MEMO *memo;
1141 
1142  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1143 
1144  memo = MEMO_NEW(rb_ary_new(), rb_ary_new(), 0);
1145  rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);
1146 
1147  return rb_assoc_new(memo->v1, memo->v2);
1148 }
1149 
1150 static VALUE
1151 group_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
1152 {
1153  VALUE group;
1154  VALUE values;
1155 
1156  ENUM_WANT_SVALUE();
1157 
1158  group = enum_yield(argc, i);
1159  values = rb_hash_aref(hash, group);
1160  if (!RB_TYPE_P(values, T_ARRAY)) {
1161  values = rb_ary_new3(1, i);
1162  rb_hash_aset(hash, group, values);
1163  }
1164  else {
1165  rb_ary_push(values, i);
1166  }
1167  return Qnil;
1168 }
1169 
1170 /*
1171  * call-seq:
1172  * group_by {|element| ... } -> hash
1173  * group_by -> enumerator
1174  *
1175  * With a block given returns a hash:
1176  *
1177  * - Each key is a return value from the block.
1178  * - Each value is an array of those elements for which the block returned that key.
1179  *
1180  * Examples:
1181  *
1182  * g = (1..6).group_by {|i| i%3 }
1183  * g # => {1=>[1, 4], 2=>[2, 5], 0=>[3, 6]}
1184  * h = {foo: 0, bar: 1, baz: 0, bat: 1}
1185  * g = h.group_by {|key, value| value }
1186  * g # => {0=>[[:foo, 0], [:baz, 0]], 1=>[[:bar, 1], [:bat, 1]]}
1187  *
1188  * With no block given, returns an Enumerator.
1189  *
1190  */
1191 
1192 static VALUE
1193 enum_group_by(VALUE obj)
1194 {
1195  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1196 
1197  return enum_hashify(obj, 0, 0, group_by_i);
1198 }
1199 
1200 static int
1201 tally_up(st_data_t *group, st_data_t *value, st_data_t arg, int existing)
1202 {
1203  VALUE tally = (VALUE)*value;
1204  VALUE hash = (VALUE)arg;
1205  if (!existing) {
1206  tally = INT2FIX(1);
1207  }
1208  else if (FIXNUM_P(tally) && tally < INT2FIX(FIXNUM_MAX)) {
1209  tally += INT2FIX(1) & ~FIXNUM_FLAG;
1210  }
1211  else {
1212  Check_Type(tally, T_BIGNUM);
1213  tally = rb_big_plus(tally, INT2FIX(1));
1214  RB_OBJ_WRITTEN(hash, Qundef, tally);
1215  }
1216  *value = (st_data_t)tally;
1217  if (!SPECIAL_CONST_P(*group)) RB_OBJ_WRITTEN(hash, Qundef, *group);
1218  return ST_CONTINUE;
1219 }
1220 
1221 static VALUE
1222 rb_enum_tally_up(VALUE hash, VALUE group)
1223 {
1224  rb_hash_stlike_update(hash, group, tally_up, (st_data_t)hash);
1225  return hash;
1226 }
1227 
1228 static VALUE
1229 tally_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
1230 {
1231  ENUM_WANT_SVALUE();
1232  rb_enum_tally_up(hash, i);
1233  return Qnil;
1234 }
1235 
1236 /*
1237  * call-seq:
1238  * tally(hash = {}) -> hash
1239  *
1240  * When argument +hash+ is not given,
1241  * returns a new hash whose keys are the distinct elements in +self+;
1242  * each integer value is the count of occurrences of each element:
1243  *
1244  * %w[a b c b c a c b].tally # => {"a"=>2, "b"=>3, "c"=>3}
1245  *
1246  * When argument +hash+ is given,
1247  * returns +hash+, possibly augmented; for each element +ele+ in +self+:
1248  *
1249  * - Adds it as a key with a zero value if that key does not already exist:
1250  *
1251  * hash[ele] = 0 unless hash.include?(ele)
1252  *
1253  * - Increments the value of key +ele+:
1254  *
1255  * hash[ele] += 1
1256  *
1257  * This is useful for accumulating tallies across multiple enumerables:
1258  *
1259  * h = {} # => {}
1260  * %w[a c d b c a].tally(h) # => {"a"=>2, "c"=>2, "d"=>1, "b"=>1}
1261  * %w[b a z].tally(h) # => {"a"=>3, "c"=>2, "d"=>1, "b"=>2, "z"=>1}
1262  * %w[b a m].tally(h) # => {"a"=>4, "c"=>2, "d"=>1, "b"=>3, "z"=>1, "m"=>1}
1263  *
1264  * The key to be added or found for an element depends on the class of +self+;
1265  * see {Enumerable in Ruby Classes}[rdoc-ref:Enumerable@Enumerable+in+Ruby+Classes].
1266  *
1267  * Examples:
1268  *
1269  * - Array (and certain array-like classes):
1270  * the key is the element (as above).
1271  * - Hash (and certain hash-like classes):
1272  * the key is the 2-element array formed from the key-value pair:
1273  *
1274  * h = {} # => {}
1275  * {foo: 'a', bar: 'b'}.tally(h) # => {[:foo, "a"]=>1, [:bar, "b"]=>1}
1276  * {foo: 'c', bar: 'd'}.tally(h) # => {[:foo, "a"]=>1, [:bar, "b"]=>1, [:foo, "c"]=>1, [:bar, "d"]=>1}
1277  * {foo: 'a', bar: 'b'}.tally(h) # => {[:foo, "a"]=>2, [:bar, "b"]=>2, [:foo, "c"]=>1, [:bar, "d"]=>1}
1278  * {foo: 'c', bar: 'd'}.tally(h) # => {[:foo, "a"]=>2, [:bar, "b"]=>2, [:foo, "c"]=>2, [:bar, "d"]=>2}
1279  *
1280  */
1281 
1282 static VALUE
1283 enum_tally(int argc, VALUE *argv, VALUE obj)
1284 {
1285  VALUE hash;
1286  if (rb_check_arity(argc, 0, 1)) {
1287  hash = rb_to_hash_type(argv[0]);
1288  rb_check_frozen(hash);
1289  }
1290  else {
1291  hash = rb_hash_new();
1292  }
1293 
1294  return enum_hashify_into(obj, 0, 0, tally_i, hash);
1295 }
1296 
1297 NORETURN(static VALUE first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params)));
1298 static VALUE
1299 first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))
1300 {
1301  struct MEMO *memo = MEMO_CAST(params);
1302  ENUM_WANT_SVALUE();
1303 
1304  MEMO_V1_SET(memo, i);
1305  rb_iter_break();
1306 
1308 }
1309 
1310 static VALUE enum_take(VALUE obj, VALUE n);
1311 
1312 /*
1313  * call-seq:
1314  * first -> element or nil
1315  * first(n) -> array
1316  *
1317  * Returns the first element or elements.
1318  *
1319  * With no argument, returns the first element, or +nil+ if there is none:
1320  *
1321  * (1..4).first # => 1
1322  * %w[a b c].first # => "a"
1323  * {foo: 1, bar: 1, baz: 2}.first # => [:foo, 1]
1324  * [].first # => nil
1325  *
1326  * With integer argument +n+, returns an array
1327  * containing the first +n+ elements that exist:
1328  *
1329  * (1..4).first(2) # => [1, 2]
1330  * %w[a b c d].first(3) # => ["a", "b", "c"]
1331  * %w[a b c d].first(50) # => ["a", "b", "c", "d"]
1332  * {foo: 1, bar: 1, baz: 2}.first(2) # => [[:foo, 1], [:bar, 1]]
1333  * [].first(2) # => []
1334  *
1335  */
1336 
1337 static VALUE
1338 enum_first(int argc, VALUE *argv, VALUE obj)
1339 {
1340  struct MEMO *memo;
1341  rb_check_arity(argc, 0, 1);
1342  if (argc > 0) {
1343  return enum_take(obj, argv[0]);
1344  }
1345  else {
1346  memo = MEMO_NEW(Qnil, 0, 0);
1347  rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
1348  return memo->v1;
1349  }
1350 }
1351 
1352 /*
1353  * call-seq:
1354  * sort -> array
1355  * sort {|a, b| ... } -> array
1356  *
1357  * Returns an array containing the sorted elements of +self+.
1358  * The ordering of equal elements is indeterminate and may be unstable.
1359  *
1360  * With no block given, the sort compares
1361  * using the elements' own method <tt>#<=></tt>:
1362  *
1363  * %w[b c a d].sort # => ["a", "b", "c", "d"]
1364  * {foo: 0, bar: 1, baz: 2}.sort # => [[:bar, 1], [:baz, 2], [:foo, 0]]
1365  *
1366  * With a block given, comparisons in the block determine the ordering.
1367  * The block is called with two elements +a+ and +b+, and must return:
1368  *
1369  * - A negative integer if <tt>a < b</tt>.
1370  * - Zero if <tt>a == b</tt>.
1371  * - A positive integer if <tt>a > b</tt>.
1372  *
1373  * Examples:
1374  *
1375  * a = %w[b c a d]
1376  * a.sort {|a, b| b <=> a } # => ["d", "c", "b", "a"]
1377  * h = {foo: 0, bar: 1, baz: 2}
1378  * h.sort {|a, b| b <=> a } # => [[:foo, 0], [:baz, 2], [:bar, 1]]
1379  *
1380  * See also #sort_by. It implements a Schwartzian transform
1381  * which is useful when key computation or comparison is expensive.
1382  */
1383 
1384 static VALUE
1385 enum_sort(VALUE obj)
1386 {
1387  return rb_ary_sort_bang(enum_to_a(0, 0, obj));
1388 }
1389 
1390 #define SORT_BY_BUFSIZE 16
1391 #define SORT_BY_UNIFORMED(num, flo, fix) (((num&1)<<2)|((flo&1)<<1)|fix)
1393  const VALUE ary;
1394  const VALUE buf;
1395  uint8_t n;
1396  uint8_t primitive_uniformed;
1397 };
1398 
1399 static VALUE
1400 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
1401 {
1402  struct sort_by_data *data = (struct sort_by_data *)&MEMO_CAST(_data)->v1;
1403  VALUE ary = data->ary;
1404  VALUE v;
1405 
1406  ENUM_WANT_SVALUE();
1407 
1408  v = enum_yield(argc, i);
1409 
1410  if (RBASIC(ary)->klass) {
1411  rb_raise(rb_eRuntimeError, "sort_by reentered");
1412  }
1413  if (RARRAY_LEN(data->buf) != SORT_BY_BUFSIZE*2) {
1414  rb_raise(rb_eRuntimeError, "sort_by reentered");
1415  }
1416 
1417  if (data->primitive_uniformed) {
1418  data->primitive_uniformed &= SORT_BY_UNIFORMED((FIXNUM_P(v)) || (RB_FLOAT_TYPE_P(v)),
1419  RB_FLOAT_TYPE_P(v),
1420  FIXNUM_P(v));
1421  }
1422  RARRAY_ASET(data->buf, data->n*2, v);
1423  RARRAY_ASET(data->buf, data->n*2+1, i);
1424  data->n++;
1425  if (data->n == SORT_BY_BUFSIZE) {
1426  rb_ary_concat(ary, data->buf);
1427  data->n = 0;
1428  }
1429  return Qnil;
1430 }
1431 
1432 static int
1433 sort_by_cmp(const void *ap, const void *bp, void *data)
1434 {
1435  VALUE a;
1436  VALUE b;
1437  VALUE ary = (VALUE)data;
1438 
1439  if (RBASIC(ary)->klass) {
1440  rb_raise(rb_eRuntimeError, "sort_by reentered");
1441  }
1442 
1443  a = *(VALUE *)ap;
1444  b = *(VALUE *)bp;
1445 
1446  return OPTIMIZED_CMP(a, b);
1447 }
1448 
1449 
1450 /*
1451  This is parts of uniform sort
1452 */
1453 
1454 #define uless rb_uniform_is_less
1455 #define UNIFORM_SWAP(a,b)\
1456  do{struct rb_uniform_sort_data tmp = a; a = b; b = tmp;} while(0)
1457 
1459  VALUE v;
1460  VALUE i;
1461 };
1462 
1463 static inline bool
1464 rb_uniform_is_less(VALUE a, VALUE b)
1465 {
1466 
1467  if (FIXNUM_P(a) && FIXNUM_P(b)) {
1468  return (SIGNED_VALUE)a < (SIGNED_VALUE)b;
1469  }
1470  else if (FIXNUM_P(a)) {
1472  return rb_float_cmp(b, a) > 0;
1473  }
1474  else {
1476  return rb_float_cmp(a, b) < 0;
1477  }
1478 }
1479 
1480 static inline bool
1481 rb_uniform_is_larger(VALUE a, VALUE b)
1482 {
1483 
1484  if (FIXNUM_P(a) && FIXNUM_P(b)) {
1485  return (SIGNED_VALUE)a > (SIGNED_VALUE)b;
1486  }
1487  else if (FIXNUM_P(a)) {
1489  return rb_float_cmp(b, a) < 0;
1490  }
1491  else {
1493  return rb_float_cmp(a, b) > 0;
1494  }
1495 }
1496 
1497 #define med3_val(a,b,c) (uless(a,b)?(uless(b,c)?b:uless(c,a)?a:c):(uless(c,b)?b:uless(a,c)?a:c))
1498 
1499 static void
1500 rb_uniform_insertionsort_2(struct rb_uniform_sort_data* ptr_begin,
1501  struct rb_uniform_sort_data* ptr_end)
1502 {
1503  if ((ptr_end - ptr_begin) < 2) return;
1504  struct rb_uniform_sort_data tmp, *j, *k,
1505  *index = ptr_begin+1;
1506  for (; index < ptr_end; index++) {
1507  tmp = *index;
1508  j = k = index;
1509  if (uless(tmp.v, ptr_begin->v)) {
1510  while (ptr_begin < j) {
1511  *j = *(--k);
1512  j = k;
1513  }
1514  }
1515  else {
1516  while (uless(tmp.v, (--k)->v)) {
1517  *j = *k;
1518  j = k;
1519  }
1520  }
1521  *j = tmp;
1522  }
1523 }
1524 
1525 static inline void
1526 rb_uniform_heap_down_2(struct rb_uniform_sort_data* ptr_begin,
1527  size_t offset, size_t len)
1528 {
1529  size_t c;
1530  struct rb_uniform_sort_data tmp = ptr_begin[offset];
1531  while ((c = (offset<<1)+1) <= len) {
1532  if (c < len && uless(ptr_begin[c].v, ptr_begin[c+1].v)) {
1533  c++;
1534  }
1535  if (!uless(tmp.v, ptr_begin[c].v)) break;
1536  ptr_begin[offset] = ptr_begin[c];
1537  offset = c;
1538  }
1539  ptr_begin[offset] = tmp;
1540 }
1541 
1542 static void
1543 rb_uniform_heapsort_2(struct rb_uniform_sort_data* ptr_begin,
1544  struct rb_uniform_sort_data* ptr_end)
1545 {
1546  size_t n = ptr_end - ptr_begin;
1547  if (n < 2) return;
1548 
1549  for (size_t offset = n>>1; offset > 0;) {
1550  rb_uniform_heap_down_2(ptr_begin, --offset, n-1);
1551  }
1552  for (size_t offset = n-1; offset > 0;) {
1553  UNIFORM_SWAP(*ptr_begin, ptr_begin[offset]);
1554  rb_uniform_heap_down_2(ptr_begin, 0, --offset);
1555  }
1556 }
1557 
1558 
1559 static void
1560 rb_uniform_quicksort_intro_2(struct rb_uniform_sort_data* ptr_begin,
1561  struct rb_uniform_sort_data* ptr_end, size_t d)
1562 {
1563 
1564  if (ptr_end - ptr_begin <= 16) {
1565  rb_uniform_insertionsort_2(ptr_begin, ptr_end);
1566  return;
1567  }
1568  if (d == 0) {
1569  rb_uniform_heapsort_2(ptr_begin, ptr_end);
1570  return;
1571  }
1572 
1573  VALUE x = med3_val(ptr_begin->v,
1574  ptr_begin[(ptr_end - ptr_begin)>>1].v,
1575  ptr_end[-1].v);
1576  struct rb_uniform_sort_data *i = ptr_begin;
1577  struct rb_uniform_sort_data *j = ptr_end-1;
1578 
1579  do {
1580  while (uless(i->v, x)) i++;
1581  while (uless(x, j->v)) j--;
1582  if (i <= j) {
1583  UNIFORM_SWAP(*i, *j);
1584  i++;
1585  j--;
1586  }
1587  } while (i <= j);
1588  j++;
1589  if (ptr_end - j > 1) rb_uniform_quicksort_intro_2(j, ptr_end, d-1);
1590  if (i - ptr_begin > 1) rb_uniform_quicksort_intro_2(ptr_begin, i, d-1);
1591 }
1592 
1598 static void
1599 rb_uniform_intro_sort_2(struct rb_uniform_sort_data* ptr_begin,
1600  struct rb_uniform_sort_data* ptr_end)
1601 {
1602  size_t n = ptr_end - ptr_begin;
1603  size_t d = CHAR_BIT * sizeof(n) - nlz_intptr(n) - 1;
1604  bool sorted_flag = true;
1605 
1606  for (struct rb_uniform_sort_data* ptr = ptr_begin+1; ptr < ptr_end; ptr++) {
1607  if (rb_uniform_is_larger((ptr-1)->v, (ptr)->v)) {
1608  sorted_flag = false;
1609  break;
1610  }
1611  }
1612 
1613  if (sorted_flag) {
1614  return;
1615  }
1616  rb_uniform_quicksort_intro_2(ptr_begin, ptr_end, d<<1);
1617 }
1618 
1619 #undef uless
1620 
1621 
1622 /*
1623  * call-seq:
1624  * sort_by {|element| ... } -> array
1625  * sort_by -> enumerator
1626  *
1627  * With a block given, returns an array of elements of +self+,
1628  * sorted according to the value returned by the block for each element.
1629  * The ordering of equal elements is indeterminate and may be unstable.
1630  *
1631  * Examples:
1632  *
1633  * a = %w[xx xxx x xxxx]
1634  * a.sort_by {|s| s.size } # => ["x", "xx", "xxx", "xxxx"]
1635  * a.sort_by {|s| -s.size } # => ["xxxx", "xxx", "xx", "x"]
1636  * h = {foo: 2, bar: 1, baz: 0}
1637  * h.sort_by{|key, value| value } # => [[:baz, 0], [:bar, 1], [:foo, 2]]
1638  * h.sort_by{|key, value| key } # => [[:bar, 1], [:baz, 0], [:foo, 2]]
1639  *
1640  * With no block given, returns an Enumerator.
1641  *
1642  * The current implementation of #sort_by generates an array of
1643  * tuples containing the original collection element and the mapped
1644  * value. This makes #sort_by fairly expensive when the keysets are
1645  * simple.
1646  *
1647  * require 'benchmark'
1648  *
1649  * a = (1..100000).map { rand(100000) }
1650  *
1651  * Benchmark.bm(10) do |b|
1652  * b.report("Sort") { a.sort }
1653  * b.report("Sort by") { a.sort_by { |a| a } }
1654  * end
1655  *
1656  * <em>produces:</em>
1657  *
1658  * user system total real
1659  * Sort 0.180000 0.000000 0.180000 ( 0.175469)
1660  * Sort by 1.980000 0.040000 2.020000 ( 2.013586)
1661  *
1662  * However, consider the case where comparing the keys is a non-trivial
1663  * operation. The following code sorts some files on modification time
1664  * using the basic #sort method.
1665  *
1666  * files = Dir["*"]
1667  * sorted = files.sort { |a, b| File.new(a).mtime <=> File.new(b).mtime }
1668  * sorted #=> ["mon", "tues", "wed", "thurs"]
1669  *
1670  * This sort is inefficient: it generates two new File
1671  * objects during every comparison. A slightly better technique is to
1672  * use the Kernel#test method to generate the modification
1673  * times directly.
1674  *
1675  * files = Dir["*"]
1676  * sorted = files.sort { |a, b|
1677  * test(?M, a) <=> test(?M, b)
1678  * }
1679  * sorted #=> ["mon", "tues", "wed", "thurs"]
1680  *
1681  * This still generates many unnecessary Time objects. A more
1682  * efficient technique is to cache the sort keys (modification times
1683  * in this case) before the sort. Perl users often call this approach
1684  * a Schwartzian transform, after Randal Schwartz. We construct a
1685  * temporary array, where each element is an array containing our
1686  * sort key along with the filename. We sort this array, and then
1687  * extract the filename from the result.
1688  *
1689  * sorted = Dir["*"].collect { |f|
1690  * [test(?M, f), f]
1691  * }.sort.collect { |f| f[1] }
1692  * sorted #=> ["mon", "tues", "wed", "thurs"]
1693  *
1694  * This is exactly what #sort_by does internally.
1695  *
1696  * sorted = Dir["*"].sort_by { |f| test(?M, f) }
1697  * sorted #=> ["mon", "tues", "wed", "thurs"]
1698  *
1699  * To produce the reverse of a specific order, the following can be used:
1700  *
1701  * ary.sort_by { ... }.reverse!
1702  */
1703 
1704 static VALUE
1705 enum_sort_by(VALUE obj)
1706 {
1707  VALUE ary, buf;
1708  struct MEMO *memo;
1709  long i;
1710  struct sort_by_data *data;
1711 
1712  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1713 
1714  if (RB_TYPE_P(obj, T_ARRAY) && RARRAY_LEN(obj) <= LONG_MAX/2) {
1715  ary = rb_ary_new2(RARRAY_LEN(obj)*2);
1716  }
1717  else {
1718  ary = rb_ary_new();
1719  }
1720  RBASIC_CLEAR_CLASS(ary);
1721  buf = rb_ary_hidden_new(SORT_BY_BUFSIZE*2);
1722  rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
1723  memo = MEMO_NEW(0, 0, 0);
1724  data = (struct sort_by_data *)&memo->v1;
1725  RB_OBJ_WRITE(memo, &data->ary, ary);
1726  RB_OBJ_WRITE(memo, &data->buf, buf);
1727  data->n = 0;
1728  data->primitive_uniformed = SORT_BY_UNIFORMED((CMP_OPTIMIZABLE(FLOAT) && CMP_OPTIMIZABLE(INTEGER)),
1729  CMP_OPTIMIZABLE(FLOAT),
1730  CMP_OPTIMIZABLE(INTEGER));
1731  rb_block_call(obj, id_each, 0, 0, sort_by_i, (VALUE)memo);
1732  ary = data->ary;
1733  buf = data->buf;
1734  if (data->n) {
1735  rb_ary_resize(buf, data->n*2);
1736  rb_ary_concat(ary, buf);
1737  }
1738  if (RARRAY_LEN(ary) > 2) {
1739  if (data->primitive_uniformed) {
1740  RARRAY_PTR_USE(ary, ptr,
1741  rb_uniform_intro_sort_2((struct rb_uniform_sort_data*)ptr,
1742  (struct rb_uniform_sort_data*)(ptr + RARRAY_LEN(ary))));
1743  }
1744  else {
1745  RARRAY_PTR_USE(ary, ptr,
1746  ruby_qsort(ptr, RARRAY_LEN(ary)/2, 2*sizeof(VALUE),
1747  sort_by_cmp, (void *)ary));
1748  }
1749  }
1750  if (RBASIC(ary)->klass) {
1751  rb_raise(rb_eRuntimeError, "sort_by reentered");
1752  }
1753  for (i=1; i<RARRAY_LEN(ary); i+=2) {
1754  RARRAY_ASET(ary, i/2, RARRAY_AREF(ary, i));
1755  }
1756  rb_ary_resize(ary, RARRAY_LEN(ary)/2);
1757  RBASIC_SET_CLASS_RAW(ary, rb_cArray);
1758 
1759  return ary;
1760 }
1761 
1762 #define ENUMFUNC(name) argc ? name##_eqq : rb_block_given_p() ? name##_iter_i : name##_i
1763 
1764 #define ENUM_BLOCK_CALL(name) \
1765  rb_block_call2(obj, id_each, 0, 0, ENUMFUNC(name), (VALUE)memo, rb_block_given_p() && rb_block_pair_yield_optimizable() ? RB_BLOCK_NO_USE_PACKED_ARGS : 0);
1766 
1767 #define MEMO_ENUM_NEW(v1) (rb_check_arity(argc, 0, 1), MEMO_NEW((v1), (argc ? *argv : 0), 0))
1768 
1769 #define DEFINE_ENUMFUNCS(name) \
1770 static VALUE enum_##name##_func(VALUE result, struct MEMO *memo); \
1771 \
1772 static VALUE \
1773 name##_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1774 { \
1775  return enum_##name##_func(rb_enum_values_pack(argc, argv), MEMO_CAST(memo)); \
1776 } \
1777 \
1778 static VALUE \
1779 name##_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1780 { \
1781  return enum_##name##_func(rb_yield_values2(argc, argv), MEMO_CAST(memo)); \
1782 } \
1783 \
1784 static VALUE \
1785 name##_eqq(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1786 { \
1787  ENUM_WANT_SVALUE(); \
1788  return enum_##name##_func(rb_funcallv(MEMO_CAST(memo)->v2, id_eqq, 1, &i), MEMO_CAST(memo)); \
1789 } \
1790 \
1791 static VALUE \
1792 enum_##name##_func(VALUE result, struct MEMO *memo)
1793 
1794 #define WARN_UNUSED_BLOCK(argc) do { \
1795  if ((argc) > 0 && rb_block_given_p()) { \
1796  rb_warn("given block not used"); \
1797  } \
1798 } while (0)
1799 
1800 DEFINE_ENUMFUNCS(all)
1801 {
1802  if (!RTEST(result)) {
1803  MEMO_V1_SET(memo, Qfalse);
1804  rb_iter_break();
1805  }
1806  return Qnil;
1807 }
1808 
1809 /*
1810  * call-seq:
1811  * all? -> true or false
1812  * all?(pattern) -> true or false
1813  * all? {|element| ... } -> true or false
1814  *
1815  * Returns whether every element meets a given criterion.
1816  *
1817  * If +self+ has no element, returns +true+ and argument or block
1818  * are not used.
1819  *
1820  * With no argument and no block,
1821  * returns whether every element is truthy:
1822  *
1823  * (1..4).all? # => true
1824  * %w[a b c d].all? # => true
1825  * [1, 2, nil].all? # => false
1826  * ['a','b', false].all? # => false
1827  * [].all? # => true
1828  *
1829  * With argument +pattern+ and no block,
1830  * returns whether for each element +element+,
1831  * <tt>pattern === element</tt>:
1832  *
1833  * (1..4).all?(Integer) # => true
1834  * (1..4).all?(Numeric) # => true
1835  * (1..4).all?(Float) # => false
1836  * %w[bar baz bat bam].all?(/ba/) # => true
1837  * %w[bar baz bat bam].all?(/bar/) # => false
1838  * %w[bar baz bat bam].all?('ba') # => false
1839  * {foo: 0, bar: 1, baz: 2}.all?(Array) # => true
1840  * {foo: 0, bar: 1, baz: 2}.all?(Hash) # => false
1841  * [].all?(Integer) # => true
1842  *
1843  * With a block given, returns whether the block returns a truthy value
1844  * for every element:
1845  *
1846  * (1..4).all? {|element| element < 5 } # => true
1847  * (1..4).all? {|element| element < 4 } # => false
1848  * {foo: 0, bar: 1, baz: 2}.all? {|key, value| value < 3 } # => true
1849  * {foo: 0, bar: 1, baz: 2}.all? {|key, value| value < 2 } # => false
1850  *
1851  * Related: #any?, #none? #one?.
1852  *
1853  */
1854 
1855 static VALUE
1856 enum_all(int argc, VALUE *argv, VALUE obj)
1857 {
1858  struct MEMO *memo = MEMO_ENUM_NEW(Qtrue);
1859  WARN_UNUSED_BLOCK(argc);
1860  ENUM_BLOCK_CALL(all);
1861  return memo->v1;
1862 }
1863 
1864 DEFINE_ENUMFUNCS(any)
1865 {
1866  if (RTEST(result)) {
1867  MEMO_V1_SET(memo, Qtrue);
1868  rb_iter_break();
1869  }
1870  return Qnil;
1871 }
1872 
1873 /*
1874  * call-seq:
1875  * any? -> true or false
1876  * any?(pattern) -> true or false
1877  * any? {|element| ... } -> true or false
1878  *
1879  * Returns whether any element meets a given criterion.
1880  *
1881  * If +self+ has no element, returns +false+ and argument or block
1882  * are not used.
1883  *
1884  * With no argument and no block,
1885  * returns whether any element is truthy:
1886  *
1887  * (1..4).any? # => true
1888  * %w[a b c d].any? # => true
1889  * [1, false, nil].any? # => true
1890  * [].any? # => false
1891  *
1892  * With argument +pattern+ and no block,
1893  * returns whether for any element +element+,
1894  * <tt>pattern === element</tt>:
1895  *
1896  * [nil, false, 0].any?(Integer) # => true
1897  * [nil, false, 0].any?(Numeric) # => true
1898  * [nil, false, 0].any?(Float) # => false
1899  * %w[bar baz bat bam].any?(/m/) # => true
1900  * %w[bar baz bat bam].any?(/foo/) # => false
1901  * %w[bar baz bat bam].any?('ba') # => false
1902  * {foo: 0, bar: 1, baz: 2}.any?(Array) # => true
1903  * {foo: 0, bar: 1, baz: 2}.any?(Hash) # => false
1904  * [].any?(Integer) # => false
1905  *
1906  * With a block given, returns whether the block returns a truthy value
1907  * for any element:
1908  *
1909  * (1..4).any? {|element| element < 2 } # => true
1910  * (1..4).any? {|element| element < 1 } # => false
1911  * {foo: 0, bar: 1, baz: 2}.any? {|key, value| value < 1 } # => true
1912  * {foo: 0, bar: 1, baz: 2}.any? {|key, value| value < 0 } # => false
1913  *
1914  * Related: #all?, #none?, #one?.
1915  */
1916 
1917 static VALUE
1918 enum_any(int argc, VALUE *argv, VALUE obj)
1919 {
1920  struct MEMO *memo = MEMO_ENUM_NEW(Qfalse);
1921  WARN_UNUSED_BLOCK(argc);
1922  ENUM_BLOCK_CALL(any);
1923  return memo->v1;
1924 }
1925 
1926 DEFINE_ENUMFUNCS(one)
1927 {
1928  if (RTEST(result)) {
1929  if (UNDEF_P(memo->v1)) {
1930  MEMO_V1_SET(memo, Qtrue);
1931  }
1932  else if (memo->v1 == Qtrue) {
1933  MEMO_V1_SET(memo, Qfalse);
1934  rb_iter_break();
1935  }
1936  }
1937  return Qnil;
1938 }
1939 
1940 struct nmin_data {
1941  long n;
1942  long bufmax;
1943  long curlen;
1944  VALUE buf;
1945  VALUE limit;
1946  int (*cmpfunc)(const void *, const void *, void *);
1947  int rev: 1; /* max if 1 */
1948  int by: 1; /* min_by if 1 */
1949 };
1950 
1951 static VALUE
1952 cmpint_reenter_check(struct nmin_data *data, VALUE val)
1953 {
1954  if (RBASIC(data->buf)->klass) {
1955  rb_raise(rb_eRuntimeError, "%s%s reentered",
1956  data->rev ? "max" : "min",
1957  data->by ? "_by" : "");
1958  }
1959  return val;
1960 }
1961 
1962 static int
1963 nmin_cmp(const void *ap, const void *bp, void *_data)
1964 {
1965  struct nmin_data *data = (struct nmin_data *)_data;
1966  VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
1967 #define rb_cmpint(cmp, a, b) rb_cmpint(cmpint_reenter_check(data, (cmp)), a, b)
1968  return OPTIMIZED_CMP(a, b);
1969 #undef rb_cmpint
1970 }
1971 
1972 static int
1973 nmin_block_cmp(const void *ap, const void *bp, void *_data)
1974 {
1975  struct nmin_data *data = (struct nmin_data *)_data;
1976  VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
1977  VALUE cmp = rb_yield_values(2, a, b);
1978  cmpint_reenter_check(data, cmp);
1979  return rb_cmpint(cmp, a, b);
1980 }
1981 
1982 static void
1983 nmin_filter(struct nmin_data *data)
1984 {
1985  long n;
1986  VALUE *beg;
1987  int eltsize;
1988  long numelts;
1989 
1990  long left, right;
1991  long store_index;
1992 
1993  long i, j;
1994 
1995  if (data->curlen <= data->n)
1996  return;
1997 
1998  n = data->n;
1999  beg = RARRAY_PTR(data->buf);
2000  eltsize = data->by ? 2 : 1;
2001  numelts = data->curlen;
2002 
2003  left = 0;
2004  right = numelts-1;
2005 
2006 #define GETPTR(i) (beg+(i)*eltsize)
2007 
2008 #define SWAP(i, j) do { \
2009  VALUE tmp[2]; \
2010  memcpy(tmp, GETPTR(i), sizeof(VALUE)*eltsize); \
2011  memcpy(GETPTR(i), GETPTR(j), sizeof(VALUE)*eltsize); \
2012  memcpy(GETPTR(j), tmp, sizeof(VALUE)*eltsize); \
2013 } while (0)
2014 
2015  while (1) {
2016  long pivot_index = left + (right-left)/2;
2017  long num_pivots = 1;
2018 
2019  SWAP(pivot_index, right);
2020  pivot_index = right;
2021 
2022  store_index = left;
2023  i = left;
2024  while (i <= right-num_pivots) {
2025  int c = data->cmpfunc(GETPTR(i), GETPTR(pivot_index), data);
2026  if (data->rev)
2027  c = -c;
2028  if (c == 0) {
2029  SWAP(i, right-num_pivots);
2030  num_pivots++;
2031  continue;
2032  }
2033  if (c < 0) {
2034  SWAP(i, store_index);
2035  store_index++;
2036  }
2037  i++;
2038  }
2039  j = store_index;
2040  for (i = right; right-num_pivots < i; i--) {
2041  if (i <= j)
2042  break;
2043  SWAP(j, i);
2044  j++;
2045  }
2046 
2047  if (store_index <= n && n <= store_index+num_pivots)
2048  break;
2049 
2050  if (n < store_index) {
2051  right = store_index-1;
2052  }
2053  else {
2054  left = store_index+num_pivots;
2055  }
2056  }
2057 #undef GETPTR
2058 #undef SWAP
2059 
2060  data->limit = RARRAY_AREF(data->buf, store_index*eltsize); /* the last pivot */
2061  data->curlen = data->n;
2062  rb_ary_resize(data->buf, data->n * eltsize);
2063 }
2064 
2065 static VALUE
2066 nmin_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
2067 {
2068  struct nmin_data *data = (struct nmin_data *)_data;
2069  VALUE cmpv;
2070 
2071  ENUM_WANT_SVALUE();
2072 
2073  if (data->by)
2074  cmpv = enum_yield(argc, i);
2075  else
2076  cmpv = i;
2077 
2078  if (!UNDEF_P(data->limit)) {
2079  int c = data->cmpfunc(&cmpv, &data->limit, data);
2080  if (data->rev)
2081  c = -c;
2082  if (c >= 0)
2083  return Qnil;
2084  }
2085 
2086  if (data->by)
2087  rb_ary_push(data->buf, cmpv);
2088  rb_ary_push(data->buf, i);
2089 
2090  data->curlen++;
2091 
2092  if (data->curlen == data->bufmax) {
2093  nmin_filter(data);
2094  }
2095 
2096  return Qnil;
2097 }
2098 
2099 VALUE
2100 rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary)
2101 {
2102  VALUE result;
2103  struct nmin_data data;
2104 
2105  data.n = NUM2LONG(num);
2106  if (data.n < 0)
2107  rb_raise(rb_eArgError, "negative size (%ld)", data.n);
2108  if (data.n == 0)
2109  return rb_ary_new2(0);
2110  if (LONG_MAX/4/(by ? 2 : 1) < data.n)
2111  rb_raise(rb_eArgError, "too big size");
2112  data.bufmax = data.n * 4;
2113  data.curlen = 0;
2114  data.buf = rb_ary_hidden_new(data.bufmax * (by ? 2 : 1));
2115  data.limit = Qundef;
2116  data.cmpfunc = by ? nmin_cmp :
2117  rb_block_given_p() ? nmin_block_cmp :
2118  nmin_cmp;
2119  data.rev = rev;
2120  data.by = by;
2121  if (ary) {
2122  long i;
2123  for (i = 0; i < RARRAY_LEN(obj); i++) {
2124  VALUE args[1];
2125  args[0] = RARRAY_AREF(obj, i);
2126  nmin_i(obj, (VALUE)&data, 1, args, Qundef);
2127  }
2128  }
2129  else {
2130  rb_block_call(obj, id_each, 0, 0, nmin_i, (VALUE)&data);
2131  }
2132  nmin_filter(&data);
2133  result = data.buf;
2134  if (by) {
2135  long i;
2136  RARRAY_PTR_USE(result, ptr, {
2137  ruby_qsort(ptr,
2138  RARRAY_LEN(result)/2,
2139  sizeof(VALUE)*2,
2140  data.cmpfunc, (void *)&data);
2141  for (i=1; i<RARRAY_LEN(result); i+=2) {
2142  ptr[i/2] = ptr[i];
2143  }
2144  });
2145  rb_ary_resize(result, RARRAY_LEN(result)/2);
2146  }
2147  else {
2148  RARRAY_PTR_USE(result, ptr, {
2149  ruby_qsort(ptr, RARRAY_LEN(result), sizeof(VALUE),
2150  data.cmpfunc, (void *)&data);
2151  });
2152  }
2153  if (rev) {
2154  rb_ary_reverse(result);
2155  }
2156  RBASIC_SET_CLASS(result, rb_cArray);
2157  return result;
2158 
2159 }
2160 
2161 /*
2162  * call-seq:
2163  * one? -> true or false
2164  * one?(pattern) -> true or false
2165  * one? {|element| ... } -> true or false
2166  *
2167  * Returns whether exactly one element meets a given criterion.
2168  *
2169  * With no argument and no block,
2170  * returns whether exactly one element is truthy:
2171  *
2172  * (1..1).one? # => true
2173  * [1, nil, false].one? # => true
2174  * (1..4).one? # => false
2175  * {foo: 0}.one? # => true
2176  * {foo: 0, bar: 1}.one? # => false
2177  * [].one? # => false
2178  *
2179  * With argument +pattern+ and no block,
2180  * returns whether for exactly one element +element+,
2181  * <tt>pattern === element</tt>:
2182  *
2183  * [nil, false, 0].one?(Integer) # => true
2184  * [nil, false, 0].one?(Numeric) # => true
2185  * [nil, false, 0].one?(Float) # => false
2186  * %w[bar baz bat bam].one?(/m/) # => true
2187  * %w[bar baz bat bam].one?(/foo/) # => false
2188  * %w[bar baz bat bam].one?('ba') # => false
2189  * {foo: 0, bar: 1, baz: 2}.one?(Array) # => false
2190  * {foo: 0}.one?(Array) # => true
2191  * [].one?(Integer) # => false
2192  *
2193  * With a block given, returns whether the block returns a truthy value
2194  * for exactly one element:
2195  *
2196  * (1..4).one? {|element| element < 2 } # => true
2197  * (1..4).one? {|element| element < 1 } # => false
2198  * {foo: 0, bar: 1, baz: 2}.one? {|key, value| value < 1 } # => true
2199  * {foo: 0, bar: 1, baz: 2}.one? {|key, value| value < 2 } # => false
2200  *
2201  * Related: #none?, #all?, #any?.
2202  *
2203  */
2204 static VALUE
2205 enum_one(int argc, VALUE *argv, VALUE obj)
2206 {
2207  struct MEMO *memo = MEMO_ENUM_NEW(Qundef);
2208  VALUE result;
2209 
2210  WARN_UNUSED_BLOCK(argc);
2211  ENUM_BLOCK_CALL(one);
2212  result = memo->v1;
2213  if (UNDEF_P(result)) return Qfalse;
2214  return result;
2215 }
2216 
2217 DEFINE_ENUMFUNCS(none)
2218 {
2219  if (RTEST(result)) {
2220  MEMO_V1_SET(memo, Qfalse);
2221  rb_iter_break();
2222  }
2223  return Qnil;
2224 }
2225 
2226 /*
2227  * call-seq:
2228  * none? -> true or false
2229  * none?(pattern) -> true or false
2230  * none? {|element| ... } -> true or false
2231  *
2232  * Returns whether no element meets a given criterion.
2233  *
2234  * With no argument and no block,
2235  * returns whether no element is truthy:
2236  *
2237  * (1..4).none? # => false
2238  * [nil, false].none? # => true
2239  * {foo: 0}.none? # => false
2240  * {foo: 0, bar: 1}.none? # => false
2241  * [].none? # => true
2242  *
2243  * With argument +pattern+ and no block,
2244  * returns whether for no element +element+,
2245  * <tt>pattern === element</tt>:
2246  *
2247  * [nil, false, 1.1].none?(Integer) # => true
2248  * %w[bar baz bat bam].none?(/m/) # => false
2249  * %w[bar baz bat bam].none?(/foo/) # => true
2250  * %w[bar baz bat bam].none?('ba') # => true
2251  * {foo: 0, bar: 1, baz: 2}.none?(Hash) # => true
2252  * {foo: 0}.none?(Array) # => false
2253  * [].none?(Integer) # => true
2254  *
2255  * With a block given, returns whether the block returns a truthy value
2256  * for no element:
2257  *
2258  * (1..4).none? {|element| element < 1 } # => true
2259  * (1..4).none? {|element| element < 2 } # => false
2260  * {foo: 0, bar: 1, baz: 2}.none? {|key, value| value < 0 } # => true
2261  * {foo: 0, bar: 1, baz: 2}.none? {|key, value| value < 1 } # => false
2262  *
2263  * Related: #one?, #all?, #any?.
2264  *
2265  */
2266 static VALUE
2267 enum_none(int argc, VALUE *argv, VALUE obj)
2268 {
2269  struct MEMO *memo = MEMO_ENUM_NEW(Qtrue);
2270 
2271  WARN_UNUSED_BLOCK(argc);
2272  ENUM_BLOCK_CALL(none);
2273  return memo->v1;
2274 }
2275 
2276 struct min_t {
2277  VALUE min;
2278 };
2279 
2280 static VALUE
2281 min_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2282 {
2283  struct min_t *memo = MEMO_FOR(struct min_t, args);
2284 
2285  ENUM_WANT_SVALUE();
2286 
2287  if (UNDEF_P(memo->min)) {
2288  memo->min = i;
2289  }
2290  else {
2291  if (OPTIMIZED_CMP(i, memo->min) < 0) {
2292  memo->min = i;
2293  }
2294  }
2295  return Qnil;
2296 }
2297 
2298 static VALUE
2299 min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2300 {
2301  VALUE cmp;
2302  struct min_t *memo = MEMO_FOR(struct min_t, args);
2303 
2304  ENUM_WANT_SVALUE();
2305 
2306  if (UNDEF_P(memo->min)) {
2307  memo->min = i;
2308  }
2309  else {
2310  cmp = rb_yield_values(2, i, memo->min);
2311  if (rb_cmpint(cmp, i, memo->min) < 0) {
2312  memo->min = i;
2313  }
2314  }
2315  return Qnil;
2316 }
2317 
2318 
2319 /*
2320  * call-seq:
2321  * min -> element
2322  * min(n) -> array
2323  * min {|a, b| ... } -> element
2324  * min(n) {|a, b| ... } -> array
2325  *
2326  * Returns the element with the minimum element according to a given criterion.
2327  * The ordering of equal elements is indeterminate and may be unstable.
2328  *
2329  * With no argument and no block, returns the minimum element,
2330  * using the elements' own method <tt>#<=></tt> for comparison:
2331  *
2332  * (1..4).min # => 1
2333  * (-4..-1).min # => -4
2334  * %w[d c b a].min # => "a"
2335  * {foo: 0, bar: 1, baz: 2}.min # => [:bar, 1]
2336  * [].min # => nil
2337  *
2338  * With positive integer argument +n+ given, and no block,
2339  * returns an array containing the first +n+ minimum elements that exist:
2340  *
2341  * (1..4).min(2) # => [1, 2]
2342  * (-4..-1).min(2) # => [-4, -3]
2343  * %w[d c b a].min(2) # => ["a", "b"]
2344  * {foo: 0, bar: 1, baz: 2}.min(2) # => [[:bar, 1], [:baz, 2]]
2345  * [].min(2) # => []
2346  *
2347  * With a block given, the block determines the minimum elements.
2348  * The block is called with two elements +a+ and +b+, and must return:
2349  *
2350  * - A negative integer if <tt>a < b</tt>.
2351  * - Zero if <tt>a == b</tt>.
2352  * - A positive integer if <tt>a > b</tt>.
2353  *
2354  * With a block given and no argument,
2355  * returns the minimum element as determined by the block:
2356  *
2357  * %w[xxx x xxxx xx].min {|a, b| a.size <=> b.size } # => "x"
2358  * h = {foo: 0, bar: 1, baz: 2}
2359  * h.min {|pair1, pair2| pair1[1] <=> pair2[1] } # => [:foo, 0]
2360  * [].min {|a, b| a <=> b } # => nil
2361  *
2362  * With a block given and positive integer argument +n+ given,
2363  * returns an array containing the first +n+ minimum elements that exist,
2364  * as determined by the block.
2365  *
2366  * %w[xxx x xxxx xx].min(2) {|a, b| a.size <=> b.size } # => ["x", "xx"]
2367  * h = {foo: 0, bar: 1, baz: 2}
2368  * h.min(2) {|pair1, pair2| pair1[1] <=> pair2[1] }
2369  * # => [[:foo, 0], [:bar, 1]]
2370  * [].min(2) {|a, b| a <=> b } # => []
2371  *
2372  * Related: #min_by, #minmax, #max.
2373  *
2374  */
2375 
2376 static VALUE
2377 enum_min(int argc, VALUE *argv, VALUE obj)
2378 {
2379  VALUE memo;
2380  struct min_t *m = NEW_MEMO_FOR(struct min_t, memo);
2381  VALUE result;
2382  VALUE num;
2383 
2384  if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
2385  return rb_nmin_run(obj, num, 0, 0, 0);
2386 
2387  m->min = Qundef;
2388  if (rb_block_given_p()) {
2389  rb_block_call(obj, id_each, 0, 0, min_ii, memo);
2390  }
2391  else {
2392  rb_block_call(obj, id_each, 0, 0, min_i, memo);
2393  }
2394  result = m->min;
2395  if (UNDEF_P(result)) return Qnil;
2396  return result;
2397 }
2398 
2399 struct max_t {
2400  VALUE max;
2401 };
2402 
2403 static VALUE
2404 max_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2405 {
2406  struct max_t *memo = MEMO_FOR(struct max_t, args);
2407 
2408  ENUM_WANT_SVALUE();
2409 
2410  if (UNDEF_P(memo->max)) {
2411  memo->max = i;
2412  }
2413  else {
2414  if (OPTIMIZED_CMP(i, memo->max) > 0) {
2415  memo->max = i;
2416  }
2417  }
2418  return Qnil;
2419 }
2420 
2421 static VALUE
2422 max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2423 {
2424  struct max_t *memo = MEMO_FOR(struct max_t, args);
2425  VALUE cmp;
2426 
2427  ENUM_WANT_SVALUE();
2428 
2429  if (UNDEF_P(memo->max)) {
2430  memo->max = i;
2431  }
2432  else {
2433  cmp = rb_yield_values(2, i, memo->max);
2434  if (rb_cmpint(cmp, i, memo->max) > 0) {
2435  memo->max = i;
2436  }
2437  }
2438  return Qnil;
2439 }
2440 
2441 /*
2442  * call-seq:
2443  * max -> element
2444  * max(n) -> array
2445  * max {|a, b| ... } -> element
2446  * max(n) {|a, b| ... } -> array
2447  *
2448  * Returns the element with the maximum element according to a given criterion.
2449  * The ordering of equal elements is indeterminate and may be unstable.
2450  *
2451  * With no argument and no block, returns the maximum element,
2452  * using the elements' own method <tt>#<=></tt> for comparison:
2453  *
2454  * (1..4).max # => 4
2455  * (-4..-1).max # => -1
2456  * %w[d c b a].max # => "d"
2457  * {foo: 0, bar: 1, baz: 2}.max # => [:foo, 0]
2458  * [].max # => nil
2459  *
2460  * With positive integer argument +n+ given, and no block,
2461  * returns an array containing the first +n+ maximum elements that exist:
2462  *
2463  * (1..4).max(2) # => [4, 3]
2464  * (-4..-1).max(2) # => [-1, -2]
2465  * %w[d c b a].max(2) # => ["d", "c"]
2466  * {foo: 0, bar: 1, baz: 2}.max(2) # => [[:foo, 0], [:baz, 2]]
2467  * [].max(2) # => []
2468  *
2469  * With a block given, the block determines the maximum elements.
2470  * The block is called with two elements +a+ and +b+, and must return:
2471  *
2472  * - A negative integer if <tt>a < b</tt>.
2473  * - Zero if <tt>a == b</tt>.
2474  * - A positive integer if <tt>a > b</tt>.
2475  *
2476  * With a block given and no argument,
2477  * returns the maximum element as determined by the block:
2478  *
2479  * %w[xxx x xxxx xx].max {|a, b| a.size <=> b.size } # => "xxxx"
2480  * h = {foo: 0, bar: 1, baz: 2}
2481  * h.max {|pair1, pair2| pair1[1] <=> pair2[1] } # => [:baz, 2]
2482  * [].max {|a, b| a <=> b } # => nil
2483  *
2484  * With a block given and positive integer argument +n+ given,
2485  * returns an array containing the first +n+ maximum elements that exist,
2486  * as determined by the block.
2487  *
2488  * %w[xxx x xxxx xx].max(2) {|a, b| a.size <=> b.size } # => ["xxxx", "xxx"]
2489  * h = {foo: 0, bar: 1, baz: 2}
2490  * h.max(2) {|pair1, pair2| pair1[1] <=> pair2[1] }
2491  * # => [[:baz, 2], [:bar, 1]]
2492  * [].max(2) {|a, b| a <=> b } # => []
2493  *
2494  * Related: #min, #minmax, #max_by.
2495  *
2496  */
2497 
2498 static VALUE
2499 enum_max(int argc, VALUE *argv, VALUE obj)
2500 {
2501  VALUE memo;
2502  struct max_t *m = NEW_MEMO_FOR(struct max_t, memo);
2503  VALUE result;
2504  VALUE num;
2505 
2506  if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
2507  return rb_nmin_run(obj, num, 0, 1, 0);
2508 
2509  m->max = Qundef;
2510  if (rb_block_given_p()) {
2511  rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)memo);
2512  }
2513  else {
2514  rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)memo);
2515  }
2516  result = m->max;
2517  if (UNDEF_P(result)) return Qnil;
2518  return result;
2519 }
2520 
2521 struct minmax_t {
2522  VALUE min;
2523  VALUE max;
2524  VALUE last;
2525 };
2526 
2527 static void
2528 minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo)
2529 {
2530  int n;
2531 
2532  if (UNDEF_P(memo->min)) {
2533  memo->min = i;
2534  memo->max = j;
2535  }
2536  else {
2537  n = OPTIMIZED_CMP(i, memo->min);
2538  if (n < 0) {
2539  memo->min = i;
2540  }
2541  n = OPTIMIZED_CMP(j, memo->max);
2542  if (n > 0) {
2543  memo->max = j;
2544  }
2545  }
2546 }
2547 
2548 static VALUE
2549 minmax_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
2550 {
2551  struct minmax_t *memo = MEMO_FOR(struct minmax_t, _memo);
2552  int n;
2553  VALUE j;
2554 
2555  ENUM_WANT_SVALUE();
2556 
2557  if (UNDEF_P(memo->last)) {
2558  memo->last = i;
2559  return Qnil;
2560  }
2561  j = memo->last;
2562  memo->last = Qundef;
2563 
2564  n = OPTIMIZED_CMP(j, i);
2565  if (n == 0)
2566  i = j;
2567  else if (n < 0) {
2568  VALUE tmp;
2569  tmp = i;
2570  i = j;
2571  j = tmp;
2572  }
2573 
2574  minmax_i_update(i, j, memo);
2575 
2576  return Qnil;
2577 }
2578 
2579 static void
2580 minmax_ii_update(VALUE i, VALUE j, struct minmax_t *memo)
2581 {
2582  int n;
2583 
2584  if (UNDEF_P(memo->min)) {
2585  memo->min = i;
2586  memo->max = j;
2587  }
2588  else {
2589  n = rb_cmpint(rb_yield_values(2, i, memo->min), i, memo->min);
2590  if (n < 0) {
2591  memo->min = i;
2592  }
2593  n = rb_cmpint(rb_yield_values(2, j, memo->max), j, memo->max);
2594  if (n > 0) {
2595  memo->max = j;
2596  }
2597  }
2598 }
2599 
2600 static VALUE
2601 minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
2602 {
2603  struct minmax_t *memo = MEMO_FOR(struct minmax_t, _memo);
2604  int n;
2605  VALUE j;
2606 
2607  ENUM_WANT_SVALUE();
2608 
2609  if (UNDEF_P(memo->last)) {
2610  memo->last = i;
2611  return Qnil;
2612  }
2613  j = memo->last;
2614  memo->last = Qundef;
2615 
2616  n = rb_cmpint(rb_yield_values(2, j, i), j, i);
2617  if (n == 0)
2618  i = j;
2619  else if (n < 0) {
2620  VALUE tmp;
2621  tmp = i;
2622  i = j;
2623  j = tmp;
2624  }
2625 
2626  minmax_ii_update(i, j, memo);
2627 
2628  return Qnil;
2629 }
2630 
2631 /*
2632  * call-seq:
2633  * minmax -> [minimum, maximum]
2634  * minmax {|a, b| ... } -> [minimum, maximum]
2635  *
2636  * Returns a 2-element array containing the minimum and maximum elements
2637  * according to a given criterion.
2638  * The ordering of equal elements is indeterminate and may be unstable.
2639  *
2640  * With no argument and no block, returns the minimum and maximum elements,
2641  * using the elements' own method <tt>#<=></tt> for comparison:
2642  *
2643  * (1..4).minmax # => [1, 4]
2644  * (-4..-1).minmax # => [-4, -1]
2645  * %w[d c b a].minmax # => ["a", "d"]
2646  * {foo: 0, bar: 1, baz: 2}.minmax # => [[:bar, 1], [:foo, 0]]
2647  * [].minmax # => [nil, nil]
2648  *
2649  * With a block given, returns the minimum and maximum elements
2650  * as determined by the block:
2651  *
2652  * %w[xxx x xxxx xx].minmax {|a, b| a.size <=> b.size } # => ["x", "xxxx"]
2653  * h = {foo: 0, bar: 1, baz: 2}
2654  * h.minmax {|pair1, pair2| pair1[1] <=> pair2[1] }
2655  * # => [[:foo, 0], [:baz, 2]]
2656  * [].minmax {|a, b| a <=> b } # => [nil, nil]
2657  *
2658  * Related: #min, #max, #minmax_by.
2659  *
2660  */
2661 
2662 static VALUE
2663 enum_minmax(VALUE obj)
2664 {
2665  VALUE memo;
2666  struct minmax_t *m = NEW_MEMO_FOR(struct minmax_t, memo);
2667 
2668  m->min = Qundef;
2669  m->last = Qundef;
2670  if (rb_block_given_p()) {
2671  rb_block_call(obj, id_each, 0, 0, minmax_ii, memo);
2672  if (!UNDEF_P(m->last))
2673  minmax_ii_update(m->last, m->last, m);
2674  }
2675  else {
2676  rb_block_call(obj, id_each, 0, 0, minmax_i, memo);
2677  if (!UNDEF_P(m->last))
2678  minmax_i_update(m->last, m->last, m);
2679  }
2680  if (!UNDEF_P(m->min)) {
2681  return rb_assoc_new(m->min, m->max);
2682  }
2683  return rb_assoc_new(Qnil, Qnil);
2684 }
2685 
2686 static VALUE
2687 min_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2688 {
2689  struct MEMO *memo = MEMO_CAST(args);
2690  VALUE v;
2691 
2692  ENUM_WANT_SVALUE();
2693 
2694  v = enum_yield(argc, i);
2695  if (UNDEF_P(memo->v1)) {
2696  MEMO_V1_SET(memo, v);
2697  MEMO_V2_SET(memo, i);
2698  }
2699  else if (OPTIMIZED_CMP(v, memo->v1) < 0) {
2700  MEMO_V1_SET(memo, v);
2701  MEMO_V2_SET(memo, i);
2702  }
2703  return Qnil;
2704 }
2705 
2706 /*
2707  * call-seq:
2708  * min_by {|element| ... } -> element
2709  * min_by(n) {|element| ... } -> array
2710  * min_by -> enumerator
2711  * min_by(n) -> enumerator
2712  *
2713  * Returns the elements for which the block returns the minimum values.
2714  *
2715  * With a block given and no argument,
2716  * returns the element for which the block returns the minimum value:
2717  *
2718  * (1..4).min_by {|element| -element } # => 4
2719  * %w[a b c d].min_by {|element| -element.ord } # => "d"
2720  * {foo: 0, bar: 1, baz: 2}.min_by {|key, value| -value } # => [:baz, 2]
2721  * [].min_by {|element| -element } # => nil
2722  *
2723  * With a block given and positive integer argument +n+ given,
2724  * returns an array containing the +n+ elements
2725  * for which the block returns minimum values:
2726  *
2727  * (1..4).min_by(2) {|element| -element }
2728  * # => [4, 3]
2729  * %w[a b c d].min_by(2) {|element| -element.ord }
2730  * # => ["d", "c"]
2731  * {foo: 0, bar: 1, baz: 2}.min_by(2) {|key, value| -value }
2732  * # => [[:baz, 2], [:bar, 1]]
2733  * [].min_by(2) {|element| -element }
2734  * # => []
2735  *
2736  * Returns an Enumerator if no block is given.
2737  *
2738  * Related: #min, #minmax, #max_by.
2739  *
2740  */
2741 
2742 static VALUE
2743 enum_min_by(int argc, VALUE *argv, VALUE obj)
2744 {
2745  struct MEMO *memo;
2746  VALUE num;
2747 
2748  rb_check_arity(argc, 0, 1);
2749 
2750  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
2751 
2752  if (argc && !NIL_P(num = argv[0]))
2753  return rb_nmin_run(obj, num, 1, 0, 0);
2754 
2755  memo = MEMO_NEW(Qundef, Qnil, 0);
2756  rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
2757  return memo->v2;
2758 }
2759 
2760 static VALUE
2761 max_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2762 {
2763  struct MEMO *memo = MEMO_CAST(args);
2764  VALUE v;
2765 
2766  ENUM_WANT_SVALUE();
2767 
2768  v = enum_yield(argc, i);
2769  if (UNDEF_P(memo->v1)) {
2770  MEMO_V1_SET(memo, v);
2771  MEMO_V2_SET(memo, i);
2772  }
2773  else if (OPTIMIZED_CMP(v, memo->v1) > 0) {
2774  MEMO_V1_SET(memo, v);
2775  MEMO_V2_SET(memo, i);
2776  }
2777  return Qnil;
2778 }
2779 
2780 /*
2781  * call-seq:
2782  * max_by {|element| ... } -> element
2783  * max_by(n) {|element| ... } -> array
2784  * max_by -> enumerator
2785  * max_by(n) -> enumerator
2786  *
2787  * Returns the elements for which the block returns the maximum values.
2788  *
2789  * With a block given and no argument,
2790  * returns the element for which the block returns the maximum value:
2791  *
2792  * (1..4).max_by {|element| -element } # => 1
2793  * %w[a b c d].max_by {|element| -element.ord } # => "a"
2794  * {foo: 0, bar: 1, baz: 2}.max_by {|key, value| -value } # => [:foo, 0]
2795  * [].max_by {|element| -element } # => nil
2796  *
2797  * With a block given and positive integer argument +n+ given,
2798  * returns an array containing the +n+ elements
2799  * for which the block returns maximum values:
2800  *
2801  * (1..4).max_by(2) {|element| -element }
2802  * # => [1, 2]
2803  * %w[a b c d].max_by(2) {|element| -element.ord }
2804  * # => ["a", "b"]
2805  * {foo: 0, bar: 1, baz: 2}.max_by(2) {|key, value| -value }
2806  * # => [[:foo, 0], [:bar, 1]]
2807  * [].max_by(2) {|element| -element }
2808  * # => []
2809  *
2810  * Returns an Enumerator if no block is given.
2811  *
2812  * Related: #max, #minmax, #min_by.
2813  *
2814  */
2815 
2816 static VALUE
2817 enum_max_by(int argc, VALUE *argv, VALUE obj)
2818 {
2819  struct MEMO *memo;
2820  VALUE num;
2821 
2822  rb_check_arity(argc, 0, 1);
2823 
2824  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
2825 
2826  if (argc && !NIL_P(num = argv[0]))
2827  return rb_nmin_run(obj, num, 1, 1, 0);
2828 
2829  memo = MEMO_NEW(Qundef, Qnil, 0);
2830  rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
2831  return memo->v2;
2832 }
2833 
2834 struct minmax_by_t {
2835  VALUE min_bv;
2836  VALUE max_bv;
2837  VALUE min;
2838  VALUE max;
2839  VALUE last_bv;
2840  VALUE last;
2841 };
2842 
2843 static void
2844 minmax_by_i_update(VALUE v1, VALUE v2, VALUE i1, VALUE i2, struct minmax_by_t *memo)
2845 {
2846  if (UNDEF_P(memo->min_bv)) {
2847  memo->min_bv = v1;
2848  memo->max_bv = v2;
2849  memo->min = i1;
2850  memo->max = i2;
2851  }
2852  else {
2853  if (OPTIMIZED_CMP(v1, memo->min_bv) < 0) {
2854  memo->min_bv = v1;
2855  memo->min = i1;
2856  }
2857  if (OPTIMIZED_CMP(v2, memo->max_bv) > 0) {
2858  memo->max_bv = v2;
2859  memo->max = i2;
2860  }
2861  }
2862 }
2863 
2864 static VALUE
2865 minmax_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
2866 {
2867  struct minmax_by_t *memo = MEMO_FOR(struct minmax_by_t, _memo);
2868  VALUE vi, vj, j;
2869  int n;
2870 
2871  ENUM_WANT_SVALUE();
2872 
2873  vi = enum_yield(argc, i);
2874 
2875  if (UNDEF_P(memo->last_bv)) {
2876  memo->last_bv = vi;
2877  memo->last = i;
2878  return Qnil;
2879  }
2880  vj = memo->last_bv;
2881  j = memo->last;
2882  memo->last_bv = Qundef;
2883 
2884  n = OPTIMIZED_CMP(vj, vi);
2885  if (n == 0) {
2886  i = j;
2887  vi = vj;
2888  }
2889  else if (n < 0) {
2890  VALUE tmp;
2891  tmp = i;
2892  i = j;
2893  j = tmp;
2894  tmp = vi;
2895  vi = vj;
2896  vj = tmp;
2897  }
2898 
2899  minmax_by_i_update(vi, vj, i, j, memo);
2900 
2901  return Qnil;
2902 }
2903 
2904 /*
2905  * call-seq:
2906  * minmax_by {|element| ... } -> [minimum, maximum]
2907  * minmax_by -> enumerator
2908  *
2909  * Returns a 2-element array containing the elements
2910  * for which the block returns minimum and maximum values:
2911  *
2912  * (1..4).minmax_by {|element| -element }
2913  * # => [4, 1]
2914  * %w[a b c d].minmax_by {|element| -element.ord }
2915  * # => ["d", "a"]
2916  * {foo: 0, bar: 1, baz: 2}.minmax_by {|key, value| -value }
2917  * # => [[:baz, 2], [:foo, 0]]
2918  * [].minmax_by {|element| -element }
2919  * # => [nil, nil]
2920  *
2921  * Returns an Enumerator if no block is given.
2922  *
2923  * Related: #max_by, #minmax, #min_by.
2924  *
2925  */
2926 
2927 static VALUE
2928 enum_minmax_by(VALUE obj)
2929 {
2930  VALUE memo;
2931  struct minmax_by_t *m = NEW_MEMO_FOR(struct minmax_by_t, memo);
2932 
2933  RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
2934 
2935  m->min_bv = Qundef;
2936  m->max_bv = Qundef;
2937  m->min = Qnil;
2938  m->max = Qnil;
2939  m->last_bv = Qundef;
2940  m->last = Qundef;
2941  rb_block_call(obj, id_each, 0, 0, minmax_by_i, memo);
2942  if (!UNDEF_P(m->last_bv))
2943  minmax_by_i_update(m->last_bv, m->last_bv, m->last, m->last, m);
2944  m = MEMO_FOR(struct minmax_by_t, memo);
2945  return rb_assoc_new(m->min, m->max);
2946 }
2947 
2948 static VALUE
2949 member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args))
2950 {
2951  struct MEMO *memo = MEMO_CAST(args);
2952 
2953  if (rb_equal(rb_enum_values_pack(argc, argv), memo->v1)) {
2954  MEMO_V2_SET(memo, Qtrue);
2955  rb_iter_break();
2956  }
2957  return Qnil;
2958 }
2959 
2960 /*
2961  * call-seq:
2962  * include?(object) -> true or false
2963  *
2964  * Returns whether for any element <tt>object == element</tt>:
2965  *
2966  * (1..4).include?(2) # => true
2967  * (1..4).include?(5) # => false
2968  * (1..4).include?('2') # => false
2969  * %w[a b c d].include?('b') # => true
2970  * %w[a b c d].include?('2') # => false
2971  * {foo: 0, bar: 1, baz: 2}.include?(:foo) # => true
2972  * {foo: 0, bar: 1, baz: 2}.include?('foo') # => false
2973  * {foo: 0, bar: 1, baz: 2}.include?(0) # => false
2974  *
2975  */
2976 
2977 static VALUE
2978 enum_member(VALUE obj, VALUE val)
2979 {
2980  struct MEMO *memo = MEMO_NEW(val, Qfalse, 0);
2981 
2982  rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
2983  return memo->v2;
2984 }
2985 
2986 static VALUE
2987 each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(_, index))
2988 {
2989  struct vm_ifunc *ifunc = rb_current_ifunc();
2990  ifunc->data = (const void *)rb_int_succ(index);
2991 
2992  return rb_yield_values(2, rb_enum_values_pack(argc, argv), index);
2993 }
2994 
2995 /*
2996  * call-seq:
2997  * each_with_index(*args) {|element, i| ..... } -> self
2998  * each_with_index(*args) -> enumerator
2999  *
3000  * Invoke <tt>self.each</tt> with <tt>*args</tt>.
3001  * With a block given, the block receives each element and its index;
3002  * returns +self+:
3003  *
3004  * h = {}
3005  * (1..4).each_with_index {|element, i| h[element] = i } # => 1..4
3006  * h # => {1=>0, 2=>1, 3=>2, 4=>3}
3007  *
3008  * h = {}
3009  * %w[a b c d].each_with_index {|element, i| h[element] = i }
3010  * # => ["a", "b", "c", "d"]
3011  * h # => {"a"=>0, "b"=>1, "c"=>2, "d"=>3}
3012  *
3013  * a = []
3014  * h = {foo: 0, bar: 1, baz: 2}
3015  * h.each_with_index {|element, i| a.push([i, element]) }
3016  * # => {:foo=>0, :bar=>1, :baz=>2}
3017  * a # => [[0, [:foo, 0]], [1, [:bar, 1]], [2, [:baz, 2]]]
3018  *
3019  * With no block given, returns an Enumerator.
3020  *
3021  */
3022 
3023 static VALUE
3024 enum_each_with_index(int argc, VALUE *argv, VALUE obj)
3025 {
3026  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
3027 
3028  rb_block_call(obj, id_each, argc, argv, each_with_index_i, INT2FIX(0));
3029  return obj;
3030 }
3031 
3032 
3033 /*
3034  * call-seq:
3035  * reverse_each(*args) {|element| ... } -> self
3036  * reverse_each(*args) -> enumerator
3037  *
3038  * With a block given, calls the block with each element,
3039  * but in reverse order; returns +self+:
3040  *
3041  * a = []
3042  * (1..4).reverse_each {|element| a.push(-element) } # => 1..4
3043  * a # => [-4, -3, -2, -1]
3044  *
3045  * a = []
3046  * %w[a b c d].reverse_each {|element| a.push(element) }
3047  * # => ["a", "b", "c", "d"]
3048  * a # => ["d", "c", "b", "a"]
3049  *
3050  * a = []
3051  * h.reverse_each {|element| a.push(element) }
3052  * # => {:foo=>0, :bar=>1, :baz=>2}
3053  * a # => [[:baz, 2], [:bar, 1], [:foo, 0]]
3054  *
3055  * With no block given, returns an Enumerator.
3056  *
3057  */
3058 
3059 static VALUE
3060 enum_reverse_each(int argc, VALUE *argv, VALUE obj)
3061 {
3062  VALUE ary;
3063  long len;
3064 
3065  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
3066 
3067  ary = enum_to_a(argc, argv, obj);
3068 
3069  len = RARRAY_LEN(ary);
3070  while (len--) {
3071  long nlen;
3072  rb_yield(RARRAY_AREF(ary, len));
3073  nlen = RARRAY_LEN(ary);
3074  if (nlen < len) {
3075  len = nlen;
3076  }
3077  }
3078 
3079  return obj;
3080 }
3081 
3082 
3083 static VALUE
3084 each_val_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
3085 {
3086  ENUM_WANT_SVALUE();
3087  enum_yield(argc, i);
3088  return Qnil;
3089 }
3090 
3091 /*
3092  * call-seq:
3093  * each_entry(*args) {|element| ... } -> self
3094  * each_entry(*args) -> enumerator
3095  *
3096  * Calls the given block with each element,
3097  * converting multiple values from yield to an array; returns +self+:
3098  *
3099  * a = []
3100  * (1..4).each_entry {|element| a.push(element) } # => 1..4
3101  * a # => [1, 2, 3, 4]
3102  *
3103  * a = []
3104  * h = {foo: 0, bar: 1, baz:2}
3105  * h.each_entry {|element| a.push(element) }
3106  * # => {:foo=>0, :bar=>1, :baz=>2}
3107  * a # => [[:foo, 0], [:bar, 1], [:baz, 2]]
3108  *
3109  * class Foo
3110  * include Enumerable
3111  * def each
3112  * yield 1
3113  * yield 1, 2
3114  * yield
3115  * end
3116  * end
3117  * Foo.new.each_entry {|yielded| p yielded }
3118  *
3119  * Output:
3120  *
3121  * 1
3122  * [1, 2]
3123  * nil
3124  *
3125  * With no block given, returns an Enumerator.
3126  *
3127  */
3128 
3129 static VALUE
3130 enum_each_entry(int argc, VALUE *argv, VALUE obj)
3131 {
3132  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
3133  rb_block_call(obj, id_each, argc, argv, each_val_i, 0);
3134  return obj;
3135 }
3136 
3137 static VALUE
3138 add_int(VALUE x, long n)
3139 {
3140  const VALUE y = LONG2NUM(n);
3141  if (RB_INTEGER_TYPE_P(x)) return rb_int_plus(x, y);
3142  return rb_funcallv(x, '+', 1, &y);
3143 }
3144 
3145 static VALUE
3146 div_int(VALUE x, long n)
3147 {
3148  const VALUE y = LONG2NUM(n);
3149  if (RB_INTEGER_TYPE_P(x)) return rb_int_idiv(x, y);
3150  return rb_funcallv(x, id_div, 1, &y);
3151 }
3152 
3153 #define dont_recycle_block_arg(arity) ((arity) == 1 || (arity) < 0)
3154 
3155 static VALUE
3156 each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, m))
3157 {
3158  struct MEMO *memo = MEMO_CAST(m);
3159  VALUE ary = memo->v1;
3160  VALUE v = Qnil;
3161  long size = memo->u3.cnt;
3162  ENUM_WANT_SVALUE();
3163 
3164  rb_ary_push(ary, i);
3165 
3166  if (RARRAY_LEN(ary) == size) {
3167  v = rb_yield(ary);
3168 
3169  if (memo->v2) {
3170  MEMO_V1_SET(memo, rb_ary_new2(size));
3171  }
3172  else {
3173  rb_ary_clear(ary);
3174  }
3175  }
3176 
3177  return v;
3178 }
3179 
3180 static VALUE
3181 enum_each_slice_size(VALUE obj, VALUE args, VALUE eobj)
3182 {
3183  VALUE n, size;
3184  long slice_size = NUM2LONG(RARRAY_AREF(args, 0));
3185  ID infinite_p;
3186  CONST_ID(infinite_p, "infinite?");
3187  if (slice_size <= 0) rb_raise(rb_eArgError, "invalid slice size");
3188 
3189  size = enum_size(obj, 0, 0);
3190  if (NIL_P(size)) return Qnil;
3191  if (RB_FLOAT_TYPE_P(size) && RTEST(rb_funcall(size, infinite_p, 0))) {
3192  return size;
3193  }
3194 
3195  n = add_int(size, slice_size-1);
3196  return div_int(n, slice_size);
3197 }
3198 
3199 /*
3200  * call-seq:
3201  * each_slice(n) { ... } -> self
3202  * each_slice(n) -> enumerator
3203  *
3204  * Calls the block with each successive disjoint +n+-tuple of elements;
3205  * returns +self+:
3206  *
3207  * a = []
3208  * (1..10).each_slice(3) {|tuple| a.push(tuple) }
3209  * a # => [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
3210  *
3211  * a = []
3212  * h = {foo: 0, bar: 1, baz: 2, bat: 3, bam: 4}
3213  * h.each_slice(2) {|tuple| a.push(tuple) }
3214  * a # => [[[:foo, 0], [:bar, 1]], [[:baz, 2], [:bat, 3]], [[:bam, 4]]]
3215  *
3216  * With no block given, returns an Enumerator.
3217  *
3218  */
3219 static VALUE
3220 enum_each_slice(VALUE obj, VALUE n)
3221 {
3222  long size = NUM2LONG(n);
3223  VALUE ary;
3224  struct MEMO *memo;
3225  int arity;
3226 
3227  if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
3228  RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_slice_size);
3229  size = limit_by_enum_size(obj, size);
3230  ary = rb_ary_new2(size);
3231  arity = rb_block_arity();
3232  memo = MEMO_NEW(ary, dont_recycle_block_arg(arity), size);
3233  rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
3234  ary = memo->v1;
3235  if (RARRAY_LEN(ary) > 0) rb_yield(ary);
3236 
3237  return obj;
3238 }
3239 
3240 static VALUE
3241 each_cons_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
3242 {
3243  struct MEMO *memo = MEMO_CAST(args);
3244  VALUE ary = memo->v1;
3245  VALUE v = Qnil;
3246  long size = memo->u3.cnt;
3247  ENUM_WANT_SVALUE();
3248 
3249  if (RARRAY_LEN(ary) == size) {
3250  rb_ary_shift(ary);
3251  }
3252  rb_ary_push(ary, i);
3253  if (RARRAY_LEN(ary) == size) {
3254  if (memo->v2) {
3255  ary = rb_ary_dup(ary);
3256  }
3257  v = rb_yield(ary);
3258  }
3259  return v;
3260 }
3261 
3262 static VALUE
3263 enum_each_cons_size(VALUE obj, VALUE args, VALUE eobj)
3264 {
3265  const VALUE zero = LONG2FIX(0);
3266  VALUE n, size;
3267  long cons_size = NUM2LONG(RARRAY_AREF(args, 0));
3268  if (cons_size <= 0) rb_raise(rb_eArgError, "invalid size");
3269 
3270  size = enum_size(obj, 0, 0);
3271  if (NIL_P(size)) return Qnil;
3272 
3273  n = add_int(size, 1 - cons_size);
3274  return (OPTIMIZED_CMP(n, zero) == -1) ? zero : n;
3275 }
3276 
3277 /*
3278  * call-seq:
3279  * each_cons(n) { ... } -> self
3280  * each_cons(n) -> enumerator
3281  *
3282  * Calls the block with each successive overlapped +n+-tuple of elements;
3283  * returns +self+:
3284  *
3285  * a = []
3286  * (1..5).each_cons(3) {|element| a.push(element) }
3287  * a # => [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
3288  *
3289  * a = []
3290  * h = {foo: 0, bar: 1, baz: 2, bam: 3}
3291  * h.each_cons(2) {|element| a.push(element) }
3292  * a # => [[[:foo, 0], [:bar, 1]], [[:bar, 1], [:baz, 2]], [[:baz, 2], [:bam, 3]]]
3293  *
3294  * With no block given, returns an Enumerator.
3295  *
3296  */
3297 static VALUE
3298 enum_each_cons(VALUE obj, VALUE n)
3299 {
3300  long size = NUM2LONG(n);
3301  struct MEMO *memo;
3302  int arity;
3303 
3304  if (size <= 0) rb_raise(rb_eArgError, "invalid size");
3305  RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size);
3306  arity = rb_block_arity();
3307  if (enum_size_over_p(obj, size)) return obj;
3308  memo = MEMO_NEW(rb_ary_new2(size), dont_recycle_block_arg(arity), size);
3309  rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo);
3310 
3311  return obj;
3312 }
3313 
3314 static VALUE
3315 each_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
3316 {
3317  ENUM_WANT_SVALUE();
3318  return rb_yield_values(2, i, memo);
3319 }
3320 
3321 /*
3322  * call-seq:
3323  * each_with_object(object) { |(*args), memo_object| ... } -> object
3324  * each_with_object(object) -> enumerator
3325  *
3326  * Calls the block once for each element, passing both the element
3327  * and the given object:
3328  *
3329  * (1..4).each_with_object([]) {|i, a| a.push(i**2) }
3330  * # => [1, 4, 9, 16]
3331  *
3332  * {foo: 0, bar: 1, baz: 2}.each_with_object({}) {|(k, v), h| h[v] = k }
3333  * # => {0=>:foo, 1=>:bar, 2=>:baz}
3334  *
3335  * With no block given, returns an Enumerator.
3336  *
3337  */
3338 static VALUE
3339 enum_each_with_object(VALUE obj, VALUE memo)
3340 {
3341  RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enum_size);
3342 
3343  rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);
3344 
3345  return memo;
3346 }
3347 
3348 static VALUE
3349 zip_ary(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
3350 {
3351  struct MEMO *memo = (struct MEMO *)memoval;
3352  VALUE result = memo->v1;
3353  VALUE args = memo->v2;
3354  long n = memo->u3.cnt++;
3355  VALUE tmp;
3356  int i;
3357 
3358  tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
3359  rb_ary_store(tmp, 0, rb_enum_values_pack(argc, argv));
3360  for (i=0; i<RARRAY_LEN(args); i++) {
3361  VALUE e = RARRAY_AREF(args, i);
3362 
3363  if (RARRAY_LEN(e) <= n) {
3364  rb_ary_push(tmp, Qnil);
3365  }
3366  else {
3367  rb_ary_push(tmp, RARRAY_AREF(e, n));
3368  }
3369  }
3370  if (NIL_P(result)) {
3371  enum_yield_array(tmp);
3372  }
3373  else {
3374  rb_ary_push(result, tmp);
3375  }
3376 
3377  RB_GC_GUARD(args);
3378 
3379  return Qnil;
3380 }
3381 
3382 static VALUE
3383 call_next(VALUE w)
3384 {
3385  VALUE *v = (VALUE *)w;
3386  return v[0] = rb_funcallv(v[1], id_next, 0, 0);
3387 }
3388 
3389 static VALUE
3390 call_stop(VALUE w, VALUE _)
3391 {
3392  VALUE *v = (VALUE *)w;
3393  return v[0] = Qundef;
3394 }
3395 
3396 static VALUE
3397 zip_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
3398 {
3399  struct MEMO *memo = (struct MEMO *)memoval;
3400  VALUE result = memo->v1;
3401  VALUE args = memo->v2;
3402  VALUE tmp;
3403  int i;
3404 
3405  tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
3406  rb_ary_store(tmp, 0, rb_enum_values_pack(argc, argv));
3407  for (i=0; i<RARRAY_LEN(args); i++) {
3408  if (NIL_P(RARRAY_AREF(args, i))) {
3409  rb_ary_push(tmp, Qnil);
3410  }
3411  else {
3412  VALUE v[2];
3413 
3414  v[1] = RARRAY_AREF(args, i);
3415  rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, (VALUE)0);
3416  if (UNDEF_P(v[0])) {
3417  RARRAY_ASET(args, i, Qnil);
3418  v[0] = Qnil;
3419  }
3420  rb_ary_push(tmp, v[0]);
3421  }
3422  }
3423  if (NIL_P(result)) {
3424  enum_yield_array(tmp);
3425  }
3426  else {
3427  rb_ary_push(result, tmp);
3428  }
3429 
3430  RB_GC_GUARD(args);
3431 
3432  return Qnil;
3433 }
3434 
3435 /*
3436  * call-seq:
3437  * zip(*other_enums) -> array
3438  * zip(*other_enums) {|array| ... } -> nil
3439  *
3440  * With no block given, returns a new array +new_array+ of size self.size
3441  * whose elements are arrays.
3442  * Each nested array <tt>new_array[n]</tt>
3443  * is of size <tt>other_enums.size+1</tt>, and contains:
3444  *
3445  * - The +n+-th element of self.
3446  * - The +n+-th element of each of the +other_enums+.
3447  *
3448  * If all +other_enums+ and self are the same size,
3449  * all elements are included in the result, and there is no +nil+-filling:
3450  *
3451  * a = [:a0, :a1, :a2, :a3]
3452  * b = [:b0, :b1, :b2, :b3]
3453  * c = [:c0, :c1, :c2, :c3]
3454  * d = a.zip(b, c)
3455  * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
3456  *
3457  * f = {foo: 0, bar: 1, baz: 2}
3458  * g = {goo: 3, gar: 4, gaz: 5}
3459  * h = {hoo: 6, har: 7, haz: 8}
3460  * d = f.zip(g, h)
3461  * d # => [
3462  * # [[:foo, 0], [:goo, 3], [:hoo, 6]],
3463  * # [[:bar, 1], [:gar, 4], [:har, 7]],
3464  * # [[:baz, 2], [:gaz, 5], [:haz, 8]]
3465  * # ]
3466  *
3467  * If any enumerable in other_enums is smaller than self,
3468  * fills to <tt>self.size</tt> with +nil+:
3469  *
3470  * a = [:a0, :a1, :a2, :a3]
3471  * b = [:b0, :b1, :b2]
3472  * c = [:c0, :c1]
3473  * d = a.zip(b, c)
3474  * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
3475  *
3476  * If any enumerable in other_enums is larger than self,
3477  * its trailing elements are ignored:
3478  *
3479  * a = [:a0, :a1, :a2, :a3]
3480  * b = [:b0, :b1, :b2, :b3, :b4]
3481  * c = [:c0, :c1, :c2, :c3, :c4, :c5]
3482  * d = a.zip(b, c)
3483  * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
3484  *
3485  * When a block is given, calls the block with each of the sub-arrays
3486  * (formed as above); returns nil:
3487  *
3488  * a = [:a0, :a1, :a2, :a3]
3489  * b = [:b0, :b1, :b2, :b3]
3490  * c = [:c0, :c1, :c2, :c3]
3491  * a.zip(b, c) {|sub_array| p sub_array} # => nil
3492  *
3493  * Output:
3494  *
3495  * [:a0, :b0, :c0]
3496  * [:a1, :b1, :c1]
3497  * [:a2, :b2, :c2]
3498  * [:a3, :b3, :c3]
3499  *
3500  */
3501 
3502 static VALUE
3503 enum_zip(int argc, VALUE *argv, VALUE obj)
3504 {
3505  int i;
3506  ID conv;
3507  struct MEMO *memo;
3508  VALUE result = Qnil;
3509  VALUE args = rb_ary_new4(argc, argv);
3510  int allary = TRUE;
3511 
3512  argv = RARRAY_PTR(args);
3513  for (i=0; i<argc; i++) {
3514  VALUE ary = rb_check_array_type(argv[i]);
3515  if (NIL_P(ary)) {
3516  allary = FALSE;
3517  break;
3518  }
3519  argv[i] = ary;
3520  }
3521  if (!allary) {
3522  static const VALUE sym_each = STATIC_ID2SYM(id_each);
3523  CONST_ID(conv, "to_enum");
3524  for (i=0; i<argc; i++) {
3525  if (!rb_respond_to(argv[i], id_each)) {
3526  rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
3527  rb_obj_class(argv[i]));
3528  }
3529  argv[i] = rb_funcallv(argv[i], conv, 1, &sym_each);
3530  }
3531  }
3532  if (!rb_block_given_p()) {
3533  result = rb_ary_new();
3534  }
3535 
3536  /* TODO: use NODE_DOT2 as memo(v, v, -) */
3537  memo = MEMO_NEW(result, args, 0);
3538  rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
3539 
3540  return result;
3541 }
3542 
3543 static VALUE
3544 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
3545 {
3546  struct MEMO *memo = MEMO_CAST(args);
3547  rb_ary_push(memo->v1, rb_enum_values_pack(argc, argv));
3548  if (--memo->u3.cnt == 0) rb_iter_break();
3549  return Qnil;
3550 }
3551 
3552 /*
3553  * call-seq:
3554  * take(n) -> array
3555  *
3556  * For non-negative integer +n+, returns the first +n+ elements:
3557  *
3558  * r = (1..4)
3559  * r.take(2) # => [1, 2]
3560  * r.take(0) # => []
3561  *
3562  * h = {foo: 0, bar: 1, baz: 2, bat: 3}
3563  * h.take(2) # => [[:foo, 0], [:bar, 1]]
3564  *
3565  */
3566 
3567 static VALUE
3568 enum_take(VALUE obj, VALUE n)
3569 {
3570  struct MEMO *memo;
3571  VALUE result;
3572  long len = NUM2LONG(n);
3573 
3574  if (len < 0) {
3575  rb_raise(rb_eArgError, "attempt to take negative size");
3576  }
3577 
3578  if (len == 0) return rb_ary_new2(0);
3579  result = rb_ary_new2(len);
3580  memo = MEMO_NEW(result, 0, len);
3581  rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)memo);
3582  return result;
3583 }
3584 
3585 
3586 static VALUE
3587 take_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
3588 {
3589  if (!RTEST(rb_yield_values2(argc, argv))) rb_iter_break();
3590  rb_ary_push(ary, rb_enum_values_pack(argc, argv));
3591  return Qnil;
3592 }
3593 
3594 /*
3595  * call-seq:
3596  * take_while {|element| ... } -> array
3597  * take_while -> enumerator
3598  *
3599  * Calls the block with successive elements as long as the block
3600  * returns a truthy value;
3601  * returns an array of all elements up to that point:
3602  *
3603  *
3604  * (1..4).take_while{|i| i < 3 } # => [1, 2]
3605  * h = {foo: 0, bar: 1, baz: 2}
3606  * h.take_while{|element| key, value = *element; value < 2 }
3607  * # => [[:foo, 0], [:bar, 1]]
3608  *
3609  * With no block given, returns an Enumerator.
3610  *
3611  */
3612 
3613 static VALUE
3614 enum_take_while(VALUE obj)
3615 {
3616  VALUE ary;
3617 
3618  RETURN_ENUMERATOR(obj, 0, 0);
3619  ary = rb_ary_new();
3620  rb_block_call(obj, id_each, 0, 0, take_while_i, ary);
3621  return ary;
3622 }
3623 
3624 static VALUE
3625 drop_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
3626 {
3627  struct MEMO *memo = MEMO_CAST(args);
3628  if (memo->u3.cnt == 0) {
3629  rb_ary_push(memo->v1, rb_enum_values_pack(argc, argv));
3630  }
3631  else {
3632  memo->u3.cnt--;
3633  }
3634  return Qnil;
3635 }
3636 
3637 /*
3638  * call-seq:
3639  * drop(n) -> array
3640  *
3641  * For positive integer +n+, returns an array containing
3642  * all but the first +n+ elements:
3643  *
3644  * r = (1..4)
3645  * r.drop(3) # => [4]
3646  * r.drop(2) # => [3, 4]
3647  * r.drop(1) # => [2, 3, 4]
3648  * r.drop(0) # => [1, 2, 3, 4]
3649  * r.drop(50) # => []
3650  *
3651  * h = {foo: 0, bar: 1, baz: 2, bat: 3}
3652  * h.drop(2) # => [[:baz, 2], [:bat, 3]]
3653  *
3654  */
3655 
3656 static VALUE
3657 enum_drop(VALUE obj, VALUE n)
3658 {
3659  VALUE result;
3660  struct MEMO *memo;
3661  long len = NUM2LONG(n);
3662 
3663  if (len < 0) {
3664  rb_raise(rb_eArgError, "attempt to drop negative size");
3665  }
3666 
3667  result = rb_ary_new();
3668  memo = MEMO_NEW(result, 0, len);
3669  rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)memo);
3670  return result;
3671 }
3672 
3673 
3674 static VALUE
3675 drop_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
3676 {
3677  struct MEMO *memo = MEMO_CAST(args);
3678  ENUM_WANT_SVALUE();
3679 
3680  if (!memo->u3.state && !RTEST(enum_yield(argc, i))) {
3681  memo->u3.state = TRUE;
3682  }
3683  if (memo->u3.state) {
3684  rb_ary_push(memo->v1, i);
3685  }
3686  return Qnil;
3687 }
3688 
3689 /*
3690  * call-seq:
3691  * drop_while {|element| ... } -> array
3692  * drop_while -> enumerator
3693  *
3694  * Calls the block with successive elements as long as the block
3695  * returns a truthy value;
3696  * returns an array of all elements after that point:
3697  *
3698  *
3699  * (1..4).drop_while{|i| i < 3 } # => [3, 4]
3700  * h = {foo: 0, bar: 1, baz: 2}
3701  * a = h.drop_while{|element| key, value = *element; value < 2 }
3702  * a # => [[:baz, 2]]
3703  *
3704  * With no block given, returns an Enumerator.
3705  *
3706  */
3707 
3708 static VALUE
3709 enum_drop_while(VALUE obj)
3710 {
3711  VALUE result;
3712  struct MEMO *memo;
3713 
3714  RETURN_ENUMERATOR(obj, 0, 0);
3715  result = rb_ary_new();
3716  memo = MEMO_NEW(result, 0, FALSE);
3717  rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)memo);
3718  return result;
3719 }
3720 
3721 static VALUE
3722 cycle_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
3723 {
3724  ENUM_WANT_SVALUE();
3725 
3726  rb_ary_push(ary, argc > 1 ? i : rb_ary_new_from_values(argc, argv));
3727  enum_yield(argc, i);
3728  return Qnil;
3729 }
3730 
3731 static VALUE
3732 enum_cycle_size(VALUE self, VALUE args, VALUE eobj)
3733 {
3734  long mul = 0;
3735  VALUE n = Qnil;
3736  VALUE size;
3737 
3738  if (args && (RARRAY_LEN(args) > 0)) {
3739  n = RARRAY_AREF(args, 0);
3740  if (!NIL_P(n)) mul = NUM2LONG(n);
3741  }
3742 
3743  size = enum_size(self, args, 0);
3744  if (NIL_P(size) || FIXNUM_ZERO_P(size)) return size;
3745 
3746  if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
3747  if (mul <= 0) return INT2FIX(0);
3748  n = LONG2FIX(mul);
3749  return rb_funcallv(size, '*', 1, &n);
3750 }
3751 
3752 /*
3753  * call-seq:
3754  * cycle(n = nil) {|element| ...} -> nil
3755  * cycle(n = nil) -> enumerator
3756  *
3757  * When called with positive integer argument +n+ and a block,
3758  * calls the block with each element, then does so again,
3759  * until it has done so +n+ times; returns +nil+:
3760  *
3761  * a = []
3762  * (1..4).cycle(3) {|element| a.push(element) } # => nil
3763  * a # => [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
3764  * a = []
3765  * ('a'..'d').cycle(2) {|element| a.push(element) }
3766  * a # => ["a", "b", "c", "d", "a", "b", "c", "d"]
3767  * a = []
3768  * {foo: 0, bar: 1, baz: 2}.cycle(2) {|element| a.push(element) }
3769  * a # => [[:foo, 0], [:bar, 1], [:baz, 2], [:foo, 0], [:bar, 1], [:baz, 2]]
3770  *
3771  * If count is zero or negative, does not call the block.
3772  *
3773  * When called with a block and +n+ is +nil+, cycles forever.
3774  *
3775  * When no block is given, returns an Enumerator.
3776  *
3777  */
3778 
3779 static VALUE
3780 enum_cycle(int argc, VALUE *argv, VALUE obj)
3781 {
3782  VALUE ary;
3783  VALUE nv = Qnil;
3784  long n, i, len;
3785 
3786  rb_check_arity(argc, 0, 1);
3787 
3788  RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_cycle_size);
3789  if (!argc || NIL_P(nv = argv[0])) {
3790  n = -1;
3791  }
3792  else {
3793  n = NUM2LONG(nv);
3794  if (n <= 0) return Qnil;
3795  }
3796  ary = rb_ary_new();
3797  RBASIC_CLEAR_CLASS(ary);
3798  rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
3799  len = RARRAY_LEN(ary);
3800  if (len == 0) return Qnil;
3801  while (n < 0 || 0 < --n) {
3802  for (i=0; i<len; i++) {
3803  enum_yield_array(RARRAY_AREF(ary, i));
3804  }
3805  }
3806  return Qnil;
3807 }
3808 
3809 struct chunk_arg {
3810  VALUE categorize;
3811  VALUE prev_value;
3812  VALUE prev_elts;
3813  VALUE yielder;
3814 };
3815 
3816 static VALUE
3817 chunk_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
3818 {
3819  struct chunk_arg *argp = MEMO_FOR(struct chunk_arg, _argp);
3820  VALUE v, s;
3821  VALUE alone = ID2SYM(id__alone);
3822  VALUE separator = ID2SYM(id__separator);
3823 
3824  ENUM_WANT_SVALUE();
3825 
3826  v = rb_funcallv(argp->categorize, id_call, 1, &i);
3827 
3828  if (v == alone) {
3829  if (!NIL_P(argp->prev_value)) {
3830  s = rb_assoc_new(argp->prev_value, argp->prev_elts);
3831  rb_funcallv(argp->yielder, id_lshift, 1, &s);
3832  argp->prev_value = argp->prev_elts = Qnil;
3833  }
3834  v = rb_assoc_new(v, rb_ary_new3(1, i));
3835  rb_funcallv(argp->yielder, id_lshift, 1, &v);
3836  }
3837  else if (NIL_P(v) || v == separator) {
3838  if (!NIL_P(argp->prev_value)) {
3839  v = rb_assoc_new(argp->prev_value, argp->prev_elts);
3840  rb_funcallv(argp->yielder, id_lshift, 1, &v);
3841  argp->prev_value = argp->prev_elts = Qnil;
3842  }
3843  }
3844  else if (SYMBOL_P(v) && (s = rb_sym2str(v), RSTRING_PTR(s)[0] == '_')) {
3845  rb_raise(rb_eRuntimeError, "symbols beginning with an underscore are reserved");
3846  }
3847  else {
3848  if (NIL_P(argp->prev_value)) {
3849  argp->prev_value = v;
3850  argp->prev_elts = rb_ary_new3(1, i);
3851  }
3852  else {
3853  if (rb_equal(argp->prev_value, v)) {
3854  rb_ary_push(argp->prev_elts, i);
3855  }
3856  else {
3857  s = rb_assoc_new(argp->prev_value, argp->prev_elts);
3858  rb_funcallv(argp->yielder, id_lshift, 1, &s);
3859  argp->prev_value = v;
3860  argp->prev_elts = rb_ary_new3(1, i);
3861  }
3862  }
3863  }
3864  return Qnil;
3865 }
3866 
3867 static VALUE
3869 {
3870  VALUE enumerable;
3871  VALUE arg;
3872  struct chunk_arg *memo = NEW_MEMO_FOR(struct chunk_arg, arg);
3873 
3874  enumerable = rb_ivar_get(enumerator, id_chunk_enumerable);
3875  memo->categorize = rb_ivar_get(enumerator, id_chunk_categorize);
3876  memo->prev_value = Qnil;
3877  memo->prev_elts = Qnil;
3878  memo->yielder = yielder;
3879 
3880  rb_block_call(enumerable, id_each, 0, 0, chunk_ii, arg);
3881  memo = MEMO_FOR(struct chunk_arg, arg);
3882  if (!NIL_P(memo->prev_elts)) {
3883  arg = rb_assoc_new(memo->prev_value, memo->prev_elts);
3884  rb_funcallv(memo->yielder, id_lshift, 1, &arg);
3885  }
3886  return Qnil;
3887 }
3888 
3889 /*
3890  * call-seq:
3891  * chunk {|array| ... } -> enumerator
3892  *
3893  * Each element in the returned enumerator is a 2-element array consisting of:
3894  *
3895  * - A value returned by the block.
3896  * - An array ("chunk") containing the element for which that value was returned,
3897  * and all following elements for which the block returned the same value:
3898  *
3899  * So that:
3900  *
3901  * - Each block return value that is different from its predecessor
3902  * begins a new chunk.
3903  * - Each block return value that is the same as its predecessor
3904  * continues the same chunk.
3905  *
3906  * Example:
3907  *
3908  * e = (0..10).chunk {|i| (i / 3).floor } # => #<Enumerator: ...>
3909  * # The enumerator elements.
3910  * e.next # => [0, [0, 1, 2]]
3911  * e.next # => [1, [3, 4, 5]]
3912  * e.next # => [2, [6, 7, 8]]
3913  * e.next # => [3, [9, 10]]
3914  *
3915  * \Method +chunk+ is especially useful for an enumerable that is already sorted.
3916  * This example counts words for each initial letter in a large array of words:
3917  *
3918  * # Get sorted words from a web page.
3919  * url = 'https://raw.githubusercontent.com/eneko/data-repository/master/data/words.txt'
3920  * words = URI::open(url).readlines
3921  * # Make chunks, one for each letter.
3922  * e = words.chunk {|word| word.upcase[0] } # => #<Enumerator: ...>
3923  * # Display 'A' through 'F'.
3924  * e.each {|c, words| p [c, words.length]; break if c == 'F' }
3925  *
3926  * Output:
3927  *
3928  * ["A", 17096]
3929  * ["B", 11070]
3930  * ["C", 19901]
3931  * ["D", 10896]
3932  * ["E", 8736]
3933  * ["F", 6860]
3934  *
3935  * You can use the special symbol <tt>:_alone</tt> to force an element
3936  * into its own separate chuck:
3937  *
3938  * a = [0, 0, 1, 1]
3939  * e = a.chunk{|i| i.even? ? :_alone : true }
3940  * e.to_a # => [[:_alone, [0]], [:_alone, [0]], [true, [1, 1]]]
3941  *
3942  * For example, you can put each line that contains a URL into its own chunk:
3943  *
3944  * pattern = /http/
3945  * open(filename) { |f|
3946  * f.chunk { |line| line =~ pattern ? :_alone : true }.each { |key, lines|
3947  * pp lines
3948  * }
3949  * }
3950  *
3951  * You can use the special symbol <tt>:_separator</tt> or +nil+
3952  * to force an element to be ignored (not included in any chunk):
3953  *
3954  * a = [0, 0, -1, 1, 1]
3955  * e = a.chunk{|i| i < 0 ? :_separator : true }
3956  * e.to_a # => [[true, [0, 0]], [true, [1, 1]]]
3957  *
3958  * Note that the separator does end the chunk:
3959  *
3960  * a = [0, 0, -1, 1, -1, 1]
3961  * e = a.chunk{|i| i < 0 ? :_separator : true }
3962  * e.to_a # => [[true, [0, 0]], [true, [1]], [true, [1]]]
3963  *
3964  * For example, the sequence of hyphens in svn log can be eliminated as follows:
3965  *
3966  * sep = "-"*72 + "\n"
3967  * IO.popen("svn log README") { |f|
3968  * f.chunk { |line|
3969  * line != sep || nil
3970  * }.each { |_, lines|
3971  * pp lines
3972  * }
3973  * }
3974  * #=> ["r20018 | knu | 2008-10-29 13:20:42 +0900 (Wed, 29 Oct 2008) | 2 lines\n",
3975  * # "\n",
3976  * # "* README, README.ja: Update the portability section.\n",
3977  * # "\n"]
3978  * # ["r16725 | knu | 2008-05-31 23:34:23 +0900 (Sat, 31 May 2008) | 2 lines\n",
3979  * # "\n",
3980  * # "* README, README.ja: Add a note about default C flags.\n",
3981  * # "\n"]
3982  * # ...
3983  *
3984  * Paragraphs separated by empty lines can be parsed as follows:
3985  *
3986  * File.foreach("README").chunk { |line|
3987  * /\A\s*\z/ !~ line || nil
3988  * }.each { |_, lines|
3989  * pp lines
3990  * }
3991  *
3992  */
3993 static VALUE
3994 enum_chunk(VALUE enumerable)
3995 {
3996  VALUE enumerator;
3997 
3998  RETURN_SIZED_ENUMERATOR(enumerable, 0, 0, enum_size);
3999 
4001  rb_ivar_set(enumerator, id_chunk_enumerable, enumerable);
4002  rb_ivar_set(enumerator, id_chunk_categorize, rb_block_proc());
4003  rb_block_call(enumerator, idInitialize, 0, 0, chunk_i, enumerator);
4004  return enumerator;
4005 }
4006 
4007 
4009  VALUE sep_pred;
4010  VALUE sep_pat;
4011  VALUE prev_elts;
4012  VALUE yielder;
4013 };
4014 
4015 static VALUE
4016 slicebefore_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
4017 {
4018  struct slicebefore_arg *argp = MEMO_FOR(struct slicebefore_arg, _argp);
4019  VALUE header_p;
4020 
4021  ENUM_WANT_SVALUE();
4022 
4023  if (!NIL_P(argp->sep_pat))
4024  header_p = rb_funcallv(argp->sep_pat, id_eqq, 1, &i);
4025  else
4026  header_p = rb_funcallv(argp->sep_pred, id_call, 1, &i);
4027  if (RTEST(header_p)) {
4028  if (!NIL_P(argp->prev_elts))
4029  rb_funcallv(argp->yielder, id_lshift, 1, &argp->prev_elts);
4030  argp->prev_elts = rb_ary_new3(1, i);
4031  }
4032  else {
4033  if (NIL_P(argp->prev_elts))
4034  argp->prev_elts = rb_ary_new3(1, i);
4035  else
4036  rb_ary_push(argp->prev_elts, i);
4037  }
4038 
4039  return Qnil;
4040 }
4041 
4042 static VALUE
4044 {
4045  VALUE enumerable;
4046  VALUE arg;
4047  struct slicebefore_arg *memo = NEW_MEMO_FOR(struct slicebefore_arg, arg);
4048 
4049  enumerable = rb_ivar_get(enumerator, id_slicebefore_enumerable);
4050  memo->sep_pred = rb_attr_get(enumerator, id_slicebefore_sep_pred);
4051  memo->sep_pat = NIL_P(memo->sep_pred) ? rb_ivar_get(enumerator, id_slicebefore_sep_pat) : Qnil;
4052  memo->prev_elts = Qnil;
4053  memo->yielder = yielder;
4054 
4055  rb_block_call(enumerable, id_each, 0, 0, slicebefore_ii, arg);
4056  memo = MEMO_FOR(struct slicebefore_arg, arg);
4057  if (!NIL_P(memo->prev_elts))
4058  rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4059  return Qnil;
4060 }
4061 
4062 /*
4063  * call-seq:
4064  * slice_before(pattern) -> enumerator
4065  * slice_before {|elt| ... } -> enumerator
4066  *
4067  * With argument +pattern+, returns an enumerator that uses the pattern
4068  * to partition elements into arrays ("slices").
4069  * An element begins a new slice if <tt>element === pattern</tt>
4070  * (or if it is the first element).
4071  *
4072  * a = %w[foo bar fop for baz fob fog bam foy]
4073  * e = a.slice_before(/ba/) # => #<Enumerator: ...>
4074  * e.each {|array| p array }
4075  *
4076  * Output:
4077  *
4078  * ["foo"]
4079  * ["bar", "fop", "for"]
4080  * ["baz", "fob", "fog"]
4081  * ["bam", "foy"]
4082  *
4083  * With a block, returns an enumerator that uses the block
4084  * to partition elements into arrays.
4085  * An element begins a new slice if its block return is a truthy value
4086  * (or if it is the first element):
4087  *
4088  * e = (1..20).slice_before {|i| i % 4 == 2 } # => #<Enumerator: ...>
4089  * e.each {|array| p array }
4090  *
4091  * Output:
4092  *
4093  * [1]
4094  * [2, 3, 4, 5]
4095  * [6, 7, 8, 9]
4096  * [10, 11, 12, 13]
4097  * [14, 15, 16, 17]
4098  * [18, 19, 20]
4099  *
4100  * Other methods of the Enumerator class and Enumerable module,
4101  * such as +to_a+, +map+, etc., are also usable.
4102  *
4103  * For example, iteration over ChangeLog entries can be implemented as
4104  * follows:
4105  *
4106  * # iterate over ChangeLog entries.
4107  * open("ChangeLog") { |f|
4108  * f.slice_before(/\A\S/).each { |e| pp e }
4109  * }
4110  *
4111  * # same as above. block is used instead of pattern argument.
4112  * open("ChangeLog") { |f|
4113  * f.slice_before { |line| /\A\S/ === line }.each { |e| pp e }
4114  * }
4115  *
4116  * "svn proplist -R" produces multiline output for each file.
4117  * They can be chunked as follows:
4118  *
4119  * IO.popen([{"LC_ALL"=>"C"}, "svn", "proplist", "-R"]) { |f|
4120  * f.lines.slice_before(/\AProp/).each { |lines| p lines }
4121  * }
4122  * #=> ["Properties on '.':\n", " svn:ignore\n", " svk:merge\n"]
4123  * # ["Properties on 'goruby.c':\n", " svn:eol-style\n"]
4124  * # ["Properties on 'complex.c':\n", " svn:mime-type\n", " svn:eol-style\n"]
4125  * # ["Properties on 'regparse.c':\n", " svn:eol-style\n"]
4126  * # ...
4127  *
4128  * If the block needs to maintain state over multiple elements,
4129  * local variables can be used.
4130  * For example, three or more consecutive increasing numbers can be squashed
4131  * as follows (see +chunk_while+ for a better way):
4132  *
4133  * a = [0, 2, 3, 4, 6, 7, 9]
4134  * prev = a[0]
4135  * p a.slice_before { |e|
4136  * prev, prev2 = e, prev
4137  * prev2 + 1 != e
4138  * }.map { |es|
4139  * es.length <= 2 ? es.join(",") : "#{es.first}-#{es.last}"
4140  * }.join(",")
4141  * #=> "0,2-4,6,7,9"
4142  *
4143  * However local variables should be used carefully
4144  * if the result enumerator is enumerated twice or more.
4145  * The local variables should be initialized for each enumeration.
4146  * Enumerator.new can be used to do it.
4147  *
4148  * # Word wrapping. This assumes all characters have same width.
4149  * def wordwrap(words, maxwidth)
4150  * Enumerator.new {|y|
4151  * # cols is initialized in Enumerator.new.
4152  * cols = 0
4153  * words.slice_before { |w|
4154  * cols += 1 if cols != 0
4155  * cols += w.length
4156  * if maxwidth < cols
4157  * cols = w.length
4158  * true
4159  * else
4160  * false
4161  * end
4162  * }.each {|ws| y.yield ws }
4163  * }
4164  * end
4165  * text = (1..20).to_a.join(" ")
4166  * enum = wordwrap(text.split(/\s+/), 10)
4167  * puts "-"*10
4168  * enum.each { |ws| puts ws.join(" ") } # first enumeration.
4169  * puts "-"*10
4170  * enum.each { |ws| puts ws.join(" ") } # second enumeration generates same result as the first.
4171  * puts "-"*10
4172  * #=> ----------
4173  * # 1 2 3 4 5
4174  * # 6 7 8 9 10
4175  * # 11 12 13
4176  * # 14 15 16
4177  * # 17 18 19
4178  * # 20
4179  * # ----------
4180  * # 1 2 3 4 5
4181  * # 6 7 8 9 10
4182  * # 11 12 13
4183  * # 14 15 16
4184  * # 17 18 19
4185  * # 20
4186  * # ----------
4187  *
4188  * mbox contains series of mails which start with Unix From line.
4189  * So each mail can be extracted by slice before Unix From line.
4190  *
4191  * # parse mbox
4192  * open("mbox") { |f|
4193  * f.slice_before { |line|
4194  * line.start_with? "From "
4195  * }.each { |mail|
4196  * unix_from = mail.shift
4197  * i = mail.index("\n")
4198  * header = mail[0...i]
4199  * body = mail[(i+1)..-1]
4200  * body.pop if body.last == "\n"
4201  * fields = header.slice_before { |line| !" \t".include?(line[0]) }.to_a
4202  * p unix_from
4203  * pp fields
4204  * pp body
4205  * }
4206  * }
4207  *
4208  * # split mails in mbox (slice before Unix From line after an empty line)
4209  * open("mbox") { |f|
4210  * emp = true
4211  * f.slice_before { |line|
4212  * prevemp = emp
4213  * emp = line == "\n"
4214  * prevemp && line.start_with?("From ")
4215  * }.each { |mail|
4216  * mail.pop if mail.last == "\n"
4217  * pp mail
4218  * }
4219  * }
4220  *
4221  */
4222 static VALUE
4223 enum_slice_before(int argc, VALUE *argv, VALUE enumerable)
4224 {
4225  VALUE enumerator;
4226 
4227  if (rb_block_given_p()) {
4228  if (argc != 0)
4229  rb_error_arity(argc, 0, 0);
4231  rb_ivar_set(enumerator, id_slicebefore_sep_pred, rb_block_proc());
4232  }
4233  else {
4234  VALUE sep_pat;
4235  rb_scan_args(argc, argv, "1", &sep_pat);
4237  rb_ivar_set(enumerator, id_slicebefore_sep_pat, sep_pat);
4238  }
4239  rb_ivar_set(enumerator, id_slicebefore_enumerable, enumerable);
4240  rb_block_call(enumerator, idInitialize, 0, 0, slicebefore_i, enumerator);
4241  return enumerator;
4242 }
4243 
4244 
4246  VALUE pat;
4247  VALUE pred;
4248  VALUE prev_elts;
4249  VALUE yielder;
4250 };
4251 
4252 static VALUE
4253 sliceafter_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
4254 {
4255 #define UPDATE_MEMO ((void)(memo = MEMO_FOR(struct sliceafter_arg, _memo)))
4256  struct sliceafter_arg *memo;
4257  int split_p;
4258  UPDATE_MEMO;
4259 
4260  ENUM_WANT_SVALUE();
4261 
4262  if (NIL_P(memo->prev_elts)) {
4263  memo->prev_elts = rb_ary_new3(1, i);
4264  }
4265  else {
4266  rb_ary_push(memo->prev_elts, i);
4267  }
4268 
4269  if (NIL_P(memo->pred)) {
4270  split_p = RTEST(rb_funcallv(memo->pat, id_eqq, 1, &i));
4271  UPDATE_MEMO;
4272  }
4273  else {
4274  split_p = RTEST(rb_funcallv(memo->pred, id_call, 1, &i));
4275  UPDATE_MEMO;
4276  }
4277 
4278  if (split_p) {
4279  rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4280  UPDATE_MEMO;
4281  memo->prev_elts = Qnil;
4282  }
4283 
4284  return Qnil;
4285 #undef UPDATE_MEMO
4286 }
4287 
4288 static VALUE
4290 {
4291  VALUE enumerable;
4292  VALUE arg;
4293  struct sliceafter_arg *memo = NEW_MEMO_FOR(struct sliceafter_arg, arg);
4294 
4295  enumerable = rb_ivar_get(enumerator, id_sliceafter_enum);
4296  memo->pat = rb_ivar_get(enumerator, id_sliceafter_pat);
4297  memo->pred = rb_attr_get(enumerator, id_sliceafter_pred);
4298  memo->prev_elts = Qnil;
4299  memo->yielder = yielder;
4300 
4301  rb_block_call(enumerable, id_each, 0, 0, sliceafter_ii, arg);
4302  memo = MEMO_FOR(struct sliceafter_arg, arg);
4303  if (!NIL_P(memo->prev_elts))
4304  rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4305  return Qnil;
4306 }
4307 
4308 /*
4309  * call-seq:
4310  * enum.slice_after(pattern) -> an_enumerator
4311  * enum.slice_after { |elt| bool } -> an_enumerator
4312  *
4313  * Creates an enumerator for each chunked elements.
4314  * The ends of chunks are defined by _pattern_ and the block.
4315  *
4316  * If <code>_pattern_ === _elt_</code> returns <code>true</code> or the block
4317  * returns <code>true</code> for the element, the element is end of a
4318  * chunk.
4319  *
4320  * The <code>===</code> and _block_ is called from the first element to the last
4321  * element of _enum_.
4322  *
4323  * The result enumerator yields the chunked elements as an array.
4324  * So +each+ method can be called as follows:
4325  *
4326  * enum.slice_after(pattern).each { |ary| ... }
4327  * enum.slice_after { |elt| bool }.each { |ary| ... }
4328  *
4329  * Other methods of the Enumerator class and Enumerable module,
4330  * such as +map+, etc., are also usable.
4331  *
4332  * For example, continuation lines (lines end with backslash) can be
4333  * concatenated as follows:
4334  *
4335  * lines = ["foo\n", "bar\\\n", "baz\n", "\n", "qux\n"]
4336  * e = lines.slice_after(/(?<!\\‍)\n\z/)
4337  * p e.to_a
4338  * #=> [["foo\n"], ["bar\\\n", "baz\n"], ["\n"], ["qux\n"]]
4339  * p e.map {|ll| ll[0...-1].map {|l| l.sub(/\\\n\z/, "") }.join + ll.last }
4340  * #=>["foo\n", "barbaz\n", "\n", "qux\n"]
4341  *
4342  */
4343 
4344 static VALUE
4345 enum_slice_after(int argc, VALUE *argv, VALUE enumerable)
4346 {
4347  VALUE enumerator;
4348  VALUE pat = Qnil, pred = Qnil;
4349 
4350  if (rb_block_given_p()) {
4351  if (0 < argc)
4352  rb_raise(rb_eArgError, "both pattern and block are given");
4353  pred = rb_block_proc();
4354  }
4355  else {
4356  rb_scan_args(argc, argv, "1", &pat);
4357  }
4358 
4360  rb_ivar_set(enumerator, id_sliceafter_enum, enumerable);
4361  rb_ivar_set(enumerator, id_sliceafter_pat, pat);
4362  rb_ivar_set(enumerator, id_sliceafter_pred, pred);
4363 
4364  rb_block_call(enumerator, idInitialize, 0, 0, sliceafter_i, enumerator);
4365  return enumerator;
4366 }
4367 
4369  VALUE pred;
4370  VALUE prev_elt;
4371  VALUE prev_elts;
4372  VALUE yielder;
4373  int inverted; /* 0 for slice_when and 1 for chunk_while. */
4374 };
4375 
4376 static VALUE
4377 slicewhen_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
4378 {
4379 #define UPDATE_MEMO ((void)(memo = MEMO_FOR(struct slicewhen_arg, _memo)))
4380  struct slicewhen_arg *memo;
4381  int split_p;
4382  UPDATE_MEMO;
4383 
4384  ENUM_WANT_SVALUE();
4385 
4386  if (UNDEF_P(memo->prev_elt)) {
4387  /* The first element */
4388  memo->prev_elt = i;
4389  memo->prev_elts = rb_ary_new3(1, i);
4390  }
4391  else {
4392  VALUE args[2];
4393  args[0] = memo->prev_elt;
4394  args[1] = i;
4395  split_p = RTEST(rb_funcallv(memo->pred, id_call, 2, args));
4396  UPDATE_MEMO;
4397 
4398  if (memo->inverted)
4399  split_p = !split_p;
4400 
4401  if (split_p) {
4402  rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4403  UPDATE_MEMO;
4404  memo->prev_elts = rb_ary_new3(1, i);
4405  }
4406  else {
4407  rb_ary_push(memo->prev_elts, i);
4408  }
4409 
4410  memo->prev_elt = i;
4411  }
4412 
4413  return Qnil;
4414 #undef UPDATE_MEMO
4415 }
4416 
4417 static VALUE
4419 {
4420  VALUE enumerable;
4421  VALUE arg;
4422  struct slicewhen_arg *memo =
4423  NEW_PARTIAL_MEMO_FOR(struct slicewhen_arg, arg, inverted);
4424 
4425  enumerable = rb_ivar_get(enumerator, id_slicewhen_enum);
4426  memo->pred = rb_attr_get(enumerator, id_slicewhen_pred);
4427  memo->prev_elt = Qundef;
4428  memo->prev_elts = Qnil;
4429  memo->yielder = yielder;
4430  memo->inverted = RTEST(rb_attr_get(enumerator, id_slicewhen_inverted));
4431 
4432  rb_block_call(enumerable, id_each, 0, 0, slicewhen_ii, arg);
4433  memo = MEMO_FOR(struct slicewhen_arg, arg);
4434  if (!NIL_P(memo->prev_elts))
4435  rb_funcallv(memo->yielder, id_lshift, 1, &memo->prev_elts);
4436  return Qnil;
4437 }
4438 
4439 /*
4440  * call-seq:
4441  * enum.slice_when {|elt_before, elt_after| bool } -> an_enumerator
4442  *
4443  * Creates an enumerator for each chunked elements.
4444  * The beginnings of chunks are defined by the block.
4445  *
4446  * This method splits each chunk using adjacent elements,
4447  * _elt_before_ and _elt_after_,
4448  * in the receiver enumerator.
4449  * This method split chunks between _elt_before_ and _elt_after_ where
4450  * the block returns <code>true</code>.
4451  *
4452  * The block is called the length of the receiver enumerator minus one.
4453  *
4454  * The result enumerator yields the chunked elements as an array.
4455  * So +each+ method can be called as follows:
4456  *
4457  * enum.slice_when { |elt_before, elt_after| bool }.each { |ary| ... }
4458  *
4459  * Other methods of the Enumerator class and Enumerable module,
4460  * such as +to_a+, +map+, etc., are also usable.
4461  *
4462  * For example, one-by-one increasing subsequence can be chunked as follows:
4463  *
4464  * a = [1,2,4,9,10,11,12,15,16,19,20,21]
4465  * b = a.slice_when {|i, j| i+1 != j }
4466  * p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
4467  * c = b.map {|a| a.length < 3 ? a : "#{a.first}-#{a.last}" }
4468  * p c #=> [[1, 2], [4], "9-12", [15, 16], "19-21"]
4469  * d = c.join(",")
4470  * p d #=> "1,2,4,9-12,15,16,19-21"
4471  *
4472  * Near elements (threshold: 6) in sorted array can be chunked as follows:
4473  *
4474  * a = [3, 11, 14, 25, 28, 29, 29, 41, 55, 57]
4475  * p a.slice_when {|i, j| 6 < j - i }.to_a
4476  * #=> [[3], [11, 14], [25, 28, 29, 29], [41], [55, 57]]
4477  *
4478  * Increasing (non-decreasing) subsequence can be chunked as follows:
4479  *
4480  * a = [0, 9, 2, 2, 3, 2, 7, 5, 9, 5]
4481  * p a.slice_when {|i, j| i > j }.to_a
4482  * #=> [[0, 9], [2, 2, 3], [2, 7], [5, 9], [5]]
4483  *
4484  * Adjacent evens and odds can be chunked as follows:
4485  * (Enumerable#chunk is another way to do it.)
4486  *
4487  * a = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]
4488  * p a.slice_when {|i, j| i.even? != j.even? }.to_a
4489  * #=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]
4490  *
4491  * Paragraphs (non-empty lines with trailing empty lines) can be chunked as follows:
4492  * (See Enumerable#chunk to ignore empty lines.)
4493  *
4494  * lines = ["foo\n", "bar\n", "\n", "baz\n", "qux\n"]
4495  * p lines.slice_when {|l1, l2| /\A\s*\z/ =~ l1 && /\S/ =~ l2 }.to_a
4496  * #=> [["foo\n", "bar\n", "\n"], ["baz\n", "qux\n"]]
4497  *
4498  * Enumerable#chunk_while does the same, except splitting when the block
4499  * returns <code>false</code> instead of <code>true</code>.
4500  */
4501 static VALUE
4502 enum_slice_when(VALUE enumerable)
4503 {
4504  VALUE enumerator;
4505  VALUE pred;
4506 
4507  pred = rb_block_proc();
4508 
4510  rb_ivar_set(enumerator, id_slicewhen_enum, enumerable);
4511  rb_ivar_set(enumerator, id_slicewhen_pred, pred);
4512  rb_ivar_set(enumerator, id_slicewhen_inverted, Qfalse);
4513 
4514  rb_block_call(enumerator, idInitialize, 0, 0, slicewhen_i, enumerator);
4515  return enumerator;
4516 }
4517 
4518 /*
4519  * call-seq:
4520  * enum.chunk_while {|elt_before, elt_after| bool } -> an_enumerator
4521  *
4522  * Creates an enumerator for each chunked elements.
4523  * The beginnings of chunks are defined by the block.
4524  *
4525  * This method splits each chunk using adjacent elements,
4526  * _elt_before_ and _elt_after_,
4527  * in the receiver enumerator.
4528  * This method split chunks between _elt_before_ and _elt_after_ where
4529  * the block returns <code>false</code>.
4530  *
4531  * The block is called the length of the receiver enumerator minus one.
4532  *
4533  * The result enumerator yields the chunked elements as an array.
4534  * So +each+ method can be called as follows:
4535  *
4536  * enum.chunk_while { |elt_before, elt_after| bool }.each { |ary| ... }
4537  *
4538  * Other methods of the Enumerator class and Enumerable module,
4539  * such as +to_a+, +map+, etc., are also usable.
4540  *
4541  * For example, one-by-one increasing subsequence can be chunked as follows:
4542  *
4543  * a = [1,2,4,9,10,11,12,15,16,19,20,21]
4544  * b = a.chunk_while {|i, j| i+1 == j }
4545  * p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
4546  * c = b.map {|a| a.length < 3 ? a : "#{a.first}-#{a.last}" }
4547  * p c #=> [[1, 2], [4], "9-12", [15, 16], "19-21"]
4548  * d = c.join(",")
4549  * p d #=> "1,2,4,9-12,15,16,19-21"
4550  *
4551  * Increasing (non-decreasing) subsequence can be chunked as follows:
4552  *
4553  * a = [0, 9, 2, 2, 3, 2, 7, 5, 9, 5]
4554  * p a.chunk_while {|i, j| i <= j }.to_a
4555  * #=> [[0, 9], [2, 2, 3], [2, 7], [5, 9], [5]]
4556  *
4557  * Adjacent evens and odds can be chunked as follows:
4558  * (Enumerable#chunk is another way to do it.)
4559  *
4560  * a = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]
4561  * p a.chunk_while {|i, j| i.even? == j.even? }.to_a
4562  * #=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]
4563  *
4564  * Enumerable#slice_when does the same, except splitting when the block
4565  * returns <code>true</code> instead of <code>false</code>.
4566  */
4567 static VALUE
4568 enum_chunk_while(VALUE enumerable)
4569 {
4570  VALUE enumerator;
4571  VALUE pred;
4572 
4573  pred = rb_block_proc();
4574 
4576  rb_ivar_set(enumerator, id_slicewhen_enum, enumerable);
4577  rb_ivar_set(enumerator, id_slicewhen_pred, pred);
4578  rb_ivar_set(enumerator, id_slicewhen_inverted, Qtrue);
4579 
4580  rb_block_call(enumerator, idInitialize, 0, 0, slicewhen_i, enumerator);
4581  return enumerator;
4582 }
4583 
4585  VALUE v, r;
4586  long n;
4587  double f, c;
4588  int block_given;
4589  int float_value;
4590 };
4591 
4592 static void
4593 sum_iter_normalize_memo(struct enum_sum_memo *memo)
4594 {
4595  RUBY_ASSERT(FIXABLE(memo->n));
4596  memo->v = rb_fix_plus(LONG2FIX(memo->n), memo->v);
4597  memo->n = 0;
4598 
4599  switch (TYPE(memo->r)) {
4600  case T_RATIONAL: memo->v = rb_rational_plus(memo->r, memo->v); break;
4601  case T_UNDEF: break;
4602  default: UNREACHABLE; /* or ...? */
4603  }
4604  memo->r = Qundef;
4605 }
4606 
4607 static void
4608 sum_iter_fixnum(VALUE i, struct enum_sum_memo *memo)
4609 {
4610  memo->n += FIX2LONG(i); /* should not overflow long type */
4611  if (! FIXABLE(memo->n)) {
4612  memo->v = rb_big_plus(LONG2NUM(memo->n), memo->v);
4613  memo->n = 0;
4614  }
4615 }
4616 
4617 static void
4618 sum_iter_bignum(VALUE i, struct enum_sum_memo *memo)
4619 {
4620  memo->v = rb_big_plus(i, memo->v);
4621 }
4622 
4623 static void
4624 sum_iter_rational(VALUE i, struct enum_sum_memo *memo)
4625 {
4626  if (UNDEF_P(memo->r)) {
4627  memo->r = i;
4628  }
4629  else {
4630  memo->r = rb_rational_plus(memo->r, i);
4631  }
4632 }
4633 
4634 static void
4635 sum_iter_some_value(VALUE i, struct enum_sum_memo *memo)
4636 {
4637  memo->v = rb_funcallv(memo->v, idPLUS, 1, &i);
4638 }
4639 
4640 static void
4641 sum_iter_Kahan_Babuska(VALUE i, struct enum_sum_memo *memo)
4642 {
4643  /*
4644  * Kahan-Babuska balancing compensated summation algorithm
4645  * See https://link.springer.com/article/10.1007/s00607-005-0139-x
4646  */
4647  double x;
4648 
4649  switch (TYPE(i)) {
4650  case T_FLOAT: x = RFLOAT_VALUE(i); break;
4651  case T_FIXNUM: x = FIX2LONG(i); break;
4652  case T_BIGNUM: x = rb_big2dbl(i); break;
4653  case T_RATIONAL: x = rb_num2dbl(i); break;
4654  default:
4655  memo->v = DBL2NUM(memo->f);
4656  memo->float_value = 0;
4657  sum_iter_some_value(i, memo);
4658  return;
4659  }
4660 
4661  double f = memo->f;
4662 
4663  if (isnan(f)) {
4664  return;
4665  }
4666  else if (! isfinite(x)) {
4667  if (isinf(x) && isinf(f) && signbit(x) != signbit(f)) {
4668  i = DBL2NUM(f);
4669  x = nan("");
4670  }
4671  memo->v = i;
4672  memo->f = x;
4673  return;
4674  }
4675  else if (isinf(f)) {
4676  return;
4677  }
4678 
4679  double c = memo->c;
4680  double t = f + x;
4681 
4682  if (fabs(f) >= fabs(x)) {
4683  c += ((f - t) + x);
4684  }
4685  else {
4686  c += ((x - t) + f);
4687  }
4688  f = t;
4689 
4690  memo->f = f;
4691  memo->c = c;
4692 }
4693 
4694 static void
4695 sum_iter(VALUE i, struct enum_sum_memo *memo)
4696 {
4697  RUBY_ASSERT(memo != NULL);
4698  if (memo->block_given) {
4699  i = rb_yield(i);
4700  }
4701 
4702  if (memo->float_value) {
4703  sum_iter_Kahan_Babuska(i, memo);
4704  }
4705  else switch (TYPE(memo->v)) {
4706  default: sum_iter_some_value(i, memo); return;
4707  case T_FLOAT: sum_iter_Kahan_Babuska(i, memo); return;
4708  case T_FIXNUM:
4709  case T_BIGNUM:
4710  case T_RATIONAL:
4711  switch (TYPE(i)) {
4712  case T_FIXNUM: sum_iter_fixnum(i, memo); return;
4713  case T_BIGNUM: sum_iter_bignum(i, memo); return;
4714  case T_RATIONAL: sum_iter_rational(i, memo); return;
4715  case T_FLOAT:
4716  sum_iter_normalize_memo(memo);
4717  memo->f = NUM2DBL(memo->v);
4718  memo->c = 0.0;
4719  memo->float_value = 1;
4720  sum_iter_Kahan_Babuska(i, memo);
4721  return;
4722  default:
4723  sum_iter_normalize_memo(memo);
4724  sum_iter_some_value(i, memo);
4725  return;
4726  }
4727  }
4728 }
4729 
4730 static VALUE
4731 enum_sum_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
4732 {
4733  ENUM_WANT_SVALUE();
4734  sum_iter(i, (struct enum_sum_memo *) args);
4735  return Qnil;
4736 }
4737 
4738 static int
4739 hash_sum_i(VALUE key, VALUE value, VALUE arg)
4740 {
4741  sum_iter(rb_assoc_new(key, value), (struct enum_sum_memo *) arg);
4742  return ST_CONTINUE;
4743 }
4744 
4745 static void
4746 hash_sum(VALUE hash, struct enum_sum_memo *memo)
4747 {
4748  RUBY_ASSERT(RB_TYPE_P(hash, T_HASH));
4749  RUBY_ASSERT(memo != NULL);
4750 
4751  rb_hash_foreach(hash, hash_sum_i, (VALUE)memo);
4752 }
4753 
4754 static VALUE
4755 int_range_sum(VALUE beg, VALUE end, int excl, VALUE init)
4756 {
4757  if (excl) {
4758  if (FIXNUM_P(end))
4759  end = LONG2FIX(FIX2LONG(end) - 1);
4760  else
4761  end = rb_big_minus(end, LONG2FIX(1));
4762  }
4763 
4764  if (rb_int_ge(end, beg)) {
4765  VALUE a;
4766  a = rb_int_plus(rb_int_minus(end, beg), LONG2FIX(1));
4767  a = rb_int_mul(a, rb_int_plus(end, beg));
4768  a = rb_int_idiv(a, LONG2FIX(2));
4769  return rb_int_plus(init, a);
4770  }
4771 
4772  return init;
4773 }
4774 
4775 /*
4776  * call-seq:
4777  * sum(initial_value = 0) -> number
4778  * sum(initial_value = 0) {|element| ... } -> object
4779  *
4780  * With no block given,
4781  * returns the sum of +initial_value+ and the elements:
4782  *
4783  * (1..100).sum # => 5050
4784  * (1..100).sum(1) # => 5051
4785  * ('a'..'d').sum('foo') # => "fooabcd"
4786  *
4787  * Generally, the sum is computed using methods <tt>+</tt> and +each+;
4788  * for performance optimizations, those methods may not be used,
4789  * and so any redefinition of those methods may not have effect here.
4790  *
4791  * One such optimization: When possible, computes using Gauss's summation
4792  * formula <em>n(n+1)/2</em>:
4793  *
4794  * 100 * (100 + 1) / 2 # => 5050
4795  *
4796  * With a block given, calls the block with each element;
4797  * returns the sum of +initial_value+ and the block return values:
4798  *
4799  * (1..4).sum {|i| i*i } # => 30
4800  * (1..4).sum(100) {|i| i*i } # => 130
4801  * h = {a: 0, b: 1, c: 2, d: 3, e: 4, f: 5}
4802  * h.sum {|key, value| value.odd? ? value : 0 } # => 9
4803  * ('a'..'f').sum('x') {|c| c < 'd' ? c : '' } # => "xabc"
4804  *
4805  */
4806 static VALUE
4807 enum_sum(int argc, VALUE* argv, VALUE obj)
4808 {
4809  struct enum_sum_memo memo;
4810  VALUE beg, end;
4811  int excl;
4812 
4813  memo.v = (rb_check_arity(argc, 0, 1) == 0) ? LONG2FIX(0) : argv[0];
4814  memo.block_given = rb_block_given_p();
4815  memo.n = 0;
4816  memo.r = Qundef;
4817 
4818  if ((memo.float_value = RB_FLOAT_TYPE_P(memo.v))) {
4819  memo.f = RFLOAT_VALUE(memo.v);
4820  memo.c = 0.0;
4821  }
4822  else {
4823  memo.f = 0.0;
4824  memo.c = 0.0;
4825  }
4826 
4827  if (RTEST(rb_range_values(obj, &beg, &end, &excl))) {
4828  if (!memo.block_given && !memo.float_value &&
4829  (FIXNUM_P(beg) || RB_BIGNUM_TYPE_P(beg)) &&
4830  (FIXNUM_P(end) || RB_BIGNUM_TYPE_P(end))) {
4831  return int_range_sum(beg, end, excl, memo.v);
4832  }
4833  }
4834 
4835  if (RB_TYPE_P(obj, T_HASH) &&
4836  rb_method_basic_definition_p(CLASS_OF(obj), id_each))
4837  hash_sum(obj, &memo);
4838  else
4839  rb_block_call(obj, id_each, 0, 0, enum_sum_i, (VALUE)&memo);
4840 
4841  if (memo.float_value) {
4842  return DBL2NUM(memo.f + memo.c);
4843  }
4844  else {
4845  if (memo.n != 0)
4846  memo.v = rb_fix_plus(LONG2FIX(memo.n), memo.v);
4847  if (!UNDEF_P(memo.r)) {
4848  memo.v = rb_rational_plus(memo.r, memo.v);
4849  }
4850  return memo.v;
4851  }
4852 }
4853 
4854 static VALUE
4855 uniq_func(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
4856 {
4857  ENUM_WANT_SVALUE();
4858  rb_hash_add_new_element(hash, i, i);
4859  return Qnil;
4860 }
4861 
4862 static VALUE
4863 uniq_iter(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
4864 {
4865  ENUM_WANT_SVALUE();
4866  rb_hash_add_new_element(hash, rb_yield_values2(argc, argv), i);
4867  return Qnil;
4868 }
4869 
4870 /*
4871  * call-seq:
4872  * uniq -> array
4873  * uniq {|element| ... } -> array
4874  *
4875  * With no block, returns a new array containing only unique elements;
4876  * the array has no two elements +e0+ and +e1+ such that <tt>e0.eql?(e1)</tt>:
4877  *
4878  * %w[a b c c b a a b c].uniq # => ["a", "b", "c"]
4879  * [0, 1, 2, 2, 1, 0, 0, 1, 2].uniq # => [0, 1, 2]
4880  *
4881  * With a block, returns a new array containing elements only for which the block
4882  * returns a unique value:
4883  *
4884  * a = [0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1]
4885  * a.uniq {|i| i.even? ? i : 0 } # => [0, 2, 4]
4886  * a = %w[a b c d e e d c b a a b c d e]
4887  * a.uniq {|c| c < 'c' } # => ["a", "c"]
4888  *
4889  */
4890 
4891 static VALUE
4892 enum_uniq(VALUE obj)
4893 {
4894  VALUE hash, ret;
4895  rb_block_call_func *const func =
4896  rb_block_given_p() ? uniq_iter : uniq_func;
4897 
4898  hash = rb_obj_hide(rb_hash_new());
4899  rb_block_call(obj, id_each, 0, 0, func, hash);
4900  ret = rb_hash_values(hash);
4901  rb_hash_clear(hash);
4902  return ret;
4903 }
4904 
4905 static VALUE
4906 compact_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
4907 {
4908  ENUM_WANT_SVALUE();
4909 
4910  if (!NIL_P(i)) {
4911  rb_ary_push(ary, i);
4912  }
4913  return Qnil;
4914 }
4915 
4916 /*
4917  * call-seq:
4918  * compact -> array
4919  *
4920  * Returns an array of all non-+nil+ elements:
4921  *
4922  * a = [nil, 0, nil, 'a', false, nil, false, nil, 'a', nil, 0, nil]
4923  * a.compact # => [0, "a", false, false, "a", 0]
4924  *
4925  */
4926 
4927 static VALUE
4928 enum_compact(VALUE obj)
4929 {
4930  VALUE ary;
4931 
4932  ary = rb_ary_new();
4933  rb_block_call(obj, id_each, 0, 0, compact_i, ary);
4934 
4935  return ary;
4936 }
4937 
4938 
4939 /*
4940  * == What's Here
4941  *
4942  * \Module \Enumerable provides methods that are useful to a collection class for:
4943  *
4944  * - {Querying}[rdoc-ref:Enumerable@Methods+for+Querying]
4945  * - {Fetching}[rdoc-ref:Enumerable@Methods+for+Fetching]
4946  * - {Searching and Filtering}[rdoc-ref:Enumerable@Methods+for+Searching+and+Filtering]
4947  * - {Sorting}[rdoc-ref:Enumerable@Methods+for+Sorting]
4948  * - {Iterating}[rdoc-ref:Enumerable@Methods+for+Iterating]
4949  * - {And more....}[rdoc-ref:Enumerable@Other+Methods]
4950  *
4951  * === Methods for Querying
4952  *
4953  * These methods return information about the \Enumerable other than the elements themselves:
4954  *
4955  * - #member? (aliased as #include?): Returns +true+ if <tt>self == object</tt>, +false+ otherwise.
4956  * - #all?: Returns +true+ if all elements meet a specified criterion; +false+ otherwise.
4957  * - #any?: Returns +true+ if any element meets a specified criterion; +false+ otherwise.
4958  * - #none?: Returns +true+ if no element meets a specified criterion; +false+ otherwise.
4959  * - #one?: Returns +true+ if exactly one element meets a specified criterion; +false+ otherwise.
4960  * - #count: Returns the count of elements,
4961  * based on an argument or block criterion, if given.
4962  * - #tally: Returns a new Hash containing the counts of occurrences of each element.
4963  *
4964  * === Methods for Fetching
4965  *
4966  * These methods return entries from the \Enumerable, without modifying it:
4967  *
4968  * <i>Leading, trailing, or all elements</i>:
4969  *
4970  * - #to_a (aliased as #entries): Returns all elements.
4971  * - #first: Returns the first element or leading elements.
4972  * - #take: Returns a specified number of leading elements.
4973  * - #drop: Returns a specified number of trailing elements.
4974  * - #take_while: Returns leading elements as specified by the given block.
4975  * - #drop_while: Returns trailing elements as specified by the given block.
4976  *
4977  * <i>Minimum and maximum value elements</i>:
4978  *
4979  * - #min: Returns the elements whose values are smallest among the elements,
4980  * as determined by <tt>#<=></tt> or a given block.
4981  * - #max: Returns the elements whose values are largest among the elements,
4982  * as determined by <tt>#<=></tt> or a given block.
4983  * - #minmax: Returns a 2-element Array containing the smallest and largest elements.
4984  * - #min_by: Returns the smallest element, as determined by the given block.
4985  * - #max_by: Returns the largest element, as determined by the given block.
4986  * - #minmax_by: Returns the smallest and largest elements, as determined by the given block.
4987  *
4988  * <i>Groups, slices, and partitions</i>:
4989  *
4990  * - #group_by: Returns a Hash that partitions the elements into groups.
4991  * - #partition: Returns elements partitioned into two new Arrays, as determined by the given block.
4992  * - #slice_after: Returns a new Enumerator whose entries are a partition of +self+,
4993  * based either on a given +object+ or a given block.
4994  * - #slice_before: Returns a new Enumerator whose entries are a partition of +self+,
4995  * based either on a given +object+ or a given block.
4996  * - #slice_when: Returns a new Enumerator whose entries are a partition of +self+
4997  * based on the given block.
4998  * - #chunk: Returns elements organized into chunks as specified by the given block.
4999  * - #chunk_while: Returns elements organized into chunks as specified by the given block.
5000  *
5001  * === Methods for Searching and Filtering
5002  *
5003  * These methods return elements that meet a specified criterion:
5004  *
5005  * - #find (aliased as #detect): Returns an element selected by the block.
5006  * - #find_all (aliased as #filter, #select): Returns elements selected by the block.
5007  * - #find_index: Returns the index of an element selected by a given object or block.
5008  * - #reject: Returns elements not rejected by the block.
5009  * - #uniq: Returns elements that are not duplicates.
5010  *
5011  * === Methods for Sorting
5012  *
5013  * These methods return elements in sorted order:
5014  *
5015  * - #sort: Returns the elements, sorted by <tt>#<=></tt> or the given block.
5016  * - #sort_by: Returns the elements, sorted by the given block.
5017  *
5018  * === Methods for Iterating
5019  *
5020  * - #each_entry: Calls the block with each successive element
5021  * (slightly different from #each).
5022  * - #each_with_index: Calls the block with each successive element and its index.
5023  * - #each_with_object: Calls the block with each successive element and a given object.
5024  * - #each_slice: Calls the block with successive non-overlapping slices.
5025  * - #each_cons: Calls the block with successive overlapping slices.
5026  * (different from #each_slice).
5027  * - #reverse_each: Calls the block with each successive element, in reverse order.
5028  *
5029  * === Other Methods
5030  *
5031  * - #collect (aliased as #map): Returns objects returned by the block.
5032  * - #filter_map: Returns truthy objects returned by the block.
5033  * - #flat_map (aliased as #collect_concat): Returns flattened objects returned by the block.
5034  * - #grep: Returns elements selected by a given object
5035  * or objects returned by a given block.
5036  * - #grep_v: Returns elements selected by a given object
5037  * or objects returned by a given block.
5038  * - #inject (aliased as #reduce): Returns the object formed by combining all elements.
5039  * - #sum: Returns the sum of the elements, using method <tt>+</tt>.
5040  * - #zip: Combines each element with elements from other enumerables;
5041  * returns the n-tuples or calls the block with each.
5042  * - #cycle: Calls the block with each element, cycling repeatedly.
5043  *
5044  * == Usage
5045  *
5046  * To use module \Enumerable in a collection class:
5047  *
5048  * - Include it:
5049  *
5050  * include Enumerable
5051  *
5052  * - Implement method <tt>#each</tt>
5053  * which must yield successive elements of the collection.
5054  * The method will be called by almost any \Enumerable method.
5055  *
5056  * Example:
5057  *
5058  * class Foo
5059  * include Enumerable
5060  * def each
5061  * yield 1
5062  * yield 1, 2
5063  * yield
5064  * end
5065  * end
5066  * Foo.new.each_entry{ |element| p element }
5067  *
5068  * Output:
5069  *
5070  * 1
5071  * [1, 2]
5072  * nil
5073  *
5074  * == \Enumerable in Ruby Classes
5075  *
5076  * These Ruby core classes include (or extend) \Enumerable:
5077  *
5078  * - ARGF
5079  * - Array
5080  * - Dir
5081  * - Enumerator
5082  * - ENV (extends)
5083  * - Hash
5084  * - IO
5085  * - Range
5086  * - Struct
5087  *
5088  * These Ruby standard library classes include \Enumerable:
5089  *
5090  * - CSV
5091  * - CSV::Table
5092  * - CSV::Row
5093  * - Set
5094  *
5095  * Virtually all methods in \Enumerable call method +#each+ in the including class:
5096  *
5097  * - <tt>Hash#each</tt> yields the next key-value pair as a 2-element Array.
5098  * - <tt>Struct#each</tt> yields the next name-value pair as a 2-element Array.
5099  * - For the other classes above, +#each+ yields the next object from the collection.
5100  *
5101  * == About the Examples
5102  *
5103  * The example code snippets for the \Enumerable methods:
5104  *
5105  * - Always show the use of one or more Array-like classes (often Array itself).
5106  * - Sometimes show the use of a Hash-like class.
5107  * For some methods, though, the usage would not make sense,
5108  * and so it is not shown. Example: #tally would find exactly one of each Hash entry.
5109  *
5110  */
5111 
5112 void
5113 Init_Enumerable(void)
5114 {
5115  rb_mEnumerable = rb_define_module("Enumerable");
5116 
5117  rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
5118  rb_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
5119  rb_define_method(rb_mEnumerable, "to_h", enum_to_h, -1);
5120 
5121  rb_define_method(rb_mEnumerable, "sort", enum_sort, 0);
5122  rb_define_method(rb_mEnumerable, "sort_by", enum_sort_by, 0);
5123  rb_define_method(rb_mEnumerable, "grep", enum_grep, 1);
5124  rb_define_method(rb_mEnumerable, "grep_v", enum_grep_v, 1);
5125  rb_define_method(rb_mEnumerable, "count", enum_count, -1);
5126  rb_define_method(rb_mEnumerable, "find", enum_find, -1);
5127  rb_define_method(rb_mEnumerable, "detect", enum_find, -1);
5128  rb_define_method(rb_mEnumerable, "find_index", enum_find_index, -1);
5129  rb_define_method(rb_mEnumerable, "find_all", enum_find_all, 0);
5130  rb_define_method(rb_mEnumerable, "select", enum_find_all, 0);
5131  rb_define_method(rb_mEnumerable, "filter", enum_find_all, 0);
5132  rb_define_method(rb_mEnumerable, "filter_map", enum_filter_map, 0);
5133  rb_define_method(rb_mEnumerable, "reject", enum_reject, 0);
5134  rb_define_method(rb_mEnumerable, "collect", enum_collect, 0);
5135  rb_define_method(rb_mEnumerable, "map", enum_collect, 0);
5136  rb_define_method(rb_mEnumerable, "flat_map", enum_flat_map, 0);
5137  rb_define_method(rb_mEnumerable, "collect_concat", enum_flat_map, 0);
5138  rb_define_method(rb_mEnumerable, "inject", enum_inject, -1);
5139  rb_define_method(rb_mEnumerable, "reduce", enum_inject, -1);
5140  rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
5141  rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
5142  rb_define_method(rb_mEnumerable, "tally", enum_tally, -1);
5143  rb_define_method(rb_mEnumerable, "first", enum_first, -1);
5144  rb_define_method(rb_mEnumerable, "all?", enum_all, -1);
5145  rb_define_method(rb_mEnumerable, "any?", enum_any, -1);
5146  rb_define_method(rb_mEnumerable, "one?", enum_one, -1);
5147  rb_define_method(rb_mEnumerable, "none?", enum_none, -1);
5148  rb_define_method(rb_mEnumerable, "min", enum_min, -1);
5149  rb_define_method(rb_mEnumerable, "max", enum_max, -1);
5150  rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
5151  rb_define_method(rb_mEnumerable, "min_by", enum_min_by, -1);
5152  rb_define_method(rb_mEnumerable, "max_by", enum_max_by, -1);
5153  rb_define_method(rb_mEnumerable, "minmax_by", enum_minmax_by, 0);
5154  rb_define_method(rb_mEnumerable, "member?", enum_member, 1);
5155  rb_define_method(rb_mEnumerable, "include?", enum_member, 1);
5156  rb_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, -1);
5157  rb_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1);
5158  rb_define_method(rb_mEnumerable, "each_entry", enum_each_entry, -1);
5159  rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
5160  rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
5161  rb_define_method(rb_mEnumerable, "each_with_object", enum_each_with_object, 1);
5162  rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
5163  rb_define_method(rb_mEnumerable, "take", enum_take, 1);
5164  rb_define_method(rb_mEnumerable, "take_while", enum_take_while, 0);
5165  rb_define_method(rb_mEnumerable, "drop", enum_drop, 1);
5166  rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
5167  rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
5168  rb_define_method(rb_mEnumerable, "chunk", enum_chunk, 0);
5169  rb_define_method(rb_mEnumerable, "slice_before", enum_slice_before, -1);
5170  rb_define_method(rb_mEnumerable, "slice_after", enum_slice_after, -1);
5171  rb_define_method(rb_mEnumerable, "slice_when", enum_slice_when, 0);
5172  rb_define_method(rb_mEnumerable, "chunk_while", enum_chunk_while, 0);
5173  rb_define_method(rb_mEnumerable, "sum", enum_sum, -1);
5174  rb_define_method(rb_mEnumerable, "uniq", enum_uniq, 0);
5175  rb_define_method(rb_mEnumerable, "compact", enum_compact, 0);
5176 
5177  id__alone = rb_intern_const("_alone");
5178  id__separator = rb_intern_const("_separator");
5179  id_chunk_categorize = rb_intern_const("chunk_categorize");
5180  id_chunk_enumerable = rb_intern_const("chunk_enumerable");
5181  id_next = rb_intern_const("next");
5182  id_sliceafter_enum = rb_intern_const("sliceafter_enum");
5183  id_sliceafter_pat = rb_intern_const("sliceafter_pat");
5184  id_sliceafter_pred = rb_intern_const("sliceafter_pred");
5185  id_slicebefore_enumerable = rb_intern_const("slicebefore_enumerable");
5186  id_slicebefore_sep_pat = rb_intern_const("slicebefore_sep_pat");
5187  id_slicebefore_sep_pred = rb_intern_const("slicebefore_sep_pred");
5188  id_slicewhen_enum = rb_intern_const("slicewhen_enum");
5189  id_slicewhen_inverted = rb_intern_const("slicewhen_inverted");
5190  id_slicewhen_pred = rb_intern_const("slicewhen_pred");
5191 }
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition: assert.h:219
VALUE rb_define_module(const char *name)
Defines a top-level module.
Definition: class.c:1095
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
Definition: class.c:2635
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
Definition: class.c:2142
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:916
#define TYPE(_)
Old name of rb_type.
Definition: value_type.h:108
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
Definition: value_type.h:87
#define RFLOAT_VALUE
Old name of rb_float_value.
Definition: double.h:28
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition: long.h:48
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
Definition: assume.h:28
#define T_FLOAT
Old name of RUBY_T_FLOAT.
Definition: value_type.h:64
#define ID2SYM
Old name of RB_ID2SYM.
Definition: symbol.h:44
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
Definition: value_type.h:57
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define ULONG2NUM
Old name of RB_ULONG2NUM.
Definition: long.h:60
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
Definition: value_type.h:63
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
Definition: assume.h:29
#define SYM2ID
Old name of RB_SYM2ID.
Definition: symbol.h:45
#define FIXNUM_FLAG
Old name of RUBY_FIXNUM_FLAG.
#define CLASS_OF
Old name of rb_class_of.
Definition: globals.h:203
#define rb_ary_new4
Old name of rb_ary_new_from_values.
Definition: array.h:659
#define FIXABLE
Old name of RB_FIXABLE.
Definition: fixnum.h:25
#define LONG2FIX
Old name of RB_INT2FIX.
Definition: long.h:49
#define FIX2ULONG
Old name of RB_FIX2ULONG.
Definition: long.h:47
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
Definition: value_type.h:76
#define T_HASH
Old name of RUBY_T_HASH.
Definition: value_type.h:65
#define NUM2DBL
Old name of rb_num2dbl.
Definition: double.h:27
#define rb_ary_new3
Old name of rb_ary_new_from_args.
Definition: array.h:658
#define LONG2NUM
Old name of RB_LONG2NUM.
Definition: long.h:50
#define T_UNDEF
Old name of RUBY_T_UNDEF.
Definition: value_type.h:82
#define Qtrue
Old name of RUBY_Qtrue.
#define FIXNUM_MAX
Old name of RUBY_FIXNUM_MAX.
Definition: fixnum.h:26
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
Definition: long.h:46
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition: value_type.h:56
#define NIL_P
Old name of RB_NIL_P.
#define DBL2NUM
Old name of rb_float_new.
Definition: double.h:29
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition: long.h:51
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define CONST_ID
Old name of RUBY_CONST_ID.
Definition: symbol.h:47
#define rb_ary_new2
Old name of rb_ary_new_capa.
Definition: array.h:657
#define SYMBOL_P
Old name of RB_SYMBOL_P.
Definition: value_type.h:88
#define T_REGEXP
Old name of RUBY_T_REGEXP.
Definition: value_type.h:77
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition: error.c:3627
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:945
void rb_iter_break(void)
Breaks from a block.
Definition: vm.c:2067
VALUE rb_eTypeError
TypeError exception.
Definition: error.c:1403
VALUE rb_eRuntimeError
RuntimeError exception.
Definition: error.c:1401
VALUE rb_eStopIteration
StopIteration exception.
Definition: enumerator.c:181
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition: error.c:465
VALUE rb_eArgError
ArgumentError exception.
Definition: error.c:1404
void rb_warning(const char *fmt,...)
Issues a warning.
Definition: error.c:496
VALUE rb_cArray
Array class.
Definition: array.c:40
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
Definition: object.c:2091
VALUE rb_mEnumerable
Enumerable module.
Definition: enum.c:27
VALUE rb_cEnumerator
Enumerator class.
Definition: enumerator.c:163
VALUE rb_cInteger
Module class.
Definition: numeric.c:198
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition: object.c:104
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition: object.c:247
double rb_num2dbl(VALUE num)
Converts an instance of rb_cNumeric into C's double.
Definition: object.c:3684
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition: object.c:179
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
Definition: gc.h:615
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
Definition: gc.h:603
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition: vm_eval.c:1099
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
Definition: vm_eval.c:1058
VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it only takes public methods into account.
Definition: vm_eval.c:1150
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
Identical to rb_ary_new_from_args(), except how objects are passed.
Definition: array.c:786
VALUE rb_ary_concat(VALUE lhs, VALUE rhs)
Destructively appends the contents of latter into the end of former.
Definition: array.c:4981
VALUE rb_ary_reverse(VALUE ary)
Destructively reverses the passed array in-place.
Definition: array.c:3119
VALUE rb_ary_shift(VALUE ary)
Destructively deletes an element from the beginning of the passed array and returns what was deleted.
Definition: array.c:1496
VALUE rb_ary_dup(VALUE ary)
Duplicates an array.
Definition: array.c:2777
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
Definition: array.c:1014
VALUE rb_ary_new(void)
Allocates a new, empty array.
Definition: array.c:747
VALUE rb_ary_resize(VALUE ary, long len)
Expands or shrinks the passed array to the passed length.
Definition: array.c:2296
VALUE rb_ary_hidden_new(long capa)
Allocates a hidden (no class) empty array.
Definition: array.c:859
VALUE rb_ary_clear(VALUE ary)
Destructively removes everything form an array.
Definition: array.c:4642
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
Definition: array.c:1384
VALUE rb_ary_sort_bang(VALUE ary)
Destructively sorts the passed array in-place, according to each elements' <=> result.
Definition: array.c:3394
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
Definition: array.c:1001
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
Definition: array.c:1207
VALUE rb_big_minus(VALUE x, VALUE y)
Performs subtraction of the passed two objects.
Definition: bignum.c:5881
VALUE rb_big_plus(VALUE x, VALUE y)
Performs addition of the passed two objects.
Definition: bignum.c:5852
VALUE rb_big_unpack(unsigned long *buf, long num_longs)
Constructs a (possibly very big) bignum from a series of integers.
Definition: bignum.c:3265
double rb_big2dbl(VALUE x)
Converts a bignum into C's double.
Definition: bignum.c:5346
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Canonicalises the passed val, which is the return value of a <=> b, into C's {-1, 0,...
Definition: bignum.c:2965
VALUE rb_enum_values_pack(int argc, const VALUE *argv)
Basically identical to rb_ary_new_form_values(), except it returns something different when argc < 2.
Definition: enum.c:53
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
Definition: enumerator.h:206
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
Definition: enumerator.h:239
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition: error.h:284
void rb_hash_foreach(VALUE hash, int(*func)(VALUE key, VALUE val, VALUE arg), VALUE arg)
Iterates over a hash.
VALUE rb_hash_aref(VALUE hash, VALUE key)
Queries the given key in the given hash table.
Definition: hash.c:2073
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Inserts or replaces ("upsert"s) the objects into the given hash table.
Definition: hash.c:2893
VALUE rb_hash_clear(VALUE hash)
Swipes everything out of the passed hash table.
Definition: hash.c:2820
VALUE rb_hash_new(void)
Creates a new, empty hash object.
Definition: hash.c:1475
VALUE rb_block_proc(void)
Constructs a Proc object from implicitly passed components.
Definition: proc.c:813
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Deconstructs a range into its components.
Definition: range.c:1754
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition: string.c:2845
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
Definition: variable.c:1358
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
Definition: variable.c:1859
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
Definition: variable.c:1350
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
Definition: vm_method.c:2955
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well...
Definition: vm_method.c:2833
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
Definition: vm_eval.c:668
int rb_obj_respond_to(VALUE obj, ID mid, int private_p)
Identical to rb_respond_to(), except it additionally takes the visibility parameter.
Definition: vm_method.c:2939
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition: symbol.h:276
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
Definition: symbol.c:1117
VALUE rb_sym2str(VALUE id)
Identical to rb_id2str(), except it takes an instance of rb_cSymbol rather than an ID.
Definition: symbol.c:970
char * ptr
Pointer to the underlying memory region, of at least capa bytes.
Definition: io.h:2
int len
Length of the buffer.
Definition: io.h:8
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
Reentrant implementation of quick sort.
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
Definition: iterator.h:58
VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2)
Identical to rb_funcallv(), except it additionally passes a function as a block.
Definition: vm_eval.c:1534
VALUE rb_yield_values(int n,...)
Identical to rb_yield(), except it takes variadic number of parameters and pass them to the block.
Definition: vm_eval.c:1366
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
Definition: vm_eval.c:1388
VALUE rb_yield(VALUE val)
Yields the block.
Definition: vm_eval.c:1354
rb_block_call_func * rb_block_call_func_t
Shorthand type that represents an iterator-written-in-C function pointer.
Definition: iterator.h:88
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
This is the type of a function that the interpreter expect for C-backended blocks.
Definition: iterator.h:83
VALUE rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2, int kw_splat)
Identical to rb_funcallv_kw(), except it additionally passes a function as a block.
Definition: vm_eval.c:1541
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition: memory.h:162
static VALUE * RARRAY_PTR(VALUE ary)
Wild use of a C pointer.
Definition: rarray.h:366
#define RARRAY_LEN
Just another name of rb_array_len.
Definition: rarray.h:51
static void RARRAY_ASET(VALUE ary, long i, VALUE v)
Assigns an object in an array.
Definition: rarray.h:386
#define RARRAY_PTR_USE(ary, ptr_name, expr)
Declares a section of code where raw pointers are used.
Definition: rarray.h:348
#define RARRAY_AREF(a, i)
Definition: rarray.h:403
#define RBASIC(obj)
Convenient casting macro.
Definition: rbasic.h:40
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
Definition: rstring.h:416
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
Definition: scan_args.h:78
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
Definition: stdarg.h:35
MEMO.
Definition: imemo.h:109
Definition: enum.c:2399
Definition: enum.c:2276
IFUNC (Internal FUNCtion)
Definition: imemo.h:88
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
Definition: value.h:63
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition: value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
Definition: value_type.h:264
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition: value_type.h:433
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition: value_type.h:376