• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IntelPython / dpctl / 15468000697

05 Jun 2025 01:14PM UTC coverage: 84.978% (-0.006%) from 84.984%
15468000697

Pull #2096

github

web-flow
Merge 58710ed66 into a26cac1ed
Pull Request #2096: Enable architecture selection for `DPCTL_TARGET_CUDA`

2967 of 3766 branches covered (78.78%)

Branch coverage included in aggregate %.

12233 of 14121 relevant lines covered (86.63%)

6884.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.57
/dpctl/tensor/_stride_utils.pxi
1
#                       Data Parallel Control (dpctl)
2
#
3
#  Copyright 2020-2025 Intel Corporation
4
#
5
#  Licensed under the Apache License, Version 2.0 (the "License");
6
#  you may not use this file except in compliance with the License.
7
#  You may obtain a copy of the License at
8
#
9
#     http://www.apache.org/licenses/LICENSE-2.0
10
#
11
#  Unless required by applicable law or agreed to in writing, software
12
#  distributed under the License is distributed on an "AS IS" BASIS,
13
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
#  See the License for the specific language governing permissions and
15
#  limitations under the License.
16

17
# distutils: language = c++
18
# cython: language_level=3
19

20
from cpython.mem cimport PyMem_Malloc
21
from cpython.ref cimport Py_INCREF
22
from cpython.tuple cimport PyTuple_New, PyTuple_SetItem
23

24

25
cdef int ERROR_MALLOC = 1
×
26
cdef int ERROR_INTERNAL = -1
×
27
cdef int ERROR_INCORRECT_ORDER = 2
×
28
cdef int ERROR_UNEXPECTED_STRIDES = 3
×
29

30
cdef int USM_ARRAY_C_CONTIGUOUS = 1
×
31
cdef int USM_ARRAY_F_CONTIGUOUS = 2
×
32
cdef int USM_ARRAY_WRITABLE = 4
×
33

34

35
cdef Py_ssize_t shape_to_elem_count(int nd, Py_ssize_t *shape_arr):
×
36
    """
37
    Computes number of elements in an array.
38
    """
39
    cdef Py_ssize_t count = 1
1✔
40
    for i in range(nd):
1✔
41
        count *= shape_arr[i]
1✔
42
    return count
1✔
43

44

45
cdef int _from_input_shape_strides(
×
46
    int nd, object shape, object strides, int itemsize, char order,
47
    Py_ssize_t **shape_ptr, Py_ssize_t **strides_ptr,
48
    Py_ssize_t *nelems, Py_ssize_t *min_disp, Py_ssize_t *max_disp,
49
    int *contig
50
):
51
    """
52
    Arguments: nd, shape, strides, itemsize, order
53
    Modifies:
54
        shape_ptr - pointer to C array for shape values
55
        stride_ptr - pointer to C array for strides values
56
        nelems - Number of elements in array
57
        min_disp = min( dot(strides, index), index for shape)
58
        max_disp = max( dor(strides, index), index for shape)
59
        contig = enumeration for array contiguity
60
    Returns: 0 on success, error code otherwise.
61
        On success pointers point to allocated arrays,
62
        Otherwise they are set to NULL
63
    """
64
    cdef int i
65
    cdef int j
66
    cdef bint all_incr = 1
1✔
67
    cdef bint all_decr = 1
1✔
68
    cdef bint strides_inspected = 0
1✔
69
    cdef Py_ssize_t elem_count = 1
1✔
70
    cdef Py_ssize_t min_shift = 0
1✔
71
    cdef Py_ssize_t max_shift = 0
1✔
72
    cdef Py_ssize_t str_i
73
    cdef Py_ssize_t* shape_arr
74
    cdef Py_ssize_t* strides_arr
75

76
    if (int(order) not in [ord("C"), ord("F"), ord("c"), ord("f")]):
1✔
77
        return ERROR_INCORRECT_ORDER
1✔
78

79
    # 0-d array
80
    if (nd == 0):
1✔
81
        contig[0] = (USM_ARRAY_C_CONTIGUOUS | USM_ARRAY_F_CONTIGUOUS)
1✔
82
        nelems[0] = 1
1✔
83
        min_disp[0] = 0
1✔
84
        max_disp[0] = 0
1✔
85
        shape_ptr[0] = <Py_ssize_t *>(<size_t>0)
1✔
86
        strides_ptr[0] = <Py_ssize_t *>(<size_t>0)
1✔
87
        return 0
1✔
88

89
    shape_arr = <Py_ssize_t*>PyMem_Malloc(nd * sizeof(Py_ssize_t))
1✔
90
    if (not shape_arr):
1✔
91
        return ERROR_MALLOC
×
92
    shape_ptr[0] = shape_arr
1✔
93
    for i in range(0, nd):
1✔
94
        shape_arr[i] = <Py_ssize_t> shape[i]
1✔
95
        elem_count *= shape_arr[i]
1✔
96
    if elem_count == 0:
1✔
97
        contig[0] = (USM_ARRAY_C_CONTIGUOUS | USM_ARRAY_F_CONTIGUOUS)
1✔
98
        nelems[0] = 1
1✔
99
        min_disp[0] = 0
1✔
100
        max_disp[0] = 0
1✔
101
        if strides is None:
1✔
102
            strides_ptr[0] = <Py_ssize_t *>(<size_t>0)
1✔
103
        else:
104
            strides_arr = <Py_ssize_t*>PyMem_Malloc(nd * sizeof(Py_ssize_t))
1✔
105
            if (not strides_arr):
1✔
106
                PyMem_Free(shape_ptr[0])
×
107
                shape_ptr[0] = <Py_ssize_t *>(<size_t>0)
×
108
                return ERROR_MALLOC
×
109
            strides_ptr[0] = strides_arr
1✔
110
            for i in range(0, nd):
1✔
111
                strides_arr[i] = <Py_ssize_t> strides[i]
1✔
112
        return 0
1✔
113
    nelems[0] = elem_count
1✔
114
    if (strides is None):
1✔
115
        # no need to allocate and populate strides
116
        if order == <char> ord("C") or order == <char> ord("c"):
1✔
117
            contig[0] = USM_ARRAY_C_CONTIGUOUS
1✔
118
        else:
119
            contig[0] = USM_ARRAY_F_CONTIGUOUS
1✔
120
        if nd == 1:
1✔
121
            contig[0] = USM_ARRAY_C_CONTIGUOUS | USM_ARRAY_F_CONTIGUOUS
1✔
122
        else:
123
            j = 0
1✔
124
            for i in range(nd):
1✔
125
                if shape_arr[i] > 1:
1✔
126
                    j = j + 1
1✔
127
            if j < 2:
1✔
128
                contig[0] = USM_ARRAY_C_CONTIGUOUS | USM_ARRAY_F_CONTIGUOUS
1✔
129
        min_disp[0] = 0
1✔
130
        max_disp[0] = (elem_count - 1)
1✔
131
        strides_ptr[0] = <Py_ssize_t *>(<size_t>0)
1✔
132
        return 0
1✔
133
    elif ((isinstance(strides, (list, tuple)) or hasattr(strides, "tolist"))
1✔
134
          and len(strides) == nd):
1✔
135
        strides_arr = <Py_ssize_t*>PyMem_Malloc(nd * sizeof(Py_ssize_t))
1✔
136
        if (not strides_arr):
1✔
137
            PyMem_Free(shape_ptr[0])
×
138
            shape_ptr[0] = <Py_ssize_t *>(<size_t>0)
×
139
            return ERROR_MALLOC
×
140
        strides_ptr[0] = strides_arr
1✔
141
        for i in range(0, nd):
1✔
142
            str_i = <Py_ssize_t> strides[i]
1✔
143
            strides_arr[i] = str_i
1✔
144
            if str_i > 0:
1✔
145
                max_shift += str_i * (shape_arr[i] - 1)
1✔
146
            else:
147
                min_shift += str_i * (shape_arr[i] - 1)
1✔
148
        min_disp[0] = min_shift
1✔
149
        max_disp[0] = max_shift
1✔
150
        if max_shift == min_shift + (elem_count - 1):
1✔
151
            if elem_count == 1:
1✔
152
                contig[0] = (USM_ARRAY_C_CONTIGUOUS | USM_ARRAY_F_CONTIGUOUS)
1✔
153
                return 0
1✔
154
            if nd == 1:
1✔
155
                if strides_arr[0] == 1:
1✔
156
                    contig[0] = USM_ARRAY_C_CONTIGUOUS | USM_ARRAY_F_CONTIGUOUS
1✔
157
                else:
158
                    contig[0] = 0
1✔
159
                return 0
1✔
160
            i = 0
1✔
161
            while i < nd:
1✔
162
                if shape_arr[i] == 1:
1✔
163
                    i = i + 1
1✔
164
                    continue
1✔
165
                j = i + 1
1✔
166
                while (j < nd and shape_arr[j] == 1):
1✔
167
                    j = j + 1
1✔
168
                if j < nd:
1✔
169
                    strides_inspected = 1
1✔
170
                    if all_incr:
1✔
171
                        all_incr = (
172
                            (strides_arr[i] > 0) and
1✔
173
                            (strides_arr[j] > 0) and
1✔
174
                            (strides_arr[i] <= strides_arr[j])
1✔
175
                        )
176
                    if all_decr:
1✔
177
                        all_decr = (
178
                            (strides_arr[i] > 0) and
1✔
179
                            (strides_arr[j] > 0) and
1✔
180
                            (strides_arr[i] >= strides_arr[j])
1✔
181
                        )
182
                    i = j
1✔
183
                else:
184
                    if not strides_inspected:
1✔
185
                        # all dimensions have size 1 except
186
                        # dimension 'i'. Array is both C and F
187
                        # contiguous
188
                        strides_inspected = 1
1✔
189
                        all_incr = (strides_arr[i] == 1)
1✔
190
                        all_decr = all_incr
1✔
191
                    break
1✔
192
            # should only set contig flags on actually obtained
193
            # values, rather than default values
194
            all_incr = all_incr and strides_inspected
1✔
195
            all_decr = all_decr and strides_inspected
1✔
196
            if all_incr and all_decr:
1✔
197
                contig[0] = (USM_ARRAY_C_CONTIGUOUS | USM_ARRAY_F_CONTIGUOUS)
1✔
198
            elif all_incr:
1✔
199
                contig[0] = USM_ARRAY_F_CONTIGUOUS
1✔
200
            elif all_decr:
1✔
201
                contig[0] = USM_ARRAY_C_CONTIGUOUS
1✔
202
            else:
203
                contig[0] = 0
1✔
204
            return 0
1✔
205
        else:
206
            contig[0] = 0  # non-contiguous
1✔
207
        return 0
1✔
208
    else:
209
        PyMem_Free(shape_ptr[0])
1✔
210
        shape_ptr[0] = <Py_ssize_t *>(<size_t>0)
1✔
211
        return ERROR_UNEXPECTED_STRIDES
1✔
212
    # return ERROR_INTERNAL
213

214

215
cdef object _make_int_tuple(int nd, const Py_ssize_t *ary):
×
216
    """
217
    Makes Python tuple from C array
218
    """
219
    cdef tuple res
220
    cdef object tmp
221
    if (ary):
1✔
222
        res = PyTuple_New(nd)
1✔
223
        for i in range(nd):
1✔
224
            tmp = <object>ary[i]
1✔
225
            Py_INCREF(tmp)  # SetItem steals the reference
1✔
226
            PyTuple_SetItem(res, i, tmp)
1✔
227
        return res
1✔
228
    else:
229
        return None
×
230

231

232
cdef object _make_reversed_int_tuple(int nd, const Py_ssize_t *ary):
1✔
233
    """
234
    Makes Python reversed tuple from C array
235
    """
236
    cdef tuple res
237
    cdef object tmp
238
    cdef int i
239
    cdef int nd_1
240
    if (ary):
1✔
241
        res = PyTuple_New(nd)
1✔
242
        nd_1 = nd - 1
1✔
243
        for i in range(nd):
1✔
244
            tmp = <object>ary[i]
1✔
245
            Py_INCREF(tmp)  # SetItem steals the reference
1✔
246
            PyTuple_SetItem(res, nd_1 - i, tmp)
1✔
247
        return res
1✔
248
    else:
249
        return None
×
250

251

252
cdef object _c_contig_strides(int nd, Py_ssize_t *shape):
×
253
    """
254
    Makes Python tuple for strides of C-contiguous array
255
    """
256
    cdef tuple cc_strides = PyTuple_New(nd)
1✔
257
    cdef object si = 1
1✔
258
    cdef int i
259
    cdef int nd_1 = nd - 1
1✔
260
    for i in range(0, nd):
1✔
261
        Py_INCREF(si)  # SetItem steals the reference
1✔
262
        PyTuple_SetItem(cc_strides, nd_1 - i, si)
1✔
263
        si = si * shape[nd_1 - i]
1✔
264
    return cc_strides
1✔
265

266

267
cdef object _f_contig_strides(int nd, Py_ssize_t *shape):
×
268
    """
269
    Makes Python tuple for strides of F-contiguous array
270
    """
271
    cdef tuple fc_strides = PyTuple_New(nd)
1✔
272
    cdef object si = 1
1✔
273
    for i in range(0, nd):
1✔
274
        Py_INCREF(si)  # SetItem steals the reference
1✔
275
        PyTuple_SetItem(fc_strides, i, si)
1✔
276
        si = si * shape[i]
1✔
277
    return fc_strides
1✔
278

279
cdef object _swap_last_two(tuple t):
×
280
    """
281
    Swap last two elements of a tuple
282
    """
283
    cdef int nd = len(t)
1✔
284
    cdef tuple res
285
    cdef int i
286
    cdef object tmp
287
    if (nd < 2):
1✔
288
        return t
×
289
    res = PyTuple_New(nd)
1✔
290
    # copy all elements except the last two
291
    for i in range(0, nd-2):
1✔
292
        tmp = t[i]
1✔
293
        Py_INCREF(tmp)  # SetItem steals the reference
1✔
294
        PyTuple_SetItem(res, i, tmp)
1✔
295
    # swap the last two elements
296
    tmp = t[nd-1]
1✔
297
    Py_INCREF(tmp)  # SetItem steals
1✔
298
    PyTuple_SetItem(res, nd - 2, tmp)
1✔
299
    tmp = t[nd-2]
1✔
300
    Py_INCREF(tmp)  # SetItem steals
1✔
301
    PyTuple_SetItem(res, nd - 1, tmp)
1✔
302
    return res
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc