1
/* -*- c -*- */
2

3
/*
4
 * This file is for the definitions of the non-c99 functions used in ufuncs.
5
 * All the complex ufuncs are defined here along with a smattering of real and
6
 * object functions.
7
 */
8

9
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
10
#include "npy_pycompat.h"
11
#include "npy_import.h"
12

13

14
/*
15
 *****************************************************************************
16
 **                        PYTHON OBJECT FUNCTIONS                          **
17
 *****************************************************************************
18
 */
19

20
static PyObject *
21 1
Py_square(PyObject *o)
22
{
23 1
    return PyNumber_Multiply(o, o);
24
}
25

26
static PyObject *
27 1
Py_get_one(PyObject *NPY_UNUSED(o))
28
{
29 1
    return PyLong_FromLong(1);
30
}
31

32
static PyObject *
33 1
Py_reciprocal(PyObject *o)
34
{
35 1
    PyObject *one = PyLong_FromLong(1);
36
    PyObject *result;
37

38 1
    if (!one) {
39
        return NULL;
40
    }
41 1
    result = PyNumber_TrueDivide(one, o);
42 1
    Py_DECREF(one);
43
    return result;
44
}
45

46
/*
47
 * Define numpy version of PyNumber_Power as binary function.
48
 */
49
static PyObject *
50 1
npy_ObjectPower(PyObject *x, PyObject *y)
51
{
52 1
    return PyNumber_Power(x, y, Py_None);
53
}
54

55
/**begin repeat
56
 * #Kind = Max, Min#
57
 * #OP = Py_GE, Py_LE#
58
 */
59
static PyObject *
60 1
npy_Object@Kind@(PyObject *i1, PyObject *i2)
61
{
62
    PyObject *result;
63
    int cmp;
64

65 1
    cmp = PyObject_RichCompareBool(i1, i2, @OP@);
66 1
    if (cmp < 0) {
67
        return NULL;
68
    }
69 1
    if (cmp == 1) {
70
        result = i1;
71
    }
72
    else {
73 1
        result = i2;
74
    }
75 1
    Py_INCREF(result);
76 1
    return result;
77
}
78
/**end repeat**/
79

80
/* Emulates Python's 'a or b' behavior */
81
static PyObject *
82 1
npy_ObjectLogicalOr(PyObject *i1, PyObject *i2)
83
{
84 1
    if (i1 == NULL) {
85 0
        Py_XINCREF(i2);
86
        return i2;
87
    }
88 1
    else if (i2 == NULL) {
89 0
        Py_INCREF(i1);
90 0
        return i1;
91
    }
92
    else {
93 1
        int retcode = PyObject_IsTrue(i1);
94 1
        if (retcode == -1) {
95
            return NULL;
96
        }
97 1
        else if (retcode) {
98 1
            Py_INCREF(i1);
99 1
            return i1;
100
        }
101
        else {
102 1
            Py_INCREF(i2);
103 1
            return i2;
104
        }
105
    }
106
}
107

108
/* Emulates Python's 'a and b' behavior */
109
static PyObject *
110 1
npy_ObjectLogicalAnd(PyObject *i1, PyObject *i2)
111
{
112 1
    if (i1 == NULL) {
113
        return NULL;
114
    }
115 1
    else if (i2 == NULL) {
116
        return NULL;
117
    }
118
    else {
119 1
        int retcode = PyObject_IsTrue(i1);
120 1
        if (retcode == -1) {
121
            return NULL;
122
        }
123 1
        else if (!retcode) {
124 1
            Py_INCREF(i1);
125 1
            return i1;
126
        }
127
        else {
128 1
            Py_INCREF(i2);
129 1
            return i2;
130
        }
131
    }
132
}
133

134

135
/* Emulates Python's 'not b' behavior */
136
static PyObject *
137 1
npy_ObjectLogicalNot(PyObject *i1)
138
{
139 1
    if (i1 == NULL) {
140
        return NULL;
141
    }
142
    else {
143 1
        int retcode = PyObject_Not(i1);
144 1
        if (retcode == -1) {
145
            return NULL;
146
        }
147 1
        else if (retcode) {
148 1
            Py_INCREF(Py_True);
149 1
            return Py_True;
150
        }
151
        else {
152 1
            Py_INCREF(Py_False);
153 1
            return Py_False;
154
        }
155
    }
156
}
157

158
static PyObject *
159 1
npy_ObjectFloor(PyObject *obj) {
160
    static PyObject *math_floor_func = NULL;
161

162 1
    npy_cache_import("math", "floor", &math_floor_func);
163 1
    if (math_floor_func == NULL) {
164
        return NULL;
165
    }
166 1
    return PyObject_CallFunction(math_floor_func, "O", obj);
167
}
168

169
static PyObject *
170 1
npy_ObjectCeil(PyObject *obj) {
171
    static PyObject *math_ceil_func = NULL;
172

173 1
    npy_cache_import("math", "ceil", &math_ceil_func);
174 1
    if (math_ceil_func == NULL) {
175
        return NULL;
176
    }
177 1
    return PyObject_CallFunction(math_ceil_func, "O", obj);
178
}
179

180
static PyObject *
181 1
npy_ObjectTrunc(PyObject *obj) {
182
    static PyObject *math_trunc_func = NULL;
183

184 1
    npy_cache_import("math", "trunc", &math_trunc_func);
185 1
    if (math_trunc_func == NULL) {
186
        return NULL;
187
    }
188 1
    return PyObject_CallFunction(math_trunc_func, "O", obj);
189
}
190

191
static PyObject *
192 1
npy_ObjectGCD(PyObject *i1, PyObject *i2)
193
{
194 1
    PyObject *gcd = NULL;
195

196
    /* use math.gcd if valid on the provided types */
197
    {
198
        static PyObject *math_gcd_func = NULL;
199

200 1
        npy_cache_import("math", "gcd", &math_gcd_func);
201 1
        if (math_gcd_func == NULL) {
202
            return NULL;
203
        }
204 1
        gcd = PyObject_CallFunction(math_gcd_func, "OO", i1, i2);
205 1
        if (gcd != NULL) {
206
            return gcd;
207
        }
208
        /* silence errors, and fall back on pure-python gcd */
209 1
        PyErr_Clear();
210
    }
211

212
    /* otherwise, use our internal one, written in python */
213
    {
214
        static PyObject *internal_gcd_func = NULL;
215

216 1
        npy_cache_import("numpy.core._internal", "_gcd", &internal_gcd_func);
217 1
        if (internal_gcd_func == NULL) {
218
            return NULL;
219
        }
220 1
        gcd = PyObject_CallFunction(internal_gcd_func, "OO", i1, i2);
221 1
        if (gcd == NULL) {
222
            return NULL;
223
        }
224
        /* _gcd has some unusual behaviour regarding sign */
225 1
        Py_SETREF(gcd, PyNumber_Absolute(gcd));
226
        return gcd;
227
    }
228
}
229

230
static PyObject *
231 1
npy_ObjectLCM(PyObject *i1, PyObject *i2)
232
{
233
    /* lcm(a, b) = abs(a // gcd(a, b) * b) */
234

235 1
    PyObject *gcd = npy_ObjectGCD(i1, i2);
236
    PyObject *tmp;
237 1
    if(gcd == NULL) {
238
        return NULL;
239
    }
240
    /* Floor divide preserves integer types - we know the division will have
241
     * no remainder
242
     */
243 1
    tmp = PyNumber_FloorDivide(i1, gcd);
244 1
    Py_DECREF(gcd);
245 1
    if(tmp == NULL) {
246
        return NULL;
247
    }
248

249 1
    Py_SETREF(tmp, PyNumber_Multiply(tmp, i2));
250 1
    if(tmp == NULL) {
251
        return NULL;
252
    }
253

254
    /* even though we fix gcd to be positive, we need to do it again here */
255 1
    Py_SETREF(tmp,  PyNumber_Absolute(tmp));
256
    return tmp;
257
}
258

259

260
static PyObject *
261 1
npy_ObjectClip(PyObject *arr, PyObject *min, PyObject *max) {
262 1
    PyObject *o = npy_ObjectMax(arr, min);
263 1
    if (o == NULL) {
264
        return NULL;
265
    }
266 1
    Py_SETREF(o, npy_ObjectMin(o, max));
267
    return o;
268
}
269

270
/*
271
 *****************************************************************************
272
 **                           COMPLEX FUNCTIONS                             **
273
 *****************************************************************************
274
 */
275

276

277
/*
278
 * Don't pass structures between functions (only pointers) because how
279
 * structures are passed is compiler dependent and could cause segfaults if
280
 * umath_ufunc_object.inc is compiled with a different compiler than an
281
 * extension that makes use of the UFUNC API
282
 */
283

284
/**begin repeat
285
 *
286
 * #ctype = npy_cfloat, npy_cdouble, npy_clongdouble#
287
 * #ftype = npy_float, npy_double, npy_longdouble#
288
 * #c = f, ,l#
289
 */
290

291
static void
292 1
nc_neg@c@(@ctype@ *a, @ctype@ *r)
293
{
294 1
    r->real = -a->real;
295 1
    r->imag = -a->imag;
296 1
    return;
297
}
298

299
static void
300 1
nc_pos@c@(@ctype@ *a, @ctype@ *r)
301
{
302 1
    r->real = +a->real;
303 1
    r->imag = +a->imag;
304 1
    return;
305
}
306

307
static void
308 1
nc_sqrt@c@(@ctype@ *x, @ctype@ *r)
309
{
310 1
    *r = npy_csqrt@c@(*x);
311 1
    return;
312
}
313

314
static void
315 1
nc_rint@c@(@ctype@ *x, @ctype@ *r)
316
{
317 1
    r->real = npy_rint@c@(x->real);
318 1
    r->imag = npy_rint@c@(x->imag);
319 1
}
320

321
static void
322 1
nc_log@c@(@ctype@ *x, @ctype@ *r)
323
{
324 1
    *r = npy_clog@c@(*x);
325 1
    return;
326
}
327

328
static void
329 1
nc_log1p@c@(@ctype@ *x, @ctype@ *r)
330
{
331 1
    @ftype@ l = npy_hypot@c@(x->real + 1,x->imag);
332 1
    r->imag = npy_atan2@c@(x->imag, x->real + 1);
333 1
    r->real = npy_log@c@(l);
334 1
    return;
335
}
336

337
static void
338 1
nc_exp@c@(@ctype@ *x, @ctype@ *r)
339
{
340 1
    *r = npy_cexp@c@(*x);
341 1
    return;
342
}
343

344
static void
345 1
nc_exp2@c@(@ctype@ *x, @ctype@ *r)
346
{
347
    @ctype@ a;
348 1
    a.real = x->real*NPY_LOGE2@c@;
349 1
    a.imag = x->imag*NPY_LOGE2@c@;
350 1
    nc_exp@c@(&a, r);
351 1
    return;
352
}
353

354
static void
355 1
nc_expm1@c@(@ctype@ *x, @ctype@ *r)
356
{
357 1
    @ftype@ a = npy_sin@c@(x->imag / 2);
358 1
    r->real = npy_expm1@c@(x->real) * npy_cos@c@(x->imag) - 2 * a * a;
359 1
    r->imag = npy_exp@c@(x->real) * npy_sin@c@(x->imag);
360 1
    return;
361
}
362

363
static void
364 1
nc_pow@c@(@ctype@ *a, @ctype@ *b, @ctype@ *r)
365
{
366 1
   *r = npy_cpow@c@(*a, *b);
367 1
    return;
368
}
369

370
static void
371 1
nc_acos@c@(@ctype@ *x, @ctype@ *r)
372
{
373 1
    *r = npy_cacos@c@(*x);
374 1
    return;
375
}
376

377
static void
378 1
nc_acosh@c@(@ctype@ *x, @ctype@ *r)
379
{
380 1
    *r = npy_cacosh@c@(*x);
381 1
    return;
382
}
383

384
static void
385 1
nc_asin@c@(@ctype@ *x, @ctype@ *r)
386
{
387 1
    *r = npy_casin@c@(*x);
388 1
    return;
389
}
390

391

392
static void
393 1
nc_asinh@c@(@ctype@ *x, @ctype@ *r)
394
{
395 1
    *r = npy_casinh@c@(*x);
396 1
    return;
397
}
398

399
static void
400 1
nc_atan@c@(@ctype@ *x, @ctype@ *r)
401
{
402 1
    *r = npy_catan@c@(*x);
403 1
    return;
404
}
405

406
static void
407 1
nc_atanh@c@(@ctype@ *x, @ctype@ *r)
408
{
409 1
    *r = npy_catanh@c@(*x);
410 1
    return;
411
}
412

413
static void
414 1
nc_cos@c@(@ctype@ *x, @ctype@ *r)
415
{
416 1
    *r = npy_ccos@c@(*x);
417 1
    return;
418
}
419

420
static void
421 1
nc_cosh@c@(@ctype@ *x, @ctype@ *r)
422
{
423 1
    *r = npy_ccosh@c@(*x);
424 1
    return;
425
}
426

427
static void
428 1
nc_log10@c@(@ctype@ *x, @ctype@ *r)
429
{
430 1
    nc_log@c@(x, r);
431 1
    r->real *= NPY_LOG10E@c@;
432 1
    r->imag *= NPY_LOG10E@c@;
433 1
    return;
434
}
435

436
static void
437 1
nc_log2@c@(@ctype@ *x, @ctype@ *r)
438
{
439 1
    nc_log@c@(x, r);
440 1
    r->real *= NPY_LOG2E@c@;
441 1
    r->imag *= NPY_LOG2E@c@;
442 1
    return;
443
}
444

445
static void
446 1
nc_sin@c@(@ctype@ *x, @ctype@ *r)
447
{
448 1
    *r = npy_csin@c@(*x);
449 1
    return;
450
}
451

452
static void
453 1
nc_sinh@c@(@ctype@ *x, @ctype@ *r)
454
{
455 1
    *r = npy_csinh@c@(*x);
456 1
    return;
457
}
458

459
static void
460 1
nc_tan@c@(@ctype@ *x, @ctype@ *r)
461
{
462 1
   *r = npy_ctan@c@(*x);
463 1
   return;
464
}
465

466
static void
467 1
nc_tanh@c@(@ctype@ *x, @ctype@ *r)
468
{
469 1
    *r = npy_ctanh@c@(*x);
470 1
    return;
471
}
472

473
/**end repeat**/

Read our documentation on viewing source code .

Loading