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 }