reimpl random

This commit is contained in:
blueloveTH 2023-03-18 23:04:34 +08:00
parent d6535aba93
commit f0b66c43e6
5 changed files with 94 additions and 30 deletions

View File

@ -1,3 +1,10 @@
_inst = Random()
seed = _inst.seed
random = _inst.random
uniform = _inst.uniform
randint = _inst.randint
def shuffle(L): def shuffle(L):
for i in range(len(L)): for i in range(len(L)):
j = randint(i, len(L) - 1) j = randint(i, len(L) - 1)

View File

@ -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. Beautiful is better than ugly.
Explicit is better than implicit. Explicit is better than implicit.
@ -18,6 +18,4 @@ Now is better than never.
Although never is often better than *right* now. Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea. 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. 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!""" Namespaces are one honking great idea -- let's do more of those!""")
print(s)

View File

@ -9,11 +9,10 @@ namespace pkpy {
template<typename Ret, typename... Params> template<typename Ret, typename... Params>
struct NativeProxyFunc { struct NativeProxyFunc {
using T = Ret(*)(Params...);
// using T = std::function<Ret(Params...)>;
static constexpr int N = sizeof...(Params); static constexpr int N = sizeof...(Params);
T func; using _Fp = Ret(*)(Params...);
NativeProxyFunc(T func) : func(func) {} _Fp func;
NativeProxyFunc(_Fp func) : func(func) {}
PyVar operator()(VM* vm, Args& args) { PyVar operator()(VM* vm, Args& args) {
if (args.size() != N) { 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> template<typename T>
constexpr int type_index() { return 0; } constexpr int type_index() { return 0; }
template<> constexpr int type_index<void>() { return 1; } template<> constexpr int type_index<void>() { return 1; }
@ -480,6 +520,7 @@ py_var(VM* vm, T p){
template<typename T> template<typename T>
std::enable_if_t<!std::is_pointer_v<std::decay_t<T>>, PyVar> std::enable_if_t<!std::is_pointer_v<std::decay_t<T>>, PyVar>
py_var(VM* vm, T p){ py_var(VM* vm, T p){
if constexpr(std::is_same_v<T, PyVar>) return p;
const TypeInfo* type = _type_db.get<T>(); const TypeInfo* type = _type_db.get<T>();
return VAR_T(Value, type, &p); return VAR_T(Value, type, &p);
} }

View File

@ -26,8 +26,10 @@
#include <map> #include <map>
#include <set> #include <set>
#include <algorithm> #include <algorithm>
#include <random>
#include <chrono>
#define PK_VERSION "0.9.3" #define PK_VERSION "0.9.4"
#define PK_EXTRA_CHECK 0 #define PK_EXTRA_CHECK 0
#if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__) #if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__)

View File

@ -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){ void add_module_random(VM* vm){
PyVar mod = vm->new_module("random"); PyVar mod = vm->new_module("random");
std::srand(std::time(0)); Random::register_class(vm, mod);
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);
});
CodeObject_ code = vm->compile(kPythonLibs["random"], "random.py", EXEC_MODE); CodeObject_ code = vm->compile(kPythonLibs["random"], "random.py", EXEC_MODE);
vm->_exec(code, mod); vm->_exec(code, mod);
} }