numba-cuda 0.19.1__py3-none-any.whl → 0.20.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of numba-cuda might be problematic. Click here for more details.

Files changed (171) hide show
  1. numba_cuda/VERSION +1 -1
  2. numba_cuda/numba/cuda/__init__.py +1 -1
  3. numba_cuda/numba/cuda/_internal/cuda_bf16.py +12706 -1470
  4. numba_cuda/numba/cuda/_internal/cuda_fp16.py +2653 -8769
  5. numba_cuda/numba/cuda/api.py +6 -1
  6. numba_cuda/numba/cuda/bf16.py +285 -2
  7. numba_cuda/numba/cuda/cgutils.py +2 -2
  8. numba_cuda/numba/cuda/cloudpickle/__init__.py +21 -0
  9. numba_cuda/numba/cuda/cloudpickle/cloudpickle.py +1598 -0
  10. numba_cuda/numba/cuda/cloudpickle/cloudpickle_fast.py +17 -0
  11. numba_cuda/numba/cuda/codegen.py +1 -1
  12. numba_cuda/numba/cuda/compiler.py +373 -30
  13. numba_cuda/numba/cuda/core/analysis.py +319 -0
  14. numba_cuda/numba/cuda/core/annotations/__init__.py +0 -0
  15. numba_cuda/numba/cuda/core/annotations/type_annotations.py +304 -0
  16. numba_cuda/numba/cuda/core/base.py +1289 -0
  17. numba_cuda/numba/cuda/core/bytecode.py +727 -0
  18. numba_cuda/numba/cuda/core/caching.py +2 -2
  19. numba_cuda/numba/cuda/core/compiler.py +6 -14
  20. numba_cuda/numba/cuda/core/compiler_machinery.py +497 -0
  21. numba_cuda/numba/cuda/core/config.py +747 -0
  22. numba_cuda/numba/cuda/core/consts.py +124 -0
  23. numba_cuda/numba/cuda/core/cpu.py +370 -0
  24. numba_cuda/numba/cuda/core/environment.py +68 -0
  25. numba_cuda/numba/cuda/core/event.py +511 -0
  26. numba_cuda/numba/cuda/core/funcdesc.py +330 -0
  27. numba_cuda/numba/cuda/core/inline_closurecall.py +1889 -0
  28. numba_cuda/numba/cuda/core/interpreter.py +48 -26
  29. numba_cuda/numba/cuda/core/ir_utils.py +15 -26
  30. numba_cuda/numba/cuda/core/options.py +262 -0
  31. numba_cuda/numba/cuda/core/postproc.py +249 -0
  32. numba_cuda/numba/cuda/core/pythonapi.py +1868 -0
  33. numba_cuda/numba/cuda/core/rewrites/__init__.py +26 -0
  34. numba_cuda/numba/cuda/core/rewrites/ir_print.py +90 -0
  35. numba_cuda/numba/cuda/core/rewrites/registry.py +104 -0
  36. numba_cuda/numba/cuda/core/rewrites/static_binop.py +40 -0
  37. numba_cuda/numba/cuda/core/rewrites/static_getitem.py +187 -0
  38. numba_cuda/numba/cuda/core/rewrites/static_raise.py +98 -0
  39. numba_cuda/numba/cuda/core/ssa.py +496 -0
  40. numba_cuda/numba/cuda/core/targetconfig.py +329 -0
  41. numba_cuda/numba/cuda/core/tracing.py +231 -0
  42. numba_cuda/numba/cuda/core/transforms.py +952 -0
  43. numba_cuda/numba/cuda/core/typed_passes.py +738 -7
  44. numba_cuda/numba/cuda/core/typeinfer.py +1948 -0
  45. numba_cuda/numba/cuda/core/unsafe/__init__.py +0 -0
  46. numba_cuda/numba/cuda/core/unsafe/bytes.py +67 -0
  47. numba_cuda/numba/cuda/core/unsafe/eh.py +66 -0
  48. numba_cuda/numba/cuda/core/unsafe/refcount.py +98 -0
  49. numba_cuda/numba/cuda/core/untyped_passes.py +1983 -0
  50. numba_cuda/numba/cuda/cpython/cmathimpl.py +560 -0
  51. numba_cuda/numba/cuda/cpython/mathimpl.py +499 -0
  52. numba_cuda/numba/cuda/cpython/numbers.py +1474 -0
  53. numba_cuda/numba/cuda/cuda_paths.py +422 -246
  54. numba_cuda/numba/cuda/cudadecl.py +1 -1
  55. numba_cuda/numba/cuda/cudadrv/__init__.py +1 -1
  56. numba_cuda/numba/cuda/cudadrv/devicearray.py +2 -1
  57. numba_cuda/numba/cuda/cudadrv/driver.py +11 -140
  58. numba_cuda/numba/cuda/cudadrv/dummyarray.py +111 -24
  59. numba_cuda/numba/cuda/cudadrv/libs.py +5 -5
  60. numba_cuda/numba/cuda/cudadrv/mappings.py +1 -1
  61. numba_cuda/numba/cuda/cudadrv/nvrtc.py +19 -8
  62. numba_cuda/numba/cuda/cudadrv/nvvm.py +1 -4
  63. numba_cuda/numba/cuda/cudadrv/runtime.py +1 -1
  64. numba_cuda/numba/cuda/cudaimpl.py +5 -1
  65. numba_cuda/numba/cuda/debuginfo.py +85 -2
  66. numba_cuda/numba/cuda/decorators.py +3 -3
  67. numba_cuda/numba/cuda/descriptor.py +3 -4
  68. numba_cuda/numba/cuda/deviceufunc.py +66 -2
  69. numba_cuda/numba/cuda/dispatcher.py +18 -39
  70. numba_cuda/numba/cuda/flags.py +141 -1
  71. numba_cuda/numba/cuda/fp16.py +0 -2
  72. numba_cuda/numba/cuda/include/13/cuda_bf16.h +5118 -0
  73. numba_cuda/numba/cuda/include/13/cuda_bf16.hpp +3865 -0
  74. numba_cuda/numba/cuda/include/13/cuda_fp16.h +5363 -0
  75. numba_cuda/numba/cuda/include/13/cuda_fp16.hpp +3483 -0
  76. numba_cuda/numba/cuda/lowering.py +7 -144
  77. numba_cuda/numba/cuda/mathimpl.py +2 -1
  78. numba_cuda/numba/cuda/memory_management/nrt.py +43 -17
  79. numba_cuda/numba/cuda/misc/findlib.py +75 -0
  80. numba_cuda/numba/cuda/models.py +9 -1
  81. numba_cuda/numba/cuda/np/npdatetime_helpers.py +217 -0
  82. numba_cuda/numba/cuda/np/npyfuncs.py +1807 -0
  83. numba_cuda/numba/cuda/np/numpy_support.py +553 -0
  84. numba_cuda/numba/cuda/np/ufunc/ufuncbuilder.py +59 -0
  85. numba_cuda/numba/cuda/nvvmutils.py +1 -1
  86. numba_cuda/numba/cuda/printimpl.py +12 -1
  87. numba_cuda/numba/cuda/random.py +1 -1
  88. numba_cuda/numba/cuda/serialize.py +1 -1
  89. numba_cuda/numba/cuda/simulator/__init__.py +1 -1
  90. numba_cuda/numba/cuda/simulator/api.py +1 -1
  91. numba_cuda/numba/cuda/simulator/compiler.py +4 -0
  92. numba_cuda/numba/cuda/simulator/cudadrv/devicearray.py +1 -1
  93. numba_cuda/numba/cuda/simulator/kernelapi.py +1 -1
  94. numba_cuda/numba/cuda/simulator/memory_management/nrt.py +14 -2
  95. numba_cuda/numba/cuda/target.py +35 -17
  96. numba_cuda/numba/cuda/testing.py +4 -19
  97. numba_cuda/numba/cuda/tests/__init__.py +1 -1
  98. numba_cuda/numba/cuda/tests/cloudpickle_main_class.py +9 -0
  99. numba_cuda/numba/cuda/tests/core/test_serialize.py +4 -4
  100. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_devicerecord.py +1 -1
  101. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_libraries.py +1 -1
  102. numba_cuda/numba/cuda/tests/cudadrv/test_deallocations.py +1 -1
  103. numba_cuda/numba/cuda/tests/cudadrv/test_detect.py +6 -3
  104. numba_cuda/numba/cuda/tests/cudadrv/test_emm_plugins.py +1 -1
  105. numba_cuda/numba/cuda/tests/cudadrv/test_linker.py +18 -2
  106. numba_cuda/numba/cuda/tests/cudadrv/test_module_callbacks.py +2 -1
  107. numba_cuda/numba/cuda/tests/cudadrv/test_nvjitlink.py +1 -1
  108. numba_cuda/numba/cuda/tests/cudadrv/test_ptds.py +1 -1
  109. numba_cuda/numba/cuda/tests/cudapy/extensions_usecases.py +1 -1
  110. numba_cuda/numba/cuda/tests/cudapy/test_array.py +2 -1
  111. numba_cuda/numba/cuda/tests/cudapy/test_atomics.py +1 -1
  112. numba_cuda/numba/cuda/tests/cudapy/test_bfloat16.py +539 -2
  113. numba_cuda/numba/cuda/tests/cudapy/test_bfloat16_bindings.py +81 -1
  114. numba_cuda/numba/cuda/tests/cudapy/test_caching.py +1 -3
  115. numba_cuda/numba/cuda/tests/cudapy/test_complex.py +1 -1
  116. numba_cuda/numba/cuda/tests/cudapy/test_constmem.py +1 -1
  117. numba_cuda/numba/cuda/tests/cudapy/test_cooperative_groups.py +2 -3
  118. numba_cuda/numba/cuda/tests/cudapy/test_copy_propagate.py +130 -0
  119. numba_cuda/numba/cuda/tests/cudapy/test_datetime.py +1 -1
  120. numba_cuda/numba/cuda/tests/cudapy/test_debug.py +1 -1
  121. numba_cuda/numba/cuda/tests/cudapy/test_debuginfo.py +293 -4
  122. numba_cuda/numba/cuda/tests/cudapy/test_debuginfo_types.py +1 -1
  123. numba_cuda/numba/cuda/tests/cudapy/test_dispatcher.py +1 -1
  124. numba_cuda/numba/cuda/tests/cudapy/test_errors.py +1 -1
  125. numba_cuda/numba/cuda/tests/cudapy/test_exception.py +1 -1
  126. numba_cuda/numba/cuda/tests/cudapy/test_extending.py +2 -1
  127. numba_cuda/numba/cuda/tests/cudapy/test_inline.py +18 -8
  128. numba_cuda/numba/cuda/tests/cudapy/test_ir_utils.py +10 -37
  129. numba_cuda/numba/cuda/tests/cudapy/test_laplace.py +1 -1
  130. numba_cuda/numba/cuda/tests/cudapy/test_math.py +1 -1
  131. numba_cuda/numba/cuda/tests/cudapy/test_matmul.py +1 -1
  132. numba_cuda/numba/cuda/tests/cudapy/test_operator.py +1 -1
  133. numba_cuda/numba/cuda/tests/cudapy/test_print.py +20 -0
  134. numba_cuda/numba/cuda/tests/cudapy/test_record_dtype.py +1 -1
  135. numba_cuda/numba/cuda/tests/cudapy/test_reduction.py +1 -1
  136. numba_cuda/numba/cuda/tests/cudapy/test_serialize.py +1 -1
  137. numba_cuda/numba/cuda/tests/cudapy/test_sm.py +1 -1
  138. numba_cuda/numba/cuda/tests/cudapy/test_ssa.py +453 -0
  139. numba_cuda/numba/cuda/tests/cudapy/test_sync.py +1 -1
  140. numba_cuda/numba/cuda/tests/cudapy/test_typeinfer.py +538 -0
  141. numba_cuda/numba/cuda/tests/cudapy/test_ufuncs.py +263 -2
  142. numba_cuda/numba/cuda/tests/cudapy/test_userexc.py +1 -1
  143. numba_cuda/numba/cuda/tests/cudapy/test_vector_type.py +1 -1
  144. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_decor.py +112 -6
  145. numba_cuda/numba/cuda/tests/cudapy/test_warning.py +1 -1
  146. numba_cuda/numba/cuda/tests/cudapy/test_warp_ops.py +1 -1
  147. numba_cuda/numba/cuda/tests/doc_examples/test_cg.py +0 -2
  148. numba_cuda/numba/cuda/tests/doc_examples/test_ffi.py +3 -2
  149. numba_cuda/numba/cuda/tests/doc_examples/test_laplace.py +0 -2
  150. numba_cuda/numba/cuda/tests/doc_examples/test_sessionize.py +0 -2
  151. numba_cuda/numba/cuda/tests/nocuda/test_import.py +3 -1
  152. numba_cuda/numba/cuda/tests/nocuda/test_library_lookup.py +24 -12
  153. numba_cuda/numba/cuda/tests/nrt/test_nrt.py +2 -1
  154. numba_cuda/numba/cuda/tests/support.py +55 -15
  155. numba_cuda/numba/cuda/tests/test_tracing.py +200 -0
  156. numba_cuda/numba/cuda/types.py +56 -0
  157. numba_cuda/numba/cuda/typing/__init__.py +9 -1
  158. numba_cuda/numba/cuda/typing/cffi_utils.py +55 -0
  159. numba_cuda/numba/cuda/typing/context.py +751 -0
  160. numba_cuda/numba/cuda/typing/enumdecl.py +74 -0
  161. numba_cuda/numba/cuda/typing/npydecl.py +658 -0
  162. numba_cuda/numba/cuda/typing/templates.py +7 -6
  163. numba_cuda/numba/cuda/ufuncs.py +3 -3
  164. numba_cuda/numba/cuda/utils.py +6 -112
  165. {numba_cuda-0.19.1.dist-info → numba_cuda-0.20.0.dist-info}/METADATA +2 -1
  166. {numba_cuda-0.19.1.dist-info → numba_cuda-0.20.0.dist-info}/RECORD +170 -115
  167. numba_cuda/numba/cuda/tests/cudadrv/test_mvc.py +0 -60
  168. {numba_cuda-0.19.1.dist-info → numba_cuda-0.20.0.dist-info}/WHEEL +0 -0
  169. {numba_cuda-0.19.1.dist-info → numba_cuda-0.20.0.dist-info}/licenses/LICENSE +0 -0
  170. {numba_cuda-0.19.1.dist-info → numba_cuda-0.20.0.dist-info}/licenses/LICENSE.numba +0 -0
  171. {numba_cuda-0.19.1.dist-info → numba_cuda-0.20.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1474 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: BSD-2-Clause
3
+
4
+ import math
5
+ import numbers
6
+
7
+ import numpy as np
8
+ import operator
9
+
10
+ from llvmlite import ir
11
+ from llvmlite.ir import Constant
12
+
13
+ from numba.core.imputils import impl_ret_untracked, Registry
14
+ from numba.core import typing, types, errors
15
+ from numba.core.extending import overload_method
16
+ from numba.cpython.unsafe.numbers import viewer
17
+ from numba.cuda import cgutils
18
+
19
+ registry = Registry("numbers")
20
+ lower_builtin = registry.lower
21
+ lower_cast = registry.lower_cast
22
+ lower_constant = registry.lower_constant
23
+ lower_getattr = registry.lower_getattr
24
+
25
+
26
+ def _int_arith_flags(rettype):
27
+ """
28
+ Return the modifier flags for integer arithmetic.
29
+ """
30
+ if rettype.signed:
31
+ # Ignore the effects of signed overflow. This is important for
32
+ # optimization of some indexing operations. For example
33
+ # array[i+1] could see `i+1` trigger a signed overflow and
34
+ # give a negative number. With Python's indexing, a negative
35
+ # index is treated differently: its resolution has a runtime cost.
36
+ # Telling LLVM to ignore signed overflows allows it to optimize
37
+ # away the check for a negative `i+1` if it knows `i` is positive.
38
+ return ["nsw"]
39
+ else:
40
+ return []
41
+
42
+
43
+ def int_add_impl(context, builder, sig, args):
44
+ [va, vb] = args
45
+ [ta, tb] = sig.args
46
+ a = context.cast(builder, va, ta, sig.return_type)
47
+ b = context.cast(builder, vb, tb, sig.return_type)
48
+ res = builder.add(a, b, flags=_int_arith_flags(sig.return_type))
49
+ return impl_ret_untracked(context, builder, sig.return_type, res)
50
+
51
+
52
+ def int_sub_impl(context, builder, sig, args):
53
+ [va, vb] = args
54
+ [ta, tb] = sig.args
55
+ a = context.cast(builder, va, ta, sig.return_type)
56
+ b = context.cast(builder, vb, tb, sig.return_type)
57
+ res = builder.sub(a, b, flags=_int_arith_flags(sig.return_type))
58
+ return impl_ret_untracked(context, builder, sig.return_type, res)
59
+
60
+
61
+ def int_mul_impl(context, builder, sig, args):
62
+ [va, vb] = args
63
+ [ta, tb] = sig.args
64
+ a = context.cast(builder, va, ta, sig.return_type)
65
+ b = context.cast(builder, vb, tb, sig.return_type)
66
+ res = builder.mul(a, b, flags=_int_arith_flags(sig.return_type))
67
+ return impl_ret_untracked(context, builder, sig.return_type, res)
68
+
69
+
70
+ def int_divmod_signed(context, builder, ty, x, y):
71
+ """
72
+ Reference Objects/intobject.c
73
+ xdivy = x / y;
74
+ xmody = (long)(x - (unsigned long)xdivy * y);
75
+ /* If the signs of x and y differ, and the remainder is non-0,
76
+ * C89 doesn't define whether xdivy is now the floor or the
77
+ * ceiling of the infinitely precise quotient. We want the floor,
78
+ * and we have it iff the remainder's sign matches y's.
79
+ */
80
+ if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) {
81
+ xmody += y;
82
+ --xdivy;
83
+ assert(xmody && ((y ^ xmody) >= 0));
84
+ }
85
+ *p_xdivy = xdivy;
86
+ *p_xmody = xmody;
87
+ """
88
+ assert x.type == y.type
89
+
90
+ ZERO = y.type(0)
91
+ ONE = y.type(1)
92
+
93
+ # NOTE: On x86 at least, dividing the lowest representable integer
94
+ # (e.g. 0x80000000 for int32) by -1 causes a SIFGPE (division overflow),
95
+ # causing the process to crash.
96
+ # We return 0, 0 instead (more or less like Numpy).
97
+
98
+ resdiv = cgutils.alloca_once_value(builder, ZERO)
99
+ resmod = cgutils.alloca_once_value(builder, ZERO)
100
+
101
+ is_overflow = builder.and_(
102
+ builder.icmp_signed("==", x, x.type(ty.minval)),
103
+ builder.icmp_signed("==", y, y.type(-1)),
104
+ )
105
+
106
+ with builder.if_then(builder.not_(is_overflow), likely=True):
107
+ # Note LLVM will optimize this to a single divmod instruction,
108
+ # if available on the target CPU (e.g. x86).
109
+ xdivy = builder.sdiv(x, y)
110
+ xmody = builder.srem(x, y)
111
+
112
+ y_xor_xmody_ltz = builder.icmp_signed("<", builder.xor(y, xmody), ZERO)
113
+ xmody_istrue = builder.icmp_signed("!=", xmody, ZERO)
114
+ cond = builder.and_(xmody_istrue, y_xor_xmody_ltz)
115
+
116
+ with builder.if_else(cond) as (if_different_signs, if_same_signs):
117
+ with if_same_signs:
118
+ builder.store(xdivy, resdiv)
119
+ builder.store(xmody, resmod)
120
+
121
+ with if_different_signs:
122
+ builder.store(builder.sub(xdivy, ONE), resdiv)
123
+ builder.store(builder.add(xmody, y), resmod)
124
+
125
+ return builder.load(resdiv), builder.load(resmod)
126
+
127
+
128
+ def int_divmod(context, builder, ty, x, y):
129
+ """
130
+ Integer divmod(x, y). The caller must ensure that y != 0.
131
+ """
132
+ if ty.signed:
133
+ return int_divmod_signed(context, builder, ty, x, y)
134
+ else:
135
+ return builder.udiv(x, y), builder.urem(x, y)
136
+
137
+
138
+ def _int_divmod_impl(context, builder, sig, args, zerodiv_message):
139
+ va, vb = args
140
+ ta, tb = sig.args
141
+
142
+ ty = sig.return_type
143
+ if isinstance(ty, types.UniTuple):
144
+ ty = ty.dtype
145
+ a = context.cast(builder, va, ta, ty)
146
+ b = context.cast(builder, vb, tb, ty)
147
+ quot = cgutils.alloca_once(builder, a.type, name="quot")
148
+ rem = cgutils.alloca_once(builder, a.type, name="rem")
149
+
150
+ with builder.if_else(cgutils.is_scalar_zero(builder, b), likely=False) as (
151
+ if_zero,
152
+ if_non_zero,
153
+ ):
154
+ with if_zero:
155
+ if not context.error_model.fp_zero_division(
156
+ builder, (zerodiv_message,)
157
+ ):
158
+ # No exception raised => return 0
159
+ # XXX We should also set the FPU exception status, but
160
+ # there's no easy way to do that from LLVM.
161
+ builder.store(b, quot)
162
+ builder.store(b, rem)
163
+ with if_non_zero:
164
+ q, r = int_divmod(context, builder, ty, a, b)
165
+ builder.store(q, quot)
166
+ builder.store(r, rem)
167
+
168
+ return quot, rem
169
+
170
+
171
+ @lower_builtin(divmod, types.Integer, types.Integer)
172
+ def int_divmod_impl(context, builder, sig, args):
173
+ quot, rem = _int_divmod_impl(
174
+ context, builder, sig, args, "integer divmod by zero"
175
+ )
176
+
177
+ return cgutils.pack_array(builder, (builder.load(quot), builder.load(rem)))
178
+
179
+
180
+ @lower_builtin(operator.floordiv, types.Integer, types.Integer)
181
+ @lower_builtin(operator.ifloordiv, types.Integer, types.Integer)
182
+ def int_floordiv_impl(context, builder, sig, args):
183
+ quot, rem = _int_divmod_impl(
184
+ context, builder, sig, args, "integer division by zero"
185
+ )
186
+ return builder.load(quot)
187
+
188
+
189
+ @lower_builtin(operator.truediv, types.Integer, types.Integer)
190
+ @lower_builtin(operator.itruediv, types.Integer, types.Integer)
191
+ def int_truediv_impl(context, builder, sig, args):
192
+ [va, vb] = args
193
+ [ta, tb] = sig.args
194
+ a = context.cast(builder, va, ta, sig.return_type)
195
+ b = context.cast(builder, vb, tb, sig.return_type)
196
+ with cgutils.if_zero(builder, b):
197
+ context.error_model.fp_zero_division(builder, ("division by zero",))
198
+ res = builder.fdiv(a, b)
199
+ return impl_ret_untracked(context, builder, sig.return_type, res)
200
+
201
+
202
+ @lower_builtin(operator.mod, types.Integer, types.Integer)
203
+ @lower_builtin(operator.imod, types.Integer, types.Integer)
204
+ def int_rem_impl(context, builder, sig, args):
205
+ quot, rem = _int_divmod_impl(
206
+ context, builder, sig, args, "integer modulo by zero"
207
+ )
208
+ return builder.load(rem)
209
+
210
+
211
+ def _get_power_zerodiv_return(context, return_type):
212
+ if (
213
+ isinstance(return_type, types.Integer)
214
+ and not context.error_model.raise_on_fp_zero_division
215
+ ):
216
+ # If not raising, return 0x8000... when computing 0 ** <negative number>
217
+ return -1 << (return_type.bitwidth - 1)
218
+ else:
219
+ return False
220
+
221
+
222
+ def int_power_impl(context, builder, sig, args):
223
+ """
224
+ a ^ b, where a is an integer or real, and b an integer
225
+ """
226
+ is_integer = isinstance(sig.args[0], types.Integer)
227
+ tp = sig.return_type
228
+ zerodiv_return = _get_power_zerodiv_return(context, tp)
229
+
230
+ def int_power(a, b):
231
+ # Ensure computations are done with a large enough width
232
+ r = tp(1)
233
+ a = tp(a)
234
+ if b < 0:
235
+ invert = True
236
+ exp = -b
237
+ if exp < 0:
238
+ raise OverflowError
239
+ if is_integer:
240
+ if a == 0:
241
+ if zerodiv_return:
242
+ return zerodiv_return
243
+ else:
244
+ raise ZeroDivisionError(
245
+ "0 cannot be raised to a negative power"
246
+ )
247
+ if a != 1 and a != -1:
248
+ return 0
249
+ else:
250
+ invert = False
251
+ exp = b
252
+ if exp > 0x10000:
253
+ # Optimization cutoff: fallback on the generic algorithm
254
+ return math.pow(a, float(b))
255
+ while exp != 0:
256
+ if exp & 1:
257
+ r *= a
258
+ exp >>= 1
259
+ a *= a
260
+
261
+ return 1.0 / r if invert else r
262
+
263
+ res = context.compile_internal(builder, int_power, sig, args)
264
+ return impl_ret_untracked(context, builder, sig.return_type, res)
265
+
266
+
267
+ @lower_builtin(operator.pow, types.Integer, types.IntegerLiteral)
268
+ @lower_builtin(operator.ipow, types.Integer, types.IntegerLiteral)
269
+ @lower_builtin(operator.pow, types.Float, types.IntegerLiteral)
270
+ @lower_builtin(operator.ipow, types.Float, types.IntegerLiteral)
271
+ def static_power_impl(context, builder, sig, args):
272
+ """
273
+ a ^ b, where a is an integer or real, and b a constant integer
274
+ """
275
+ exp = sig.args[1].value
276
+ if not isinstance(exp, numbers.Integral):
277
+ raise NotImplementedError
278
+ if abs(exp) > 0x10000:
279
+ # Optimization cutoff: fallback on the generic algorithm above
280
+ raise NotImplementedError
281
+ invert = exp < 0
282
+ exp = abs(exp)
283
+
284
+ tp = sig.return_type
285
+ is_integer = isinstance(tp, types.Integer)
286
+ zerodiv_return = _get_power_zerodiv_return(context, tp)
287
+
288
+ val = context.cast(builder, args[0], sig.args[0], tp)
289
+ lty = val.type
290
+
291
+ def mul(a, b):
292
+ if is_integer:
293
+ return builder.mul(a, b)
294
+ else:
295
+ return builder.fmul(a, b)
296
+
297
+ # Unroll the exponentiation loop
298
+ res = lty(1)
299
+ while exp != 0:
300
+ if exp & 1:
301
+ res = mul(res, val)
302
+ exp >>= 1
303
+ val = mul(val, val)
304
+
305
+ if invert:
306
+ # If the exponent was negative, fix the result by inverting it
307
+ if is_integer:
308
+ # Integer inversion
309
+ def invert_impl(a):
310
+ if a == 0:
311
+ if zerodiv_return:
312
+ return zerodiv_return
313
+ else:
314
+ raise ZeroDivisionError(
315
+ "0 cannot be raised to a negative power"
316
+ )
317
+ if a != 1 and a != -1:
318
+ return 0
319
+ else:
320
+ return a
321
+
322
+ else:
323
+ # Real inversion
324
+ def invert_impl(a):
325
+ return 1.0 / a
326
+
327
+ res = context.compile_internal(
328
+ builder, invert_impl, typing.signature(tp, tp), (res,)
329
+ )
330
+
331
+ return res
332
+
333
+
334
+ def int_slt_impl(context, builder, sig, args):
335
+ res = builder.icmp_signed("<", *args)
336
+ return impl_ret_untracked(context, builder, sig.return_type, res)
337
+
338
+
339
+ def int_sle_impl(context, builder, sig, args):
340
+ res = builder.icmp_signed("<=", *args)
341
+ return impl_ret_untracked(context, builder, sig.return_type, res)
342
+
343
+
344
+ def int_sgt_impl(context, builder, sig, args):
345
+ res = builder.icmp_signed(">", *args)
346
+ return impl_ret_untracked(context, builder, sig.return_type, res)
347
+
348
+
349
+ def int_sge_impl(context, builder, sig, args):
350
+ res = builder.icmp_signed(">=", *args)
351
+ return impl_ret_untracked(context, builder, sig.return_type, res)
352
+
353
+
354
+ def int_ult_impl(context, builder, sig, args):
355
+ res = builder.icmp_unsigned("<", *args)
356
+ return impl_ret_untracked(context, builder, sig.return_type, res)
357
+
358
+
359
+ def int_ule_impl(context, builder, sig, args):
360
+ res = builder.icmp_unsigned("<=", *args)
361
+ return impl_ret_untracked(context, builder, sig.return_type, res)
362
+
363
+
364
+ def int_ugt_impl(context, builder, sig, args):
365
+ res = builder.icmp_unsigned(">", *args)
366
+ return impl_ret_untracked(context, builder, sig.return_type, res)
367
+
368
+
369
+ def int_uge_impl(context, builder, sig, args):
370
+ res = builder.icmp_unsigned(">=", *args)
371
+ return impl_ret_untracked(context, builder, sig.return_type, res)
372
+
373
+
374
+ def int_eq_impl(context, builder, sig, args):
375
+ res = builder.icmp_unsigned("==", *args)
376
+ return impl_ret_untracked(context, builder, sig.return_type, res)
377
+
378
+
379
+ def int_ne_impl(context, builder, sig, args):
380
+ res = builder.icmp_unsigned("!=", *args)
381
+ return impl_ret_untracked(context, builder, sig.return_type, res)
382
+
383
+
384
+ def int_signed_unsigned_cmp(op):
385
+ def impl(context, builder, sig, args):
386
+ (left, right) = args
387
+ # This code is translated from the NumPy source.
388
+ # What we're going to do is divide the range of a signed value at zero.
389
+ # If the signed value is less than zero, then we can treat zero as the
390
+ # unsigned value since the unsigned value is necessarily zero or larger
391
+ # and any signed comparison between a negative value and zero/infinity
392
+ # will yield the same result. If the signed value is greater than or
393
+ # equal to zero, then we can safely cast it to an unsigned value and do
394
+ # the expected unsigned-unsigned comparison operation.
395
+ # Original: https://github.com/numpy/numpy/pull/23713
396
+ cmp_zero = builder.icmp_signed("<", left, Constant(left.type, 0))
397
+ lt_zero = builder.icmp_signed(op, left, Constant(left.type, 0))
398
+ ge_zero = builder.icmp_unsigned(op, left, right)
399
+ res = builder.select(cmp_zero, lt_zero, ge_zero)
400
+ return impl_ret_untracked(context, builder, sig.return_type, res)
401
+
402
+ return impl
403
+
404
+
405
+ def int_unsigned_signed_cmp(op):
406
+ def impl(context, builder, sig, args):
407
+ (left, right) = args
408
+ # See the function `int_signed_unsigned_cmp` for implementation notes.
409
+ cmp_zero = builder.icmp_signed("<", right, Constant(right.type, 0))
410
+ lt_zero = builder.icmp_signed(op, Constant(right.type, 0), right)
411
+ ge_zero = builder.icmp_unsigned(op, left, right)
412
+ res = builder.select(cmp_zero, lt_zero, ge_zero)
413
+ return impl_ret_untracked(context, builder, sig.return_type, res)
414
+
415
+ return impl
416
+
417
+
418
+ def int_abs_impl(context, builder, sig, args):
419
+ [x] = args
420
+ ZERO = Constant(x.type, None)
421
+ ltz = builder.icmp_signed("<", x, ZERO)
422
+ negated = builder.neg(x)
423
+ res = builder.select(ltz, negated, x)
424
+ return impl_ret_untracked(context, builder, sig.return_type, res)
425
+
426
+
427
+ def uint_abs_impl(context, builder, sig, args):
428
+ [x] = args
429
+ return impl_ret_untracked(context, builder, sig.return_type, x)
430
+
431
+
432
+ def int_shl_impl(context, builder, sig, args):
433
+ [valty, amtty] = sig.args
434
+ [val, amt] = args
435
+ val = context.cast(builder, val, valty, sig.return_type)
436
+ amt = context.cast(builder, amt, amtty, sig.return_type)
437
+ res = builder.shl(val, amt)
438
+ return impl_ret_untracked(context, builder, sig.return_type, res)
439
+
440
+
441
+ def int_shr_impl(context, builder, sig, args):
442
+ [valty, amtty] = sig.args
443
+ [val, amt] = args
444
+ val = context.cast(builder, val, valty, sig.return_type)
445
+ amt = context.cast(builder, amt, amtty, sig.return_type)
446
+ if sig.return_type.signed:
447
+ res = builder.ashr(val, amt)
448
+ else:
449
+ res = builder.lshr(val, amt)
450
+ return impl_ret_untracked(context, builder, sig.return_type, res)
451
+
452
+
453
+ def int_and_impl(context, builder, sig, args):
454
+ [at, bt] = sig.args
455
+ [av, bv] = args
456
+ cav = context.cast(builder, av, at, sig.return_type)
457
+ cbc = context.cast(builder, bv, bt, sig.return_type)
458
+ res = builder.and_(cav, cbc)
459
+ return impl_ret_untracked(context, builder, sig.return_type, res)
460
+
461
+
462
+ def int_or_impl(context, builder, sig, args):
463
+ [at, bt] = sig.args
464
+ [av, bv] = args
465
+ cav = context.cast(builder, av, at, sig.return_type)
466
+ cbc = context.cast(builder, bv, bt, sig.return_type)
467
+ res = builder.or_(cav, cbc)
468
+ return impl_ret_untracked(context, builder, sig.return_type, res)
469
+
470
+
471
+ def int_xor_impl(context, builder, sig, args):
472
+ [at, bt] = sig.args
473
+ [av, bv] = args
474
+ cav = context.cast(builder, av, at, sig.return_type)
475
+ cbc = context.cast(builder, bv, bt, sig.return_type)
476
+ res = builder.xor(cav, cbc)
477
+ return impl_ret_untracked(context, builder, sig.return_type, res)
478
+
479
+
480
+ def int_negate_impl(context, builder, sig, args):
481
+ [typ] = sig.args
482
+ [val] = args
483
+ # Negate before upcasting, for unsigned numbers
484
+ res = builder.neg(val)
485
+ res = context.cast(builder, res, typ, sig.return_type)
486
+ return impl_ret_untracked(context, builder, sig.return_type, res)
487
+
488
+
489
+ def int_positive_impl(context, builder, sig, args):
490
+ [typ] = sig.args
491
+ [val] = args
492
+ res = context.cast(builder, val, typ, sig.return_type)
493
+ return impl_ret_untracked(context, builder, sig.return_type, res)
494
+
495
+
496
+ def int_invert_impl(context, builder, sig, args):
497
+ [typ] = sig.args
498
+ [val] = args
499
+ # Invert before upcasting, for unsigned numbers
500
+ res = builder.xor(val, Constant(val.type, int("1" * val.type.width, 2)))
501
+ res = context.cast(builder, res, typ, sig.return_type)
502
+ return impl_ret_untracked(context, builder, sig.return_type, res)
503
+
504
+
505
+ def int_sign_impl(context, builder, sig, args):
506
+ """
507
+ np.sign(int)
508
+ """
509
+ [x] = args
510
+ POS = Constant(x.type, 1)
511
+ NEG = Constant(x.type, -1)
512
+ ZERO = Constant(x.type, 0)
513
+
514
+ cmp_zero = builder.icmp_unsigned("==", x, ZERO)
515
+ cmp_pos = builder.icmp_signed(">", x, ZERO)
516
+
517
+ presult = cgutils.alloca_once(builder, x.type)
518
+
519
+ bb_zero = builder.append_basic_block(".zero")
520
+ bb_postest = builder.append_basic_block(".postest")
521
+ bb_pos = builder.append_basic_block(".pos")
522
+ bb_neg = builder.append_basic_block(".neg")
523
+ bb_exit = builder.append_basic_block(".exit")
524
+
525
+ builder.cbranch(cmp_zero, bb_zero, bb_postest)
526
+
527
+ with builder.goto_block(bb_zero):
528
+ builder.store(ZERO, presult)
529
+ builder.branch(bb_exit)
530
+
531
+ with builder.goto_block(bb_postest):
532
+ builder.cbranch(cmp_pos, bb_pos, bb_neg)
533
+
534
+ with builder.goto_block(bb_pos):
535
+ builder.store(POS, presult)
536
+ builder.branch(bb_exit)
537
+
538
+ with builder.goto_block(bb_neg):
539
+ builder.store(NEG, presult)
540
+ builder.branch(bb_exit)
541
+
542
+ builder.position_at_end(bb_exit)
543
+ res = builder.load(presult)
544
+ return impl_ret_untracked(context, builder, sig.return_type, res)
545
+
546
+
547
+ def bool_negate_impl(context, builder, sig, args):
548
+ [typ] = sig.args
549
+ [val] = args
550
+ res = context.cast(builder, val, typ, sig.return_type)
551
+ res = builder.neg(res)
552
+ return impl_ret_untracked(context, builder, sig.return_type, res)
553
+
554
+
555
+ def bool_unary_positive_impl(context, builder, sig, args):
556
+ [typ] = sig.args
557
+ [val] = args
558
+ res = context.cast(builder, val, typ, sig.return_type)
559
+ return impl_ret_untracked(context, builder, sig.return_type, res)
560
+
561
+
562
+ lower_builtin(operator.eq, types.boolean, types.boolean)(int_eq_impl)
563
+ lower_builtin(operator.ne, types.boolean, types.boolean)(int_ne_impl)
564
+ lower_builtin(operator.lt, types.boolean, types.boolean)(int_ult_impl)
565
+ lower_builtin(operator.le, types.boolean, types.boolean)(int_ule_impl)
566
+ lower_builtin(operator.gt, types.boolean, types.boolean)(int_ugt_impl)
567
+ lower_builtin(operator.ge, types.boolean, types.boolean)(int_uge_impl)
568
+ lower_builtin(operator.neg, types.boolean)(bool_negate_impl)
569
+ lower_builtin(operator.pos, types.boolean)(bool_unary_positive_impl)
570
+
571
+
572
+ def _implement_integer_operators():
573
+ ty = types.Integer
574
+
575
+ lower_builtin(operator.add, ty, ty)(int_add_impl)
576
+ lower_builtin(operator.iadd, ty, ty)(int_add_impl)
577
+ lower_builtin(operator.sub, ty, ty)(int_sub_impl)
578
+ lower_builtin(operator.isub, ty, ty)(int_sub_impl)
579
+ lower_builtin(operator.mul, ty, ty)(int_mul_impl)
580
+ lower_builtin(operator.imul, ty, ty)(int_mul_impl)
581
+ lower_builtin(operator.eq, ty, ty)(int_eq_impl)
582
+ lower_builtin(operator.ne, ty, ty)(int_ne_impl)
583
+
584
+ lower_builtin(operator.lshift, ty, ty)(int_shl_impl)
585
+ lower_builtin(operator.ilshift, ty, ty)(int_shl_impl)
586
+ lower_builtin(operator.rshift, ty, ty)(int_shr_impl)
587
+ lower_builtin(operator.irshift, ty, ty)(int_shr_impl)
588
+
589
+ lower_builtin(operator.neg, ty)(int_negate_impl)
590
+ lower_builtin(operator.pos, ty)(int_positive_impl)
591
+
592
+ lower_builtin(operator.pow, ty, ty)(int_power_impl)
593
+ lower_builtin(operator.ipow, ty, ty)(int_power_impl)
594
+ lower_builtin(pow, ty, ty)(int_power_impl)
595
+
596
+ for ty in types.unsigned_domain:
597
+ lower_builtin(operator.lt, ty, ty)(int_ult_impl)
598
+ lower_builtin(operator.le, ty, ty)(int_ule_impl)
599
+ lower_builtin(operator.gt, ty, ty)(int_ugt_impl)
600
+ lower_builtin(operator.ge, ty, ty)(int_uge_impl)
601
+ lower_builtin(operator.pow, types.Float, ty)(int_power_impl)
602
+ lower_builtin(operator.ipow, types.Float, ty)(int_power_impl)
603
+ lower_builtin(pow, types.Float, ty)(int_power_impl)
604
+ lower_builtin(abs, ty)(uint_abs_impl)
605
+
606
+ lower_builtin(operator.lt, types.IntegerLiteral, types.IntegerLiteral)(
607
+ int_slt_impl
608
+ )
609
+ lower_builtin(operator.gt, types.IntegerLiteral, types.IntegerLiteral)(
610
+ int_slt_impl
611
+ )
612
+ lower_builtin(operator.le, types.IntegerLiteral, types.IntegerLiteral)(
613
+ int_slt_impl
614
+ )
615
+ lower_builtin(operator.ge, types.IntegerLiteral, types.IntegerLiteral)(
616
+ int_slt_impl
617
+ )
618
+ for ty in types.signed_domain:
619
+ lower_builtin(operator.lt, ty, ty)(int_slt_impl)
620
+ lower_builtin(operator.le, ty, ty)(int_sle_impl)
621
+ lower_builtin(operator.gt, ty, ty)(int_sgt_impl)
622
+ lower_builtin(operator.ge, ty, ty)(int_sge_impl)
623
+ lower_builtin(operator.pow, types.Float, ty)(int_power_impl)
624
+ lower_builtin(operator.ipow, types.Float, ty)(int_power_impl)
625
+ lower_builtin(pow, types.Float, ty)(int_power_impl)
626
+ lower_builtin(abs, ty)(int_abs_impl)
627
+
628
+
629
+ def _implement_bitwise_operators():
630
+ for ty in (types.Boolean, types.Integer):
631
+ lower_builtin(operator.and_, ty, ty)(int_and_impl)
632
+ lower_builtin(operator.iand, ty, ty)(int_and_impl)
633
+ lower_builtin(operator.or_, ty, ty)(int_or_impl)
634
+ lower_builtin(operator.ior, ty, ty)(int_or_impl)
635
+ lower_builtin(operator.xor, ty, ty)(int_xor_impl)
636
+ lower_builtin(operator.ixor, ty, ty)(int_xor_impl)
637
+
638
+ lower_builtin(operator.invert, ty)(int_invert_impl)
639
+
640
+
641
+ _implement_integer_operators()
642
+
643
+ _implement_bitwise_operators()
644
+
645
+
646
+ def real_add_impl(context, builder, sig, args):
647
+ res = builder.fadd(*args)
648
+ return impl_ret_untracked(context, builder, sig.return_type, res)
649
+
650
+
651
+ def real_sub_impl(context, builder, sig, args):
652
+ res = builder.fsub(*args)
653
+ return impl_ret_untracked(context, builder, sig.return_type, res)
654
+
655
+
656
+ def real_mul_impl(context, builder, sig, args):
657
+ res = builder.fmul(*args)
658
+ return impl_ret_untracked(context, builder, sig.return_type, res)
659
+
660
+
661
+ def real_div_impl(context, builder, sig, args):
662
+ with cgutils.if_zero(builder, args[1]):
663
+ context.error_model.fp_zero_division(builder, ("division by zero",))
664
+ res = builder.fdiv(*args)
665
+ return impl_ret_untracked(context, builder, sig.return_type, res)
666
+
667
+
668
+ def real_divmod(context, builder, x, y):
669
+ assert x.type == y.type
670
+ floatty = x.type
671
+
672
+ module = builder.module
673
+ fname = context.mangler(".numba.python.rem", [x.type])
674
+ fnty = ir.FunctionType(floatty, (floatty, floatty, ir.PointerType(floatty)))
675
+ fn = cgutils.get_or_insert_function(module, fnty, fname)
676
+
677
+ if fn.is_declaration:
678
+ fn.linkage = "linkonce_odr"
679
+ fnbuilder = ir.IRBuilder(fn.append_basic_block("entry"))
680
+ fx, fy, pmod = fn.args
681
+ div, mod = real_divmod_func_body(context, fnbuilder, fx, fy)
682
+ fnbuilder.store(mod, pmod)
683
+ fnbuilder.ret(div)
684
+
685
+ pmod = cgutils.alloca_once(builder, floatty)
686
+ quotient = builder.call(fn, (x, y, pmod))
687
+ return quotient, builder.load(pmod)
688
+
689
+
690
+ def real_divmod_func_body(context, builder, vx, wx):
691
+ # Reference Objects/floatobject.c
692
+ #
693
+ # float_divmod(PyObject *v, PyObject *w)
694
+ # {
695
+ # double vx, wx;
696
+ # double div, mod, floordiv;
697
+ # CONVERT_TO_DOUBLE(v, vx);
698
+ # CONVERT_TO_DOUBLE(w, wx);
699
+ # mod = fmod(vx, wx);
700
+ # /* fmod is typically exact, so vx-mod is *mathematically* an
701
+ # exact multiple of wx. But this is fp arithmetic, and fp
702
+ # vx - mod is an approximation; the result is that div may
703
+ # not be an exact integral value after the division, although
704
+ # it will always be very close to one.
705
+ # */
706
+ # div = (vx - mod) / wx;
707
+ # if (mod) {
708
+ # /* ensure the remainder has the same sign as the denominator */
709
+ # if ((wx < 0) != (mod < 0)) {
710
+ # mod += wx;
711
+ # div -= 1.0;
712
+ # }
713
+ # }
714
+ # else {
715
+ # /* the remainder is zero, and in the presence of signed zeroes
716
+ # fmod returns different results across platforms; ensure
717
+ # it has the same sign as the denominator; we'd like to do
718
+ # "mod = wx * 0.0", but that may get optimized away */
719
+ # mod *= mod; /* hide "mod = +0" from optimizer */
720
+ # if (wx < 0.0)
721
+ # mod = -mod;
722
+ # }
723
+ # /* snap quotient to nearest integral value */
724
+ # if (div) {
725
+ # floordiv = floor(div);
726
+ # if (div - floordiv > 0.5)
727
+ # floordiv += 1.0;
728
+ # }
729
+ # else {
730
+ # /* div is zero - get the same sign as the true quotient */
731
+ # div *= div; /* hide "div = +0" from optimizers */
732
+ # floordiv = div * vx / wx; /* zero w/ sign of vx/wx */
733
+ # }
734
+ # return Py_BuildValue("(dd)", floordiv, mod);
735
+ # }
736
+ pmod = cgutils.alloca_once(builder, vx.type)
737
+ pdiv = cgutils.alloca_once(builder, vx.type)
738
+ pfloordiv = cgutils.alloca_once(builder, vx.type)
739
+
740
+ mod = builder.frem(vx, wx)
741
+ div = builder.fdiv(builder.fsub(vx, mod), wx)
742
+
743
+ builder.store(mod, pmod)
744
+ builder.store(div, pdiv)
745
+
746
+ # Note the use of negative zero for proper negating with `ZERO - x`
747
+ ZERO = vx.type(0.0)
748
+ NZERO = vx.type(-0.0)
749
+ ONE = vx.type(1.0)
750
+ mod_istrue = builder.fcmp_unordered("!=", mod, ZERO)
751
+ wx_ltz = builder.fcmp_ordered("<", wx, ZERO)
752
+ mod_ltz = builder.fcmp_ordered("<", mod, ZERO)
753
+
754
+ with builder.if_else(mod_istrue, likely=True) as (
755
+ if_nonzero_mod,
756
+ if_zero_mod,
757
+ ):
758
+ with if_nonzero_mod:
759
+ # `mod` is non-zero or NaN
760
+ # Ensure the remainder has the same sign as the denominator
761
+ wx_ltz_ne_mod_ltz = builder.icmp_unsigned("!=", wx_ltz, mod_ltz)
762
+
763
+ with builder.if_then(wx_ltz_ne_mod_ltz):
764
+ builder.store(builder.fsub(div, ONE), pdiv)
765
+ builder.store(builder.fadd(mod, wx), pmod)
766
+
767
+ with if_zero_mod:
768
+ # `mod` is zero, select the proper sign depending on
769
+ # the denominator's sign
770
+ mod = builder.select(wx_ltz, NZERO, ZERO)
771
+ builder.store(mod, pmod)
772
+
773
+ del mod, div
774
+
775
+ div = builder.load(pdiv)
776
+ div_istrue = builder.fcmp_ordered("!=", div, ZERO)
777
+
778
+ with builder.if_then(div_istrue):
779
+ realtypemap = {"float": types.float32, "double": types.float64}
780
+ realtype = realtypemap[str(wx.type)]
781
+ floorfn = context.get_function(
782
+ math.floor, typing.signature(realtype, realtype)
783
+ )
784
+ floordiv = floorfn(builder, [div])
785
+ floordivdiff = builder.fsub(div, floordiv)
786
+ floordivincr = builder.fadd(floordiv, ONE)
787
+ HALF = Constant(wx.type, 0.5)
788
+ pred = builder.fcmp_ordered(">", floordivdiff, HALF)
789
+ floordiv = builder.select(pred, floordivincr, floordiv)
790
+ builder.store(floordiv, pfloordiv)
791
+
792
+ with cgutils.ifnot(builder, div_istrue):
793
+ div = builder.fmul(div, div)
794
+ builder.store(div, pdiv)
795
+ floordiv = builder.fdiv(builder.fmul(div, vx), wx)
796
+ builder.store(floordiv, pfloordiv)
797
+
798
+ return builder.load(pfloordiv), builder.load(pmod)
799
+
800
+
801
+ @lower_builtin(divmod, types.Float, types.Float)
802
+ def real_divmod_impl(context, builder, sig, args, loc=None):
803
+ x, y = args
804
+ quot = cgutils.alloca_once(builder, x.type, name="quot")
805
+ rem = cgutils.alloca_once(builder, x.type, name="rem")
806
+
807
+ with builder.if_else(cgutils.is_scalar_zero(builder, y), likely=False) as (
808
+ if_zero,
809
+ if_non_zero,
810
+ ):
811
+ with if_zero:
812
+ if not context.error_model.fp_zero_division(
813
+ builder, ("modulo by zero",), loc
814
+ ):
815
+ # No exception raised => compute the nan result,
816
+ # and set the FP exception word for Numpy warnings.
817
+ q = builder.fdiv(x, y)
818
+ r = builder.frem(x, y)
819
+ builder.store(q, quot)
820
+ builder.store(r, rem)
821
+ with if_non_zero:
822
+ q, r = real_divmod(context, builder, x, y)
823
+ builder.store(q, quot)
824
+ builder.store(r, rem)
825
+
826
+ return cgutils.pack_array(builder, (builder.load(quot), builder.load(rem)))
827
+
828
+
829
+ def real_mod_impl(context, builder, sig, args, loc=None):
830
+ x, y = args
831
+ res = cgutils.alloca_once(builder, x.type)
832
+ with builder.if_else(cgutils.is_scalar_zero(builder, y), likely=False) as (
833
+ if_zero,
834
+ if_non_zero,
835
+ ):
836
+ with if_zero:
837
+ if not context.error_model.fp_zero_division(
838
+ builder, ("modulo by zero",), loc
839
+ ):
840
+ # No exception raised => compute the nan result,
841
+ # and set the FP exception word for Numpy warnings.
842
+ rem = builder.frem(x, y)
843
+ builder.store(rem, res)
844
+ with if_non_zero:
845
+ _, rem = real_divmod(context, builder, x, y)
846
+ builder.store(rem, res)
847
+ return impl_ret_untracked(
848
+ context, builder, sig.return_type, builder.load(res)
849
+ )
850
+
851
+
852
+ def real_floordiv_impl(context, builder, sig, args, loc=None):
853
+ x, y = args
854
+ res = cgutils.alloca_once(builder, x.type)
855
+ with builder.if_else(cgutils.is_scalar_zero(builder, y), likely=False) as (
856
+ if_zero,
857
+ if_non_zero,
858
+ ):
859
+ with if_zero:
860
+ if not context.error_model.fp_zero_division(
861
+ builder, ("division by zero",), loc
862
+ ):
863
+ # No exception raised => compute the +/-inf or nan result,
864
+ # and set the FP exception word for Numpy warnings.
865
+ quot = builder.fdiv(x, y)
866
+ builder.store(quot, res)
867
+ with if_non_zero:
868
+ quot, _ = real_divmod(context, builder, x, y)
869
+ builder.store(quot, res)
870
+ return impl_ret_untracked(
871
+ context, builder, sig.return_type, builder.load(res)
872
+ )
873
+
874
+
875
+ def real_power_impl(context, builder, sig, args):
876
+ x, y = args
877
+ module = builder.module
878
+ if context.implement_powi_as_math_call:
879
+ imp = context.get_function(math.pow, sig)
880
+ res = imp(builder, args)
881
+ else:
882
+ fn = module.declare_intrinsic("llvm.pow", [y.type])
883
+ res = builder.call(fn, (x, y))
884
+ return impl_ret_untracked(context, builder, sig.return_type, res)
885
+
886
+
887
+ def real_lt_impl(context, builder, sig, args):
888
+ res = builder.fcmp_ordered("<", *args)
889
+ return impl_ret_untracked(context, builder, sig.return_type, res)
890
+
891
+
892
+ def real_le_impl(context, builder, sig, args):
893
+ res = builder.fcmp_ordered("<=", *args)
894
+ return impl_ret_untracked(context, builder, sig.return_type, res)
895
+
896
+
897
+ def real_gt_impl(context, builder, sig, args):
898
+ res = builder.fcmp_ordered(">", *args)
899
+ return impl_ret_untracked(context, builder, sig.return_type, res)
900
+
901
+
902
+ def real_ge_impl(context, builder, sig, args):
903
+ res = builder.fcmp_ordered(">=", *args)
904
+ return impl_ret_untracked(context, builder, sig.return_type, res)
905
+
906
+
907
+ def real_eq_impl(context, builder, sig, args):
908
+ res = builder.fcmp_ordered("==", *args)
909
+ return impl_ret_untracked(context, builder, sig.return_type, res)
910
+
911
+
912
+ def real_ne_impl(context, builder, sig, args):
913
+ res = builder.fcmp_unordered("!=", *args)
914
+ return impl_ret_untracked(context, builder, sig.return_type, res)
915
+
916
+
917
+ def real_abs_impl(context, builder, sig, args):
918
+ [ty] = sig.args
919
+ sig = typing.signature(ty, ty)
920
+ impl = context.get_function(math.fabs, sig)
921
+ return impl(builder, args)
922
+
923
+
924
+ def real_negate_impl(context, builder, sig, args):
925
+ from numba.cuda.cpython import mathimpl
926
+
927
+ res = mathimpl.negate_real(builder, args[0])
928
+ return impl_ret_untracked(context, builder, sig.return_type, res)
929
+
930
+
931
+ def real_positive_impl(context, builder, sig, args):
932
+ [typ] = sig.args
933
+ [val] = args
934
+ res = context.cast(builder, val, typ, sig.return_type)
935
+ return impl_ret_untracked(context, builder, sig.return_type, res)
936
+
937
+
938
+ def real_sign_impl(context, builder, sig, args):
939
+ """
940
+ np.sign(float)
941
+ """
942
+ [x] = args
943
+ POS = Constant(x.type, 1)
944
+ NEG = Constant(x.type, -1)
945
+ ZERO = Constant(x.type, 0)
946
+
947
+ presult = cgutils.alloca_once(builder, x.type)
948
+
949
+ is_pos = builder.fcmp_ordered(">", x, ZERO)
950
+ is_neg = builder.fcmp_ordered("<", x, ZERO)
951
+
952
+ with builder.if_else(is_pos) as (gt_zero, not_gt_zero):
953
+ with gt_zero:
954
+ builder.store(POS, presult)
955
+ with not_gt_zero:
956
+ with builder.if_else(is_neg) as (lt_zero, not_lt_zero):
957
+ with lt_zero:
958
+ builder.store(NEG, presult)
959
+ with not_lt_zero:
960
+ # For both NaN and 0, the result of sign() is simply
961
+ # the input value.
962
+ builder.store(x, presult)
963
+
964
+ res = builder.load(presult)
965
+ return impl_ret_untracked(context, builder, sig.return_type, res)
966
+
967
+
968
+ ty = types.Float
969
+
970
+ lower_builtin(operator.add, ty, ty)(real_add_impl)
971
+ lower_builtin(operator.iadd, ty, ty)(real_add_impl)
972
+ lower_builtin(operator.sub, ty, ty)(real_sub_impl)
973
+ lower_builtin(operator.isub, ty, ty)(real_sub_impl)
974
+ lower_builtin(operator.mul, ty, ty)(real_mul_impl)
975
+ lower_builtin(operator.imul, ty, ty)(real_mul_impl)
976
+ lower_builtin(operator.floordiv, ty, ty)(real_floordiv_impl)
977
+ lower_builtin(operator.ifloordiv, ty, ty)(real_floordiv_impl)
978
+ lower_builtin(operator.truediv, ty, ty)(real_div_impl)
979
+ lower_builtin(operator.itruediv, ty, ty)(real_div_impl)
980
+ lower_builtin(operator.mod, ty, ty)(real_mod_impl)
981
+ lower_builtin(operator.imod, ty, ty)(real_mod_impl)
982
+ lower_builtin(operator.pow, ty, ty)(real_power_impl)
983
+ lower_builtin(operator.ipow, ty, ty)(real_power_impl)
984
+ lower_builtin(pow, ty, ty)(real_power_impl)
985
+
986
+ lower_builtin(operator.eq, ty, ty)(real_eq_impl)
987
+ lower_builtin(operator.ne, ty, ty)(real_ne_impl)
988
+ lower_builtin(operator.lt, ty, ty)(real_lt_impl)
989
+ lower_builtin(operator.le, ty, ty)(real_le_impl)
990
+ lower_builtin(operator.gt, ty, ty)(real_gt_impl)
991
+ lower_builtin(operator.ge, ty, ty)(real_ge_impl)
992
+
993
+ lower_builtin(abs, ty)(real_abs_impl)
994
+
995
+ lower_builtin(operator.neg, ty)(real_negate_impl)
996
+ lower_builtin(operator.pos, ty)(real_positive_impl)
997
+
998
+ del ty
999
+
1000
+
1001
+ @lower_getattr(types.Complex, "real")
1002
+ def complex_real_impl(context, builder, typ, value):
1003
+ cplx = context.make_complex(builder, typ, value=value)
1004
+ res = cplx.real
1005
+ return impl_ret_untracked(context, builder, typ, res)
1006
+
1007
+
1008
+ @lower_getattr(types.Complex, "imag")
1009
+ def complex_imag_impl(context, builder, typ, value):
1010
+ cplx = context.make_complex(builder, typ, value=value)
1011
+ res = cplx.imag
1012
+ return impl_ret_untracked(context, builder, typ, res)
1013
+
1014
+
1015
+ @lower_builtin("complex.conjugate", types.Complex)
1016
+ def complex_conjugate_impl(context, builder, sig, args):
1017
+ from numba.cuda.cpython import mathimpl
1018
+
1019
+ z = context.make_complex(builder, sig.args[0], args[0])
1020
+ z.imag = mathimpl.negate_real(builder, z.imag)
1021
+ res = z._getvalue()
1022
+ return impl_ret_untracked(context, builder, sig.return_type, res)
1023
+
1024
+
1025
+ def real_real_impl(context, builder, typ, value):
1026
+ return impl_ret_untracked(context, builder, typ, value)
1027
+
1028
+
1029
+ def real_imag_impl(context, builder, typ, value):
1030
+ res = cgutils.get_null_value(value.type)
1031
+ return impl_ret_untracked(context, builder, typ, res)
1032
+
1033
+
1034
+ def real_conjugate_impl(context, builder, sig, args):
1035
+ return impl_ret_untracked(context, builder, sig.return_type, args[0])
1036
+
1037
+
1038
+ for cls in (types.Float, types.Integer):
1039
+ lower_getattr(cls, "real")(real_real_impl)
1040
+ lower_getattr(cls, "imag")(real_imag_impl)
1041
+ lower_builtin("complex.conjugate", cls)(real_conjugate_impl)
1042
+
1043
+
1044
+ @lower_builtin(operator.pow, types.Complex, types.Complex)
1045
+ @lower_builtin(operator.ipow, types.Complex, types.Complex)
1046
+ @lower_builtin(pow, types.Complex, types.Complex)
1047
+ def complex_power_impl(context, builder, sig, args):
1048
+ [ca, cb] = args
1049
+ ty = sig.args[0]
1050
+ fty = ty.underlying_float
1051
+ a = context.make_helper(builder, ty, value=ca)
1052
+ b = context.make_helper(builder, ty, value=cb)
1053
+ c = context.make_helper(builder, ty)
1054
+ module = builder.module
1055
+ pa = a._getpointer()
1056
+ pb = b._getpointer()
1057
+ pc = c._getpointer()
1058
+
1059
+ # Optimize for square because cpow loses a lot of precision
1060
+ TWO = context.get_constant(fty, 2)
1061
+ ZERO = context.get_constant(fty, 0)
1062
+
1063
+ b_real_is_two = builder.fcmp_ordered("==", b.real, TWO)
1064
+ b_imag_is_zero = builder.fcmp_ordered("==", b.imag, ZERO)
1065
+ b_is_two = builder.and_(b_real_is_two, b_imag_is_zero)
1066
+
1067
+ with builder.if_else(b_is_two) as (then, otherwise):
1068
+ with then:
1069
+ # Lower as multiplication
1070
+ res = complex_mul_impl(context, builder, sig, (ca, ca))
1071
+ cres = context.make_helper(builder, ty, value=res)
1072
+ c.real = cres.real
1073
+ c.imag = cres.imag
1074
+
1075
+ with otherwise:
1076
+ # Lower with call to external function
1077
+ func_name = {
1078
+ types.complex64: "numba_cpowf",
1079
+ types.complex128: "numba_cpow",
1080
+ }[ty]
1081
+ fnty = ir.FunctionType(ir.VoidType(), [pa.type] * 3)
1082
+ cpow = cgutils.get_or_insert_function(module, fnty, func_name)
1083
+ builder.call(cpow, (pa, pb, pc))
1084
+
1085
+ res = builder.load(pc)
1086
+ return impl_ret_untracked(context, builder, sig.return_type, res)
1087
+
1088
+
1089
+ def complex_add_impl(context, builder, sig, args):
1090
+ [cx, cy] = args
1091
+ ty = sig.args[0]
1092
+ x = context.make_complex(builder, ty, value=cx)
1093
+ y = context.make_complex(builder, ty, value=cy)
1094
+ z = context.make_complex(builder, ty)
1095
+ a = x.real
1096
+ b = x.imag
1097
+ c = y.real
1098
+ d = y.imag
1099
+ z.real = builder.fadd(a, c)
1100
+ z.imag = builder.fadd(b, d)
1101
+ res = z._getvalue()
1102
+ return impl_ret_untracked(context, builder, sig.return_type, res)
1103
+
1104
+
1105
+ def complex_sub_impl(context, builder, sig, args):
1106
+ [cx, cy] = args
1107
+ ty = sig.args[0]
1108
+ x = context.make_complex(builder, ty, value=cx)
1109
+ y = context.make_complex(builder, ty, value=cy)
1110
+ z = context.make_complex(builder, ty)
1111
+ a = x.real
1112
+ b = x.imag
1113
+ c = y.real
1114
+ d = y.imag
1115
+ z.real = builder.fsub(a, c)
1116
+ z.imag = builder.fsub(b, d)
1117
+ res = z._getvalue()
1118
+ return impl_ret_untracked(context, builder, sig.return_type, res)
1119
+
1120
+
1121
+ def complex_mul_impl(context, builder, sig, args):
1122
+ """
1123
+ (a+bi)(c+di)=(ac-bd)+i(ad+bc)
1124
+ """
1125
+ [cx, cy] = args
1126
+ ty = sig.args[0]
1127
+ x = context.make_complex(builder, ty, value=cx)
1128
+ y = context.make_complex(builder, ty, value=cy)
1129
+ z = context.make_complex(builder, ty)
1130
+ a = x.real
1131
+ b = x.imag
1132
+ c = y.real
1133
+ d = y.imag
1134
+ ac = builder.fmul(a, c)
1135
+ bd = builder.fmul(b, d)
1136
+ ad = builder.fmul(a, d)
1137
+ bc = builder.fmul(b, c)
1138
+ z.real = builder.fsub(ac, bd)
1139
+ z.imag = builder.fadd(ad, bc)
1140
+ res = z._getvalue()
1141
+ return impl_ret_untracked(context, builder, sig.return_type, res)
1142
+
1143
+
1144
+ NAN = float("nan")
1145
+
1146
+
1147
+ def complex_div_impl(context, builder, sig, args):
1148
+ def complex_div(a, b):
1149
+ # This is CPython's algorithm (in _Py_c_quot()).
1150
+ areal = a.real
1151
+ aimag = a.imag
1152
+ breal = b.real
1153
+ bimag = b.imag
1154
+ if not breal and not bimag:
1155
+ raise ZeroDivisionError("complex division by zero")
1156
+ if abs(breal) >= abs(bimag):
1157
+ # Divide tops and bottom by b.real
1158
+ if not breal:
1159
+ return complex(NAN, NAN)
1160
+ ratio = bimag / breal
1161
+ denom = breal + bimag * ratio
1162
+ return complex(
1163
+ (areal + aimag * ratio) / denom, (aimag - areal * ratio) / denom
1164
+ )
1165
+ else:
1166
+ # Divide tops and bottom by b.imag
1167
+ if not bimag:
1168
+ return complex(NAN, NAN)
1169
+ ratio = breal / bimag
1170
+ denom = breal * ratio + bimag
1171
+ return complex(
1172
+ (a.real * ratio + a.imag) / denom,
1173
+ (a.imag * ratio - a.real) / denom,
1174
+ )
1175
+
1176
+ res = context.compile_internal(builder, complex_div, sig, args)
1177
+ return impl_ret_untracked(context, builder, sig.return_type, res)
1178
+
1179
+
1180
+ def complex_negate_impl(context, builder, sig, args):
1181
+ from numba.cpython import mathimpl
1182
+
1183
+ [typ] = sig.args
1184
+ [val] = args
1185
+ cmplx = context.make_complex(builder, typ, value=val)
1186
+ res = context.make_complex(builder, typ)
1187
+ res.real = mathimpl.negate_real(builder, cmplx.real)
1188
+ res.imag = mathimpl.negate_real(builder, cmplx.imag)
1189
+ res = res._getvalue()
1190
+ return impl_ret_untracked(context, builder, sig.return_type, res)
1191
+
1192
+
1193
+ def complex_positive_impl(context, builder, sig, args):
1194
+ [val] = args
1195
+ return impl_ret_untracked(context, builder, sig.return_type, val)
1196
+
1197
+
1198
+ def complex_eq_impl(context, builder, sig, args):
1199
+ [cx, cy] = args
1200
+ typ = sig.args[0]
1201
+ x = context.make_complex(builder, typ, value=cx)
1202
+ y = context.make_complex(builder, typ, value=cy)
1203
+
1204
+ reals_are_eq = builder.fcmp_ordered("==", x.real, y.real)
1205
+ imags_are_eq = builder.fcmp_ordered("==", x.imag, y.imag)
1206
+ res = builder.and_(reals_are_eq, imags_are_eq)
1207
+ return impl_ret_untracked(context, builder, sig.return_type, res)
1208
+
1209
+
1210
+ def complex_ne_impl(context, builder, sig, args):
1211
+ [cx, cy] = args
1212
+ typ = sig.args[0]
1213
+ x = context.make_complex(builder, typ, value=cx)
1214
+ y = context.make_complex(builder, typ, value=cy)
1215
+
1216
+ reals_are_ne = builder.fcmp_unordered("!=", x.real, y.real)
1217
+ imags_are_ne = builder.fcmp_unordered("!=", x.imag, y.imag)
1218
+ res = builder.or_(reals_are_ne, imags_are_ne)
1219
+ return impl_ret_untracked(context, builder, sig.return_type, res)
1220
+
1221
+
1222
+ def complex_abs_impl(context, builder, sig, args):
1223
+ """
1224
+ abs(z) := hypot(z.real, z.imag)
1225
+ """
1226
+
1227
+ def complex_abs(z):
1228
+ return math.hypot(z.real, z.imag)
1229
+
1230
+ res = context.compile_internal(builder, complex_abs, sig, args)
1231
+ return impl_ret_untracked(context, builder, sig.return_type, res)
1232
+
1233
+
1234
+ ty = types.Complex
1235
+
1236
+ lower_builtin(operator.add, ty, ty)(complex_add_impl)
1237
+ lower_builtin(operator.iadd, ty, ty)(complex_add_impl)
1238
+ lower_builtin(operator.sub, ty, ty)(complex_sub_impl)
1239
+ lower_builtin(operator.isub, ty, ty)(complex_sub_impl)
1240
+ lower_builtin(operator.mul, ty, ty)(complex_mul_impl)
1241
+ lower_builtin(operator.imul, ty, ty)(complex_mul_impl)
1242
+ lower_builtin(operator.truediv, ty, ty)(complex_div_impl)
1243
+ lower_builtin(operator.itruediv, ty, ty)(complex_div_impl)
1244
+ lower_builtin(operator.neg, ty)(complex_negate_impl)
1245
+ lower_builtin(operator.pos, ty)(complex_positive_impl)
1246
+ # Complex modulo is deprecated in python3
1247
+
1248
+ lower_builtin(operator.eq, ty, ty)(complex_eq_impl)
1249
+ lower_builtin(operator.ne, ty, ty)(complex_ne_impl)
1250
+
1251
+ lower_builtin(abs, ty)(complex_abs_impl)
1252
+
1253
+ del ty
1254
+
1255
+
1256
+ @lower_builtin("number.item", types.Boolean)
1257
+ @lower_builtin("number.item", types.Number)
1258
+ def number_item_impl(context, builder, sig, args):
1259
+ """
1260
+ The no-op .item() method on booleans and numbers.
1261
+ """
1262
+ return args[0]
1263
+
1264
+
1265
+ # ------------------------------------------------------------------------------
1266
+
1267
+
1268
+ def number_not_impl(context, builder, sig, args):
1269
+ [typ] = sig.args
1270
+ [val] = args
1271
+ istrue = context.cast(builder, val, typ, sig.return_type)
1272
+ res = builder.not_(istrue)
1273
+ return impl_ret_untracked(context, builder, sig.return_type, res)
1274
+
1275
+
1276
+ @lower_builtin(bool, types.Boolean)
1277
+ def bool_as_bool(context, builder, sig, args):
1278
+ [val] = args
1279
+ return val
1280
+
1281
+
1282
+ @lower_builtin(bool, types.Integer)
1283
+ def int_as_bool(context, builder, sig, args):
1284
+ [val] = args
1285
+ return builder.icmp_unsigned("!=", val, Constant(val.type, 0))
1286
+
1287
+
1288
+ @lower_builtin(bool, types.Float)
1289
+ def float_as_bool(context, builder, sig, args):
1290
+ [val] = args
1291
+ return builder.fcmp_unordered("!=", val, Constant(val.type, 0.0))
1292
+
1293
+
1294
+ @lower_builtin(bool, types.Complex)
1295
+ def complex_as_bool(context, builder, sig, args):
1296
+ [typ] = sig.args
1297
+ [val] = args
1298
+ cmplx = context.make_complex(builder, typ, val)
1299
+ real, imag = cmplx.real, cmplx.imag
1300
+ zero = Constant(real.type, 0.0)
1301
+ real_istrue = builder.fcmp_unordered("!=", real, zero)
1302
+ imag_istrue = builder.fcmp_unordered("!=", imag, zero)
1303
+ return builder.or_(real_istrue, imag_istrue)
1304
+
1305
+
1306
+ for ty in (types.Integer, types.Float, types.Complex):
1307
+ lower_builtin(operator.not_, ty)(number_not_impl)
1308
+
1309
+ lower_builtin(operator.not_, types.boolean)(number_not_impl)
1310
+
1311
+
1312
+ # ------------------------------------------------------------------------------
1313
+ # Hashing numbers, see hashing.py
1314
+
1315
+ # -------------------------------------------------------------------------------
1316
+ # Implicit casts between numerics
1317
+
1318
+
1319
+ @lower_cast(types.IntegerLiteral, types.Integer)
1320
+ @lower_cast(types.IntegerLiteral, types.Float)
1321
+ @lower_cast(types.IntegerLiteral, types.Complex)
1322
+ def literal_int_to_number(context, builder, fromty, toty, val):
1323
+ lit = context.get_constant_generic(
1324
+ builder,
1325
+ fromty.literal_type,
1326
+ fromty.literal_value,
1327
+ )
1328
+ return context.cast(builder, lit, fromty.literal_type, toty)
1329
+
1330
+
1331
+ @lower_cast(types.Integer, types.Integer)
1332
+ def integer_to_integer(context, builder, fromty, toty, val):
1333
+ if toty.bitwidth == fromty.bitwidth:
1334
+ # Just a change of signedness
1335
+ return val
1336
+ elif toty.bitwidth < fromty.bitwidth:
1337
+ # Downcast
1338
+ return builder.trunc(val, context.get_value_type(toty))
1339
+ elif fromty.signed:
1340
+ # Signed upcast
1341
+ return builder.sext(val, context.get_value_type(toty))
1342
+ else:
1343
+ # Unsigned upcast
1344
+ return builder.zext(val, context.get_value_type(toty))
1345
+
1346
+
1347
+ @lower_cast(types.Integer, types.voidptr)
1348
+ def integer_to_voidptr(context, builder, fromty, toty, val):
1349
+ return builder.inttoptr(val, context.get_value_type(toty))
1350
+
1351
+
1352
+ @lower_cast(types.Float, types.Float)
1353
+ def float_to_float(context, builder, fromty, toty, val):
1354
+ lty = context.get_value_type(toty)
1355
+ if fromty.bitwidth < toty.bitwidth:
1356
+ return builder.fpext(val, lty)
1357
+ else:
1358
+ return builder.fptrunc(val, lty)
1359
+
1360
+
1361
+ @lower_cast(types.Integer, types.Float)
1362
+ def integer_to_float(context, builder, fromty, toty, val):
1363
+ lty = context.get_value_type(toty)
1364
+ if fromty.signed:
1365
+ return builder.sitofp(val, lty)
1366
+ else:
1367
+ return builder.uitofp(val, lty)
1368
+
1369
+
1370
+ @lower_cast(types.Float, types.Integer)
1371
+ def float_to_integer(context, builder, fromty, toty, val):
1372
+ lty = context.get_value_type(toty)
1373
+ if toty.signed:
1374
+ return builder.fptosi(val, lty)
1375
+ else:
1376
+ return builder.fptoui(val, lty)
1377
+
1378
+
1379
+ @lower_cast(types.Float, types.Complex)
1380
+ @lower_cast(types.Integer, types.Complex)
1381
+ def non_complex_to_complex(context, builder, fromty, toty, val):
1382
+ real = context.cast(builder, val, fromty, toty.underlying_float)
1383
+ imag = context.get_constant(toty.underlying_float, 0)
1384
+
1385
+ cmplx = context.make_complex(builder, toty)
1386
+ cmplx.real = real
1387
+ cmplx.imag = imag
1388
+ return cmplx._getvalue()
1389
+
1390
+
1391
+ @lower_cast(types.Complex, types.Complex)
1392
+ def complex_to_complex(context, builder, fromty, toty, val):
1393
+ srcty = fromty.underlying_float
1394
+ dstty = toty.underlying_float
1395
+
1396
+ src = context.make_complex(builder, fromty, value=val)
1397
+ dst = context.make_complex(builder, toty)
1398
+ dst.real = context.cast(builder, src.real, srcty, dstty)
1399
+ dst.imag = context.cast(builder, src.imag, srcty, dstty)
1400
+ return dst._getvalue()
1401
+
1402
+
1403
+ @lower_cast(types.Any, types.Boolean)
1404
+ def any_to_boolean(context, builder, fromty, toty, val):
1405
+ return context.is_true(builder, fromty, val)
1406
+
1407
+
1408
+ @lower_cast(types.Boolean, types.Number)
1409
+ def boolean_to_any(context, builder, fromty, toty, val):
1410
+ # Casting from boolean to anything first casts to int32
1411
+ asint = builder.zext(val, ir.IntType(32))
1412
+ return context.cast(builder, asint, types.int32, toty)
1413
+
1414
+
1415
+ @lower_cast(types.IntegerLiteral, types.Boolean)
1416
+ @lower_cast(types.BooleanLiteral, types.Boolean)
1417
+ def literal_int_to_boolean(context, builder, fromty, toty, val):
1418
+ lit = context.get_constant_generic(
1419
+ builder,
1420
+ fromty.literal_type,
1421
+ fromty.literal_value,
1422
+ )
1423
+ return context.is_true(builder, fromty.literal_type, lit)
1424
+
1425
+
1426
+ # -------------------------------------------------------------------------------
1427
+ # Constants
1428
+
1429
+
1430
+ @lower_constant(types.Complex)
1431
+ def constant_complex(context, builder, ty, pyval):
1432
+ fty = ty.underlying_float
1433
+ real = context.get_constant_generic(builder, fty, pyval.real)
1434
+ imag = context.get_constant_generic(builder, fty, pyval.imag)
1435
+ return Constant.literal_struct((real, imag))
1436
+
1437
+
1438
+ @lower_constant(types.Integer)
1439
+ @lower_constant(types.Float)
1440
+ @lower_constant(types.Boolean)
1441
+ def constant_integer(context, builder, ty, pyval):
1442
+ # See https://github.com/numba/numba/issues/6979
1443
+ # llvmlite ir.IntType specialises the formatting of the constant for a
1444
+ # cpython bool. A NumPy np.bool_ is not a cpython bool so force it to be one
1445
+ # so that the constant renders correctly!
1446
+ if isinstance(pyval, np.bool_):
1447
+ pyval = bool(pyval)
1448
+ lty = context.get_value_type(ty)
1449
+ return lty(pyval)
1450
+
1451
+
1452
+ # -------------------------------------------------------------------------------
1453
+ # View
1454
+
1455
+
1456
+ def scalar_view(scalar, viewty):
1457
+ """Typing for the np scalar 'view' method."""
1458
+ if isinstance(scalar, (types.Float, types.Integer)) and isinstance(
1459
+ viewty, types.abstract.DTypeSpec
1460
+ ):
1461
+ if scalar.bitwidth != viewty.dtype.bitwidth:
1462
+ raise errors.TypingError(
1463
+ "Changing the dtype of a 0d array is only supported if the "
1464
+ "itemsize is unchanged"
1465
+ )
1466
+
1467
+ def impl(scalar, viewty):
1468
+ return viewer(scalar, viewty)
1469
+
1470
+ return impl
1471
+
1472
+
1473
+ overload_method(types.Float, "view")(scalar_view)
1474
+ overload_method(types.Integer, "view")(scalar_view)