1 3 package org.python.core; 4 5 12 class MergeState { 13 20 static final int MAX_MERGE_PENDING = 85; 21 22 27 static final int MIN_GALLOP = 8; 28 29 32 static final int MERGESTATE_TEMP_SIZE = 256; 33 34 private PyObject[] a = new PyObject[MERGESTATE_TEMP_SIZE]; 35 36 private int[] base = new int[MAX_MERGE_PENDING]; 37 private int[] len = new int[MAX_MERGE_PENDING]; 38 39 private PyObject compare; 40 private PyObject[] data; 41 private int size; 42 private int n; 43 44 MergeState(PyObject[] data, int size, PyObject compare) { 45 this.data = data; 46 this.compare = compare; 47 this.size = size; 48 this.n = 0; 49 } 50 51 public void sort() { 52 int nremaining = size; 53 if (nremaining < 2) { 54 return; 55 } 56 57 int lo = 0; 58 int hi = nremaining; 59 int minrun = merge_compute_minrun(nremaining); 60 61 boolean[] descending = new boolean[1]; 62 do { 63 64 int n = count_run(lo, hi, descending); 65 if (descending[0]) 66 reverse_slice(lo, lo + n); 67 68 if (n < minrun) { 69 int force = nremaining < minrun ? nremaining : minrun; 70 binarysort(lo, lo + force, lo + n); 71 n = force; 72 } 73 74 base[this.n] = lo; 76 len[this.n] = n; 77 ++this.n; 78 merge_collapse(); 79 80 lo += n; 81 nremaining -= n; 82 } while (nremaining != 0); 83 85 merge_force_collapse(); 86 } 90 91 public void getmem(int need) { 92 if (need <= a.length) 93 return; 94 a = new PyObject[need]; 95 } 96 97 int count_run(int lo, int hi, boolean[] descending) { 98 descending[0] = false; 100 ++lo; 101 if (lo == hi) 102 return 1; 103 int n = 2; 104 if (iflt(data[lo], data[lo-1])) { 105 descending[0] = true; 106 for (lo = lo + 1; lo < hi; ++lo, ++n) { 107 if (! iflt(data[lo], data[lo-1])) 108 break; 109 } 110 } else { 111 for (lo = lo + 1; lo < hi; ++lo, ++n) { 112 if (iflt(data[lo], data[lo-1])) 113 break; 114 } 115 } 116 return n; 117 } 118 119 120 void merge_lo(int pa, int na, int pb, int nb) { 121 int cnt = nb + na; 123 int origpa = pa; 124 127 getmem(na); 129 System.arraycopy(data, pa, a, 0, na); 130 int dest = pa; 131 pa = 0; 132 133 data[dest++] = data[pb++]; 134 --nb; 135 if (nb == 0) 136 return; 137 if (na == 1) { 138 System.arraycopy(data, pb, data, dest, nb); 140 data[dest + nb] = a[pa]; 141 return; 142 } 143 144 try { 145 PyObject compare = this.compare; 146 for (;;) { 147 int acount = 0; 148 int bcount = 0; 149 150 153 for (;;) { 154 boolean k = iflt(data[pb], a[pa]); 155 if (k) { 156 data[dest++] = data[pb++]; 157 ++bcount; 158 acount = 0; 159 --nb; 160 if (nb == 0) 161 return; 162 if (bcount >= MIN_GALLOP) 163 break; 164 } else { 165 data[dest++] = a[pa++]; 166 ++acount; 167 bcount = 0; 168 --na; 169 if (na == 1) { 170 System.arraycopy(data, pb, data, dest, nb); 172 data[dest + nb] = a[pa]; 173 na = 0; 174 return; 175 } 176 if (acount >= MIN_GALLOP) 177 break; 178 } 179 } 180 181 186 do { 187 int k = gallop_right(data[pb], a, pa, na, 0); 188 acount = k; 189 if (k != 0) { 190 System.arraycopy(a, pa, data, dest, k); 191 dest += k; 192 pa += k; 193 na -= k; 194 if (na == 1) { 195 System.arraycopy(data, pb, data, dest, nb); 197 data[dest + nb] = a[pa]; 198 na = 0; 199 return; 200 } 201 205 if (na == 0) 206 return; 207 } 208 209 data[dest++] = data[pb++]; 210 --nb; 211 if (nb == 0) 212 return; 213 214 k = gallop_left(a[pa], data, pb, nb, 0); 215 bcount = k; 216 if (k != 0) { 217 System.arraycopy(data, pb, data, dest, k); 218 dest += k; 219 pb += k; 220 nb -= k; 221 if (nb == 0) 222 return; 223 } 224 data[dest++] = a[pa++]; 225 --na; 226 if (na == 1) { 227 System.arraycopy(data, pb, data, dest, nb); 229 data[dest + nb] = a[pa]; 230 na = 0; 231 return; 232 } 233 } while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP); 234 } 235 } finally { 236 if (na != 0) 237 System.arraycopy(a, pa, data, dest, na); 238 239 } 241 } 242 243 244 245 void merge_hi(int pa, int na, int pb, int nb) { 246 int cnt = nb + na; 248 int origpa = pa; 249 252 getmem(nb); 254 int dest = pb + nb - 1; 255 int basea = pa; 256 System.arraycopy(data, pb, a, 0, nb); 257 258 pb = nb - 1; 259 pa += na - 1; 260 261 data[dest--] = data[pa--]; 262 --na; 263 if (na == 0) 264 return; 265 if (nb == 1) { 266 dest -= na; 268 pa -= na; 269 System.arraycopy(data, pa+1, data, dest+1, na); 270 data[dest] = a[pb]; 271 nb = 0; 272 return; 273 } 274 275 try { 276 PyObject compare = this.compare; 277 for (;;) { 278 int acount = 0; 279 int bcount = 0; 280 281 284 for (;;) { 285 boolean k = iflt(a[pb], data[pa]); 286 if (k) { 287 data[dest--] = data[pa--]; 288 ++acount; 289 bcount = 0; 290 --na; 291 if (na == 0) 292 return; 293 if (acount >= MIN_GALLOP) 294 break; 295 } else { 296 data[dest--] = a[pb--]; 297 ++bcount; 298 acount = 0; 299 --nb; 300 if (nb == 1) { 301 dest -= na; 303 pa -= na; 304 System.arraycopy(data, pa+1, data, dest+1, na); 305 data[dest] = a[pb]; 306 nb = 0; 307 return; 308 } 309 if (bcount >= MIN_GALLOP) 310 break; 311 } 312 } 313 314 319 do { 320 int k = gallop_right(a[pb], data, basea, na, na-1); 321 acount = k = na - k; 322 if (k != 0) { 323 dest -= k; 324 pa -= k; 325 System.arraycopy(data, pa+1, data, dest+1, k); 326 na -= k; 327 if (na == 0) 328 return; 329 } 330 331 data[dest--] = a[pb--]; 332 --nb; 333 if (nb == 1) { 334 dest -= na; 336 pa -= na; 337 System.arraycopy(data, pa+1, data, dest+1, na); 338 data[dest] = a[pb]; 339 nb = 0; 340 return; 341 } 342 343 k = gallop_left(data[pa], a, 0, nb, nb-1); 344 bcount = k = nb - k; 345 if (k != 0) { 346 dest -= k; 347 pb -= k; 348 System.arraycopy(a, pb+1, data, dest+1, k); 349 nb -= k; 350 if (nb == 1) { 351 dest -= na; 353 pa -= na; 354 System.arraycopy(data, pa+1, data, dest+1, na); 355 data[dest] = a[pb]; 356 nb = 0; 357 return; 358 } 359 363 if (nb == 0) 364 return; 365 } 366 data[dest--] = data[pa--]; 367 --na; 368 if (na == 0) 369 return; 370 } while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP); 371 } 372 } finally { 373 if (nb != 0) 374 System.arraycopy(a, 0, data, dest-(nb-1), nb); 375 376 } 378 } 379 380 381 382 403 404 private int gallop_left(PyObject key, PyObject[] data, int a, int n, 405 int hint) 406 { 407 a += hint; 409 int ofs = 1; 410 int lastofs = 0; 411 412 if (iflt(data[a], key)) { 413 416 int maxofs = n - hint; while (ofs < maxofs) { 418 if (iflt(data[a + ofs], key)) { 419 lastofs = ofs; 420 ofs = (ofs << 1) + 1; 421 if (ofs <= 0) ofs = maxofs; 423 } else { 424 break; 426 } 427 } 428 if (ofs > maxofs) 429 ofs = maxofs; 430 lastofs += hint; 432 ofs += hint; 433 } else { 434 437 int maxofs = hint + 1; while (ofs < maxofs) { 439 if (iflt(data[a - ofs], key)) 440 break; 441 lastofs = ofs; 443 ofs = (ofs << 1) + 1; 444 if (ofs <= 0) ofs = maxofs; 446 } 447 if (ofs > maxofs) 448 ofs = maxofs; 449 int k = lastofs; 451 lastofs = hint - ofs; 452 ofs = hint - k; 453 } 454 a -= hint; 455 460 ++lastofs; 461 while (lastofs < ofs) { 462 int m = lastofs + ((ofs - lastofs) >> 1); 463 if (iflt(data[a + m], key)) 464 lastofs = m+1; else 466 ofs = m; } 468 return ofs; 470 } 471 472 473 485 486 private int gallop_right(PyObject key, PyObject[] data, int a, int n, 487 int hint) 488 { 489 a += hint; 491 int lastofs = 0; 492 int ofs = 1; 493 494 if (iflt(key, data[a])) { 495 498 int maxofs = hint + 1; 499 while (ofs < maxofs) { 500 if (iflt(key, data[a - ofs])) { 501 lastofs = ofs; 502 ofs = (ofs << 1) + 1; 503 if (ofs <= 0) ofs = maxofs; 505 } else { 506 507 break; 508 } 509 } 510 if (ofs > maxofs) 511 ofs = maxofs; 512 513 int k = lastofs; 514 lastofs = hint - ofs; 515 ofs = hint - k; 516 } else { 517 520 int maxofs = n - hint; 521 while (ofs < maxofs) { 522 if (iflt(key, data[a + ofs])) 523 break; 524 525 lastofs = ofs; 526 ofs = (ofs << 1) + 1; 527 if (ofs <= 0) 528 ofs = maxofs; 529 } 530 if (ofs > maxofs) 531 ofs = maxofs; 532 533 lastofs += hint; 534 ofs += hint; 535 } 536 a -= hint; 537 538 540 544 ++lastofs; 545 while (lastofs < ofs) { 546 int m = lastofs + ((ofs - lastofs) >> 1); 547 if (iflt(key, data[a + m])) 548 ofs = m; else 550 lastofs = m+1; } 552 return ofs; 554 } 555 556 557 void merge_at(int i) { 558 562 int pa = base[i]; 563 int pb = base[i+1]; 564 int na = len[i]; 565 int nb = len[i+1]; 566 567 570 if (i == n - 3) { 574 len[i+1] = len[i+2]; 575 base[i+1] = base[i+2]; 576 } 577 len[i] = na + nb; 578 --n; 579 580 int k = gallop_right(data[pb], data, pa, na, 0); 583 pa += k; 584 na -= k; 585 if (na == 0) 586 return; 587 588 nb = gallop_left(data[pa + na - 1], data, pb, nb, nb-1); 591 if (nb == 0) 592 return; 593 594 if (na <= nb) 597 merge_lo(pa, na, pb, nb); 598 else 599 merge_hi(pa, na, pb, nb); 600 } 601 602 603 611 void merge_collapse() { 612 while (this.n > 1) { 613 int n = this.n - 2; 614 if (n > 0 && len[n-1] <= len[n] + len[n+1]) { 615 if (len[n-1] < len[n+1]) 616 --n; 617 merge_at(n); 618 } else if (len[n] <= len[n+1]) { 619 merge_at(n); 620 } else { 621 break; 622 } 623 } 624 } 625 626 627 632 void merge_force_collapse() { 633 while (this.n > 1) { 634 int n = this.n - 2; 635 if (n > 0 && len[n-1] < len[n+1]) 636 --n; 637 merge_at(n); 638 } 639 } 640 641 642 652 int merge_compute_minrun(int n) { 653 int r = 0; 655 while (n >= 64) { 657 r |= n & 1; 658 n >>= 1; 659 } 660 return n + r; 661 } 662 663 664 void assert_(boolean expr) { 665 if (!expr) 666 throw new RuntimeException ("assert"); 667 } 668 669 670 private boolean iflt(PyObject x, PyObject y) { 671 674 if (compare == null) { 675 680 return x._lt(y).__nonzero__(); 681 } 682 683 PyObject ret = compare.__call__(x, y); 684 685 if (ret instanceof PyInteger) { 686 int v = ((PyInteger)ret).getValue(); 687 return v < 0; 688 } 689 throw Py.TypeError("comparision function must return int"); 690 } 691 692 693 void reverse_slice(int lo, int hi) { 694 --hi; 695 while (lo < hi) { 696 PyObject t = data[lo]; 697 data[lo] = data[hi]; 698 data[hi] = t; 699 ++lo; 700 --hi; 701 } 702 } 703 704 705 706 718 void binarysort(int lo, int hi, int start) { 719 int p; 721 722 724 if (lo == start) 725 ++start; 726 for (; start < hi; ++start) { 727 728 int l = lo; 729 int r = start; 730 PyObject pivot = data[r]; 731 do { 737 p = l + ((r - l) >> 1); 738 if (iflt(pivot, data[p])) 739 r = p; 740 else 741 l = p+1; 742 } while (l < r); 743 for (p = start; p > l; --p) 750 data[p] = data[p - 1]; 751 data[l] = pivot; 752 } 753 } 755 756 757 private void dump_data(String txt, int lo, int n) { 758 764 } 765 766 private void debug(String str) { 767 } 769 } 770 | Popular Tags |