|
44 | 44 | * $(LREF anySatisfy) |
45 | 45 | * $(LREF staticIndexOf) |
46 | 46 | * )) |
47 | | - * $(TR $(TD Boolean template predicate operators) $(TD |
| 47 | + * $(TR $(TD Template predicates) $(TD |
48 | 48 | * $(LREF templateAnd) |
49 | 49 | * $(LREF templateNot) |
50 | 50 | * $(LREF templateOr) |
| 51 | + * $(LREF staticIsSorted) |
51 | 52 | * )) |
52 | 53 | * $(TR $(TD Template instantiation) $(TD |
53 | 54 | * $(LREF ApplyLeft) |
@@ -1393,9 +1394,15 @@ template staticSort(alias cmp, Seq...) |
1393 | 1394 | } |
1394 | 1395 | else |
1395 | 1396 | { |
1396 | | - private alias bottom = staticSort!(cmp, Seq[0 .. $ / 2]); |
| 1397 | + private alias btm = staticSort!(cmp, Seq[0 .. $ / 2]); |
1397 | 1398 | private alias top = staticSort!(cmp, Seq[$ / 2 .. $]); |
1398 | | - alias staticSort = staticMerge!(cmp, Seq.length / 2, bottom, top); |
| 1399 | + |
| 1400 | + static if (isLessEq!(cmp, btm[$ - 1], top[0])) |
| 1401 | + alias staticSort = AliasSeq!(btm, top); // already ascending |
| 1402 | + else static if (isLessEq!(cmp, top[$ - 1], btm[0])) |
| 1403 | + alias staticSort = AliasSeq!(top, btm); // already descending |
| 1404 | + else |
| 1405 | + alias staticSort = staticMerge!(cmp, Seq.length / 2, btm, top); |
1399 | 1406 | } |
1400 | 1407 | } |
1401 | 1408 |
|
@@ -1424,31 +1431,74 @@ private template staticMerge(alias cmp, int half, Seq...) |
1424 | 1431 | } |
1425 | 1432 | else |
1426 | 1433 | { |
1427 | | - private enum Result = cmp!(Seq[0], Seq[half]); |
1428 | | - static if (is(typeof(Result) == bool)) |
1429 | | - { |
1430 | | - private enum Check = Result; |
1431 | | - } |
1432 | | - else static if (is(typeof(Result) : int)) |
1433 | | - { |
1434 | | - private enum Check = Result <= 0; |
1435 | | - } |
1436 | | - else |
| 1434 | + static if (isLessEq!(cmp, Seq[0], Seq[half])) |
1437 | 1435 | { |
1438 | | - static assert(0, typeof(Result).stringof ~ " is not a value comparison type"); |
1439 | | - } |
1440 | | - static if (Check) |
1441 | | - { |
1442 | | - alias staticMerge = AliasSeq!(Seq[0], staticMerge!(cmp, half - 1, Seq[1 .. $])); |
| 1436 | + alias staticMerge = AliasSeq!(Seq[0], |
| 1437 | + staticMerge!(cmp, half - 1, Seq[1 .. $])); |
1443 | 1438 | } |
1444 | 1439 | else |
1445 | 1440 | { |
1446 | | - alias staticMerge = AliasSeq!(Seq[half], staticMerge!(cmp, half, |
1447 | | - Seq[0 .. half], Seq[half + 1 .. $])); |
| 1441 | + alias staticMerge = AliasSeq!(Seq[half], |
| 1442 | + staticMerge!(cmp, half, Seq[0 .. half], Seq[half + 1 .. $])); |
1448 | 1443 | } |
1449 | 1444 | } |
1450 | 1445 | } |
1451 | 1446 |
|
| 1447 | +private template isLessEq(alias cmp, Seq...) |
| 1448 | + if (Seq.length == 2) |
| 1449 | +{ |
| 1450 | + private enum Result = cmp!(Seq[1], Seq[0]); |
| 1451 | + static if (is(typeof(Result) == bool)) |
| 1452 | + enum isLessEq = !Result; |
| 1453 | + else static if (is(typeof(Result) : int)) |
| 1454 | + enum isLessEq = Result >= 0; |
| 1455 | + else |
| 1456 | + static assert(0, typeof(Result).stringof ~ " is not a value comparison type"); |
| 1457 | +} |
| 1458 | + |
| 1459 | +/** |
| 1460 | + * Checks if an $(LREF AliasSeq) is sorted according to $(D cmp). |
| 1461 | + * |
| 1462 | + * Parameters: |
| 1463 | + * cmp = A template that returns a $(D bool) (if its first argument is less than the second one) |
| 1464 | + * or an $(D int) (-1 means less than, 0 means equal, 1 means greater than) |
| 1465 | + * |
| 1466 | + * Seq = The $(LREF AliasSeq) to check |
| 1467 | + * |
| 1468 | + * Returns: `true` if `Seq` is sorted; otherwise `false` |
| 1469 | + */ |
| 1470 | +template staticIsSorted(alias cmp, Seq...) |
| 1471 | +{ |
| 1472 | + static if (Seq.length <= 1) |
| 1473 | + enum staticIsSorted = true; |
| 1474 | + else static if (Seq.length == 2) |
| 1475 | + enum staticIsSorted = isLessEq!(cmp, Seq[0], Seq[1]); |
| 1476 | + else |
| 1477 | + { |
| 1478 | + enum staticIsSorted = |
| 1479 | + isLessEq!(cmp, Seq[($ / 2) - 1], Seq[$ / 2]) && |
| 1480 | + staticIsSorted!(cmp, Seq[0 .. $ / 2]) && |
| 1481 | + staticIsSorted!(cmp, Seq[$ / 2 .. $]); |
| 1482 | + } |
| 1483 | +} |
| 1484 | + |
| 1485 | +/// |
| 1486 | +unittest |
| 1487 | +{ |
| 1488 | + enum Comp(int N1, int N2) = N1 < N2; |
| 1489 | + static assert( staticIsSorted!(Comp, 2, 2)); |
| 1490 | + static assert( staticIsSorted!(Comp, 2, 3, 7, 23)); |
| 1491 | + static assert(!staticIsSorted!(Comp, 7, 2, 3, 23)); |
| 1492 | +} |
| 1493 | + |
| 1494 | +/// |
| 1495 | +unittest |
| 1496 | +{ |
| 1497 | + enum Comp(T1, T2) = __traits(isUnsigned, T2) - __traits(isUnsigned, T1); |
| 1498 | + static assert( staticIsSorted!(Comp, uint, ubyte, ulong, short, long)); |
| 1499 | + static assert(!staticIsSorted!(Comp, uint, short, ubyte, long, ulong)); |
| 1500 | +} |
| 1501 | + |
1452 | 1502 | // : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : // |
1453 | 1503 | private: |
1454 | 1504 |
|
|
0 commit comments