[Cython] Fused Types

Robert Bradshaw robertwb at math.washington.edu
Sat Apr 30 08:39:58 CEST 2011


On Fri, Apr 29, 2011 at 3:53 AM, mark florisson
<markflorisson88 at gmail.com> wrote:
> On 29 April 2011 12:28, Pauli Virtanen <pav at iki.fi> wrote:
>> Fri, 29 Apr 2011 11:30:19 +0200, mark florisson wrote:
>>> On 29 April 2011 11:03, Pauli Virtanen <pav at iki.fi> wrote:
>> [clip]
>>>> Are you planning to special-case the "real_t complex" syntax? Shooting
>>>> from the sidelines, one more generic solution might be, e.g.,
>>>
>>> I'm sorry, I'm not sure what syntax you are referring to. Are you
>>> talking about actual complex numbers?
>>
>> This:
>>
>> On 28 April 2011 23:30, Robert Bradshaw <robertwb at math.washington.edu>
>> wrote:
>>> OK, I take back what I said, I was looking at the RHS, not the LHS. If
>>> one needs to specialize in this manner, explicitly creating two
>>> branches should typically be enough. The same for casting. The one
>>> exception (perhaps) is "my_fused_type complex." Otherwise it's
>>> starting to feel too much like C++ template magic and complexity for
>>> little additional benefit.
>>
>> That is, declaring a complex type matching a real one.
>
> Ah, I see what you mean now.
>
>>>>        ctypedef cython.fused_type(A, B) struct_t
>>>>        ctypedef cython.fused_type(float, double, paired=struct_t) real_t
>>>>        ctypedef cython.fused_type(int_t, string_t, paired=struct_t) var_t
>>>>
>>>> and just restrict the specialization to cases that make sense.
>>>
>>> The paired means you're declaring types of attributes?
>>
>> No, just that real_t is specialized to float whenever struct_t is specialized
>> to A and to double when B. Or a more realistic example,
>>
>>        ctypedef cython.fused_type(float, double) real_t
>>        ctypedef cython.fused_type(float complex, double complex) complex_t
>>
>>        cdef real_plus_one(complex_t a):
>>            real_t b = a.real
>>            return b + 1
>>
>> which I suppose would not be a very unusual thing in numerical codes.
>> This would also allow writing the case you had earlier as
>>
>>        cdef cython.fused_type(string_t, int, paired=struct_t) attr_t
>>
>>        cdef func(struct_t mystruct, int i):
>>            cdef attr_t var
>>
>>            if typeof(mystruct) is typeof(int):
>>                var = mystruct.attrib + i
>>                ...
>>            else:
>>                var = mystruct.attrib + i
>>                ...
>>
>> Things would need to be done explicitly instead of implicitly, though,
>> but it would remove the need for any special handling of
>> the "complex" keyword.

If we're going to introduce pairing, another option would be

    ctypedef fused_type((double complex, double), (float complex,
float)) (complex_t, real_t)

though I'm not sure I like that either. We're not trying to create the
all-powerful templating system here, and anything that can be done
with pairing can be done (though less elegantly) via branching on the
types, or, as Pauli mentions, using a wider type is often (but not
always) a viable option.

We talked of supporting fused types in classes, one could do the same
for structs, thus

    cdef fused_type(int, double) int_or_double
    cdef my_struct:
        int_or_double attr

    cdef func1(int_or_double x):
        cdef my_struct
        my_struct.attr = x

and

    cdef func2(my_struct s)
        cdef int_or_double x = s.attr

could work. Maybe we'd require an explicit "my_struct[int_or_double]".
This would solve a large number of the remaining cases, and complex is
like a struct + native arithmetic/promotion.

> I see, so it's like a mapping. So, I didn't realize that you can't do this:
>
> def func(arbitrary_type complex x):
>    ...
>
> But if we just allow that for fused types, then couldn't we simply do
>
> ctypedef cython.fused_type(float, double) real_t
>
> cdef real_plus_one(real_t complex a):
>    real_t b = a.real
>    return b + 1
>
> ? Then you don't need to pair anything.

That's what I was thinking. It's a bit special, but on the other hand
a very natural pairing that one would want to be able to do with a
very natural syntax (no one reading that code would wonder what it
means).

> Perhaps we could introduce
> real_t as a type, just like numeric and floating. So I guess
> special-casing complex sounds fine with me. Perhaps real_t should be
> builtin (not as an attribute of the Cython module), so the parser can
> just recognize it immediately?

I'd rather not add new keywords to the language, and I don't see what
advantage letting real_t be known to the parser woud be, we can ship a
pxd file with the common fused types.

- Robert


More information about the cython-devel mailing list