lmathlib.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /*
  2. ** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $
  3. ** Standard mathematical library
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <stdlib.h>
  7. #include <math.h>
  8. #define lmathlib_c
  9. #define LUA_LIB
  10. #include "lua.h"
  11. #include "lauxlib.h"
  12. #include "lualib.h"
  13. #include "lrotable.h"
  14. #undef PI
  15. #define PI (3.14159265358979323846)
  16. #define RADIANS_PER_DEGREE (PI/180.0)
  17. static int math_abs (lua_State *L) {
  18. #ifdef LUA_NUMBER_INTEGRAL
  19. lua_Number x = luaL_checknumber(L, 1);
  20. if (x < 0) x = -x; //fails for -2^31
  21. lua_pushnumber(L, x);
  22. #else
  23. lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
  24. #endif
  25. return 1;
  26. }
  27. #ifndef LUA_NUMBER_INTEGRAL
  28. static int math_sin (lua_State *L) {
  29. lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
  30. return 1;
  31. }
  32. static int math_sinh (lua_State *L) {
  33. lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
  34. return 1;
  35. }
  36. static int math_cos (lua_State *L) {
  37. lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
  38. return 1;
  39. }
  40. static int math_cosh (lua_State *L) {
  41. lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
  42. return 1;
  43. }
  44. static int math_tan (lua_State *L) {
  45. lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
  46. return 1;
  47. }
  48. static int math_tanh (lua_State *L) {
  49. lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
  50. return 1;
  51. }
  52. static int math_asin (lua_State *L) {
  53. lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
  54. return 1;
  55. }
  56. static int math_acos (lua_State *L) {
  57. lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
  58. return 1;
  59. }
  60. static int math_atan (lua_State *L) {
  61. lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
  62. return 1;
  63. }
  64. static int math_atan2 (lua_State *L) {
  65. lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
  66. return 1;
  67. }
  68. static int math_ceil (lua_State *L) {
  69. lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
  70. return 1;
  71. }
  72. static int math_floor (lua_State *L) {
  73. lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
  74. return 1;
  75. }
  76. static int math_fmod (lua_State *L) {
  77. lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
  78. return 1;
  79. }
  80. static int math_modf (lua_State *L) {
  81. double ip;
  82. double fp = modf(luaL_checknumber(L, 1), &ip);
  83. lua_pushnumber(L, ip);
  84. lua_pushnumber(L, fp);
  85. return 2;
  86. }
  87. #else // #ifndef LUA_NUMBER_INTEGRAL
  88. // In integer math, floor() and ceil() give the same value;
  89. // having them in the integer library allows you to write code that
  90. // works in both integer and floating point versions of Lua.
  91. // This identity function is used for them.
  92. static int math_identity (lua_State *L) {
  93. lua_pushnumber(L, luaL_checknumber(L, 1));
  94. return 1;
  95. }
  96. #endif // #ifndef LUA_NUMBER_INTEGRAL
  97. #ifdef LUA_NUMBER_INTEGRAL
  98. // Integer square root for integer version
  99. static lua_Number isqrt(lua_Number x)
  100. {
  101. lua_Number op, res, one;
  102. op = x; res = 0;
  103. /* "one" starts at the highest power of four <= than the argument. */
  104. one = 1 << 30; /* second-to-top bit set */
  105. while (one > op) one >>= 2;
  106. while (one != 0) {
  107. if (op >= res + one) {
  108. op = op - (res + one);
  109. res = res + 2 * one;
  110. }
  111. res >>= 1;
  112. one >>= 2;
  113. }
  114. return(res);
  115. }
  116. #endif
  117. static int math_sqrt (lua_State *L) {
  118. #ifdef LUA_NUMBER_INTEGRAL
  119. lua_Number x = luaL_checknumber(L, 1);
  120. luaL_argcheck(L, 0<=x, 1, "negative");
  121. lua_pushnumber(L, isqrt(x));
  122. #else
  123. lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
  124. #endif
  125. return 1;
  126. }
  127. #ifdef LUA_NUMBER_INTEGRAL
  128. # define pow(a,b) luai_ipow(a,b)
  129. #endif
  130. static int math_pow (lua_State *L) {
  131. lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
  132. return 1;
  133. }
  134. #ifdef LUA_NUMBER_INTEGRAL
  135. # undef pow
  136. #endif
  137. #ifndef LUA_NUMBER_INTEGRAL
  138. static int math_log (lua_State *L) {
  139. lua_pushnumber(L, log(luaL_checknumber(L, 1)));
  140. return 1;
  141. }
  142. static int math_log10 (lua_State *L) {
  143. lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
  144. return 1;
  145. }
  146. static int math_exp (lua_State *L) {
  147. lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
  148. return 1;
  149. }
  150. static int math_deg (lua_State *L) {
  151. lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);
  152. return 1;
  153. }
  154. static int math_rad (lua_State *L) {
  155. lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);
  156. return 1;
  157. }
  158. static int math_frexp (lua_State *L) {
  159. int e;
  160. lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
  161. lua_pushinteger(L, e);
  162. return 2;
  163. }
  164. static int math_ldexp (lua_State *L) {
  165. lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
  166. return 1;
  167. }
  168. #endif // #ifdef LUA_NUMBER_INTEGRAL
  169. static int math_min (lua_State *L) {
  170. int n = lua_gettop(L); /* number of arguments */
  171. lua_Number dmin = luaL_checknumber(L, 1);
  172. int i;
  173. for (i=2; i<=n; i++) {
  174. lua_Number d = luaL_checknumber(L, i);
  175. if (d < dmin)
  176. dmin = d;
  177. }
  178. lua_pushnumber(L, dmin);
  179. return 1;
  180. }
  181. static int math_max (lua_State *L) {
  182. int n = lua_gettop(L); /* number of arguments */
  183. lua_Number dmax = luaL_checknumber(L, 1);
  184. int i;
  185. for (i=2; i<=n; i++) {
  186. lua_Number d = luaL_checknumber(L, i);
  187. if (d > dmax)
  188. dmax = d;
  189. }
  190. lua_pushnumber(L, dmax);
  191. return 1;
  192. }
  193. #ifdef LUA_NUMBER_INTEGRAL
  194. static int math_random (lua_State *L) {
  195. lua_Number r = (lua_Number)(rand()%RAND_MAX);
  196. switch (lua_gettop(L)) { /* check number of arguments */
  197. case 0: { /* no arguments */
  198. lua_pushnumber(L, 0); /* Number between 0 and 1 - always 0 with ints */
  199. break;
  200. }
  201. case 1: { /* only upper limit */
  202. int u = luaL_checkint(L, 1);
  203. luaL_argcheck(L, 1<=u, 1, "interval is empty");
  204. lua_pushnumber(L, (r % u)+1); /* int between 1 and `u' */
  205. break;
  206. }
  207. case 2: { /* lower and upper limits */
  208. int l = luaL_checkint(L, 1);
  209. int u = luaL_checkint(L, 2);
  210. luaL_argcheck(L, l<=u, 2, "interval is empty");
  211. lua_pushnumber(L, (r%(u-l+1))+l); /* int between `l' and `u' */
  212. break;
  213. }
  214. default: return luaL_error(L, "wrong number of arguments");
  215. }
  216. return 1;
  217. }
  218. #else
  219. static int math_random (lua_State *L) {
  220. /* the `%' avoids the (rare) case of r==1, and is needed also because on
  221. some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
  222. lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
  223. switch (lua_gettop(L)) { /* check number of arguments */
  224. case 0: { /* no arguments */
  225. lua_pushnumber(L, r); /* Number between 0 and 1 */
  226. break;
  227. }
  228. case 1: { /* only upper limit */
  229. int u = luaL_checkint(L, 1);
  230. luaL_argcheck(L, 1<=u, 1, "interval is empty");
  231. lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
  232. break;
  233. }
  234. case 2: { /* lower and upper limits */
  235. int l = luaL_checkint(L, 1);
  236. int u = luaL_checkint(L, 2);
  237. luaL_argcheck(L, l<=u, 2, "interval is empty");
  238. lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
  239. break;
  240. }
  241. default: return luaL_error(L, "wrong number of arguments");
  242. }
  243. return 1;
  244. }
  245. #endif
  246. static int math_randomseed (lua_State *L) {
  247. srand(luaL_checkint(L, 1));
  248. return 0;
  249. }
  250. #define MIN_OPT_LEVEL 1
  251. #include "lrodefs.h"
  252. const LUA_REG_TYPE math_map[] = {
  253. #ifdef LUA_NUMBER_INTEGRAL
  254. {LSTRKEY("abs"), LFUNCVAL(math_abs)},
  255. {LSTRKEY("ceil"), LFUNCVAL(math_identity)},
  256. {LSTRKEY("floor"), LFUNCVAL(math_identity)},
  257. {LSTRKEY("max"), LFUNCVAL(math_max)},
  258. {LSTRKEY("min"), LFUNCVAL(math_min)},
  259. {LSTRKEY("pow"), LFUNCVAL(math_pow)},
  260. {LSTRKEY("random"), LFUNCVAL(math_random)},
  261. {LSTRKEY("randomseed"), LFUNCVAL(math_randomseed)},
  262. {LSTRKEY("sqrt"), LFUNCVAL(math_sqrt)},
  263. #if LUA_OPTIMIZE_MEMORY > 0
  264. {LSTRKEY("huge"), LNUMVAL(LONG_MAX)},
  265. #endif
  266. #else
  267. {LSTRKEY("abs"), LFUNCVAL(math_abs)},
  268. {LSTRKEY("acos"), LFUNCVAL(math_acos)},
  269. {LSTRKEY("asin"), LFUNCVAL(math_asin)},
  270. {LSTRKEY("atan2"), LFUNCVAL(math_atan2)},
  271. {LSTRKEY("atan"), LFUNCVAL(math_atan)},
  272. {LSTRKEY("ceil"), LFUNCVAL(math_ceil)},
  273. {LSTRKEY("cosh"), LFUNCVAL(math_cosh)},
  274. {LSTRKEY("cos"), LFUNCVAL(math_cos)},
  275. {LSTRKEY("deg"), LFUNCVAL(math_deg)},
  276. {LSTRKEY("exp"), LFUNCVAL(math_exp)},
  277. {LSTRKEY("floor"), LFUNCVAL(math_floor)},
  278. {LSTRKEY("fmod"), LFUNCVAL(math_fmod)},
  279. #if LUA_OPTIMIZE_MEMORY > 0 && defined(LUA_COMPAT_MOD)
  280. {LSTRKEY("mod"), LFUNCVAL(math_fmod)},
  281. #endif
  282. {LSTRKEY("frexp"), LFUNCVAL(math_frexp)},
  283. {LSTRKEY("ldexp"), LFUNCVAL(math_ldexp)},
  284. {LSTRKEY("log10"), LFUNCVAL(math_log10)},
  285. {LSTRKEY("log"), LFUNCVAL(math_log)},
  286. {LSTRKEY("max"), LFUNCVAL(math_max)},
  287. {LSTRKEY("min"), LFUNCVAL(math_min)},
  288. {LSTRKEY("modf"), LFUNCVAL(math_modf)},
  289. {LSTRKEY("pow"), LFUNCVAL(math_pow)},
  290. {LSTRKEY("rad"), LFUNCVAL(math_rad)},
  291. {LSTRKEY("random"), LFUNCVAL(math_random)},
  292. {LSTRKEY("randomseed"), LFUNCVAL(math_randomseed)},
  293. {LSTRKEY("sinh"), LFUNCVAL(math_sinh)},
  294. {LSTRKEY("sin"), LFUNCVAL(math_sin)},
  295. {LSTRKEY("sqrt"), LFUNCVAL(math_sqrt)},
  296. {LSTRKEY("tanh"), LFUNCVAL(math_tanh)},
  297. {LSTRKEY("tan"), LFUNCVAL(math_tan)},
  298. #if LUA_OPTIMIZE_MEMORY > 0
  299. {LSTRKEY("pi"), LNUMVAL(PI)},
  300. {LSTRKEY("huge"), LNUMVAL(HUGE_VAL)},
  301. #endif // #if LUA_OPTIMIZE_MEMORY > 0
  302. #endif // #ifdef LUA_NUMBER_INTEGRAL
  303. {LNILKEY, LNILVAL}
  304. };
  305. /*
  306. ** Open math library
  307. */
  308. #if defined LUA_NUMBER_INTEGRAL
  309. # include <limits.h> /* for LONG_MAX */
  310. #endif
  311. LUALIB_API int luaopen_math (lua_State *L) {
  312. #if LUA_OPTIMIZE_MEMORY > 0
  313. return 0;
  314. #else
  315. luaL_register(L, LUA_MATHLIBNAME, math_map);
  316. # if defined LUA_NUMBER_INTEGRAL
  317. lua_pushnumber(L, LONG_MAX);
  318. lua_setfield(L, -2, "huge");
  319. # else
  320. lua_pushnumber(L, PI);
  321. lua_setfield(L, -2, "pi");
  322. lua_pushnumber(L, HUGE_VAL);
  323. lua_setfield(L, -2, "huge");
  324. # if defined(LUA_COMPAT_MOD)
  325. lua_getfield(L, -1, "fmod");
  326. lua_setfield(L, -2, "mod");
  327. # endif
  328. # endif
  329. return 1;
  330. #endif
  331. }