Commit ff8e254e authored by Thomas VINCENT's avatar Thomas VINCENT Committed by Stefan Behnel

Add support of const fused type memory views (GH-3118)

parent 97f1bbde
...@@ -1573,6 +1573,8 @@ class PythranExpr(CType): ...@@ -1573,6 +1573,8 @@ class PythranExpr(CType):
class CConstOrVolatileType(BaseType): class CConstOrVolatileType(BaseType):
"A C const or volatile type" "A C const or volatile type"
subtypes = ['cv_base_type']
is_cv_qualified = 1 is_cv_qualified = 1
def __init__(self, base_type, is_const=0, is_volatile=0): def __init__(self, base_type, is_const=0, is_volatile=0):
......
# mode: error # mode: error
# ticket: 1772
cimport cython cimport cython
from cython import fused_type from cython import fused_type
...@@ -64,17 +65,30 @@ ctypedef fused fused2: ...@@ -64,17 +65,30 @@ ctypedef fused fused2:
func(x, y) func(x, y)
cdef fused mix_const_t:
int
const int
cdef cdef_func_with_mix_const_type(mix_const_t val):
print(val)
# Mixing const and non-const type makes fused type ambiguous
cdef_func_with_mix_const_type(1)
_ERRORS = u""" _ERRORS = u"""
10:15: fused_type does not take keyword arguments 11:15: fused_type does not take keyword arguments
15:33: Type specified multiple times 16:33: Type specified multiple times
26:0: Invalid use of fused types, type cannot be specialized
26:4: Not enough types specified to specialize the function, int2_t is still fused
27:0: Invalid use of fused types, type cannot be specialized 27:0: Invalid use of fused types, type cannot be specialized
27:4: Not enough types specified to specialize the function, int2_t is still fused 27:4: Not enough types specified to specialize the function, int2_t is still fused
28:16: Call with wrong number of arguments (expected 2, got 1) 28:0: Invalid use of fused types, type cannot be specialized
29:16: Call with wrong number of arguments (expected 2, got 3) 28:4: Not enough types specified to specialize the function, int2_t is still fused
36:6: Invalid base type for memoryview slice: int * 29:16: Call with wrong number of arguments (expected 2, got 1)
39:0: Fused lambdas not allowed 30:16: Call with wrong number of arguments (expected 2, got 3)
42:5: Fused types not allowed here 37:6: Invalid base type for memoryview slice: int *
45:9: Fused types not allowed here 40:0: Fused lambdas not allowed
43:5: Fused types not allowed here
46:9: Fused types not allowed here
76:0: Invalid use of fused types, type cannot be specialized
76:29: ambiguous overloaded method
""" """
# mode: run # mode: run
# tag: readonly, const, numpy # tag: readonly, const, numpy
# ticket: 1772
import numpy as np import numpy as np
cimport cython
def new_array(): def new_array(dtype='float', writeable=True):
return np.arange(10).astype('float') array = np.arange(10, dtype=dtype)
array.setflags(write=writeable)
return array
ARRAY = new_array() ARRAY = new_array()
...@@ -124,3 +128,45 @@ def test_copy(): ...@@ -124,3 +128,45 @@ def test_copy():
rw[1] = 2 rw[1] = 2
rw2[2] = 2 rw2[2] = 2
return rw[0], rw[1], rw[2], rw2[0], rw2[1], rw2[2] return rw[0], rw[1], rw[2], rw2[0], rw2[1], rw2[2]
cdef getmax_floating(const cython.floating[:] x):
"""Function with fused type, should work with both ro and rw memoryviews"""
cdef cython.floating max_val = - float('inf')
for val in x:
if val > max_val:
max_val = val
return max_val
def test_mmview_const_fused_cdef():
"""Test cdef function with const fused type memory view as argument.
>>> test_mmview_const_fused_cdef()
"""
cdef float[:] data_rw = new_array(dtype='float32')
assert getmax_floating(data_rw) == 9
cdef const float[:] data_ro = new_array(dtype='float32', writeable=False)
assert getmax_floating(data_ro) == 9
def test_mmview_const_fused_def(const cython.floating[:] x):
"""Test def function with const fused type memory view as argument.
With read-write numpy array:
>>> test_mmview_const_fused_def(new_array('float32', writeable=True))
0.0
>>> test_mmview_const_fused_def(new_array('float64', writeable=True))
0.0
With read-only numpy array:
>>> test_mmview_const_fused_def(new_array('float32', writeable=False))
0.0
>>> test_mmview_const_fused_def(new_array('float64', writeable=False))
0.0
"""
cdef cython.floating result = x[0]
return result
# mode: run # mode: run
# ticket: 1772
cimport cython cimport cython
from cython.view cimport array from cython.view cimport array
...@@ -361,6 +362,22 @@ def test_fused_memslice_dtype_repeated_2(cython.floating[:] array1, cython.float ...@@ -361,6 +362,22 @@ def test_fused_memslice_dtype_repeated_2(cython.floating[:] array1, cython.float
""" """
print cython.typeof(array1), cython.typeof(array2), cython.typeof(array3) print cython.typeof(array1), cython.typeof(array2), cython.typeof(array3)
def test_fused_const_memslice_dtype_repeated(const cython.floating[:] array1, cython.floating[:] array2):
"""Test fused types memory view with one being const
>>> sorted(test_fused_const_memslice_dtype_repeated.__signatures__)
['double', 'float']
>>> test_fused_const_memslice_dtype_repeated(get_array(8, 'd'), get_array(8, 'd'))
const double[:] double[:]
>>> test_fused_const_memslice_dtype_repeated(get_array(4, 'f'), get_array(4, 'f'))
const float[:] float[:]
>>> test_fused_const_memslice_dtype_repeated(get_array(8, 'd'), get_array(4, 'f'))
Traceback (most recent call last):
ValueError: Buffer dtype mismatch, expected 'double' but got 'float'
"""
print cython.typeof(array1), cython.typeof(array2)
def test_cython_numeric(cython.numeric arg): def test_cython_numeric(cython.numeric arg):
""" """
Test to see whether complex numbers have their utility code declared Test to see whether complex numbers have their utility code declared
...@@ -386,6 +403,18 @@ def test_index_fused_args(cython.floating f, ints_t i): ...@@ -386,6 +403,18 @@ def test_index_fused_args(cython.floating f, ints_t i):
""" """
_test_index_fused_args[cython.floating, ints_t](f, i) _test_index_fused_args[cython.floating, ints_t](f, i)
cdef _test_index_const_fused_args(const cython.floating f, const ints_t i):
print(cython.typeof(f), cython.typeof(i))
def test_index_const_fused_args(const cython.floating f, const ints_t i):
"""Test indexing function implementation with const fused type args
>>> import cython
>>> test_index_const_fused_args[cython.double, cython.int](2.0, 3)
('const double', 'const int')
"""
_test_index_const_fused_args[cython.floating, ints_t](f, i)
def test_composite(fused_composite x): def test_composite(fused_composite x):
""" """
...@@ -400,3 +429,27 @@ def test_composite(fused_composite x): ...@@ -400,3 +429,27 @@ def test_composite(fused_composite x):
return x return x
else: else:
return 2 * x return 2 * x
cdef cdef_func_const_fused_arg(const cython.floating val,
const fused_type1 * ptr_to_const,
const (cython.floating *) const_ptr):
print(val, cython.typeof(val))
print(ptr_to_const[0], cython.typeof(ptr_to_const[0]))
print(const_ptr[0], cython.typeof(const_ptr[0]))
ptr_to_const = NULL # pointer is not const, value is const
const_ptr[0] = 0.0 # pointer is const, value is not const
def test_cdef_func_with_const_fused_arg():
"""Test cdef function with const fused type argument
>>> test_cdef_func_with_const_fused_arg()
(0.0, 'const float')
(1, 'const int')
(2.0, 'float')
"""
cdef float arg0 = 0.0
cdef int arg1 = 1
cdef float arg2 = 2.0
cdef_func_const_fused_arg(arg0, &arg1, &arg2)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment