1r""" 2Building the required library in this example requires a source distribution 3of NumPy or clone of the NumPy git repository since distributions.c is not 4included in binary distributions. 5 6On *nix, execute in numpy/random/src/distributions 7 8export ${PYTHON_VERSION}=3.8 # Python version 9export PYTHON_INCLUDE=#path to Python's include folder, usually \ 10 ${PYTHON_HOME}/include/python${PYTHON_VERSION}m 11export NUMPY_INCLUDE=#path to numpy's include folder, usually \ 12 ${PYTHON_HOME}/lib/python${PYTHON_VERSION}/site-packages/numpy/core/include 13gcc -shared -o libdistributions.so -fPIC distributions.c \ 14 -I${NUMPY_INCLUDE} -I${PYTHON_INCLUDE} 15mv libdistributions.so ../../_examples/numba/ 16 17On Windows 18 19rem PYTHON_HOME and PYTHON_VERSION are setup dependent, this is an example 20set PYTHON_HOME=c:\Anaconda 21set PYTHON_VERSION=38 22cl.exe /LD .\distributions.c -DDLL_EXPORT \ 23 -I%PYTHON_HOME%\lib\site-packages\numpy\core\include \ 24 -I%PYTHON_HOME%\include %PYTHON_HOME%\libs\python%PYTHON_VERSION%.lib 25move distributions.dll ../../_examples/numba/ 26""" 27import os 28 29import numba as nb 30import numpy as np 31from cffi import FFI 32 33from numpy.random import PCG64 34 35ffi = FFI() 36if os.path.exists('./distributions.dll'): 37 lib = ffi.dlopen('./distributions.dll') 38elif os.path.exists('./libdistributions.so'): 39 lib = ffi.dlopen('./libdistributions.so') 40else: 41 raise RuntimeError('Required DLL/so file was not found.') 42 43ffi.cdef(""" 44double random_standard_normal(void *bitgen_state); 45""") 46x = PCG64() 47xffi = x.cffi 48bit_generator = xffi.bit_generator 49 50random_standard_normal = lib.random_standard_normal 51 52 53def normals(n, bit_generator): 54 out = np.empty(n) 55 for i in range(n): 56 out[i] = random_standard_normal(bit_generator) 57 return out 58 59 60normalsj = nb.jit(normals, nopython=True) 61 62# Numba requires a memory address for void * 63# Can also get address from x.ctypes.bit_generator.value 64bit_generator_address = int(ffi.cast('uintptr_t', bit_generator)) 65 66norm = normalsj(1000, bit_generator_address) 67print(norm[:12]) 68