1# mode: run
2
3import sys
4IS_PY3 = sys.version_info[0] >= 3
5IS_32BIT_PY2 = not IS_PY3 and sys.maxint < 2**32
6
7
8from libc cimport stdint
9from libc.stdint cimport int16_t as my_int16_t
10
11
12def unlongify(v):
13    # on 32bit Py2.x platforms, 'unsigned int' coerces to a Python long => fix doctest output here.
14    s = repr(v)
15    if IS_32BIT_PY2:
16        assert s.count('L') == s.count(',') + 1, s
17        s = s.replace('L', '')
18    return s
19
20
21def from_int_array():
22    """
23    >>> from_int_array()
24    [1, 2, 3]
25    """
26    cdef int[3] v
27    v[0] = 1
28    v[1] = 2
29    v[2] = 3
30    return v
31
32
33cpdef tuple tuple_from_int_array():
34    """
35    >>> tuple_from_int_array()
36    (1, 2, 3)
37    """
38    cdef int[3] v
39    v[0] = 1
40    v[1] = 2
41    v[2] = 3
42    assert isinstance(<tuple>v, tuple)
43    return v
44
45
46cdef extern from "stdint.h":
47    ctypedef unsigned long uint32_t
48
49
50def from_typedef_int_array():
51    """
52    >>> unlongify(from_typedef_int_array())
53    '[1, 2, 3]'
54    """
55    cdef uint32_t[3] v
56    v[0] = 1
57    v[1] = 2
58    v[2] = 3
59    return v
60
61
62cpdef tuple tuple_from_typedef_int_array():
63    """
64    >>> unlongify(tuple_from_typedef_int_array())
65    '(1, 2, 3)'
66    """
67    cdef uint32_t[3] v
68    v[0] = 1
69    v[1] = 2
70    v[2] = 3
71    return v
72
73
74def from_cimported_int_array():
75    """
76    >>> from_cimported_int_array()
77    [1, 2, 3]
78    """
79    cdef stdint.int32_t[3] v
80    v[0] = 1
81    v[1] = 2
82    v[2] = 3
83    return v
84
85
86def from_cimported_as_int_array():
87    """
88    >>> from_cimported_as_int_array()
89    [1, 2, 3]
90    """
91    cdef my_int16_t[3] v
92    v[0] = 1
93    v[1] = 2
94    v[2] = 3
95    return v
96
97
98def from_int_array_array():
99    """
100    >>> from_int_array_array()
101    [[11, 12, 13], [21, 22, 23]]
102    """
103    cdef int[2][3] v
104    v[0][0] = 11
105    v[0][1] = 12
106    v[0][2] = 13
107    v[1][0] = 21
108    v[1][1] = 22
109    v[1][2] = 23
110    return v
111
112
113def assign_int_array_array():
114    """
115    >>> assign_int_array_array()
116    [[11, 12, 13], [21, 22, 23]]
117    """
118    cdef int[2][3] v = [[11, 12, 13], [21, 22, 23]]
119    return v
120
121
122def assign_int_array_array_from_tuples():
123    """
124    >>> assign_int_array_array_from_tuples()
125    [[11, 12, 13], [21, 22, 23]]
126    """
127    cdef int[2][3] v = ([11, 12, 13], [21, 22, 23])
128    return v
129
130
131''' FIXME: this currently crashes:
132def assign_int_array_array_from_tuples():
133    """
134    >>> assign_int_array_array_from_tuples()
135    [[11, 12, 13], [21, 22, 23]]
136    """
137    cdef int[2][3] v = ((11, 12, 13), (21, 22, 23))
138    return v
139'''
140
141
142def build_from_list_of_arrays():
143    """
144    >>> build_from_list_of_arrays()
145    [[11, 12, 13], [21, 22, 23]]
146    """
147    cdef int[3] x = [11, 12, 13]
148    cdef int[3] y = [21, 22, 23]
149    cdef int[2][3] v = [x, y]
150    return v
151
152
153def build_from_tuple_of_arrays():
154    """
155    >>> build_from_tuple_of_arrays()
156    [[11, 12, 13], [21, 22, 23]]
157    """
158    cdef int[3] x = [11, 12, 13]
159    cdef int[3] y = [21, 22, 23]
160    cdef int[2][3] v = (x, y)
161    return v
162
163
164ctypedef struct MyStructType:
165    int x
166    double y
167
168
169cdef struct MyStruct:
170    int x
171    double y
172
173
174def from_struct_array():
175    """
176    >>> a, b = from_struct_array()
177    >>> a['x'], a['y']
178    (1, 2.0)
179    >>> b['x'], b['y']
180    (3, 4.0)
181    """
182    cdef MyStructType[2] v
183    cdef MyStruct[2] w
184    v[0] = MyStructType(1, 2)
185    v[1] = MyStructType(3, 4)
186    assert isinstance(<tuple>v, tuple)
187    assert isinstance(v, list)
188
189    w[0] = MyStruct(1, 2)
190    w[1] = MyStruct(3, 4)
191    assert (<object>w) == v
192    assert w == (<object>v)
193
194    return v
195
196
197def to_int_array(x):
198    """
199    >>> to_int_array([1, 2, 3])
200    (1, 2, 3)
201    >>> to_int_array([1, 2])
202    Traceback (most recent call last):
203    IndexError: not enough values found during array assignment, expected 3, got 2
204    >>> to_int_array([1, 2, 3, 4])
205    Traceback (most recent call last):
206    IndexError: too many values found during array assignment, expected 3
207    """
208    cdef int[3] v = x
209    return v[0], v[1], v[2]
210
211
212def to_int_array_array(x):
213    """
214    >>> to_int_array_array([[1, 2, 3], [4, 5, 6]])
215    (1, 2, 3, 4, 5, 6)
216    >>> to_int_array_array(iter([[1, 2, 3], [4, 5, 6]]))
217    (1, 2, 3, 4, 5, 6)
218
219    >>> to_int_array_array([[1, 2, 3]])
220    Traceback (most recent call last):
221    IndexError: not enough values found during array assignment, expected 2, got 1
222    >>> to_int_array_array(iter([[1, 2, 3]]))
223    Traceback (most recent call last):
224    IndexError: not enough values found during array assignment, expected 2, got 1
225
226    >>> to_int_array_array([[1, 2, 3], [4, 5]])
227    Traceback (most recent call last):
228    IndexError: not enough values found during array assignment, expected 3, got 2
229    >>> to_int_array_array(iter([[1, 2, 3], [4, 5]]))
230    Traceback (most recent call last):
231    IndexError: not enough values found during array assignment, expected 3, got 2
232
233    >>> to_int_array_array([[1, 2, 3, 4], [5, 6, 7]])
234    Traceback (most recent call last):
235    IndexError: too many values found during array assignment, expected 3
236    >>> to_int_array_array(iter([[1, 2, 3, 4], [5, 6, 7]]))
237    Traceback (most recent call last):
238    IndexError: too many values found during array assignment, expected 3
239    """
240    cdef int[2][3] v = x
241    return v[0][0], v[0][1], v[0][2], v[1][0], v[1][1], v[1][2]
242
243
244'''
245# FIXME: this isn't currently allowed
246cdef enum:
247    SIZE_A = 2
248    SIZE_B = 3
249
250def to_int_array_array_enumsize(x):
251    """
252    >>> to_int_array_array([[1, 2, 3], [4, 5, 6]])
253    (1, 2, 3, 4, 5, 6)
254    >>> to_int_array_array(iter([[1, 2, 3], [4, 5, 6]]))
255    (1, 2, 3, 4, 5, 6)
256    >>> to_int_array([1, 2])
257    Traceback (most recent call last):
258    IndexError: not enough values found during array assignment, expected 3, got 2
259    >>> to_int_array([1, 2, 3, 4])
260    Traceback (most recent call last):
261    IndexError: too many values found during array assignment, expected 3
262    """
263    cdef int[SIZE_A][SIZE_B] v = x
264    return v[0][0], v[0][1], v[0][2], v[1][0], v[1][1], v[1][2]
265'''
266
267
268'''
269# FIXME: this isn't currently supported
270def array_as_argument(int[2] x):
271    """
272    >>> array_as_argument([1, 2])
273    (1, 2)
274    """
275    return x[0], x[1]
276'''
277
278
279def to_int_array_slice(x):
280    """
281    >>> to_int_array_slice([1, 2, 3])
282    (1, 2, 3)
283    >>> to_int_array_slice([1, 2])
284    Traceback (most recent call last):
285    IndexError: not enough values found during array assignment, expected 3, got 2
286    >>> to_int_array_slice([1, 2, 3, 4])
287    Traceback (most recent call last):
288    IndexError: too many values found during array assignment, expected 3
289    """
290    cdef int[3] v
291    v[:] = x[:3]
292    assert v[0] == x[0]
293    assert v[1] == x[1]
294    assert v[2] == x[2]
295    v[:3] = [0, 0, 0]
296    assert v[0] == 0
297    assert v[1] == 0
298    assert v[2] == 0
299    v[:] = x
300    return v[0], v[1], v[2]
301
302
303def iterable_to_int_array(x):
304    """
305    >>> iterable_to_int_array(iter([1, 2, 3]))
306    (1, 2, 3)
307    >>> iterable_to_int_array(iter([1, 2]))
308    Traceback (most recent call last):
309    IndexError: not enough values found during array assignment, expected 3, got 2
310    >>> iterable_to_int_array(iter([1, 2, 3, 4]))
311    Traceback (most recent call last):
312    IndexError: too many values found during array assignment, expected 3
313    """
314    cdef int[3] v
315    v[:] = x
316    return v[0], v[1], v[2]
317
318
319def to_struct_array(x):
320    """
321    >>> a, b = to_struct_array(({'x': 1, 'y': 2}, {'x': 3, 'y': 4}))
322    >>> a['x'], a['y']
323    (1, 2.0)
324    >>> b['x'], b['y']
325    (3, 4.0)
326    """
327    cdef MyStructType[2] v
328    v[:] = x
329
330    cdef MyStruct[2] w
331    w[:] = x
332
333    assert w[0].x == v[0].x
334    assert w[0].y == v[0].y
335    assert w[1].x == v[1].x
336    assert w[1].y == v[1].y
337
338    return v[0], w[1]
339
340
341def to_struct_array_array(x):
342    """
343    >>> (a1, a2, a3), (b1, b2, b3) = to_struct_array_array([
344    ...     ({'x': 11, 'y': 12}, {'x': 13, 'y': 14}, {'x': 15, 'y': 16}),
345    ...     ({'x': 21, 'y': 22}, {'x': 23, 'y': 24}, {'x': 25, 'y': 26}),
346    ... ])
347    >>> a1['x'], a1['y']
348    (11, 12.0)
349    >>> b3['x'], b3['y']
350    (25, 26.0)
351    """
352    cdef MyStructType[2][3] v = x
353    return v[0], v[1]
354
355
356cdef struct StructWithArray:
357    int a
358    MyStruct[2] b
359
360
361def to_struct_with_array(x):
362    """
363    >>> x, y = to_struct_with_array([
364    ...     {'a': 11, 'b': [{'x': 12, 'y': 13}, {'x': 14, 'y': 15}]},
365    ...     {'a': 21, 'b': [{'x': 22, 'y': 23}, {'x': 24, 'y': 25}]},
366    ... ])
367    >>> x['a'], y['a']
368    (11, 21)
369    >>> sorted(sorted(v.items()) for v in x['b'])
370    [[('x', 12), ('y', 13.0)], [('x', 14), ('y', 15.0)]]
371    >>> sorted(sorted(v.items()) for v in y['b'])
372    [[('x', 22), ('y', 23.0)], [('x', 24), ('y', 25.0)]]
373
374    >>> x, y = to_struct_with_array(iter([
375    ...     {'a': 11, 'b': iter([{'x': 12, 'y': 13}, {'x': 14, 'y': 15}])},
376    ...     {'a': 21, 'b': iter([{'x': 22, 'y': 23}, {'x': 24, 'y': 25}])},
377    ... ]))
378    >>> x['a'], y['a']
379    (11, 21)
380    >>> sorted(sorted(v.items()) for v in x['b'])
381    [[('x', 12), ('y', 13.0)], [('x', 14), ('y', 15.0)]]
382    >>> sorted(sorted(v.items()) for v in y['b'])
383    [[('x', 22), ('y', 23.0)], [('x', 24), ('y', 25.0)]]
384    """
385    cdef StructWithArray[2] v
386    v = x
387    return v
388
389
390def to_struct_with_array_slice(x):
391    """
392    >>> x, y = to_struct_with_array_slice([
393    ...     {'a': 11, 'b': [{'x': 12, 'y': 13}, {'x': 14, 'y': 15}]},
394    ...     {'a': 21, 'b': [{'x': 22, 'y': 23}, {'x': 24, 'y': 25}]},
395    ... ])
396    >>> x['a'], y['a']
397    (11, 21)
398    >>> sorted(sorted(v.items()) for v in x['b'])
399    [[('x', 12), ('y', 13.0)], [('x', 14), ('y', 15.0)]]
400    >>> sorted(sorted(v.items()) for v in y['b'])
401    [[('x', 22), ('y', 23.0)], [('x', 24), ('y', 25.0)]]
402
403    >>> x, y = to_struct_with_array_slice(iter([
404    ...     {'a': 11, 'b': iter([{'x': 12, 'y': 13}, {'x': 14, 'y': 15}])},
405    ...     {'a': 21, 'b': iter([{'x': 22, 'y': 23}, {'x': 24, 'y': 25}])},
406    ... ]))
407    >>> x['a'], y['a']
408    (11, 21)
409    >>> sorted(sorted(v.items()) for v in x['b'])
410    [[('x', 12), ('y', 13.0)], [('x', 14), ('y', 15.0)]]
411    >>> sorted(sorted(v.items()) for v in y['b'])
412    [[('x', 22), ('y', 23.0)], [('x', 24), ('y', 25.0)]]
413    """
414    cdef StructWithArray[2] v
415    v[:] = x
416    return v
417
418
419'''
420# FIXME: this isn't currently allowed
421def to_struct_with_array_slice_end(x):
422    """
423    >>> to_struct_with_array_slice_end([
424    ...     {'a': 11, 'b': [{'x': 12, 'y': 13}, {'x': 14, 'y': 15}]},
425    ... ])
426    [{'a': 11, 'b': [{'y': 13.0, 'x': 12}, {'y': 15.0, 'x': 14}]}]
427    >>> to_struct_with_array_slice_end(iter([
428    ...     {'a': 11, 'b': iter([{'x': 12, 'y': 13}, {'x': 14, 'y': 15}])},
429    ... ]))
430    [{'a': 11, 'b': [{'y': 13.0, 'x': 12}, {'y': 15.0, 'x': 14}]}]
431    >>> to_struct_with_array_slice_end(iter([
432    ...     {'a': 11, 'b': iter([{'x': 12, 'y': 13}, {'x': 14, 'y': 15}])},
433    ...     {'a': 21, 'b': iter([{'x': 22, 'y': 23}, {'x': 24, 'y': 25}])},
434    ... ]))
435    Traceback (most recent call last):
436    IndexError: too many values found during array assignment, expected 1
437    """
438    cdef StructWithArray[2] v
439    v[:1] = x
440    return v
441
442
443def to_int_array_slice_start_end(x):
444    """
445    >>> to_int_array_slice_start_end([1, 2, 3])
446    (1, 2, 3, 2, 3)
447    """
448    cdef int[5] v
449    v[2:] = x
450    v[:3] = x
451    return v[0], v[1], v[2], v[3], v[4]
452'''
453