def binomial_ll(parameter, sample): """ Return the likelihood of the model parameter under sample. """ # compile our method body from qy import ( Value, type_from_any, build_engine, ) q = \ Qy( return_type = type_from_any(float) , argument_types = [type_from_any(float)] * 3, default_return = Value.from_any(numpy.nan) , ) with q.active() as bar: q.return_(binomial_log_pdf(*q.main_body.argument_values)) engine = build_engine(q.module) # define the python wrapper from ctypes import ( CFUNCTYPE, c_double, ) prototype = CFUNCTYPE(c_double, c_double, c_double, c_double) generated = prototype(engine.get_pointer_to_function(q.main)) from qy.support import raise_if_set def wrapper(parameter, sample): """ Return the likelihood of the model parameter under sample. """ parameter = numpy.asarray(parameter, Binomial.parameter_dtype) result = generated(sample, parameter["p"], parameter["n"]) raise_if_set() return result # don't let the engine be GCed wrapper._engine = engine # replace and compute global binomial_ll binomial_ll = wrapper return binomial_ll(parameter, sample)
def named(name, return_type=llvm.Type.void(), argument_types=()): """ Look up or create a named function. """ type_ = llvm.Type.function(qy.type_from_any(return_type), map(qy.type_from_any, argument_types)) return Function(qy.get().module.get_or_insert_function(type_, name))
def pointed(address, return_type, argument_types): """ Return a function from a function pointer. """ type_ = llvm.Type.function(qy.type_from_any(return_type), map(qy.type_from_any, argument_types)) return Function(llvm.Constant.int(iptr_type, address).inttoptr(llvm.Type.pointer(type_)))
def new_named(name, return_type=llvm.Type.void(), argument_types=(), internal=True): """ Create a named function. """ type_ = llvm.Type.function(qy.type_from_any(return_type), map(qy.type_from_any, argument_types)) function = qy.get().module.add_function(type_, name) if internal: function.linkage = llvm.LINKAGE_INTERNAL return Function(function)
def cast_to(self, type_, name = ""): """ Cast this value to the specified type. """ # XXX support more casts type_ = qy.type_from_any(type_) low_value = None if type_.kind == llvm.TYPE_DOUBLE: if self.type_.kind == llvm.TYPE_DOUBLE: low_value = self._value if type_.kind == llvm.TYPE_INTEGER: low_value = qy.get().builder.fptosi(self._value, type_, name) if low_value is None: raise CoercionError(self.type_, type_) else: return qy.Value.from_low(low_value)
def cast_to(self, type_, name = ""): """ Cast this value to the specified type. """ # XXX support more casts type_ = qy.type_from_any(type_) low_value = None if type_.kind == llvm.TYPE_POINTER: low_value = qy.get().builder.bitcast(self._value, type_, name) elif type_.kind == llvm.TYPE_INTEGER: if type_.width == qy.iptr_type.width: low_value = qy.get().builder.ptrtoint(self._value, type_, name) if low_value is None: raise CoercionError(self.type_, type_) else: return qy.Value.from_any(low_value)
def cast_to(self, type_, name = ""): """ Cast this value to the specified type. """ # XXX cleanly handle signedness somehow (explicit "signed" qy value?) type_ = qy.type_from_any(type_) low_value = None if type_.kind == llvm.TYPE_DOUBLE: low_value = qy.get().builder.sitofp(self._value, type_, name) elif type_.kind == llvm.TYPE_INTEGER: if self.type_.width == type_.width: low_value = self._value elif self.type_.width < type_.width: low_value = qy.get().builder.sext(self._value, type_, name) elif self.type_.width > type_.width: low_value = qy.get().builder.trunc(self._value, type_, name) if low_value is None: raise CoercionError(self.type_, type_) else: return qy.Value.from_any(low_value)