77# cython: boundscheck=False
88
99import platform
10+ from libcpp.vector cimport vector
1011
1112cdef extern from " simd_search.h" :
1213 size_t neon_count(const char * data, size_t length, char target)
@@ -15,21 +16,30 @@ cdef extern from "simd_search.h":
1516 int avx_search(const char * data, size_t length, char target)
1617 int neon_find_delimiter(const char * data, size_t length)
1718 int avx_find_delimiter(const char * data, size_t length)
19+ vector[size_t] neon_find_all(const char * data, size_t length, char target)
20+ vector[size_t] avx_find_all(const char * data, size_t length, char target)
21+
22+ cdef extern from " simd_string_ops.h" :
23+ void simd_to_upper(char * data, size_t length)
24+ void simd_to_lower(char * data, size_t length)
1825
1926# Architecture detection
2027cdef size_t (* simd_count)(const char * , size_t, char )
2128cdef int (* simd_search)(const char * , size_t, char )
2229cdef int (* simd_find_delimiter)(const char * , size_t)
30+ cdef vector[size_t] (* simd_find_all)(const char * , size_t, char )
2331
2432_arch = platform.machine().lower()
2533if _arch in (' arm64' , ' aarch64' ):
2634 simd_count = neon_count
2735 simd_search = neon_search
2836 simd_find_delimiter = neon_find_delimiter
37+ simd_find_all = neon_find_all
2938else :
3039 simd_count = avx_count
3140 simd_search = avx_search
3241 simd_find_delimiter = avx_find_delimiter
42+ simd_find_all = avx_find_all
3343
3444
3545# Expose simd_count to Python so higher-level code can reuse the optimized newline/count routine.
@@ -43,3 +53,70 @@ cpdef size_t count_instances(const unsigned char[::1] mv, char target=10):
4353 cdef const char * data = < const char * > udata
4454 cdef size_t data_len = mv.shape[0 ]
4555 return simd_count(data, data_len, target)
56+
57+
58+ # String case conversion functions
59+ def to_upper (bytes data ):
60+ """
61+ Convert ASCII characters in bytes to uppercase using SIMD.
62+ Non-ASCII bytes are left unchanged.
63+
64+ Returns a new bytes object with uppercase characters.
65+ """
66+ cdef size_t length = len (data)
67+ cdef bytearray result = bytearray(data)
68+ cdef char * ptr = < char * > result
69+ simd_to_upper(ptr, length)
70+ return bytes(result)
71+
72+
73+ def to_lower (bytes data ):
74+ """
75+ Convert ASCII characters in bytes to lowercase using SIMD.
76+ Non-ASCII bytes are left unchanged.
77+
78+ Returns a new bytes object with lowercase characters.
79+ """
80+ cdef size_t length = len (data)
81+ cdef bytearray result = bytearray(data)
82+ cdef char * ptr = < char * > result
83+ simd_to_lower(ptr, length)
84+ return bytes(result)
85+
86+
87+ # Character search functions
88+ def find_char (bytes data , int target ):
89+ """
90+ Find the first occurrence of a character in bytes using SIMD.
91+
92+ Returns the index of the first occurrence, or -1 if not found.
93+ """
94+ cdef const char * ptr = < const char * > (< char * > data)
95+ cdef size_t length = len (data)
96+ cdef char char_target = < char > target
97+ return simd_search(ptr, length, char_target)
98+
99+
100+ def count_char (bytes data , int target ):
101+ """
102+ Count occurrences of a character in bytes using SIMD.
103+
104+ Returns the count of occurrences.
105+ """
106+ cdef const char * ptr = < const char * > (< char * > data)
107+ cdef size_t length = len (data)
108+ cdef char char_target = < char > target
109+ return simd_count(ptr, length, char_target)
110+
111+
112+ def find_all_char (bytes data , int target ):
113+ """
114+ Find all occurrences of a character in bytes using SIMD.
115+
116+ Returns a list of indices where the character occurs.
117+ """
118+ cdef const char * ptr = < const char * > (< char * > data)
119+ cdef size_t length = len (data)
120+ cdef char char_target = < char > target
121+ cdef vector[size_t] positions = simd_find_all(ptr, length, char_target)
122+ return list (positions)
0 commit comments