From e1f12512b2ecc9de1aa86ac3069c5103043857b3 Mon Sep 17 00:00:00 2001 From: Olivier Grisel Date: Wed, 6 May 2015 17:54:38 +0100 Subject: [PATCH 1/2] FIX make take_nd support readonly array --- pandas/src/generate_code.py | 62 +- pandas/src/generated.pyx | 2318 ++++++++++++++++++++++++++++++----- pandas/tests/test_common.py | 31 +- 3 files changed, 2105 insertions(+), 306 deletions(-) diff --git a/pandas/src/generate_code.py b/pandas/src/generate_code.py index 9d0384857ed81..3b71d1c083ba1 100644 --- a/pandas/src/generate_code.py +++ b/pandas/src/generate_code.py @@ -93,12 +93,7 @@ def take_1d_%(name)s_%(dest)s(ndarray[%(c_type_in)s] values, """ -take_2d_axis0_template = """@cython.wraparound(False) -@cython.boundscheck(False) -def take_2d_axis0_%(name)s_%(dest)s(%(c_type_in)s[:, :] values, - ndarray[int64_t] indexer, - %(c_type_out)s[:, :] out, - fill_value=np.nan): +inner_take_2d_axis0_template = """\ cdef: Py_ssize_t i, j, k, n, idx %(c_type_out)s fv @@ -140,12 +135,34 @@ def take_2d_axis0_%(name)s_%(dest)s(%(c_type_in)s[:, :] values, """ -take_2d_axis1_template = """@cython.wraparound(False) +take_2d_axis0_template = """\ +@cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_%(name)s_%(dest)s(%(c_type_in)s[:, :] values, +cdef inline take_2d_axis0_%(name)s_%(dest)s_memview(%(c_type_in)s[:, :] values, + ndarray[int64_t] indexer, + %(c_type_out)s[:, :] out, + fill_value=np.nan): +""" + inner_take_2d_axis0_template + """ + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis0_%(name)s_%(dest)s(ndarray[%(c_type_in)s, ndim=2] values, ndarray[int64_t] indexer, %(c_type_out)s[:, :] out, fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_%(name)s_%(dest)s_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. +""" + inner_take_2d_axis0_template + + +inner_take_2d_axis1_template = """\ cdef: Py_ssize_t i, j, k, n, idx %(c_type_out)s fv @@ -165,9 +182,36 @@ def take_2d_axis1_%(name)s_%(dest)s(%(c_type_in)s[:, :] values, out[i, j] = fv else: out[i, j] = %(preval)svalues[i, idx]%(postval)s - """ +take_2d_axis1_template = """\ +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis1_%(name)s_%(dest)s_memview(%(c_type_in)s[:, :] values, + ndarray[int64_t] indexer, + %(c_type_out)s[:, :] out, + fill_value=np.nan): +""" + inner_take_2d_axis1_template + """ + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis1_%(name)s_%(dest)s(ndarray[%(c_type_in)s, ndim=2] values, + ndarray[int64_t] indexer, + %(c_type_out)s[:, :] out, + fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_%(name)s_%(dest)s_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. +""" + inner_take_2d_axis1_template + + take_2d_multi_template = """@cython.wraparound(False) @cython.boundscheck(False) def take_2d_multi_%(name)s_%(dest)s(ndarray[%(c_type_in)s, ndim=2] values, diff --git a/pandas/src/generated.pyx b/pandas/src/generated.pyx index cab3a84f6ffe8..ac31fdedf2ea6 100644 --- a/pandas/src/generated.pyx +++ b/pandas/src/generated.pyx @@ -2704,10 +2704,10 @@ def take_1d_object_object(ndarray[object] values, @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_bool_bool(uint8_t[:, :] values, - ndarray[int64_t] indexer, - uint8_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis0_bool_bool_memview(uint8_t[:, :] values, + ndarray[int64_t] indexer, + uint8_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx uint8_t fv @@ -2747,30 +2747,41 @@ def take_2d_axis0_bool_bool(uint8_t[:, :] values, for j from 0 <= j < k: out[i, j] = values[idx, j] + + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_bool_object(uint8_t[:, :] values, +def take_2d_axis0_bool_bool(ndarray[uint8_t, ndim=2] values, ndarray[int64_t] indexer, - object[:, :] out, + uint8_t[:, :] out, fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_bool_bool_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - object fv + uint8_t fv n = len(indexer) k = values.shape[1] fv = fill_value - IF False: + IF True: cdef: - object *v - object *o + uint8_t *v + uint8_t *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(object) and - sizeof(object) * n >= 256): + values.strides[1] == sizeof(uint8_t) and + sizeof(uint8_t) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -2780,7 +2791,7 @@ def take_2d_axis0_bool_object(uint8_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(object) * k)) + memmove(o, v, (sizeof(uint8_t) * k)) return for i from 0 <= i < n: @@ -2790,32 +2801,32 @@ def take_2d_axis0_bool_object(uint8_t[:, :] values, out[i, j] = fv else: for j from 0 <= j < k: - out[i, j] = True if values[idx, j] > 0 else False + out[i, j] = values[idx, j] @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int8_int8(int8_t[:, :] values, - ndarray[int64_t] indexer, - int8_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis0_bool_object_memview(uint8_t[:, :] values, + ndarray[int64_t] indexer, + object[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - int8_t fv + object fv n = len(indexer) k = values.shape[1] fv = fill_value - IF True: + IF False: cdef: - int8_t *v - int8_t *o + object *v + object *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(int8_t) and - sizeof(int8_t) * n >= 256): + values.strides[1] == sizeof(object) and + sizeof(object) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -2825,7 +2836,7 @@ def take_2d_axis0_int8_int8(int8_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(int8_t) * k)) + memmove(o, v, (sizeof(object) * k)) return for i from 0 <= i < n: @@ -2835,17 +2846,28 @@ def take_2d_axis0_int8_int8(int8_t[:, :] values, out[i, j] = fv else: for j from 0 <= j < k: - out[i, j] = values[idx, j] + out[i, j] = True if values[idx, j] > 0 else False + + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int8_int32(int8_t[:, :] values, +def take_2d_axis0_bool_object(ndarray[uint8_t, ndim=2] values, ndarray[int64_t] indexer, - int32_t[:, :] out, + object[:, :] out, fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_bool_object_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - int32_t fv + object fv n = len(indexer) k = values.shape[1] @@ -2854,13 +2876,13 @@ def take_2d_axis0_int8_int32(int8_t[:, :] values, IF False: cdef: - int32_t *v - int32_t *o + object *v + object *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(int32_t) and - sizeof(int32_t) * n >= 256): + values.strides[1] == sizeof(object) and + sizeof(object) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -2870,7 +2892,7 @@ def take_2d_axis0_int8_int32(int8_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(int32_t) * k)) + memmove(o, v, (sizeof(object) * k)) return for i from 0 <= i < n: @@ -2880,32 +2902,32 @@ def take_2d_axis0_int8_int32(int8_t[:, :] values, out[i, j] = fv else: for j from 0 <= j < k: - out[i, j] = values[idx, j] + out[i, j] = True if values[idx, j] > 0 else False @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int8_int64(int8_t[:, :] values, - ndarray[int64_t] indexer, - int64_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis0_int8_int8_memview(int8_t[:, :] values, + ndarray[int64_t] indexer, + int8_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - int64_t fv + int8_t fv n = len(indexer) k = values.shape[1] fv = fill_value - IF False: + IF True: cdef: - int64_t *v - int64_t *o + int8_t *v + int8_t *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(int64_t) and - sizeof(int64_t) * n >= 256): + values.strides[1] == sizeof(int8_t) and + sizeof(int8_t) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -2915,7 +2937,7 @@ def take_2d_axis0_int8_int64(int8_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(int64_t) * k)) + memmove(o, v, (sizeof(int8_t) * k)) return for i from 0 <= i < n: @@ -2927,30 +2949,41 @@ def take_2d_axis0_int8_int64(int8_t[:, :] values, for j from 0 <= j < k: out[i, j] = values[idx, j] + + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int8_float64(int8_t[:, :] values, +def take_2d_axis0_int8_int8(ndarray[int8_t, ndim=2] values, ndarray[int64_t] indexer, - float64_t[:, :] out, + int8_t[:, :] out, fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int8_int8_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - float64_t fv + int8_t fv n = len(indexer) k = values.shape[1] fv = fill_value - IF False: + IF True: cdef: - float64_t *v - float64_t *o + int8_t *v + int8_t *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(float64_t) and - sizeof(float64_t) * n >= 256): + values.strides[1] == sizeof(int8_t) and + sizeof(int8_t) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -2960,7 +2993,7 @@ def take_2d_axis0_int8_float64(int8_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(float64_t) * k)) + memmove(o, v, (sizeof(int8_t) * k)) return for i from 0 <= i < n: @@ -2974,28 +3007,28 @@ def take_2d_axis0_int8_float64(int8_t[:, :] values, @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int16_int16(int16_t[:, :] values, - ndarray[int64_t] indexer, - int16_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis0_int8_int32_memview(int8_t[:, :] values, + ndarray[int64_t] indexer, + int32_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - int16_t fv + int32_t fv n = len(indexer) k = values.shape[1] fv = fill_value - IF True: + IF False: cdef: - int16_t *v - int16_t *o + int32_t *v + int32_t *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(int16_t) and - sizeof(int16_t) * n >= 256): + values.strides[1] == sizeof(int32_t) and + sizeof(int32_t) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -3005,7 +3038,7 @@ def take_2d_axis0_int16_int16(int16_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(int16_t) * k)) + memmove(o, v, (sizeof(int32_t) * k)) return for i from 0 <= i < n: @@ -3017,12 +3050,23 @@ def take_2d_axis0_int16_int16(int16_t[:, :] values, for j from 0 <= j < k: out[i, j] = values[idx, j] + + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int16_int32(int16_t[:, :] values, +def take_2d_axis0_int8_int32(ndarray[int8_t, ndim=2] values, ndarray[int64_t] indexer, int32_t[:, :] out, fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int8_int32_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx int32_t fv @@ -3064,10 +3108,10 @@ def take_2d_axis0_int16_int32(int16_t[:, :] values, @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int16_int64(int16_t[:, :] values, - ndarray[int64_t] indexer, - int64_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis0_int8_int64_memview(int8_t[:, :] values, + ndarray[int64_t] indexer, + int64_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx int64_t fv @@ -3107,15 +3151,26 @@ def take_2d_axis0_int16_int64(int16_t[:, :] values, for j from 0 <= j < k: out[i, j] = values[idx, j] + + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int16_float64(int16_t[:, :] values, +def take_2d_axis0_int8_int64(ndarray[int8_t, ndim=2] values, ndarray[int64_t] indexer, - float64_t[:, :] out, + int64_t[:, :] out, fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int8_int64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - float64_t fv + int64_t fv n = len(indexer) k = values.shape[1] @@ -3124,13 +3179,13 @@ def take_2d_axis0_int16_float64(int16_t[:, :] values, IF False: cdef: - float64_t *v - float64_t *o + int64_t *v + int64_t *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(float64_t) and - sizeof(float64_t) * n >= 256): + values.strides[1] == sizeof(int64_t) and + sizeof(int64_t) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -3140,7 +3195,7 @@ def take_2d_axis0_int16_float64(int16_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(float64_t) * k)) + memmove(o, v, (sizeof(int64_t) * k)) return for i from 0 <= i < n: @@ -3154,28 +3209,28 @@ def take_2d_axis0_int16_float64(int16_t[:, :] values, @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int32_int32(int32_t[:, :] values, - ndarray[int64_t] indexer, - int32_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis0_int8_float64_memview(int8_t[:, :] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - int32_t fv + float64_t fv n = len(indexer) k = values.shape[1] fv = fill_value - IF True: + IF False: cdef: - int32_t *v - int32_t *o + float64_t *v + float64_t *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(int32_t) and - sizeof(int32_t) * n >= 256): + values.strides[1] == sizeof(float64_t) and + sizeof(float64_t) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -3185,7 +3240,7 @@ def take_2d_axis0_int32_int32(int32_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(int32_t) * k)) + memmove(o, v, (sizeof(float64_t) * k)) return for i from 0 <= i < n: @@ -3197,15 +3252,26 @@ def take_2d_axis0_int32_int32(int32_t[:, :] values, for j from 0 <= j < k: out[i, j] = values[idx, j] + + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int32_int64(int32_t[:, :] values, +def take_2d_axis0_int8_float64(ndarray[int8_t, ndim=2] values, ndarray[int64_t] indexer, - int64_t[:, :] out, + float64_t[:, :] out, fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int8_float64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - int64_t fv + float64_t fv n = len(indexer) k = values.shape[1] @@ -3214,13 +3280,13 @@ def take_2d_axis0_int32_int64(int32_t[:, :] values, IF False: cdef: - int64_t *v - int64_t *o + float64_t *v + float64_t *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(int64_t) and - sizeof(int64_t) * n >= 256): + values.strides[1] == sizeof(float64_t) and + sizeof(float64_t) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -3230,7 +3296,7 @@ def take_2d_axis0_int32_int64(int32_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(int64_t) * k)) + memmove(o, v, (sizeof(float64_t) * k)) return for i from 0 <= i < n: @@ -3244,28 +3310,28 @@ def take_2d_axis0_int32_int64(int32_t[:, :] values, @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int32_float64(int32_t[:, :] values, - ndarray[int64_t] indexer, - float64_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis0_int16_int16_memview(int16_t[:, :] values, + ndarray[int64_t] indexer, + int16_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - float64_t fv + int16_t fv n = len(indexer) k = values.shape[1] fv = fill_value - IF False: + IF True: cdef: - float64_t *v - float64_t *o + int16_t *v + int16_t *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(float64_t) and - sizeof(float64_t) * n >= 256): + values.strides[1] == sizeof(int16_t) and + sizeof(int16_t) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -3275,7 +3341,7 @@ def take_2d_axis0_int32_float64(int32_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(float64_t) * k)) + memmove(o, v, (sizeof(int16_t) * k)) return for i from 0 <= i < n: @@ -3287,15 +3353,26 @@ def take_2d_axis0_int32_float64(int32_t[:, :] values, for j from 0 <= j < k: out[i, j] = values[idx, j] + + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int64_int64(int64_t[:, :] values, +def take_2d_axis0_int16_int16(ndarray[int16_t, ndim=2] values, ndarray[int64_t] indexer, - int64_t[:, :] out, + int16_t[:, :] out, fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int16_int16_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - int64_t fv + int16_t fv n = len(indexer) k = values.shape[1] @@ -3304,13 +3381,13 @@ def take_2d_axis0_int64_int64(int64_t[:, :] values, IF True: cdef: - int64_t *v - int64_t *o + int16_t *v + int16_t *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(int64_t) and - sizeof(int64_t) * n >= 256): + values.strides[1] == sizeof(int16_t) and + sizeof(int16_t) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -3320,7 +3397,7 @@ def take_2d_axis0_int64_int64(int64_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(int64_t) * k)) + memmove(o, v, (sizeof(int16_t) * k)) return for i from 0 <= i < n: @@ -3334,13 +3411,13 @@ def take_2d_axis0_int64_int64(int64_t[:, :] values, @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_int64_float64(int64_t[:, :] values, - ndarray[int64_t] indexer, - float64_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis0_int16_int32_memview(int16_t[:, :] values, + ndarray[int64_t] indexer, + int32_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - float64_t fv + int32_t fv n = len(indexer) k = values.shape[1] @@ -3349,13 +3426,13 @@ def take_2d_axis0_int64_float64(int64_t[:, :] values, IF False: cdef: - float64_t *v - float64_t *o + int32_t *v + int32_t *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(float64_t) and - sizeof(float64_t) * n >= 256): + values.strides[1] == sizeof(int32_t) and + sizeof(int32_t) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -3365,7 +3442,7 @@ def take_2d_axis0_int64_float64(int64_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(float64_t) * k)) + memmove(o, v, (sizeof(int32_t) * k)) return for i from 0 <= i < n: @@ -3377,30 +3454,41 @@ def take_2d_axis0_int64_float64(int64_t[:, :] values, for j from 0 <= j < k: out[i, j] = values[idx, j] + + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_float32_float32(float32_t[:, :] values, +def take_2d_axis0_int16_int32(ndarray[int16_t, ndim=2] values, ndarray[int64_t] indexer, - float32_t[:, :] out, + int32_t[:, :] out, fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int16_int32_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - float32_t fv + int32_t fv n = len(indexer) k = values.shape[1] fv = fill_value - IF True: + IF False: cdef: - float32_t *v - float32_t *o + int32_t *v + int32_t *o #GH3130 if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(float32_t) and - sizeof(float32_t) * n >= 256): + values.strides[1] == sizeof(int32_t) and + sizeof(int32_t) * n >= 256): for i from 0 <= i < n: idx = indexer[i] @@ -3410,7 +3498,7 @@ def take_2d_axis0_float32_float32(float32_t[:, :] values, else: v = &values[idx, 0] o = &out[i, 0] - memmove(o, v, (sizeof(float32_t) * k)) + memmove(o, v, (sizeof(int32_t) * k)) return for i from 0 <= i < n: @@ -3424,13 +3512,13 @@ def take_2d_axis0_float32_float32(float32_t[:, :] values, @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_float32_float64(float32_t[:, :] values, - ndarray[int64_t] indexer, - float64_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis0_int16_int64_memview(int16_t[:, :] values, + ndarray[int64_t] indexer, + int64_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - float64_t fv + int64_t fv n = len(indexer) k = values.shape[1] @@ -3439,9 +3527,166 @@ def take_2d_axis0_float32_float64(float32_t[:, :] values, IF False: cdef: - float64_t *v - float64_t *o - + int64_t *v + int64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(int64_t) and + sizeof(int64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(int64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis0_int16_int64(ndarray[int16_t, ndim=2] values, + ndarray[int64_t] indexer, + int64_t[:, :] out, + fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int16_int64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + int64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + int64_t *v + int64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(int64_t) and + sizeof(int64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(int64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis0_int16_float64_memview(int16_t[:, :] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + float64_t *v + float64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(float64_t) and + sizeof(float64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(float64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis0_int16_float64(ndarray[int16_t, ndim=2] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int16_float64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + float64_t *v + float64_t *o + #GH3130 if (values.strides[1] == out.strides[1] and values.strides[1] == sizeof(float64_t) and @@ -3459,114 +3704,1528 @@ def take_2d_axis0_float32_float64(float32_t[:, :] values, return for i from 0 <= i < n: - idx = indexer[i] - if idx == -1: - for j from 0 <= j < k: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis0_int32_int32_memview(int32_t[:, :] values, + ndarray[int64_t] indexer, + int32_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + int32_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF True: + cdef: + int32_t *v + int32_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(int32_t) and + sizeof(int32_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(int32_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis0_int32_int32(ndarray[int32_t, ndim=2] values, + ndarray[int64_t] indexer, + int32_t[:, :] out, + fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int32_int32_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + int32_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF True: + cdef: + int32_t *v + int32_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(int32_t) and + sizeof(int32_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(int32_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis0_int32_int64_memview(int32_t[:, :] values, + ndarray[int64_t] indexer, + int64_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + int64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + int64_t *v + int64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(int64_t) and + sizeof(int64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(int64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis0_int32_int64(ndarray[int32_t, ndim=2] values, + ndarray[int64_t] indexer, + int64_t[:, :] out, + fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int32_int64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + int64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + int64_t *v + int64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(int64_t) and + sizeof(int64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(int64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis0_int32_float64_memview(int32_t[:, :] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + float64_t *v + float64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(float64_t) and + sizeof(float64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(float64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis0_int32_float64(ndarray[int32_t, ndim=2] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int32_float64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + float64_t *v + float64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(float64_t) and + sizeof(float64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(float64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis0_int64_int64_memview(int64_t[:, :] values, + ndarray[int64_t] indexer, + int64_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + int64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF True: + cdef: + int64_t *v + int64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(int64_t) and + sizeof(int64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(int64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis0_int64_int64(ndarray[int64_t, ndim=2] values, + ndarray[int64_t] indexer, + int64_t[:, :] out, + fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int64_int64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + int64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF True: + cdef: + int64_t *v + int64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(int64_t) and + sizeof(int64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(int64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis0_int64_float64_memview(int64_t[:, :] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + float64_t *v + float64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(float64_t) and + sizeof(float64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(float64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis0_int64_float64(ndarray[int64_t, ndim=2] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_int64_float64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + float64_t *v + float64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(float64_t) and + sizeof(float64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(float64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis0_float32_float32_memview(float32_t[:, :] values, + ndarray[int64_t] indexer, + float32_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + float32_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF True: + cdef: + float32_t *v + float32_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(float32_t) and + sizeof(float32_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(float32_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis0_float32_float32(ndarray[float32_t, ndim=2] values, + ndarray[int64_t] indexer, + float32_t[:, :] out, + fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_float32_float32_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + float32_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF True: + cdef: + float32_t *v + float32_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(float32_t) and + sizeof(float32_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(float32_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis0_float32_float64_memview(float32_t[:, :] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + float64_t *v + float64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(float64_t) and + sizeof(float64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(float64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis0_float32_float64(ndarray[float32_t, ndim=2] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_float32_float64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + float64_t *v + float64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(float64_t) and + sizeof(float64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(float64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis0_float64_float64_memview(float64_t[:, :] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF True: + cdef: + float64_t *v + float64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(float64_t) and + sizeof(float64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(float64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis0_float64_float64(ndarray[float64_t, ndim=2] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_float64_float64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF True: + cdef: + float64_t *v + float64_t *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(float64_t) and + sizeof(float64_t) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(float64_t) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis0_object_object_memview(object[:, :] values, + ndarray[int64_t] indexer, + object[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + object fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + object *v + object *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(object) and + sizeof(object) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(object) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis0_object_object(ndarray[object, ndim=2] values, + ndarray[int64_t] indexer, + object[:, :] out, + fill_value=np.nan): + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis0_object_object_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + object fv + + n = len(indexer) + k = values.shape[1] + + fv = fill_value + + IF False: + cdef: + object *v + object *o + + #GH3130 + if (values.strides[1] == out.strides[1] and + values.strides[1] == sizeof(object) and + sizeof(object) * n >= 256): + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + v = &values[idx, 0] + o = &out[i, 0] + memmove(o, v, (sizeof(object) * k)) + return + + for i from 0 <= i < n: + idx = indexer[i] + if idx == -1: + for j from 0 <= j < k: + out[i, j] = fv + else: + for j from 0 <= j < k: + out[i, j] = values[idx, j] + + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis1_bool_bool_memview(uint8_t[:, :] values, + ndarray[int64_t] indexer, + uint8_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + uint8_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis1_bool_bool(ndarray[uint8_t, ndim=2] values, + ndarray[int64_t] indexer, + uint8_t[:, :] out, + fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_bool_bool_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + uint8_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis1_bool_object_memview(uint8_t[:, :] values, + ndarray[int64_t] indexer, + object[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + object fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = True if values[i, idx] > 0 else False + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis1_bool_object(ndarray[uint8_t, ndim=2] values, + ndarray[int64_t] indexer, + object[:, :] out, + fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_bool_object_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + object fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = True if values[i, idx] > 0 else False +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis1_int8_int8_memview(int8_t[:, :] values, + ndarray[int64_t] indexer, + int8_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + int8_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis1_int8_int8(ndarray[int8_t, ndim=2] values, + ndarray[int64_t] indexer, + int8_t[:, :] out, + fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int8_int8_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + int8_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis1_int8_int32_memview(int8_t[:, :] values, + ndarray[int64_t] indexer, + int32_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + int32_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis1_int8_int32(ndarray[int8_t, ndim=2] values, + ndarray[int64_t] indexer, + int32_t[:, :] out, + fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int8_int32_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + int32_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis1_int8_int64_memview(int8_t[:, :] values, + ndarray[int64_t] indexer, + int64_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + int64_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis1_int8_int64(ndarray[int8_t, ndim=2] values, + ndarray[int64_t] indexer, + int64_t[:, :] out, + fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int8_int64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + int64_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis1_int8_float64_memview(int8_t[:, :] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis1_int8_float64(ndarray[int8_t, ndim=2] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int8_float64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis1_int16_int16_memview(int16_t[:, :] values, + ndarray[int64_t] indexer, + int16_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + int16_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] + + +@cython.wraparound(False) +@cython.boundscheck(False) +def take_2d_axis1_int16_int16(ndarray[int16_t, ndim=2] values, + ndarray[int64_t] indexer, + int16_t[:, :] out, + fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int16_int16_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. + cdef: + Py_ssize_t i, j, k, n, idx + int16_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis1_int16_int32_memview(int16_t[:, :] values, + ndarray[int64_t] indexer, + int32_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + int32_t fv + + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return + + fv = fill_value + + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: out[i, j] = fv - else: - for j from 0 <= j < k: - out[i, j] = values[idx, j] + else: + out[i, j] = values[i, idx] + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_float64_float64(float64_t[:, :] values, +def take_2d_axis1_int16_int32(ndarray[int16_t, ndim=2] values, ndarray[int64_t] indexer, - float64_t[:, :] out, + int32_t[:, :] out, fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int16_int32_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - float64_t fv + int32_t fv - n = len(indexer) - k = values.shape[1] + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return fv = fill_value - IF True: - cdef: - float64_t *v - float64_t *o + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis1_int16_int64_memview(int16_t[:, :] values, + ndarray[int64_t] indexer, + int64_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + int64_t fv - #GH3130 - if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(float64_t) and - sizeof(float64_t) * n >= 256): + n = len(values) + k = len(indexer) - for i from 0 <= i < n: - idx = indexer[i] - if idx == -1: - for j from 0 <= j < k: - out[i, j] = fv - else: - v = &values[idx, 0] - o = &out[i, 0] - memmove(o, v, (sizeof(float64_t) * k)) - return + if n == 0 or k == 0: + return + + fv = fill_value for i from 0 <= i < n: - idx = indexer[i] - if idx == -1: - for j from 0 <= j < k: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: out[i, j] = fv - else: - for j from 0 <= j < k: - out[i, j] = values[idx, j] + else: + out[i, j] = values[i, idx] + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis0_object_object(object[:, :] values, +def take_2d_axis1_int16_int64(ndarray[int16_t, ndim=2] values, ndarray[int64_t] indexer, - object[:, :] out, + int64_t[:, :] out, fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int16_int64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - object fv + int64_t fv - n = len(indexer) - k = values.shape[1] + n = len(values) + k = len(indexer) + + if n == 0 or k == 0: + return fv = fill_value - IF False: - cdef: - object *v - object *o + for i from 0 <= i < n: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: + out[i, j] = fv + else: + out[i, j] = values[i, idx] +@cython.wraparound(False) +@cython.boundscheck(False) +cdef inline take_2d_axis1_int16_float64_memview(int16_t[:, :] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): + cdef: + Py_ssize_t i, j, k, n, idx + float64_t fv - #GH3130 - if (values.strides[1] == out.strides[1] and - values.strides[1] == sizeof(object) and - sizeof(object) * n >= 256): + n = len(values) + k = len(indexer) - for i from 0 <= i < n: - idx = indexer[i] - if idx == -1: - for j from 0 <= j < k: - out[i, j] = fv - else: - v = &values[idx, 0] - o = &out[i, 0] - memmove(o, v, (sizeof(object) * k)) - return + if n == 0 or k == 0: + return + + fv = fill_value for i from 0 <= i < n: - idx = indexer[i] - if idx == -1: - for j from 0 <= j < k: + for j from 0 <= j < k: + idx = indexer[j] + if idx == -1: out[i, j] = fv - else: - for j from 0 <= j < k: - out[i, j] = values[idx, j] + else: + out[i, j] = values[i, idx] @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_bool_bool(uint8_t[:, :] values, +def take_2d_axis1_int16_float64(ndarray[int16_t, ndim=2] values, ndarray[int64_t] indexer, - uint8_t[:, :] out, + float64_t[:, :] out, fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int16_float64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - uint8_t fv + float64_t fv n = len(values) k = len(indexer) @@ -3583,16 +5242,15 @@ def take_2d_axis1_bool_bool(uint8_t[:, :] values, out[i, j] = fv else: out[i, j] = values[i, idx] - @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_bool_object(uint8_t[:, :] values, - ndarray[int64_t] indexer, - object[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis1_int32_int32_memview(int32_t[:, :] values, + ndarray[int64_t] indexer, + int32_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - object fv + int32_t fv n = len(values) k = len(indexer) @@ -3608,17 +5266,28 @@ def take_2d_axis1_bool_object(uint8_t[:, :] values, if idx == -1: out[i, j] = fv else: - out[i, j] = True if values[i, idx] > 0 else False + out[i, j] = values[i, idx] + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int8_int8(int8_t[:, :] values, +def take_2d_axis1_int32_int32(ndarray[int32_t, ndim=2] values, ndarray[int64_t] indexer, - int8_t[:, :] out, + int32_t[:, :] out, fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int32_int32_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - int8_t fv + int32_t fv n = len(values) k = len(indexer) @@ -3635,16 +5304,15 @@ def take_2d_axis1_int8_int8(int8_t[:, :] values, out[i, j] = fv else: out[i, j] = values[i, idx] - @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int8_int32(int8_t[:, :] values, - ndarray[int64_t] indexer, - int32_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis1_int32_int64_memview(int32_t[:, :] values, + ndarray[int64_t] indexer, + int64_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - int32_t fv + int64_t fv n = len(values) k = len(indexer) @@ -3662,12 +5330,23 @@ def take_2d_axis1_int8_int32(int8_t[:, :] values, else: out[i, j] = values[i, idx] + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int8_int64(int8_t[:, :] values, +def take_2d_axis1_int32_int64(ndarray[int32_t, ndim=2] values, ndarray[int64_t] indexer, int64_t[:, :] out, fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int32_int64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx int64_t fv @@ -3687,13 +5366,12 @@ def take_2d_axis1_int8_int64(int8_t[:, :] values, out[i, j] = fv else: out[i, j] = values[i, idx] - @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int8_float64(int8_t[:, :] values, - ndarray[int64_t] indexer, - float64_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis1_int32_float64_memview(int32_t[:, :] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx float64_t fv @@ -3714,15 +5392,26 @@ def take_2d_axis1_int8_float64(int8_t[:, :] values, else: out[i, j] = values[i, idx] + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int16_int16(int16_t[:, :] values, +def take_2d_axis1_int32_float64(ndarray[int32_t, ndim=2] values, ndarray[int64_t] indexer, - int16_t[:, :] out, + float64_t[:, :] out, fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int32_float64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - int16_t fv + float64_t fv n = len(values) k = len(indexer) @@ -3739,16 +5428,15 @@ def take_2d_axis1_int16_int16(int16_t[:, :] values, out[i, j] = fv else: out[i, j] = values[i, idx] - @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int16_int32(int16_t[:, :] values, - ndarray[int64_t] indexer, - int32_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis1_int64_int64_memview(int64_t[:, :] values, + ndarray[int64_t] indexer, + int64_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - int32_t fv + int64_t fv n = len(values) k = len(indexer) @@ -3766,12 +5454,23 @@ def take_2d_axis1_int16_int32(int16_t[:, :] values, else: out[i, j] = values[i, idx] + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int16_int64(int16_t[:, :] values, +def take_2d_axis1_int64_int64(ndarray[int64_t, ndim=2] values, ndarray[int64_t] indexer, int64_t[:, :] out, fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int64_int64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx int64_t fv @@ -3791,13 +5490,12 @@ def take_2d_axis1_int16_int64(int16_t[:, :] values, out[i, j] = fv else: out[i, j] = values[i, idx] - @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int16_float64(int16_t[:, :] values, - ndarray[int64_t] indexer, - float64_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis1_int64_float64_memview(int64_t[:, :] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx float64_t fv @@ -3818,15 +5516,26 @@ def take_2d_axis1_int16_float64(int16_t[:, :] values, else: out[i, j] = values[i, idx] + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int32_int32(int32_t[:, :] values, +def take_2d_axis1_int64_float64(ndarray[int64_t, ndim=2] values, ndarray[int64_t] indexer, - int32_t[:, :] out, + float64_t[:, :] out, fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_int64_float64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - int32_t fv + float64_t fv n = len(values) k = len(indexer) @@ -3843,16 +5552,15 @@ def take_2d_axis1_int32_int32(int32_t[:, :] values, out[i, j] = fv else: out[i, j] = values[i, idx] - @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int32_int64(int32_t[:, :] values, - ndarray[int64_t] indexer, - int64_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis1_float32_float32_memview(float32_t[:, :] values, + ndarray[int64_t] indexer, + float32_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - int64_t fv + float32_t fv n = len(values) k = len(indexer) @@ -3870,15 +5578,26 @@ def take_2d_axis1_int32_int64(int32_t[:, :] values, else: out[i, j] = values[i, idx] + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int32_float64(int32_t[:, :] values, +def take_2d_axis1_float32_float32(ndarray[float32_t, ndim=2] values, ndarray[int64_t] indexer, - float64_t[:, :] out, + float32_t[:, :] out, fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_float32_float32_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx - float64_t fv + float32_t fv n = len(values) k = len(indexer) @@ -3895,16 +5614,15 @@ def take_2d_axis1_int32_float64(int32_t[:, :] values, out[i, j] = fv else: out[i, j] = values[i, idx] - @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int64_int64(int64_t[:, :] values, - ndarray[int64_t] indexer, - int64_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis1_float32_float64_memview(float32_t[:, :] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - int64_t fv + float64_t fv n = len(values) k = len(indexer) @@ -3922,12 +5640,23 @@ def take_2d_axis1_int64_int64(int64_t[:, :] values, else: out[i, j] = values[i, idx] + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_int64_float64(int64_t[:, :] values, +def take_2d_axis1_float32_float64(ndarray[float32_t, ndim=2] values, ndarray[int64_t] indexer, float64_t[:, :] out, fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_float32_float64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx float64_t fv @@ -3947,16 +5676,15 @@ def take_2d_axis1_int64_float64(int64_t[:, :] values, out[i, j] = fv else: out[i, j] = values[i, idx] - @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_float32_float32(float32_t[:, :] values, - ndarray[int64_t] indexer, - float32_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis1_float64_float64_memview(float64_t[:, :] values, + ndarray[int64_t] indexer, + float64_t[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - float32_t fv + float64_t fv n = len(values) k = len(indexer) @@ -3974,12 +5702,23 @@ def take_2d_axis1_float32_float32(float32_t[:, :] values, else: out[i, j] = values[i, idx] + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_float32_float64(float32_t[:, :] values, +def take_2d_axis1_float64_float64(ndarray[float64_t, ndim=2] values, ndarray[int64_t] indexer, float64_t[:, :] out, fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_float64_float64_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx float64_t fv @@ -3999,16 +5738,15 @@ def take_2d_axis1_float32_float64(float32_t[:, :] values, out[i, j] = fv else: out[i, j] = values[i, idx] - @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_float64_float64(float64_t[:, :] values, - ndarray[int64_t] indexer, - float64_t[:, :] out, - fill_value=np.nan): +cdef inline take_2d_axis1_object_object_memview(object[:, :] values, + ndarray[int64_t] indexer, + object[:, :] out, + fill_value=np.nan): cdef: Py_ssize_t i, j, k, n, idx - float64_t fv + object fv n = len(values) k = len(indexer) @@ -4026,12 +5764,23 @@ def take_2d_axis1_float64_float64(float64_t[:, :] values, else: out[i, j] = values[i, idx] + @cython.wraparound(False) @cython.boundscheck(False) -def take_2d_axis1_object_object(object[:, :] values, +def take_2d_axis1_object_object(ndarray[object, ndim=2] values, ndarray[int64_t] indexer, object[:, :] out, fill_value=np.nan): + + if values.flags.writeable: + # We can call the memoryview version of the code + take_2d_axis1_object_object_memview(values, indexer, out, + fill_value=fill_value) + return + + # We cannot use the memoryview version on readonly-buffers due to + # a limitation of Cython's typed memoryviews. Instead we can use + # the slightly slower Cython ndarray type directly. cdef: Py_ssize_t i, j, k, n, idx object fv @@ -4052,7 +5801,6 @@ def take_2d_axis1_object_object(object[:, :] values, else: out[i, j] = values[i, idx] - @cython.wraparound(False) @cython.boundscheck(False) def take_2d_multi_bool_bool(ndarray[uint8_t, ndim=2] values, @@ -5784,7 +7532,8 @@ def group_ohlc_float64(ndarray[float64_t, ndim=2] out, b = 0 if K > 1: - raise NotImplementedError + raise NotImplementedError("Argument 'values' must have only " + "one dimension") else: for i in range(N): while b < ngroups - 1 and i >= bins[b]: @@ -5857,7 +7606,8 @@ def group_ohlc_float32(ndarray[float32_t, ndim=2] out, b = 0 if K > 1: - raise NotImplementedError + raise NotImplementedError("Argument 'values' must have only " + "one dimension") else: for i in range(N): while b < ngroups - 1 and i >= bins[b]: diff --git a/pandas/tests/test_common.py b/pandas/tests/test_common.py index 0daea15e617a3..3282a36bda7b8 100644 --- a/pandas/tests/test_common.py +++ b/pandas/tests/test_common.py @@ -628,8 +628,9 @@ def _test_dtype(dtype, fill_value, out_dtype): _test_dtype(np.bool_, '', np.object_) def test_2d_with_out(self): - def _test_dtype(dtype, can_hold_na): + def _test_dtype(dtype, can_hold_na, writeable=True): data = np.random.randint(0, 2, (5, 3)).astype(dtype) + data.flags.writeable = writeable indexer = [2, 1, 0, 1] out0 = np.empty((4, 3), dtype=dtype) @@ -660,18 +661,22 @@ def _test_dtype(dtype, can_hold_na): # no exception o/w data.take(indexer, out=out, axis=i) - _test_dtype(np.float64, True) - _test_dtype(np.float32, True) - _test_dtype(np.uint64, False) - _test_dtype(np.uint32, False) - _test_dtype(np.uint16, False) - _test_dtype(np.uint8, False) - _test_dtype(np.int64, False) - _test_dtype(np.int32, False) - _test_dtype(np.int16, False) - _test_dtype(np.int8, False) - _test_dtype(np.object_, True) - _test_dtype(np.bool, False) + for writeable in [True, False]: + # Check that take_nd works both with writeable arrays (in which + # case fast typed memoryviews implementation) and read-only + # arrays alike. + _test_dtype(np.float64, True, writeable=writeable) + _test_dtype(np.float32, True, writeable=writeable) + _test_dtype(np.uint64, False, writeable=writeable) + _test_dtype(np.uint32, False, writeable=writeable) + _test_dtype(np.uint16, False, writeable=writeable) + _test_dtype(np.uint8, False, writeable=writeable) + _test_dtype(np.int64, False, writeable=writeable) + _test_dtype(np.int32, False, writeable=writeable) + _test_dtype(np.int16, False, writeable=writeable) + _test_dtype(np.int8, False, writeable=writeable) + _test_dtype(np.object_, True, writeable=writeable) + _test_dtype(np.bool, False, writeable=writeable) def test_2d_fill_nonna(self): def _test_dtype(dtype, fill_value, out_dtype): From ca558185a8e95f999551141f80f1f55d4aafed5d Mon Sep 17 00:00:00 2001 From: Jeff Reback Date: Wed, 6 May 2015 19:23:31 -0400 Subject: [PATCH 2/2] BUG: use memory view for indexer in take_2d / tests (GH10043) --- doc/source/whatsnew/v0.16.1.txt | 2 +- pandas/src/generate_code.py | 4 +- pandas/src/generated.pyx | 76 ++++++++++++++++----------------- pandas/tests/test_indexing.py | 19 +++++++++ 4 files changed, 60 insertions(+), 41 deletions(-) diff --git a/doc/source/whatsnew/v0.16.1.txt b/doc/source/whatsnew/v0.16.1.txt index 493f299b2bf32..d7a63ea21ad40 100755 --- a/doc/source/whatsnew/v0.16.1.txt +++ b/doc/source/whatsnew/v0.16.1.txt @@ -255,7 +255,7 @@ Bug Fixes - Bug where ``TimdeltaIndex`` were not properly serialized in fixed ``HDFStore`` (:issue:`9635`) - Bug with ``TimedeltaIndex`` constructor ignoring ``name`` when given another ``TimedeltaIndex`` as data (:issue:`10025`). - Bug in ``DataFrameFormatter._get_formatted_index`` with not applying ``max_colwidth`` to the ``DataFrame`` index (:issue:`7856`) - +- Bug in ``.loc`` with a read-only ndarray data source (:issue:`10043`) - Bug in ``groupby.apply()`` that would raise if a passed user defined function either returned only ``None`` (for all input). (:issue:`9685`) - Bug in plotting continuously using ``secondary_y`` may not show legend properly. (:issue:`9610`, :issue:`9779`) diff --git a/pandas/src/generate_code.py b/pandas/src/generate_code.py index 3b71d1c083ba1..a0cdc0ff5e841 100644 --- a/pandas/src/generate_code.py +++ b/pandas/src/generate_code.py @@ -139,7 +139,7 @@ def take_1d_%(name)s_%(dest)s(ndarray[%(c_type_in)s] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_%(name)s_%(dest)s_memview(%(c_type_in)s[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, %(c_type_out)s[:, :] out, fill_value=np.nan): """ + inner_take_2d_axis0_template + """ @@ -188,7 +188,7 @@ def take_2d_axis0_%(name)s_%(dest)s(ndarray[%(c_type_in)s, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_%(name)s_%(dest)s_memview(%(c_type_in)s[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, %(c_type_out)s[:, :] out, fill_value=np.nan): """ + inner_take_2d_axis1_template + """ diff --git a/pandas/src/generated.pyx b/pandas/src/generated.pyx index ac31fdedf2ea6..79722a26ebedc 100644 --- a/pandas/src/generated.pyx +++ b/pandas/src/generated.pyx @@ -2705,7 +2705,7 @@ def take_1d_object_object(ndarray[object] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_bool_bool_memview(uint8_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, uint8_t[:, :] out, fill_value=np.nan): cdef: @@ -2806,7 +2806,7 @@ def take_2d_axis0_bool_bool(ndarray[uint8_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_bool_object_memview(uint8_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, object[:, :] out, fill_value=np.nan): cdef: @@ -2907,7 +2907,7 @@ def take_2d_axis0_bool_object(ndarray[uint8_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int8_int8_memview(int8_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int8_t[:, :] out, fill_value=np.nan): cdef: @@ -3008,7 +3008,7 @@ def take_2d_axis0_int8_int8(ndarray[int8_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int8_int32_memview(int8_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int32_t[:, :] out, fill_value=np.nan): cdef: @@ -3109,7 +3109,7 @@ def take_2d_axis0_int8_int32(ndarray[int8_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int8_int64_memview(int8_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int64_t[:, :] out, fill_value=np.nan): cdef: @@ -3210,7 +3210,7 @@ def take_2d_axis0_int8_int64(ndarray[int8_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int8_float64_memview(int8_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float64_t[:, :] out, fill_value=np.nan): cdef: @@ -3311,7 +3311,7 @@ def take_2d_axis0_int8_float64(ndarray[int8_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int16_int16_memview(int16_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int16_t[:, :] out, fill_value=np.nan): cdef: @@ -3412,7 +3412,7 @@ def take_2d_axis0_int16_int16(ndarray[int16_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int16_int32_memview(int16_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int32_t[:, :] out, fill_value=np.nan): cdef: @@ -3513,7 +3513,7 @@ def take_2d_axis0_int16_int32(ndarray[int16_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int16_int64_memview(int16_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int64_t[:, :] out, fill_value=np.nan): cdef: @@ -3614,7 +3614,7 @@ def take_2d_axis0_int16_int64(ndarray[int16_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int16_float64_memview(int16_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float64_t[:, :] out, fill_value=np.nan): cdef: @@ -3715,7 +3715,7 @@ def take_2d_axis0_int16_float64(ndarray[int16_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int32_int32_memview(int32_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int32_t[:, :] out, fill_value=np.nan): cdef: @@ -3816,7 +3816,7 @@ def take_2d_axis0_int32_int32(ndarray[int32_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int32_int64_memview(int32_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int64_t[:, :] out, fill_value=np.nan): cdef: @@ -3917,7 +3917,7 @@ def take_2d_axis0_int32_int64(ndarray[int32_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int32_float64_memview(int32_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float64_t[:, :] out, fill_value=np.nan): cdef: @@ -4018,7 +4018,7 @@ def take_2d_axis0_int32_float64(ndarray[int32_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int64_int64_memview(int64_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int64_t[:, :] out, fill_value=np.nan): cdef: @@ -4119,7 +4119,7 @@ def take_2d_axis0_int64_int64(ndarray[int64_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_int64_float64_memview(int64_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float64_t[:, :] out, fill_value=np.nan): cdef: @@ -4220,7 +4220,7 @@ def take_2d_axis0_int64_float64(ndarray[int64_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_float32_float32_memview(float32_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float32_t[:, :] out, fill_value=np.nan): cdef: @@ -4321,7 +4321,7 @@ def take_2d_axis0_float32_float32(ndarray[float32_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_float32_float64_memview(float32_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float64_t[:, :] out, fill_value=np.nan): cdef: @@ -4422,7 +4422,7 @@ def take_2d_axis0_float32_float64(ndarray[float32_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_float64_float64_memview(float64_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float64_t[:, :] out, fill_value=np.nan): cdef: @@ -4523,7 +4523,7 @@ def take_2d_axis0_float64_float64(ndarray[float64_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis0_object_object_memview(object[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, object[:, :] out, fill_value=np.nan): cdef: @@ -4625,7 +4625,7 @@ def take_2d_axis0_object_object(ndarray[object, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_bool_bool_memview(uint8_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, uint8_t[:, :] out, fill_value=np.nan): cdef: @@ -4687,7 +4687,7 @@ def take_2d_axis1_bool_bool(ndarray[uint8_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_bool_object_memview(uint8_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, object[:, :] out, fill_value=np.nan): cdef: @@ -4749,7 +4749,7 @@ def take_2d_axis1_bool_object(ndarray[uint8_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int8_int8_memview(int8_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int8_t[:, :] out, fill_value=np.nan): cdef: @@ -4811,7 +4811,7 @@ def take_2d_axis1_int8_int8(ndarray[int8_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int8_int32_memview(int8_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int32_t[:, :] out, fill_value=np.nan): cdef: @@ -4873,7 +4873,7 @@ def take_2d_axis1_int8_int32(ndarray[int8_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int8_int64_memview(int8_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int64_t[:, :] out, fill_value=np.nan): cdef: @@ -4935,7 +4935,7 @@ def take_2d_axis1_int8_int64(ndarray[int8_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int8_float64_memview(int8_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float64_t[:, :] out, fill_value=np.nan): cdef: @@ -4997,7 +4997,7 @@ def take_2d_axis1_int8_float64(ndarray[int8_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int16_int16_memview(int16_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int16_t[:, :] out, fill_value=np.nan): cdef: @@ -5059,7 +5059,7 @@ def take_2d_axis1_int16_int16(ndarray[int16_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int16_int32_memview(int16_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int32_t[:, :] out, fill_value=np.nan): cdef: @@ -5121,7 +5121,7 @@ def take_2d_axis1_int16_int32(ndarray[int16_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int16_int64_memview(int16_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int64_t[:, :] out, fill_value=np.nan): cdef: @@ -5183,7 +5183,7 @@ def take_2d_axis1_int16_int64(ndarray[int16_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int16_float64_memview(int16_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float64_t[:, :] out, fill_value=np.nan): cdef: @@ -5245,7 +5245,7 @@ def take_2d_axis1_int16_float64(ndarray[int16_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int32_int32_memview(int32_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int32_t[:, :] out, fill_value=np.nan): cdef: @@ -5307,7 +5307,7 @@ def take_2d_axis1_int32_int32(ndarray[int32_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int32_int64_memview(int32_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int64_t[:, :] out, fill_value=np.nan): cdef: @@ -5369,7 +5369,7 @@ def take_2d_axis1_int32_int64(ndarray[int32_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int32_float64_memview(int32_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float64_t[:, :] out, fill_value=np.nan): cdef: @@ -5431,7 +5431,7 @@ def take_2d_axis1_int32_float64(ndarray[int32_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int64_int64_memview(int64_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, int64_t[:, :] out, fill_value=np.nan): cdef: @@ -5493,7 +5493,7 @@ def take_2d_axis1_int64_int64(ndarray[int64_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_int64_float64_memview(int64_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float64_t[:, :] out, fill_value=np.nan): cdef: @@ -5555,7 +5555,7 @@ def take_2d_axis1_int64_float64(ndarray[int64_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_float32_float32_memview(float32_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float32_t[:, :] out, fill_value=np.nan): cdef: @@ -5617,7 +5617,7 @@ def take_2d_axis1_float32_float32(ndarray[float32_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_float32_float64_memview(float32_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float64_t[:, :] out, fill_value=np.nan): cdef: @@ -5679,7 +5679,7 @@ def take_2d_axis1_float32_float64(ndarray[float32_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_float64_float64_memview(float64_t[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, float64_t[:, :] out, fill_value=np.nan): cdef: @@ -5741,7 +5741,7 @@ def take_2d_axis1_float64_float64(ndarray[float64_t, ndim=2] values, @cython.wraparound(False) @cython.boundscheck(False) cdef inline take_2d_axis1_object_object_memview(object[:, :] values, - ndarray[int64_t] indexer, + int64_t[:] indexer, object[:, :] out, fill_value=np.nan): cdef: diff --git a/pandas/tests/test_indexing.py b/pandas/tests/test_indexing.py index 1bea124bb9f81..c998ce65791a3 100644 --- a/pandas/tests/test_indexing.py +++ b/pandas/tests/test_indexing.py @@ -4530,6 +4530,25 @@ def test_loc_listlike(self): # not all labels in the categories self.assertRaises(KeyError, lambda : self.df2.loc[['a','d']]) + def test_read_only_source(self): + # GH 10043 + rw_array = np.eye(10) + rw_df = DataFrame(rw_array) + + ro_array = np.eye(10) + ro_array.setflags(write=False) + ro_df = DataFrame(ro_array) + + assert_frame_equal(rw_df.iloc[[1,2,3]],ro_df.iloc[[1,2,3]]) + assert_frame_equal(rw_df.iloc[[1]],ro_df.iloc[[1]]) + assert_series_equal(rw_df.iloc[1],ro_df.iloc[1]) + assert_frame_equal(rw_df.iloc[1:3],ro_df.iloc[1:3]) + + assert_frame_equal(rw_df.loc[[1,2,3]],ro_df.loc[[1,2,3]]) + assert_frame_equal(rw_df.loc[[1]],ro_df.loc[[1]]) + assert_series_equal(rw_df.loc[1],ro_df.loc[1]) + assert_frame_equal(rw_df.loc[1:3],ro_df.loc[1:3]) + def test_reindexing(self): # reindexing