@@ -1409,6 +1409,76 @@ mrb_ary_delete(mrb_state *mrb, mrb_value self)
14091409return ret;
14101410}
141114111412+static mrb_bool
1413+sort_cmp(mrb_state *mrb, mrb_value *p, mrb_int a, mrb_int b, mrb_value blk)
1414+{
1415+mrb_int cmp;
1416+1417+if (mrb_nil_p(blk)) {
1418+cmp = mrb_cmp(mrb, p[a], p[b]);
1419+ }
1420+else {
1421+mrb_value c = mrb_funcall_id(mrb, blk, MRB_SYM(call), 2, p[a], p[b]);
1422+if (mrb_nil_p(c) || !mrb_fixnum_p(c)) {
1423+mrb_raisef(mrb, E_ARGUMENT_ERROR, "comparison of %!v and %!v failed", p[a], p[b]);
1424+ }
1425+cmp = mrb_fixnum(c);
1426+ }
1427+return cmp > 0;
1428+}
1429+1430+static void
1431+heapify(mrb_state *mrb, mrb_value *a, mrb_int index, mrb_int size, mrb_value blk)
1432+{
1433+mrb_int max = index;
1434+mrb_int left_index = 2 * index + 1;
1435+mrb_int right_index = left_index + 1;
1436+if (left_index < size && sort_cmp(mrb, a, left_index, max, blk)) {
1437+max = left_index;
1438+ }
1439+if (right_index < size && sort_cmp(mrb, a, right_index, max, blk)) {
1440+max = right_index;
1441+ }
1442+if (max != index) {
1443+mrb_value tmp = a[max];
1444+a[max] = a[index];
1445+a[index] = tmp;
1446+heapify(mrb, a, max, size, blk);
1447+ }
1448+}
1449+1450+/*
1451+ * call-seq:
1452+ * array.sort! -> self
1453+ * array.sort! {|a, b| ... } -> self
1454+ *
1455+ * Sort all elements and replace +self+ with these
1456+ * elements.
1457+ */
1458+static mrb_value
1459+mrb_ary_sort_bang(mrb_state *mrb, mrb_value ary)
1460+{
1461+mrb_value blk;
1462+1463+mrb_int n = RARRAY_LEN(ary);
1464+if (n < 2) return ary;
1465+1466+ary_modify(mrb, mrb_ary_ptr(ary));
1467+mrb_get_args(mrb, "&", &blk);
1468+1469+mrb_value *a = RARRAY_PTR(ary);
1470+for (mrb_int i = n / 2 - 1; i > -1; i--) {
1471+heapify(mrb, a, i, n, blk);
1472+ }
1473+for (mrb_int i = n - 1; i > 0; i--) {
1474+mrb_value tmp = a[0];
1475+a[0] = a[i];
1476+a[i] = tmp;
1477+heapify(mrb, a, 0, i, blk);
1478+ }
1479+return ary;
1480+}
1481+14121482void
14131483mrb_init_array(mrb_state *mrb)
14141484{
@@ -1446,6 +1516,7 @@ mrb_init_array(mrb_state *mrb)
14461516mrb_define_method_id(mrb, a, MRB_SYM(unshift), mrb_ary_unshift_m, MRB_ARGS_ANY()); /* 15.2.12.5.30 */
14471517mrb_define_method_id(mrb, a, MRB_SYM(to_s), mrb_ary_to_s, MRB_ARGS_NONE());
14481518mrb_define_method_id(mrb, a, MRB_SYM(inspect), mrb_ary_to_s, MRB_ARGS_NONE());
1519+mrb_define_method_id(mrb, a, MRB_SYM_B(sort), mrb_ary_sort_bang, MRB_ARGS_NONE());
1449152014501521mrb_define_method_id(mrb, a, MRB_SYM(__ary_eq), mrb_ary_eq, MRB_ARGS_REQ(1));
14511522mrb_define_method_id(mrb, a, MRB_SYM(__ary_cmp), mrb_ary_cmp, MRB_ARGS_REQ(1));