mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-19 19:10:17 +00:00
reimpl random
This commit is contained in:
parent
d6535aba93
commit
f0b66c43e6
@ -1,3 +1,10 @@
|
||||
_inst = Random()
|
||||
|
||||
seed = _inst.seed
|
||||
random = _inst.random
|
||||
uniform = _inst.uniform
|
||||
randint = _inst.randint
|
||||
|
||||
def shuffle(L):
|
||||
for i in range(len(L)):
|
||||
j = randint(i, len(L) - 1)
|
||||
|
@ -1,4 +1,4 @@
|
||||
s = """The Zen of Python, by Tim Peters
|
||||
print("""The Zen of Python, by Tim Peters
|
||||
|
||||
Beautiful is better than ugly.
|
||||
Explicit is better than implicit.
|
||||
@ -18,6 +18,4 @@ Now is better than never.
|
||||
Although never is often better than *right* now.
|
||||
If the implementation is hard to explain, it's a bad idea.
|
||||
If the implementation is easy to explain, it may be a good idea.
|
||||
Namespaces are one honking great idea -- let's do more of those!"""
|
||||
|
||||
print(s)
|
||||
Namespaces are one honking great idea -- let's do more of those!""")
|
49
src/cffi.h
49
src/cffi.h
@ -9,11 +9,10 @@ namespace pkpy {
|
||||
|
||||
template<typename Ret, typename... Params>
|
||||
struct NativeProxyFunc {
|
||||
using T = Ret(*)(Params...);
|
||||
// using T = std::function<Ret(Params...)>;
|
||||
static constexpr int N = sizeof...(Params);
|
||||
T func;
|
||||
NativeProxyFunc(T func) : func(func) {}
|
||||
using _Fp = Ret(*)(Params...);
|
||||
_Fp func;
|
||||
NativeProxyFunc(_Fp func) : func(func) {}
|
||||
|
||||
PyVar operator()(VM* vm, Args& args) {
|
||||
if (args.size() != N) {
|
||||
@ -35,6 +34,47 @@ struct NativeProxyFunc {
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret, typename T, typename... Params>
|
||||
struct NativeProxyMethod {
|
||||
static constexpr int N = sizeof...(Params);
|
||||
using _Fp = Ret(T::*)(Params...);
|
||||
_Fp func;
|
||||
NativeProxyMethod(_Fp func) : func(func) {}
|
||||
|
||||
PyVar operator()(VM* vm, Args& args) {
|
||||
int actual_size = args.size() - 1;
|
||||
if (actual_size != N) {
|
||||
vm->TypeError("expected " + std::to_string(N) + " arguments, but got " + std::to_string(actual_size));
|
||||
}
|
||||
return call<Ret>(vm, args, std::make_index_sequence<N>());
|
||||
}
|
||||
|
||||
template<typename __Ret, size_t... Is>
|
||||
std::enable_if_t<std::is_void_v<__Ret>, PyVar> call(VM* vm, Args& args, std::index_sequence<Is...>) {
|
||||
T& self = py_cast<T&>(vm, args[0]);
|
||||
(self.*func)(py_cast<Params>(vm, args[Is+1])...);
|
||||
return vm->None;
|
||||
}
|
||||
|
||||
template<typename __Ret, size_t... Is>
|
||||
std::enable_if_t<!std::is_void_v<__Ret>, PyVar> call(VM* vm, Args& args, std::index_sequence<Is...>) {
|
||||
T& self = py_cast<T&>(vm, args[0]);
|
||||
__Ret ret = (self.*func)(py_cast<Params>(vm, args[Is+1])...);
|
||||
return VAR(std::move(ret));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret, typename... Params>
|
||||
auto native_proxy_callable(Ret(*func)(Params...)) {
|
||||
return NativeProxyFunc<Ret, Params...>(func);
|
||||
}
|
||||
|
||||
template<typename Ret, typename T, typename... Params>
|
||||
auto native_proxy_callable(Ret(T::*func)(Params...)) {
|
||||
return NativeProxyMethod<Ret, T, Params...>(func);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
constexpr int type_index() { return 0; }
|
||||
template<> constexpr int type_index<void>() { return 1; }
|
||||
@ -480,6 +520,7 @@ py_var(VM* vm, T p){
|
||||
template<typename T>
|
||||
std::enable_if_t<!std::is_pointer_v<std::decay_t<T>>, PyVar>
|
||||
py_var(VM* vm, T p){
|
||||
if constexpr(std::is_same_v<T, PyVar>) return p;
|
||||
const TypeInfo* type = _type_db.get<T>();
|
||||
return VAR_T(Value, type, &p);
|
||||
}
|
||||
|
@ -26,8 +26,10 @@
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <chrono>
|
||||
|
||||
#define PK_VERSION "0.9.3"
|
||||
#define PK_VERSION "0.9.4"
|
||||
#define PK_EXTRA_CHECK 0
|
||||
|
||||
#if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__)
|
||||
|
@ -690,29 +690,45 @@ void add_module_re(VM* vm){
|
||||
});
|
||||
}
|
||||
|
||||
struct Random{
|
||||
PY_CLASS(Random, random, Random)
|
||||
std::mt19937 gen;
|
||||
|
||||
Random(){
|
||||
gen.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
|
||||
}
|
||||
|
||||
i64 randint(i64 a, i64 b) {
|
||||
std::uniform_int_distribution<i64> dis(a, b);
|
||||
return dis(gen);
|
||||
}
|
||||
|
||||
f64 random() {
|
||||
std::uniform_real_distribution<f64> dis(0.0, 1.0);
|
||||
return dis(gen);
|
||||
}
|
||||
|
||||
f64 uniform(f64 a, f64 b) {
|
||||
std::uniform_real_distribution<f64> dis(a, b);
|
||||
return dis(gen);
|
||||
}
|
||||
|
||||
void seed(i64 seed) {
|
||||
gen.seed(seed);
|
||||
}
|
||||
|
||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind_static_method<0>(type, "__new__", CPP_LAMBDA(VAR_T(Random)));
|
||||
vm->bind_method<1>(type, "seed", native_proxy_callable(&Random::seed));
|
||||
vm->bind_method<2>(type, "randint", native_proxy_callable(&Random::randint));
|
||||
vm->bind_method<0>(type, "random", native_proxy_callable(&Random::random));
|
||||
vm->bind_method<2>(type, "uniform", native_proxy_callable(&Random::uniform));
|
||||
}
|
||||
};
|
||||
|
||||
void add_module_random(VM* vm){
|
||||
PyVar mod = vm->new_module("random");
|
||||
std::srand(std::time(0));
|
||||
vm->bind_func<1>(mod, "seed", [](VM* vm, Args& args) {
|
||||
std::srand((unsigned int)CAST(i64, args[0]));
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
vm->bind_func<0>(mod, "random", CPP_LAMBDA(VAR(std::rand() / (f64)RAND_MAX)));
|
||||
vm->bind_func<2>(mod, "randint", [](VM* vm, Args& args) {
|
||||
i64 a = CAST(i64, args[0]);
|
||||
i64 b = CAST(i64, args[1]);
|
||||
if(a > b) std::swap(a, b);
|
||||
return VAR(a + std::rand() % (b - a + 1));
|
||||
});
|
||||
|
||||
vm->bind_func<2>(mod, "uniform", [](VM* vm, Args& args) {
|
||||
f64 a = CAST(f64, args[0]);
|
||||
f64 b = CAST(f64, args[1]);
|
||||
if(a > b) std::swap(a, b);
|
||||
return VAR(a + (b - a) * std::rand() / (f64)RAND_MAX);
|
||||
});
|
||||
|
||||
Random::register_class(vm, mod);
|
||||
CodeObject_ code = vm->compile(kPythonLibs["random"], "random.py", EXEC_MODE);
|
||||
vm->_exec(code, mod);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user