blueloveTH 2 rokov pred
rodič
commit
d3d8d9a8e6
3 zmenil súbory, kde vykonal 140 pridanie a 46 odobranie
  1. 84 24
      docs/modules/math.md
  2. 2 0
      src/obj.h
  3. 54 22
      src/pocketpy.h

+ 84 - 24
docs/modules/math.md

@@ -3,62 +3,122 @@ icon: package
 label: math
 ---
 
+### `math.pi`
+
+3.141592653589793
+
 ### `math.e`
 
 2.718281828459045
 
-### `math.pi`
+### `math.inf`
 
-3.141592653589793
+The `inf`.
 
-### `math.log(x)`
+### `math.nan`
 
-Return the natural logarithm of `x`.
+The `nan`.
 
-### `math.log10(x)`
+### `math.ceil(x)`
 
-Return the base-10 logarithm of `x`.
+Return the ceiling of `x` as a float, the smallest integer value greater than or equal to `x`.
 
-### `math.log2(x)`
+### `math.fabs(x)`
 
-Return the base-2 logarithm of `x`.
+Return the absolute value of `x`.
 
-### `math.sin(x)`
+### `math.floor(x)`
 
-Return the sine of `x`.
+Return the floor of `x` as a float, the largest integer value less than or equal to `x`.
 
-### `math.cos(x)`
+### `math.fsum(iterable)`
 
-Return the cosine of `x`.
+Return an accurate floating point sum of values in the iterable. Avoids loss of precision by tracking multiple intermediate partial sums:
 
-### `math.tan(x)`
+```
+>>> sum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])
+0.9999999999999999
+>>> fsum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1])
+1.0
+```
+
+### `math.gcd(a, b)`
+
+Return the greatest common divisor of the integers `a` and `b`.
+
+
+### `math.isfinite(x)`
+
+Return `True` if `x` is neither an infinity nor a NaN, and `False` otherwise.
 
-Return the tangent of `x`.
+### `math.isinf(x)`
+
+Return `True` if `x` is a positive or negative infinity, and `False` otherwise.
 
 ### `math.isnan(x)`
 
 Return `True` if `x` is a NaN (not a number), and `False` otherwise.
 
-### `math.isinf(x)`
+### `math.exp(x)`
 
-Return `True` if `x` is positive or negative infinity, and `False` otherwise.
+Return `e` raised to the power of `x`.
 
-### `math.fabs(x)`
+### `math.log(x)`
 
-Return the absolute value of `x`.
+Return the natural logarithm of `x` (to base `e`).
 
-### `math.floor(x)`
+### `math.log2(x)`
 
-Return the largest integer value less than or equal to `x`.
+Return the base-2 logarithm of `x`. This is usually more accurate than `log(x, 2)`.
 
-### `math.ceil(x)`
+### `math.log10(x)`
+
+Return the base-10 logarithm of `x`. This is usually more accurate than `log(x, 10)`.
 
-Return the smallest integer value greater than or equal to `x`.
+### `math.pow(x, y)`
+
+Return `x` raised to the power `y`.
 
 ### `math.sqrt(x)`
 
 Return the square root of `x`.
 
-### `math.gcd(a, b)`
+### `math.acos(x)`
+
+Return the arc cosine of `x`, in radians.
+
+### `math.asin(x)`
+
+Return the arc sine of `x`, in radians.
+
+### `math.atan(x)`
+
+Return the arc tangent of `x`, in radians.
+
+### `math.atan2(y, x)`
+
+Return `atan(y / x)`, in radians. The result is between `-pi` and `pi`. The vector in the plane from the origin to point `(x, y)` makes this angle with the positive X axis. The point of `atan2()` is that the signs of both inputs are known to it, so it can compute the correct quadrant for the angle. For example, `atan(1)` and `atan2(1, 1)` are both `pi/4`, but `atan2(-1, -1)` is `-3*pi/4`.
+
+### `math.cos(x)`
+
+Return the cosine of `x` radians.
+
+### `math.sin(x)`
+
+Return the sine of `x` radians.
+
+### `math.tan(x)`
+
+Return the tangent of `x` radians.
+
+### `math.degrees(x)`
+
+Convert angle `x` from radians to degrees.
+
+### `math.radians(x)`
+
+Convert angle `x` from degrees to radians.
+
+
+
 
-Return the greatest common divisor of `a` and `b`.

+ 2 - 0
src/obj.h

@@ -263,6 +263,8 @@ __T _py_cast(VM* vm, PyObject* obj) {
 #define CAST(T, x) py_cast<T>(vm, x)
 #define _CAST(T, x) _py_cast<T>(vm, x)
 
+#define FLOAT(x) vm->num_to_float(x)
+
 /*****************************************************************/
 template<>
 struct Py_<List> final: PyObject {

+ 54 - 22
src/pocketpy.h

@@ -766,14 +766,14 @@ inline void init_builtins(VM* _vm) {
 }
 
 #ifdef _WIN32
-#define __EXPORT __declspec(dllexport) inline
+#define PK_LEGACY_EXPORT __declspec(dllexport) inline
 #elif __APPLE__
-#define __EXPORT __attribute__((visibility("default"))) __attribute__((used)) inline
+#define PK_LEGACY_EXPORT __attribute__((visibility("default"))) __attribute__((used)) inline
 #elif __EMSCRIPTEN__
 #include <emscripten.h>
-#define __EXPORT EMSCRIPTEN_KEEPALIVE inline
+#define PK_LEGACY_EXPORT EMSCRIPTEN_KEEPALIVE inline
 #else
-#define __EXPORT inline
+#define PK_LEGACY_EXPORT inline
 #endif
 
 inline void add_module_time(VM* vm){
@@ -815,23 +815,31 @@ inline void add_module_json(VM* vm){
     vm->bind_func<1>(mod, "dumps", CPP_LAMBDA(vm->call_method(args[0], __json__)));
 }
 
+
+// https://docs.python.org/3.5/library/math.html
 inline void add_module_math(VM* vm){
     PyObject* mod = vm->new_module("math");
     mod->attr().set("pi", VAR(3.1415926535897932384));
     mod->attr().set("e" , VAR(2.7182818284590452354));
+    mod->attr().set("inf", VAR(std::numeric_limits<double>::infinity()));
+    mod->attr().set("nan", VAR(std::numeric_limits<double>::quiet_NaN()));
 
-    vm->bind_func<1>(mod, "log", CPP_LAMBDA(VAR(std::log(vm->num_to_float(args[0])))));
-    vm->bind_func<1>(mod, "log10", CPP_LAMBDA(VAR(std::log10(vm->num_to_float(args[0])))));
-    vm->bind_func<1>(mod, "log2", CPP_LAMBDA(VAR(std::log2(vm->num_to_float(args[0])))));
-    vm->bind_func<1>(mod, "sin", CPP_LAMBDA(VAR(std::sin(vm->num_to_float(args[0])))));
-    vm->bind_func<1>(mod, "cos", CPP_LAMBDA(VAR(std::cos(vm->num_to_float(args[0])))));
-    vm->bind_func<1>(mod, "tan", CPP_LAMBDA(VAR(std::tan(vm->num_to_float(args[0])))));
-    vm->bind_func<1>(mod, "isnan", CPP_LAMBDA(VAR(std::isnan(vm->num_to_float(args[0])))));
-    vm->bind_func<1>(mod, "isinf", CPP_LAMBDA(VAR(std::isinf(vm->num_to_float(args[0])))));
+    vm->bind_func<1>(mod, "ceil", CPP_LAMBDA(VAR((i64)std::ceil(vm->num_to_float(args[0])))));
     vm->bind_func<1>(mod, "fabs", CPP_LAMBDA(VAR(std::fabs(vm->num_to_float(args[0])))));
     vm->bind_func<1>(mod, "floor", CPP_LAMBDA(VAR((i64)std::floor(vm->num_to_float(args[0])))));
-    vm->bind_func<1>(mod, "ceil", CPP_LAMBDA(VAR((i64)std::ceil(vm->num_to_float(args[0])))));
-    vm->bind_func<1>(mod, "sqrt", CPP_LAMBDA(VAR(std::sqrt(vm->num_to_float(args[0])))));
+    vm->bind_func<1>(mod, "fsum", [](VM* vm, ArgsView args) {
+        List& list = CAST(List&, args[0]);
+        double sum = 0;
+        double c = 0;
+        for(PyObject* arg : list){
+            double x = vm->num_to_float(arg);
+            double y = x - c;
+            double t = sum + y;
+            c = (t - sum) - y;
+            sum = t;
+        }
+        return VAR(sum);
+    });
     vm->bind_func<2>(mod, "gcd", [](VM* vm, ArgsView args) {
         i64 a = CAST(i64, args[0]);
         i64 b = CAST(i64, args[1]);
@@ -844,6 +852,30 @@ inline void add_module_math(VM* vm){
         }
         return VAR(a);
     });
+
+    vm->bind_func<1>(mod, "isfinite", CPP_LAMBDA(VAR(std::isfinite(vm->num_to_float(args[0])))));
+    vm->bind_func<1>(mod, "isinf", CPP_LAMBDA(VAR(std::isinf(vm->num_to_float(args[0])))));
+    vm->bind_func<1>(mod, "isnan", CPP_LAMBDA(VAR(std::isnan(vm->num_to_float(args[0])))));
+
+    vm->bind_func<1>(mod, "exp", CPP_LAMBDA(VAR(std::exp(vm->num_to_float(args[0])))));
+    vm->bind_func<1>(mod, "log", CPP_LAMBDA(VAR(std::log(vm->num_to_float(args[0])))));
+    vm->bind_func<1>(mod, "log2", CPP_LAMBDA(VAR(std::log2(vm->num_to_float(args[0])))));
+    vm->bind_func<1>(mod, "log10", CPP_LAMBDA(VAR(std::log10(vm->num_to_float(args[0])))));
+
+    vm->bind_func<2>(mod, "pow", CPP_LAMBDA(VAR(std::pow(vm->num_to_float(args[0]), vm->num_to_float(args[1])))));
+    vm->bind_func<1>(mod, "sqrt", CPP_LAMBDA(VAR(std::sqrt(vm->num_to_float(args[0])))));
+
+    vm->bind_func<1>(mod, "acos", CPP_LAMBDA(VAR(std::acos(vm->num_to_float(args[0])))));
+    vm->bind_func<1>(mod, "asin", CPP_LAMBDA(VAR(std::asin(vm->num_to_float(args[0])))));
+    vm->bind_func<1>(mod, "atan", CPP_LAMBDA(VAR(std::atan(vm->num_to_float(args[0])))));
+    vm->bind_func<2>(mod, "atan2", CPP_LAMBDA(VAR(std::atan2(vm->num_to_float(args[0]), vm->num_to_float(args[1])))));
+
+    vm->bind_func<1>(mod, "cos", CPP_LAMBDA(VAR(std::cos(vm->num_to_float(args[0])))));
+    vm->bind_func<1>(mod, "sin", CPP_LAMBDA(VAR(std::sin(vm->num_to_float(args[0])))));
+    vm->bind_func<1>(mod, "tan", CPP_LAMBDA(VAR(std::tan(vm->num_to_float(args[0])))));
+    
+    vm->bind_func<1>(mod, "degrees", CPP_LAMBDA(VAR(vm->num_to_float(args[0]) * 180 / 3.1415926535897932384)));
+    vm->bind_func<1>(mod, "radians", CPP_LAMBDA(VAR(vm->num_to_float(args[0]) * 3.1415926535897932384 / 180)));
 }
 
 inline void add_module_dis(VM* vm){
@@ -1075,7 +1107,7 @@ inline void VM::post_init(){
 static std::map<void*, void(*)(void*)> _pk_deleter_map;
 
 extern "C" {
-    __EXPORT
+    PK_LEGACY_EXPORT
     void pkpy_delete(void* p){
         auto it = _pk_deleter_map.find(p);
         if(it != _pk_deleter_map.end()){
@@ -1085,12 +1117,12 @@ extern "C" {
         }
     }
 
-    __EXPORT
+    PK_LEGACY_EXPORT
     void pkpy_vm_exec(pkpy::VM* vm, const char* source){
         vm->exec(source, "main.py", pkpy::EXEC_MODE);
     }
 
-    __EXPORT
+    PK_LEGACY_EXPORT
     char* pkpy_vm_get_global(pkpy::VM* vm, const char* name){
         pkpy::PyObject* val = vm->_main->attr().try_get(name);
         if(val == nullptr) return nullptr;
@@ -1102,7 +1134,7 @@ extern "C" {
         }
     }
 
-    __EXPORT
+    PK_LEGACY_EXPORT
     char* pkpy_vm_eval(pkpy::VM* vm, const char* source){
         pkpy::PyObject* ret = vm->exec(source, "<eval>", pkpy::EVAL_MODE);
         if(ret == nullptr) return nullptr;
@@ -1114,24 +1146,24 @@ extern "C" {
         }
     }
 
-    __EXPORT
+    PK_LEGACY_EXPORT
     pkpy::REPL* pkpy_new_repl(pkpy::VM* vm){
         pkpy::REPL* p = new pkpy::REPL(vm);
         _pk_deleter_map[p] = [](void* p){ delete (pkpy::REPL*)p; };
         return p;
     }
 
-    __EXPORT
+    PK_LEGACY_EXPORT
     bool pkpy_repl_input(pkpy::REPL* r, const char* line){
         return r->input(line);
     }
 
-    __EXPORT
+    PK_LEGACY_EXPORT
     void pkpy_vm_add_module(pkpy::VM* vm, const char* name, const char* source){
         vm->_lazy_modules[name] = source;
     }
 
-    __EXPORT
+    PK_LEGACY_EXPORT
     pkpy::VM* pkpy_new_vm(bool enable_os=true){
         pkpy::VM* p = new pkpy::VM(enable_os);
         _pk_deleter_map[p] = [](void* p){ delete (pkpy::VM*)p; };