Changeset 1712
- Timestamp:
- 07/03/10 21:42:27 (14 years ago)
- Files:
-
- trunk/phobos/std/algorithm.d (modified) (2 diffs)
- trunk/phobos/std/range.d (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/phobos/std/algorithm.d
r1703 r1712 265 265 266 266 auto repeatMap = map!"a"(repeat(1)); 267 267 static assert(isInfinite!(typeof(repeatMap))); 268 268 269 269 auto intRange = map!"a"([1,2,3]); 270 270 static assert(isRandomAccessRange!(typeof(intRange))); 271 271 272 272 foreach(DummyType; AllDummyRanges) { 273 273 DummyType d; 274 274 auto m = map!"a * a"(d); 275 276 static assert(propagatesRangeType!(typeof(m), DummyType)); 275 277 assert(equal(m, [1,4,9,16,25,36,49,64,81,100])); 276 278 } 277 279 } 278 280 279 281 // reduce 280 282 /** 281 283 Implements the homonym function (also known as $(D accumulate), $(D 282 284 compress), $(D inject), or $(D foldl)) present in various programming 283 285 languages of functional flavor. The call $(D reduce!(fun)(seed, 284 286 range)) first assigns $(D seed) to an internal variable $(D result), … … 1827 1829 b.length - (b.length - 1) / 2); 1828 1830 } 1829 1831 } 1830 1832 1831 1833 unittest 1832 1834 { 1833 1835 int[] a = [ -1, 0, 1, 2, 3, 4, 5 ]; 1834 1836 int[] b = [ 1, 2, 3 ]; 1835 1837 assert(find(a, b) == [ 1, 2, 3, 4, 5 ]); 1836 1838 assert(find(b, a).empty); 1839 1840 foreach(DummyType; AllDummyRanges) { 1841 DummyType d; 1842 auto findRes = find(d, 5); 1843 assert(equal(findRes, [5,6,7,8,9,10])); 1844 } 1837 1845 } 1838 1846 1839 1847 /// Ditto 1840 1848 struct BoyerMooreFinder(alias pred, Range) 1841 1849 { 1842 1850 private: 1843 1851 size_t skip[]; 1844 1852 int[ElementType!(Range)] occ; 1845 1853 Range needle; 1846 1854 trunk/phobos/std/range.d
r1704 r1712 147 147 ) AllDummyRanges; 148 148 149 149 alias TypeTuple!(1,2,3,4,5,6,7,8,9,0,11,12,13,14,15,16) DummyIndices; 150 150 }; 151 151 152 152 version(unittest) 153 153 { 154 154 import std.container, std.conv, std.math, std.stdio; 155 155 156 156 mixin(dummyRanges); 157 158 // Tests whether forward, bidirectional and random access properties are 159 // propagated properly from the base range(s) R to the higher order range 160 // H. Useful in combination with DummyRange for testing several higher 161 // order ranges. 162 template propagatesRangeType(H, R...) { 163 static if(allSatisfy!(isRandomAccessRange, R)) { 164 enum bool propagatesRangeType = isRandomAccessRange!H; 165 } else static if(allSatisfy!(isBidirectionalRange, R)) { 166 enum bool propagatesRangeType = isBidirectionalRange!H; 167 } else static if(allSatisfy!(isForwardRange, R)) { 168 enum bool propagatesRangeType = isForwardRange!H; 169 } else { 170 enum bool propagatesRangeType = isInputRange!H; 171 } 172 } 173 174 template propagatesLength(H, R...) { 175 static if(allSatisfy!(hasLength, R)) { 176 enum bool propagatesLength = hasLength!H; 177 } else { 178 enum bool propagatesLength = !hasLength!H; 179 } 180 } 157 181 } 158 182 159 183 /** 160 184 Returns $(D true) if $(D R) is an input range. An input range must 161 185 define the primitives $(D empty), $(D popFront), and $(D front). The 162 186 following code should compile for any input range. 163 187 164 188 ---- 165 189 R r; // can define a range object 166 190 if (r.empty) {} // can test for empty … … 753 777 test([ 1, 2, 3, 4, 5, 6 ], [ 6, 5, 4, 3, 2, 1 ]); 754 778 755 779 foreach(DummyType; AllDummyRanges) { 756 780 static if(!isBidirectionalRange!DummyType) { 757 781 static assert(!__traits(compiles, Retro!DummyType)); 758 782 } else { 759 783 DummyType dummyRange; 760 784 dummyRange.reinit(); 761 785 762 786 auto myRetro = retro(dummyRange); 787 static assert(propagatesRangeType!(typeof(myRetro), DummyType)); 763 788 assert(myRetro.front == 10); 764 789 assert(myRetro.back == 1); 765 790 766 791 static if(isRandomAccessRange!DummyType && hasLength!DummyType) { 767 792 assert(myRetro[0] == myRetro.front); 768 793 769 794 static if(DummyType.r == ReturnBy.Reference) { 770 795 myRetro[9]++; 771 796 assert(dummyRange[0] == 2); 772 797 myRetro.front++; … … 946 971 test(3, arr, [1, 4, 7, 10]); 947 972 test(4, arr, [1, 5, 9]); 948 973 949 974 foreach(DummyType; AllDummyRanges) { 950 975 static if(DummyType.r == ReturnBy.Reference) { 951 976 // Doesn't work yet w/o ref returns, see DMD bug 3294 and 3894. 952 977 DummyType dummyRange; 953 978 dummyRange.reinit(); 954 979 955 980 auto myStride = stride(dummyRange, 4); 981 982 // Should fail if no length and bidirectional b/c there's no way 983 // to know how much slack we have. 984 static if(hasLength!DummyType || !isBidirectionalRange!DummyType) { 985 static assert(propagatesRangeType!(typeof(myStride), DummyType)); 986 } 956 987 assert(myStride.front == 1); 957 988 assert(equal(myStride, [1, 5, 9])); 958 989 959 990 static if(hasLength!DummyType) { 960 991 assert(myStride.length == 3); 961 992 } 962 993 963 994 static if(isBidirectionalRange!DummyType && hasLength!DummyType) { 964 995 assert(myStride.back == 9); 965 996 } … … 1250 1281 assert(c[3] == 42); 1251 1282 } 1252 1283 1253 1284 // Make sure bug 3311 is fixed. ChainImpl should compile even if not all 1254 1285 // elements are mutable. 1255 1286 auto c = chain( iota(0, 10), iota(0, 10) ); 1256 1287 1257 1288 // Check that chain at least instantiates and compiles with every possible 1258 1289 // pair of DummyRange types, in either order. 1259 1290 1260 // This test should be uncommented when DMD bug 4379 gets fixed. 1291 // This test should be uncommented when DMD bug 4379 gets fixed, or if 1292 // you've made sure you've turned off -O. (Bug 4379 is triggered by -O). 1261 1293 // foreach(DummyType1; AllDummyRanges) { 1262 1294 // DummyType1 dummy1; 1263 1295 // foreach(DummyType2; AllDummyRanges) { 1264 1296 // DummyType2 dummy2; 1265 1297 // auto myChain = chain(dummy1, dummy2); 1298 // 1299 // static assert( 1300 // propagatesRangeType!(typeof(myChain), DummyType1, DummyType2) 1301 // ); 1302 // 1266 1303 // assert(myChain.front == 1); 1267 1304 // foreach(i; 0..dummyLength) { 1268 1305 // myChain.popFront(); 1269 1306 // } 1270 1307 // assert(myChain.front == 1); 1308 // 1309 // static if(isBidirectionalRange!DummyType1 && 1310 // isBidirectionalRange!DummyType2) { 1311 // assert(myChain.back == 10); 1312 // } 1313 // 1314 // static if(isRandomAccessRange!DummyType1 && 1315 // isRandomAccessRange!DummyType2) { 1316 // assert(myChain[0] == 1); 1317 // } 1271 1318 // } 1272 1319 // } 1273 1274 1320 } 1275 1321 1276 1322 /** 1277 1323 Iterates a random-access range starting from a given point and 1278 1324 progressively extending left and right from that point. If no initial 1279 1325 point is given, iteration starts from the middle of the 1280 1326 range. Iteration spans the entire range. 1281 1327 1282 1328 Example: 1283 1329 ---- … … 1504 1550 } 1505 1551 } 1506 1552 else static if (hasLength!(R)) 1507 1553 { 1508 1554 @property size_t length() 1509 1555 { 1510 1556 return min(_maxAvailable, original.length); 1511 1557 } 1512 1558 } 1513 1559 1514 static if (isRandomAccessRange!(R) && (hasLength!(R) || isInfinite!(R)))1560 static if (isRandomAccessRange!(R)) 1515 1561 { 1516 1562 void popBack() 1517 1563 { 1518 1564 enforce(_maxAvailable > 0, 1519 1565 "Attempting to popBack() past the beginning of a " 1520 1566 ~ Take.stringof); 1521 1567 --_maxAvailable; 1522 1568 } 1523 1569 1524 1570 mixin( 1525 1571 (byRef ? "ref " : "")~ 1526 1572 q{/+auto ref+/ ElementType back() 1527 1573 { 1528 1574 return original[this.length - 1]; 1529 1575 }}); 1530 } 1531 1532 static if (isRandomAccessRange!(R)) 1533 { 1576 1534 1577 mixin( 1535 1578 (byRef ? "ref " : "")~ 1536 1579 q{/+auto ref+/ ElementType opIndex(size_t index) 1537 1580 { 1538 1581 enforce(index < this.length, 1539 1582 "Attempting to index out of the bounds of a " 1540 1583 ~ Take.stringof); 1541 1584 return original[index]; 1542 1585 }}); 1543 1586 } … … 1578 1621 int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; 1579 1622 auto s = take(arr1, 5); 1580 1623 assert(s.length == 5); 1581 1624 assert(s[4] == 5); 1582 1625 assert(equal(s, [ 1, 2, 3, 4, 5 ][])); 1583 1626 assert(equal(retro(s), [ 5, 4, 3, 2, 1 ][])); 1584 1627 1585 1628 foreach(DummyType; AllDummyRanges) { 1586 1629 DummyType dummy; 1587 1630 auto t = take(dummy, 5); 1631 alias typeof(t) T; 1632 1633 static if(isRandomAccessRange!DummyType) { 1634 static assert(isRandomAccessRange!T); 1635 assert(t[4] == 5); 1636 } else static if(isForwardRange!DummyType) { 1637 static assert(isForwardRange!T); 1638 } 1639 1640 // Bidirectional ranges can't be propagated properly if they don't 1641 // also have random access. 1642 1588 1643 assert(equal(t, [1,2,3,4,5])); 1589 1644 } 1590 1645 } 1591 1646 1592 1647 /** 1593 1648 Eagerly advances $(D r) itself (not a copy) $(D n) times (by calling 1594 1649 $(D r.popFront) $(D n) times). The pass of $(D r) into $(D popFrontN) 1595 1650 is by reference, so the original range is affected. Completes in 1596 1651 $(BIGOH 1) steps for ranges that support slicing, and in $(BIGOH n) 1597 1652 time for all other ranges.
