virtuelle Umgebungen teil20 und teil20a
This commit is contained in:
		
										
											Binary file not shown.
										
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
#cython: language_level=3
 | 
			
		||||
 | 
			
		||||
from libc.stdint cimport uint32_t
 | 
			
		||||
from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
cimport numpy as np
 | 
			
		||||
cimport cython
 | 
			
		||||
 | 
			
		||||
from numpy.random cimport bitgen_t
 | 
			
		||||
from numpy.random import PCG64
 | 
			
		||||
 | 
			
		||||
np.import_array()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@cython.boundscheck(False)
 | 
			
		||||
@cython.wraparound(False)
 | 
			
		||||
def uniform_mean(Py_ssize_t n):
 | 
			
		||||
    cdef Py_ssize_t i
 | 
			
		||||
    cdef bitgen_t *rng
 | 
			
		||||
    cdef const char *capsule_name = "BitGenerator"
 | 
			
		||||
    cdef double[::1] random_values
 | 
			
		||||
    cdef np.ndarray randoms
 | 
			
		||||
 | 
			
		||||
    x = PCG64()
 | 
			
		||||
    capsule = x.capsule
 | 
			
		||||
    if not PyCapsule_IsValid(capsule, capsule_name):
 | 
			
		||||
        raise ValueError("Invalid pointer to anon_func_state")
 | 
			
		||||
    rng = <bitgen_t *> PyCapsule_GetPointer(capsule, capsule_name)
 | 
			
		||||
    random_values = np.empty(n)
 | 
			
		||||
    # Best practice is to acquire the lock whenever generating random values.
 | 
			
		||||
    # This prevents other threads from modifying the state. Acquiring the lock
 | 
			
		||||
    # is only necessary if the GIL is also released, as in this example.
 | 
			
		||||
    with x.lock, nogil:
 | 
			
		||||
        for i in range(n):
 | 
			
		||||
            random_values[i] = rng.next_double(rng.state)
 | 
			
		||||
    randoms = np.asarray(random_values)
 | 
			
		||||
    return randoms.mean()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# This function is declared nogil so it can be used without the GIL below
 | 
			
		||||
cdef uint32_t bounded_uint(uint32_t lb, uint32_t ub, bitgen_t *rng) nogil:
 | 
			
		||||
    cdef uint32_t mask, delta, val
 | 
			
		||||
    mask = delta = ub - lb
 | 
			
		||||
    mask |= mask >> 1
 | 
			
		||||
    mask |= mask >> 2
 | 
			
		||||
    mask |= mask >> 4
 | 
			
		||||
    mask |= mask >> 8
 | 
			
		||||
    mask |= mask >> 16
 | 
			
		||||
 | 
			
		||||
    val = rng.next_uint32(rng.state) & mask
 | 
			
		||||
    while val > delta:
 | 
			
		||||
        val = rng.next_uint32(rng.state) & mask
 | 
			
		||||
 | 
			
		||||
    return lb + val
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@cython.boundscheck(False)
 | 
			
		||||
@cython.wraparound(False)
 | 
			
		||||
def bounded_uints(uint32_t lb, uint32_t ub, Py_ssize_t n):
 | 
			
		||||
    cdef Py_ssize_t i
 | 
			
		||||
    cdef bitgen_t *rng
 | 
			
		||||
    cdef uint32_t[::1] out
 | 
			
		||||
    cdef const char *capsule_name = "BitGenerator"
 | 
			
		||||
 | 
			
		||||
    x = PCG64()
 | 
			
		||||
    out = np.empty(n, dtype=np.uint32)
 | 
			
		||||
    capsule = x.capsule
 | 
			
		||||
 | 
			
		||||
    if not PyCapsule_IsValid(capsule, capsule_name):
 | 
			
		||||
        raise ValueError("Invalid pointer to anon_func_state")
 | 
			
		||||
    rng = <bitgen_t *>PyCapsule_GetPointer(capsule, capsule_name)
 | 
			
		||||
 | 
			
		||||
    with x.lock, nogil:
 | 
			
		||||
        for i in range(n):
 | 
			
		||||
            out[i] = bounded_uint(lb, ub, rng)
 | 
			
		||||
    return np.asarray(out)
 | 
			
		||||
@@ -0,0 +1,117 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
#cython: language_level=3
 | 
			
		||||
"""
 | 
			
		||||
This file shows how the to use a BitGenerator to create a distribution.
 | 
			
		||||
"""
 | 
			
		||||
import numpy as np
 | 
			
		||||
cimport numpy as np
 | 
			
		||||
cimport cython
 | 
			
		||||
from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer
 | 
			
		||||
from libc.stdint cimport uint16_t, uint64_t
 | 
			
		||||
from numpy.random cimport bitgen_t
 | 
			
		||||
from numpy.random import PCG64
 | 
			
		||||
from numpy.random.c_distributions cimport (
 | 
			
		||||
      random_standard_uniform_fill, random_standard_uniform_fill_f)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@cython.boundscheck(False)
 | 
			
		||||
@cython.wraparound(False)
 | 
			
		||||
def uniforms(Py_ssize_t n):
 | 
			
		||||
    """
 | 
			
		||||
    Create an array of `n` uniformly distributed doubles.
 | 
			
		||||
    A 'real' distribution would want to process the values into
 | 
			
		||||
    some non-uniform distribution
 | 
			
		||||
    """
 | 
			
		||||
    cdef Py_ssize_t i
 | 
			
		||||
    cdef bitgen_t *rng
 | 
			
		||||
    cdef const char *capsule_name = "BitGenerator"
 | 
			
		||||
    cdef double[::1] random_values
 | 
			
		||||
 | 
			
		||||
    x = PCG64()
 | 
			
		||||
    capsule = x.capsule
 | 
			
		||||
    # Optional check that the capsule if from a BitGenerator
 | 
			
		||||
    if not PyCapsule_IsValid(capsule, capsule_name):
 | 
			
		||||
        raise ValueError("Invalid pointer to anon_func_state")
 | 
			
		||||
    # Cast the pointer
 | 
			
		||||
    rng = <bitgen_t *> PyCapsule_GetPointer(capsule, capsule_name)
 | 
			
		||||
    random_values = np.empty(n, dtype='float64')
 | 
			
		||||
    with x.lock, nogil:
 | 
			
		||||
        for i in range(n):
 | 
			
		||||
            # Call the function
 | 
			
		||||
            random_values[i] = rng.next_double(rng.state)
 | 
			
		||||
    randoms = np.asarray(random_values)
 | 
			
		||||
 | 
			
		||||
    return randoms
 | 
			
		||||
 | 
			
		||||
# cython example 2
 | 
			
		||||
@cython.boundscheck(False)
 | 
			
		||||
@cython.wraparound(False)
 | 
			
		||||
def uint10_uniforms(Py_ssize_t n):
 | 
			
		||||
    """Uniform 10 bit integers stored as 16-bit unsigned integers"""
 | 
			
		||||
    cdef Py_ssize_t i
 | 
			
		||||
    cdef bitgen_t *rng
 | 
			
		||||
    cdef const char *capsule_name = "BitGenerator"
 | 
			
		||||
    cdef uint16_t[::1] random_values
 | 
			
		||||
    cdef int bits_remaining
 | 
			
		||||
    cdef int width = 10
 | 
			
		||||
    cdef uint64_t buff, mask = 0x3FF
 | 
			
		||||
 | 
			
		||||
    x = PCG64()
 | 
			
		||||
    capsule = x.capsule
 | 
			
		||||
    if not PyCapsule_IsValid(capsule, capsule_name):
 | 
			
		||||
        raise ValueError("Invalid pointer to anon_func_state")
 | 
			
		||||
    rng = <bitgen_t *> PyCapsule_GetPointer(capsule, capsule_name)
 | 
			
		||||
    random_values = np.empty(n, dtype='uint16')
 | 
			
		||||
    # Best practice is to release GIL and acquire the lock
 | 
			
		||||
    bits_remaining = 0
 | 
			
		||||
    with x.lock, nogil:
 | 
			
		||||
        for i in range(n):
 | 
			
		||||
            if bits_remaining < width:
 | 
			
		||||
                buff = rng.next_uint64(rng.state)
 | 
			
		||||
            random_values[i] = buff & mask
 | 
			
		||||
            buff >>= width
 | 
			
		||||
 | 
			
		||||
    randoms = np.asarray(random_values)
 | 
			
		||||
    return randoms
 | 
			
		||||
 | 
			
		||||
# cython example 3
 | 
			
		||||
def uniforms_ex(bit_generator, Py_ssize_t n, dtype=np.float64):
 | 
			
		||||
    """
 | 
			
		||||
    Create an array of `n` uniformly distributed doubles via a "fill" function.
 | 
			
		||||
 | 
			
		||||
    A 'real' distribution would want to process the values into
 | 
			
		||||
    some non-uniform distribution
 | 
			
		||||
 | 
			
		||||
    Parameters
 | 
			
		||||
    ----------
 | 
			
		||||
    bit_generator: BitGenerator instance
 | 
			
		||||
    n: int
 | 
			
		||||
        Output vector length
 | 
			
		||||
    dtype: {str, dtype}, optional
 | 
			
		||||
        Desired dtype, either 'd' (or 'float64') or 'f' (or 'float32'). The
 | 
			
		||||
        default dtype value is 'd'
 | 
			
		||||
    """
 | 
			
		||||
    cdef Py_ssize_t i
 | 
			
		||||
    cdef bitgen_t *rng
 | 
			
		||||
    cdef const char *capsule_name = "BitGenerator"
 | 
			
		||||
    cdef np.ndarray randoms
 | 
			
		||||
 | 
			
		||||
    capsule = bit_generator.capsule
 | 
			
		||||
    # Optional check that the capsule if from a BitGenerator
 | 
			
		||||
    if not PyCapsule_IsValid(capsule, capsule_name):
 | 
			
		||||
        raise ValueError("Invalid pointer to anon_func_state")
 | 
			
		||||
    # Cast the pointer
 | 
			
		||||
    rng = <bitgen_t *> PyCapsule_GetPointer(capsule, capsule_name)
 | 
			
		||||
 | 
			
		||||
    _dtype = np.dtype(dtype)
 | 
			
		||||
    randoms = np.empty(n, dtype=_dtype)
 | 
			
		||||
    if _dtype == np.float32:
 | 
			
		||||
        with bit_generator.lock:
 | 
			
		||||
            random_standard_uniform_fill_f(rng, n, <float*>np.PyArray_DATA(randoms))
 | 
			
		||||
    elif _dtype == np.float64:
 | 
			
		||||
        with bit_generator.lock:
 | 
			
		||||
            random_standard_uniform_fill(rng, n, <double*>np.PyArray_DATA(randoms))
 | 
			
		||||
    else:
 | 
			
		||||
        raise TypeError('Unsupported dtype %r for random' % _dtype)
 | 
			
		||||
    return randoms
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,45 @@
 | 
			
		||||
project('random-build-examples', 'c', 'cpp', 'cython')
 | 
			
		||||
 | 
			
		||||
py_mod = import('python')
 | 
			
		||||
py3 = py_mod.find_installation(pure: false)
 | 
			
		||||
 | 
			
		||||
cc = meson.get_compiler('c')
 | 
			
		||||
cy = meson.get_compiler('cython')
 | 
			
		||||
 | 
			
		||||
if not cy.version().version_compare('>=0.29.35')
 | 
			
		||||
  error('tests requires Cython >= 0.29.35')
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
_numpy_abs = run_command(py3, ['-c',
 | 
			
		||||
               'import os; os.chdir(".."); import numpy; print(os.path.abspath(numpy.get_include() + "../../.."))'],
 | 
			
		||||
                         check: true).stdout().strip()
 | 
			
		||||
 | 
			
		||||
npymath_path = _numpy_abs / 'core' / 'lib'
 | 
			
		||||
npy_include_path = _numpy_abs / 'core' / 'include'
 | 
			
		||||
npyrandom_path = _numpy_abs / 'random' / 'lib'
 | 
			
		||||
npymath_lib = cc.find_library('npymath', dirs: npymath_path)
 | 
			
		||||
npyrandom_lib = cc.find_library('npyrandom', dirs: npyrandom_path)
 | 
			
		||||
 | 
			
		||||
py3.extension_module(
 | 
			
		||||
    'extending_distributions',
 | 
			
		||||
    'extending_distributions.pyx',
 | 
			
		||||
    install: false,
 | 
			
		||||
    include_directories: [npy_include_path],
 | 
			
		||||
    dependencies: [npyrandom_lib, npymath_lib],
 | 
			
		||||
)
 | 
			
		||||
py3.extension_module(
 | 
			
		||||
    'extending',
 | 
			
		||||
    'extending.pyx',
 | 
			
		||||
    install: false,
 | 
			
		||||
    include_directories: [npy_include_path],
 | 
			
		||||
    dependencies: [npyrandom_lib, npymath_lib],
 | 
			
		||||
)
 | 
			
		||||
py3.extension_module(
 | 
			
		||||
    'extending_cpp',
 | 
			
		||||
    'extending_distributions.pyx',
 | 
			
		||||
    install: false,
 | 
			
		||||
    override_options : ['cython_language=cpp'],
 | 
			
		||||
    cython_args: ['--module-name', 'extending_cpp'],
 | 
			
		||||
    include_directories: [npy_include_path],
 | 
			
		||||
    dependencies: [npyrandom_lib, npymath_lib],
 | 
			
		||||
)
 | 
			
		||||
@@ -0,0 +1,46 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
"""
 | 
			
		||||
Build the Cython demonstrations of low-level access to NumPy random
 | 
			
		||||
 | 
			
		||||
Usage: python setup.py build_ext -i
 | 
			
		||||
"""
 | 
			
		||||
from os.path import dirname, join, abspath
 | 
			
		||||
 | 
			
		||||
from setuptools import setup
 | 
			
		||||
from setuptools.extension import Extension
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
from Cython.Build import cythonize
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
path = dirname(__file__)
 | 
			
		||||
src_dir = join(dirname(path), '..', 'src')
 | 
			
		||||
defs = [('NPY_NO_DEPRECATED_API', 0)]
 | 
			
		||||
inc_path = np.get_include()
 | 
			
		||||
# Add paths for npyrandom and npymath libraries:
 | 
			
		||||
lib_path = [
 | 
			
		||||
    abspath(join(np.get_include(), '..', '..', 'random', 'lib')),
 | 
			
		||||
    abspath(join(np.get_include(), '..', 'lib'))
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
extending = Extension("extending",
 | 
			
		||||
                      sources=[join('.', 'extending.pyx')],
 | 
			
		||||
                      include_dirs=[
 | 
			
		||||
                            np.get_include(),
 | 
			
		||||
                            join(path, '..', '..')
 | 
			
		||||
                        ],
 | 
			
		||||
                      define_macros=defs,
 | 
			
		||||
                      )
 | 
			
		||||
distributions = Extension("extending_distributions",
 | 
			
		||||
                          sources=[join('.', 'extending_distributions.pyx')],
 | 
			
		||||
                          include_dirs=[inc_path],
 | 
			
		||||
                          library_dirs=lib_path,
 | 
			
		||||
                          libraries=['npyrandom', 'npymath'],
 | 
			
		||||
                          define_macros=defs,
 | 
			
		||||
                          )
 | 
			
		||||
 | 
			
		||||
extensions = [extending, distributions]
 | 
			
		||||
 | 
			
		||||
setup(
 | 
			
		||||
    ext_modules=cythonize(extensions)
 | 
			
		||||
)
 | 
			
		||||
		Reference in New Issue
	
	Block a user