math.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #include "pocketpy/pocketpy.h"
  2. #include "pocketpy/common/dmath.h"
  3. #include "pocketpy/interpreter/vm.h"
  4. #define ONE_ARG_FUNC(name, func) \
  5. static bool math_##name(int argc, py_Ref argv) { \
  6. PY_CHECK_ARGC(1); \
  7. double x; \
  8. if(!py_castfloat(py_arg(0), &x)) return false; \
  9. py_newfloat(py_retval(), func(x)); \
  10. return true; \
  11. }
  12. #define ONE_ARG_INT_FUNC(name, func) \
  13. static bool math_##name(int argc, py_Ref argv) { \
  14. PY_CHECK_ARGC(1); \
  15. double x; \
  16. if(!py_castfloat(py_arg(0), &x)) return false; \
  17. py_newint(py_retval(), (py_i64)func(x)); \
  18. return true; \
  19. }
  20. #define ONE_ARG_BOOL_FUNC(name, func) \
  21. static bool math_##name(int argc, py_Ref argv) { \
  22. PY_CHECK_ARGC(1); \
  23. double x; \
  24. if(!py_castfloat(py_arg(0), &x)) return false; \
  25. py_newbool(py_retval(), func(x)); \
  26. return true; \
  27. }
  28. #define TWO_ARG_FUNC(name, func) \
  29. static bool math_##name(int argc, py_Ref argv) { \
  30. PY_CHECK_ARGC(2); \
  31. double x, y; \
  32. if(!py_castfloat(py_arg(0), &x)) return false; \
  33. if(!py_castfloat(py_arg(1), &y)) return false; \
  34. py_newfloat(py_retval(), func(x, y)); \
  35. return true; \
  36. }
  37. ONE_ARG_INT_FUNC(ceil, dmath_ceil)
  38. ONE_ARG_INT_FUNC(floor, dmath_floor)
  39. ONE_ARG_INT_FUNC(trunc, dmath_trunc)
  40. ONE_ARG_FUNC(fabs, dmath_fabs)
  41. static bool math_fsum(int argc, py_Ref argv) {
  42. PY_CHECK_ARGC(1);
  43. PY_CHECK_ARG_TYPE(0, tp_list);
  44. py_Ref list = py_arg(0);
  45. double sum = 0;
  46. double c = 0;
  47. for(int i = 0; i < py_list_len(list); i++) {
  48. py_Ref item = py_list_getitem(list, i);
  49. double x;
  50. if(!py_castfloat(item, &x)) return false;
  51. double y = x - c;
  52. double t = sum + y;
  53. c = (t - sum) - y;
  54. sum = t;
  55. }
  56. py_newfloat(py_retval(), sum);
  57. return true;
  58. }
  59. static bool math_gcd(int argc, py_Ref argv) {
  60. PY_CHECK_ARGC(2);
  61. PY_CHECK_ARG_TYPE(0, tp_int);
  62. PY_CHECK_ARG_TYPE(1, tp_int);
  63. py_i64 a = py_toint(py_arg(0));
  64. py_i64 b = py_toint(py_arg(1));
  65. if(a < 0) a = -a;
  66. if(b < 0) b = -b;
  67. while(b != 0) {
  68. py_i64 t = b;
  69. b = a % b;
  70. a = t;
  71. }
  72. py_newint(py_retval(), a);
  73. return true;
  74. }
  75. ONE_ARG_BOOL_FUNC(isfinite, dmath_isfinite)
  76. ONE_ARG_BOOL_FUNC(isinf, dmath_isinf)
  77. ONE_ARG_BOOL_FUNC(isnan, dmath_isnan)
  78. static bool math_isclose(int argc, py_Ref argv) {
  79. PY_CHECK_ARGC(2);
  80. double a, b;
  81. if(!py_castfloat(py_arg(0), &a)) return false;
  82. if(!py_castfloat(py_arg(1), &b)) return false;
  83. py_newbool(py_retval(), dmath_fabs(a - b) < 1e-9);
  84. return true;
  85. }
  86. ONE_ARG_FUNC(exp, dmath_exp)
  87. static bool math_log(int argc, py_Ref argv) {
  88. double x;
  89. if(!py_castfloat(py_arg(0), &x)) return false;
  90. if(x < 0) {
  91. py_newfloat(py_retval(), DMATH_NAN);
  92. return true;
  93. }
  94. if(argc == 1) {
  95. py_newfloat(py_retval(), dmath_log(x));
  96. } else if(argc == 2) {
  97. double base;
  98. if(!py_castfloat(py_arg(1), &base)) return false;
  99. py_newfloat(py_retval(), dmath_log2(x) / dmath_log2(base));
  100. } else {
  101. return TypeError("log() takes 1 or 2 arguments");
  102. }
  103. return true;
  104. }
  105. ONE_ARG_FUNC(log2, dmath_log2)
  106. ONE_ARG_FUNC(log10, dmath_log10)
  107. TWO_ARG_FUNC(pow, dmath_pow)
  108. ONE_ARG_FUNC(sqrt, dmath_sqrt)
  109. ONE_ARG_FUNC(cbrt, dmath_cbrt)
  110. ONE_ARG_FUNC(acos, dmath_acos)
  111. ONE_ARG_FUNC(asin, dmath_asin)
  112. ONE_ARG_FUNC(atan, dmath_atan)
  113. ONE_ARG_FUNC(cos, dmath_cos)
  114. ONE_ARG_FUNC(sin, dmath_sin)
  115. ONE_ARG_FUNC(tan, dmath_tan)
  116. TWO_ARG_FUNC(atan2, dmath_atan2)
  117. static bool math_degrees(int argc, py_Ref argv) {
  118. PY_CHECK_ARGC(1);
  119. double x;
  120. if(!py_castfloat(py_arg(0), &x)) return false;
  121. py_newfloat(py_retval(), x * DMATH_RAD2DEG);
  122. return true;
  123. }
  124. static bool math_radians(int argc, py_Ref argv) {
  125. PY_CHECK_ARGC(1);
  126. double x;
  127. if(!py_castfloat(py_arg(0), &x)) return false;
  128. py_newfloat(py_retval(), x * DMATH_DEG2RAD);
  129. return true;
  130. }
  131. TWO_ARG_FUNC(copysign, dmath_copysign)
  132. TWO_ARG_FUNC(fmod, dmath_fmod)
  133. static bool math_modf(int argc, py_Ref argv) {
  134. PY_CHECK_ARGC(1);
  135. double i;
  136. double f = dmath_modf(py_tofloat(py_arg(0)), &i);
  137. py_Ref p = py_newtuple(py_retval(), 2);
  138. py_newfloat(&p[0], f);
  139. py_newfloat(&p[1], i);
  140. return true;
  141. }
  142. static bool math_factorial(int argc, py_Ref argv) {
  143. PY_CHECK_ARGC(1);
  144. PY_CHECK_ARG_TYPE(0, tp_int);
  145. py_i64 n = py_toint(py_arg(0));
  146. if(n < 0) return ValueError("factorial() not defined for negative values");
  147. py_i64 r = 1;
  148. for(py_i64 i = 2; i <= n; i++)
  149. r *= i;
  150. py_newint(py_retval(), r);
  151. return true;
  152. }
  153. void pk__add_module_math() {
  154. py_Ref mod = py_newmodule("math");
  155. py_newfloat(py_emplacedict(mod, py_name("pi")), DMATH_PI);
  156. py_newfloat(py_emplacedict(mod, py_name("e")), DMATH_E);
  157. py_newfloat(py_emplacedict(mod, py_name("inf")), DMATH_INFINITY);
  158. py_newfloat(py_emplacedict(mod, py_name("nan")), DMATH_NAN);
  159. py_bindfunc(mod, "ceil", math_ceil);
  160. py_bindfunc(mod, "fabs", math_fabs);
  161. py_bindfunc(mod, "floor", math_floor);
  162. py_bindfunc(mod, "trunc", math_trunc);
  163. py_bindfunc(mod, "fsum", math_fsum);
  164. py_bindfunc(mod, "gcd", math_gcd);
  165. py_bindfunc(mod, "isfinite", math_isfinite);
  166. py_bindfunc(mod, "isinf", math_isinf);
  167. py_bindfunc(mod, "isnan", math_isnan);
  168. py_bindfunc(mod, "isclose", math_isclose);
  169. py_bindfunc(mod, "exp", math_exp);
  170. py_bindfunc(mod, "log", math_log);
  171. py_bindfunc(mod, "log2", math_log2);
  172. py_bindfunc(mod, "log10", math_log10);
  173. py_bindfunc(mod, "pow", math_pow);
  174. py_bindfunc(mod, "sqrt", math_sqrt);
  175. py_bindfunc(mod, "cbrt", math_cbrt);
  176. py_bindfunc(mod, "acos", math_acos);
  177. py_bindfunc(mod, "asin", math_asin);
  178. py_bindfunc(mod, "atan", math_atan);
  179. py_bindfunc(mod, "cos", math_cos);
  180. py_bindfunc(mod, "sin", math_sin);
  181. py_bindfunc(mod, "tan", math_tan);
  182. py_bindfunc(mod, "atan2", math_atan2);
  183. py_bindfunc(mod, "degrees", math_degrees);
  184. py_bindfunc(mod, "radians", math_radians);
  185. py_bindfunc(mod, "fmod", math_fmod);
  186. py_bindfunc(mod, "modf", math_modf);
  187. py_bindfunc(mod, "copysign", math_copysign);
  188. py_bindfunc(mod, "factorial", math_factorial);
  189. }
  190. #undef ONE_ARG_FUNC
  191. #undef ONE_ARG_BOOL_FUNC
  192. #undef ONE_ARG_INT_FUNC
  193. #undef TWO_ARG_FUNC