CoolFace
Apppublic

Aluode/PerceptionLabPortable

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
numbers.py1396 linesDownload Raw Back to cpython
1import math
2import numbers
3
4import numpy as np
5import operator
6
7from llvmlite import ir
8from llvmlite.ir import Constant
9
10from numba.core.imputils import (lower_builtin, lower_getattr,
11                                    lower_getattr_generic, lower_cast,
12                                    lower_constant, impl_ret_borrowed,
13                                    impl_ret_untracked)
14from numba.core import typing, types, utils, errors, cgutils, optional
15from numba.core.extending import intrinsic, overload_method
16from numba.cpython.unsafe.numbers import viewer
17
18def _int_arith_flags(rettype):
19    """
20    Return the modifier flags for integer arithmetic.
21    """
22    if rettype.signed:
23        # Ignore the effects of signed overflow.  This is important for
24        # optimization of some indexing operations.  For example
25        # array[i+1] could see `i+1` trigger a signed overflow and
26        # give a negative number.  With Python's indexing, a negative
27        # index is treated differently: its resolution has a runtime cost.
28        # Telling LLVM to ignore signed overflows allows it to optimize
29        # away the check for a negative `i+1` if it knows `i` is positive.
30        return ['nsw']
31    else:
32        return []
33
34
35def int_add_impl(context, builder, sig, args):
36    [va, vb] = args
37    [ta, tb] = sig.args
38    a = context.cast(builder, va, ta, sig.return_type)
39    b = context.cast(builder, vb, tb, sig.return_type)
40    res = builder.add(a, b, flags=_int_arith_flags(sig.return_type))
41    return impl_ret_untracked(context, builder, sig.return_type, res)
42
43
44def int_sub_impl(context, builder, sig, args):
45    [va, vb] = args
46    [ta, tb] = sig.args
47    a = context.cast(builder, va, ta, sig.return_type)
48    b = context.cast(builder, vb, tb, sig.return_type)
49    res = builder.sub(a, b, flags=_int_arith_flags(sig.return_type))
50    return impl_ret_untracked(context, builder, sig.return_type, res)
51
52
53def int_mul_impl(context, builder, sig, args):
54    [va, vb] = args
55    [ta, tb] = sig.args
56    a = context.cast(builder, va, ta, sig.return_type)
57    b = context.cast(builder, vb, tb, sig.return_type)
58    res = builder.mul(a, b, flags=_int_arith_flags(sig.return_type))
59    return impl_ret_untracked(context, builder, sig.return_type, res)
60
61
62def int_divmod_signed(context, builder, ty, x, y):
63    """
64    Reference Objects/intobject.c
65    xdivy = x / y;
66    xmody = (long)(x - (unsigned long)xdivy * y);
67    /* If the signs of x and y differ, and the remainder is non-0,
68     * C89 doesn't define whether xdivy is now the floor or the
69     * ceiling of the infinitely precise quotient.  We want the floor,
70     * and we have it iff the remainder's sign matches y's.
71     */
72    if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) {
73        xmody += y;
74        --xdivy;
75        assert(xmody && ((y ^ xmody) >= 0));
76    }
77    *p_xdivy = xdivy;
78    *p_xmody = xmody;
79    """
80    assert x.type == y.type
81
82    ZERO = y.type(0)
83    ONE = y.type(1)
84
85    # NOTE: On x86 at least, dividing the lowest representable integer
86    # (e.g. 0x80000000 for int32) by -1 causes a SIFGPE (division overflow),
87    # causing the process to crash.
88    # We return 0, 0 instead (more or less like Numpy).
89
90    resdiv = cgutils.alloca_once_value(builder, ZERO)
91    resmod = cgutils.alloca_once_value(builder, ZERO)
92
93    is_overflow = builder.and_(
94        builder.icmp_signed('==', x, x.type(ty.minval)),
95        builder.icmp_signed('==', y, y.type(-1)))
96
97    with builder.if_then(builder.not_(is_overflow), likely=True):
98        # Note LLVM will optimize this to a single divmod instruction,
99        # if available on the target CPU (e.g. x86).
100        xdivy = builder.sdiv(x, y)
101        xmody = builder.srem(x, y)
102
103        y_xor_xmody_ltz = builder.icmp_signed('<', builder.xor(y, xmody), ZERO)
104        xmody_istrue = builder.icmp_signed('!=', xmody, ZERO)
105        cond = builder.and_(xmody_istrue, y_xor_xmody_ltz)
106
107        with builder.if_else(cond) as (if_different_signs, if_same_signs):
108            with if_same_signs:
109                builder.store(xdivy, resdiv)
110                builder.store(xmody, resmod)
111
112            with if_different_signs:
113                builder.store(builder.sub(xdivy, ONE), resdiv)
114                builder.store(builder.add(xmody, y), resmod)
115
116    return builder.load(resdiv), builder.load(resmod)
117
118
119def int_divmod(context, builder, ty, x, y):
120    """
121    Integer divmod(x, y).  The caller must ensure that y != 0.
122    """
123    if ty.signed:
124        return int_divmod_signed(context, builder, ty, x, y)
125    else:
126        return builder.udiv(x, y), builder.urem(x, y)
127
128
129def _int_divmod_impl(context, builder, sig, args, zerodiv_message):
130    va, vb = args
131    ta, tb = sig.args
132
133    ty = sig.return_type
134    if isinstance(ty, types.UniTuple):
135        ty = ty.dtype
136    a = context.cast(builder, va, ta, ty)
137    b = context.cast(builder, vb, tb, ty)
138    quot = cgutils.alloca_once(builder, a.type, name="quot")
139    rem = cgutils.alloca_once(builder, a.type, name="rem")
140
141    with builder.if_else(cgutils.is_scalar_zero(builder, b), likely=False
142                         ) as (if_zero, if_non_zero):
143        with if_zero:
144            if not context.error_model.fp_zero_division(
145                builder, (zerodiv_message,)):
146                # No exception raised => return 0
147                # XXX We should also set the FPU exception status, but
148                # there's no easy way to do that from LLVM.
149                builder.store(b, quot)
150                builder.store(b, rem)
151        with if_non_zero:
152            q, r = int_divmod(context, builder, ty, a, b)
153            builder.store(q, quot)
154            builder.store(r, rem)
155
156    return quot, rem
157
158
159@lower_builtin(divmod, types.Integer, types.Integer)
160def int_divmod_impl(context, builder, sig, args):
161    quot, rem = _int_divmod_impl(context, builder, sig, args,
162                                 "integer divmod by zero")
163
164    return cgutils.pack_array(builder,
165                              (builder.load(quot), builder.load(rem)))
166
167
168@lower_builtin(operator.floordiv, types.Integer, types.Integer)
169@lower_builtin(operator.ifloordiv, types.Integer, types.Integer)
170def int_floordiv_impl(context, builder, sig, args):
171    quot, rem = _int_divmod_impl(context, builder, sig, args,
172                                 "integer division by zero")
173    return builder.load(quot)
174
175
176@lower_builtin(operator.truediv, types.Integer, types.Integer)
177@lower_builtin(operator.itruediv, types.Integer, types.Integer)
178def int_truediv_impl(context, builder, sig, args):
179    [va, vb] = args
180    [ta, tb] = sig.args
181    a = context.cast(builder, va, ta, sig.return_type)
182    b = context.cast(builder, vb, tb, sig.return_type)
183    with cgutils.if_zero(builder, b):
184        context.error_model.fp_zero_division(builder, ("division by zero",))
185    res = builder.fdiv(a, b)
186    return impl_ret_untracked(context, builder, sig.return_type, res)
187
188
189@lower_builtin(operator.mod, types.Integer, types.Integer)
190@lower_builtin(operator.imod, types.Integer, types.Integer)
191def int_rem_impl(context, builder, sig, args):
192    quot, rem = _int_divmod_impl(context, builder, sig, args,
193                                 "integer modulo by zero")
194    return builder.load(rem)
195
196
197def _get_power_zerodiv_return(context, return_type):
198    if (isinstance(return_type, types.Integer)
199        and not context.error_model.raise_on_fp_zero_division):
200        # If not raising, return 0x8000... when computing 0 ** <negative number>
201        return -1 << (return_type.bitwidth - 1)
202    else:
203        return False
204
205
206def int_power_impl(context, builder, sig, args):
207    """
208    a ^ b, where a is an integer or real, and b an integer
209    """
210    is_integer = isinstance(sig.args[0], types.Integer)
211    tp = sig.return_type
212    zerodiv_return = _get_power_zerodiv_return(context, tp)
213
214    def int_power(a, b):
215        # Ensure computations are done with a large enough width
216        r = tp(1)
217        a = tp(a)
218        if b < 0:
219            invert = True
220            exp = -b
221            if exp < 0:
222                raise OverflowError
223            if is_integer:
224                if a == 0:
225                    if zerodiv_return:
226                        return zerodiv_return
227                    else:
228                        raise ZeroDivisionError("0 cannot be raised to a negative power")
229                if a != 1 and a != -1:
230                    return 0
231        else:
232            invert = False
233            exp = b
234        if exp > 0x10000:
235            # Optimization cutoff: fallback on the generic algorithm
236            return math.pow(a, float(b))
237        while exp != 0:
238            if exp & 1:
239                r *= a
240            exp >>= 1
241            a *= a
242
243        return 1.0 / r if invert else r
244
245    res = context.compile_internal(builder, int_power, sig, args)
246    return impl_ret_untracked(context, builder, sig.return_type, res)
247
248
249@lower_builtin(operator.pow, types.Integer, types.IntegerLiteral)
250@lower_builtin(operator.ipow, types.Integer, types.IntegerLiteral)
251@lower_builtin(operator.pow, types.Float, types.IntegerLiteral)
252@lower_builtin(operator.ipow, types.Float, types.IntegerLiteral)
253def static_power_impl(context, builder, sig, args):
254    """
255    a ^ b, where a is an integer or real, and b a constant integer
256    """
257    exp = sig.args[1].value
258    if not isinstance(exp, numbers.Integral):
259        raise NotImplementedError
260    if abs(exp) > 0x10000:
261        # Optimization cutoff: fallback on the generic algorithm above
262        raise NotImplementedError
263    invert = exp < 0
264    exp = abs(exp)
265
266    tp = sig.return_type
267    is_integer = isinstance(tp, types.Integer)
268    zerodiv_return = _get_power_zerodiv_return(context, tp)
269
270    val = context.cast(builder, args[0], sig.args[0], tp)
271    lty = val.type
272
273    def mul(a, b):
274        if is_integer:
275            return builder.mul(a, b)
276        else:
277            return builder.fmul(a, b)
278
279    # Unroll the exponentiation loop
280    res = lty(1)
281    a = val
282    while exp != 0:
283        if exp & 1:
284            res = mul(res, val)
285        exp >>= 1
286        val = mul(val, val)
287
288    if invert:
289        # If the exponent was negative, fix the result by inverting it
290        if is_integer:
291            # Integer inversion
292            def invert_impl(a):
293                if a == 0:
294                    if zerodiv_return:
295                        return zerodiv_return
296                    else:
297                        raise ZeroDivisionError("0 cannot be raised to a negative power")
298                if a != 1 and a != -1:
299                    return 0
300                else:
301                    return a
302
303        else:
304            # Real inversion
305            def invert_impl(a):
306                return 1.0 / a
307
308        res = context.compile_internal(builder, invert_impl,
309                                       typing.signature(tp, tp), (res,))
310
311    return res
312
313
314def int_slt_impl(context, builder, sig, args):
315    res = builder.icmp_signed('<', *args)
316    return impl_ret_untracked(context, builder, sig.return_type, res)
317
318
319def int_sle_impl(context, builder, sig, args):
320    res = builder.icmp_signed('<=', *args)
321    return impl_ret_untracked(context, builder, sig.return_type, res)
322
323
324def int_sgt_impl(context, builder, sig, args):
325    res = builder.icmp_signed('>', *args)
326    return impl_ret_untracked(context, builder, sig.return_type, res)
327
328
329def int_sge_impl(context, builder, sig, args):
330    res = builder.icmp_signed('>=', *args)
331    return impl_ret_untracked(context, builder, sig.return_type, res)
332
333
334def int_ult_impl(context, builder, sig, args):
335    res = builder.icmp_unsigned('<', *args)
336    return impl_ret_untracked(context, builder, sig.return_type, res)
337
338
339def int_ule_impl(context, builder, sig, args):
340    res = builder.icmp_unsigned('<=', *args)
341    return impl_ret_untracked(context, builder, sig.return_type, res)
342
343
344def int_ugt_impl(context, builder, sig, args):
345    res = builder.icmp_unsigned('>', *args)
346    return impl_ret_untracked(context, builder, sig.return_type, res)
347
348
349def int_uge_impl(context, builder, sig, args):
350    res = builder.icmp_unsigned('>=', *args)
351    return impl_ret_untracked(context, builder, sig.return_type, res)
352
353
354def int_eq_impl(context, builder, sig, args):
355    res = builder.icmp_unsigned('==', *args)
356    return impl_ret_untracked(context, builder, sig.return_type, res)
357
358
359def int_ne_impl(context, builder, sig, args):
360    res = builder.icmp_unsigned('!=', *args)
361    return impl_ret_untracked(context, builder, sig.return_type, res)
362
363
364def int_signed_unsigned_cmp(op):
365    def impl(context, builder, sig, args):
366        (left, right) = args
367        # This code is translated from the NumPy source.
368        # What we're going to do is divide the range of a signed value at zero.
369        # If the signed value is less than zero, then we can treat zero as the
370        # unsigned value since the unsigned value is necessarily zero or larger
371        # and any signed comparison between a negative value and zero/infinity
372        # will yield the same result. If the signed value is greater than or
373        # equal to zero, then we can safely cast it to an unsigned value and do
374        # the expected unsigned-unsigned comparison operation.
375        # Original: https://github.com/numpy/numpy/pull/23713
376        cmp_zero = builder.icmp_signed('<', left, Constant(left.type, 0))
377        lt_zero = builder.icmp_signed(op, left, Constant(left.type, 0))
378        ge_zero = builder.icmp_unsigned(op, left, right)
379        res = builder.select(cmp_zero, lt_zero, ge_zero)
380        return impl_ret_untracked(context, builder, sig.return_type, res)
381    return impl
382
383
384def int_unsigned_signed_cmp(op):
385    def impl(context, builder, sig, args):
386        (left, right) = args
387        # See the function `int_signed_unsigned_cmp` for implementation notes.
388        cmp_zero = builder.icmp_signed('<', right, Constant(right.type, 0))
389        lt_zero = builder.icmp_signed(op, Constant(right.type, 0), right)
390        ge_zero = builder.icmp_unsigned(op, left, right)
391        res = builder.select(cmp_zero, lt_zero, ge_zero)
392        return impl_ret_untracked(context, builder, sig.return_type, res)
393    return impl
394
395
396def int_abs_impl(context, builder, sig, args):
397    [x] = args
398    ZERO = Constant(x.type, None)
399    ltz = builder.icmp_signed('<', x, ZERO)
400    negated = builder.neg(x)
401    res = builder.select(ltz, negated, x)
402    return impl_ret_untracked(context, builder, sig.return_type, res)
403
404
405def uint_abs_impl(context, builder, sig, args):
406    [x] = args
407    return impl_ret_untracked(context, builder, sig.return_type, x)
408
409
410def int_shl_impl(context, builder, sig, args):
411    [valty, amtty] = sig.args
412    [val, amt] = args
413    val = context.cast(builder, val, valty, sig.return_type)
414    amt = context.cast(builder, amt, amtty, sig.return_type)
415    res = builder.shl(val, amt)
416    return impl_ret_untracked(context, builder, sig.return_type, res)
417
418
419def int_shr_impl(context, builder, sig, args):
420    [valty, amtty] = sig.args
421    [val, amt] = args
422    val = context.cast(builder, val, valty, sig.return_type)
423    amt = context.cast(builder, amt, amtty, sig.return_type)
424    if sig.return_type.signed:
425        res = builder.ashr(val, amt)
426    else:
427        res = builder.lshr(val, amt)
428    return impl_ret_untracked(context, builder, sig.return_type, res)
429
430
431def int_and_impl(context, builder, sig, args):
432    [at, bt] = sig.args
433    [av, bv] = args
434    cav = context.cast(builder, av, at, sig.return_type)
435    cbc = context.cast(builder, bv, bt, sig.return_type)
436    res = builder.and_(cav, cbc)
437    return impl_ret_untracked(context, builder, sig.return_type, res)
438
439
440def int_or_impl(context, builder, sig, args):
441    [at, bt] = sig.args
442    [av, bv] = args
443    cav = context.cast(builder, av, at, sig.return_type)
444    cbc = context.cast(builder, bv, bt, sig.return_type)
445    res = builder.or_(cav, cbc)
446    return impl_ret_untracked(context, builder, sig.return_type, res)
447
448
449def int_xor_impl(context, builder, sig, args):
450    [at, bt] = sig.args
451    [av, bv] = args
452    cav = context.cast(builder, av, at, sig.return_type)
453    cbc = context.cast(builder, bv, bt, sig.return_type)
454    res = builder.xor(cav, cbc)
455    return impl_ret_untracked(context, builder, sig.return_type, res)
456
457
458def int_negate_impl(context, builder, sig, args):
459    [typ] = sig.args
460    [val] = args
461    # Negate before upcasting, for unsigned numbers
462    res = builder.neg(val)
463    res = context.cast(builder, res, typ, sig.return_type)
464    return impl_ret_untracked(context, builder, sig.return_type, res)
465
466
467def int_positive_impl(context, builder, sig, args):
468    [typ] = sig.args
469    [val] = args
470    res = context.cast(builder, val, typ, sig.return_type)
471    return impl_ret_untracked(context, builder, sig.return_type, res)
472
473
474def int_invert_impl(context, builder, sig, args):
475    [typ] = sig.args
476    [val] = args
477    # Invert before upcasting, for unsigned numbers
478    res = builder.xor(val, Constant(val.type, int('1' * val.type.width, 2)))
479    res = context.cast(builder, res, typ, sig.return_type)
480    return impl_ret_untracked(context, builder, sig.return_type, res)
481
482
483def int_sign_impl(context, builder, sig, args):
484    """
485    np.sign(int)
486    """
487    [x] = args
488    POS = Constant(x.type, 1)
489    NEG = Constant(x.type, -1)
490    ZERO = Constant(x.type, 0)
491
492    cmp_zero = builder.icmp_unsigned('==', x, ZERO)
493    cmp_pos = builder.icmp_signed('>', x, ZERO)
494
495    presult = cgutils.alloca_once(builder, x.type)
496
497    bb_zero = builder.append_basic_block(".zero")
498    bb_postest = builder.append_basic_block(".postest")
499    bb_pos = builder.append_basic_block(".pos")
500    bb_neg = builder.append_basic_block(".neg")
501    bb_exit = builder.append_basic_block(".exit")
502
503    builder.cbranch(cmp_zero, bb_zero, bb_postest)
504
505    with builder.goto_block(bb_zero):
506        builder.store(ZERO, presult)
507        builder.branch(bb_exit)
508
509    with builder.goto_block(bb_postest):
510        builder.cbranch(cmp_pos, bb_pos, bb_neg)
511
512    with builder.goto_block(bb_pos):
513        builder.store(POS, presult)
514        builder.branch(bb_exit)
515
516    with builder.goto_block(bb_neg):
517        builder.store(NEG, presult)
518        builder.branch(bb_exit)
519
520    builder.position_at_end(bb_exit)
521    res = builder.load(presult)
522    return impl_ret_untracked(context, builder, sig.return_type, res)
523
524
525def bool_negate_impl(context, builder, sig, args):
526    [typ] = sig.args
527    [val] = args
528    res = context.cast(builder, val, typ, sig.return_type)
529    res = builder.neg(res)
530    return impl_ret_untracked(context, builder, sig.return_type, res)
531
532
533def bool_unary_positive_impl(context, builder, sig, args):
534    [typ] = sig.args
535    [val] = args
536    res = context.cast(builder, val, typ, sig.return_type)
537    return impl_ret_untracked(context, builder, sig.return_type, res)
538
539
540lower_builtin(operator.eq, types.boolean, types.boolean)(int_eq_impl)
541lower_builtin(operator.ne, types.boolean, types.boolean)(int_ne_impl)
542lower_builtin(operator.lt, types.boolean, types.boolean)(int_ult_impl)
543lower_builtin(operator.le, types.boolean, types.boolean)(int_ule_impl)
544lower_builtin(operator.gt, types.boolean, types.boolean)(int_ugt_impl)
545lower_builtin(operator.ge, types.boolean, types.boolean)(int_uge_impl)
546lower_builtin(operator.neg, types.boolean)(bool_negate_impl)
547lower_builtin(operator.pos, types.boolean)(bool_unary_positive_impl)
548
549
550def _implement_integer_operators():
551    ty = types.Integer
552
553    lower_builtin(operator.add, ty, ty)(int_add_impl)
554    lower_builtin(operator.iadd, ty, ty)(int_add_impl)
555    lower_builtin(operator.sub, ty, ty)(int_sub_impl)
556    lower_builtin(operator.isub, ty, ty)(int_sub_impl)
557    lower_builtin(operator.mul, ty, ty)(int_mul_impl)
558    lower_builtin(operator.imul, ty, ty)(int_mul_impl)
559    lower_builtin(operator.eq, ty, ty)(int_eq_impl)
560    lower_builtin(operator.ne, ty, ty)(int_ne_impl)
561
562    lower_builtin(operator.lshift, ty, ty)(int_shl_impl)
563    lower_builtin(operator.ilshift, ty, ty)(int_shl_impl)
564    lower_builtin(operator.rshift, ty, ty)(int_shr_impl)
565    lower_builtin(operator.irshift, ty, ty)(int_shr_impl)
566
567    lower_builtin(operator.neg, ty)(int_negate_impl)
568    lower_builtin(operator.pos, ty)(int_positive_impl)
569
570    lower_builtin(operator.pow, ty, ty)(int_power_impl)
571    lower_builtin(operator.ipow, ty, ty)(int_power_impl)
572    lower_builtin(pow, ty, ty)(int_power_impl)
573
574    for ty in types.unsigned_domain:
575        lower_builtin(operator.lt, ty, ty)(int_ult_impl)
576        lower_builtin(operator.le, ty, ty)(int_ule_impl)
577        lower_builtin(operator.gt, ty, ty)(int_ugt_impl)
578        lower_builtin(operator.ge, ty, ty)(int_uge_impl)
579        lower_builtin(operator.pow, types.Float, ty)(int_power_impl)
580        lower_builtin(operator.ipow, types.Float, ty)(int_power_impl)
581        lower_builtin(pow, types.Float, ty)(int_power_impl)
582        lower_builtin(abs, ty)(uint_abs_impl)
583
584    lower_builtin(operator.lt, types.IntegerLiteral, types.IntegerLiteral)(int_slt_impl)
585    lower_builtin(operator.gt, types.IntegerLiteral, types.IntegerLiteral)(int_slt_impl)
586    lower_builtin(operator.le, types.IntegerLiteral, types.IntegerLiteral)(int_slt_impl)
587    lower_builtin(operator.ge, types.IntegerLiteral, types.IntegerLiteral)(int_slt_impl)
588    for ty in types.signed_domain:
589        lower_builtin(operator.lt, ty, ty)(int_slt_impl)
590        lower_builtin(operator.le, ty, ty)(int_sle_impl)
591        lower_builtin(operator.gt, ty, ty)(int_sgt_impl)
592        lower_builtin(operator.ge, ty, ty)(int_sge_impl)
593        lower_builtin(operator.pow, types.Float, ty)(int_power_impl)
594        lower_builtin(operator.ipow, types.Float, ty)(int_power_impl)
595        lower_builtin(pow, types.Float, ty)(int_power_impl)
596        lower_builtin(abs, ty)(int_abs_impl)
597
598def _implement_bitwise_operators():
599    for ty in (types.Boolean, types.Integer):
600        lower_builtin(operator.and_, ty, ty)(int_and_impl)
601        lower_builtin(operator.iand, ty, ty)(int_and_impl)
602        lower_builtin(operator.or_, ty, ty)(int_or_impl)
603        lower_builtin(operator.ior, ty, ty)(int_or_impl)
604        lower_builtin(operator.xor, ty, ty)(int_xor_impl)
605        lower_builtin(operator.ixor, ty, ty)(int_xor_impl)
606
607        lower_builtin(operator.invert, ty)(int_invert_impl)
608
609_implement_integer_operators()
610
611_implement_bitwise_operators()
612
613
614def real_add_impl(context, builder, sig, args):
615    res = builder.fadd(*args)
616    return impl_ret_untracked(context, builder, sig.return_type, res)
617
618
619def real_sub_impl(context, builder, sig, args):
620    res = builder.fsub(*args)
621    return impl_ret_untracked(context, builder, sig.return_type, res)
622
623
624def real_mul_impl(context, builder, sig, args):
625    res = builder.fmul(*args)
626    return impl_ret_untracked(context, builder, sig.return_type, res)
627
628
629def real_div_impl(context, builder, sig, args):
630    with cgutils.if_zero(builder, args[1]):
631        context.error_model.fp_zero_division(builder, ("division by zero",))
632    res = builder.fdiv(*args)
633    return impl_ret_untracked(context, builder, sig.return_type, res)
634
635
636def real_divmod(context, builder, x, y):
637    assert x.type == y.type
638    floatty = x.type
639
640    module = builder.module
641    fname = context.mangler(".numba.python.rem", [x.type])
642    fnty = ir.FunctionType(floatty, (floatty, floatty, ir.PointerType(floatty)))
643    fn = cgutils.get_or_insert_function(module, fnty, fname)
644
645    if fn.is_declaration:
646        fn.linkage = 'linkonce_odr'
647        fnbuilder = ir.IRBuilder(fn.append_basic_block('entry'))
648        fx, fy, pmod = fn.args
649        div, mod = real_divmod_func_body(context, fnbuilder, fx, fy)
650        fnbuilder.store(mod, pmod)
651        fnbuilder.ret(div)
652
653    pmod = cgutils.alloca_once(builder, floatty)
654    quotient = builder.call(fn, (x, y, pmod))
655    return quotient, builder.load(pmod)
656
657
658def real_divmod_func_body(context, builder, vx, wx):
659    # Reference Objects/floatobject.c
660    #
661    # float_divmod(PyObject *v, PyObject *w)
662    # {
663    #     double vx, wx;
664    #     double div, mod, floordiv;
665    #     CONVERT_TO_DOUBLE(v, vx);
666    #     CONVERT_TO_DOUBLE(w, wx);
667    #     mod = fmod(vx, wx);
668    #     /* fmod is typically exact, so vx-mod is *mathematically* an
669    #        exact multiple of wx.  But this is fp arithmetic, and fp
670    #        vx - mod is an approximation; the result is that div may
671    #        not be an exact integral value after the division, although
672    #        it will always be very close to one.
673    #     */
674    #     div = (vx - mod) / wx;
675    #     if (mod) {
676    #         /* ensure the remainder has the same sign as the denominator */
677    #         if ((wx < 0) != (mod < 0)) {
678    #             mod += wx;
679    #             div -= 1.0;
680    #         }
681    #     }
682    #     else {
683    #         /* the remainder is zero, and in the presence of signed zeroes
684    #            fmod returns different results across platforms; ensure
685    #            it has the same sign as the denominator; we'd like to do
686    #            "mod = wx * 0.0", but that may get optimized away */
687    #         mod *= mod;  /* hide "mod = +0" from optimizer */
688    #         if (wx < 0.0)
689    #             mod = -mod;
690    #     }
691    #     /* snap quotient to nearest integral value */
692    #     if (div) {
693    #         floordiv = floor(div);
694    #         if (div - floordiv > 0.5)
695    #             floordiv += 1.0;
696    #     }
697    #     else {
698    #         /* div is zero - get the same sign as the true quotient */
699    #         div *= div;             /* hide "div = +0" from optimizers */
700    #         floordiv = div * vx / wx; /* zero w/ sign of vx/wx */
701    #     }
702    #     return Py_BuildValue("(dd)", floordiv, mod);
703    # }
704    pmod = cgutils.alloca_once(builder, vx.type)
705    pdiv = cgutils.alloca_once(builder, vx.type)
706    pfloordiv = cgutils.alloca_once(builder, vx.type)
707
708    mod = builder.frem(vx, wx)
709    div = builder.fdiv(builder.fsub(vx, mod), wx)
710
711    builder.store(mod, pmod)
712    builder.store(div, pdiv)
713
714    # Note the use of negative zero for proper negating with `ZERO - x`
715    ZERO = vx.type(0.0)
716    NZERO = vx.type(-0.0)
717    ONE = vx.type(1.0)
718    mod_istrue = builder.fcmp_unordered('!=', mod, ZERO)
719    wx_ltz = builder.fcmp_ordered('<', wx, ZERO)
720    mod_ltz = builder.fcmp_ordered('<', mod, ZERO)
721
722    with builder.if_else(mod_istrue, likely=True) as (if_nonzero_mod, if_zero_mod):
723        with if_nonzero_mod:
724            # `mod` is non-zero or NaN
725            # Ensure the remainder has the same sign as the denominator
726            wx_ltz_ne_mod_ltz = builder.icmp_unsigned('!=', wx_ltz, mod_ltz)
727
728            with builder.if_then(wx_ltz_ne_mod_ltz):
729                builder.store(builder.fsub(div, ONE), pdiv)
730                builder.store(builder.fadd(mod, wx), pmod)
731
732        with if_zero_mod:
733            # `mod` is zero, select the proper sign depending on
734            # the denominator's sign
735            mod = builder.select(wx_ltz, NZERO, ZERO)
736            builder.store(mod, pmod)
737
738    del mod, div
739
740    div = builder.load(pdiv)
741    div_istrue = builder.fcmp_ordered('!=', div, ZERO)
742
743    with builder.if_then(div_istrue):
744        realtypemap = {'float': types.float32,
745                       'double': types.float64}
746        realtype = realtypemap[str(wx.type)]
747        floorfn = context.get_function(math.floor,
748                                       typing.signature(realtype, realtype))
749        floordiv = floorfn(builder, [div])
750        floordivdiff = builder.fsub(div, floordiv)
751        floordivincr = builder.fadd(floordiv, ONE)
752        HALF = Constant(wx.type, 0.5)
753        pred = builder.fcmp_ordered('>', floordivdiff, HALF)
754        floordiv = builder.select(pred, floordivincr, floordiv)
755        builder.store(floordiv, pfloordiv)
756
757    with cgutils.ifnot(builder, div_istrue):
758        div = builder.fmul(div, div)
759        builder.store(div, pdiv)
760        floordiv = builder.fdiv(builder.fmul(div, vx), wx)
761        builder.store(floordiv, pfloordiv)
762
763    return builder.load(pfloordiv), builder.load(pmod)
764
765
766@lower_builtin(divmod, types.Float, types.Float)
767def real_divmod_impl(context, builder, sig, args, loc=None):
768    x, y = args
769    quot = cgutils.alloca_once(builder, x.type, name="quot")
770    rem = cgutils.alloca_once(builder, x.type, name="rem")
771
772    with builder.if_else(cgutils.is_scalar_zero(builder, y), likely=False
773                         ) as (if_zero, if_non_zero):
774        with if_zero:
775            if not context.error_model.fp_zero_division(
776                builder, ("modulo by zero",), loc):
777                # No exception raised => compute the nan result,
778                # and set the FP exception word for Numpy warnings.
779                q = builder.fdiv(x, y)
780                r = builder.frem(x, y)
781                builder.store(q, quot)
782                builder.store(r, rem)
783        with if_non_zero:
784            q, r = real_divmod(context, builder, x, y)
785            builder.store(q, quot)
786            builder.store(r, rem)
787
788    return cgutils.pack_array(builder,
789                              (builder.load(quot), builder.load(rem)))
790
791
792def real_mod_impl(context, builder, sig, args, loc=None):
793    x, y = args
794    res = cgutils.alloca_once(builder, x.type)
795    with builder.if_else(cgutils.is_scalar_zero(builder, y), likely=False
796                         ) as (if_zero, if_non_zero):
797        with if_zero:
798            if not context.error_model.fp_zero_division(
799                builder, ("modulo by zero",), loc):
800                # No exception raised => compute the nan result,
801                # and set the FP exception word for Numpy warnings.
802                rem = builder.frem(x, y)
803                builder.store(rem, res)
804        with if_non_zero:
805            _, rem = real_divmod(context, builder, x, y)
806            builder.store(rem, res)
807    return impl_ret_untracked(context, builder, sig.return_type,
808                              builder.load(res))
809
810
811def real_floordiv_impl(context, builder, sig, args, loc=None):
812    x, y = args
813    res = cgutils.alloca_once(builder, x.type)
814    with builder.if_else(cgutils.is_scalar_zero(builder, y), likely=False
815                         ) as (if_zero, if_non_zero):
816        with if_zero:
817            if not context.error_model.fp_zero_division(
818                builder, ("division by zero",), loc):
819                # No exception raised => compute the +/-inf or nan result,
820                # and set the FP exception word for Numpy warnings.
821                quot = builder.fdiv(x, y)
822                builder.store(quot, res)
823        with if_non_zero:
824            quot, _ = real_divmod(context, builder, x, y)
825            builder.store(quot, res)
826    return impl_ret_untracked(context, builder, sig.return_type,
827                              builder.load(res))
828
829
830def real_power_impl(context, builder, sig, args):
831    x, y = args
832    module = builder.module
833    if context.implement_powi_as_math_call:
834        imp = context.get_function(math.pow, sig)
835        res = imp(builder, args)
836    else:
837        fn = module.declare_intrinsic('llvm.pow', [y.type])
838        res = builder.call(fn, (x, y))
839    return impl_ret_untracked(context, builder, sig.return_type, res)
840
841
842def real_lt_impl(context, builder, sig, args):
843    res = builder.fcmp_ordered('<', *args)
844    return impl_ret_untracked(context, builder, sig.return_type, res)
845
846
847def real_le_impl(context, builder, sig, args):
848    res = builder.fcmp_ordered('<=', *args)
849    return impl_ret_untracked(context, builder, sig.return_type, res)
850
851
852def real_gt_impl(context, builder, sig, args):
853    res = builder.fcmp_ordered('>', *args)
854    return impl_ret_untracked(context, builder, sig.return_type, res)
855
856
857def real_ge_impl(context, builder, sig, args):
858    res = builder.fcmp_ordered('>=', *args)
859    return impl_ret_untracked(context, builder, sig.return_type, res)
860
861
862def real_eq_impl(context, builder, sig, args):
863    res = builder.fcmp_ordered('==', *args)
864    return impl_ret_untracked(context, builder, sig.return_type, res)
865
866
867def real_ne_impl(context, builder, sig, args):
868    res = builder.fcmp_unordered('!=', *args)
869    return impl_ret_untracked(context, builder, sig.return_type, res)
870
871
872def real_abs_impl(context, builder, sig, args):
873    [ty] = sig.args
874    sig = typing.signature(ty, ty)
875    impl = context.get_function(math.fabs, sig)
876    return impl(builder, args)
877
878
879def real_negate_impl(context, builder, sig, args):
880    from numba.cpython import mathimpl
881    res = mathimpl.negate_real(builder, args[0])
882    return impl_ret_untracked(context, builder, sig.return_type, res)
883
884
885def real_positive_impl(context, builder, sig, args):
886    [typ] = sig.args
887    [val] = args
888    res = context.cast(builder, val, typ, sig.return_type)
889    return impl_ret_untracked(context, builder, sig.return_type, res)
890
891
892def real_sign_impl(context, builder, sig, args):
893    """
894    np.sign(float)
895    """
896    [x] = args
897    POS = Constant(x.type, 1)
898    NEG = Constant(x.type, -1)
899    ZERO = Constant(x.type, 0)
900
901    presult = cgutils.alloca_once(builder, x.type)
902
903    is_pos = builder.fcmp_ordered('>', x, ZERO)
904    is_neg = builder.fcmp_ordered('<', x, ZERO)
905
906    with builder.if_else(is_pos) as (gt_zero, not_gt_zero):
907        with gt_zero:
908            builder.store(POS, presult)
909        with not_gt_zero:
910            with builder.if_else(is_neg) as (lt_zero, not_lt_zero):
911                with lt_zero:
912                    builder.store(NEG, presult)
913                with not_lt_zero:
914                    # For both NaN and 0, the result of sign() is simply
915                    # the input value.
916                    builder.store(x, presult)
917
918    res = builder.load(presult)
919    return impl_ret_untracked(context, builder, sig.return_type, res)
920
921
922ty = types.Float
923
924lower_builtin(operator.add, ty, ty)(real_add_impl)
925lower_builtin(operator.iadd, ty, ty)(real_add_impl)
926lower_builtin(operator.sub, ty, ty)(real_sub_impl)
927lower_builtin(operator.isub, ty, ty)(real_sub_impl)
928lower_builtin(operator.mul, ty, ty)(real_mul_impl)
929lower_builtin(operator.imul, ty, ty)(real_mul_impl)
930lower_builtin(operator.floordiv, ty, ty)(real_floordiv_impl)
931lower_builtin(operator.ifloordiv, ty, ty)(real_floordiv_impl)
932lower_builtin(operator.truediv, ty, ty)(real_div_impl)
933lower_builtin(operator.itruediv, ty, ty)(real_div_impl)
934lower_builtin(operator.mod, ty, ty)(real_mod_impl)
935lower_builtin(operator.imod, ty, ty)(real_mod_impl)
936lower_builtin(operator.pow, ty, ty)(real_power_impl)
937lower_builtin(operator.ipow, ty, ty)(real_power_impl)
938lower_builtin(pow, ty, ty)(real_power_impl)
939
940lower_builtin(operator.eq, ty, ty)(real_eq_impl)
941lower_builtin(operator.ne, ty, ty)(real_ne_impl)
942lower_builtin(operator.lt, ty, ty)(real_lt_impl)
943lower_builtin(operator.le, ty, ty)(real_le_impl)
944lower_builtin(operator.gt, ty, ty)(real_gt_impl)
945lower_builtin(operator.ge, ty, ty)(real_ge_impl)
946
947lower_builtin(abs, ty)(real_abs_impl)
948
949lower_builtin(operator.neg, ty)(real_negate_impl)
950lower_builtin(operator.pos, ty)(real_positive_impl)
951
952del ty
953
954
955@lower_getattr(types.Complex, "real")
956def complex_real_impl(context, builder, typ, value):
957    cplx = context.make_complex(builder, typ, value=value)
958    res = cplx.real
959    return impl_ret_untracked(context, builder, typ, res)
960
961@lower_getattr(types.Complex, "imag")
962def complex_imag_impl(context, builder, typ, value):
963    cplx = context.make_complex(builder, typ, value=value)
964    res = cplx.imag
965    return impl_ret_untracked(context, builder, typ, res)
966
967@lower_builtin("complex.conjugate", types.Complex)
968def complex_conjugate_impl(context, builder, sig, args):
969    from numba.cpython import mathimpl
970    z = context.make_complex(builder, sig.args[0], args[0])
971    z.imag = mathimpl.negate_real(builder, z.imag)
972    res = z._getvalue()
973    return impl_ret_untracked(context, builder, sig.return_type, res)
974
975def real_real_impl(context, builder, typ, value):
976    return impl_ret_untracked(context, builder, typ, value)
977
978def real_imag_impl(context, builder, typ, value):
979    res = cgutils.get_null_value(value.type)
980    return impl_ret_untracked(context, builder, typ, res)
981
982def real_conjugate_impl(context, builder, sig, args):
983    return impl_ret_untracked(context, builder, sig.return_type, args[0])
984
985for cls in (types.Float, types.Integer):
986    lower_getattr(cls, "real")(real_real_impl)
987    lower_getattr(cls, "imag")(real_imag_impl)
988    lower_builtin("complex.conjugate", cls)(real_conjugate_impl)
989
990
991@lower_builtin(operator.pow, types.Complex, types.Complex)
992@lower_builtin(operator.ipow, types.Complex, types.Complex)
993@lower_builtin(pow, types.Complex, types.Complex)
994def complex_power_impl(context, builder, sig, args):
995    [ca, cb] = args
996    ty = sig.args[0]
997    fty = ty.underlying_float
998    a = context.make_helper(builder, ty, value=ca)
999    b = context.make_helper(builder, ty, value=cb)
1000    c = context.make_helper(builder, ty)
1001    module = builder.module
1002    pa = a._getpointer()
1003    pb = b._getpointer()
1004    pc = c._getpointer()
1005
1006    # Optimize for square because cpow loses a lot of precision
1007    TWO = context.get_constant(fty, 2)
1008    ZERO = context.get_constant(fty, 0)
1009
1010    b_real_is_two = builder.fcmp_ordered('==', b.real, TWO)
1011    b_imag_is_zero = builder.fcmp_ordered('==', b.imag, ZERO)
1012    b_is_two = builder.and_(b_real_is_two, b_imag_is_zero)
1013
1014    with builder.if_else(b_is_two) as (then, otherwise):
1015        with then:
1016            # Lower as multiplication
1017            res = complex_mul_impl(context, builder, sig, (ca, ca))
1018            cres = context.make_helper(builder, ty, value=res)
1019            c.real = cres.real
1020            c.imag = cres.imag
1021
1022        with otherwise:
1023            # Lower with call to external function
1024            func_name = {
1025                types.complex64: "numba_cpowf",
1026                types.complex128: "numba_cpow",
1027                }[ty]
1028            fnty = ir.FunctionType(ir.VoidType(), [pa.type] * 3)
1029            cpow = cgutils.get_or_insert_function(module, fnty, func_name)
1030            builder.call(cpow, (pa, pb, pc))
1031
1032    res = builder.load(pc)
1033    return impl_ret_untracked(context, builder, sig.return_type, res)
1034
1035def complex_add_impl(context, builder, sig, args):
1036    [cx, cy] = args
1037    ty = sig.args[0]
1038    x = context.make_complex(builder, ty, value=cx)
1039    y = context.make_complex(builder, ty, value=cy)
1040    z = context.make_complex(builder, ty)
1041    a = x.real
1042    b = x.imag
1043    c = y.real
1044    d = y.imag
1045    z.real = builder.fadd(a, c)
1046    z.imag = builder.fadd(b, d)
1047    res = z._getvalue()
1048    return impl_ret_untracked(context, builder, sig.return_type, res)
1049
1050
1051def complex_sub_impl(context, builder, sig, args):
1052    [cx, cy] = args
1053    ty = sig.args[0]
1054    x = context.make_complex(builder, ty, value=cx)
1055    y = context.make_complex(builder, ty, value=cy)
1056    z = context.make_complex(builder, ty)
1057    a = x.real
1058    b = x.imag
1059    c = y.real
1060    d = y.imag
1061    z.real = builder.fsub(a, c)
1062    z.imag = builder.fsub(b, d)
1063    res = z._getvalue()
1064    return impl_ret_untracked(context, builder, sig.return_type, res)
1065
1066
1067def complex_mul_impl(context, builder, sig, args):
1068    """
1069    (a+bi)(c+di)=(ac-bd)+i(ad+bc)
1070    """
1071    [cx, cy] = args
1072    ty = sig.args[0]
1073    x = context.make_complex(builder, ty, value=cx)
1074    y = context.make_complex(builder, ty, value=cy)
1075    z = context.make_complex(builder, ty)
1076    a = x.real
1077    b = x.imag
1078    c = y.real
1079    d = y.imag
1080    ac = builder.fmul(a, c)
1081    bd = builder.fmul(b, d)
1082    ad = builder.fmul(a, d)
1083    bc = builder.fmul(b, c)
1084    z.real = builder.fsub(ac, bd)
1085    z.imag = builder.fadd(ad, bc)
1086    res = z._getvalue()
1087    return impl_ret_untracked(context, builder, sig.return_type, res)
1088
1089
1090NAN = float('nan')
1091
1092def complex_div_impl(context, builder, sig, args):
1093    def complex_div(a, b):
1094        # This is CPython's algorithm (in _Py_c_quot()).
1095        areal = a.real
1096        aimag = a.imag
1097        breal = b.real
1098        bimag = b.imag
1099        if not breal and not bimag:
1100            raise ZeroDivisionError("complex division by zero")
1101        if abs(breal) >= abs(bimag):
1102            # Divide tops and bottom by b.real
1103            if not breal:
1104                return complex(NAN, NAN)
1105            ratio = bimag / breal
1106            denom = breal + bimag * ratio
1107            return complex(
1108                (areal + aimag * ratio) / denom,
1109                (aimag - areal * ratio) / denom)
1110        else:
1111            # Divide tops and bottom by b.imag
1112            if not bimag:
1113                return complex(NAN, NAN)
1114            ratio = breal / bimag
1115            denom = breal * ratio + bimag
1116            return complex(
1117                (a.real * ratio + a.imag) / denom,
1118                (a.imag * ratio - a.real) / denom)
1119
1120    res = context.compile_internal(builder, complex_div, sig, args)
1121    return impl_ret_untracked(context, builder, sig.return_type, res)
1122
1123
1124def complex_negate_impl(context, builder, sig, args):
1125    from numba.cpython import mathimpl
1126    [typ] = sig.args
1127    [val] = args
1128    cmplx = context.make_complex(builder, typ, value=val)
1129    res = context.make_complex(builder, typ)
1130    res.real = mathimpl.negate_real(builder, cmplx.real)
1131    res.imag = mathimpl.negate_real(builder, cmplx.imag)
1132    res = res._getvalue()
1133    return impl_ret_untracked(context, builder, sig.return_type, res)
1134
1135
1136def complex_positive_impl(context, builder, sig, args):
1137    [val] = args
1138    return impl_ret_untracked(context, builder, sig.return_type, val)
1139
1140
1141def complex_eq_impl(context, builder, sig, args):
1142    [cx, cy] = args
1143    typ = sig.args[0]
1144    x = context.make_complex(builder, typ, value=cx)
1145    y = context.make_complex(builder, typ, value=cy)
1146
1147    reals_are_eq = builder.fcmp_ordered('==', x.real, y.real)
1148    imags_are_eq = builder.fcmp_ordered('==', x.imag, y.imag)
1149    res = builder.and_(reals_are_eq, imags_are_eq)
1150    return impl_ret_untracked(context, builder, sig.return_type, res)
1151
1152
1153def complex_ne_impl(context, builder, sig, args):
1154    [cx, cy] = args
1155    typ = sig.args[0]
1156    x = context.make_complex(builder, typ, value=cx)
1157    y = context.make_complex(builder, typ, value=cy)
1158
1159    reals_are_ne = builder.fcmp_unordered('!=', x.real, y.real)
1160    imags_are_ne = builder.fcmp_unordered('!=', x.imag, y.imag)
1161    res = builder.or_(reals_are_ne, imags_are_ne)
1162    return impl_ret_untracked(context, builder, sig.return_type, res)
1163
1164
1165def complex_abs_impl(context, builder, sig, args):
1166    """
1167    abs(z) := hypot(z.real, z.imag)
1168    """
1169    def complex_abs(z):
1170        return math.hypot(z.real, z.imag)
1171
1172    res = context.compile_internal(builder, complex_abs, sig, args)
1173    return impl_ret_untracked(context, builder, sig.return_type, res)
1174
1175
1176ty = types.Complex
1177
1178lower_builtin(operator.add, ty, ty)(complex_add_impl)
1179lower_builtin(operator.iadd, ty, ty)(complex_add_impl)
1180lower_builtin(operator.sub, ty, ty)(complex_sub_impl)
1181lower_builtin(operator.isub, ty, ty)(complex_sub_impl)
1182lower_builtin(operator.mul, ty, ty)(complex_mul_impl)
1183lower_builtin(operator.imul, ty, ty)(complex_mul_impl)
1184lower_builtin(operator.truediv, ty, ty)(complex_div_impl)
1185lower_builtin(operator.itruediv, ty, ty)(complex_div_impl)
1186lower_builtin(operator.neg, ty)(complex_negate_impl)
1187lower_builtin(operator.pos, ty)(complex_positive_impl)
1188# Complex modulo is deprecated in python3
1189
1190lower_builtin(operator.eq, ty, ty)(complex_eq_impl)
1191lower_builtin(operator.ne, ty, ty)(complex_ne_impl)
1192
1193lower_builtin(abs, ty)(complex_abs_impl)
1194
1195del ty
1196
1197
1198@lower_builtin("number.item", types.Boolean)
1199@lower_builtin("number.item", types.Number)
1200def number_item_impl(context, builder, sig, args):

Showing the first 1,200 of 1396 lines. Download the file for the rest.

Aluode/PerceptionLabPortable · CoolFace