Videre
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
from os.path import dirname
|
||||
import unittest
|
||||
from unittest.suite import TestSuite
|
||||
|
||||
from numba.testing import load_testsuite
|
||||
|
||||
def load_tests(loader, tests, pattern):
|
||||
suite = TestSuite()
|
||||
suite.addTests(load_testsuite(loader, dirname(__file__)))
|
||||
return suite
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,660 @@
|
||||
# Contents in this file are referenced from the sphinx-generated docs.
|
||||
# "magictoken" is used for markers as beginning and ending of example text.
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from numba.tests.support import TestCase, captured_stdout
|
||||
from numba.core.config import IS_WIN32
|
||||
from numba.np.numpy_support import numpy_version
|
||||
|
||||
|
||||
class MatplotlibBlocker:
|
||||
'''Blocks the import of matplotlib, so that doc examples that attempt to
|
||||
plot the output don't result in plots popping up and blocking testing.'''
|
||||
|
||||
def find_spec(self, fullname, path, target=None):
|
||||
if fullname == 'matplotlib':
|
||||
msg = 'Blocked import of matplotlib for test suite run'
|
||||
raise ImportError(msg)
|
||||
|
||||
|
||||
class DocsExamplesTest(TestCase):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._mpl_blocker = MatplotlibBlocker()
|
||||
|
||||
def setUp(self):
|
||||
sys.meta_path.insert(0, self._mpl_blocker)
|
||||
|
||||
def tearDown(self):
|
||||
sys.meta_path.remove(self._mpl_blocker)
|
||||
|
||||
def test_mandelbrot(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_mandelbrot.begin
|
||||
from timeit import default_timer as timer
|
||||
try:
|
||||
from matplotlib.pylab import imshow, show
|
||||
have_mpl = True
|
||||
except ImportError:
|
||||
have_mpl = False
|
||||
import numpy as np
|
||||
from numba import jit
|
||||
|
||||
@jit(nopython=True)
|
||||
def mandel(x, y, max_iters):
|
||||
"""
|
||||
Given the real and imaginary parts of a complex number,
|
||||
determine if it is a candidate for membership in the Mandelbrot
|
||||
set given a fixed number of iterations.
|
||||
"""
|
||||
i = 0
|
||||
c = complex(x,y)
|
||||
z = 0.0j
|
||||
for i in range(max_iters):
|
||||
z = z * z + c
|
||||
if (z.real * z.real + z.imag * z.imag) >= 4:
|
||||
return i
|
||||
|
||||
return 255
|
||||
|
||||
@jit(nopython=True)
|
||||
def create_fractal(min_x, max_x, min_y, max_y, image, iters):
|
||||
height = image.shape[0]
|
||||
width = image.shape[1]
|
||||
|
||||
pixel_size_x = (max_x - min_x) / width
|
||||
pixel_size_y = (max_y - min_y) / height
|
||||
for x in range(width):
|
||||
real = min_x + x * pixel_size_x
|
||||
for y in range(height):
|
||||
imag = min_y + y * pixel_size_y
|
||||
color = mandel(real, imag, iters)
|
||||
image[y, x] = color
|
||||
|
||||
return image
|
||||
|
||||
image = np.zeros((500 * 2, 750 * 2), dtype=np.uint8)
|
||||
s = timer()
|
||||
create_fractal(-2.0, 1.0, -1.0, 1.0, image, 20)
|
||||
e = timer()
|
||||
print(e - s)
|
||||
if have_mpl:
|
||||
imshow(image)
|
||||
show()
|
||||
# magictoken.ex_mandelbrot.end
|
||||
|
||||
def test_moving_average(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_moving_average.begin
|
||||
import numpy as np
|
||||
|
||||
from numba import guvectorize
|
||||
|
||||
@guvectorize(['void(float64[:], intp[:], float64[:])'],
|
||||
'(n),()->(n)')
|
||||
def move_mean(a, window_arr, out):
|
||||
window_width = window_arr[0]
|
||||
asum = 0.0
|
||||
count = 0
|
||||
for i in range(window_width):
|
||||
asum += a[i]
|
||||
count += 1
|
||||
out[i] = asum / count
|
||||
for i in range(window_width, len(a)):
|
||||
asum += a[i] - a[i - window_width]
|
||||
out[i] = asum / count
|
||||
|
||||
arr = np.arange(20, dtype=np.float64).reshape(2, 10)
|
||||
print(arr)
|
||||
print(move_mean(arr, 3))
|
||||
# magictoken.ex_moving_average.end
|
||||
|
||||
def test_nogil(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_no_gil.begin
|
||||
import math
|
||||
import threading
|
||||
from timeit import repeat
|
||||
|
||||
import numpy as np
|
||||
from numba import jit
|
||||
|
||||
nthreads = 4
|
||||
size = 10**6
|
||||
|
||||
def func_np(a, b):
|
||||
"""
|
||||
Control function using Numpy.
|
||||
"""
|
||||
return np.exp(2.1 * a + 3.2 * b)
|
||||
|
||||
@jit('void(double[:], double[:], double[:])', nopython=True,
|
||||
nogil=True)
|
||||
def inner_func_nb(result, a, b):
|
||||
"""
|
||||
Function under test.
|
||||
"""
|
||||
for i in range(len(result)):
|
||||
result[i] = math.exp(2.1 * a[i] + 3.2 * b[i])
|
||||
|
||||
def timefunc(correct, s, func, *args, **kwargs):
|
||||
"""
|
||||
Benchmark *func* and print out its runtime.
|
||||
"""
|
||||
print(s.ljust(20), end=" ")
|
||||
# Make sure the function is compiled before the benchmark is
|
||||
# started
|
||||
res = func(*args, **kwargs)
|
||||
if correct is not None:
|
||||
assert np.allclose(res, correct), (res, correct)
|
||||
# time it
|
||||
print('{:>5.0f} ms'.format(min(repeat(
|
||||
lambda: func(*args, **kwargs), number=5, repeat=2)) * 1000))
|
||||
return res
|
||||
|
||||
def make_singlethread(inner_func):
|
||||
"""
|
||||
Run the given function inside a single thread.
|
||||
"""
|
||||
def func(*args):
|
||||
length = len(args[0])
|
||||
result = np.empty(length, dtype=np.float64)
|
||||
inner_func(result, *args)
|
||||
return result
|
||||
return func
|
||||
|
||||
def make_multithread(inner_func, numthreads):
|
||||
"""
|
||||
Run the given function inside *numthreads* threads, splitting
|
||||
its arguments into equal-sized chunks.
|
||||
"""
|
||||
def func_mt(*args):
|
||||
length = len(args[0])
|
||||
result = np.empty(length, dtype=np.float64)
|
||||
args = (result,) + args
|
||||
chunklen = (length + numthreads - 1) // numthreads
|
||||
# Create argument tuples for each input chunk
|
||||
chunks = [[arg[i * chunklen:(i + 1) * chunklen] for arg in
|
||||
args] for i in range(numthreads)]
|
||||
# Spawn one thread per chunk
|
||||
threads = [threading.Thread(target=inner_func, args=chunk)
|
||||
for chunk in chunks]
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
return result
|
||||
return func_mt
|
||||
|
||||
func_nb = make_singlethread(inner_func_nb)
|
||||
func_nb_mt = make_multithread(inner_func_nb, nthreads)
|
||||
|
||||
a = np.random.rand(size)
|
||||
b = np.random.rand(size)
|
||||
|
||||
correct = timefunc(None, "numpy (1 thread)", func_np, a, b)
|
||||
timefunc(correct, "numba (1 thread)", func_nb, a, b)
|
||||
timefunc(correct, "numba (%d threads)" % nthreads, func_nb_mt, a, b)
|
||||
# magictoken.ex_no_gil.end
|
||||
|
||||
def test_vectorize_one_signature(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_vectorize_one_signature.begin
|
||||
from numba import vectorize, float64
|
||||
|
||||
@vectorize([float64(float64, float64)])
|
||||
def f(x, y):
|
||||
return x + y
|
||||
# magictoken.ex_vectorize_one_signature.end
|
||||
|
||||
def test_vectorize_multiple_signatures(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_vectorize_multiple_signatures.begin
|
||||
from numba import vectorize, int32, int64, float32, float64
|
||||
import numpy as np
|
||||
|
||||
@vectorize([int32(int32, int32),
|
||||
int64(int64, int64),
|
||||
float32(float32, float32),
|
||||
float64(float64, float64)])
|
||||
def f(x, y):
|
||||
return x + y
|
||||
# magictoken.ex_vectorize_multiple_signatures.end
|
||||
|
||||
# magictoken.ex_vectorize_return_call_one.begin
|
||||
a = np.arange(6)
|
||||
result = f(a, a)
|
||||
# result == array([ 0, 2, 4, 6, 8, 10])
|
||||
# magictoken.ex_vectorize_return_call_one.end
|
||||
|
||||
self.assertIsInstance(result, np.ndarray)
|
||||
correct = np.array([0, 2, 4, 6, 8, 10])
|
||||
np.testing.assert_array_equal(result, correct)
|
||||
|
||||
# magictoken.ex_vectorize_return_call_two.begin
|
||||
a = np.linspace(0, 1, 6)
|
||||
result = f(a, a)
|
||||
# Now, result == array([0. , 0.4, 0.8, 1.2, 1.6, 2. ])
|
||||
# magictoken.ex_vectorize_return_call_two.end
|
||||
|
||||
self.assertIsInstance(result, np.ndarray)
|
||||
correct = np.array([0., 0.4, 0.8, 1.2, 1.6, 2. ])
|
||||
np.testing.assert_allclose(result, correct)
|
||||
|
||||
# magictoken.ex_vectorize_return_call_three.begin
|
||||
a = np.arange(12).reshape(3, 4)
|
||||
# a == array([[ 0, 1, 2, 3],
|
||||
# [ 4, 5, 6, 7],
|
||||
# [ 8, 9, 10, 11]])
|
||||
|
||||
result1 = f.reduce(a, axis=0)
|
||||
# result1 == array([12, 15, 18, 21])
|
||||
|
||||
result2 = f.reduce(a, axis=1)
|
||||
# result2 == array([ 6, 22, 38])
|
||||
|
||||
result3 = f.accumulate(a)
|
||||
# result3 == array([[ 0, 1, 2, 3],
|
||||
# [ 4, 6, 8, 10],
|
||||
# [12, 15, 18, 21]])
|
||||
|
||||
result4 = f.accumulate(a, axis=1)
|
||||
# result3 == array([[ 0, 1, 3, 6],
|
||||
# [ 4, 9, 15, 22],
|
||||
# [ 8, 17, 27, 38]])
|
||||
# magictoken.ex_vectorize_return_call_three.end
|
||||
|
||||
self.assertIsInstance(result1, np.ndarray)
|
||||
correct = np.array([12, 15, 18, 21])
|
||||
np.testing.assert_array_equal(result1, correct)
|
||||
|
||||
self.assertIsInstance(result2, np.ndarray)
|
||||
correct = np.array([6, 22, 38])
|
||||
np.testing.assert_array_equal(result2, correct)
|
||||
|
||||
self.assertIsInstance(result3, np.ndarray)
|
||||
correct = np.array([
|
||||
[0, 1, 2, 3],
|
||||
[4, 6, 8, 10],
|
||||
[12, 15, 18, 21]
|
||||
])
|
||||
np.testing.assert_array_equal(result3, correct)
|
||||
|
||||
self.assertIsInstance(result4, np.ndarray)
|
||||
correct = np.array([
|
||||
[0, 1, 3, 6],
|
||||
[4, 9, 15, 22],
|
||||
[8, 17, 27, 38]
|
||||
])
|
||||
np.testing.assert_array_equal(result4, correct)
|
||||
|
||||
def test_guvectorize(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_guvectorize.begin
|
||||
from numba import guvectorize, int64
|
||||
import numpy as np
|
||||
|
||||
@guvectorize([(int64[:], int64, int64[:])], '(n),()->(n)')
|
||||
def g(x, y, res):
|
||||
for i in range(x.shape[0]):
|
||||
res[i] = x[i] + y
|
||||
# magictoken.ex_guvectorize.end
|
||||
|
||||
# magictoken.ex_guvectorize_call_one.begin
|
||||
a = np.arange(5)
|
||||
result = g(a, 2)
|
||||
# result == array([2, 3, 4, 5, 6])
|
||||
# magictoken.ex_guvectorize_call_one.end
|
||||
|
||||
self.assertIsInstance(result, np.ndarray)
|
||||
correct = np.array([2, 3, 4, 5, 6])
|
||||
np.testing.assert_array_equal(result, correct)
|
||||
|
||||
# magictoken.ex_guvectorize_call_two.begin
|
||||
a = np.arange(6).reshape(2, 3)
|
||||
# a == array([[0, 1, 2],
|
||||
# [3, 4, 5]])
|
||||
|
||||
result1 = g(a, 10)
|
||||
# result1 == array([[10, 11, 12],
|
||||
# [13, 14, 15]])
|
||||
|
||||
result2 = g(a, np.array([10, 20]))
|
||||
g(a, np.array([10, 20]))
|
||||
# result2 == array([[10, 11, 12],
|
||||
# [23, 24, 25]])
|
||||
# magictoken.ex_guvectorize_call_two.end
|
||||
|
||||
self.assertIsInstance(result1, np.ndarray)
|
||||
correct = np.array([[10, 11, 12], [13, 14, 15]])
|
||||
np.testing.assert_array_equal(result1, correct)
|
||||
|
||||
self.assertIsInstance(result2, np.ndarray)
|
||||
correct = np.array([[10, 11, 12], [23, 24, 25]])
|
||||
np.testing.assert_array_equal(result2, correct)
|
||||
|
||||
def test_guvectorize_scalar_return(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_guvectorize_scalar_return.begin
|
||||
from numba import guvectorize, int64
|
||||
import numpy as np
|
||||
|
||||
@guvectorize([(int64[:], int64, int64[:])], '(n),()->()')
|
||||
def g(x, y, res):
|
||||
acc = 0
|
||||
for i in range(x.shape[0]):
|
||||
acc += x[i] + y
|
||||
res[0] = acc
|
||||
# magictoken.ex_guvectorize_scalar_return.end
|
||||
|
||||
# magictoken.ex_guvectorize_scalar_return_call.begin
|
||||
a = np.arange(5)
|
||||
result = g(a, 2)
|
||||
# At this point, result == 20.
|
||||
# magictoken.ex_guvectorize_scalar_return_call.end
|
||||
|
||||
self.assertIsInstance(result, np.integer)
|
||||
self.assertEqual(result, 20)
|
||||
|
||||
def test_guvectorize_jit(self):
|
||||
with captured_stdout():
|
||||
# magictoken.gufunc_jit.begin
|
||||
import numpy as np
|
||||
|
||||
from numba import jit, guvectorize
|
||||
|
||||
@guvectorize('(n)->(n)')
|
||||
def copy(x, res):
|
||||
for i in range(x.shape[0]):
|
||||
res[i] = x[i]
|
||||
|
||||
@jit(nopython=True)
|
||||
def jit_fn(x, res):
|
||||
copy(x, res)
|
||||
# magictoken.gufunc_jit.end
|
||||
|
||||
# magictoken.gufunc_jit_call.begin
|
||||
x = np.arange(5, dtype='i4')
|
||||
res = np.zeros_like(x)
|
||||
jit_fn(x, res)
|
||||
# At this point, res == np.array([0, 1, 2, 3, 4], 'i4').
|
||||
# magictoken.gufunc_jit_call.end
|
||||
self.assertPreciseEqual(x, res)
|
||||
|
||||
def test_guvectorize_jit_fail(self):
|
||||
with captured_stdout():
|
||||
# magictoken.gufunc_jit_fail.begin
|
||||
import numpy as np
|
||||
from numba import jit, guvectorize
|
||||
|
||||
@guvectorize('(n)->(n)')
|
||||
def copy(x, res):
|
||||
for i in range(x.shape[0]):
|
||||
res[i] = x[i]
|
||||
|
||||
@jit(nopython=True)
|
||||
def jit_fn(x, res):
|
||||
copy(x, res)
|
||||
|
||||
x = np.ones((1, 5))
|
||||
res = np.empty((5,))
|
||||
with self.assertRaises(ValueError) as raises:
|
||||
jit_fn(x, res)
|
||||
# magictoken.gufunc_jit_fail.end
|
||||
self.assertIn('Loop and array shapes are incompatible',
|
||||
str(raises.exception))
|
||||
|
||||
def test_guvectorize_overwrite(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_guvectorize_overwrite.begin
|
||||
from numba import guvectorize, float64
|
||||
import numpy as np
|
||||
|
||||
@guvectorize([(float64[:], float64[:])], '()->()')
|
||||
def init_values(invals, outvals):
|
||||
invals[0] = 6.5
|
||||
outvals[0] = 4.2
|
||||
# magictoken.ex_guvectorize_overwrite.end
|
||||
|
||||
# magictoken.ex_guvectorize_overwrite_call_one.begin
|
||||
invals = np.zeros(shape=(3, 3), dtype=np.float64)
|
||||
# invals == array([[6.5, 6.5, 6.5],
|
||||
# [6.5, 6.5, 6.5],
|
||||
# [6.5, 6.5, 6.5]])
|
||||
|
||||
outvals = init_values(invals)
|
||||
# outvals == array([[4.2, 4.2, 4.2],
|
||||
# [4.2, 4.2, 4.2],
|
||||
# [4.2, 4.2, 4.2]])
|
||||
# magictoken.ex_guvectorize_overwrite_call_one.end
|
||||
|
||||
self.assertIsInstance(invals, np.ndarray)
|
||||
correct = np.array([
|
||||
[6.5, 6.5, 6.5],
|
||||
[6.5, 6.5, 6.5],
|
||||
[6.5, 6.5, 6.5]])
|
||||
np.testing.assert_array_equal(invals, correct)
|
||||
|
||||
self.assertIsInstance(outvals, np.ndarray)
|
||||
correct = np.array([
|
||||
[4.2, 4.2, 4.2],
|
||||
[4.2, 4.2, 4.2],
|
||||
[4.2, 4.2, 4.2]])
|
||||
np.testing.assert_array_equal(outvals, correct)
|
||||
|
||||
# magictoken.ex_guvectorize_overwrite_call_two.begin
|
||||
invals = np.zeros(shape=(3, 3), dtype=np.float32)
|
||||
# invals == array([[0., 0., 0.],
|
||||
# [0., 0., 0.],
|
||||
# [0., 0., 0.]], dtype=float32)
|
||||
outvals = init_values(invals)
|
||||
# outvals == array([[4.2, 4.2, 4.2],
|
||||
# [4.2, 4.2, 4.2],
|
||||
# [4.2, 4.2, 4.2]])
|
||||
print(invals)
|
||||
# invals == array([[0., 0., 0.],
|
||||
# [0., 0., 0.],
|
||||
# [0., 0., 0.]], dtype=float32)
|
||||
# magictoken.ex_guvectorize_overwrite_call_two.end
|
||||
|
||||
self.assertIsInstance(invals, np.ndarray)
|
||||
correct = np.array([
|
||||
[0., 0., 0.],
|
||||
[0., 0., 0.],
|
||||
[0., 0., 0.]], dtype=np.float32)
|
||||
np.testing.assert_array_equal(invals, correct)
|
||||
|
||||
self.assertIsInstance(outvals, np.ndarray)
|
||||
correct = np.array([
|
||||
[4.2, 4.2, 4.2],
|
||||
[4.2, 4.2, 4.2],
|
||||
[4.2, 4.2, 4.2]])
|
||||
np.testing.assert_array_equal(outvals, correct)
|
||||
|
||||
# magictoken.ex_guvectorize_overwrite_call_three.begin
|
||||
@guvectorize(
|
||||
[(float64[:], float64[:])],
|
||||
'()->()',
|
||||
writable_args=('invals',)
|
||||
)
|
||||
def init_values(invals, outvals):
|
||||
invals[0] = 6.5
|
||||
outvals[0] = 4.2
|
||||
|
||||
invals = np.zeros(shape=(3, 3), dtype=np.float32)
|
||||
# invals == array([[0., 0., 0.],
|
||||
# [0., 0., 0.],
|
||||
# [0., 0., 0.]], dtype=float32)
|
||||
outvals = init_values(invals)
|
||||
# outvals == array([[4.2, 4.2, 4.2],
|
||||
# [4.2, 4.2, 4.2],
|
||||
# [4.2, 4.2, 4.2]])
|
||||
print(invals)
|
||||
# invals == array([[6.5, 6.5, 6.5],
|
||||
# [6.5, 6.5, 6.5],
|
||||
# [6.5, 6.5, 6.5]], dtype=float32)
|
||||
# magictoken.ex_guvectorize_overwrite_call_three.end
|
||||
|
||||
self.assertIsInstance(invals, np.ndarray)
|
||||
correct = np.array([
|
||||
[6.5, 6.5, 6.5],
|
||||
[6.5, 6.5, 6.5],
|
||||
[6.5, 6.5, 6.5]])
|
||||
np.testing.assert_array_equal(invals, correct)
|
||||
|
||||
self.assertIsInstance(outvals, np.ndarray)
|
||||
correct = np.array([
|
||||
[4.2, 4.2, 4.2],
|
||||
[4.2, 4.2, 4.2],
|
||||
[4.2, 4.2, 4.2]])
|
||||
np.testing.assert_array_equal(outvals, correct)
|
||||
|
||||
def test_vectorize_dynamic(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_vectorize_dynamic.begin
|
||||
from numba import vectorize
|
||||
|
||||
@vectorize
|
||||
def f(x, y):
|
||||
return x * y
|
||||
# magictoken.ex_vectorize_dynamic.end
|
||||
|
||||
# magictoken.ex_vectorize_dynamic_call_one.begin
|
||||
result = f(3,4)
|
||||
# result == 12
|
||||
|
||||
print(f.types)
|
||||
# ['ll->l']
|
||||
# magictoken.ex_vectorize_dynamic_call_one.end
|
||||
|
||||
self.assertEqual(result, 12)
|
||||
if IS_WIN32:
|
||||
if numpy_version < (2, 0):
|
||||
correct = ['ll->q']
|
||||
else:
|
||||
correct = ['qq->q']
|
||||
else:
|
||||
correct = ['ll->l']
|
||||
self.assertEqual(f.types, correct)
|
||||
|
||||
# magictoken.ex_vectorize_dynamic_call_two.begin
|
||||
result = f(1.,2.)
|
||||
# result == 2.0
|
||||
|
||||
print(f.types)
|
||||
# ['ll->l', 'dd->d']
|
||||
# magictoken.ex_vectorize_dynamic_call_two.end
|
||||
|
||||
self.assertEqual(result, 2.0)
|
||||
if IS_WIN32:
|
||||
if numpy_version < (2, 0):
|
||||
correct = ['ll->q', 'dd->d']
|
||||
else:
|
||||
correct = ['qq->q', 'dd->d']
|
||||
else:
|
||||
correct = ['ll->l', 'dd->d']
|
||||
self.assertEqual(f.types, correct)
|
||||
|
||||
# magictoken.ex_vectorize_dynamic_call_three.begin
|
||||
result = f(1,2.)
|
||||
# result == 2.0
|
||||
|
||||
print(f.types)
|
||||
# ['ll->l', 'dd->d']
|
||||
# magictoken.ex_vectorize_dynamic_call_three.end
|
||||
|
||||
self.assertEqual(result, 2.0)
|
||||
if IS_WIN32:
|
||||
if numpy_version < (2, 0):
|
||||
correct = ['ll->q', 'dd->d']
|
||||
else:
|
||||
correct = ['qq->q', 'dd->d']
|
||||
else:
|
||||
correct = ['ll->l', 'dd->d']
|
||||
self.assertEqual(f.types, correct)
|
||||
|
||||
# magictoken.ex_vectorize_dynamic_call_four.begin
|
||||
@vectorize
|
||||
def g(a, b):
|
||||
return a / b
|
||||
|
||||
print(g(2.,3.))
|
||||
# 0.66666666666666663
|
||||
|
||||
print(g(2,3))
|
||||
# 0.66666666666666663
|
||||
|
||||
print(g.types)
|
||||
# ['dd->d']
|
||||
# magictoken.ex_vectorize_dynamic_call_four.end
|
||||
|
||||
correct = ['dd->d']
|
||||
self.assertEqual(g.types, correct)
|
||||
|
||||
def test_guvectorize_dynamic(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_guvectorize_dynamic.begin
|
||||
from numba import guvectorize
|
||||
import numpy as np
|
||||
|
||||
@guvectorize('(n),()->(n)')
|
||||
def g(x, y, res):
|
||||
for i in range(x.shape[0]):
|
||||
res[i] = x[i] + y
|
||||
# magictoken.ex_guvectorize_dynamic.end
|
||||
|
||||
# magictoken.ex_guvectorize_dynamic_call_one.begin
|
||||
x = np.arange(5, dtype=np.int64)
|
||||
y = 10
|
||||
res = np.zeros_like(x)
|
||||
g(x, y, res)
|
||||
# res == array([10, 11, 12, 13, 14])
|
||||
print(g.types)
|
||||
# ['ll->l']
|
||||
# magictoken.ex_guvectorize_dynamic_call_one.end
|
||||
|
||||
correct = np.array([10, 11, 12, 13, 14])
|
||||
np.testing.assert_array_equal(res, correct)
|
||||
if IS_WIN32:
|
||||
correct = ['qq->q']
|
||||
else:
|
||||
correct = ['ll->l']
|
||||
self.assertEqual(g.types, correct)
|
||||
|
||||
# magictoken.ex_guvectorize_dynamic_call_two.begin
|
||||
x = np.arange(5, dtype=np.double)
|
||||
y = 2.2
|
||||
res = np.zeros_like(x)
|
||||
g(x, y, res)
|
||||
# res == array([2.2, 3.2, 4.2, 5.2, 6.2])
|
||||
# magictoken.ex_guvectorize_dynamic_call_two.end
|
||||
|
||||
# magictoken.ex_guvectorize_dynamic_call_three.begin
|
||||
print(g.types) # shorthand for g.ufunc.types
|
||||
# ['ll->l', 'dd->d']
|
||||
# magictoken.ex_guvectorize_dynamic_call_three.end
|
||||
|
||||
if IS_WIN32:
|
||||
correct = ['qq->q', 'dd->d']
|
||||
else:
|
||||
correct = ['ll->l', 'dd->d']
|
||||
self.assertEqual(g.types, correct)
|
||||
|
||||
# magictoken.ex_guvectorize_dynamic_call_four.begin
|
||||
x = np.arange(5, dtype=np.int64)
|
||||
y = 2
|
||||
res = np.zeros_like(x)
|
||||
g(x, y, res)
|
||||
print(res)
|
||||
# res == array([2, 3, 4, 5, 6])
|
||||
# magictoken.ex_guvectorize_dynamic_call_four.end
|
||||
|
||||
correct = np.array([2, 3, 4, 5, 6])
|
||||
np.testing.assert_array_equal(res, correct)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,242 @@
|
||||
"""
|
||||
This test is used by `docs/source/extending/interval-example.rst`.
|
||||
|
||||
The "magictoken" comments are used as markers for the beginning and ending of
|
||||
example code.
|
||||
"""
|
||||
import unittest
|
||||
|
||||
|
||||
class IntervalExampleTest(unittest.TestCase):
|
||||
|
||||
def test_interval_class_usage(self):
|
||||
# magictoken.interval_py_class.begin
|
||||
class Interval(object):
|
||||
"""
|
||||
A half-open interval on the real number line.
|
||||
"""
|
||||
def __init__(self, lo, hi):
|
||||
self.lo = lo
|
||||
self.hi = hi
|
||||
|
||||
def __repr__(self):
|
||||
return 'Interval(%f, %f)' % (self.lo, self.hi)
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
return self.hi - self.lo
|
||||
# magictoken.interval_py_class.end
|
||||
|
||||
# magictoken.interval_type_class.begin
|
||||
from numba import types
|
||||
|
||||
class IntervalType(types.Type):
|
||||
def __init__(self):
|
||||
super(IntervalType, self).__init__(name='Interval')
|
||||
|
||||
interval_type = IntervalType()
|
||||
# magictoken.interval_type_class.end
|
||||
|
||||
# magictoken.interval_typeof_register.begin
|
||||
from numba.extending import typeof_impl
|
||||
|
||||
@typeof_impl.register(Interval)
|
||||
def typeof_index(val, c):
|
||||
return interval_type
|
||||
# magictoken.interval_typeof_register.end
|
||||
|
||||
# magictoken.numba_type_register.begin
|
||||
from numba.extending import as_numba_type
|
||||
|
||||
as_numba_type.register(Interval, interval_type)
|
||||
# magictoken.numba_type_register.end
|
||||
|
||||
# magictoken.numba_type_callable.begin
|
||||
from numba.extending import type_callable
|
||||
|
||||
@type_callable(Interval)
|
||||
def type_interval(context):
|
||||
def typer(lo, hi):
|
||||
if isinstance(lo, types.Float) and isinstance(hi, types.Float):
|
||||
return interval_type
|
||||
return typer
|
||||
# magictoken.numba_type_callable.end
|
||||
|
||||
# magictoken.interval_model.begin
|
||||
from numba.extending import models, register_model
|
||||
|
||||
@register_model(IntervalType)
|
||||
class IntervalModel(models.StructModel):
|
||||
def __init__(self, dmm, fe_type):
|
||||
members = [('lo', types.float64),
|
||||
('hi', types.float64),]
|
||||
models.StructModel.__init__(self, dmm, fe_type, members)
|
||||
# magictoken.interval_model.end
|
||||
|
||||
# magictoken.interval_attribute_wrapper.begin
|
||||
from numba.extending import make_attribute_wrapper
|
||||
|
||||
make_attribute_wrapper(IntervalType, 'lo', 'lo')
|
||||
make_attribute_wrapper(IntervalType, 'hi', 'hi')
|
||||
# magictoken.interval_attribute_wrapper.end
|
||||
|
||||
# magictoken.interval_overload_attribute.begin
|
||||
from numba.extending import overload_attribute
|
||||
|
||||
@overload_attribute(IntervalType, "width")
|
||||
def get_width(interval):
|
||||
def getter(interval):
|
||||
return interval.hi - interval.lo
|
||||
return getter
|
||||
# magictoken.interval_overload_attribute.end
|
||||
|
||||
# magictoken.interval_lower_builtin.begin
|
||||
from numba.extending import lower_builtin
|
||||
from numba.core import cgutils
|
||||
|
||||
@lower_builtin(Interval, types.Float, types.Float)
|
||||
def impl_interval(context, builder, sig, args):
|
||||
typ = sig.return_type
|
||||
lo, hi = args
|
||||
interval = cgutils.create_struct_proxy(typ)(context, builder)
|
||||
interval.lo = lo
|
||||
interval.hi = hi
|
||||
return interval._getvalue()
|
||||
# magictoken.interval_lower_builtin.end
|
||||
|
||||
# magictoken.interval_unbox.begin
|
||||
from numba.extending import unbox, NativeValue
|
||||
from contextlib import ExitStack
|
||||
|
||||
@unbox(IntervalType)
|
||||
def unbox_interval(typ, obj, c):
|
||||
"""
|
||||
Convert a Interval object to a native interval structure.
|
||||
"""
|
||||
is_error_ptr = cgutils.alloca_once_value(c.builder, cgutils.false_bit)
|
||||
interval = cgutils.create_struct_proxy(typ)(c.context, c.builder)
|
||||
|
||||
with ExitStack() as stack:
|
||||
lo_obj = c.pyapi.object_getattr_string(obj, "lo")
|
||||
with cgutils.early_exit_if_null(c.builder, stack, lo_obj):
|
||||
c.builder.store(cgutils.true_bit, is_error_ptr)
|
||||
lo_native = c.unbox(types.float64, lo_obj)
|
||||
c.pyapi.decref(lo_obj)
|
||||
with cgutils.early_exit_if(c.builder, stack, lo_native.is_error):
|
||||
c.builder.store(cgutils.true_bit, is_error_ptr)
|
||||
|
||||
hi_obj = c.pyapi.object_getattr_string(obj, "hi")
|
||||
with cgutils.early_exit_if_null(c.builder, stack, hi_obj):
|
||||
c.builder.store(cgutils.true_bit, is_error_ptr)
|
||||
hi_native = c.unbox(types.float64, hi_obj)
|
||||
c.pyapi.decref(hi_obj)
|
||||
with cgutils.early_exit_if(c.builder, stack, hi_native.is_error):
|
||||
c.builder.store(cgutils.true_bit, is_error_ptr)
|
||||
|
||||
interval.lo = lo_native.value
|
||||
interval.hi = hi_native.value
|
||||
|
||||
return NativeValue(interval._getvalue(), is_error=c.builder.load(is_error_ptr))
|
||||
# magictoken.interval_unbox.end
|
||||
|
||||
# magictoken.interval_box.begin
|
||||
from numba.extending import box
|
||||
|
||||
@box(IntervalType)
|
||||
def box_interval(typ, val, c):
|
||||
"""
|
||||
Convert a native interval structure to an Interval object.
|
||||
"""
|
||||
ret_ptr = cgutils.alloca_once(c.builder, c.pyapi.pyobj)
|
||||
fail_obj = c.pyapi.get_null_object()
|
||||
|
||||
with ExitStack() as stack:
|
||||
interval = cgutils.create_struct_proxy(typ)(c.context, c.builder, value=val)
|
||||
lo_obj = c.box(types.float64, interval.lo)
|
||||
with cgutils.early_exit_if_null(c.builder, stack, lo_obj):
|
||||
c.builder.store(fail_obj, ret_ptr)
|
||||
|
||||
hi_obj = c.box(types.float64, interval.hi)
|
||||
with cgutils.early_exit_if_null(c.builder, stack, hi_obj):
|
||||
c.pyapi.decref(lo_obj)
|
||||
c.builder.store(fail_obj, ret_ptr)
|
||||
|
||||
class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(Interval))
|
||||
with cgutils.early_exit_if_null(c.builder, stack, class_obj):
|
||||
c.pyapi.decref(lo_obj)
|
||||
c.pyapi.decref(hi_obj)
|
||||
c.builder.store(fail_obj, ret_ptr)
|
||||
|
||||
# NOTE: The result of this call is not checked as the clean up
|
||||
# has to occur regardless of whether it is successful. If it
|
||||
# fails `res` is set to NULL and a Python exception is set.
|
||||
res = c.pyapi.call_function_objargs(class_obj, (lo_obj, hi_obj))
|
||||
c.pyapi.decref(lo_obj)
|
||||
c.pyapi.decref(hi_obj)
|
||||
c.pyapi.decref(class_obj)
|
||||
c.builder.store(res, ret_ptr)
|
||||
|
||||
return c.builder.load(ret_ptr)
|
||||
# magictoken.interval_box.end
|
||||
|
||||
# magictoken.interval_usage.begin
|
||||
from numba import njit
|
||||
|
||||
@njit
|
||||
def inside_interval(interval, x):
|
||||
return interval.lo <= x < interval.hi
|
||||
|
||||
@njit
|
||||
def interval_width(interval):
|
||||
return interval.width
|
||||
|
||||
@njit
|
||||
def sum_intervals(i, j):
|
||||
return Interval(i.lo + j.lo, i.hi + j.hi)
|
||||
# magictoken.interval_usage.end
|
||||
|
||||
def check_equal_intervals(x, y):
|
||||
self.assertIsInstance(x, Interval)
|
||||
self.assertIsInstance(y, Interval)
|
||||
self.assertEqual(x.lo, y.lo)
|
||||
self.assertEqual(x.hi, y.hi)
|
||||
|
||||
a = Interval(2, 3)
|
||||
b = Interval(4, 5)
|
||||
c = Interval(6, 8)
|
||||
|
||||
# Test box-unbox
|
||||
return_func = njit(lambda x: x)
|
||||
check_equal_intervals(a, return_func(a))
|
||||
|
||||
# Test .width attribute
|
||||
self.assertEqual(a.width, interval_width(a))
|
||||
|
||||
# Test exceptions
|
||||
class NotAFloat:
|
||||
def __float__(self):
|
||||
raise RuntimeError("I am not a float")
|
||||
|
||||
# TODO: This should produce a `RuntimeError`, but the `unbox` handler for `float` ignores
|
||||
# the error raised by `__float__`, leading to a subsequent `TypeError` cause by passing
|
||||
# `NULL` to `PyFloat_AsDouble`.
|
||||
# This isn't the fault of the `Interval` extension that is being testing
|
||||
# in this file.
|
||||
with self.assertRaises(TypeError):
|
||||
interval_width(Interval(2, NotAFloat()))
|
||||
|
||||
bad_interval = Interval(1, 2)
|
||||
del bad_interval.hi
|
||||
|
||||
with self.assertRaises(AttributeError):
|
||||
interval_width(bad_interval)
|
||||
|
||||
# Test .lo and .hi usage
|
||||
self.assertFalse(inside_interval(a, 5))
|
||||
|
||||
# Test native Interval constructor
|
||||
check_equal_intervals(c, sum_intervals(a, b))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,97 @@
|
||||
# Contents in this file are referenced from the sphinx-generated docs.
|
||||
# "magictoken" is used for markers as beginning and ending of example text.
|
||||
|
||||
import unittest
|
||||
from numba.tests.support import TestCase
|
||||
|
||||
|
||||
class DocsJitclassUsageTest(TestCase):
|
||||
|
||||
def test_ex_jitclass(self):
|
||||
# magictoken.ex_jitclass.begin
|
||||
import numpy as np
|
||||
from numba import int32, float32 # import the types
|
||||
from numba.experimental import jitclass
|
||||
|
||||
spec = [
|
||||
('value', int32), # a simple scalar field
|
||||
('array', float32[:]), # an array field
|
||||
]
|
||||
|
||||
@jitclass(spec)
|
||||
class Bag(object):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
self.array = np.zeros(value, dtype=np.float32)
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
return self.array.size
|
||||
|
||||
def increment(self, val):
|
||||
for i in range(self.size):
|
||||
self.array[i] += val
|
||||
return self.array
|
||||
|
||||
@staticmethod
|
||||
def add(x, y):
|
||||
return x + y
|
||||
|
||||
n = 21
|
||||
mybag = Bag(n)
|
||||
# magictoken.ex_jitclass.end
|
||||
|
||||
self.assertTrue(isinstance(mybag, Bag))
|
||||
self.assertPreciseEqual(mybag.value, n)
|
||||
np.testing.assert_allclose(mybag.array, np.zeros(n, dtype=np.float32))
|
||||
self.assertPreciseEqual(mybag.size, n)
|
||||
np.testing.assert_allclose(mybag.increment(3),
|
||||
3 * np.ones(n, dtype=np.float32))
|
||||
np.testing.assert_allclose(mybag.increment(6),
|
||||
9 * np.ones(n, dtype=np.float32))
|
||||
self.assertPreciseEqual(mybag.add(1, 1), 2)
|
||||
self.assertPreciseEqual(Bag.add(1, 2), 3)
|
||||
|
||||
def test_ex_jitclass_type_hints(self):
|
||||
# magictoken.ex_jitclass_type_hints.begin
|
||||
from typing import List
|
||||
from numba.experimental import jitclass
|
||||
from numba.typed import List as NumbaList
|
||||
|
||||
@jitclass
|
||||
class Counter:
|
||||
value: int
|
||||
|
||||
def __init__(self):
|
||||
self.value = 0
|
||||
|
||||
def get(self) -> int:
|
||||
ret = self.value
|
||||
self.value += 1
|
||||
return ret
|
||||
|
||||
@jitclass
|
||||
class ListLoopIterator:
|
||||
counter: Counter
|
||||
items: List[float]
|
||||
|
||||
def __init__(self, items: List[float]):
|
||||
self.items = items
|
||||
self.counter = Counter()
|
||||
|
||||
def get(self) -> float:
|
||||
idx = self.counter.get() % len(self.items)
|
||||
return self.items[idx]
|
||||
|
||||
items = NumbaList([3.14, 2.718, 0.123, -4.])
|
||||
loop_itr = ListLoopIterator(items)
|
||||
# magictoken.ex_jitclass_type_hints.end
|
||||
|
||||
for idx in range(10):
|
||||
self.assertEqual(loop_itr.counter.value, idx)
|
||||
self.assertAlmostEqual(loop_itr.get(), items[idx % len(items)])
|
||||
self.assertEqual(loop_itr.counter.value, idx + 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,161 @@
|
||||
# Contents in this file are referenced from the sphinx-generated docs.
|
||||
# "magictoken" is used for markers as beginning and ending of example text.
|
||||
|
||||
import unittest
|
||||
from numba.tests.support import captured_stdout
|
||||
from numba import typed
|
||||
|
||||
|
||||
class DocsLiteralContainerUsageTest(unittest.TestCase):
|
||||
|
||||
def test_ex_literal_dict_compile_time_consts(self):
|
||||
with captured_stdout():
|
||||
# magictoken.test_ex_literal_dict_compile_time_consts.begin
|
||||
import numpy as np
|
||||
from numba import njit, types
|
||||
from numba.extending import overload
|
||||
|
||||
# overload this function
|
||||
def specialize(x):
|
||||
pass
|
||||
|
||||
@overload(specialize)
|
||||
def ol_specialize(x):
|
||||
ld = x.literal_value
|
||||
const_expr = []
|
||||
for k, v in ld.items():
|
||||
if isinstance(v, types.Literal):
|
||||
lv = v.literal_value
|
||||
if lv == 'cat':
|
||||
const_expr.append("Meow!")
|
||||
elif lv == 'dog':
|
||||
const_expr.append("Woof!")
|
||||
elif isinstance(lv, int):
|
||||
const_expr.append(k.literal_value * lv)
|
||||
else: # it's an array
|
||||
const_expr.append("Array(dim={dim}".format(dim=v.ndim))
|
||||
const_strings = tuple(const_expr)
|
||||
|
||||
def impl(x):
|
||||
return const_strings
|
||||
return impl
|
||||
|
||||
@njit
|
||||
def foo():
|
||||
pets_ints_and_array = {'a': 1,
|
||||
'b': 2,
|
||||
'c': 'cat',
|
||||
'd': 'dog',
|
||||
'e': np.ones(5,)}
|
||||
return specialize(pets_ints_and_array)
|
||||
|
||||
result = foo()
|
||||
print(result) # ('a', 'bb', 'Meow!', 'Woof!', 'Array(dim=1')
|
||||
# magictoken.test_ex_literal_dict_compile_time_consts.end
|
||||
|
||||
self.assertEqual(result, ('a', 'bb', 'Meow!', 'Woof!', 'Array(dim=1'))
|
||||
|
||||
def test_ex_initial_value_dict_compile_time_consts(self):
|
||||
with captured_stdout():
|
||||
# magictoken.test_ex_initial_value_dict_compile_time_consts.begin
|
||||
from numba import njit, literally
|
||||
from numba.extending import overload
|
||||
|
||||
# overload this function
|
||||
def specialize(x):
|
||||
pass
|
||||
|
||||
@overload(specialize)
|
||||
def ol_specialize(x):
|
||||
iv = x.initial_value
|
||||
if iv is None:
|
||||
return lambda x: literally(x) # Force literal dispatch
|
||||
assert iv == {'a': 1, 'b': 2, 'c': 3} # INITIAL VALUE
|
||||
return lambda x: literally(x)
|
||||
|
||||
@njit
|
||||
def foo():
|
||||
d = {'a': 1, 'b': 2, 'c': 3}
|
||||
d['c'] = 20 # no impact on .initial_value
|
||||
d['d'] = 30 # no impact on .initial_value
|
||||
return specialize(d)
|
||||
|
||||
result = foo()
|
||||
print(result) # {a: 1, b: 2, c: 20, d: 30} # NOT INITIAL VALUE!
|
||||
# magictoken.test_ex_initial_value_dict_compile_time_consts.end
|
||||
|
||||
expected = typed.Dict()
|
||||
for k, v in {'a': 1, 'b': 2, 'c': 20, 'd': 30}.items():
|
||||
expected[k] = v
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_ex_literal_list(self):
|
||||
with captured_stdout():
|
||||
# magictoken.test_ex_literal_list.begin
|
||||
from numba import njit
|
||||
from numba.extending import overload
|
||||
|
||||
# overload this function
|
||||
def specialize(x):
|
||||
pass
|
||||
|
||||
@overload(specialize)
|
||||
def ol_specialize(x):
|
||||
l = x.literal_value
|
||||
const_expr = []
|
||||
for v in l:
|
||||
const_expr.append(str(v))
|
||||
const_strings = tuple(const_expr)
|
||||
|
||||
def impl(x):
|
||||
return const_strings
|
||||
return impl
|
||||
|
||||
@njit
|
||||
def foo():
|
||||
const_list = ['a', 10, 1j, ['another', 'list']]
|
||||
return specialize(const_list)
|
||||
|
||||
result = foo()
|
||||
print(result) # ('Literal[str](a)', 'Literal[int](10)', 'complex128', 'list(unicode_type)') # noqa E501
|
||||
# magictoken.test_ex_literal_list.end
|
||||
|
||||
expected = ('Literal[str](a)', 'Literal[int](10)', 'complex128',
|
||||
"list(unicode_type)<iv=['another', 'list']>")
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_ex_initial_value_list_compile_time_consts(self):
|
||||
with captured_stdout():
|
||||
# magictoken.test_ex_initial_value_list_compile_time_consts.begin
|
||||
from numba import njit, literally
|
||||
from numba.extending import overload
|
||||
|
||||
# overload this function
|
||||
def specialize(x):
|
||||
pass
|
||||
|
||||
@overload(specialize)
|
||||
def ol_specialize(x):
|
||||
iv = x.initial_value
|
||||
if iv is None:
|
||||
return lambda x: literally(x) # Force literal dispatch
|
||||
assert iv == [1, 2, 3] # INITIAL VALUE
|
||||
return lambda x: x
|
||||
|
||||
@njit
|
||||
def foo():
|
||||
l = [1, 2, 3]
|
||||
l[2] = 20 # no impact on .initial_value
|
||||
l.append(30) # no impact on .initial_value
|
||||
return specialize(l)
|
||||
|
||||
result = foo()
|
||||
print(result) # [1, 2, 20, 30] # NOT INITIAL VALUE!
|
||||
# magictoken.test_ex_initial_value_list_compile_time_consts.end
|
||||
|
||||
expected = [1, 2, 20, 30]
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,59 @@
|
||||
# "magictoken" is used for markers as beginning and ending of example text.
|
||||
|
||||
import unittest
|
||||
from numba.tests.support import captured_stdout
|
||||
|
||||
|
||||
class DocsLiterallyUsageTest(unittest.TestCase):
|
||||
|
||||
def test_literally_usage(self):
|
||||
with captured_stdout() as stdout:
|
||||
# magictoken.ex_literally_usage.begin
|
||||
import numba
|
||||
|
||||
def power(x, n):
|
||||
raise NotImplementedError
|
||||
|
||||
@numba.extending.overload(power)
|
||||
def ov_power(x, n):
|
||||
if isinstance(n, numba.types.Literal):
|
||||
# only if `n` is a literal
|
||||
if n.literal_value == 2:
|
||||
# special case: square
|
||||
print("square")
|
||||
return lambda x, n: x * x
|
||||
elif n.literal_value == 3:
|
||||
# special case: cubic
|
||||
print("cubic")
|
||||
return lambda x, n: x * x * x
|
||||
else:
|
||||
# If `n` is not literal, request literal dispatch
|
||||
return lambda x, n: numba.literally(n)
|
||||
|
||||
print("generic")
|
||||
return lambda x, n: x ** n
|
||||
|
||||
@numba.njit
|
||||
def test_power(x, n):
|
||||
return power(x, n)
|
||||
|
||||
# should print "square" and "9"
|
||||
print(test_power(3, 2))
|
||||
|
||||
# should print "cubic" and "27"
|
||||
print(test_power(3, 3))
|
||||
|
||||
# should print "generic" and "81"
|
||||
print(test_power(3, 4))
|
||||
|
||||
# magictoken.ex_literally_usage.end
|
||||
assert test_power(3, 2) == 3 ** 2
|
||||
assert test_power(3, 3) == 3 ** 3
|
||||
assert test_power(3, 4) == 3 ** 4
|
||||
|
||||
self.assertEqual('square\n9\ncubic\n27\ngeneric\n81\n',
|
||||
stdout.getvalue())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,31 @@
|
||||
# "magictoken" is used for markers as beginning and ending of example text.
|
||||
|
||||
import unittest
|
||||
from numba.tests.support import captured_stdout, override_config
|
||||
|
||||
|
||||
class DocsLLVMPassTimings(unittest.TestCase):
|
||||
|
||||
def test_pass_timings(self):
|
||||
with override_config('LLVM_PASS_TIMINGS', True):
|
||||
with captured_stdout() as stdout:
|
||||
# magictoken.ex_llvm_pass_timings.begin
|
||||
import numba
|
||||
|
||||
@numba.njit
|
||||
def foo(n):
|
||||
c = 0
|
||||
for i in range(n):
|
||||
for j in range(i):
|
||||
c += j
|
||||
return c
|
||||
|
||||
foo(10)
|
||||
md = foo.get_metadata(foo.signatures[0])
|
||||
print(md['llvm_pass_timings'])
|
||||
# magictoken.ex_llvm_pass_timings.end
|
||||
self.assertIn("Finalize object", stdout.getvalue())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,38 @@
|
||||
# "magictoken" is used for markers as beginning and ending of example text.
|
||||
|
||||
import unittest
|
||||
import numpy as np
|
||||
import numba
|
||||
|
||||
|
||||
class NumpyGeneratorUsageTest(unittest.TestCase):
|
||||
|
||||
def test_numpy_gen_usage(self):
|
||||
# magictoken.npgen_usage.begin
|
||||
x = np.random.default_rng(1)
|
||||
y = np.random.default_rng(1)
|
||||
|
||||
size = 10
|
||||
|
||||
@numba.njit
|
||||
def do_stuff(gen):
|
||||
return gen.random(size=int(size / 2))
|
||||
|
||||
original = x.random(size=size)
|
||||
# [0.51182162 0.9504637 0.14415961 0.94864945 0.31183145
|
||||
# 0.42332645 0.82770259 0.40919914 0.54959369 0.02755911]
|
||||
|
||||
numba_func_res = do_stuff(y)
|
||||
# [0.51182162 0.9504637 0.14415961 0.94864945 0.31183145]
|
||||
|
||||
after_numba = y.random(size=int(size / 2))
|
||||
# [0.42332645 0.82770259 0.40919914 0.54959369 0.02755911]
|
||||
|
||||
# magictoken.npgen_usage.end
|
||||
numba_res = np.concatenate((numba_func_res, after_numba))
|
||||
for _np_res, _nb_res in zip(original, numba_res):
|
||||
self.assertEqual(_np_res, _nb_res)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,122 @@
|
||||
# Contents in this file are referenced from the sphinx-generated docs.
|
||||
# "magictoken" is used for markers as beginning and ending of example text.
|
||||
|
||||
import unittest
|
||||
from numba.tests.support import captured_stdout, skip_parfors_unsupported
|
||||
from numba import set_parallel_chunksize
|
||||
from numba.tests.support import TestCase
|
||||
|
||||
|
||||
@skip_parfors_unsupported
|
||||
class ChunksizeExamplesTest(TestCase):
|
||||
|
||||
_numba_parallel_test_ = False
|
||||
|
||||
def setUp(self):
|
||||
set_parallel_chunksize(0)
|
||||
|
||||
def tearDown(self):
|
||||
set_parallel_chunksize(0)
|
||||
|
||||
def test_unbalanced_example(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_unbalanced.begin
|
||||
from numba import (njit,
|
||||
prange,
|
||||
)
|
||||
import numpy as np
|
||||
|
||||
@njit(parallel=True)
|
||||
def func1():
|
||||
n = 100
|
||||
vals = np.empty(n)
|
||||
# The work in each iteration of the following prange
|
||||
# loop is proportional to its index.
|
||||
for i in prange(n):
|
||||
cur = i + 1
|
||||
for j in range(i):
|
||||
if cur % 2 == 0:
|
||||
cur //= 2
|
||||
else:
|
||||
cur = cur * 3 + 1
|
||||
vals[i] = cur
|
||||
return vals
|
||||
|
||||
result = func1()
|
||||
# magictoken.ex_unbalanced.end
|
||||
self.assertPreciseEqual(result, func1.py_func())
|
||||
|
||||
def test_chunksize_manual(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_chunksize_manual.begin
|
||||
from numba import (njit,
|
||||
prange,
|
||||
set_parallel_chunksize,
|
||||
get_parallel_chunksize,
|
||||
)
|
||||
|
||||
@njit(parallel=True)
|
||||
def func1(n):
|
||||
acc = 0
|
||||
print(get_parallel_chunksize()) # Will print 4.
|
||||
for i in prange(n):
|
||||
print(get_parallel_chunksize()) # Will print 0.
|
||||
acc += i
|
||||
print(get_parallel_chunksize()) # Will print 4.
|
||||
return acc
|
||||
|
||||
@njit(parallel=True)
|
||||
def func2(n):
|
||||
acc = 0
|
||||
# This version gets the previous chunksize explicitly.
|
||||
old_chunksize = get_parallel_chunksize()
|
||||
set_parallel_chunksize(8)
|
||||
for i in prange(n):
|
||||
acc += i
|
||||
set_parallel_chunksize(old_chunksize)
|
||||
return acc
|
||||
|
||||
# This version saves the previous chunksize as returned
|
||||
# by set_parallel_chunksize.
|
||||
old_chunksize = set_parallel_chunksize(4)
|
||||
result1 = func1(12)
|
||||
result2 = func2(12)
|
||||
result3 = func1(12)
|
||||
set_parallel_chunksize(old_chunksize)
|
||||
# magictoken.ex_chunksize_manual.end
|
||||
self.assertPreciseEqual(result1, func1.py_func(12))
|
||||
self.assertPreciseEqual(result2, func2.py_func(12))
|
||||
self.assertPreciseEqual(result3, func1.py_func(12))
|
||||
|
||||
def test_chunksize_with(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_chunksize_with.begin
|
||||
from numba import njit, prange, parallel_chunksize
|
||||
|
||||
@njit(parallel=True)
|
||||
def func1(n):
|
||||
acc = 0
|
||||
for i in prange(n):
|
||||
acc += i
|
||||
return acc
|
||||
|
||||
@njit(parallel=True)
|
||||
def func2(n):
|
||||
acc = 0
|
||||
with parallel_chunksize(8):
|
||||
for i in prange(n):
|
||||
acc += i
|
||||
return acc
|
||||
|
||||
with parallel_chunksize(4):
|
||||
result1 = func1(12)
|
||||
result2 = func2(12)
|
||||
result3 = func1(12)
|
||||
# magictoken.ex_chunksize_with.end
|
||||
self.assertPreciseEqual(result1, func1.py_func(12))
|
||||
self.assertPreciseEqual(result2, func2.py_func(12))
|
||||
self.assertPreciseEqual(result3, func1.py_func(12))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,46 @@
|
||||
import unittest
|
||||
|
||||
|
||||
class TestExample(unittest.TestCase):
|
||||
|
||||
def test_documentation_example1(self):
|
||||
# magictoken.ex_rec_arr_const_index.begin
|
||||
import numpy as np
|
||||
from numba import njit
|
||||
|
||||
arr = np.array([(1, 2)], dtype=[('a1', 'f8'), ('a2', 'f8')])
|
||||
fields_gl = ('a1', 'a2')
|
||||
|
||||
@njit
|
||||
def get_field_sum(rec):
|
||||
fields_lc = ('a1', 'a2')
|
||||
field_name1 = fields_lc[0]
|
||||
field_name2 = fields_gl[1]
|
||||
return rec[field_name1] + rec[field_name2]
|
||||
|
||||
get_field_sum(arr[0]) # returns 3
|
||||
# magictoken.ex_rec_arr_const_index.end
|
||||
self.assertEqual(get_field_sum(arr[0]), 3)
|
||||
|
||||
def test_documentation_example2(self):
|
||||
# magictoken.ex_rec_arr_lit_unroll_index.begin
|
||||
import numpy as np
|
||||
from numba import njit, literal_unroll
|
||||
|
||||
arr = np.array([(1, 2)], dtype=[('a1', 'f8'), ('a2', 'f8')])
|
||||
fields_gl = ('a1', 'a2')
|
||||
|
||||
@njit
|
||||
def get_field_sum(rec):
|
||||
out = 0
|
||||
for f in literal_unroll(fields_gl):
|
||||
out += rec[f]
|
||||
return out
|
||||
|
||||
get_field_sum(arr[0]) # returns 3
|
||||
# magictoken.ex_rec_arr_lit_unroll_index.end
|
||||
self.assertEqual(get_field_sum(arr[0]), 3)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,149 @@
|
||||
# "magictoken" is used for markers as beginning and ending of example text.
|
||||
|
||||
import unittest
|
||||
|
||||
# magictoken.ex_structref_type_definition.begin
|
||||
import numpy as np
|
||||
|
||||
from numba import njit
|
||||
from numba.core import types
|
||||
from numba.experimental import structref
|
||||
|
||||
from numba.tests.support import skip_unless_scipy
|
||||
|
||||
|
||||
# Define a StructRef.
|
||||
# `structref.register` associates the type with the default data model.
|
||||
# This will also install getters and setters to the fields of
|
||||
# the StructRef.
|
||||
@structref.register
|
||||
class MyStructType(types.StructRef):
|
||||
def preprocess_fields(self, fields):
|
||||
# This method is called by the type constructor for additional
|
||||
# preprocessing on the fields.
|
||||
# Here, we don't want the struct to take Literal types.
|
||||
return tuple((name, types.unliteral(typ)) for name, typ in fields)
|
||||
|
||||
|
||||
# Define a Python type that can be use as a proxy to the StructRef
|
||||
# allocated inside Numba. Users can construct the StructRef via
|
||||
# the constructor for this type in python code and jit-code.
|
||||
class MyStruct(structref.StructRefProxy):
|
||||
def __new__(cls, name, vector):
|
||||
# Overriding the __new__ method is optional, doing so
|
||||
# allows Python code to use keyword arguments,
|
||||
# or add other customized behavior.
|
||||
# The default __new__ takes `*args`.
|
||||
# IMPORTANT: Users should not override __init__.
|
||||
return structref.StructRefProxy.__new__(cls, name, vector)
|
||||
|
||||
# By default, the proxy type does not reflect the attributes or
|
||||
# methods to the Python side. It is up to users to define
|
||||
# these. (This may be automated in the future.)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
# To access a field, we can define a function that simply
|
||||
# return the field in jit-code.
|
||||
# The definition of MyStruct_get_name is shown later.
|
||||
return MyStruct_get_name(self)
|
||||
|
||||
@property
|
||||
def vector(self):
|
||||
# The definition of MyStruct_get_vector is shown later.
|
||||
return MyStruct_get_vector(self)
|
||||
|
||||
|
||||
@njit
|
||||
def MyStruct_get_name(self):
|
||||
# In jit-code, the StructRef's attribute is exposed via
|
||||
# structref.register
|
||||
return self.name
|
||||
|
||||
|
||||
@njit
|
||||
def MyStruct_get_vector(self):
|
||||
return self.vector
|
||||
|
||||
|
||||
# This associates the proxy with MyStructType for the given set of
|
||||
# fields. Notice how we are not constraining the type of each field.
|
||||
# Field types remain generic.
|
||||
structref.define_proxy(MyStruct, MyStructType, ["name", "vector"])
|
||||
# magictoken.ex_structref_type_definition.end
|
||||
|
||||
|
||||
@skip_unless_scipy
|
||||
class TestStructRefUsage(unittest.TestCase):
|
||||
def test_type_definition(self):
|
||||
np.random.seed(0)
|
||||
# Redirect print
|
||||
buf = []
|
||||
|
||||
def print(*args):
|
||||
buf.append(args)
|
||||
|
||||
# magictoken.ex_structref_type_definition_test.begin
|
||||
# Let's test our new StructRef.
|
||||
|
||||
# Define one in Python
|
||||
alice = MyStruct("Alice", vector=np.random.random(3))
|
||||
|
||||
# Define one in jit-code
|
||||
@njit
|
||||
def make_bob():
|
||||
bob = MyStruct("unnamed", vector=np.zeros(3))
|
||||
# Mutate the attributes
|
||||
bob.name = "Bob"
|
||||
bob.vector = np.random.random(3)
|
||||
return bob
|
||||
|
||||
bob = make_bob()
|
||||
|
||||
# Out: Alice: [0.5488135 0.71518937 0.60276338]
|
||||
print(f"{alice.name}: {alice.vector}")
|
||||
# Out: Bob: [0.88325739 0.73527629 0.87746707]
|
||||
print(f"{bob.name}: {bob.vector}")
|
||||
|
||||
# Define a jit function to operate on the structs.
|
||||
@njit
|
||||
def distance(a, b):
|
||||
return np.linalg.norm(a.vector - b.vector)
|
||||
|
||||
# Out: 0.4332647200356598
|
||||
print(distance(alice, bob))
|
||||
# magictoken.ex_structref_type_definition_test.end
|
||||
|
||||
self.assertEqual(len(buf), 3)
|
||||
|
||||
def test_overload_method(self):
|
||||
# magictoken.ex_structref_method.begin
|
||||
from numba.core.extending import overload_method
|
||||
from numba.core.errors import TypingError
|
||||
|
||||
# Use @overload_method to add a method for
|
||||
# MyStructType.distance(other)
|
||||
# where *other* is an instance of MyStructType.
|
||||
@overload_method(MyStructType, "distance")
|
||||
def ol_distance(self, other):
|
||||
# Guard that *other* is an instance of MyStructType
|
||||
if not isinstance(other, MyStructType):
|
||||
raise TypingError(
|
||||
f"*other* must be a {MyStructType}; got {other}"
|
||||
)
|
||||
|
||||
def impl(self, other):
|
||||
return np.linalg.norm(self.vector - other.vector)
|
||||
|
||||
return impl
|
||||
|
||||
# Test
|
||||
@njit
|
||||
def test():
|
||||
alice = MyStruct("Alice", vector=np.random.random(3))
|
||||
bob = MyStruct("Bob", vector=np.random.random(3))
|
||||
# Use the method
|
||||
return alice.distance(bob)
|
||||
# magictoken.ex_structref_method.end
|
||||
|
||||
self.assertIsInstance(test(), float)
|
||||
@@ -0,0 +1,111 @@
|
||||
# Contents in this file are referenced from the sphinx-generated docs.
|
||||
# "magictoken" is used for markers as beginning and ending of example text.
|
||||
|
||||
import unittest
|
||||
from numba.tests.support import captured_stdout
|
||||
|
||||
|
||||
class DocsTypedDictUsageTest(unittest.TestCase):
|
||||
|
||||
def test_ex_typed_dict_from_cpython(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_typed_dict_from_cpython.begin
|
||||
import numpy as np
|
||||
from numba import njit
|
||||
from numba.core import types
|
||||
from numba.typed import Dict
|
||||
|
||||
# The Dict.empty() constructs a typed dictionary.
|
||||
# The key and value typed must be explicitly declared.
|
||||
d = Dict.empty(
|
||||
key_type=types.unicode_type,
|
||||
value_type=types.float64[:],
|
||||
)
|
||||
|
||||
# The typed-dict can be used from the interpreter.
|
||||
d['posx'] = np.asarray([1, 0.5, 2], dtype='f8')
|
||||
d['posy'] = np.asarray([1.5, 3.5, 2], dtype='f8')
|
||||
d['velx'] = np.asarray([0.5, 0, 0.7], dtype='f8')
|
||||
d['vely'] = np.asarray([0.2, -0.2, 0.1], dtype='f8')
|
||||
|
||||
# Here's a function that expects a typed-dict as the argument
|
||||
@njit
|
||||
def move(d):
|
||||
# inplace operations on the arrays
|
||||
d['posx'] += d['velx']
|
||||
d['posy'] += d['vely']
|
||||
|
||||
print('posx: ', d['posx']) # Out: posx: [1. 0.5 2. ]
|
||||
print('posy: ', d['posy']) # Out: posy: [1.5 3.5 2. ]
|
||||
|
||||
# Call move(d) to inplace update the arrays in the typed-dict.
|
||||
move(d)
|
||||
|
||||
print('posx: ', d['posx']) # Out: posx: [1.5 0.5 2.7]
|
||||
print('posy: ', d['posy']) # Out: posy: [1.7 3.3 2.1]
|
||||
# magictoken.ex_typed_dict_from_cpython.end
|
||||
|
||||
# Test
|
||||
np.testing.assert_array_equal(d['posx'], [1.5, 0.5, 2.7])
|
||||
np.testing.assert_array_equal(d['posy'], [1.7, 3.3, 2.1])
|
||||
|
||||
def test_ex_typed_dict_njit(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_typed_dict_njit.begin
|
||||
import numpy as np
|
||||
from numba import njit
|
||||
from numba.core import types
|
||||
from numba.typed import Dict
|
||||
|
||||
# Make array type. Type-expression is not supported in jit
|
||||
# functions.
|
||||
float_array = types.float64[:]
|
||||
|
||||
@njit
|
||||
def foo():
|
||||
# Make dictionary
|
||||
d = Dict.empty(
|
||||
key_type=types.unicode_type,
|
||||
value_type=float_array,
|
||||
)
|
||||
# Fill the dictionary
|
||||
d["posx"] = np.arange(3).astype(np.float64)
|
||||
d["posy"] = np.arange(3, 6).astype(np.float64)
|
||||
return d
|
||||
|
||||
d = foo()
|
||||
# Print the dictionary
|
||||
print(d) # Out: {posx: [0. 1. 2.], posy: [3. 4. 5.]}
|
||||
# magictoken.ex_typed_dict_njit.end
|
||||
np.testing.assert_array_equal(d['posx'], [0, 1, 2])
|
||||
np.testing.assert_array_equal(d['posy'], [3, 4, 5])
|
||||
|
||||
def test_ex_inferred_dict_njit(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_inferred_dict_njit.begin
|
||||
from numba import njit
|
||||
import numpy as np
|
||||
|
||||
@njit
|
||||
def foo():
|
||||
d = dict()
|
||||
k = {1: np.arange(1), 2: np.arange(2)}
|
||||
# The following tells the compiler what the key type and the
|
||||
# value
|
||||
# type are for `d`.
|
||||
d[3] = np.arange(3)
|
||||
d[5] = np.arange(5)
|
||||
return d, k
|
||||
|
||||
d, k = foo()
|
||||
print(d) # {3: [0 1 2], 5: [0 1 2 3 4]}
|
||||
print(k) # {1: [0], 2: [0 1]}
|
||||
# magictoken.ex_inferred_dict_njit.end
|
||||
np.testing.assert_array_equal(d[3], [0, 1, 2])
|
||||
np.testing.assert_array_equal(d[5], [0, 1, 2, 3, 4])
|
||||
np.testing.assert_array_equal(k[1], [0])
|
||||
np.testing.assert_array_equal(k[2], [0, 1])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,95 @@
|
||||
# Contents in this file are referenced from the sphinx-generated docs.
|
||||
# "magictoken" is used for markers as beginning and ending of example text.
|
||||
|
||||
import unittest
|
||||
from numba.tests.support import captured_stdout
|
||||
|
||||
|
||||
class DocsTypedListUsageTest(unittest.TestCase):
|
||||
|
||||
def test_ex_inferred_list_jit(self):
|
||||
with captured_stdout():
|
||||
|
||||
# magictoken.ex_inferred_list_jit.begin
|
||||
from numba import njit
|
||||
from numba.typed import List
|
||||
|
||||
@njit
|
||||
def foo():
|
||||
# Instantiate a typed-list
|
||||
l = List()
|
||||
# Append a value to it, this will set the type to int32/int64
|
||||
# (depending on platform)
|
||||
l.append(42)
|
||||
# The usual list operations, getitem, pop and length are
|
||||
# supported
|
||||
print(l[0]) # 42
|
||||
l[0] = 23
|
||||
print(l[0]) # 23
|
||||
print(len(l)) # 1
|
||||
l.pop()
|
||||
print(len(l)) # 0
|
||||
return l
|
||||
|
||||
foo()
|
||||
|
||||
# magictoken.ex_inferred_list_jit.end
|
||||
|
||||
def test_ex_inferred_list(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_inferred_list.begin
|
||||
from numba import njit
|
||||
from numba.typed import List
|
||||
|
||||
@njit
|
||||
def foo(mylist):
|
||||
for i in range(10, 20):
|
||||
mylist.append(i)
|
||||
return mylist
|
||||
|
||||
# Instantiate a typed-list, outside of a jit context
|
||||
l = List()
|
||||
# Append a value to it, this will set the type to int32/int64
|
||||
# (depending on platform)
|
||||
l.append(42)
|
||||
# The usual list operations, getitem, pop and length are supported
|
||||
print(l[0]) # 42
|
||||
l[0] = 23
|
||||
print(l[0]) # 23
|
||||
print(len(l)) # 1
|
||||
l.pop()
|
||||
print(len(l)) # 0
|
||||
|
||||
# And you can use the typed-list as an argument for a jit compiled
|
||||
# function
|
||||
l = foo(l)
|
||||
print(len(l)) # 10
|
||||
|
||||
# You can also directly construct a typed-list from an existing
|
||||
# Python list
|
||||
py_list = [2, 3, 5]
|
||||
numba_list = List(py_list)
|
||||
print(len(numba_list)) # 3
|
||||
|
||||
# magictoken.ex_inferred_list.end
|
||||
|
||||
def test_ex_nested_list(self):
|
||||
with captured_stdout():
|
||||
# magictoken.ex_nested_list.begin
|
||||
from numba.typed import List
|
||||
|
||||
# typed-lists can be nested in typed-lists
|
||||
mylist = List()
|
||||
for i in range(10):
|
||||
l = List()
|
||||
for i in range(10):
|
||||
l.append(i)
|
||||
mylist.append(l)
|
||||
# mylist is now a list of 10 lists, each containing 10 integers
|
||||
print(mylist)
|
||||
|
||||
# magictoken.ex_nested_list.end
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user