#include "ruby.h" static inline VALUE ary_make_hash(ary1, ary2) VALUE ary1, ary2; { VALUE hash = rb_hash_new(); long i; for (i=0; i<RARRAY_LEN(ary1); i++) { rb_hash_aset(hash, rb_ary_entry(ary1,i), Qtrue); } if (ary2) { for (i=0; i<RARRAY_LEN(ary2); i++) { rb_hash_aset(hash, rb_ary_entry(ary2, i), Qtrue); } } return hash; } static inline VALUE rb_ary_length(VALUE ary) { long length = RARRAY_LEN(ary); return LONG2NUM(length); } // This version: // * orders the arrays by ascending size, small to large. // * calls the & consecutively for all arrays. // static inline VALUE memory_efficient_intersect(VALUE self, VALUE unsorted_array_of_arrays) { // Counters. // long i, j; // Vars. // VALUE rb_array_of_arrays; VALUE smallest_array; VALUE current_array; VALUE hash; // Temps. // VALUE v; // Conversions & presorting. // rb_array_of_arrays = rb_block_call(unsorted_array_of_arrays, rb_intern("sort_by!"), 0, 0, rb_ary_length, 0); smallest_array = rb_ary_dup(rb_ary_entry(rb_array_of_arrays, 0)); // Iterate through all arrays. // for (i = 1; i < RARRAY_LEN(rb_array_of_arrays); i++) { // Break if the smallest array is empty // if (RARRAY_LEN(smallest_array) == 0) { break; } // Make a hash from the currently smallest version. // hash = ary_make_hash(smallest_array, 0); // Clear for use as temp array. // rb_ary_clear(smallest_array); // Iterate through all array elements. // current_array = rb_ary_entry(rb_array_of_arrays, i); for (j = 0; j < RARRAY_LEN(current_array); j++) { v = rb_ary_entry(current_array, j); if (rb_hash_delete(hash, v) != Qnil) { rb_ary_push(smallest_array, v); } } } return smallest_array; } VALUE p_mPerformant, p_cArray; void Init_picky() { p_mPerformant = rb_define_module("Performant"); p_cArray = rb_define_class_under(p_mPerformant, "Array", rb_cObject); rb_define_singleton_method(p_cArray, "memory_efficient_intersect", memory_efficient_intersect, 1); }