Просмотр исходного кода

use qpow algo for int to fix precision loss

blueloveTH 3 лет назад
Родитель
Сommit
30c673b875
2 измененных файлов с 21 добавлено и 1 удалено
  1. 12 1
      src/pocketpy.h
  2. 9 0
      tests/_basic.py

+ 12 - 1
src/pocketpy.h

@@ -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])));
         }

+ 9 - 0
tests/_basic.py

@@ -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