| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- #include "pocketpy/pocketpy.h"
- #include "pocketpy/interpreter/vm.h"
- #include <math.h>
- #if PK_ENABLE_DETERMINISM
- #ifndef _DMATH_H
- #error "_DMATH_H not defined"
- #endif
- #endif
- #define ONE_ARG_FUNC(name, func) \
- static bool math_##name(int argc, py_Ref argv) { \
- PY_CHECK_ARGC(1); \
- double x; \
- if(!py_castfloat(py_arg(0), &x)) return false; \
- py_newfloat(py_retval(), func(x)); \
- return true; \
- }
- #define TWO_ARG_FUNC(name, func) \
- static bool math_##name(int argc, py_Ref argv) { \
- PY_CHECK_ARGC(2); \
- double x, y; \
- if(!py_castfloat(py_arg(0), &x)) return false; \
- if(!py_castfloat(py_arg(1), &y)) return false; \
- py_newfloat(py_retval(), func(x, y)); \
- return true; \
- }
- ONE_ARG_FUNC(ceil, ceil)
- ONE_ARG_FUNC(fabs, fabs)
- ONE_ARG_FUNC(floor, floor)
- ONE_ARG_FUNC(trunc, trunc)
- static bool math_fsum(int argc, py_Ref argv) {
- PY_CHECK_ARGC(1);
- PY_CHECK_ARG_TYPE(0, tp_list);
- py_Ref list = py_arg(0);
- double sum = 0;
- double c = 0;
- for(int i = 0; i < py_list_len(list); i++) {
- py_Ref item = py_list_getitem(list, i);
- double x;
- if(!py_castfloat(item, &x)) return false;
- double y = x - c;
- double t = sum + y;
- c = (t - sum) - y;
- sum = t;
- }
- py_newfloat(py_retval(), sum);
- return true;
- }
- static bool math_gcd(int argc, py_Ref argv) {
- PY_CHECK_ARGC(2);
- PY_CHECK_ARG_TYPE(0, tp_int);
- PY_CHECK_ARG_TYPE(1, tp_int);
- py_i64 a = py_toint(py_arg(0));
- py_i64 b = py_toint(py_arg(1));
- if(a < 0) a = -a;
- if(b < 0) b = -b;
- while(b != 0) {
- py_i64 t = b;
- b = a % b;
- a = t;
- }
- py_newint(py_retval(), a);
- return true;
- }
- ONE_ARG_FUNC(isfinite, isfinite)
- ONE_ARG_FUNC(isinf, isinf)
- ONE_ARG_FUNC(isnan, isnan)
- static bool math_isclose(int argc, py_Ref argv) {
- PY_CHECK_ARGC(2);
- double a, b;
- if(!py_castfloat(py_arg(0), &a)) return false;
- if(!py_castfloat(py_arg(1), &b)) return false;
- py_newbool(py_retval(), fabs(a - b) < 1e-9);
- return true;
- }
- ONE_ARG_FUNC(exp, exp)
- static bool math_log(int argc, py_Ref argv) {
- double x;
- if(!py_castfloat(py_arg(0), &x)) return false;
- if(argc == 1) {
- py_newfloat(py_retval(), log(x));
- } else if(argc == 2) {
- double base;
- if(!py_castfloat(py_arg(1), &base)) return false;
- py_newfloat(py_retval(), log(x) / log(base));
- } else {
- return TypeError("log() takes 1 or 2 arguments");
- }
- return true;
- }
- ONE_ARG_FUNC(log2, log2)
- ONE_ARG_FUNC(log10, log10)
- TWO_ARG_FUNC(pow, pow)
- ONE_ARG_FUNC(sqrt, sqrt)
- ONE_ARG_FUNC(acos, acos)
- ONE_ARG_FUNC(asin, asin)
- ONE_ARG_FUNC(atan, atan)
- ONE_ARG_FUNC(cos, cos)
- ONE_ARG_FUNC(sin, sin)
- ONE_ARG_FUNC(tan, tan)
- TWO_ARG_FUNC(atan2, atan2)
- static bool math_degrees(int argc, py_Ref argv) {
- PY_CHECK_ARGC(1);
- double x;
- if(!py_castfloat(py_arg(0), &x)) return false;
- py_newfloat(py_retval(), x * PK_M_RAD2DEG);
- return true;
- }
- static bool math_radians(int argc, py_Ref argv) {
- PY_CHECK_ARGC(1);
- double x;
- if(!py_castfloat(py_arg(0), &x)) return false;
- py_newfloat(py_retval(), x * PK_M_DEG2RAD);
- return true;
- }
- TWO_ARG_FUNC(fmod, fmod)
- static bool math_modf(int argc, py_Ref argv) {
- PY_CHECK_ARGC(1);
- double i;
- double f = modf(py_tofloat(py_arg(0)), &i);
- py_Ref p = py_newtuple(py_retval(), 2);
- py_newfloat(&p[0], f);
- py_newfloat(&p[1], i);
- return true;
- }
- static bool math_factorial(int argc, py_Ref argv) {
- PY_CHECK_ARGC(1);
- PY_CHECK_ARG_TYPE(0, tp_int);
- py_i64 n = py_toint(py_arg(0));
- if(n < 0) return ValueError("factorial() not defined for negative values");
- py_i64 r = 1;
- for(py_i64 i = 2; i <= n; i++)
- r *= i;
- py_newint(py_retval(), r);
- return true;
- }
- void pk__add_module_math() {
- py_Ref mod = py_newmodule("math");
- py_newfloat(py_emplacedict(mod, py_name("pi")), PK_M_PI);
- py_newfloat(py_emplacedict(mod, py_name("e")), PK_M_E);
- py_newfloat(py_emplacedict(mod, py_name("inf")), INFINITY);
- py_newfloat(py_emplacedict(mod, py_name("nan")), NAN);
- py_bindfunc(mod, "ceil", math_ceil);
- py_bindfunc(mod, "fabs", math_fabs);
- py_bindfunc(mod, "floor", math_floor);
- py_bindfunc(mod, "trunc", math_trunc);
- py_bindfunc(mod, "fsum", math_fsum);
- py_bindfunc(mod, "gcd", math_gcd);
- py_bindfunc(mod, "isfinite", math_isfinite);
- py_bindfunc(mod, "isinf", math_isinf);
- py_bindfunc(mod, "isnan", math_isnan);
- py_bindfunc(mod, "isclose", math_isclose);
- py_bindfunc(mod, "exp", math_exp);
- py_bindfunc(mod, "log", math_log);
- py_bindfunc(mod, "log2", math_log2);
- py_bindfunc(mod, "log10", math_log10);
- py_bindfunc(mod, "pow", math_pow);
- py_bindfunc(mod, "sqrt", math_sqrt);
- py_bindfunc(mod, "acos", math_acos);
- py_bindfunc(mod, "asin", math_asin);
- py_bindfunc(mod, "atan", math_atan);
- py_bindfunc(mod, "cos", math_cos);
- py_bindfunc(mod, "sin", math_sin);
- py_bindfunc(mod, "tan", math_tan);
- py_bindfunc(mod, "atan2", math_atan2);
- py_bindfunc(mod, "degrees", math_degrees);
- py_bindfunc(mod, "radians", math_radians);
- py_bindfunc(mod, "fmod", math_fmod);
- py_bindfunc(mod, "modf", math_modf);
- py_bindfunc(mod, "factorial", math_factorial);
- }
- #undef ONE_ARG_FUNC
- #undef TWO_ARG_FUNC
|