numpy_test.pyx 11.4 KB
Newer Older
Robert Bradshaw's avatar
Robert Bradshaw committed
1
# cannot be named "numpy" in order to not clash with the numpy module!
2

3
cimport numpy as np
4

5 6 7 8 9 10 11 12 13 14 15
def little_endian():
    cdef int endian_detector = 1
    return (<char*>&endian_detector)[0] != 0

if little_endian():
    my_endian = '<'
    other_endian = '>'
else:
    my_endian = '>'
    other_endian = '<'

16
try:
17
    import numpy as np
18
    __doc__ = u"""
19 20 21 22 23 24

    >>> basic()
    [[0 1 2 3 4]
     [5 6 7 8 9]]
    2 0 9 5

Robert Bradshaw's avatar
Robert Bradshaw committed
25 26 27
    >>> three_dim()
    [[[  0.   1.   2.   3.]
      [  4.   5.   6.   7.]]
28
    <_BLANKLINE_>
Robert Bradshaw's avatar
Robert Bradshaw committed
29 30
     [[  8.   9.  10.  11.]
      [ 12.  13.  14.  15.]]
31
    <_BLANKLINE_>
Robert Bradshaw's avatar
Robert Bradshaw committed
32 33 34 35
     [[ 16.  17.  18.  19.]
      [ 20.  21.  22.  23.]]]
    6.0 0.0 13.0 8.0
    
36
    >>> obj_array()
Robert Bradshaw's avatar
Robert Bradshaw committed
37 38
    [a 1 {}]
    a 1 {}
39 40

    Test various forms of slicing, picking etc.
41
    >>> a = np.arange(10, dtype='l').reshape(2, 5)
42 43 44 45 46 47 48 49 50 51 52 53
    >>> print_long_2d(a)
    0 1 2 3 4
    5 6 7 8 9
    >>> print_long_2d(a[::-1, ::-1])
    9 8 7 6 5
    4 3 2 1 0
    >>> print_long_2d(a[1:2, 1:3])
    6 7
    >>> print_long_2d(a[::2, ::2])
    0 2 4
    >>> print_long_2d(a[::4, :])
    0 1 2 3 4
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
    >>> print_long_2d(a[:, 1:5:2])
    1 3
    6 8
    >>> print_long_2d(a[:, 5:1:-2])
    4 2
    9 7
    >>> print_long_2d(a[:, [3, 1]])
    3 1
    8 6
    >>> print_long_2d(a.T)
    0 5
    1 6
    2 7
    3 8
    4 9

    Write to slices
    >>> b = a.copy()
    >>> put_range_long_1d(b[:, 3])
    >>> print b
    [[0 1 2 0 4]
     [5 6 7 1 9]]
    >>> put_range_long_1d(b[::-1, 3])
    >>> print b
    [[0 1 2 1 4]
     [5 6 7 0 9]]
    >>> a = np.zeros(9, dtype='l')
    >>> put_range_long_1d(a[1::3])
    >>> print a
    [0 0 0 0 1 0 0 2 0]

    Write to picked subarrays. This should NOT change the original
    array as picking creates a new mutable copy.
    >>> a = np.zeros(10, dtype='l').reshape(2, 5)
    >>> put_range_long_1d(a[[0, 0, 1, 1, 0], [0, 1, 2, 4, 3]])
    >>> print a
    [[0 0 0 0 0]
     [0 0 0 0 0]]
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115

    Test contiguous access modes:
    >>> c_arr = np.array(np.arange(12, dtype='i').reshape(3,4), order='C')
    >>> f_arr = np.array(np.arange(12, dtype='i').reshape(3,4), order='F')
    >>> test_c_contig(c_arr)
    0 1 2 3
    4 5 6 7
    8 9 10 11
    >>> test_f_contig(f_arr)
    0 1 2 3
    4 5 6 7
    8 9 10 11
    >>> test_c_contig(f_arr)
    Traceback (most recent call last):
       ...
    ValueError: ndarray is not C contiguous
    >>> test_f_contig(c_arr)
    Traceback (most recent call last):
       ...
    ValueError: ndarray is not Fortran contiguous
    >>> test_c_contig(c_arr[::2,::2])
    Traceback (most recent call last):
       ...
    ValueError: ndarray is not C contiguous
116 117 118 119 120 121 122 123 124
    
    >>> test_dtype('b', inc1_byte)
    >>> test_dtype('B', inc1_ubyte)
    >>> test_dtype('h', inc1_short)
    >>> test_dtype('H', inc1_ushort)
    >>> test_dtype('i', inc1_int)
    >>> test_dtype('I', inc1_uint)
    >>> test_dtype('l', inc1_long)
    >>> test_dtype('L', inc1_ulong)
125
    
126 127 128 129
    >>> test_dtype('f', inc1_float)
    >>> test_dtype('d', inc1_double)
    >>> test_dtype('g', inc1_longdouble)
    >>> test_dtype('O', inc1_object)
130 131 132
    >>> test_dtype('F', inc1_cfloat) # numpy format codes differ from buffer ones here
    >>> test_dtype('D', inc1_cdouble)
    >>> test_dtype('G', inc1_clongdouble)
133 134 135
    >>> test_dtype('F', inc1_cfloat_struct)
    >>> test_dtype('D', inc1_cdouble_struct)
    >>> test_dtype('G', inc1_clongdouble_struct)
136

137 138 139 140
    >>> test_dtype(np.int, inc1_int_t)
    >>> test_dtype(np.long, inc1_long_t)
    >>> test_dtype(np.float, inc1_float_t)
    >>> test_dtype(np.double, inc1_double_t)
141

142 143 144 145 146
    >>> test_dtype(np.longdouble, inc1_longdouble_t)

    >>> test_dtype(np.int32, inc1_int32_t)
    >>> test_dtype(np.float64, inc1_float64_t)

147 148 149 150 151 152 153 154 155
    Endian tests:
    >>> test_dtype('%si' % my_endian, inc1_int)
    >>> test_dtype('%si' % other_endian, inc1_int)
    Traceback (most recent call last):
       ...
    ValueError: Non-native byte order not supported
    


156 157
    >>> test_recordarray()
    
158
    >>> print(test_nested_dtypes(np.zeros((3,), dtype=np.dtype([\
159 160
            ('a', np.dtype('i,i')),\
            ('b', np.dtype('i,i'))\
161
        ]))))
162
    array([((0, 0), (0, 0)), ((1, 2), (1, 4)), ((1, 2), (1, 4))], 
163
          dtype=[('a', [('f0', '!i4'), ('f1', '!i4')]), ('b', [('f0', '!i4'), ('f1', '!i4')])])
164

165
    >>> print(test_nested_dtypes(np.zeros((3,), dtype=np.dtype([\
166 167
            ('a', np.dtype('i,f')),\
            ('b', np.dtype('i,i'))\
168
        ]))))
169
    Traceback (most recent call last):
170
        ...
171 172
    ValueError: Buffer dtype mismatch, expected 'int' but got 'float' in 'DoubleInt.y'

173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
    >>> print(test_packed_align(np.zeros((1,), dtype=np.dtype('b,i', align=False))))
    array([(22, 23)], 
          dtype=[('f0', '|i1'), ('f1', '!i4')])
    >>> print(test_unpacked_align(np.zeros((1,), dtype=np.dtype('b,i', align=True))))
    array([(22, 23)], 
          dtype=[('f0', '|i1'), ('', '|V3'), ('f1', '!i4')])

    >>> print(test_packed_align(np.zeros((1,), dtype=np.dtype('b,i', align=True))))
    Traceback (most recent call last):
        ...
    ValueError: Buffer dtype mismatch; next field is at offset 4 but 1 expected

    >>> print(test_unpacked_align(np.zeros((1,), dtype=np.dtype('b,i', align=False))))
    Traceback (most recent call last):
        ...
    ValueError: Buffer dtype mismatch; next field is at offset 1 but 4 expected

190 191 192 193 194 195

    >>> test_good_cast()
    True
    >>> test_bad_cast()
    Traceback (most recent call last):
        ...
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
196
    ValueError: Item size of buffer (1 byte) does not match size of 'int' (4 bytes)
197 198 199 200 201

    >>> test_complextypes()
    1,1
    1,1
    8,16
202
    
203 204
"""
except:
205
    __doc__ = u""
206

207

208
def ndarray_str(arr):
209
    u"""
210 211 212
    Since Py2.3 doctest don't support <BLANKLINE>, manually replace blank lines
    with <_BLANKLINE_>
    """
213
    return unicode(arr).replace(u'\n\n', u'\n<_BLANKLINE_>\n')    
214

215
def basic():
216
    cdef object[int, ndim=2] buf = np.arange(10, dtype=b'i').reshape((2, 5))
217 218
    print buf
    print buf[0, 2], buf[0, 0], buf[1, 4], buf[1, 0]
Robert Bradshaw's avatar
Robert Bradshaw committed
219 220

def three_dim():
221
    cdef object[double, ndim=3] buf = np.arange(24, dtype=b'd').reshape((3,2,4))
222
    print ndarray_str(buf)
Robert Bradshaw's avatar
Robert Bradshaw committed
223 224 225
    print buf[0, 1, 2], buf[0, 0, 0], buf[1, 1, 1], buf[1, 0, 0]

def obj_array():
226
    cdef object[object, ndim=1] buf = np.array([b"a", 1, {}])
Robert Bradshaw's avatar
Robert Bradshaw committed
227 228
    print buf
    print buf[0], buf[1], buf[2]
229 230


231
def print_long_2d(np.ndarray[long, ndim=2] arr):
232 233
    cdef int i, j
    for i in range(arr.shape[0]):
234
        print u" ".join([unicode(arr[i, j]) for j in range(arr.shape[1])])
235 236

def put_range_long_1d(np.ndarray[long] arr):
237
    u"""Writes 0,1,2,... to array and returns array"""
238 239 240 241 242
    cdef int value = 0, i
    for i in range(arr.shape[0]):
        arr[i] = value
        value += 1

243
def test_c_contig(np.ndarray[int, ndim=2, mode=b'c'] arr):
244 245
    cdef int i, j
    for i in range(arr.shape[0]):
246
        print u" ".join([unicode(arr[i, j]) for j in range(arr.shape[1])])
247

248
def test_f_contig(np.ndarray[int, ndim=2, mode=b'fortran'] arr):
249 250
    cdef int i, j
    for i in range(arr.shape[0]):
251
        print u" ".join([unicode(arr[i, j]) for j in range(arr.shape[1])])
252

253
# Exhaustive dtype tests -- increments element [1] by 1 (or 1+1j) for all dtypes
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
def inc1_byte(np.ndarray[char] arr):                    arr[1] += 1
def inc1_ubyte(np.ndarray[unsigned char] arr):          arr[1] += 1
def inc1_short(np.ndarray[short] arr):                  arr[1] += 1
def inc1_ushort(np.ndarray[unsigned short] arr):        arr[1] += 1
def inc1_int(np.ndarray[int] arr):                      arr[1] += 1
def inc1_uint(np.ndarray[unsigned int] arr):            arr[1] += 1
def inc1_long(np.ndarray[long] arr):                    arr[1] += 1
def inc1_ulong(np.ndarray[unsigned long] arr):          arr[1] += 1
def inc1_longlong(np.ndarray[long long] arr):           arr[1] += 1
def inc1_ulonglong(np.ndarray[unsigned long long] arr): arr[1] += 1

def inc1_float(np.ndarray[float] arr):                  arr[1] += 1
def inc1_double(np.ndarray[double] arr):                arr[1] += 1
def inc1_longdouble(np.ndarray[long double] arr):       arr[1] += 1

269 270 271 272 273
def inc1_cfloat(np.ndarray[float complex] arr):            arr[1] = arr[1] + 1 + 1j
def inc1_cdouble(np.ndarray[double complex] arr):          arr[1] = (arr[1] + 1) + 1j
def inc1_clongdouble(np.ndarray[long double complex] arr): arr[1] = arr[1] + (1 + 1j)

def inc1_cfloat_struct(np.ndarray[np.cfloat_t] arr):
274 275 276
    arr[1].real += 1
    arr[1].imag += 1
    
277
def inc1_cdouble_struct(np.ndarray[np.cdouble_t] arr):
278 279 280
    arr[1].real += 1
    arr[1].imag += 1

281
def inc1_clongdouble_struct(np.ndarray[np.clongdouble_t] arr):
282 283 284 285
    cdef long double x
    x = arr[1].real + 1
    arr[1].real = x
    arr[1].imag = arr[1].imag + 1
286

287 288 289 290
def inc1_object(np.ndarray[object] arr):
    o = arr[1]
    o += 1
    arr[1] = o # unfortunately, += segfaults for objects
291 292 293 294 295 296 297 298 299 300 301 302 303


def inc1_int_t(np.ndarray[np.int_t] arr):               arr[1] += 1
def inc1_long_t(np.ndarray[np.long_t] arr):             arr[1] += 1
def inc1_float_t(np.ndarray[np.float_t] arr):           arr[1] += 1
def inc1_double_t(np.ndarray[np.double_t] arr):         arr[1] += 1
def inc1_longdouble_t(np.ndarray[np.longdouble_t] arr): arr[1] += 1

# The tests below only work on platforms that has the given types
def inc1_int32_t(np.ndarray[np.int32_t] arr):           arr[1] += 1
def inc1_float64_t(np.ndarray[np.float64_t] arr):       arr[1] += 1

    
304
def test_dtype(dtype, inc1):
305
    if dtype in (b'F', b'D', b'G'):
306 307
        a = np.array([0, 10+10j], dtype=dtype)
        inc1(a)
308
        if a[1] != (11 + 11j): print u"failed!", a[1]
309 310 311
    else:
        a = np.array([0, 10], dtype=dtype)
        inc1(a)
312
        if a[1] != 11: print u"failed!"
313

314 315 316 317 318
cdef struct DoubleInt:
    int x, y

def test_recordarray():
    cdef object[DoubleInt] arr
319
    arr = np.array([(5,5), (4, 6)], dtype=np.dtype(b'i,i'))
320 321
    cdef DoubleInt rec
    rec = arr[0]
322 323
    if rec.x != 5: print u"failed"
    if rec.y != 5: print u"failed"
324 325 326 327
    rec.y += 5
    arr[1] = rec
    arr[0].x -= 2
    arr[0].y += 3
328 329 330 331
    if arr[0].x != 3: print u"failed"
    if arr[0].y != 8: print u"failed"
    if arr[1].x != 5: print u"failed"
    if arr[1].y != 10: print u"failed"
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351

cdef struct NestedStruct:
    DoubleInt a
    DoubleInt b

cdef struct BadDoubleInt:
    float x
    int y

cdef struct BadNestedStruct:
    DoubleInt a
    BadDoubleInt b

def test_nested_dtypes(obj):
    cdef object[NestedStruct] arr = obj
    arr[1].a.x = 1
    arr[1].a.y = 2
    arr[1].b.x = arr[0].a.y + 1
    arr[1].b.y = 4
    arr[2] = arr[1]
352
    return repr(arr).replace('<', '!').replace('>', '!')
353 354 355 356

def test_bad_nested_dtypes():
    cdef object[BadNestedStruct] arr

357 358
def test_good_cast():
    # Check that a signed int can round-trip through casted unsigned int access
359
    cdef np.ndarray[unsigned int, cast=True] arr = np.array([-100], dtype=b'i')
360 361 362 363 364
    cdef unsigned int data = arr[0]
    return -100 == <int>data

def test_bad_cast():
    # This should raise an exception
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
365
    cdef np.ndarray[int, cast=True] arr = np.array([1], dtype=b'b')
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383

cdef packed struct PackedStruct:
    char a
    int b

cdef struct UnpackedStruct:
    char a
    int b

def test_packed_align(np.ndarray[PackedStruct] arr):
    arr[0].a = 22
    arr[0].b = 23
    return repr(arr).replace('<', '!').replace('>', '!')

def test_unpacked_align(np.ndarray[UnpackedStruct] arr):
    arr[0].a = 22
    arr[0].b = 23    
    return repr(arr).replace('<', '!').replace('>', '!')
384 385 386 387 388 389 390 391 392 393 394 395

def test_complextypes():
    cdef np.complex64_t x64 = 1, y64 = 1j
    cdef np.complex128_t x128 = 1, y128 = 1j
    x64 = x64 + y64
    print "%.0f,%.0f" % (x64.real, x64.imag)
    x128 = x128 + y128
    print "%.0f,%.0f" % (x128.real, x128.imag)
    print "%d,%d" % (sizeof(x64), sizeof(x128))