use qpow algo for int to fix precision loss

This commit is contained in:
blueloveTH 2023-02-18 20:26:58 +08:00
parent 2c111cd563
commit 30c673b875
2 changed files with 21 additions and 1 deletions

View File

@ -171,7 +171,18 @@ void init_builtins(VM* _vm) {
_vm->_bind_methods<1>({"int", "float"}, "__pow__", [](VM* vm, pkpy::Args& args) {
if(args[0]->is_type(vm->tp_int) && args[1]->is_type(vm->tp_int)){
return vm->PyInt((i64)round(pow(vm->PyInt_AS_C(args[0]), vm->PyInt_AS_C(args[1]))));
i64 lhs = vm->PyInt_AS_C(args[0]);
i64 rhs = vm->PyInt_AS_C(args[1]);
bool flag = false;
if(rhs < 0) {flag = true; rhs = -rhs;}
i64 ret = 1;
while(rhs){
if(rhs & 1) ret *= lhs;
lhs *= lhs;
rhs >>= 1;
}
if(flag) return vm->PyFloat((f64)(1.0 / ret));
return vm->PyInt(ret);
}else{
return vm->PyFloat((f64)pow(vm->num_to_float(args[0]), vm->num_to_float(args[1])));
}

View File

@ -117,3 +117,12 @@ assert round(23.2) == 23
assert round(23.8) == 24
assert round(-23.2) == -23
assert round(-23.8) == -24
assert 7**21 == 558545864083284007
assert 7**22 == 3909821048582988049
assert 2**62 == 4611686018427387904
assert eq(2**-2, 0.25)
assert 0**0 == 1
assert 0**1 == 0
assert 1**0 == 1