Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/numba/np/math/numbers.py: 11%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

742 statements  

1import math 

2import numbers 

3 

4import numpy as np 

5 

6from llvmlite import ir 

7from llvmlite.ir import Constant 

8 

9from numba.core.imputils import impl_ret_untracked 

10from numba.core import typing, types, errors, cgutils 

11from numba.cpython.unsafe.numbers import viewer 

12 

13def _int_arith_flags(rettype): 

14 """ 

15 Return the modifier flags for integer arithmetic. 

16 """ 

17 if rettype.signed: 

18 # Ignore the effects of signed overflow. This is important for 

19 # optimization of some indexing operations. For example 

20 # array[i+1] could see `i+1` trigger a signed overflow and 

21 # give a negative number. With Python's indexing, a negative 

22 # index is treated differently: its resolution has a runtime cost. 

23 # Telling LLVM to ignore signed overflows allows it to optimize 

24 # away the check for a negative `i+1` if it knows `i` is positive. 

25 return ['nsw'] 

26 else: 

27 return [] 

28 

29 

30def int_add_impl(context, builder, sig, args): 

31 [va, vb] = args 

32 [ta, tb] = sig.args 

33 a = context.cast(builder, va, ta, sig.return_type) 

34 b = context.cast(builder, vb, tb, sig.return_type) 

35 res = builder.add(a, b, flags=_int_arith_flags(sig.return_type)) 

36 return impl_ret_untracked(context, builder, sig.return_type, res) 

37 

38 

39def int_sub_impl(context, builder, sig, args): 

40 [va, vb] = args 

41 [ta, tb] = sig.args 

42 a = context.cast(builder, va, ta, sig.return_type) 

43 b = context.cast(builder, vb, tb, sig.return_type) 

44 res = builder.sub(a, b, flags=_int_arith_flags(sig.return_type)) 

45 return impl_ret_untracked(context, builder, sig.return_type, res) 

46 

47 

48def int_mul_impl(context, builder, sig, args): 

49 [va, vb] = args 

50 [ta, tb] = sig.args 

51 a = context.cast(builder, va, ta, sig.return_type) 

52 b = context.cast(builder, vb, tb, sig.return_type) 

53 res = builder.mul(a, b, flags=_int_arith_flags(sig.return_type)) 

54 return impl_ret_untracked(context, builder, sig.return_type, res) 

55 

56 

57def int_divmod_signed(context, builder, ty, x, y): 

58 """ 

59 Reference Objects/intobject.c 

60 xdivy = x / y; 

61 xmody = (long)(x - (unsigned long)xdivy * y); 

62 /* If the signs of x and y differ, and the remainder is non-0, 

63 * C89 doesn't define whether xdivy is now the floor or the 

64 * ceiling of the infinitely precise quotient. We want the floor, 

65 * and we have it iff the remainder's sign matches y's. 

66 */ 

67 if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) { 

68 xmody += y; 

69 --xdivy; 

70 assert(xmody && ((y ^ xmody) >= 0)); 

71 } 

72 *p_xdivy = xdivy; 

73 *p_xmody = xmody; 

74 """ 

75 assert x.type == y.type 

76 

77 ZERO = y.type(0) 

78 ONE = y.type(1) 

79 

80 # NOTE: On x86 at least, dividing the lowest representable integer 

81 # (e.g. 0x80000000 for int32) by -1 causes a SIFGPE (division overflow), 

82 # causing the process to crash. 

83 # We return 0, 0 instead (more or less like Numpy). 

84 

85 resdiv = cgutils.alloca_once_value(builder, ZERO) 

86 resmod = cgutils.alloca_once_value(builder, ZERO) 

87 

88 is_overflow = builder.and_( 

89 builder.icmp_signed('==', x, x.type(ty.minval)), 

90 builder.icmp_signed('==', y, y.type(-1))) 

91 

92 with builder.if_then(builder.not_(is_overflow), likely=True): 

93 # Note LLVM will optimize this to a single divmod instruction, 

94 # if available on the target CPU (e.g. x86). 

95 xdivy = builder.sdiv(x, y) 

96 xmody = builder.srem(x, y) 

97 

98 y_xor_xmody_ltz = builder.icmp_signed('<', builder.xor(y, xmody), ZERO) 

99 xmody_istrue = builder.icmp_signed('!=', xmody, ZERO) 

100 cond = builder.and_(xmody_istrue, y_xor_xmody_ltz) 

101 

102 with builder.if_else(cond) as (if_different_signs, if_same_signs): 

103 with if_same_signs: 

104 builder.store(xdivy, resdiv) 

105 builder.store(xmody, resmod) 

106 

107 with if_different_signs: 

108 builder.store(builder.sub(xdivy, ONE), resdiv) 

109 builder.store(builder.add(xmody, y), resmod) 

110 

111 return builder.load(resdiv), builder.load(resmod) 

112 

113 

114def int_divmod(context, builder, ty, x, y): 

115 """ 

116 Integer divmod(x, y). The caller must ensure that y != 0. 

117 """ 

118 if ty.signed: 

119 return int_divmod_signed(context, builder, ty, x, y) 

120 else: 

121 return builder.udiv(x, y), builder.urem(x, y) 

122 

123 

124def _int_divmod_impl(context, builder, sig, args, zerodiv_message): 

125 va, vb = args 

126 ta, tb = sig.args 

127 

128 ty = sig.return_type 

129 if isinstance(ty, types.UniTuple): 

130 ty = ty.dtype 

131 a = context.cast(builder, va, ta, ty) 

132 b = context.cast(builder, vb, tb, ty) 

133 quot = cgutils.alloca_once(builder, a.type, name="quot") 

134 rem = cgutils.alloca_once(builder, a.type, name="rem") 

135 

136 with builder.if_else(cgutils.is_scalar_zero(builder, b), likely=False 

137 ) as (if_zero, if_non_zero): 

138 with if_zero: 

139 if not context.error_model.fp_zero_division( 

140 builder, (zerodiv_message,)): 

141 # No exception raised => return 0 

142 # XXX We should also set the FPU exception status, but 

143 # there's no easy way to do that from LLVM. 

144 builder.store(b, quot) 

145 builder.store(b, rem) 

146 with if_non_zero: 

147 q, r = int_divmod(context, builder, ty, a, b) 

148 builder.store(q, quot) 

149 builder.store(r, rem) 

150 

151 return quot, rem 

152 

153 

154# @lower_builtin(divmod, types.Integer, types.Integer) 

155def int_divmod_impl(context, builder, sig, args): 

156 quot, rem = _int_divmod_impl(context, builder, sig, args, 

157 "integer divmod by zero") 

158 

159 return cgutils.pack_array(builder, 

160 (builder.load(quot), builder.load(rem))) 

161 

162 

163# @lower_builtin(operator.floordiv, types.Integer, types.Integer) 

164# @lower_builtin(operator.ifloordiv, types.Integer, types.Integer) 

165def int_floordiv_impl(context, builder, sig, args): 

166 quot, rem = _int_divmod_impl(context, builder, sig, args, 

167 "integer division by zero") 

168 return builder.load(quot) 

169 

170 

171# @lower_builtin(operator.truediv, types.Integer, types.Integer) 

172# @lower_builtin(operator.itruediv, types.Integer, types.Integer) 

173def int_truediv_impl(context, builder, sig, args): 

174 [va, vb] = args 

175 [ta, tb] = sig.args 

176 a = context.cast(builder, va, ta, sig.return_type) 

177 b = context.cast(builder, vb, tb, sig.return_type) 

178 with cgutils.if_zero(builder, b): 

179 context.error_model.fp_zero_division(builder, ("division by zero",)) 

180 res = builder.fdiv(a, b) 

181 return impl_ret_untracked(context, builder, sig.return_type, res) 

182 

183 

184# @lower_builtin(operator.mod, types.Integer, types.Integer) 

185# @lower_builtin(operator.imod, types.Integer, types.Integer) 

186def int_rem_impl(context, builder, sig, args): 

187 quot, rem = _int_divmod_impl(context, builder, sig, args, 

188 "integer modulo by zero") 

189 return builder.load(rem) 

190 

191 

192def _get_power_zerodiv_return(context, return_type): 

193 if (isinstance(return_type, types.Integer) 

194 and not context.error_model.raise_on_fp_zero_division): 

195 # If not raising, return 0x8000... when computing 0 ** <negative number> 

196 return -1 << (return_type.bitwidth - 1) 

197 else: 

198 return False 

199 

200 

201def int_power_impl(context, builder, sig, args): 

202 """ 

203 a ^ b, where a is an integer or real, and b an integer 

204 """ 

205 is_integer = isinstance(sig.args[0], types.Integer) 

206 tp = sig.return_type 

207 zerodiv_return = _get_power_zerodiv_return(context, tp) 

208 

209 def int_power(a, b): 

210 # Ensure computations are done with a large enough width 

211 r = tp(1) 

212 a = tp(a) 

213 if b < 0: 

214 invert = True 

215 exp = -b 

216 if exp < 0: 

217 raise OverflowError 

218 if is_integer: 

219 if a == 0: 

220 if zerodiv_return: 

221 return zerodiv_return 

222 else: 

223 raise ZeroDivisionError("0 cannot be raised to a negative power") 

224 if a != 1 and a != -1: 

225 return 0 

226 else: 

227 invert = False 

228 exp = b 

229 if exp > 0x10000: 

230 # Optimization cutoff: fallback on the generic algorithm 

231 return math.pow(a, float(b)) 

232 while exp != 0: 

233 if exp & 1: 

234 r *= a 

235 exp >>= 1 

236 a *= a 

237 

238 return 1.0 / r if invert else r 

239 

240 res = context.compile_internal(builder, int_power, sig, args) 

241 return impl_ret_untracked(context, builder, sig.return_type, res) 

242 

243 

244# @lower_builtin(operator.pow, types.Integer, types.IntegerLiteral) 

245# @lower_builtin(operator.ipow, types.Integer, types.IntegerLiteral) 

246# @lower_builtin(operator.pow, types.Float, types.IntegerLiteral) 

247# @lower_builtin(operator.ipow, types.Float, types.IntegerLiteral) 

248def static_power_impl(context, builder, sig, args): 

249 """ 

250 a ^ b, where a is an integer or real, and b a constant integer 

251 """ 

252 exp = sig.args[1].value 

253 if not isinstance(exp, numbers.Integral): 

254 raise NotImplementedError 

255 if abs(exp) > 0x10000: 

256 # Optimization cutoff: fallback on the generic algorithm above 

257 raise NotImplementedError 

258 invert = exp < 0 

259 exp = abs(exp) 

260 

261 tp = sig.return_type 

262 is_integer = isinstance(tp, types.Integer) 

263 zerodiv_return = _get_power_zerodiv_return(context, tp) 

264 

265 val = context.cast(builder, args[0], sig.args[0], tp) 

266 lty = val.type 

267 

268 def mul(a, b): 

269 if is_integer: 

270 return builder.mul(a, b) 

271 else: 

272 return builder.fmul(a, b) 

273 

274 # Unroll the exponentiation loop 

275 res = lty(1) 

276 a = val 

277 while exp != 0: 

278 if exp & 1: 

279 res = mul(res, val) 

280 exp >>= 1 

281 val = mul(val, val) 

282 

283 if invert: 

284 # If the exponent was negative, fix the result by inverting it 

285 if is_integer: 

286 # Integer inversion 

287 def invert_impl(a): 

288 if a == 0: 

289 if zerodiv_return: 

290 return zerodiv_return 

291 else: 

292 raise ZeroDivisionError("0 cannot be raised to a negative power") 

293 if a != 1 and a != -1: 

294 return 0 

295 else: 

296 return a 

297 

298 else: 

299 # Real inversion 

300 def invert_impl(a): 

301 return 1.0 / a 

302 

303 res = context.compile_internal(builder, invert_impl, 

304 typing.signature(tp, tp), (res,)) 

305 

306 return res 

307 

308 

309def int_slt_impl(context, builder, sig, args): 

310 res = builder.icmp_signed('<', *args) 

311 return impl_ret_untracked(context, builder, sig.return_type, res) 

312 

313 

314def int_sle_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_sgt_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_sge_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_ult_impl(context, builder, sig, args): 

330 res = builder.icmp_unsigned('<', *args) 

331 return impl_ret_untracked(context, builder, sig.return_type, res) 

332 

333 

334def int_ule_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_ugt_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_uge_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_eq_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_ne_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_signed_unsigned_cmp(op): 

360 def impl(context, builder, sig, args): 

361 (left, right) = args 

362 # This code is translated from the NumPy source. 

363 # What we're going to do is divide the range of a signed value at zero. 

364 # If the signed value is less than zero, then we can treat zero as the 

365 # unsigned value since the unsigned value is necessarily zero or larger 

366 # and any signed comparison between a negative value and zero/infinity 

367 # will yield the same result. If the signed value is greater than or 

368 # equal to zero, then we can safely cast it to an unsigned value and do 

369 # the expected unsigned-unsigned comparison operation. 

370 # Original: https://github.com/numpy/numpy/pull/23713 

371 cmp_zero = builder.icmp_signed('<', left, Constant(left.type, 0)) 

372 lt_zero = builder.icmp_signed(op, left, Constant(left.type, 0)) 

373 ge_zero = builder.icmp_unsigned(op, left, right) 

374 res = builder.select(cmp_zero, lt_zero, ge_zero) 

375 return impl_ret_untracked(context, builder, sig.return_type, res) 

376 return impl 

377 

378 

379def int_unsigned_signed_cmp(op): 

380 def impl(context, builder, sig, args): 

381 (left, right) = args 

382 # See the function `int_signed_unsigned_cmp` for implementation notes. 

383 cmp_zero = builder.icmp_signed('<', right, Constant(right.type, 0)) 

384 lt_zero = builder.icmp_signed(op, Constant(right.type, 0), right) 

385 ge_zero = builder.icmp_unsigned(op, left, right) 

386 res = builder.select(cmp_zero, lt_zero, ge_zero) 

387 return impl_ret_untracked(context, builder, sig.return_type, res) 

388 return impl 

389 

390 

391def int_abs_impl(context, builder, sig, args): 

392 [x] = args 

393 ZERO = Constant(x.type, None) 

394 ltz = builder.icmp_signed('<', x, ZERO) 

395 negated = builder.neg(x) 

396 res = builder.select(ltz, negated, x) 

397 return impl_ret_untracked(context, builder, sig.return_type, res) 

398 

399 

400def uint_abs_impl(context, builder, sig, args): 

401 [x] = args 

402 return impl_ret_untracked(context, builder, sig.return_type, x) 

403 

404 

405def int_shl_impl(context, builder, sig, args): 

406 [valty, amtty] = sig.args 

407 [val, amt] = args 

408 val = context.cast(builder, val, valty, sig.return_type) 

409 amt = context.cast(builder, amt, amtty, sig.return_type) 

410 res = builder.shl(val, amt) 

411 return impl_ret_untracked(context, builder, sig.return_type, res) 

412 

413 

414def int_shr_impl(context, builder, sig, args): 

415 [valty, amtty] = sig.args 

416 [val, amt] = args 

417 val = context.cast(builder, val, valty, sig.return_type) 

418 amt = context.cast(builder, amt, amtty, sig.return_type) 

419 if sig.return_type.signed: 

420 res = builder.ashr(val, amt) 

421 else: 

422 res = builder.lshr(val, amt) 

423 return impl_ret_untracked(context, builder, sig.return_type, res) 

424 

425 

426def int_and_impl(context, builder, sig, args): 

427 [at, bt] = sig.args 

428 [av, bv] = args 

429 cav = context.cast(builder, av, at, sig.return_type) 

430 cbc = context.cast(builder, bv, bt, sig.return_type) 

431 res = builder.and_(cav, cbc) 

432 return impl_ret_untracked(context, builder, sig.return_type, res) 

433 

434 

435def int_or_impl(context, builder, sig, args): 

436 [at, bt] = sig.args 

437 [av, bv] = args 

438 cav = context.cast(builder, av, at, sig.return_type) 

439 cbc = context.cast(builder, bv, bt, sig.return_type) 

440 res = builder.or_(cav, cbc) 

441 return impl_ret_untracked(context, builder, sig.return_type, res) 

442 

443 

444def int_xor_impl(context, builder, sig, args): 

445 [at, bt] = sig.args 

446 [av, bv] = args 

447 cav = context.cast(builder, av, at, sig.return_type) 

448 cbc = context.cast(builder, bv, bt, sig.return_type) 

449 res = builder.xor(cav, cbc) 

450 return impl_ret_untracked(context, builder, sig.return_type, res) 

451 

452 

453def int_negate_impl(context, builder, sig, args): 

454 [typ] = sig.args 

455 [val] = args 

456 # Negate before upcasting, for unsigned numbers 

457 res = builder.neg(val) 

458 res = context.cast(builder, res, typ, sig.return_type) 

459 return impl_ret_untracked(context, builder, sig.return_type, res) 

460 

461 

462def int_positive_impl(context, builder, sig, args): 

463 [typ] = sig.args 

464 [val] = args 

465 res = context.cast(builder, val, typ, sig.return_type) 

466 return impl_ret_untracked(context, builder, sig.return_type, res) 

467 

468 

469def int_invert_impl(context, builder, sig, args): 

470 [typ] = sig.args 

471 [val] = args 

472 # Invert before upcasting, for unsigned numbers 

473 res = builder.xor(val, Constant(val.type, int('1' * val.type.width, 2))) 

474 res = context.cast(builder, res, typ, sig.return_type) 

475 return impl_ret_untracked(context, builder, sig.return_type, res) 

476 

477 

478def int_sign_impl(context, builder, sig, args): 

479 """ 

480 np.sign(int) 

481 """ 

482 [x] = args 

483 POS = Constant(x.type, 1) 

484 NEG = Constant(x.type, -1) 

485 ZERO = Constant(x.type, 0) 

486 

487 cmp_zero = builder.icmp_unsigned('==', x, ZERO) 

488 cmp_pos = builder.icmp_signed('>', x, ZERO) 

489 

490 presult = cgutils.alloca_once(builder, x.type) 

491 

492 bb_zero = builder.append_basic_block(".zero") 

493 bb_postest = builder.append_basic_block(".postest") 

494 bb_pos = builder.append_basic_block(".pos") 

495 bb_neg = builder.append_basic_block(".neg") 

496 bb_exit = builder.append_basic_block(".exit") 

497 

498 builder.cbranch(cmp_zero, bb_zero, bb_postest) 

499 

500 with builder.goto_block(bb_zero): 

501 builder.store(ZERO, presult) 

502 builder.branch(bb_exit) 

503 

504 with builder.goto_block(bb_postest): 

505 builder.cbranch(cmp_pos, bb_pos, bb_neg) 

506 

507 with builder.goto_block(bb_pos): 

508 builder.store(POS, presult) 

509 builder.branch(bb_exit) 

510 

511 with builder.goto_block(bb_neg): 

512 builder.store(NEG, presult) 

513 builder.branch(bb_exit) 

514 

515 builder.position_at_end(bb_exit) 

516 res = builder.load(presult) 

517 return impl_ret_untracked(context, builder, sig.return_type, res) 

518 

519 

520def bool_negate_impl(context, builder, sig, args): 

521 [typ] = sig.args 

522 [val] = args 

523 res = context.cast(builder, val, typ, sig.return_type) 

524 res = builder.neg(res) 

525 return impl_ret_untracked(context, builder, sig.return_type, res) 

526 

527 

528def bool_unary_positive_impl(context, builder, sig, args): 

529 [typ] = sig.args 

530 [val] = args 

531 res = context.cast(builder, val, typ, sig.return_type) 

532 return impl_ret_untracked(context, builder, sig.return_type, res) 

533 

534 

535# lower_builtin(operator.eq, types.boolean, types.boolean)(int_eq_impl) 

536# lower_builtin(operator.ne, types.boolean, types.boolean)(int_ne_impl) 

537# lower_builtin(operator.lt, types.boolean, types.boolean)(int_ult_impl) 

538# lower_builtin(operator.le, types.boolean, types.boolean)(int_ule_impl) 

539# lower_builtin(operator.gt, types.boolean, types.boolean)(int_ugt_impl) 

540# lower_builtin(operator.ge, types.boolean, types.boolean)(int_uge_impl) 

541# lower_builtin(operator.neg, types.boolean)(bool_negate_impl) 

542# lower_builtin(operator.pos, types.boolean)(bool_unary_positive_impl) 

543 

544 

545# def _implement_integer_operators(): 

546# ty = types.Integer 

547 

548# lower_builtin(operator.add, ty, ty)(int_add_impl) 

549# lower_builtin(operator.iadd, ty, ty)(int_add_impl) 

550# lower_builtin(operator.sub, ty, ty)(int_sub_impl) 

551# lower_builtin(operator.isub, ty, ty)(int_sub_impl) 

552# lower_builtin(operator.mul, ty, ty)(int_mul_impl) 

553# lower_builtin(operator.imul, ty, ty)(int_mul_impl) 

554# lower_builtin(operator.eq, ty, ty)(int_eq_impl) 

555# lower_builtin(operator.ne, ty, ty)(int_ne_impl) 

556 

557# lower_builtin(operator.lshift, ty, ty)(int_shl_impl) 

558# lower_builtin(operator.ilshift, ty, ty)(int_shl_impl) 

559# lower_builtin(operator.rshift, ty, ty)(int_shr_impl) 

560# lower_builtin(operator.irshift, ty, ty)(int_shr_impl) 

561 

562# lower_builtin(operator.neg, ty)(int_negate_impl) 

563# lower_builtin(operator.pos, ty)(int_positive_impl) 

564 

565# lower_builtin(operator.pow, ty, ty)(int_power_impl) 

566# lower_builtin(operator.ipow, ty, ty)(int_power_impl) 

567# lower_builtin(pow, ty, ty)(int_power_impl) 

568 

569# for ty in types.unsigned_domain: 

570# lower_builtin(operator.lt, ty, ty)(int_ult_impl) 

571# lower_builtin(operator.le, ty, ty)(int_ule_impl) 

572# lower_builtin(operator.gt, ty, ty)(int_ugt_impl) 

573# lower_builtin(operator.ge, ty, ty)(int_uge_impl) 

574# lower_builtin(operator.pow, types.Float, ty)(int_power_impl) 

575# lower_builtin(operator.ipow, types.Float, ty)(int_power_impl) 

576# lower_builtin(pow, types.Float, ty)(int_power_impl) 

577# lower_builtin(abs, ty)(uint_abs_impl) 

578 

579# lower_builtin(operator.lt, types.IntegerLiteral, types.IntegerLiteral)(int_slt_impl) 

580# lower_builtin(operator.gt, types.IntegerLiteral, types.IntegerLiteral)(int_slt_impl) 

581# lower_builtin(operator.le, types.IntegerLiteral, types.IntegerLiteral)(int_slt_impl) 

582# lower_builtin(operator.ge, types.IntegerLiteral, types.IntegerLiteral)(int_slt_impl) 

583# for ty in types.signed_domain: 

584# lower_builtin(operator.lt, ty, ty)(int_slt_impl) 

585# lower_builtin(operator.le, ty, ty)(int_sle_impl) 

586# lower_builtin(operator.gt, ty, ty)(int_sgt_impl) 

587# lower_builtin(operator.ge, ty, ty)(int_sge_impl) 

588# lower_builtin(operator.pow, types.Float, ty)(int_power_impl) 

589# lower_builtin(operator.ipow, types.Float, ty)(int_power_impl) 

590# lower_builtin(pow, types.Float, ty)(int_power_impl) 

591# lower_builtin(abs, ty)(int_abs_impl) 

592 

593# def _implement_bitwise_operators(): 

594# for ty in (types.Boolean, types.Integer): 

595# lower_builtin(operator.and_, ty, ty)(int_and_impl) 

596# lower_builtin(operator.iand, ty, ty)(int_and_impl) 

597# lower_builtin(operator.or_, ty, ty)(int_or_impl) 

598# lower_builtin(operator.ior, ty, ty)(int_or_impl) 

599# lower_builtin(operator.xor, ty, ty)(int_xor_impl) 

600# lower_builtin(operator.ixor, ty, ty)(int_xor_impl) 

601 

602# lower_builtin(operator.invert, ty)(int_invert_impl) 

603 

604# _implement_integer_operators() 

605 

606# _implement_bitwise_operators() 

607 

608 

609def real_add_impl(context, builder, sig, args): 

610 res = builder.fadd(*args) 

611 return impl_ret_untracked(context, builder, sig.return_type, res) 

612 

613 

614def real_sub_impl(context, builder, sig, args): 

615 res = builder.fsub(*args) 

616 return impl_ret_untracked(context, builder, sig.return_type, res) 

617 

618 

619def real_mul_impl(context, builder, sig, args): 

620 res = builder.fmul(*args) 

621 return impl_ret_untracked(context, builder, sig.return_type, res) 

622 

623 

624def real_div_impl(context, builder, sig, args): 

625 with cgutils.if_zero(builder, args[1]): 

626 context.error_model.fp_zero_division(builder, ("division by zero",)) 

627 res = builder.fdiv(*args) 

628 return impl_ret_untracked(context, builder, sig.return_type, res) 

629 

630 

631def real_divmod(context, builder, x, y): 

632 assert x.type == y.type 

633 floatty = x.type 

634 

635 module = builder.module 

636 fname = context.mangler(".numba.python.rem", [x.type]) 

637 fnty = ir.FunctionType(floatty, (floatty, floatty, ir.PointerType(floatty))) 

638 fn = cgutils.get_or_insert_function(module, fnty, fname) 

639 

640 if fn.is_declaration: 

641 fn.linkage = 'linkonce_odr' 

642 fnbuilder = ir.IRBuilder(fn.append_basic_block('entry')) 

643 fx, fy, pmod = fn.args 

644 div, mod = real_divmod_func_body(context, fnbuilder, fx, fy) 

645 fnbuilder.store(mod, pmod) 

646 fnbuilder.ret(div) 

647 

648 pmod = cgutils.alloca_once(builder, floatty) 

649 quotient = builder.call(fn, (x, y, pmod)) 

650 return quotient, builder.load(pmod) 

651 

652 

653def real_divmod_func_body(context, builder, vx, wx): 

654 # Reference Objects/floatobject.c 

655 # 

656 # float_divmod(PyObject *v, PyObject *w) 

657 # { 

658 # double vx, wx; 

659 # double div, mod, floordiv; 

660 # CONVERT_TO_DOUBLE(v, vx); 

661 # CONVERT_TO_DOUBLE(w, wx); 

662 # mod = fmod(vx, wx); 

663 # /* fmod is typically exact, so vx-mod is *mathematically* an 

664 # exact multiple of wx. But this is fp arithmetic, and fp 

665 # vx - mod is an approximation; the result is that div may 

666 # not be an exact integral value after the division, although 

667 # it will always be very close to one. 

668 # */ 

669 # div = (vx - mod) / wx; 

670 # if (mod) { 

671 # /* ensure the remainder has the same sign as the denominator */ 

672 # if ((wx < 0) != (mod < 0)) { 

673 # mod += wx; 

674 # div -= 1.0; 

675 # } 

676 # } 

677 # else { 

678 # /* the remainder is zero, and in the presence of signed zeroes 

679 # fmod returns different results across platforms; ensure 

680 # it has the same sign as the denominator; we'd like to do 

681 # "mod = wx * 0.0", but that may get optimized away */ 

682 # mod *= mod; /* hide "mod = +0" from optimizer */ 

683 # if (wx < 0.0) 

684 # mod = -mod; 

685 # } 

686 # /* snap quotient to nearest integral value */ 

687 # if (div) { 

688 # floordiv = floor(div); 

689 # if (div - floordiv > 0.5) 

690 # floordiv += 1.0; 

691 # } 

692 # else { 

693 # /* div is zero - get the same sign as the true quotient */ 

694 # div *= div; /* hide "div = +0" from optimizers */ 

695 # floordiv = div * vx / wx; /* zero w/ sign of vx/wx */ 

696 # } 

697 # return Py_BuildValue("(dd)", floordiv, mod); 

698 # } 

699 pmod = cgutils.alloca_once(builder, vx.type) 

700 pdiv = cgutils.alloca_once(builder, vx.type) 

701 pfloordiv = cgutils.alloca_once(builder, vx.type) 

702 

703 mod = builder.frem(vx, wx) 

704 div = builder.fdiv(builder.fsub(vx, mod), wx) 

705 

706 builder.store(mod, pmod) 

707 builder.store(div, pdiv) 

708 

709 # Note the use of negative zero for proper negating with `ZERO - x` 

710 ZERO = vx.type(0.0) 

711 NZERO = vx.type(-0.0) 

712 ONE = vx.type(1.0) 

713 mod_istrue = builder.fcmp_unordered('!=', mod, ZERO) 

714 wx_ltz = builder.fcmp_ordered('<', wx, ZERO) 

715 mod_ltz = builder.fcmp_ordered('<', mod, ZERO) 

716 

717 with builder.if_else(mod_istrue, likely=True) as (if_nonzero_mod, if_zero_mod): 

718 with if_nonzero_mod: 

719 # `mod` is non-zero or NaN 

720 # Ensure the remainder has the same sign as the denominator 

721 wx_ltz_ne_mod_ltz = builder.icmp_unsigned('!=', wx_ltz, mod_ltz) 

722 

723 with builder.if_then(wx_ltz_ne_mod_ltz): 

724 builder.store(builder.fsub(div, ONE), pdiv) 

725 builder.store(builder.fadd(mod, wx), pmod) 

726 

727 with if_zero_mod: 

728 # `mod` is zero, select the proper sign depending on 

729 # the denominator's sign 

730 mod = builder.select(wx_ltz, NZERO, ZERO) 

731 builder.store(mod, pmod) 

732 

733 del mod, div 

734 

735 div = builder.load(pdiv) 

736 div_istrue = builder.fcmp_ordered('!=', div, ZERO) 

737 

738 with builder.if_then(div_istrue): 

739 realtypemap = {'float': types.float32, 

740 'double': types.float64} 

741 realtype = realtypemap[str(wx.type)] 

742 floorfn = context.get_function(math.floor, 

743 typing.signature(realtype, realtype)) 

744 floordiv = floorfn(builder, [div]) 

745 floordivdiff = builder.fsub(div, floordiv) 

746 floordivincr = builder.fadd(floordiv, ONE) 

747 HALF = Constant(wx.type, 0.5) 

748 pred = builder.fcmp_ordered('>', floordivdiff, HALF) 

749 floordiv = builder.select(pred, floordivincr, floordiv) 

750 builder.store(floordiv, pfloordiv) 

751 

752 with cgutils.ifnot(builder, div_istrue): 

753 div = builder.fmul(div, div) 

754 builder.store(div, pdiv) 

755 floordiv = builder.fdiv(builder.fmul(div, vx), wx) 

756 builder.store(floordiv, pfloordiv) 

757 

758 return builder.load(pfloordiv), builder.load(pmod) 

759 

760 

761# @lower_builtin(divmod, types.Float, types.Float) 

762def real_divmod_impl(context, builder, sig, args, loc=None): 

763 x, y = args 

764 quot = cgutils.alloca_once(builder, x.type, name="quot") 

765 rem = cgutils.alloca_once(builder, x.type, name="rem") 

766 

767 with builder.if_else(cgutils.is_scalar_zero(builder, y), likely=False 

768 ) as (if_zero, if_non_zero): 

769 with if_zero: 

770 if not context.error_model.fp_zero_division( 

771 builder, ("modulo by zero",), loc): 

772 # No exception raised => compute the nan result, 

773 # and set the FP exception word for Numpy warnings. 

774 q = builder.fdiv(x, y) 

775 r = builder.frem(x, y) 

776 builder.store(q, quot) 

777 builder.store(r, rem) 

778 with if_non_zero: 

779 q, r = real_divmod(context, builder, x, y) 

780 builder.store(q, quot) 

781 builder.store(r, rem) 

782 

783 return cgutils.pack_array(builder, 

784 (builder.load(quot), builder.load(rem))) 

785 

786 

787def real_mod_impl(context, builder, sig, args, loc=None): 

788 x, y = args 

789 res = cgutils.alloca_once(builder, x.type) 

790 with builder.if_else(cgutils.is_scalar_zero(builder, y), likely=False 

791 ) as (if_zero, if_non_zero): 

792 with if_zero: 

793 if not context.error_model.fp_zero_division( 

794 builder, ("modulo by zero",), loc): 

795 # No exception raised => compute the nan result, 

796 # and set the FP exception word for Numpy warnings. 

797 rem = builder.frem(x, y) 

798 builder.store(rem, res) 

799 with if_non_zero: 

800 _, rem = real_divmod(context, builder, x, y) 

801 builder.store(rem, res) 

802 return impl_ret_untracked(context, builder, sig.return_type, 

803 builder.load(res)) 

804 

805 

806def real_floordiv_impl(context, builder, sig, args, loc=None): 

807 x, y = args 

808 res = cgutils.alloca_once(builder, x.type) 

809 with builder.if_else(cgutils.is_scalar_zero(builder, y), likely=False 

810 ) as (if_zero, if_non_zero): 

811 with if_zero: 

812 if not context.error_model.fp_zero_division( 

813 builder, ("division by zero",), loc): 

814 # No exception raised => compute the +/-inf or nan result, 

815 # and set the FP exception word for Numpy warnings. 

816 quot = builder.fdiv(x, y) 

817 builder.store(quot, res) 

818 with if_non_zero: 

819 quot, _ = real_divmod(context, builder, x, y) 

820 builder.store(quot, res) 

821 return impl_ret_untracked(context, builder, sig.return_type, 

822 builder.load(res)) 

823 

824 

825def real_power_impl(context, builder, sig, args): 

826 x, y = args 

827 module = builder.module 

828 if context.implement_powi_as_math_call: 

829 imp = context.get_function(math.pow, sig) 

830 res = imp(builder, args) 

831 else: 

832 fn = module.declare_intrinsic('llvm.pow', [y.type]) 

833 res = builder.call(fn, (x, y)) 

834 return impl_ret_untracked(context, builder, sig.return_type, res) 

835 

836 

837def real_lt_impl(context, builder, sig, args): 

838 res = builder.fcmp_ordered('<', *args) 

839 return impl_ret_untracked(context, builder, sig.return_type, res) 

840 

841 

842def real_le_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_gt_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_ge_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_eq_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_ne_impl(context, builder, sig, args): 

863 res = builder.fcmp_unordered('!=', *args) 

864 return impl_ret_untracked(context, builder, sig.return_type, res) 

865 

866 

867def real_abs_impl(context, builder, sig, args): 

868 [ty] = sig.args 

869 sig = typing.signature(ty, ty) 

870 impl = context.get_function(math.fabs, sig) 

871 return impl(builder, args) 

872 

873 

874def real_negate_impl(context, builder, sig, args): 

875 from numba.cpython import mathimpl 

876 res = mathimpl.negate_real(builder, args[0]) 

877 return impl_ret_untracked(context, builder, sig.return_type, res) 

878 

879 

880def real_positive_impl(context, builder, sig, args): 

881 [typ] = sig.args 

882 [val] = args 

883 res = context.cast(builder, val, typ, sig.return_type) 

884 return impl_ret_untracked(context, builder, sig.return_type, res) 

885 

886 

887def real_sign_impl(context, builder, sig, args): 

888 """ 

889 np.sign(float) 

890 """ 

891 [x] = args 

892 POS = Constant(x.type, 1) 

893 NEG = Constant(x.type, -1) 

894 ZERO = Constant(x.type, 0) 

895 

896 presult = cgutils.alloca_once(builder, x.type) 

897 

898 is_pos = builder.fcmp_ordered('>', x, ZERO) 

899 is_neg = builder.fcmp_ordered('<', x, ZERO) 

900 

901 with builder.if_else(is_pos) as (gt_zero, not_gt_zero): 

902 with gt_zero: 

903 builder.store(POS, presult) 

904 with not_gt_zero: 

905 with builder.if_else(is_neg) as (lt_zero, not_lt_zero): 

906 with lt_zero: 

907 builder.store(NEG, presult) 

908 with not_lt_zero: 

909 # For both NaN and 0, the result of sign() is simply 

910 # the input value. 

911 builder.store(x, presult) 

912 

913 res = builder.load(presult) 

914 return impl_ret_untracked(context, builder, sig.return_type, res) 

915 

916 

917# ty = types.Float 

918 

919# lower_builtin(operator.add, ty, ty)(real_add_impl) 

920# lower_builtin(operator.iadd, ty, ty)(real_add_impl) 

921# lower_builtin(operator.sub, ty, ty)(real_sub_impl) 

922# lower_builtin(operator.isub, ty, ty)(real_sub_impl) 

923# lower_builtin(operator.mul, ty, ty)(real_mul_impl) 

924# lower_builtin(operator.imul, ty, ty)(real_mul_impl) 

925# lower_builtin(operator.floordiv, ty, ty)(real_floordiv_impl) 

926# lower_builtin(operator.ifloordiv, ty, ty)(real_floordiv_impl) 

927# lower_builtin(operator.truediv, ty, ty)(real_div_impl) 

928# lower_builtin(operator.itruediv, ty, ty)(real_div_impl) 

929# lower_builtin(operator.mod, ty, ty)(real_mod_impl) 

930# lower_builtin(operator.imod, ty, ty)(real_mod_impl) 

931# lower_builtin(operator.pow, ty, ty)(real_power_impl) 

932# lower_builtin(operator.ipow, ty, ty)(real_power_impl) 

933# lower_builtin(pow, ty, ty)(real_power_impl) 

934 

935# lower_builtin(operator.eq, ty, ty)(real_eq_impl) 

936# lower_builtin(operator.ne, ty, ty)(real_ne_impl) 

937# lower_builtin(operator.lt, ty, ty)(real_lt_impl) 

938# lower_builtin(operator.le, ty, ty)(real_le_impl) 

939# lower_builtin(operator.gt, ty, ty)(real_gt_impl) 

940# lower_builtin(operator.ge, ty, ty)(real_ge_impl) 

941 

942# lower_builtin(abs, ty)(real_abs_impl) 

943 

944# lower_builtin(operator.neg, ty)(real_negate_impl) 

945# lower_builtin(operator.pos, ty)(real_positive_impl) 

946 

947# del ty 

948 

949 

950# @lower_getattr(types.Complex, "real") 

951def complex_real_impl(context, builder, typ, value): 

952 cplx = context.make_complex(builder, typ, value=value) 

953 res = cplx.real 

954 return impl_ret_untracked(context, builder, typ, res) 

955 

956# @lower_getattr(types.Complex, "imag") 

957def complex_imag_impl(context, builder, typ, value): 

958 cplx = context.make_complex(builder, typ, value=value) 

959 res = cplx.imag 

960 return impl_ret_untracked(context, builder, typ, res) 

961 

962# @lower_builtin("complex.conjugate", types.Complex) 

963def complex_conjugate_impl(context, builder, sig, args): 

964 from numba.cpython import mathimpl 

965 z = context.make_complex(builder, sig.args[0], args[0]) 

966 z.imag = mathimpl.negate_real(builder, z.imag) 

967 res = z._getvalue() 

968 return impl_ret_untracked(context, builder, sig.return_type, res) 

969 

970def real_real_impl(context, builder, typ, value): 

971 return impl_ret_untracked(context, builder, typ, value) 

972 

973def real_imag_impl(context, builder, typ, value): 

974 res = cgutils.get_null_value(value.type) 

975 return impl_ret_untracked(context, builder, typ, res) 

976 

977def real_conjugate_impl(context, builder, sig, args): 

978 return impl_ret_untracked(context, builder, sig.return_type, args[0]) 

979 

980# for cls in (types.Float, types.Integer): 

981# lower_getattr(cls, "real")(real_real_impl) 

982# lower_getattr(cls, "imag")(real_imag_impl) 

983# lower_builtin("complex.conjugate", cls)(real_conjugate_impl) 

984 

985 

986# @lower_builtin(operator.pow, types.Complex, types.Complex) 

987# @lower_builtin(operator.ipow, types.Complex, types.Complex) 

988# @lower_builtin(pow, types.Complex, types.Complex) 

989def complex_power_impl(context, builder, sig, args): 

990 [ca, cb] = args 

991 ty = sig.args[0] 

992 fty = ty.underlying_float 

993 a = context.make_helper(builder, ty, value=ca) 

994 b = context.make_helper(builder, ty, value=cb) 

995 c = context.make_helper(builder, ty) 

996 module = builder.module 

997 pa = a._getpointer() 

998 pb = b._getpointer() 

999 pc = c._getpointer() 

1000 

1001 # Optimize for square because cpow loses a lot of precision 

1002 TWO = context.get_constant(fty, 2) 

1003 ZERO = context.get_constant(fty, 0) 

1004 

1005 b_real_is_two = builder.fcmp_ordered('==', b.real, TWO) 

1006 b_imag_is_zero = builder.fcmp_ordered('==', b.imag, ZERO) 

1007 b_is_two = builder.and_(b_real_is_two, b_imag_is_zero) 

1008 

1009 with builder.if_else(b_is_two) as (then, otherwise): 

1010 with then: 

1011 # Lower as multiplication 

1012 res = complex_mul_impl(context, builder, sig, (ca, ca)) 

1013 cres = context.make_helper(builder, ty, value=res) 

1014 c.real = cres.real 

1015 c.imag = cres.imag 

1016 

1017 with otherwise: 

1018 # Lower with call to external function 

1019 func_name = { 

1020 types.complex64: "numba_cpowf", 

1021 types.complex128: "numba_cpow", 

1022 }[ty] 

1023 fnty = ir.FunctionType(ir.VoidType(), [pa.type] * 3) 

1024 cpow = cgutils.get_or_insert_function(module, fnty, func_name) 

1025 builder.call(cpow, (pa, pb, pc)) 

1026 

1027 res = builder.load(pc) 

1028 return impl_ret_untracked(context, builder, sig.return_type, res) 

1029 

1030def complex_add_impl(context, builder, sig, args): 

1031 [cx, cy] = args 

1032 ty = sig.args[0] 

1033 x = context.make_complex(builder, ty, value=cx) 

1034 y = context.make_complex(builder, ty, value=cy) 

1035 z = context.make_complex(builder, ty) 

1036 a = x.real 

1037 b = x.imag 

1038 c = y.real 

1039 d = y.imag 

1040 z.real = builder.fadd(a, c) 

1041 z.imag = builder.fadd(b, d) 

1042 res = z._getvalue() 

1043 return impl_ret_untracked(context, builder, sig.return_type, res) 

1044 

1045 

1046def complex_sub_impl(context, builder, sig, args): 

1047 [cx, cy] = args 

1048 ty = sig.args[0] 

1049 x = context.make_complex(builder, ty, value=cx) 

1050 y = context.make_complex(builder, ty, value=cy) 

1051 z = context.make_complex(builder, ty) 

1052 a = x.real 

1053 b = x.imag 

1054 c = y.real 

1055 d = y.imag 

1056 z.real = builder.fsub(a, c) 

1057 z.imag = builder.fsub(b, d) 

1058 res = z._getvalue() 

1059 return impl_ret_untracked(context, builder, sig.return_type, res) 

1060 

1061 

1062def complex_mul_impl(context, builder, sig, args): 

1063 """ 

1064 (a+bi)(c+di)=(ac-bd)+i(ad+bc) 

1065 """ 

1066 [cx, cy] = args 

1067 ty = sig.args[0] 

1068 x = context.make_complex(builder, ty, value=cx) 

1069 y = context.make_complex(builder, ty, value=cy) 

1070 z = context.make_complex(builder, ty) 

1071 a = x.real 

1072 b = x.imag 

1073 c = y.real 

1074 d = y.imag 

1075 ac = builder.fmul(a, c) 

1076 bd = builder.fmul(b, d) 

1077 ad = builder.fmul(a, d) 

1078 bc = builder.fmul(b, c) 

1079 z.real = builder.fsub(ac, bd) 

1080 z.imag = builder.fadd(ad, bc) 

1081 res = z._getvalue() 

1082 return impl_ret_untracked(context, builder, sig.return_type, res) 

1083 

1084 

1085NAN = float('nan') 

1086 

1087def complex_div_impl(context, builder, sig, args): 

1088 def complex_div(a, b): 

1089 # This is CPython's algorithm (in _Py_c_quot()). 

1090 areal = a.real 

1091 aimag = a.imag 

1092 breal = b.real 

1093 bimag = b.imag 

1094 if not breal and not bimag: 

1095 raise ZeroDivisionError("complex division by zero") 

1096 if abs(breal) >= abs(bimag): 

1097 # Divide tops and bottom by b.real 

1098 if not breal: 

1099 return complex(NAN, NAN) 

1100 ratio = bimag / breal 

1101 denom = breal + bimag * ratio 

1102 return complex( 

1103 (areal + aimag * ratio) / denom, 

1104 (aimag - areal * ratio) / denom) 

1105 else: 

1106 # Divide tops and bottom by b.imag 

1107 if not bimag: 

1108 return complex(NAN, NAN) 

1109 ratio = breal / bimag 

1110 denom = breal * ratio + bimag 

1111 return complex( 

1112 (a.real * ratio + a.imag) / denom, 

1113 (a.imag * ratio - a.real) / denom) 

1114 

1115 res = context.compile_internal(builder, complex_div, sig, args) 

1116 return impl_ret_untracked(context, builder, sig.return_type, res) 

1117 

1118 

1119def complex_negate_impl(context, builder, sig, args): 

1120 from numba.cpython import mathimpl 

1121 [typ] = sig.args 

1122 [val] = args 

1123 cmplx = context.make_complex(builder, typ, value=val) 

1124 res = context.make_complex(builder, typ) 

1125 res.real = mathimpl.negate_real(builder, cmplx.real) 

1126 res.imag = mathimpl.negate_real(builder, cmplx.imag) 

1127 res = res._getvalue() 

1128 return impl_ret_untracked(context, builder, sig.return_type, res) 

1129 

1130 

1131def complex_positive_impl(context, builder, sig, args): 

1132 [val] = args 

1133 return impl_ret_untracked(context, builder, sig.return_type, val) 

1134 

1135 

1136def complex_eq_impl(context, builder, sig, args): 

1137 [cx, cy] = args 

1138 typ = sig.args[0] 

1139 x = context.make_complex(builder, typ, value=cx) 

1140 y = context.make_complex(builder, typ, value=cy) 

1141 

1142 reals_are_eq = builder.fcmp_ordered('==', x.real, y.real) 

1143 imags_are_eq = builder.fcmp_ordered('==', x.imag, y.imag) 

1144 res = builder.and_(reals_are_eq, imags_are_eq) 

1145 return impl_ret_untracked(context, builder, sig.return_type, res) 

1146 

1147 

1148def complex_ne_impl(context, builder, sig, args): 

1149 [cx, cy] = args 

1150 typ = sig.args[0] 

1151 x = context.make_complex(builder, typ, value=cx) 

1152 y = context.make_complex(builder, typ, value=cy) 

1153 

1154 reals_are_ne = builder.fcmp_unordered('!=', x.real, y.real) 

1155 imags_are_ne = builder.fcmp_unordered('!=', x.imag, y.imag) 

1156 res = builder.or_(reals_are_ne, imags_are_ne) 

1157 return impl_ret_untracked(context, builder, sig.return_type, res) 

1158 

1159 

1160def complex_abs_impl(context, builder, sig, args): 

1161 """ 

1162 abs(z) := hypot(z.real, z.imag) 

1163 """ 

1164 def complex_abs(z): 

1165 return math.hypot(z.real, z.imag) 

1166 

1167 res = context.compile_internal(builder, complex_abs, sig, args) 

1168 return impl_ret_untracked(context, builder, sig.return_type, res) 

1169 

1170 

1171# ty = types.Complex 

1172 

1173# lower_builtin(operator.add, ty, ty)(complex_add_impl) 

1174# lower_builtin(operator.iadd, ty, ty)(complex_add_impl) 

1175# lower_builtin(operator.sub, ty, ty)(complex_sub_impl) 

1176# lower_builtin(operator.isub, ty, ty)(complex_sub_impl) 

1177# lower_builtin(operator.mul, ty, ty)(complex_mul_impl) 

1178# lower_builtin(operator.imul, ty, ty)(complex_mul_impl) 

1179# lower_builtin(operator.truediv, ty, ty)(complex_div_impl) 

1180# lower_builtin(operator.itruediv, ty, ty)(complex_div_impl) 

1181# lower_builtin(operator.neg, ty)(complex_negate_impl) 

1182# lower_builtin(operator.pos, ty)(complex_positive_impl) 

1183# # Complex modulo is deprecated in python3 

1184 

1185# lower_builtin(operator.eq, ty, ty)(complex_eq_impl) 

1186# lower_builtin(operator.ne, ty, ty)(complex_ne_impl) 

1187 

1188# lower_builtin(abs, ty)(complex_abs_impl) 

1189 

1190# del ty 

1191 

1192 

1193# @lower_builtin("number.item", types.Boolean) 

1194# @lower_builtin("number.item", types.Number) 

1195def number_item_impl(context, builder, sig, args): 

1196 """ 

1197 The no-op .item() method on booleans and numbers. 

1198 """ 

1199 return args[0] 

1200 

1201 

1202#------------------------------------------------------------------------------ 

1203 

1204 

1205def number_not_impl(context, builder, sig, args): 

1206 [typ] = sig.args 

1207 [val] = args 

1208 istrue = context.cast(builder, val, typ, sig.return_type) 

1209 res = builder.not_(istrue) 

1210 return impl_ret_untracked(context, builder, sig.return_type, res) 

1211 

1212# @lower_builtin(bool, types.Boolean) 

1213def bool_as_bool(context, builder, sig, args): 

1214 [val] = args 

1215 return val 

1216 

1217# @lower_builtin(bool, types.Integer) 

1218def int_as_bool(context, builder, sig, args): 

1219 [val] = args 

1220 return builder.icmp_unsigned('!=', val, Constant(val.type, 0)) 

1221 

1222# @lower_builtin(bool, types.Float) 

1223def float_as_bool(context, builder, sig, args): 

1224 [val] = args 

1225 return builder.fcmp_unordered('!=', val, Constant(val.type, 0.0)) 

1226 

1227# @lower_builtin(bool, types.Complex) 

1228def complex_as_bool(context, builder, sig, args): 

1229 [typ] = sig.args 

1230 [val] = args 

1231 cmplx = context.make_complex(builder, typ, val) 

1232 real, imag = cmplx.real, cmplx.imag 

1233 zero = Constant(real.type, 0.0) 

1234 real_istrue = builder.fcmp_unordered('!=', real, zero) 

1235 imag_istrue = builder.fcmp_unordered('!=', imag, zero) 

1236 return builder.or_(real_istrue, imag_istrue) 

1237 

1238 

1239# for ty in (types.Integer, types.Float, types.Complex): 

1240# lower_builtin(operator.not_, ty)(number_not_impl) 

1241 

1242# lower_builtin(operator.not_, types.boolean)(number_not_impl) 

1243 

1244 

1245#------------------------------------------------------------------------------ 

1246# Hashing numbers, see hashing.py 

1247 

1248#------------------------------------------------------------------------------- 

1249# Implicit casts between numerics 

1250 

1251# @lower_cast(types.IntegerLiteral, types.Integer) 

1252# @lower_cast(types.IntegerLiteral, types.Float) 

1253# @lower_cast(types.IntegerLiteral, types.Complex) 

1254def literal_int_to_number(context, builder, fromty, toty, val): 

1255 lit = context.get_constant_generic( 

1256 builder, 

1257 fromty.literal_type, 

1258 fromty.literal_value, 

1259 ) 

1260 return context.cast(builder, lit, fromty.literal_type, toty) 

1261 

1262 

1263# @lower_cast(types.Integer, types.Integer) 

1264def integer_to_integer(context, builder, fromty, toty, val): 

1265 if toty.bitwidth == fromty.bitwidth: 

1266 # Just a change of signedness 

1267 return val 

1268 elif toty.bitwidth < fromty.bitwidth: 

1269 # Downcast 

1270 return builder.trunc(val, context.get_value_type(toty)) 

1271 elif fromty.signed: 

1272 # Signed upcast 

1273 return builder.sext(val, context.get_value_type(toty)) 

1274 else: 

1275 # Unsigned upcast 

1276 return builder.zext(val, context.get_value_type(toty)) 

1277 

1278# @lower_cast(types.Integer, types.voidptr) 

1279def integer_to_voidptr(context, builder, fromty, toty, val): 

1280 return builder.inttoptr(val, context.get_value_type(toty)) 

1281 

1282# @lower_cast(types.Float, types.Float) 

1283def float_to_float(context, builder, fromty, toty, val): 

1284 lty = context.get_value_type(toty) 

1285 if fromty.bitwidth < toty.bitwidth: 

1286 return builder.fpext(val, lty) 

1287 else: 

1288 return builder.fptrunc(val, lty) 

1289 

1290# @lower_cast(types.Integer, types.Float) 

1291def integer_to_float(context, builder, fromty, toty, val): 

1292 lty = context.get_value_type(toty) 

1293 if fromty.signed: 

1294 return builder.sitofp(val, lty) 

1295 else: 

1296 return builder.uitofp(val, lty) 

1297 

1298# @lower_cast(types.Float, types.Integer) 

1299def float_to_integer(context, builder, fromty, toty, val): 

1300 lty = context.get_value_type(toty) 

1301 if toty.signed: 

1302 return builder.fptosi(val, lty) 

1303 else: 

1304 return builder.fptoui(val, lty) 

1305 

1306# @lower_cast(types.Float, types.Complex) 

1307# @lower_cast(types.Integer, types.Complex) 

1308def non_complex_to_complex(context, builder, fromty, toty, val): 

1309 real = context.cast(builder, val, fromty, toty.underlying_float) 

1310 imag = context.get_constant(toty.underlying_float, 0) 

1311 

1312 cmplx = context.make_complex(builder, toty) 

1313 cmplx.real = real 

1314 cmplx.imag = imag 

1315 return cmplx._getvalue() 

1316 

1317# @lower_cast(types.Complex, types.Complex) 

1318def complex_to_complex(context, builder, fromty, toty, val): 

1319 srcty = fromty.underlying_float 

1320 dstty = toty.underlying_float 

1321 

1322 src = context.make_complex(builder, fromty, value=val) 

1323 dst = context.make_complex(builder, toty) 

1324 dst.real = context.cast(builder, src.real, srcty, dstty) 

1325 dst.imag = context.cast(builder, src.imag, srcty, dstty) 

1326 return dst._getvalue() 

1327 

1328# @lower_cast(types.Any, types.Boolean) 

1329def any_to_boolean(context, builder, fromty, toty, val): 

1330 return context.is_true(builder, fromty, val) 

1331 

1332# @lower_cast(types.Boolean, types.Number) 

1333def boolean_to_any(context, builder, fromty, toty, val): 

1334 # Casting from boolean to anything first casts to int32 

1335 asint = builder.zext(val, ir.IntType(32)) 

1336 return context.cast(builder, asint, types.int32, toty) 

1337 

1338# @lower_cast(types.IntegerLiteral, types.Boolean) 

1339# @lower_cast(types.BooleanLiteral, types.Boolean) 

1340def literal_int_to_boolean(context, builder, fromty, toty, val): 

1341 lit = context.get_constant_generic( 

1342 builder, 

1343 fromty.literal_type, 

1344 fromty.literal_value, 

1345 ) 

1346 return context.is_true(builder, fromty.literal_type, lit) 

1347 

1348#------------------------------------------------------------------------------- 

1349# Constants 

1350 

1351# @lower_constant(types.Complex) 

1352def constant_complex(context, builder, ty, pyval): 

1353 fty = ty.underlying_float 

1354 real = context.get_constant_generic(builder, fty, pyval.real) 

1355 imag = context.get_constant_generic(builder, fty, pyval.imag) 

1356 return Constant.literal_struct((real, imag)) 

1357 

1358# @lower_constant(types.Integer) 

1359# @lower_constant(types.Float) 

1360# @lower_constant(types.Boolean) 

1361def constant_integer(context, builder, ty, pyval): 

1362 # See https://github.com/numba/numba/issues/6979 

1363 # llvmlite ir.IntType specialises the formatting of the constant for a 

1364 # cpython bool. A NumPy np.bool_ is not a cpython bool so force it to be one 

1365 # so that the constant renders correctly! 

1366 if isinstance(pyval, np.bool_): 

1367 pyval = bool(pyval) 

1368 lty = context.get_value_type(ty) 

1369 return lty(pyval) 

1370 

1371 

1372#------------------------------------------------------------------------------- 

1373# View 

1374 

1375def scalar_view(scalar, viewty): 

1376 """ Typing for the np scalar 'view' method. """ 

1377 if (isinstance(scalar, (types.Float, types.Integer)) 

1378 and isinstance(viewty, types.abstract.DTypeSpec)): 

1379 if scalar.bitwidth != viewty.dtype.bitwidth: 

1380 raise errors.TypingError( 

1381 "Changing the dtype of a 0d array is only supported if the " 

1382 "itemsize is unchanged") 

1383 

1384 def impl(scalar, viewty): 

1385 return viewer(scalar, viewty) 

1386 return impl 

1387 

1388 

1389# overload_method(types.Float, 'view')(scalar_view) 

1390# overload_method(types.Integer, 'view')(scalar_view)