jeudi 19 mai 2016

Cython - using stdlib

I'm trying to make the c++ library work with cython using the following code: a parent that generates a random number generator and children that use it to generate uniformly distributed random numbers.

[rnd.pyx]
cdef extern from "<random>" namespace "std":
   cdef cppclass mt19937:
      mt19937() except +
      mt19937(unsigned int) except +
   cdef cppclass uniform_real_distribution[T]:
      uniform_real_distribution()
      uniform_real_distribution(double, double)
      T operator()(mt19937)

cdef class Child:
   cdef mt19937 *rng
   cdef uniform_real_distribution[double] uniform
   def __cinit__(Child self):
      cdef unsigned int seed = 123154654
      self.rng = NULL
      self.uniform = uniform_real_distribution[double](0.,1.)
   cdef set_rng(Child self, mt19937 rng):
      self.rng = &rng
   def gen_uniform(self):
      return self.uniform(self.rng[0])

cdef class Parent:
   cdef mt19937 rng
   cdef public list children
   def __cinit__(Parent self):
      cdef unsigned int seed = 123154654
      self.rng = mt19937(seed)
      self.children = []
   cpdef make_child(Parent self):
      child = Child()
      child.set_rng(self.rng)
      self.children.append(child)

[rnd.pyxbuild]
import os
from distutils.extension import Extension
dirname = os.path.dirname(__file__)
def make_ext(modname, pyxfilename):
    return Extension(
        name=modname,
        sources=[pyxfilename],
        extra_compile_args=["-std=c++11"],
        language="c++",
        include_dirs=[dirname]
    )

[test.py]
import pyximport
pyximport.install()

from rnd import Child, Parent

p = Parent()

for i in range(300):
   p.make_child()
for child in p.children:
   a = child.gen_uniform()
   print(a)

However, though the code compiles correctly, the output of the gen_uniform function is really not what I would expect: the test.py code generates first 0.941197317223, then 0.743410046664 for ever.

Moreover, though I don't manage to reproduce it, changing Child.gen_uniform, I once manage to get random numbers (much) greater that 1.0

Eventually in a more complex code where I pass the rng pointer from a class to another, I get normal numbers, zeros, greater-than-one numbers, then segmentation fault.

Could someone tell me where the problem comes from?




Aucun commentaire:

Enregistrer un commentaire