1 /** 2 * The array module provides array manipulation routines in a manner that 3 * balances performance and flexibility. Operations are provided for sorting, 4 * and for processing both sorted and unsorted arrays. 5 * 6 * Copyright: Copyright (C) 2005-2006 Sean Kelly. All rights reserved. 7 * License: BSD style: $(LICENSE) 8 * Authors: Sean Kelly 9 */ 10 module tango.core.Array; 11 12 private import tango.core.Traits; 13 private import tango.stdc.stdlib : alloca, rand; 14 15 version( TangoDoc ) 16 { 17 alias int Num; 18 alias int Elem; 19 alias int Elem2; 20 21 alias bool function( Elem ) Pred1E; 22 alias bool function( Elem, Elem ) Pred2E; 23 alias Elem2 function( Elem, Elem ) Map2E; 24 alias Elem function( Elem, Elem ) Reduce2E; 25 alias size_t function( size_t ) Oper1A; 26 } 27 28 29 private 30 { 31 struct IsEqual( T ) 32 { 33 static bool opCall( T p1, T p2 ) 34 { 35 // TODO: Fix this if/when opEquals is changed to return a bool. 36 static if( is( T == class ) || is( T == struct ) ) 37 return (p1 == p2) != 0; 38 else 39 return p1 == p2; 40 } 41 } 42 43 44 struct IsLess( T ) 45 { 46 static bool opCall( T p1, T p2 ) 47 { 48 return p1 < p2; 49 } 50 } 51 52 53 struct RandOper() 54 { 55 static size_t opCall( size_t lim ) 56 { 57 // NOTE: The use of 'max' here is intended to eliminate modulo bias 58 // in this routine. 59 size_t max = size_t.max - (size_t.max % lim); 60 size_t val; 61 62 do 63 { 64 static if( size_t.sizeof == 4 ) 65 { 66 val = (((cast(size_t)rand()) << 16) & 0xffff0000u) | 67 (((cast(size_t)rand())) & 0x0000ffffu); 68 } 69 else // assume size_t.sizeof == 8 70 { 71 val = (((cast(size_t)rand()) << 48) & 0xffff000000000000uL) | 72 (((cast(size_t)rand()) << 32) & 0x0000ffff00000000uL) | 73 (((cast(size_t)rand()) << 16) & 0x00000000ffff0000uL) | 74 (((cast(size_t)rand())) & 0x000000000000ffffuL); 75 } 76 } while( val > max ); 77 return val % lim; 78 } 79 } 80 81 82 template ElemTypeOf( T:T[] ) 83 { 84 alias T ElemTypeOf; 85 } 86 } 87 88 89 //////////////////////////////////////////////////////////////////////////////// 90 // Find 91 //////////////////////////////////////////////////////////////////////////////// 92 93 94 version( TangoDoc ) 95 { 96 /** 97 * Performs a linear scan of buf from [0 .. buf.length$(RP), returning 98 * the index of the first element matching pat, or buf.length if no match 99 * was found. Comparisons will be performed using the supplied predicate 100 * or '==' if none is supplied. 101 * 102 * Params: 103 * buf = The array to search. 104 * pat = The pattern to search for. 105 * pred = The evaluation predicate, which should return true if e1 is 106 * equal to e2 and false if not. This predicate may be any 107 * callable type. 108 * 109 * Returns: 110 * The index of the first match or buf.length if no match was found. 111 */ 112 size_t find( Elem[] buf, Elem pat, Pred2E pred = Pred2E.init ); 113 114 115 /** 116 * Performs a linear scan of buf from [0 .. buf.length$(RP), returning 117 * the index of the first element matching pat, or buf.length if no match 118 * was found. Comparisons will be performed using the supplied predicate 119 * or '==' if none is supplied. 120 * 121 * Params: 122 * buf = The array to search. 123 * pat = The pattern to search for. 124 * pred = The evaluation predicate, which should return true if e1 is 125 * equal to e2 and false if not. This predicate may be any 126 * callable type. 127 * 128 * Returns: 129 * The index of the first match or buf.length if no match was found. 130 */ 131 size_t find( Elem[] buf, Elem[] pat, Pred2E pred = Pred2E.init ); 132 133 } 134 else 135 { 136 template find_( Elem, Pred = IsEqual!(Elem) ) 137 { 138 static assert( isCallableType!(Pred) ); 139 140 141 size_t fn( Elem[] buf, Elem pat, Pred pred = Pred.init ) 142 { 143 foreach( size_t pos, Elem cur; buf ) 144 { 145 if( pred( cur, pat ) ) 146 return pos; 147 } 148 return buf.length; 149 } 150 151 152 size_t fn( Elem[] buf, Elem[] pat, Pred pred = Pred.init ) 153 { 154 if( buf.length == 0 || 155 pat.length == 0 || 156 buf.length < pat.length ) 157 { 158 return buf.length; 159 } 160 161 size_t end = buf.length - pat.length + 1; 162 163 for( size_t pos = 0; pos < end; ++pos ) 164 { 165 if( pred( buf[pos], pat[0] ) ) 166 { 167 size_t mat = 0; 168 169 do 170 { 171 if( ++mat >= pat.length ) 172 return pos - pat.length + 1; 173 if( ++pos >= buf.length ) 174 return buf.length; 175 } while( pred( buf[pos], pat[mat] ) ); 176 pos -= mat; 177 } 178 } 179 return buf.length; 180 } 181 } 182 183 184 template find( Buf, Pat ) 185 { 186 size_t find( Buf buf, Pat pat ) 187 { 188 return find_!(ElemTypeOf!(Buf)).fn( buf, pat ); 189 } 190 } 191 192 193 template find( Buf, Pat, Pred ) 194 { 195 size_t find( Buf buf, Pat pat, Pred pred ) 196 { 197 return find_!(ElemTypeOf!(Buf), Pred).fn( buf, pat, pred ); 198 } 199 } 200 201 202 debug( UnitTest ) 203 { 204 unittest 205 { 206 // find element 207 assert( find( "", 'a' ) == 0 ); 208 assert( find( "abc", 'a' ) == 0 ); 209 assert( find( "abc", 'b' ) == 1 ); 210 assert( find( "abc", 'c' ) == 2 ); 211 assert( find( "abc", 'd' ) == 3 ); 212 213 // null parameters 214 assert( find( "", "" ) == 0 ); 215 assert( find( "a", "" ) == 1 ); 216 assert( find( "", "a" ) == 0 ); 217 218 // exact match 219 assert( find( "abc", "abc" ) == 0 ); 220 221 // simple substring match 222 assert( find( "abc", "a" ) == 0 ); 223 assert( find( "abca", "a" ) == 0 ); 224 assert( find( "abc", "b" ) == 1 ); 225 assert( find( "abc", "c" ) == 2 ); 226 assert( find( "abc", "d" ) == 3 ); 227 228 // multi-char substring match 229 assert( find( "abc", "ab" ) == 0 ); 230 assert( find( "abcab", "ab" ) == 0 ); 231 assert( find( "abc", "bc" ) == 1 ); 232 assert( find( "abc", "ac" ) == 3 ); 233 assert( find( "abrabracadabra", "abracadabra" ) == 3 ); 234 } 235 } 236 } 237 238 239 //////////////////////////////////////////////////////////////////////////////// 240 // Reverse Find 241 //////////////////////////////////////////////////////////////////////////////// 242 243 244 version( TangoDoc ) 245 { 246 /** 247 * Performs a linear scan of buf from $(LP)buf.length .. 0], returning 248 * the index of the first element matching pat, or buf.length if no match 249 * was found. Comparisons will be performed using the supplied predicate 250 * or '==' if none is supplied. 251 * 252 * Params: 253 * buf = The array to search. 254 * pat = The pattern to search for. 255 * pred = The evaluation predicate, which should return true if e1 is 256 * equal to e2 and false if not. This predicate may be any 257 * callable type. 258 * 259 * Returns: 260 * The index of the first match or buf.length if no match was found. 261 */ 262 size_t rfind( Elem[] buf, Elem pat, Pred2E pred = Pred2E.init ); 263 264 265 /** 266 * Performs a linear scan of buf from $(LP)buf.length .. 0], returning 267 * the index of the first element matching pat, or buf.length if no match 268 * was found. Comparisons will be performed using the supplied predicate 269 * or '==' if none is supplied. 270 * 271 * Params: 272 * buf = The array to search. 273 * pat = The pattern to search for. 274 * pred = The evaluation predicate, which should return true if e1 is 275 * equal to e2 and false if not. This predicate may be any 276 * callable type. 277 * 278 * Returns: 279 * The index of the first match or buf.length if no match was found. 280 */ 281 size_t rfind( Elem[] buf, Elem[] pat, Pred2E pred = Pred2E.init ); 282 } 283 else 284 { 285 template rfind_( Elem, Pred = IsEqual!(Elem) ) 286 { 287 static assert( isCallableType!(Pred) ); 288 289 290 size_t fn( Elem[] buf, Elem pat, Pred pred = Pred.init ) 291 { 292 if( buf.length == 0 ) 293 return buf.length; 294 295 size_t pos = buf.length; 296 297 do 298 { 299 if( pred( buf[--pos], pat ) ) 300 return pos; 301 } while( pos > 0 ); 302 return buf.length; 303 } 304 305 306 size_t fn( Elem[] buf, Elem[] pat, Pred pred = Pred.init ) 307 { 308 if( buf.length == 0 || 309 pat.length == 0 || 310 buf.length < pat.length ) 311 { 312 return buf.length; 313 } 314 315 size_t pos = buf.length - pat.length + 1; 316 317 do 318 { 319 if( pred( buf[--pos], pat[0] ) ) 320 { 321 size_t mat = 0; 322 323 do 324 { 325 if( ++mat >= pat.length ) 326 return pos - pat.length + 1; 327 if( ++pos >= buf.length ) 328 return buf.length; 329 } while( pred( buf[pos], pat[mat] ) ); 330 pos -= mat; 331 } 332 } while( pos > 0 ); 333 return buf.length; 334 } 335 } 336 337 338 template rfind( Buf, Pat ) 339 { 340 size_t rfind( Buf buf, Pat pat ) 341 { 342 return rfind_!(ElemTypeOf!(Buf)).fn( buf, pat ); 343 } 344 } 345 346 347 template rfind( Buf, Pat, Pred ) 348 { 349 size_t rfind( Buf buf, Pat pat, Pred pred ) 350 { 351 return rfind_!(ElemTypeOf!(Buf), Pred).fn( buf, pat, pred ); 352 } 353 } 354 355 356 debug( UnitTest ) 357 { 358 unittest 359 { 360 // rfind element 361 assert( rfind( "", 'a' ) == 0 ); 362 assert( rfind( "abc", 'a' ) == 0 ); 363 assert( rfind( "abc", 'b' ) == 1 ); 364 assert( rfind( "abc", 'c' ) == 2 ); 365 assert( rfind( "abc", 'd' ) == 3 ); 366 367 // null parameters 368 assert( rfind( "", "" ) == 0 ); 369 assert( rfind( "a", "" ) == 1 ); 370 assert( rfind( "", "a" ) == 0 ); 371 372 // exact match 373 assert( rfind( "abc", "abc" ) == 0 ); 374 375 // simple substring match 376 assert( rfind( "abc", "a" ) == 0 ); 377 assert( rfind( "abca", "a" ) == 3 ); 378 assert( rfind( "abc", "b" ) == 1 ); 379 assert( rfind( "abc", "c" ) == 2 ); 380 assert( rfind( "abc", "d" ) == 3 ); 381 382 // multi-char substring match 383 assert( rfind( "abc", "ab" ) == 0 ); 384 assert( rfind( "abcab", "ab" ) == 3 ); 385 assert( rfind( "abc", "bc" ) == 1 ); 386 assert( rfind( "abc", "ac" ) == 3 ); 387 assert( rfind( "abracadabrabra", "abracadabra" ) == 0 ); 388 } 389 } 390 } 391 392 393 //////////////////////////////////////////////////////////////////////////////// 394 // KMP Find 395 //////////////////////////////////////////////////////////////////////////////// 396 397 398 version( TangoDoc ) 399 { 400 /** 401 * Performs a linear scan of buf from [0 .. buf.length$(RP), returning 402 * the index of the first element matching pat, or buf.length if no match 403 * was found. Comparisons will be performed using the supplied predicate 404 * or '==' if none is supplied. 405 * 406 * This function uses the KMP algorithm and offers O(M+N) performance but 407 * must allocate a temporary buffer of size pat.sizeof to do so. If it is 408 * available on the target system, alloca will be used for the allocation, 409 * otherwise a standard dynamic memory allocation will occur. 410 * 411 * Params: 412 * buf = The array to search. 413 * pat = The pattern to search for. 414 * pred = The evaluation predicate, which should return true if e1 is 415 * equal to e2 and false if not. This predicate may be any 416 * callable type. 417 * 418 * Returns: 419 * The index of the first match or buf.length if no match was found. 420 */ 421 size_t kfind( Elem[] buf, Elem pat, Pred2E pred = Pred2E.init ); 422 423 424 /** 425 * Performs a linear scan of buf from [0 .. buf.length$(RP), returning 426 * the index of the first element matching pat, or buf.length if no match 427 * was found. Comparisons will be performed using the supplied predicate 428 * or '==' if none is supplied. 429 * 430 * This function uses the KMP algorithm and offers O(M+N) performance but 431 * must allocate a temporary buffer of size pat.sizeof to do so. If it is 432 * available on the target system, alloca will be used for the allocation, 433 * otherwise a standard dynamic memory allocation will occur. 434 * 435 * Params: 436 * buf = The array to search. 437 * pat = The pattern to search for. 438 * pred = The evaluation predicate, which should return true if e1 is 439 * equal to e2 and false if not. This predicate may be any 440 * callable type. 441 * 442 * Returns: 443 * The index of the first match or buf.length if no match was found. 444 */ 445 size_t kfind( Elem[] buf, Elem[] pat, Pred2E pred = Pred2E.init ); 446 } 447 else 448 { 449 template kfind_( Elem, Pred = IsEqual!(Elem) ) 450 { 451 static assert( isCallableType!(Pred) ); 452 453 454 size_t fn( Elem[] buf, Elem pat, Pred pred = Pred.init ) 455 { 456 foreach( size_t pos, Elem cur; buf ) 457 { 458 if( pred( cur, pat ) ) 459 return pos; 460 } 461 return buf.length; 462 } 463 464 465 size_t fn( Elem[] buf, Elem[] pat, Pred pred = Pred.init ) 466 { 467 if( buf.length == 0 || 468 pat.length == 0 || 469 buf.length < pat.length ) 470 { 471 return buf.length; 472 } 473 474 static if( is( alloca ) ) // always false, alloca usage should be rethought 475 { 476 size_t[] func = (cast(size_t*) alloca( (pat.length + 1) * size_t.sizeof ))[0 .. pat.length + 1]; 477 } 478 else 479 { 480 size_t[] func = new size_t[pat.length + 1]; 481 scope( exit ) delete func; // force cleanup 482 } 483 484 func[0] = 0; 485 486 // 487 // building prefix-function 488 // 489 for( size_t m = 0, i = 1 ; i < pat.length ; ++i ) 490 { 491 while( ( m > 0 ) && !pred( pat[m], pat[i] ) ) 492 m = func[m - 1]; 493 if( pred( pat[m], pat[i] ) ) 494 ++m; 495 func[i] = m; 496 } 497 498 // 499 // searching 500 // 501 for( size_t m = 0, i = 0; i < buf.length; ++i ) 502 { 503 while( ( m > 0 ) && !pred( pat[m], buf[i] ) ) 504 m = func[m - 1]; 505 if( pred( pat[m], buf[i] ) ) 506 { 507 ++m; 508 if( m == pat.length ) 509 { 510 return i - pat.length + 1; 511 } 512 } 513 } 514 515 return buf.length; 516 } 517 } 518 519 520 template kfind( Buf, Pat ) 521 { 522 size_t kfind( Buf buf, Pat pat ) 523 { 524 return kfind_!(ElemTypeOf!(Buf)).fn( buf, pat ); 525 } 526 } 527 528 529 template kfind( Buf, Pat, Pred ) 530 { 531 size_t kfind( Buf buf, Pat pat, Pred pred ) 532 { 533 return kfind_!(ElemTypeOf!(Buf), Pred).fn( buf, pat, pred ); 534 } 535 } 536 537 538 debug( UnitTest ) 539 { 540 unittest 541 { 542 // find element 543 assert( kfind( "", 'a' ) == 0 ); 544 assert( kfind( "abc", 'a' ) == 0 ); 545 assert( kfind( "abc", 'b' ) == 1 ); 546 assert( kfind( "abc", 'c' ) == 2 ); 547 assert( kfind( "abc", 'd' ) == 3 ); 548 549 // null parameters 550 assert( kfind( "", "" ) == 0 ); 551 assert( kfind( "a", "" ) == 1 ); 552 assert( kfind( "", "a" ) == 0 ); 553 554 // exact match 555 assert( kfind( "abc", "abc" ) == 0 ); 556 557 // simple substring match 558 assert( kfind( "abc", "a" ) == 0 ); 559 assert( kfind( "abca", "a" ) == 0 ); 560 assert( kfind( "abc", "b" ) == 1 ); 561 assert( kfind( "abc", "c" ) == 2 ); 562 assert( kfind( "abc", "d" ) == 3 ); 563 564 // multi-char substring match 565 assert( kfind( "abc", "ab" ) == 0 ); 566 assert( kfind( "abcab", "ab" ) == 0 ); 567 assert( kfind( "abc", "bc" ) == 1 ); 568 assert( kfind( "abc", "ac" ) == 3 ); 569 assert( kfind( "abrabracadabra", "abracadabra" ) == 3 ); 570 } 571 } 572 } 573 574 575 //////////////////////////////////////////////////////////////////////////////// 576 // KMP Reverse Find 577 //////////////////////////////////////////////////////////////////////////////// 578 579 580 version( TangoDoc ) 581 { 582 /** 583 * Performs a linear scan of buf from $(LP)buf.length .. 0], returning 584 * the index of the first element matching pat, or buf.length if no match 585 * was found. Comparisons will be performed using the supplied predicate 586 * or '==' if none is supplied. 587 * 588 * This function uses the KMP algorithm and offers O(M+N) performance but 589 * must allocate a temporary buffer of size pat.sizeof to do so. If it is 590 * available on the target system, alloca will be used for the allocation, 591 * otherwise a standard dynamic memory allocation will occur. 592 * 593 * Params: 594 * buf = The array to search. 595 * pat = The pattern to search for. 596 * pred = The evaluation predicate, which should return true if e1 is 597 * equal to e2 and false if not. This predicate may be any 598 * callable type. 599 * 600 * Returns: 601 * The index of the first match or buf.length if no match was found. 602 */ 603 size_t krfind( Elem[] buf, Elem pat, Pred2E pred = Pred2E.init ); 604 605 606 /** 607 * Performs a linear scan of buf from $(LP)buf.length .. 0], returning 608 * the index of the first element matching pat, or buf.length if no match 609 * was found. Comparisons will be performed using the supplied predicate 610 * or '==' if none is supplied. 611 * 612 * This function uses the KMP algorithm and offers O(M+N) performance but 613 * must allocate a temporary buffer of size pat.sizeof to do so. If it is 614 * available on the target system, alloca will be used for the allocation, 615 * otherwise a standard dynamic memory allocation will occur. 616 * 617 * Params: 618 * buf = The array to search. 619 * pat = The pattern to search for. 620 * pred = The evaluation predicate, which should return true if e1 is 621 * equal to e2 and false if not. This predicate may be any 622 * callable type. 623 * 624 * Returns: 625 * The index of the first match or buf.length if no match was found. 626 */ 627 size_t krfind( Elem[] buf, Elem[] pat, Pred2E pred = Pred2E.init ); 628 } 629 else 630 { 631 template krfind_( Elem, Pred = IsEqual!(Elem) ) 632 { 633 static assert( isCallableType!(Pred) ); 634 635 636 size_t fn( Elem[] buf, Elem pat, Pred pred = Pred.init ) 637 { 638 if( buf.length == 0 ) 639 return buf.length; 640 641 size_t pos = buf.length; 642 643 do 644 { 645 if( pred( buf[--pos], pat ) ) 646 return pos; 647 } while( pos > 0 ); 648 return buf.length; 649 } 650 651 652 size_t fn( Elem[] buf, Elem[] pat, Pred pred = Pred.init ) 653 { 654 if( buf.length == 0 || 655 pat.length == 0 || 656 buf.length < pat.length ) 657 { 658 return buf.length; 659 } 660 661 static if( is( alloca ) ) // always false, alloca usage should be rethought 662 { 663 size_t[] func = (cast(size_t*) alloca( (pat.length + 1) * size_t.sizeof ))[0 .. pat.length + 1]; 664 } 665 else 666 { 667 size_t[] func = new size_t[pat.length + 1]; 668 scope( exit ) delete func; // force cleanup 669 } 670 671 func[$ - 1] = 0; 672 673 // 674 // building prefix-function 675 // 676 for( size_t m = 0, i = pat.length - 1; i > 0; --i ) 677 { 678 while( ( m > 0 ) && !pred( pat[$ - m - 1], pat[i - 1] ) ) 679 m = func[$ - m]; 680 if( pred( pat[$ - m - 1], pat[i - 1] ) ) 681 ++m; 682 func[i - 1] = m; 683 } 684 685 // 686 // searching 687 // 688 size_t m = 0; 689 size_t i = buf.length; 690 do 691 { 692 --i; 693 while( ( m > 0 ) && !pred( pat[$ - m - 1], buf[i] ) ) 694 m = func[$ - m - 1]; 695 if( pred( pat[$ - m - 1], buf[i] ) ) 696 { 697 ++m; 698 if ( m == pat.length ) 699 { 700 return i; 701 } 702 } 703 } while( i > 0 ); 704 705 return buf.length; 706 } 707 } 708 709 710 template krfind( Buf, Pat ) 711 { 712 size_t krfind( Buf buf, Pat pat ) 713 { 714 return krfind_!(ElemTypeOf!(Buf)).fn( buf, pat ); 715 } 716 } 717 718 719 template krfind( Buf, Pat, Pred ) 720 { 721 size_t krfind( Buf buf, Pat pat, Pred pred ) 722 { 723 return krfind_!(ElemTypeOf!(Buf), Pred).fn( buf, pat, pred ); 724 } 725 } 726 727 728 debug( UnitTest ) 729 { 730 unittest 731 { 732 // rfind element 733 assert( krfind( "", 'a' ) == 0 ); 734 assert( krfind( "abc", 'a' ) == 0 ); 735 assert( krfind( "abc", 'b' ) == 1 ); 736 assert( krfind( "abc", 'c' ) == 2 ); 737 assert( krfind( "abc", 'd' ) == 3 ); 738 739 // null parameters 740 assert( krfind( "", "" ) == 0 ); 741 assert( krfind( "a", "" ) == 1 ); 742 assert( krfind( "", "a" ) == 0 ); 743 744 // exact match 745 assert( krfind( "abc", "abc" ) == 0 ); 746 747 // simple substring match 748 assert( krfind( "abc", "a" ) == 0 ); 749 assert( krfind( "abca", "a" ) == 3 ); 750 assert( krfind( "abc", "b" ) == 1 ); 751 assert( krfind( "abc", "c" ) == 2 ); 752 assert( krfind( "abc", "d" ) == 3 ); 753 754 // multi-char substring match 755 assert( krfind( "abc", "ab" ) == 0 ); 756 assert( krfind( "abcab", "ab" ) == 3 ); 757 assert( krfind( "abc", "bc" ) == 1 ); 758 assert( krfind( "abc", "ac" ) == 3 ); 759 assert( krfind( "abracadabrabra", "abracadabra" ) == 0 ); 760 } 761 } 762 } 763 764 765 //////////////////////////////////////////////////////////////////////////////// 766 // Find-If 767 //////////////////////////////////////////////////////////////////////////////// 768 769 770 version( TangoDoc ) 771 { 772 /** 773 * Performs a linear scan of buf from [0 .. buf.length$(RP), returning 774 * the index of the first element where pred returns true. 775 * 776 * Params: 777 * buf = The array to search. 778 * pred = The evaluation predicate, which should return true if the 779 * element is a valid match and false if not. This predicate 780 * may be any callable type. 781 * 782 * Returns: 783 * The index of the first match or buf.length if no match was found. 784 */ 785 size_t findIf( Elem[] buf, Pred1E pred ); 786 } 787 else 788 { 789 template findIf_( Elem, Pred ) 790 { 791 static assert( isCallableType!(Pred) ); 792 793 794 size_t fn( Elem[] buf, Pred pred ) 795 { 796 foreach( size_t pos, Elem cur; buf ) 797 { 798 if( pred( cur ) ) 799 return pos; 800 } 801 return buf.length; 802 } 803 } 804 805 806 template findIf( Buf, Pred ) 807 { 808 size_t findIf( Buf buf, Pred pred ) 809 { 810 return findIf_!(ElemTypeOf!(Buf), Pred).fn( buf, pred ); 811 } 812 } 813 814 815 debug( UnitTest ) 816 { 817 unittest 818 { 819 assert( findIf( "bcecg", ( char c ) { return c == 'a'; } ) == 5 ); 820 assert( findIf( "bcecg", ( char c ) { return c == 'b'; } ) == 0 ); 821 assert( findIf( "bcecg", ( char c ) { return c == 'c'; } ) == 1 ); 822 assert( findIf( "bcecg", ( char c ) { return c == 'd'; } ) == 5 ); 823 assert( findIf( "bcecg", ( char c ) { return c == 'g'; } ) == 4 ); 824 assert( findIf( "bcecg", ( char c ) { return c == 'h'; } ) == 5 ); 825 } 826 } 827 } 828 829 830 //////////////////////////////////////////////////////////////////////////////// 831 // Reverse Find-If 832 //////////////////////////////////////////////////////////////////////////////// 833 834 835 version( TangoDoc ) 836 { 837 /** 838 * Performs a linear scan of buf from $(LP)buf.length .. 0], returning 839 * the index of the first element where pred returns true. 840 * 841 * Params: 842 * buf = The array to search. 843 * pred = The evaluation predicate, which should return true if the 844 * element is a valid match and false if not. This predicate 845 * may be any callable type. 846 * 847 * Returns: 848 * The index of the first match or buf.length if no match was found. 849 */ 850 size_t rfindIf( Elem[] buf, Pred1E pred ); 851 } 852 else 853 { 854 template rfindIf_( Elem, Pred ) 855 { 856 static assert( isCallableType!(Pred) ); 857 858 859 size_t fn( Elem[] buf, Pred pred ) 860 { 861 if( buf.length == 0 ) 862 return buf.length; 863 864 size_t pos = buf.length; 865 866 do 867 { 868 if( pred( buf[--pos] ) ) 869 return pos; 870 } while( pos > 0 ); 871 return buf.length; 872 } 873 } 874 875 876 template rfindIf( Buf, Pred ) 877 { 878 size_t rfindIf( Buf buf, Pred pred ) 879 { 880 return rfindIf_!(ElemTypeOf!(Buf), Pred).fn( buf, pred ); 881 } 882 } 883 884 885 debug( UnitTest ) 886 { 887 unittest 888 { 889 assert( rfindIf( "bcecg", ( char c ) { return c == 'a'; } ) == 5 ); 890 assert( rfindIf( "bcecg", ( char c ) { return c == 'b'; } ) == 0 ); 891 assert( rfindIf( "bcecg", ( char c ) { return c == 'c'; } ) == 3 ); 892 assert( rfindIf( "bcecg", ( char c ) { return c == 'd'; } ) == 5 ); 893 assert( rfindIf( "bcecg", ( char c ) { return c == 'g'; } ) == 4 ); 894 assert( rfindIf( "bcecg", ( char c ) { return c == 'h'; } ) == 5 ); 895 } 896 } 897 } 898 899 900 //////////////////////////////////////////////////////////////////////////////// 901 // Find Adjacent 902 //////////////////////////////////////////////////////////////////////////////// 903 904 905 version( TangoDoc ) 906 { 907 /** 908 * Performs a linear scan of buf from [0 .. buf.length$(RP), returning 909 * the index of the first element that compares equal to the next element 910 * in the sequence. Comparisons will be performed using the supplied 911 * predicate or '==' if none is supplied. 912 * 913 * Params: 914 * buf = The array to scan. 915 * pred = The evaluation predicate, which should return true if e1 is 916 * equal to e2 and false if not. This predicate may be any 917 * callable type. 918 * 919 * Returns: 920 * The index of the first match or buf.length if no match was found. 921 */ 922 size_t findAdj( Elem[] buf, Pred2E pred = Pred2E.init ); 923 924 } 925 else 926 { 927 template findAdj_( Elem, Pred = IsEqual!(Elem) ) 928 { 929 static assert( isCallableType!(Pred) ); 930 931 932 size_t fn( Elem[] buf, Pred pred = Pred.init ) 933 { 934 if( buf.length < 2 ) 935 return buf.length; 936 937 auto sav = cast(BaseTypeOf!(Elem))buf[0]; 938 939 foreach( size_t pos, Elem cur; buf[1 .. $] ) 940 { 941 if( pred( cur, sav ) ) 942 return pos; 943 sav = cast(BaseTypeOf!(Elem))cur; 944 } 945 return buf.length; 946 } 947 } 948 949 950 template findAdj( Buf ) 951 { 952 size_t findAdj( Buf buf ) 953 { 954 return findAdj_!(ElemTypeOf!(Buf)).fn( buf ); 955 } 956 } 957 958 959 template findAdj( Buf, Pred ) 960 { 961 size_t findAdj( Buf buf, Pred pred ) 962 { 963 return findAdj_!(ElemTypeOf!(Buf), Pred).fn( buf, pred ); 964 } 965 } 966 967 968 debug( UnitTest ) 969 { 970 unittest 971 { 972 assert( findAdj( "aabcdef" ) == 0 ); 973 assert( findAdj( "abcddef" ) == 3 ); 974 assert( findAdj( "abcdeff" ) == 5 ); 975 assert( findAdj( "abcdefg" ) == 7 ); 976 } 977 } 978 } 979 980 981 //////////////////////////////////////////////////////////////////////////////// 982 // Contains 983 //////////////////////////////////////////////////////////////////////////////// 984 985 986 version( TangoDoc ) 987 { 988 /** 989 * Performs a linear scan of buf from [0 .. buf.length$(RP), returning 990 * true if an element matching pat is found. Comparisons will be performed 991 * using the supplied predicate or '<' if none is supplied. 992 * 993 * Params: 994 * buf = The array to search. 995 * pat = The pattern to search for. 996 * pred = The evaluation predicate, which should return true if e1 is 997 * equal to e2 and false if not. This predicate may be any 998 * callable type. 999 * 1000 * Returns: 1001 * True if an element equivalent to pat is found, false if not. 1002 */ 1003 equals_t contains( Elem[] buf, Elem pat, Pred2E pred = Pred2E.init ); 1004 1005 1006 /** 1007 * Performs a linear scan of buf from [0 .. buf.length$(RP), returning 1008 * true if a sequence matching pat is found. Comparisons will be performed 1009 * using the supplied predicate or '<' if none is supplied. 1010 * 1011 * Params: 1012 * buf = The array to search. 1013 * pat = The pattern to search for. 1014 * pred = The evaluation predicate, which should return true if e1 is 1015 * equal to e2 and false if not. This predicate may be any 1016 * callable type. 1017 * 1018 * Returns: 1019 * True if an element equivalent to pat is found, false if not. 1020 */ 1021 equals_t contains( Elem[] buf, Elem[] pat, Pred2E pred = Pred2E.init ); 1022 } 1023 else 1024 { 1025 template contains( Buf, Pat ) 1026 { 1027 equals_t contains( Buf buf, Pat pat ) 1028 { 1029 return cast(equals_t)(find( buf, pat ) != buf.length); 1030 } 1031 } 1032 1033 1034 template contains( Buf, Pat, Pred ) 1035 { 1036 equals_t contains( Buf buf, Pat pat, Pred pred ) 1037 { 1038 return cast(equals_t)(find( buf, pat, pred ) != buf.length); 1039 } 1040 } 1041 1042 1043 debug( UnitTest ) 1044 { 1045 unittest 1046 { 1047 // find element 1048 assert( !contains( "", 'a' ) ); 1049 assert( contains( "abc", 'a' ) ); 1050 assert( contains( "abc", 'b' ) ); 1051 assert( contains( "abc", 'c' ) ); 1052 assert( !contains( "abc", 'd' ) ); 1053 1054 // null parameters 1055 assert( !contains( "", "" ) ); 1056 assert( !contains( "a", "" ) ); 1057 assert( !contains( "", "a" ) ); 1058 1059 // exact match 1060 assert( contains( "abc", "abc" ) ); 1061 1062 // simple substring match 1063 assert( contains( "abc", "a" ) ); 1064 assert( contains( "abca", "a" ) ); 1065 assert( contains( "abc", "b" ) ); 1066 assert( contains( "abc", "c" ) ); 1067 assert( !contains( "abc", "d" ) ); 1068 1069 // multi-char substring match 1070 assert( contains( "abc", "ab" ) ); 1071 assert( contains( "abcab", "ab" ) ); 1072 assert( contains( "abc", "bc" ) ); 1073 assert( !contains( "abc", "ac" ) ); 1074 assert( contains( "abrabracadabra", "abracadabra" ) ); 1075 } 1076 } 1077 } 1078 1079 1080 //////////////////////////////////////////////////////////////////////////////// 1081 // Mismatch 1082 //////////////////////////////////////////////////////////////////////////////// 1083 1084 1085 version( TangoDoc ) 1086 { 1087 /** 1088 * Performs a parallel linear scan of bufA and bufB from [0 .. N$(RP) 1089 * where N = min(bufA.length, bufB.length), returning the index of 1090 * the first element in bufA which does not match the corresponding element 1091 * in bufB or N if no mismatch occurs. Comparisons will be performed using 1092 * the supplied predicate or '==' if none is supplied. 1093 * 1094 * Params: 1095 * bufA = The array to evaluate. 1096 * bufB = The array to match against. 1097 * pred = The evaluation predicate, which should return true if e1 is 1098 * equal to e2 and false if not. This predicate may be any 1099 * callable type. 1100 * 1101 * Returns: 1102 * The index of the first mismatch or N if the first N elements of bufA 1103 * and bufB match, where N = min$(LP)bufA.length, bufB.length$(RP). 1104 */ 1105 size_t mismatch( Elem[] bufA, Elem[] bufB, Pred2E pred = Pred2E.init ); 1106 1107 } 1108 else 1109 { 1110 template mismatch_( Elem, Pred = IsEqual!(Elem) ) 1111 { 1112 static assert( isCallableType!(Pred) ); 1113 1114 1115 size_t fn( Elem[] bufA, Elem[] bufB, Pred pred = Pred.init ) 1116 { 1117 size_t posA = 0, 1118 posB = 0; 1119 1120 while( posA < bufA.length && posB < bufB.length ) 1121 { 1122 if( !pred( bufB[posB], bufA[posA] ) ) 1123 break; 1124 ++posA, ++posB; 1125 } 1126 return posA; 1127 } 1128 } 1129 1130 1131 template mismatch( BufA, BufB ) 1132 { 1133 size_t mismatch( BufA bufA, BufB bufB ) 1134 { 1135 return mismatch_!(ElemTypeOf!(BufA)).fn( bufA, bufB ); 1136 } 1137 } 1138 1139 1140 template mismatch( BufA, BufB, Pred ) 1141 { 1142 size_t mismatch( BufA bufA, BufB bufB, Pred pred ) 1143 { 1144 return mismatch_!(ElemTypeOf!(BufA), Pred).fn( bufA, bufB, pred ); 1145 } 1146 } 1147 1148 debug( UnitTest ) 1149 { 1150 unittest 1151 { 1152 assert( mismatch( "a", "abcdefg" ) == 1 ); 1153 assert( mismatch( "abcdefg", "a" ) == 1 ); 1154 1155 assert( mismatch( "x", "abcdefg" ) == 0 ); 1156 assert( mismatch( "abcdefg", "x" ) == 0 ); 1157 1158 assert( mismatch( "xbcdefg", "abcdefg" ) == 0 ); 1159 assert( mismatch( "abcdefg", "xbcdefg" ) == 0 ); 1160 1161 assert( mismatch( "abcxefg", "abcdefg" ) == 3 ); 1162 assert( mismatch( "abcdefg", "abcxefg" ) == 3 ); 1163 1164 assert( mismatch( "abcdefx", "abcdefg" ) == 6 ); 1165 assert( mismatch( "abcdefg", "abcdefx" ) == 6 ); 1166 } 1167 } 1168 } 1169 1170 1171 //////////////////////////////////////////////////////////////////////////////// 1172 // Count 1173 //////////////////////////////////////////////////////////////////////////////// 1174 1175 1176 version( TangoDoc ) 1177 { 1178 /** 1179 * Performs a linear scan of buf from [0 .. buf.length$(RP), returning 1180 * a count of the number of elements matching pat. Comparisons will be 1181 * performed using the supplied predicate or '==' if none is supplied. 1182 * 1183 * Params: 1184 * buf = The array to scan. 1185 * pat = The pattern to match. 1186 * pred = The evaluation predicate, which should return true if e1 is 1187 * equal to e2 and false if not. This predicate may be any 1188 * callable type. 1189 * 1190 * Returns: 1191 * The number of elements matching pat. 1192 */ 1193 size_t count( Elem[] buf, Elem pat, Pred2E pred = Pred2E.init ); 1194 1195 } 1196 else 1197 { 1198 template count_( Elem, Pred = IsEqual!(Elem) ) 1199 { 1200 static assert( isCallableType!(Pred) ); 1201 1202 1203 size_t fn( Elem[] buf, Elem pat, Pred pred = Pred.init ) 1204 { 1205 size_t cnt = 0; 1206 1207 foreach( size_t pos, Elem cur; buf ) 1208 { 1209 if( pred( cur, pat ) ) 1210 ++cnt; 1211 } 1212 return cnt; 1213 } 1214 } 1215 1216 1217 template count( Buf, Pat ) 1218 { 1219 size_t count( Buf buf, Pat pat ) 1220 { 1221 return count_!(ElemTypeOf!(Buf)).fn( buf, pat ); 1222 } 1223 } 1224 1225 1226 template count( Buf, Pat, Pred ) 1227 { 1228 size_t count( Buf buf, Pat pat, Pred pred ) 1229 { 1230 return count_!(ElemTypeOf!(Buf), Pred).fn( buf, pat, pred ); 1231 } 1232 } 1233 1234 1235 debug( UnitTest ) 1236 { 1237 unittest 1238 { 1239 assert( count( "gbbbi", 'a' ) == 0 ); 1240 assert( count( "gbbbi", 'g' ) == 1 ); 1241 assert( count( "gbbbi", 'b' ) == 3 ); 1242 assert( count( "gbbbi", 'i' ) == 1 ); 1243 assert( count( "gbbbi", 'd' ) == 0 ); 1244 } 1245 } 1246 } 1247 1248 1249 //////////////////////////////////////////////////////////////////////////////// 1250 // Count-If 1251 //////////////////////////////////////////////////////////////////////////////// 1252 1253 1254 version( TangoDoc ) 1255 { 1256 /** 1257 * Performs a linear scan of buf from [0 .. buf.length$(RP), returning 1258 * a count of the number of elements where pred returns true. 1259 * 1260 * Params: 1261 * buf = The array to scan. 1262 * pred = The evaluation predicate, which should return true if the 1263 * element is a valid match and false if not. This predicate 1264 * may be any callable type. 1265 * 1266 * Returns: 1267 * The number of elements where pred returns true. 1268 */ 1269 size_t countIf( Elem[] buf, Pred1E pred = Pred1E.init ); 1270 1271 } 1272 else 1273 { 1274 template countIf_( Elem, Pred ) 1275 { 1276 static assert( isCallableType!(Pred) ); 1277 1278 1279 size_t fn( Elem[] buf, Pred pred ) 1280 { 1281 size_t cnt = 0; 1282 1283 foreach( size_t pos, Elem cur; buf ) 1284 { 1285 if( pred( cur ) ) 1286 ++cnt; 1287 } 1288 return cnt; 1289 } 1290 } 1291 1292 1293 template countIf( Buf, Pred ) 1294 { 1295 size_t countIf( Buf buf, Pred pred ) 1296 { 1297 return countIf_!(ElemTypeOf!(Buf), Pred).fn( buf, pred ); 1298 } 1299 } 1300 1301 1302 debug( UnitTest ) 1303 { 1304 unittest 1305 { 1306 assert( countIf( "gbbbi", ( char c ) { return c == 'a'; } ) == 0 ); 1307 assert( countIf( "gbbbi", ( char c ) { return c == 'g'; } ) == 1 ); 1308 assert( countIf( "gbbbi", ( char c ) { return c == 'b'; } ) == 3 ); 1309 assert( countIf( "gbbbi", ( char c ) { return c == 'i'; } ) == 1 ); 1310 assert( countIf( "gbbbi", ( char c ) { return c == 'd'; } ) == 0 ); 1311 } 1312 } 1313 } 1314 1315 1316 //////////////////////////////////////////////////////////////////////////////// 1317 // Replace 1318 //////////////////////////////////////////////////////////////////////////////// 1319 1320 1321 version( TangoDoc ) 1322 { 1323 /** 1324 * Performs a linear scan of buf from [0 .. buf.length$(RP), replacing 1325 * occurrences of pat with val. Comparisons will be performed using the 1326 * supplied predicate or '==' if none is supplied. 1327 * 1328 * Params: 1329 * buf = The array to scan. 1330 * pat = The pattern to match. 1331 * val = The value to substitute. 1332 * pred = The evaluation predicate, which should return true if e1 is 1333 * equal to e2 and false if not. This predicate may be any 1334 * callable type. 1335 * 1336 * Returns: 1337 * The number of elements replaced. 1338 */ 1339 size_t replace( Elem[] buf, Elem pat, Elem val, Pred2E pred = Pred2E.init ); 1340 1341 } 1342 else 1343 { 1344 template replace_( Elem, Pred = IsEqual!(Elem) ) 1345 { 1346 static assert( isCallableType!(Pred) ); 1347 1348 1349 size_t fn( Elem[] buf, Elem pat, Elem val, Pred pred = Pred.init ) 1350 { 1351 size_t cnt = 0; 1352 1353 foreach( size_t pos, ref Elem cur; buf ) 1354 { 1355 if( pred( cur, pat ) ) 1356 { 1357 cur = val; 1358 ++cnt; 1359 } 1360 } 1361 return cnt; 1362 } 1363 } 1364 1365 1366 template replace( Buf, Elem ) 1367 { 1368 size_t replace( Buf buf, Elem pat, Elem val ) 1369 { 1370 return replace_!(ElemTypeOf!(Buf)).fn( buf, pat, val ); 1371 } 1372 } 1373 1374 1375 template replace( Buf, Elem, Pred ) 1376 { 1377 size_t replace( Buf buf, Elem pat, Elem val, Pred pred ) 1378 { 1379 return replace_!(ElemTypeOf!(Buf), Pred).fn( buf, pat, val, pred ); 1380 } 1381 } 1382 1383 1384 debug( UnitTest ) 1385 { 1386 unittest 1387 { 1388 assert( replace( "gbbbi".dup, 'a', 'b' ) == 0 ); 1389 assert( replace( "gbbbi".dup, 'g', 'h' ) == 1 ); 1390 assert( replace( "gbbbi".dup, 'b', 'c' ) == 3 ); 1391 assert( replace( "gbbbi".dup, 'i', 'j' ) == 1 ); 1392 assert( replace( "gbbbi".dup, 'd', 'e' ) == 0 ); 1393 } 1394 } 1395 } 1396 1397 1398 //////////////////////////////////////////////////////////////////////////////// 1399 // Replace-If 1400 //////////////////////////////////////////////////////////////////////////////// 1401 1402 1403 version( TangoDoc ) 1404 { 1405 /** 1406 * Performs a linear scan of buf from [0 .. buf.length$(RP), replacing 1407 * elements where pred returns true with val. 1408 * 1409 * Params: 1410 * buf = The array to scan. 1411 * val = The value to substitute. 1412 * pred = The evaluation predicate, which should return true if the 1413 * element is a valid match and false if not. This predicate 1414 * may be any callable type. 1415 * 1416 * Returns: 1417 * The number of elements replaced. 1418 */ 1419 size_t replaceIf( Elem[] buf, Elem val, Pred2E pred = Pred2E.init ); 1420 1421 } 1422 else 1423 { 1424 template replaceIf_( Elem, Pred ) 1425 { 1426 static assert( isCallableType!(Pred) ); 1427 1428 1429 size_t fn( Elem[] buf, Elem val, Pred pred ) 1430 { 1431 size_t cnt = 0; 1432 1433 foreach( size_t pos, ref Elem cur; buf ) 1434 { 1435 if( pred( cur ) ) 1436 { 1437 cur = val; 1438 ++cnt; 1439 } 1440 } 1441 return cnt; 1442 } 1443 } 1444 1445 1446 template replaceIf( Buf, Elem, Pred ) 1447 { 1448 size_t replaceIf( Buf buf, Elem val, Pred pred ) 1449 { 1450 return replaceIf_!(ElemTypeOf!(Buf), Pred).fn( buf, val, pred ); 1451 } 1452 } 1453 1454 1455 debug( UnitTest ) 1456 { 1457 unittest 1458 { 1459 assert( replaceIf( "gbbbi".dup, 'b', ( char c ) { return c == 'a'; } ) == 0 ); 1460 assert( replaceIf( "gbbbi".dup, 'h', ( char c ) { return c == 'g'; } ) == 1 ); 1461 assert( replaceIf( "gbbbi".dup, 'c', ( char c ) { return c == 'b'; } ) == 3 ); 1462 assert( replaceIf( "gbbbi".dup, 'j', ( char c ) { return c == 'i'; } ) == 1 ); 1463 assert( replaceIf( "gbbbi".dup, 'e', ( char c ) { return c == 'd'; } ) == 0 ); 1464 } 1465 } 1466 } 1467 1468 1469 //////////////////////////////////////////////////////////////////////////////// 1470 // Remove 1471 //////////////////////////////////////////////////////////////////////////////// 1472 1473 1474 version( TangoDoc ) 1475 { 1476 /** 1477 * Performs a linear scan of buf from [0 .. buf.length$(RP), moving all 1478 * elements matching pat to the end of the sequence. The relative order of 1479 * elements not matching pat will be preserved. Comparisons will be 1480 * performed using the supplied predicate or '==' if none is supplied. 1481 * 1482 * Params: 1483 * buf = The array to scan. This parameter is not marked 'ref' 1484 * to allow temporary slices to be modified. As buf is not resized 1485 * in any way, omitting the 'ref' qualifier has no effect on the 1486 * result of this operation, even though it may be viewed as a 1487 * side-effect. 1488 * pat = The pattern to match against. 1489 * pred = The evaluation predicate, which should return true if e1 is 1490 * equal to e2 and false if not. This predicate may be any 1491 * callable type. 1492 * 1493 * Returns: 1494 * The number of elements that do not match pat. 1495 */ 1496 size_t remove( Elem[] buf, Elem pat, Pred2E pred = Pred2E.init ); 1497 1498 /** 1499 * Performs a linear scan of buf from [0 .. buf.length$(RP), moving all 1500 * elements matching pat to the end of the sequence. The relative order of 1501 * elements not matching pat will be preserved. Comparisons will be 1502 * performed '=='. 1503 * 1504 * Params: 1505 * buf = The array to scan. This parameter is not marked 'ref' 1506 * to allow temporary slices to be modified. As buf is not resized 1507 * in any way, omitting the 'ref' qualifier has no effect on the 1508 * result of this operation, even though it may be viewed as a 1509 * side-effect. 1510 * pat = The pattern to match against. 1511 * 1512 * Returns: 1513 * The number of elements that do not match pat. 1514 */ 1515 size_t remove( Elem[] buf, Elem pat ); 1516 } 1517 else 1518 { 1519 template remove_( Elem, Pred = IsEqual!(Elem) ) 1520 { 1521 static assert( isCallableType!(Pred) ); 1522 1523 1524 size_t fn( Elem[] buf, Elem pat, Pred pred = Pred.init ) 1525 { 1526 // NOTE: Indexes are passed instead of references because DMD does 1527 // not inline the reference-based version. 1528 void exch( size_t p1, size_t p2 ) 1529 { 1530 Elem t = buf[p1]; 1531 buf[p1] = buf[p2]; 1532 buf[p2] = t; 1533 } 1534 1535 size_t cnt = 0; 1536 1537 for( size_t pos = 0, len = buf.length; pos < len; ++pos ) 1538 { 1539 if( pred( buf[pos], pat ) ) 1540 ++cnt; 1541 else 1542 exch( pos, pos - cnt ); 1543 } 1544 return buf.length - cnt; 1545 } 1546 } 1547 1548 1549 template remove( Buf, Pat ) 1550 { 1551 size_t remove( Buf buf, Pat pat ) 1552 { 1553 return remove_!(ElemTypeOf!(Buf)).fn( buf, pat ); 1554 } 1555 } 1556 1557 1558 template remove( Buf, Pat, Pred ) 1559 { 1560 size_t remove( Buf buf, Pat pat, Pred pred ) 1561 { 1562 return remove_!(ElemTypeOf!(Buf), Pred).fn( buf, pat, pred ); 1563 } 1564 } 1565 1566 1567 debug( UnitTest ) 1568 { 1569 unittest 1570 { 1571 void test( char[] buf, char pat, size_t num ) 1572 { 1573 assert( remove( buf, pat ) == num ); 1574 foreach( pos, cur; buf ) 1575 { 1576 assert( pos < num ? cur != pat : cur == pat ); 1577 } 1578 } 1579 1580 test( "abcdefghij".dup, 'x', 10 ); 1581 test( "xabcdefghi".dup, 'x', 9 ); 1582 test( "abcdefghix".dup, 'x', 9 ); 1583 test( "abxxcdefgh".dup, 'x', 8 ); 1584 test( "xaxbcdxxex".dup, 'x', 5 ); 1585 } 1586 } 1587 } 1588 1589 1590 //////////////////////////////////////////////////////////////////////////////// 1591 // Remove-If 1592 //////////////////////////////////////////////////////////////////////////////// 1593 1594 1595 version( TangoDoc ) 1596 { 1597 /** 1598 * Performs a linear scan of buf from [0 .. buf.length$(RP), moving all 1599 * elements that satisfy pred to the end of the sequence. The relative 1600 * order of elements that do not satisfy pred will be preserved. 1601 * 1602 * Params: 1603 * buf = The array to scan. This parameter is not marked 'ref' 1604 * to allow temporary slices to be modified. As buf is not resized 1605 * in any way, omitting the 'ref' qualifier has no effect on the 1606 * result of this operation, even though it may be viewed as a 1607 * side-effect. 1608 * pred = The evaluation predicate, which should return true if the 1609 * element satisfies the condition and false if not. This 1610 * predicate may be any callable type. 1611 * 1612 * Returns: 1613 * The number of elements that do not satisfy pred. 1614 */ 1615 size_t removeIf( Elem[] buf, Pred1E pred ); 1616 } 1617 else 1618 { 1619 template removeIf_( Elem, Pred ) 1620 { 1621 static assert( isCallableType!(Pred) ); 1622 1623 1624 size_t fn( Elem[] buf, Pred pred ) 1625 { 1626 // NOTE: Indexes are passed instead of references because DMD does 1627 // not inline the reference-based version. 1628 void exch( size_t p1, size_t p2 ) 1629 { 1630 Elem t = buf[p1]; 1631 buf[p1] = buf[p2]; 1632 buf[p2] = t; 1633 } 1634 1635 size_t cnt = 0; 1636 1637 for( size_t pos = 0, len = buf.length; pos < len; ++pos ) 1638 { 1639 if( pred( buf[pos] ) ) 1640 ++cnt; 1641 else 1642 exch( pos, pos - cnt ); 1643 } 1644 return buf.length - cnt; 1645 } 1646 } 1647 1648 1649 template removeIf( Buf, Pred ) 1650 { 1651 size_t removeIf( Buf buf, Pred pred ) 1652 { 1653 return removeIf_!(ElemTypeOf!(Buf), Pred).fn( buf, pred ); 1654 } 1655 } 1656 1657 1658 debug( UnitTest ) 1659 { 1660 unittest 1661 { 1662 void test( char[] buf, bool delegate( char ) dg, size_t num ) 1663 { 1664 assert( removeIf( buf, dg ) == num ); 1665 foreach( pos, cur; buf ) 1666 { 1667 assert( pos < num ? !dg( cur ) : dg( cur ) ); 1668 } 1669 } 1670 1671 test( "abcdefghij".dup, ( char c ) { return c == 'x'; }, 10 ); 1672 test( "xabcdefghi".dup, ( char c ) { return c == 'x'; }, 9 ); 1673 test( "abcdefghix".dup, ( char c ) { return c == 'x'; }, 9 ); 1674 test( "abxxcdefgh".dup, ( char c ) { return c == 'x'; }, 8 ); 1675 test( "xaxbcdxxex".dup, ( char c ) { return c == 'x'; }, 5 ); 1676 } 1677 } 1678 } 1679 1680 1681 //////////////////////////////////////////////////////////////////////////////// 1682 // Unique 1683 //////////////////////////////////////////////////////////////////////////////// 1684 1685 1686 version( TangoDoc ) 1687 { 1688 /** 1689 * Performs a linear scan of buf from [0 .. buf.length$(RP), moving all 1690 * but the first element of each consecutive group of duplicate elements to 1691 * the end of the sequence. The relative order of all remaining elements 1692 * will be preserved. Comparisons will be performed using the supplied 1693 * predicate or '==' if none is supplied. 1694 * 1695 * Params: 1696 * buf = The array to scan. This parameter is not marked 'ref' 1697 * to allow temporary slices to be modified. As buf is not resized 1698 * in any way, omitting the 'ref' qualifier has no effect on the 1699 * result of this operation, even though it may be viewed as a 1700 * side-effect. 1701 * pred = The evaluation predicate, which should return true if e1 is 1702 * equal to e2 and false if not. This predicate may be any 1703 * callable type. 1704 * 1705 * Returns: 1706 * The number of distinct sub-sequences in buf. 1707 */ 1708 size_t distinct( Elem[] buf, Pred2E pred = Pred2E.init ); 1709 } 1710 else 1711 { 1712 template distinct_( Elem, Pred = IsEqual!(Elem) ) 1713 { 1714 static assert( isCallableType!(Pred) ); 1715 1716 1717 size_t fn( Elem[] buf, Pred pred = Pred.init ) 1718 { 1719 // NOTE: Indexes are passed instead of references because DMD does 1720 // not inline the reference-based version. 1721 void exch( size_t p1, size_t p2 ) 1722 { 1723 Elem t = buf[p1]; 1724 buf[p1] = buf[p2]; 1725 buf[p2] = t; 1726 } 1727 1728 if( buf.length < 2 ) 1729 return buf.length; 1730 1731 size_t cnt = 0; 1732 Elem pat = buf[0]; 1733 1734 for( size_t pos = 1, len = buf.length; pos < len; ++pos ) 1735 { 1736 if( pred( buf[pos], pat ) ) 1737 ++cnt; 1738 else 1739 { 1740 pat = buf[pos]; 1741 exch( pos, pos - cnt ); 1742 } 1743 } 1744 return buf.length - cnt; 1745 } 1746 } 1747 1748 1749 template distinct( Buf ) 1750 { 1751 size_t distinct( Buf buf ) 1752 { 1753 return distinct_!(ElemTypeOf!(Buf)).fn( buf ); 1754 } 1755 } 1756 1757 1758 template distinct( Buf, Pred ) 1759 { 1760 size_t distinct( Buf buf, Pred pred ) 1761 { 1762 return distinct_!(ElemTypeOf!(Buf), Pred).fn( buf, pred ); 1763 } 1764 } 1765 1766 1767 debug( UnitTest ) 1768 { 1769 unittest 1770 { 1771 void test( char[] buf, char[] pat ) 1772 { 1773 assert( distinct( buf ) == pat.length ); 1774 foreach( pos, cur; pat ) 1775 { 1776 assert( buf[pos] == cur ); 1777 } 1778 } 1779 1780 test( "abcdefghij".dup, "abcdefghij".dup ); 1781 test( "aabcdefghi".dup, "abcdefghi".dup ); 1782 test( "bcdefghijj".dup, "bcdefghij".dup ); 1783 test( "abccdefghi".dup, "abcdefghi".dup ); 1784 test( "abccdddefg".dup, "abcdefg".dup ); 1785 } 1786 } 1787 } 1788 1789 1790 //////////////////////////////////////////////////////////////////////////////// 1791 // Shuffle 1792 //////////////////////////////////////////////////////////////////////////////// 1793 1794 1795 version( TangoDoc ) 1796 { 1797 /** 1798 * Performs a linear scan of buf from [2 .. buf.length$(RP), exchanging 1799 * each element with an element in the range [0 .. pos$(RP), where pos 1800 * represents the current array position. 1801 * 1802 * Params: 1803 * buf = The array to shuffle. 1804 * oper = The randomize operation, which should return a number in the 1805 * range [0 .. N$(RP) for any supplied value N. This routine 1806 * may be any callable type. 1807 */ 1808 void shuffle( Elem[] buf, Oper1A oper = Oper1A.init ); 1809 1810 } 1811 else 1812 { 1813 template shuffle_( Elem, Oper ) 1814 { 1815 static assert( isCallableType!(Oper) ); 1816 1817 1818 void fn( Elem[] buf, Oper oper ) 1819 { 1820 // NOTE: Indexes are passed instead of references because DMD does 1821 // not inline the reference-based version. 1822 void exch( size_t p1, size_t p2 ) 1823 { 1824 Elem t = buf[p1]; 1825 buf[p1] = buf[p2]; 1826 buf[p2] = t; 1827 } 1828 1829 for( size_t pos = buf.length - 1; pos > 0; --pos ) 1830 { 1831 exch( pos, oper( pos + 1 ) ); 1832 } 1833 } 1834 } 1835 1836 1837 template shuffle( Buf, Oper = RandOper!() ) 1838 { 1839 void shuffle( Buf buf, Oper oper = Oper.init ) 1840 { 1841 return shuffle_!(ElemTypeOf!(Buf), Oper).fn( buf, oper ); 1842 } 1843 } 1844 1845 1846 debug( UnitTest ) 1847 { 1848 unittest 1849 { 1850 char[] buf = "abcdefghijklmnopqrstuvwxyz".dup; 1851 char[] tmp = buf.dup; 1852 1853 assert( tmp == buf ); 1854 shuffle( tmp ); 1855 assert( tmp != buf ); 1856 } 1857 } 1858 } 1859 1860 1861 //////////////////////////////////////////////////////////////////////////////// 1862 // Partition 1863 //////////////////////////////////////////////////////////////////////////////// 1864 1865 1866 version( TangoDoc ) 1867 { 1868 /** 1869 * Partitions buf such that all elements that satisfy pred will be placed 1870 * before the elements that do not satisfy pred. The algorithm is not 1871 * required to be stable. 1872 * 1873 * Params: 1874 * buf = The array to partition. This parameter is not marked 'ref' 1875 * to allow temporary slices to be sorted. As buf is not resized 1876 * in any way, omitting the 'ref' qualifier has no effect on 1877 * the result of this operation, even though it may be viewed 1878 * as a side-effect. 1879 * pred = The evaluation predicate, which should return true if the 1880 * element satisfies the condition and false if not. This 1881 * predicate may be any callable type. 1882 * 1883 * Returns: 1884 * The number of elements that satisfy pred. 1885 */ 1886 size_t partition( Elem[] buf, Pred1E pred ); 1887 } 1888 else 1889 { 1890 template partition_( Elem, Pred = IsLess!(Elem) ) 1891 { 1892 static assert( isCallableType!(Pred ) ); 1893 1894 1895 size_t fn( Elem[] buf, Pred pred ) 1896 { 1897 // NOTE: Indexes are passed instead of references because DMD does 1898 // not inline the reference-based version. 1899 void exch( size_t p1, size_t p2 ) 1900 { 1901 Elem t = buf[p1]; 1902 buf[p1] = buf[p2]; 1903 buf[p2] = t; 1904 } 1905 1906 if( buf.length < 1 ) 1907 return 0; 1908 1909 size_t l = 0, 1910 r = buf.length, 1911 i = l, 1912 j = r - 1; 1913 1914 while( true ) 1915 { 1916 while( i < r && pred( buf[i] ) ) 1917 ++i; 1918 while( j > l && !pred( buf[j] ) ) 1919 --j; 1920 if( i >= j ) 1921 break; 1922 exch( i++, j-- ); 1923 } 1924 return i; 1925 } 1926 } 1927 1928 1929 template partition( Buf, Pred ) 1930 { 1931 size_t partition( Buf buf, Pred pred ) 1932 { 1933 return partition_!(ElemTypeOf!(Buf), Pred).fn( buf, pred ); 1934 } 1935 } 1936 1937 1938 debug( UnitTest ) 1939 { 1940 unittest 1941 { 1942 void test( char[] buf, bool delegate( char ) dg, size_t num ) 1943 { 1944 assert( partition( buf, dg ) == num ); 1945 for( size_t pos = 0; pos < buf.length; ++pos ) 1946 { 1947 assert( pos < num ? dg( buf[pos] ) : !dg( buf[pos] ) ); 1948 } 1949 } 1950 1951 test( "abcdefg".dup, ( char c ) { return c < 'a'; }, 0 ); 1952 test( "gfedcba".dup, ( char c ) { return c < 'a'; }, 0 ); 1953 test( "abcdefg".dup, ( char c ) { return c < 'h'; }, 7 ); 1954 test( "gfedcba".dup, ( char c ) { return c < 'h'; }, 7 ); 1955 test( "abcdefg".dup, ( char c ) { return c < 'd'; }, 3 ); 1956 test( "gfedcba".dup, ( char c ) { return c < 'd'; }, 3 ); 1957 test( "bbdaabc".dup, ( char c ) { return c < 'c'; }, 5 ); 1958 test( "f".dup, ( char c ) { return c == 'f'; }, 1 ); 1959 } 1960 } 1961 } 1962 1963 1964 //////////////////////////////////////////////////////////////////////////////// 1965 // Select 1966 //////////////////////////////////////////////////////////////////////////////// 1967 1968 1969 version( TangoDoc ) 1970 { 1971 /** 1972 * Partitions buf with num - 1 as a pivot such that the first num elements 1973 * will be less than or equal to the remaining elements in the array. 1974 * Comparisons will be performed using the supplied predicate or '<' if 1975 * none is supplied. The algorithm is not required to be stable. 1976 * 1977 * Params: 1978 * buf = The array to partition. This parameter is not marked 'ref' 1979 * to allow temporary slices to be sorted. As buf is not resized 1980 * in any way, omitting the 'ref' qualifier has no effect on 1981 * the result of this operation, even though it may be viewed 1982 * as a side-effect. 1983 * num = The number of elements which are considered significant in 1984 * this array, where num - 1 is the pivot around which partial 1985 * sorting will occur. For example, if num is buf.length / 2 1986 * then select will effectively partition the array around its 1987 * median value, with the elements in the first half of the array 1988 * evaluating as less than or equal to the elements in the second 1989 * half. 1990 * pred = The evaluation predicate, which should return true if e1 is 1991 * less than e2 and false if not. This predicate may be any 1992 * callable type. 1993 * 1994 * Returns: 1995 * The index of the pivot point, which will be the lesser of num - 1 and 1996 * buf.length. 1997 */ 1998 size_t select( Elem[] buf, Num num, Pred2E pred = Pred2E.init ); 1999 } 2000 else 2001 { 2002 template select_( Elem, Pred = IsLess!(Elem) ) 2003 { 2004 static assert( isCallableType!(Pred ) ); 2005 2006 2007 size_t fn( Elem[] buf, size_t num, Pred pred = Pred.init ) 2008 { 2009 // NOTE: Indexes are passed instead of references because DMD does 2010 // not inline the reference-based version. 2011 void exch( size_t p1, size_t p2 ) 2012 { 2013 Elem t = buf[p1]; 2014 buf[p1] = buf[p2]; 2015 buf[p2] = t; 2016 } 2017 2018 if( buf.length < 2 ) 2019 return buf.length; 2020 2021 size_t l = 0, 2022 r = buf.length - 1, 2023 k = num; 2024 2025 while( r > l ) 2026 { 2027 size_t i = l, 2028 j = r - 1; 2029 Elem v = buf[r]; 2030 2031 while( true ) 2032 { 2033 while( i < r && pred( buf[i], v ) ) 2034 ++i; 2035 while( j > l && pred( v, buf[j] ) ) 2036 --j; 2037 if( i >= j ) 2038 break; 2039 exch( i++, j-- ); 2040 } 2041 exch( i, r ); 2042 if( i >= k ) 2043 r = i - 1; 2044 if( i <= k ) 2045 l = i + 1; 2046 } 2047 return num - 1; 2048 } 2049 } 2050 2051 2052 template select( Buf, Num ) 2053 { 2054 size_t select( Buf buf, Num num ) 2055 { 2056 return select_!(ElemTypeOf!(Buf)).fn( buf, num ); 2057 } 2058 } 2059 2060 2061 template select( Buf, Num, Pred ) 2062 { 2063 size_t select( Buf buf, Num num, Pred pred ) 2064 { 2065 return select_!(ElemTypeOf!(Buf), Pred).fn( buf, num, pred ); 2066 } 2067 } 2068 2069 2070 debug( UnitTest ) 2071 { 2072 unittest 2073 { 2074 char[] buf = "efedcaabca".dup; 2075 size_t num = buf.length / 2; 2076 size_t pos = select( buf, num ); 2077 2078 assert( pos == num - 1 ); 2079 foreach( cur; buf[0 .. pos] ) 2080 assert( cur <= buf[pos] ); 2081 foreach( cur; buf[pos .. $] ) 2082 assert( cur >= buf[pos] ); 2083 } 2084 } 2085 } 2086 2087 2088 //////////////////////////////////////////////////////////////////////////////// 2089 // Sort 2090 //////////////////////////////////////////////////////////////////////////////// 2091 2092 2093 version( TangoDoc ) 2094 { 2095 /** 2096 * Sorts buf using the supplied predicate or '<' if none is supplied. The 2097 * algorithm is not required to be stable. The current implementation is 2098 * based on quicksort, but uses a three-way partitioning scheme to improve 2099 * performance for ranges containing duplicate values (Bentley and McIlroy, 2100 * 1993). 2101 * 2102 * Params: 2103 * buf = The array to sort. This parameter is not marked 'ref' to 2104 * allow temporary slices to be sorted. As buf is not resized 2105 * in any way, omitting the 'ref' qualifier has no effect on 2106 * the result of this operation, even though it may be viewed 2107 * as a side-effect. 2108 * pred = The evaluation predicate, which should return true if e1 is 2109 * less than e2 and false if not. This predicate may be any 2110 * callable type. 2111 */ 2112 void sort( Elem, Pred2E = IsLess!(Elem) )( Elem[] buf, Pred2E pred = Pred2E.init ); 2113 } 2114 else 2115 { 2116 template sort_( Elem, Pred = IsLess!(Elem) ) 2117 { 2118 static assert( isCallableType!(Pred ) ); 2119 2120 2121 void fn( Elem[] buf, Pred pred = Pred.init ) 2122 { 2123 bool equiv( Elem p1, Elem p2 ) 2124 { 2125 return !pred( p1, p2 ) && !pred( p2, p1 ); 2126 } 2127 2128 // NOTE: Indexes are passed instead of references because DMD does 2129 // not inline the reference-based version. 2130 void exch( size_t p1, size_t p2 ) 2131 { 2132 Elem t = buf[p1]; 2133 buf[p1] = buf[p2]; 2134 buf[p2] = t; 2135 } 2136 2137 // NOTE: This algorithm operates on the inclusive range [l .. r]. 2138 void insertionSort( size_t l, size_t r ) 2139 { 2140 for( size_t i = r; i > l; --i ) 2141 { 2142 // swap the min element to buf[0] to act as a sentinel 2143 if( pred( buf[i], buf[i - 1] ) ) 2144 exch( i, i - 1 ); 2145 } 2146 for( size_t i = l + 2; i <= r; ++i ) 2147 { 2148 size_t j = i; 2149 Elem v = buf[i]; 2150 2151 // don't need to test (j != l) because of the sentinel 2152 while( pred( v, buf[j - 1] ) ) 2153 { 2154 buf[j] = buf[j - 1]; 2155 j--; 2156 } 2157 buf[j] = v; 2158 } 2159 } 2160 2161 size_t medianOf( size_t l, size_t m, size_t r ) 2162 { 2163 if( pred( buf[m], buf[l] ) ) 2164 { 2165 if( pred( buf[r], buf[m] ) ) 2166 return m; 2167 else 2168 { 2169 if( pred( buf[r], buf[l] ) ) 2170 return r; 2171 else 2172 return l; 2173 } 2174 } 2175 else 2176 { 2177 if( pred( buf[r], buf[m] ) ) 2178 { 2179 if( pred( buf[r], buf[l] ) ) 2180 return l; 2181 else 2182 return r; 2183 } 2184 else 2185 return m; 2186 } 2187 } 2188 2189 // NOTE: This algorithm operates on the inclusive range [l .. r]. 2190 void quicksort( size_t l, size_t r, size_t d ) 2191 { 2192 if( r <= l ) 2193 return; 2194 2195 // HEURISTIC: Use insertion sort for sufficiently small arrays. 2196 enum { MIN_LENGTH = 80 } 2197 if( r - l < MIN_LENGTH ) 2198 return insertionSort( l, r ); 2199 2200 // HEURISTIC: If the recursion depth is too great, assume this 2201 // is a worst-case array and fail to heap sort. 2202 if( d-- == 0 ) 2203 { 2204 makeHeap( buf[l .. r+1], pred ); 2205 sortHeap( buf[l .. r+1], pred ); 2206 return; 2207 } 2208 2209 // HEURISTIC: Use the median-of-3 value as a pivot. Swap this 2210 // into r so quicksort remains untouched. 2211 exch( r, medianOf( l, l + (r - l) / 2, r ) ); 2212 2213 // This implementation of quicksort improves upon the classic 2214 // algorithm by partitioning the array into three parts, one 2215 // each for keys smaller than, equal to, and larger than the 2216 // partitioning element, v: 2217 // 2218 // |--less than v--|--equal to v--|--greater than v--[v] 2219 // l j i r 2220 // 2221 // This approach sorts ranges containing duplicate elements 2222 // more quickly. During processing, the following situation 2223 // is maintained: 2224 // 2225 // |--equal--|--less--|--[###]--|--greater--|--equal--[v] 2226 // l p i j q r 2227 // 2228 // Please note that this implementation varies from the typical 2229 // algorithm by replacing the use of signed index values with 2230 // unsigned values. 2231 2232 Elem v = buf[r]; 2233 size_t i = l, 2234 j = r, 2235 p = l, 2236 q = r; 2237 2238 while( true ) 2239 { 2240 while( pred( buf[i], v ) ) 2241 ++i; 2242 while( pred( v, buf[--j] ) ) 2243 if( j == l ) break; 2244 if( i >= j ) 2245 break; 2246 exch( i, j ); 2247 if( equiv( buf[i], v ) ) 2248 exch( p++, i ); 2249 if( equiv( v, buf[j] ) ) 2250 exch( --q, j ); 2251 ++i; 2252 } 2253 exch( i, r ); 2254 if( p < i ) 2255 { 2256 j = i - 1; 2257 for( size_t k = l; k < p; k++, j-- ) 2258 exch( k, j ); 2259 quicksort( l, j, d ); 2260 } 2261 if( ++i < q ) 2262 { 2263 for( size_t k = r - 1; k >= q; k--, i++ ) 2264 exch( k, i ); 2265 quicksort( i, r, d ); 2266 } 2267 } 2268 2269 size_t maxDepth( size_t x ) 2270 { 2271 size_t d = 0; 2272 2273 do 2274 { 2275 ++d; 2276 x /= 2; 2277 } while( x > 1 ); 2278 return d * 2; // same as "floor( log( x ) / log( 2 ) ) * 2" 2279 } 2280 2281 if( buf.length > 1 ) 2282 { 2283 quicksort( 0, buf.length - 1, maxDepth( buf.length ) ); 2284 } 2285 } 2286 } 2287 2288 2289 template sort( Buf ) 2290 { 2291 void sort( Buf buf ) 2292 { 2293 return sort_!(ElemTypeOf!(Buf)).fn( buf ); 2294 } 2295 } 2296 2297 2298 template sort( Buf, Pred ) 2299 { 2300 void sort( Buf buf, Pred pred ) 2301 { 2302 return sort_!(ElemTypeOf!(Buf), Pred).fn( buf, pred ); 2303 } 2304 } 2305 2306 2307 debug( UnitTest ) 2308 { 2309 unittest 2310 { 2311 void test( char[] buf ) 2312 { 2313 sort( buf ); 2314 char sav = buf[0]; 2315 foreach( cur; buf ) 2316 { 2317 assert( cur >= sav ); 2318 sav = cur; 2319 } 2320 } 2321 2322 test( "mkcvalsidivjoaisjdvmzlksvdjioawmdsvmsdfefewv".dup ); 2323 test( "asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf".dup ); 2324 test( "the quick brown fox jumped over the lazy dog".dup ); 2325 test( "abcdefghijklmnopqrstuvwxyz".dup ); 2326 test( "zyxwvutsrqponmlkjihgfedcba".dup ); 2327 } 2328 } 2329 } 2330 2331 2332 //////////////////////////////////////////////////////////////////////////////// 2333 // Lower Bound 2334 //////////////////////////////////////////////////////////////////////////////// 2335 2336 2337 version( TangoDoc ) 2338 { 2339 /** 2340 * Performs a binary search of buf, returning the index of the first 2341 * location where pat may be inserted without disrupting sort order. If 2342 * the sort order of pat precedes all elements in buf then 0 will be 2343 * returned. If the sort order of pat succeeds the largest element in buf 2344 * then buf.length will be returned. Comparisons will be performed using 2345 * the supplied predicate or '<' if none is supplied. 2346 * 2347 * Params: 2348 * buf = The sorted array to search. 2349 * pat = The pattern to search for. 2350 * pred = The evaluation predicate, which should return true if e1 is 2351 * less than e2 and false if not. This predicate may be any 2352 * callable type. 2353 * 2354 * Returns: 2355 * The index of the first match or buf.length if no match was found. 2356 */ 2357 size_t lbound( Elem[] buf, Elem pat, Pred2E pred = Pred2E.init ); 2358 } 2359 else 2360 { 2361 template lbound_( Elem, Pred = IsLess!(Elem) ) 2362 { 2363 static assert( isCallableType!(Pred) ); 2364 2365 2366 size_t fn( Elem[] buf, Elem pat, Pred pred = Pred.init ) 2367 { 2368 size_t beg = 0, 2369 end = buf.length, 2370 mid = end / 2; 2371 2372 while( beg < end ) 2373 { 2374 if( pred( buf[mid], pat ) ) 2375 beg = mid + 1; 2376 else 2377 end = mid; 2378 mid = beg + ( end - beg ) / 2; 2379 } 2380 return mid; 2381 } 2382 } 2383 2384 2385 template lbound( Buf, Pat ) 2386 { 2387 size_t lbound( Buf buf, Pat pat ) 2388 { 2389 return lbound_!(ElemTypeOf!(Buf)).fn( buf, pat ); 2390 } 2391 } 2392 2393 2394 template lbound( Buf, Pat, Pred ) 2395 { 2396 size_t lbound( Buf buf, Pat pat, Pred pred ) 2397 { 2398 return lbound_!(ElemTypeOf!(Buf), Pred).fn( buf, pat, pred ); 2399 } 2400 } 2401 2402 2403 debug( UnitTest ) 2404 { 2405 unittest 2406 { 2407 assert( lbound( "bcefg", 'a' ) == 0 ); 2408 assert( lbound( "bcefg", 'h' ) == 5 ); 2409 assert( lbound( "bcefg", 'd' ) == 2 ); 2410 assert( lbound( "bcefg", 'e' ) == 2 ); 2411 } 2412 } 2413 } 2414 2415 2416 //////////////////////////////////////////////////////////////////////////////// 2417 // Upper Bound 2418 //////////////////////////////////////////////////////////////////////////////// 2419 2420 2421 version( TangoDoc ) 2422 { 2423 /** 2424 * Performs a binary search of buf, returning the index of the first 2425 * location beyond where pat may be inserted without disrupting sort order. 2426 * If the sort order of pat precedes all elements in buf then 0 will be 2427 * returned. If the sort order of pat succeeds the largest element in buf 2428 * then buf.length will be returned. Comparisons will be performed using 2429 * the supplied predicate or '<' if none is supplied. 2430 * 2431 * Params: 2432 * buf = The sorted array to search. 2433 * pat = The pattern to search for. 2434 * pred = The evaluation predicate, which should return true if e1 is 2435 * less than e2 and false if not. This predicate may be any 2436 * callable type. 2437 * 2438 * Returns: 2439 * The index of the first match or buf.length if no match was found. 2440 */ 2441 size_t ubound( Elem[] buf, Elem pat, Pred2E pred = Pred2E.init ); 2442 } 2443 else 2444 { 2445 template ubound_( Elem, Pred = IsLess!(Elem) ) 2446 { 2447 static assert( isCallableType!(Pred) ); 2448 2449 2450 size_t fn( Elem[] buf, Elem pat, Pred pred = Pred.init ) 2451 { 2452 size_t beg = 0, 2453 end = buf.length, 2454 mid = end / 2; 2455 2456 while( beg < end ) 2457 { 2458 if( !pred( pat, buf[mid] ) ) 2459 beg = mid + 1; 2460 else 2461 end = mid; 2462 mid = beg + ( end - beg ) / 2; 2463 } 2464 return mid; 2465 } 2466 } 2467 2468 2469 template ubound( Buf, Pat ) 2470 { 2471 size_t ubound( Buf buf, Pat pat ) 2472 { 2473 return ubound_!(ElemTypeOf!(Buf)).fn( buf, pat ); 2474 } 2475 } 2476 2477 2478 template ubound( Buf, Pat, Pred ) 2479 { 2480 size_t ubound( Buf buf, Pat pat, Pred pred ) 2481 { 2482 return ubound_!(ElemTypeOf!(Buf), Pred).fn( buf, pat, pred ); 2483 } 2484 } 2485 2486 2487 debug( UnitTest ) 2488 { 2489 unittest 2490 { 2491 assert( ubound( "bcefg", 'a' ) == 0 ); 2492 assert( ubound( "bcefg", 'h' ) == 5 ); 2493 assert( ubound( "bcefg", 'd' ) == 2 ); 2494 assert( ubound( "bcefg", 'e' ) == 3 ); 2495 } 2496 } 2497 } 2498 2499 2500 //////////////////////////////////////////////////////////////////////////////// 2501 // Binary Search 2502 //////////////////////////////////////////////////////////////////////////////// 2503 2504 2505 version( TangoDoc ) 2506 { 2507 /** 2508 * Performs a binary search of buf, returning true if an element equivalent 2509 * to pat is found. Comparisons will be performed using the supplied 2510 * predicate or '<' if none is supplied. 2511 * 2512 * Params: 2513 * buf = The sorted array to search. 2514 * pat = The pattern to search for. 2515 * pred = The evaluation predicate, which should return true if e1 is 2516 * less than e2 and false if not. This predicate may be any 2517 * callable type. 2518 * 2519 * Returns: 2520 * True if an element equivalent to pat is found, false if not. 2521 */ 2522 bool bsearch( Elem[] buf, Elem pat, Pred2E pred = Pred2E.init ); 2523 } 2524 else 2525 { 2526 template bsearch_( Elem, Pred = IsLess!(Elem) ) 2527 { 2528 static assert( isCallableType!(Pred) ); 2529 2530 2531 bool fn( Elem[] buf, Elem pat, Pred pred = Pred.init ) 2532 { 2533 size_t pos = lbound( buf, pat, pred ); 2534 return pos < buf.length && !( pat < buf[pos] ); 2535 } 2536 } 2537 2538 2539 template bsearch( Buf, Pat ) 2540 { 2541 bool bsearch( Buf buf, Pat pat ) 2542 { 2543 return bsearch_!(ElemTypeOf!(Buf)).fn( buf, pat ); 2544 } 2545 } 2546 2547 2548 template bsearch( Buf, Pat, Pred ) 2549 { 2550 bool bsearch( Buf buf, Pat pat, Pred pred ) 2551 { 2552 return bsearch_!(ElemTypeOf!(Buf), Pred).fn( buf, pat, pred ); 2553 } 2554 } 2555 2556 2557 debug( UnitTest ) 2558 { 2559 unittest 2560 { 2561 assert( !bsearch( "bcefg", 'a' ) ); 2562 assert( bsearch( "bcefg", 'b' ) ); 2563 assert( bsearch( "bcefg", 'c' ) ); 2564 assert( !bsearch( "bcefg", 'd' ) ); 2565 assert( bsearch( "bcefg", 'e' ) ); 2566 assert( bsearch( "bcefg", 'f' ) ); 2567 assert( bsearch( "bcefg", 'g' ) ); 2568 assert( !bsearch( "bcefg", 'h' ) ); 2569 } 2570 } 2571 } 2572 2573 2574 //////////////////////////////////////////////////////////////////////////////// 2575 // Includes 2576 //////////////////////////////////////////////////////////////////////////////// 2577 2578 2579 version( TangoDoc ) 2580 { 2581 /** 2582 * Performs a parallel linear scan of setA and setB from [0 .. N$(RP) 2583 * where N = min(setA.length, setB.length), returning true if setA 2584 * includes all elements in setB and false if not. Both setA and setB are 2585 * required to be sorted, and duplicates in setB require an equal number of 2586 * duplicates in setA. Comparisons will be performed using the supplied 2587 * predicate or '<' if none is supplied. 2588 * 2589 * Params: 2590 * setA = The sorted array to evaluate. 2591 * setB = The sorted array to match against. 2592 * pred = The evaluation predicate, which should return true if e1 is 2593 * less than e2 and false if not. This predicate may be any 2594 * callable type. 2595 * 2596 * Returns: 2597 * True if setA includes all elements in setB, false if not. 2598 */ 2599 bool includes( Elem[] setA, Elem[] setB, Pred2E pred = Pred2E.init ); 2600 } 2601 else 2602 { 2603 template includes_( Elem, Pred = IsLess!(Elem) ) 2604 { 2605 static assert( isCallableType!(Pred ) ); 2606 2607 2608 bool fn( Elem[] setA, Elem[] setB, Pred pred = Pred.init ) 2609 { 2610 size_t posA = 0, 2611 posB = 0; 2612 2613 while( posA < setA.length && posB < setB.length ) 2614 { 2615 if( pred( setB[posB], setA[posA] ) ) 2616 return false; 2617 else if( pred( setA[posA], setB[posB] ) ) 2618 ++posA; 2619 else 2620 ++posA, ++posB; 2621 } 2622 return posB == setB.length; 2623 } 2624 } 2625 2626 2627 template includes( BufA, BufB ) 2628 { 2629 bool includes( BufA setA, BufB setB ) 2630 { 2631 return includes_!(ElemTypeOf!(BufA)).fn( setA, setB ); 2632 } 2633 } 2634 2635 2636 template includes( BufA, BufB, Pred ) 2637 { 2638 bool includes( BufA setA, BufB setB, Pred pred ) 2639 { 2640 return includes_!(ElemTypeOf!(BufA), Pred).fn( setA, setB, pred ); 2641 } 2642 } 2643 2644 2645 debug( UnitTest ) 2646 { 2647 unittest 2648 { 2649 assert( includes( "abcdefg", "a" ) ); 2650 assert( includes( "abcdefg", "g" ) ); 2651 assert( includes( "abcdefg", "d" ) ); 2652 assert( includes( "abcdefg", "abcdefg" ) ); 2653 assert( includes( "aaaabbbcdddefgg", "abbbcdefg" ) ); 2654 2655 assert( !includes( "abcdefg", "aaabcdefg" ) ); 2656 assert( !includes( "abcdefg", "abcdefggg" ) ); 2657 assert( !includes( "abbbcdefg", "abbbbcdefg" ) ); 2658 } 2659 } 2660 } 2661 2662 2663 //////////////////////////////////////////////////////////////////////////////// 2664 // Union Of 2665 //////////////////////////////////////////////////////////////////////////////// 2666 2667 2668 version( TangoDoc ) 2669 { 2670 /** 2671 * Computes the union of setA and setB as a set operation and returns the 2672 * retult in a new sorted array. Both setA and setB are required to be 2673 * sorted. If either setA or setB contain duplicates, the result will 2674 * contain the larger number of duplicates from setA and setB. When an 2675 * overlap occurs, entries will be copied from setA. Comparisons will be 2676 * performed using the supplied predicate or '<' if none is supplied. 2677 * 2678 * Params: 2679 * setA = The first sorted array to evaluate. 2680 * setB = The second sorted array to evaluate. 2681 * pred = The evaluation predicate, which should return true if e1 is 2682 * less than e2 and false if not. This predicate may be any 2683 * callable type. 2684 * 2685 * Returns: 2686 * A new array containing the union of setA and setB. 2687 */ 2688 Elem[] unionOf( Elem[] setA, Elem[] setB, Pred2E pred = Pred2E.init ); 2689 } 2690 else 2691 { 2692 template unionOf_( Elem, Pred = IsLess!(Elem) ) 2693 { 2694 static assert( isCallableType!(Pred ) ); 2695 2696 2697 Elem[] fn( Elem[] setA, Elem[] setB, Pred pred = Pred.init ) 2698 { 2699 size_t posA = 0, 2700 posB = 0; 2701 Elem[] setU; 2702 2703 while( posA < setA.length && posB < setB.length ) 2704 { 2705 if( pred( setA[posA], setB[posB] ) ) 2706 setU ~= setA[posA++]; 2707 else if( pred( setB[posB], setA[posA] ) ) 2708 setU ~= setB[posB++]; 2709 else 2710 setU ~= setA[posA++], posB++; 2711 } 2712 setU ~= setA[posA .. $]; 2713 setU ~= setB[posB .. $]; 2714 return setU; 2715 } 2716 } 2717 2718 2719 template unionOf( BufA, BufB ) 2720 { 2721 ElemTypeOf!(BufA)[] unionOf( BufA setA, BufB setB ) 2722 { 2723 return unionOf_!(ElemTypeOf!(BufA)).fn( setA, setB ); 2724 } 2725 } 2726 2727 2728 template unionOf( BufA, BufB, Pred ) 2729 { 2730 ElemTypeOf!(BufA)[] unionOf( BufA setA, BufB setB, Pred pred ) 2731 { 2732 return unionOf_!(ElemTypeOf!(BufA), Pred).fn( setA, setB, pred ); 2733 } 2734 } 2735 2736 2737 debug( UnitTest ) 2738 { 2739 unittest 2740 { 2741 assert( unionOf( "", "" ) == "" ); 2742 assert( unionOf( "abc", "def" ) == "abcdef" ); 2743 assert( unionOf( "abbbcd", "aadeefg" ) == "aabbbcdeefg" ); 2744 } 2745 } 2746 } 2747 2748 2749 //////////////////////////////////////////////////////////////////////////////// 2750 // Intersection Of 2751 //////////////////////////////////////////////////////////////////////////////// 2752 2753 2754 version( TangoDoc ) 2755 { 2756 /** 2757 * Computes the intersection of setA and setB as a set operation and 2758 * returns the retult in a new sorted array. Both setA and setB are 2759 * required to be sorted. If either setA or setB contain duplicates, the 2760 * result will contain the smaller number of duplicates from setA and setB. 2761 * All entries will be copied from setA. Comparisons will be performed 2762 * using the supplied predicate or '<' if none is supplied. 2763 * 2764 * Params: 2765 * setA = The first sorted array to evaluate. 2766 * setB = The second sorted array to evaluate. 2767 * pred = The evaluation predicate, which should return true if e1 is 2768 * less than e2 and false if not. This predicate may be any 2769 * callable type. 2770 * 2771 * Returns: 2772 * A new array containing the intersection of setA and setB. 2773 */ 2774 Elem[] intersectionOf( Elem[] setA, Elem[] setB, Pred2E pred = Pred2E.init ); 2775 } 2776 else 2777 { 2778 template intersectionOf_( Elem, Pred = IsLess!(Elem) ) 2779 { 2780 static assert( isCallableType!(Pred ) ); 2781 2782 2783 Elem[] fn( Elem[] setA, Elem[] setB, Pred pred = Pred.init ) 2784 { 2785 size_t posA = 0, 2786 posB = 0; 2787 Elem[] setI; 2788 2789 while( posA < setA.length && posB < setB.length ) 2790 { 2791 if( pred( setA[posA], setB[posB] ) ) 2792 ++posA; 2793 else if( pred( setB[posB], setA[posA] ) ) 2794 ++posB; 2795 else 2796 setI ~= setA[posA++], posB++; 2797 } 2798 return setI; 2799 } 2800 } 2801 2802 2803 template intersectionOf( BufA, BufB ) 2804 { 2805 ElemTypeOf!(BufA)[] intersectionOf( BufA setA, BufB setB ) 2806 { 2807 return intersectionOf_!(ElemTypeOf!(BufA)).fn( setA, setB ); 2808 } 2809 } 2810 2811 2812 template intersectionOf( BufA, BufB, Pred ) 2813 { 2814 ElemTypeOf!(BufA)[] intersectionOf( BufA setA, BufB setB, Pred pred ) 2815 { 2816 return intersectionOf_!(ElemTypeOf!(BufA), Pred).fn( setA, setB, pred ); 2817 } 2818 } 2819 2820 2821 debug( UnitTest ) 2822 { 2823 unittest 2824 { 2825 assert( intersectionOf( "", "" ) == "" ); 2826 assert( intersectionOf( "abc", "def" ) == "" ); 2827 assert( intersectionOf( "abbbcd", "aabdddeefg" ) == "abd" ); 2828 } 2829 } 2830 } 2831 2832 2833 //////////////////////////////////////////////////////////////////////////////// 2834 // Missing From 2835 //////////////////////////////////////////////////////////////////////////////// 2836 2837 2838 version( TangoDoc ) 2839 { 2840 /** 2841 * Returns a new array containing all elements in setA which are not 2842 * present in setB. Both setA and setB are required to be sorted. 2843 * Comparisons will be performed using the supplied predicate or '<' 2844 * if none is supplied. 2845 * 2846 * Params: 2847 * setA = The first sorted array to evaluate. 2848 * setB = The second sorted array to evaluate. 2849 * pred = The evaluation predicate, which should return true if e1 is 2850 * less than e2 and false if not. This predicate may be any 2851 * callable type. 2852 * 2853 * Returns: 2854 * A new array containing the elements in setA that are not in setB. 2855 */ 2856 Elem[] missingFrom( Elem[] setA, Elem[] setB, Pred2E pred = Pred2E.init ); 2857 } 2858 else 2859 { 2860 template missingFrom_( Elem, Pred = IsLess!(Elem) ) 2861 { 2862 static assert( isCallableType!(Pred ) ); 2863 2864 2865 Elem[] fn( Elem[] setA, Elem[] setB, Pred pred = Pred.init ) 2866 { 2867 size_t posA = 0, 2868 posB = 0; 2869 Elem[] setM; 2870 2871 while( posA < setA.length && posB < setB.length ) 2872 { 2873 if( pred( setA[posA], setB[posB] ) ) 2874 setM ~= setA[posA++]; 2875 else if( pred( setB[posB], setA[posA] ) ) 2876 ++posB; 2877 else 2878 ++posA, ++posB; 2879 } 2880 setM ~= setA[posA .. $]; 2881 return setM; 2882 } 2883 } 2884 2885 2886 template missingFrom( BufA, BufB ) 2887 { 2888 ElemTypeOf!(BufA)[] missingFrom( BufA setA, BufB setB ) 2889 { 2890 return missingFrom_!(ElemTypeOf!(BufA)).fn( setA, setB ); 2891 } 2892 } 2893 2894 2895 template missingFrom( BufA, BufB, Pred ) 2896 { 2897 ElemTypeOf!(BufA)[] missingFrom( BufA setA, BufB setB, Pred pred ) 2898 { 2899 return missingFrom_!(ElemTypeOf!(BufA), Pred).fn( setA, setB, pred ); 2900 } 2901 } 2902 2903 2904 debug( UnitTest ) 2905 { 2906 unittest 2907 { 2908 assert( missingFrom( "", "" ) == "" ); 2909 assert( missingFrom( "", "abc" ) == "" ); 2910 assert( missingFrom( "abc", "" ) == "abc" ); 2911 assert( missingFrom( "abc", "abc" ) == "" ); 2912 assert( missingFrom( "abc", "def" ) == "abc" ); 2913 assert( missingFrom( "abbbcd", "abd" ) == "bbc" ); 2914 assert( missingFrom( "abcdef", "bc" ) == "adef" ); 2915 } 2916 } 2917 } 2918 2919 2920 //////////////////////////////////////////////////////////////////////////////// 2921 // Difference Of 2922 //////////////////////////////////////////////////////////////////////////////// 2923 2924 2925 version( TangoDoc ) 2926 { 2927 /** 2928 * Returns a new array containing all elements in setA which are not 2929 * present in setB and the elements in setB which are not present in 2930 * setA. Both setA and setB are required to be sorted. Comparisons 2931 * will be performed using the supplied predicate or '<' if none is 2932 * supplied. 2933 * 2934 * Params: 2935 * setA = The first sorted array to evaluate. 2936 * setB = The second sorted array to evaluate. 2937 * pred = The evaluation predicate, which should return true if e1 is 2938 * less than e2 and false if not. This predicate may be any 2939 * callable type. 2940 * 2941 * Returns: 2942 * A new array containing the elements in setA that are not in setB 2943 * and the elements in setB that are not in setA. 2944 */ 2945 Elem[] differenceOf( Elem[] setA, Elem[] setB, Pred2E pred = Pred2E.init ); 2946 } 2947 else 2948 { 2949 template differenceOf_( Elem, Pred = IsLess!(Elem) ) 2950 { 2951 static assert( isCallableType!(Pred ) ); 2952 2953 2954 Elem[] fn( Elem[] setA, Elem[] setB, Pred pred = Pred.init ) 2955 { 2956 size_t posA = 0, 2957 posB = 0; 2958 Elem[] setD; 2959 2960 while( posA < setA.length && posB < setB.length ) 2961 { 2962 if( pred( setA[posA], setB[posB] ) ) 2963 setD ~= setA[posA++]; 2964 else if( pred( setB[posB], setA[posA] ) ) 2965 setD ~= setB[posB++]; 2966 else 2967 ++posA, ++posB; 2968 } 2969 setD ~= setA[posA .. $]; 2970 setD ~= setB[posB .. $]; 2971 return setD; 2972 } 2973 } 2974 2975 2976 template differenceOf( BufA, BufB ) 2977 { 2978 ElemTypeOf!(BufA)[] differenceOf( BufA setA, BufB setB ) 2979 { 2980 return differenceOf_!(ElemTypeOf!(BufA)).fn( setA, setB ); 2981 } 2982 } 2983 2984 2985 template differenceOf( BufA, BufB, Pred ) 2986 { 2987 ElemTypeOf!(BufA)[] differenceOf( BufA setA, BufB setB, Pred pred ) 2988 { 2989 return differenceOf_!(ElemTypeOf!(BufA), Pred).fn( setA, setB, pred ); 2990 } 2991 } 2992 2993 2994 debug( UnitTest ) 2995 { 2996 unittest 2997 { 2998 assert( differenceOf( "", "" ) == "" ); 2999 assert( differenceOf( "", "abc" ) == "abc" ); 3000 assert( differenceOf( "abc", "" ) == "abc" ); 3001 assert( differenceOf( "abc", "abc" ) == "" ); 3002 assert( differenceOf( "abc", "def" ) == "abcdef" ); 3003 assert( differenceOf( "abbbcd", "abd" ) == "bbc" ); 3004 assert( differenceOf( "abd", "abbbcd" ) == "bbc" ); 3005 } 3006 } 3007 } 3008 3009 3010 //////////////////////////////////////////////////////////////////////////////// 3011 // Make Heap 3012 //////////////////////////////////////////////////////////////////////////////// 3013 3014 3015 version( TangoDoc ) 3016 { 3017 /** 3018 * Converts buf to a heap using the supplied predicate or '<' if none is 3019 * supplied. 3020 * 3021 * Params: 3022 * buf = The array to convert. This parameter is not marked 'ref' to 3023 * allow temporary slices to be sorted. As buf is not resized in 3024 * any way, omitting the 'ref' qualifier has no effect on the 3025 * result of this operation, even though it may be viewed as a 3026 * side-effect. 3027 * pred = The evaluation predicate, which should return true if e1 is 3028 * less than e2 and false if not. This predicate may be any 3029 * callable type. 3030 */ 3031 void makeHeap( Elem[] buf, Pred2E pred = Pred2E.init ); 3032 } 3033 else 3034 { 3035 template makeHeap_( Elem, Pred = IsLess!(Elem) ) 3036 { 3037 static assert( isCallableType!(Pred ) ); 3038 3039 3040 void fn( Elem[] buf, Pred pred = Pred.init ) 3041 { 3042 // NOTE: Indexes are passed instead of references because DMD does 3043 // not inline the reference-based version. 3044 void exch( size_t p1, size_t p2 ) 3045 { 3046 Elem t = buf[p1]; 3047 buf[p1] = buf[p2]; 3048 buf[p2] = t; 3049 } 3050 3051 void fixDown( size_t pos, size_t end ) 3052 { 3053 if( end <= pos ) 3054 return; 3055 while( pos <= ( end - 1 ) / 2 ) 3056 { 3057 size_t nxt = 2 * pos + 1; 3058 3059 if( nxt < end && pred( buf[nxt], buf[nxt + 1] ) ) 3060 ++nxt; 3061 if( !pred( buf[pos], buf[nxt] ) ) 3062 break; 3063 exch( pos, nxt ); 3064 pos = nxt; 3065 } 3066 } 3067 3068 if( buf.length < 2 ) 3069 return; 3070 3071 size_t end = buf.length - 1, 3072 pos = end / 2 + 2; 3073 3074 do 3075 { 3076 fixDown( --pos, end ); 3077 } while( pos > 0 ); 3078 } 3079 } 3080 3081 3082 template makeHeap( Buf ) 3083 { 3084 void makeHeap( Buf buf ) 3085 { 3086 return makeHeap_!(ElemTypeOf!(Buf)).fn( buf ); 3087 } 3088 } 3089 3090 3091 template makeHeap( Buf, Pred ) 3092 { 3093 void makeHeap( Buf buf, Pred pred ) 3094 { 3095 return makeHeap_!(ElemTypeOf!(Buf), Pred).fn( buf, pred ); 3096 } 3097 } 3098 3099 3100 debug( UnitTest ) 3101 { 3102 unittest 3103 { 3104 void basic( char[] buf ) 3105 { 3106 if( buf.length < 2 ) 3107 return; 3108 3109 size_t pos = 0, 3110 end = buf.length - 1; 3111 3112 while( pos <= ( end - 1 ) / 2 ) 3113 { 3114 assert( buf[pos] >= buf[2 * pos + 1] ); 3115 if( 2 * pos + 1 < end ) 3116 { 3117 assert( buf[pos] >= buf[2 * pos + 2] ); 3118 } 3119 ++pos; 3120 } 3121 } 3122 3123 void test( char[] buf ) 3124 { 3125 makeHeap( buf ); 3126 basic( buf ); 3127 } 3128 3129 test( "mkcvalsidivjoaisjdvmzlksvdjioawmdsvmsdfefewv".dup ); 3130 test( "asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf".dup ); 3131 test( "the quick brown fox jumped over the lazy dog".dup ); 3132 test( "abcdefghijklmnopqrstuvwxyz".dup ); 3133 test( "zyxwvutsrqponmlkjihgfedcba".dup ); 3134 test( "ba".dup ); 3135 test( "a".dup ); 3136 test( "".dup ); 3137 } 3138 } 3139 } 3140 3141 3142 //////////////////////////////////////////////////////////////////////////////// 3143 // Push Heap 3144 //////////////////////////////////////////////////////////////////////////////// 3145 3146 3147 version( TangoDoc ) 3148 { 3149 /** 3150 * Adds val to buf by appending it and adjusting it up the heap. 3151 * 3152 * Params: 3153 * buf = The heap to modify. This parameter is marked 'ref' because 3154 * buf.length will be altered. 3155 * val = The element to push onto buf. 3156 * pred = The evaluation predicate, which should return true if e1 is 3157 * less than e2 and false if not. This predicate may be any 3158 * callable type. 3159 */ 3160 void pushHeap( ref Elem[] buf, Elem val, Pred2E pred = Pred2E.init ); 3161 } 3162 else 3163 { 3164 template pushHeap_( Elem, Pred = IsLess!(Elem) ) 3165 { 3166 static assert( isCallableType!(Pred ) ); 3167 3168 3169 void fn( ref Elem[] buf, Elem val, Pred pred = Pred.init ) 3170 { 3171 // NOTE: Indexes are passed instead of references because DMD does 3172 // not inline the reference-based version. 3173 void exch( size_t p1, size_t p2 ) 3174 { 3175 Elem t = buf[p1]; 3176 buf[p1] = buf[p2]; 3177 buf[p2] = t; 3178 } 3179 3180 void fixUp( size_t pos ) 3181 { 3182 if( pos < 1 ) 3183 return; 3184 size_t par = ( pos - 1 ) / 2; 3185 while( pos > 0 && pred( buf[par], buf[pos] ) ) 3186 { 3187 exch( par, pos ); 3188 pos = par; 3189 par = ( pos - 1 ) / 2; 3190 } 3191 } 3192 3193 buf ~= val; 3194 if( buf.length > 1 ) 3195 { 3196 fixUp( buf.length - 1 ); 3197 } 3198 } 3199 } 3200 3201 3202 template pushHeap( Buf, Val ) 3203 { 3204 void pushHeap( ref Buf buf, Val val ) 3205 { 3206 return pushHeap_!(ElemTypeOf!(Buf)).fn( buf, val ); 3207 } 3208 } 3209 3210 3211 template pushHeap( Buf, Val, Pred ) 3212 { 3213 void pushHeap( ref Buf buf, Val val, Pred pred ) 3214 { 3215 return pushHeap_!(ElemTypeOf!(Buf), Pred).fn( buf, val, pred ); 3216 } 3217 } 3218 3219 3220 debug( UnitTest ) 3221 { 3222 unittest 3223 { 3224 void basic( char[] buf ) 3225 { 3226 if( buf.length < 2 ) 3227 return; 3228 3229 size_t pos = 0, 3230 end = buf.length - 1; 3231 3232 while( pos <= ( end - 1 ) / 2 ) 3233 { 3234 assert( buf[pos] >= buf[2 * pos + 1] ); 3235 if( 2 * pos + 1 < end ) 3236 { 3237 assert( buf[pos] >= buf[2 * pos + 2] ); 3238 } 3239 ++pos; 3240 } 3241 } 3242 3243 char[] buf; 3244 3245 foreach( cur; "abcdefghijklmnopqrstuvwxyz" ) 3246 { 3247 pushHeap( buf, cur ); 3248 basic( buf ); 3249 } 3250 3251 buf.length = 0; 3252 3253 foreach( cur; "zyxwvutsrqponmlkjihgfedcba" ) 3254 { 3255 pushHeap( buf, cur ); 3256 basic( buf ); 3257 } 3258 } 3259 } 3260 } 3261 3262 3263 //////////////////////////////////////////////////////////////////////////////// 3264 // Pop Heap 3265 //////////////////////////////////////////////////////////////////////////////// 3266 3267 3268 version( TangoDoc ) 3269 { 3270 /** 3271 * Removes the top element from buf by swapping it with the bottom element, 3272 * adjusting it down the heap, and reducing the length of buf by one. 3273 * 3274 * Params: 3275 * buf = The heap to modify. This parameter is marked 'ref' because 3276 * buf.length will be altered. 3277 * pred = The evaluation predicate, which should return true if e1 is 3278 * less than e2 and false if not. This predicate may be any 3279 * callable type. 3280 */ 3281 void popHeap( ref Elem[] buf, Pred2E pred = Pred2E.init ); 3282 } 3283 else 3284 { 3285 template popHeap_( Elem, Pred = IsLess!(Elem) ) 3286 { 3287 static assert( isCallableType!(Pred ) ); 3288 3289 3290 void fn( ref Elem[] buf, Pred pred = Pred.init ) 3291 { 3292 // NOTE: Indexes are passed instead of references because DMD does 3293 // not inline the reference-based version. 3294 void exch( size_t p1, size_t p2 ) 3295 { 3296 Elem t = buf[p1]; 3297 buf[p1] = buf[p2]; 3298 buf[p2] = t; 3299 } 3300 3301 void fixDown( size_t pos, size_t end ) 3302 { 3303 if( end <= pos ) 3304 return; 3305 while( pos <= ( end - 1 ) / 2 ) 3306 { 3307 size_t nxt = 2 * pos + 1; 3308 3309 if( nxt < end && pred( buf[nxt], buf[nxt + 1] ) ) 3310 ++nxt; 3311 if( !pred( buf[pos], buf[nxt] ) ) 3312 break; 3313 exch( pos, nxt ); 3314 pos = nxt; 3315 } 3316 } 3317 3318 if( buf.length > 1 ) 3319 { 3320 exch( 0, buf.length - 1 ); 3321 fixDown( 0, buf.length - 2 ); 3322 } 3323 if( buf.length > 0 ) 3324 { 3325 buf.length = buf.length - 1; 3326 } 3327 } 3328 } 3329 3330 3331 template popHeap( Buf ) 3332 { 3333 void popHeap( ref Buf buf ) 3334 { 3335 return popHeap_!(ElemTypeOf!(Buf)).fn( buf ); 3336 } 3337 } 3338 3339 3340 template popHeap( Buf, Pred ) 3341 { 3342 void popHeap( ref Buf buf, Pred pred ) 3343 { 3344 return popHeap_!(ElemTypeOf!(Buf), Pred).fn( buf, pred ); 3345 } 3346 } 3347 3348 3349 debug( UnitTest ) 3350 { 3351 unittest 3352 { 3353 void test( char[] buf ) 3354 { 3355 if( buf.length < 2 ) 3356 return; 3357 3358 size_t pos = 0, 3359 end = buf.length - 1; 3360 3361 while( pos <= ( end - 1 ) / 2 ) 3362 { 3363 assert( buf[pos] >= buf[2 * pos + 1] ); 3364 if( 2 * pos + 1 < end ) 3365 { 3366 assert( buf[pos] >= buf[2 * pos + 2] ); 3367 } 3368 ++pos; 3369 } 3370 } 3371 3372 char[] buf = "zyxwvutsrqponmlkjihgfedcba".dup; 3373 3374 while( buf.length > 0 ) 3375 { 3376 popHeap( buf ); 3377 test( buf ); 3378 } 3379 } 3380 } 3381 } 3382 3383 3384 //////////////////////////////////////////////////////////////////////////////// 3385 // Sort Heap 3386 //////////////////////////////////////////////////////////////////////////////// 3387 3388 3389 version( TangoDoc ) 3390 { 3391 /** 3392 * Sorts buf as a heap using the supplied predicate or '<' if none is 3393 * supplied. Calling makeHeap and sortHeap on an array in succession 3394 * has the effect of sorting the array using the heapsort algorithm. 3395 * 3396 * Params: 3397 * buf = The heap to sort. This parameter is not marked 'ref' to 3398 * allow temporary slices to be sorted. As buf is not resized 3399 * in any way, omitting the 'ref' qualifier has no effect on 3400 * the result of this operation, even though it may be viewed 3401 * as a side-effect. 3402 * pred = The evaluation predicate, which should return true if e1 is 3403 * less than e2 and false if not. This predicate may be any 3404 * callable type. 3405 */ 3406 void sortHeap( Elem[] buf, Pred2E pred = Pred2E.init ); 3407 } 3408 else 3409 { 3410 template sortHeap_( Elem, Pred = IsLess!(Elem) ) 3411 { 3412 static assert( isCallableType!(Pred ) ); 3413 3414 3415 void fn( Elem[] buf, Pred pred = Pred.init ) 3416 { 3417 // NOTE: Indexes are passed instead of references because DMD does 3418 // not inline the reference-based version. 3419 void exch( size_t p1, size_t p2 ) 3420 { 3421 Elem t = buf[p1]; 3422 buf[p1] = buf[p2]; 3423 buf[p2] = t; 3424 } 3425 3426 void fixDown( size_t pos, size_t end ) 3427 { 3428 if( end <= pos ) 3429 return; 3430 while( pos <= ( end - 1 ) / 2 ) 3431 { 3432 size_t nxt = 2 * pos + 1; 3433 3434 if( nxt < end && pred( buf[nxt], buf[nxt + 1] ) ) 3435 ++nxt; 3436 if( !pred( buf[pos], buf[nxt] ) ) 3437 break; 3438 exch( pos, nxt ); 3439 pos = nxt; 3440 } 3441 } 3442 3443 if( buf.length < 2 ) 3444 return; 3445 3446 size_t pos = buf.length - 1; 3447 3448 while( pos > 0 ) 3449 { 3450 exch( 0, pos ); 3451 fixDown( 0, --pos ); 3452 } 3453 } 3454 } 3455 3456 3457 template sortHeap( Buf ) 3458 { 3459 void sortHeap( Buf buf ) 3460 { 3461 return sortHeap_!(ElemTypeOf!(Buf)).fn( buf ); 3462 } 3463 } 3464 3465 3466 template sortHeap( Buf, Pred ) 3467 { 3468 void sortHeap( Buf buf, Pred pred ) 3469 { 3470 return sortHeap_!(ElemTypeOf!(Buf), Pred).fn( buf, pred ); 3471 } 3472 } 3473 3474 3475 debug( UnitTest ) 3476 { 3477 unittest 3478 { 3479 char[] buf = "zyxwvutsrqponmlkjihgfedcba".dup; 3480 3481 sortHeap( buf ); 3482 char sav = buf[0]; 3483 foreach( cur; buf ) 3484 { 3485 assert( cur >= sav ); 3486 sav = cur; 3487 } 3488 } 3489 } 3490 } 3491 3492 //////////////////////////////////////////////////////////////////////////////// 3493 // Map 3494 //////////////////////////////////////////////////////////////////////////////// 3495 3496 version (TangoDoc) 3497 { 3498 /** Apply a function to each element an array. The function's 3499 * return values are stored in another array. 3500 * 3501 * Params: 3502 * array = the array. 3503 * func = the function to apply. 3504 * buf = a buffer in which to store the results. This will be resized if it does not have sufficient space. 3505 * 3506 * Returns: 3507 * an array (the same as the buffer passed in, if possible) where the 3508 * ith element is the result of applying func to the ith element of the 3509 * input array 3510 */ 3511 Elem2[] map(Elem[] array, Map2E func, Elem2[] buf = null); 3512 } 3513 else 3514 { 3515 template map(Func, Array) 3516 { 3517 ReturnTypeOf!(Func)[] map(Array array, Func func, ReturnTypeOf!(Func)[] buf = null) 3518 { 3519 if (buf.length < array.length) 3520 { 3521 buf.length = array.length; 3522 } 3523 foreach (i, a; array) buf[i] = func(a); 3524 return buf; 3525 } 3526 } 3527 3528 debug (UnitTest) 3529 { 3530 unittest 3531 { 3532 auto arr = map([1, 17, 8, 12], (int i) { return i * 2L; }); 3533 assert(arr == [2L, 34L, 16L, 24L]); 3534 } 3535 } 3536 } 3537 3538 //////////////////////////////////////////////////////////////////////////////// 3539 // Reduce 3540 //////////////////////////////////////////////////////////////////////////////// 3541 3542 version (TangoDoc) 3543 { 3544 /** Reduce an array of elements to a single element, using a user-supplied 3545 * reductor function. 3546 * 3547 * If the array is empty, return the default value for the element type. 3548 * 3549 * If the array contains only one element, return that element. 3550 * 3551 * Otherwise, the reductor function will be called on every member of the 3552 * array and on every resulting element until there is only one element, 3553 * which is then returned. 3554 * 3555 * Params: 3556 * array = the array to reduce 3557 * func = the reductor function 3558 * 3559 * Returns: the single element reduction 3560 */ 3561 Elem reduce(Elem[] array, Reduce2E func); 3562 } 3563 else 3564 { 3565 template reduce(Array, Func) 3566 { 3567 static assert(isCallableType!(Func)); 3568 ReturnTypeOf!(Func) reduce(Array array, Func func) 3569 { 3570 if (array.length == 0) return ReturnTypeOf!(Func).init; 3571 auto e = array[0]; 3572 foreach (i, a; array) 3573 { 3574 if (i == 0) continue; 3575 e = func(e, a); 3576 } 3577 return e; 3578 } 3579 } 3580 3581 debug (UnitTest) 3582 { 3583 unittest 3584 { 3585 auto result = reduce([1, 17, 8, 12], (int i, int j) { return i * j; }); 3586 assert(result == 1632); 3587 } 3588 } 3589 } 3590 3591 //////////////////////////////////////////////////////////////////////////////// 3592 // Filter 3593 //////////////////////////////////////////////////////////////////////////////// 3594 3595 version( TangoDoc ) 3596 { 3597 /** 3598 * Performs a linear scan of buf from [0 .. buf.length$(RP), creating a new 3599 * array with just the elements that satisfy pred. The relative order of 3600 * elements will be preserved. 3601 * 3602 * Params: 3603 * array = The array to scan. 3604 * pred = The evaluation predicate, which should return true if the 3605 * element satisfies the condition and false if not. This 3606 * predicate may be any callable type. 3607 * buf = an optional buffer into which elements are filtered. This 3608 * is the array that gets returned to you. 3609 * 3610 * Returns: 3611 * A new array with just the elements from buf that satisfy pred. 3612 * 3613 * Notes: 3614 * While most Array functions that take an output buffer size that buffer 3615 * optimally, in this case, there is no way of knowing whether the output 3616 * will be empty or the entire input array. If you have special knowledge 3617 * in this regard, preallocating the output buffer will be advantageous. 3618 */ 3619 Elem[] filter(Elem[] array, Pred1E pred, Elem[] buf = null); 3620 } 3621 else 3622 { 3623 template filter(Array, Pred) 3624 { 3625 static assert(isCallableType!(Pred)); 3626 3627 ParameterTupleOf!(Pred)[0][] filter(Array array, Pred pred, ParameterTupleOf!(Pred)[0][] buf = null) 3628 { 3629 // Unfortunately, we don't know our output size -- it could be empty or 3630 // the length of the input array. So we won't try to do anything fancy 3631 // with preallocation. 3632 buf.length = 0; 3633 foreach (i, e; array) 3634 { 3635 if (pred(e)) 3636 { 3637 buf ~= e; 3638 } 3639 } 3640 return buf; 3641 } 3642 } 3643 3644 debug( UnitTest ) 3645 { 3646 unittest 3647 { 3648 void test( char[] buf, bool delegate( char ) dg, size_t num ) 3649 { 3650 char[] r = filter( buf, dg ); 3651 assert( r.length == num ); 3652 size_t rpos = 0; 3653 foreach( pos, cur; buf ) 3654 { 3655 if ( dg( cur ) ) 3656 { 3657 assert( r[rpos] == cur ); 3658 rpos++; 3659 } 3660 } 3661 assert( rpos == num ); 3662 } 3663 3664 test( "abcdefghij".dup, ( char c ) { return c == 'x'; }, 0 ); 3665 test( "xabcdefghi".dup, ( char c ) { return c == 'x'; }, 1 ); 3666 test( "abcdefghix".dup, ( char c ) { return c == 'x'; }, 1 ); 3667 test( "abxxcdefgh".dup, ( char c ) { return c == 'x'; }, 2 ); 3668 test( "xaxbcdxxex".dup, ( char c ) { return c == 'x'; }, 5 ); 3669 } 3670 } 3671 }