| ... | @@ -1746,6 +1746,7 @@ test countScalar { | ... | @@ -1746,6 +1746,7 @@ test countScalar { |
| 1746 | // | 1746 | // |
| 1747 | /// See also: `containsAtLeastScalar` | 1747 | /// See also: `containsAtLeastScalar` |
| 1748 | pub fn containsAtLeast(comptime T: type, haystack: []const T, expected_count: usize, needle: []const T) bool { | 1748 | pub fn containsAtLeast(comptime T: type, haystack: []const T, expected_count: usize, needle: []const T) bool { |
| | 1749 | if (needle.len == 1) return containsAtLeastScalar(T, haystack, expected_count, needle[0]); |
| 1749 | assert(needle.len > 0); | 1750 | assert(needle.len > 0); |
| 1750 | if (expected_count == 0) return true; | 1751 | if (expected_count == 0) return true; |
| 1751 | | 1752 | |
| ... | @@ -1776,32 +1777,52 @@ test containsAtLeast { | ... | @@ -1776,32 +1777,52 @@ test containsAtLeast { |
| 1776 | try testing.expect(!containsAtLeast(u8, " radar radar ", 3, "radar")); | 1777 | try testing.expect(!containsAtLeast(u8, " radar radar ", 3, "radar")); |
| 1777 | } | 1778 | } |
| 1778 | | 1779 | |
| 1779 | /// Returns true if the haystack contains expected_count or more needles | 1780 | /// Deprecated in favor of `containsAtLeastScalar2`. |
| 1780 | // | 1781 | pub fn containsAtLeastScalar(comptime T: type, list: []const T, minimum: usize, element: T) bool { |
| 1781 | /// See also: `containsAtLeast` | 1782 | return containsAtLeastScalar2(T, list, element, minimum); |
| 1782 | pub fn containsAtLeastScalar(comptime T: type, haystack: []const T, expected_count: usize, needle: T) bool { | 1783 | } |
| 1783 | if (expected_count == 0) return true; | | |
| 1784 | | 1784 | |
| | 1785 | /// Returns true if `element` appears at least `minimum` number of times in `list`. |
| | 1786 | // |
| | 1787 | /// Related: |
| | 1788 | /// * `containsAtLeast` |
| | 1789 | /// * `countScalar` |
| | 1790 | pub fn containsAtLeastScalar2(comptime T: type, list: []const T, element: T, minimum: usize) bool { |
| | 1791 | const n = list.len; |
| | 1792 | var i: usize = 0; |
| 1785 | var found: usize = 0; | 1793 | var found: usize = 0; |
| 1786 | | 1794 | |
| 1787 | for (haystack) |item| { | 1795 | if (use_vectors_for_comparison and |
| 1788 | if (item == needle) { | 1796 | (@typeInfo(T) == .int or @typeInfo(T) == .float) and std.math.isPowerOfTwo(@bitSizeOf(T))) |
| 1789 | found += 1; | 1797 | { |
| 1790 | if (found == expected_count) return true; | 1798 | if (std.simd.suggestVectorLength(T)) |block_size| { |
| | 1799 | const Block = @Vector(block_size, T); |
| | 1800 | |
| | 1801 | const letter_mask: Block = @splat(element); |
| | 1802 | while (n - i >= block_size) : (i += block_size) { |
| | 1803 | const haystack_block: Block = list[i..][0..block_size].*; |
| | 1804 | found += std.simd.countTrues(letter_mask == haystack_block); |
| | 1805 | if (found >= minimum) return true; |
| | 1806 | } |
| 1791 | } | 1807 | } |
| 1792 | } | 1808 | } |
| 1793 | | 1809 | |
| | 1810 | for (list[i..n]) |item| { |
| | 1811 | found += @intFromBool(item == element); |
| | 1812 | if (found >= minimum) return true; |
| | 1813 | } |
| | 1814 | |
| 1794 | return false; | 1815 | return false; |
| 1795 | } | 1816 | } |
| 1796 | | 1817 | |
| 1797 | test containsAtLeastScalar { | 1818 | test containsAtLeastScalar2 { |
| 1798 | try testing.expect(containsAtLeastScalar(u8, "aa", 0, 'a')); | 1819 | try testing.expect(containsAtLeastScalar2(u8, "aa", 'a', 0)); |
| 1799 | try testing.expect(containsAtLeastScalar(u8, "aa", 1, 'a')); | 1820 | try testing.expect(containsAtLeastScalar2(u8, "aa", 'a', 1)); |
| 1800 | try testing.expect(containsAtLeastScalar(u8, "aa", 2, 'a')); | 1821 | try testing.expect(containsAtLeastScalar2(u8, "aa", 'a', 2)); |
| 1801 | try testing.expect(!containsAtLeastScalar(u8, "aa", 3, 'a')); | 1822 | try testing.expect(!containsAtLeastScalar2(u8, "aa", 'a', 3)); |
| 1802 | | 1823 | |
| 1803 | try testing.expect(containsAtLeastScalar(u8, "adadda", 3, 'd')); | 1824 | try testing.expect(containsAtLeastScalar2(u8, "adadda", 'd', 3)); |
| 1804 | try testing.expect(!containsAtLeastScalar(u8, "adadda", 4, 'd')); | 1825 | try testing.expect(!containsAtLeastScalar2(u8, "adadda", 'd', 4)); |
| 1805 | } | 1826 | } |
| 1806 | | 1827 | |
| 1807 | /// Reads an integer from memory with size equal to bytes.len. | 1828 | /// Reads an integer from memory with size equal to bytes.len. |