cython

Форк
0
/
cpow.pyx 
259 строк · 7.4 Кб
1
# mode: run
2
# tag: warnings
3

4
from __future__ import print_function
5

6
cimport cython
7

8

9
def pow_double_double(double a, double b, delta):
10
    """
11
    >>> pow_double_double(2, 2, 1e-15)
12
    soft double complex float
13
    >>> pow_double_double(4, 0.5, 1e-15)
14
    soft double complex float
15
    >>> pow_double_double(-4, 0.5, 1e-15)
16
    soft double complex complex
17
    """
18
    c = a**b
19
    # print out the Cython type, and the coerced type
20
    print(cython.typeof(c), type(c).__name__)
21
    object_c = (<object>a)**(<object>b)
22
    assert abs((c/object_c) - 1) < delta
23

24
@cython.cpow(True)
25
def pow_double_double_cpow(double a, double b, delta=None):
26
    """
27
    >>> pow_double_double_cpow(2, 2, 1e-15)
28
    double float
29
    >>> pow_double_double_cpow(4, 0.5, 1e-15)
30
    double float
31
    >>> x = pow_double_double_cpow(-4, 0.5)
32
    double float
33
    >>> x == x  # is nan
34
    False
35
    """
36
    c = a**b
37
    # print out the Cython type, and the coerced type
38
    print(cython.typeof(c), type(c).__name__)
39
    if delta is not None:
40
        object_c = (<object>a)**(<object>b)
41
        assert abs((c/object_c) - 1) < delta
42
    else:
43
        return c
44

45
cdef cfunc_taking_double(double x):
46
    return x
47

48
def pow_double_double_coerced_directly(double a, double b):
49
    """
50
    >>> pow_double_double_coerced_directly(2, 2)
51
    8.0
52
    >>> x = pow_double_double_coerced_directly(-2, 0.5)
53
    >>> x == x  # nan
54
    False
55
    """
56
    # Because we're assigning directly to a double assume 'cpow'
57
    # but warn.
58
    cdef double c = a**b
59
    return cfunc_taking_double(a**b) + c
60

61
def pow_double_int(double a, int b):
62
    """
63
    # a few variations of 'double**int'. In all cases
64
    # Cython should realise that the result can't be complex
65
    # and avoid going through the soft complex type
66
    >>> pow_double_int(5, 2)
67
    double
68
    double
69
    double
70
    double
71
    double
72
    """
73
    c1 = a**b
74
    c2 = a**2.0
75
    c3 = a**-2.0
76
    c4 = a**5
77
    c5 = a**-5
78
    print(cython.typeof(c1))
79
    print(cython.typeof(c2))
80
    print(cython.typeof(c3))
81
    print(cython.typeof(c4))
82
    print(cython.typeof(c5))
83

84
def soft_complex_coerced_to_double(double a, double b):
85
    """
86
    >>> soft_complex_coerced_to_double(2, 2)
87
    4.0
88
    >>> soft_complex_coerced_to_double(-2, 0.25)
89
    Traceback (most recent call last):
90
    ...
91
    TypeError: Cannot convert 'complex' with non-zero imaginary component to 'double' (this most likely comes from the '**' operator; use 'cython.cpow(True)' to return 'nan' instead of a complex number).
92
    """
93
    c = a**b
94
    assert cython.typeof(c) == "soft double complex"
95
    cdef double d = c  # will raise if complex
96
    return d
97

98
def soft_complex_coerced_to_complex(double a, double b):
99
    """
100
    >>> soft_complex_coerced_to_complex(2, 2)
101
    (4+0j)
102
    >>> x = soft_complex_coerced_to_complex(-1, 0.5)
103
    >>> abs(x.real) < 1e-15
104
    True
105
    >>> abs(x.imag - 1) < 1e-15
106
    True
107
    """
108
    # This is always fine, but just check it works
109
    c = a**b
110
    assert cython.typeof(c) == "soft double complex"
111
    cdef double complex d = c
112
    return d
113

114
def soft_complex_type_inference_1(double a, double b, pick):
115
    """
116
    >>> soft_complex_type_inference_1(2, 1, False)
117
    soft double complex 2.0
118
    >>> soft_complex_type_inference_1(2, 3, True)
119
    soft double complex 4.0
120
    """
121
    # double and soft complex should infer to soft-complex
122
    if pick:
123
        c = a**2
124
    else:
125
        c = a**b
126
    print(cython.typeof(c), c)
127

128
def soft_complex_type_inference_2(double a, double b, expected):
129
    """
130
    >>> soft_complex_type_inference_2(2, 1, 1.0)
131
    soft double complex
132
    >>> soft_complex_type_inference_2(2, 3, 7.0)
133
    soft double complex
134
    """
135
    # double and soft complex should infer to soft-complex
136
    c = a**b
137
    c -= 1
138
    print(cython.typeof(c))
139
    delta = abs(c/expected - 1)
140
    assert delta < 1e-15, delta
141

142
def pow_int_int(int a, int b):
143
    """
144
    >>> pow_int_int(2, 2)
145
    double 4.0
146
    >>> pow_int_int(2, -2)
147
    double 0.25
148
    """
149
    c = a**b
150
    print(cython.typeof(c), c)
151

152
@cython.cpow(True)
153
def pow_int_int_cpow(int a, int b):
154
    """
155
    >>> pow_int_int_cpow(2, 2)
156
    int 4
157
    >>> pow_int_int_cpow(2, -2)
158
    int 0
159
    """
160
    c = a**b
161
    print(cython.typeof(c), c)
162

163
cdef cfunc_taking_int(int x):
164
    return x
165

166
def pow_int_int_coerced_directly(int a, int b):
167
    """
168
    Generates two warnings about using cpow.
169
    The actual behaviour isn't too easy to distinguish
170
    without inspecting the c code though.
171
    >>> pow_int_int_coerced_directly(2, 2)
172
    8
173
    """
174
    cdef int c = a**b
175
    return cfunc_taking_int(a**b) + c
176

177
def pow_int_int_non_negative(int a, unsigned int b):
178
    """
179
    A couple of combinations of non-negative values for the
180
    exponent, which lets us fall back to int as a return type
181
    >>> pow_int_int_non_negative(5, 3)
182
    unsigned int
183
    long
184
    """
185
    c1 = a**b
186
    c2 = a**5
187
    print(cython.typeof(c1))
188
    print(cython.typeof(c2))
189

190

191
ctypedef double f64
192

193
def pythagoras_with_typedef(double a, double b):
194
    # see https://github.com/cython/cython/issues/5203
195
    """
196
    >>> rc = pythagoras_with_typedef(2.0, 2.0)
197
    >>> pyresult = 1.0 / (2 * 2.0 ** 2) ** 0.5
198
    >>> pyresult - 0.001 < rc < pyresult + 0.001  or  (rc, pyresult)
199
    True
200
    """
201
    cdef f64 result = a * a + b * b
202
    result = 1.0 / result ** 0.5
203
    return result
204

205

206
@cython.cpow(False)
207
def power_coercion_in_nogil_1(double a, double b):
208
    """
209
    >>> power_coercion_in_nogil_1(2., 2.)
210
    4.0
211
    >>> power_coercion_in_nogil_1(-1., 0.5)
212
    Traceback (most recent call last):
213
    ...
214
    TypeError: Cannot convert 'complex' with non-zero imaginary component to 'double' (this most likely comes from the '**' operator; use 'cython.cpow(True)' to return 'nan' instead of a complex number).
215
    """
216
    cdef double c
217
    with nogil:
218
        c = a**b
219
    return c
220

221

222
cdef double nogil_fun(double x) nogil:
223
    return x
224

225
def power_coercion_in_nogil_2(double a, double b):
226
    """
227
    >>> power_coercion_in_nogil_2(2., 2.)
228
    4.0
229
    >>> power_coercion_in_nogil_2(-1., 0.5)
230
    Traceback (most recent call last):
231
    ...
232
    TypeError: Cannot convert 'complex' with non-zero imaginary component to 'double' (this most likely comes from the '**' operator; use 'cython.cpow(True)' to return 'nan' instead of a complex number).
233
    """
234
    c = a**b
235
    with nogil:
236
        d = nogil_fun(c)
237
    return d
238

239

240
def power_coercion_in_nogil_3(double a, double b, double c):
241
    """
242
    >>> power_coercion_in_nogil_3(2., 2., 1.0)
243
    0.25
244
    >>> power_coercion_in_nogil_3(-1., 0.5, 1.0)
245
    Traceback (most recent call last):
246
    ...
247
    TypeError: Cannot convert 'complex' with non-zero imaginary component to 'double' (this most likely comes from the '**' operator; use 'cython.cpow(True)' to return 'nan' instead of a complex number).
248
    """
249
    with nogil:
250
        c /= a**b
251
    return c
252

253

254
_WARNINGS = """
255
58:21: Treating '**' as if 'cython.cpow(True)' since it is directly assigned to a a non-complex C numeric type. This is likely to be fragile and we recommend setting 'cython.cpow' explicitly.
256
59:32: Treating '**' as if 'cython.cpow(True)' since it is directly assigned to a a non-complex C numeric type. This is likely to be fragile and we recommend setting 'cython.cpow' explicitly.
257
174:18: Treating '**' as if 'cython.cpow(True)' since it is directly assigned to a an integer C numeric type. This is likely to be fragile and we recommend setting 'cython.cpow' explicitly.
258
175:29: Treating '**' as if 'cython.cpow(True)' since it is directly assigned to a an integer C numeric type. This is likely to be fragile and we recommend setting 'cython.cpow' explicitly.
259
"""
260

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.