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):
1201 """
1202 The no-op .item() method on booleans and numbers.
1203 """
1204 return args[0]
1205
1206
1207#------------------------------------------------------------------------------
1208
1209
1210def number_not_impl(context, builder, sig, args):
1211 [typ] = sig.args
1212 [val] = args
1213 istrue = context.cast(builder, val, typ, sig.return_type)
1214 res = builder.not_(istrue)
1215 return impl_ret_untracked(context, builder, sig.return_type, res)
1216
1217@lower_builtin(bool, types.Boolean)
1218def bool_as_bool(context, builder, sig, args):
1219 [val] = args
1220 return val
1221
1222@lower_builtin(bool, types.Integer)
1223def int_as_bool(context, builder, sig, args):
1224 [val] = args
1225 return builder.icmp_unsigned('!=', val, Constant(val.type, 0))
1226
1227@lower_builtin(bool, types.Float)
1228def float_as_bool(context, builder, sig, args):
1229 [val] = args
1230 return builder.fcmp_unordered('!=', val, Constant(val.type, 0.0))
1231
1232@lower_builtin(bool, types.Complex)
1233def complex_as_bool(context, builder, sig, args):
1234 [typ] = sig.args
1235 [val] = args
1236 cmplx = context.make_complex(builder, typ, val)
1237 real, imag = cmplx.real, cmplx.imag
1238 zero = Constant(real.type, 0.0)
1239 real_istrue = builder.fcmp_unordered('!=', real, zero)
1240 imag_istrue = builder.fcmp_unordered('!=', imag, zero)
1241 return builder.or_(real_istrue, imag_istrue)
1242
1243
1244for ty in (types.Integer, types.Float, types.Complex):
1245 lower_builtin(operator.not_, ty)(number_not_impl)
1246
1247lower_builtin(operator.not_, types.boolean)(number_not_impl)
1248
1249
1250#------------------------------------------------------------------------------
1251# Hashing numbers, see hashing.py
1252
1253#-------------------------------------------------------------------------------
1254# Implicit casts between numerics
1255
1256@lower_cast(types.IntegerLiteral, types.Integer)
1257@lower_cast(types.IntegerLiteral, types.Float)
1258@lower_cast(types.IntegerLiteral, types.Complex)
1259def literal_int_to_number(context, builder, fromty, toty, val):
1260 lit = context.get_constant_generic(
1261 builder,
1262 fromty.literal_type,
1263 fromty.literal_value,
1264 )
1265 return context.cast(builder, lit, fromty.literal_type, toty)
1266
1267
1268@lower_cast(types.Integer, types.Integer)
1269def integer_to_integer(context, builder, fromty, toty, val):
1270 if toty.bitwidth == fromty.bitwidth:
1271 # Just a change of signedness
1272 return val
1273 elif toty.bitwidth < fromty.bitwidth:
1274 # Downcast
1275 return builder.trunc(val, context.get_value_type(toty))
1276 elif fromty.signed:
1277 # Signed upcast
1278 return builder.sext(val, context.get_value_type(toty))
1279 else:
1280 # Unsigned upcast
1281 return builder.zext(val, context.get_value_type(toty))
1282
1283@lower_cast(types.Integer, types.voidptr)
1284def integer_to_voidptr(context, builder, fromty, toty, val):
1285 return builder.inttoptr(val, context.get_value_type(toty))
1286
1287@lower_cast(types.Float, types.Float)
1288def float_to_float(context, builder, fromty, toty, val):
1289 lty = context.get_value_type(toty)
1290 if fromty.bitwidth < toty.bitwidth:
1291 return builder.fpext(val, lty)
1292 else:
1293 return builder.fptrunc(val, lty)
1294
1295@lower_cast(types.Integer, types.Float)
1296def integer_to_float(context, builder, fromty, toty, val):
1297 lty = context.get_value_type(toty)
1298 if fromty.signed:
1299 return builder.sitofp(val, lty)
1300 else:
1301 return builder.uitofp(val, lty)
1302
1303@lower_cast(types.Float, types.Integer)
1304def float_to_integer(context, builder, fromty, toty, val):
1305 lty = context.get_value_type(toty)
1306 if toty.signed:
1307 return builder.fptosi(val, lty)
1308 else:
1309 return builder.fptoui(val, lty)
1310
1311@lower_cast(types.Float, types.Complex)
1312@lower_cast(types.Integer, types.Complex)
1313def non_complex_to_complex(context, builder, fromty, toty, val):
1314 real = context.cast(builder, val, fromty, toty.underlying_float)
1315 imag = context.get_constant(toty.underlying_float, 0)
1316
1317 cmplx = context.make_complex(builder, toty)
1318 cmplx.real = real
1319 cmplx.imag = imag
1320 return cmplx._getvalue()
1321
1322@lower_cast(types.Complex, types.Complex)
1323def complex_to_complex(context, builder, fromty, toty, val):
1324 srcty = fromty.underlying_float
1325 dstty = toty.underlying_float
1326
1327 src = context.make_complex(builder, fromty, value=val)
1328 dst = context.make_complex(builder, toty)
1329 dst.real = context.cast(builder, src.real, srcty, dstty)
1330 dst.imag = context.cast(builder, src.imag, srcty, dstty)
1331 return dst._getvalue()
1332
1333@lower_cast(types.Any, types.Boolean)
1334def any_to_boolean(context, builder, fromty, toty, val):
1335 return context.is_true(builder, fromty, val)
1336
1337@lower_cast(types.Boolean, types.Number)
1338def boolean_to_any(context, builder, fromty, toty, val):
1339 # Casting from boolean to anything first casts to int32
1340 asint = builder.zext(val, ir.IntType(32))
1341 return context.cast(builder, asint, types.int32, toty)
1342
1343@lower_cast(types.IntegerLiteral, types.Boolean)
1344@lower_cast(types.BooleanLiteral, types.Boolean)
1345def literal_int_to_boolean(context, builder, fromty, toty, val):
1346 lit = context.get_constant_generic(
1347 builder,
1348 fromty.literal_type,
1349 fromty.literal_value,
1350 )
1351 return context.is_true(builder, fromty.literal_type, lit)
1352
1353#-------------------------------------------------------------------------------
1354# Constants
1355
1356@lower_constant(types.Complex)
1357def constant_complex(context, builder, ty, pyval):
1358 fty = ty.underlying_float
1359 real = context.get_constant_generic(builder, fty, pyval.real)
1360 imag = context.get_constant_generic(builder, fty, pyval.imag)
1361 return Constant.literal_struct((real, imag))
1362
1363@lower_constant(types.Integer)
1364@lower_constant(types.Float)
1365@lower_constant(types.Boolean)
1366def constant_integer(context, builder, ty, pyval):
1367 # See https://github.com/numba/numba/issues/6979
1368 # llvmlite ir.IntType specialises the formatting of the constant for a
1369 # cpython bool. A NumPy np.bool_ is not a cpython bool so force it to be one
1370 # so that the constant renders correctly!
1371 if isinstance(pyval, np.bool_):
1372 pyval = bool(pyval)
1373 lty = context.get_value_type(ty)
1374 return lty(pyval)
1375
1376
1377#-------------------------------------------------------------------------------
1378# View
1379
1380def scalar_view(scalar, viewty):
1381 """ Typing for the np scalar 'view' method. """
1382 if (isinstance(scalar, (types.Float, types.Integer))
1383 and isinstance(viewty, types.abstract.DTypeSpec)):
1384 if scalar.bitwidth != viewty.dtype.bitwidth:
1385 raise errors.TypingError(
1386 "Changing the dtype of a 0d array is only supported if the "
1387 "itemsize is unchanged")
1388
1389 def impl(scalar, viewty):
1390 return viewer(scalar, viewty)
1391 return impl
1392
1393
1394overload_method(types.Float, 'view')(scalar_view)
1395overload_method(types.Integer, 'view')(scalar_view)