math.c 6.2 KB

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