/lcomplex.c

https://github.com/LuaDist/lcomplex · C · 174 lines · 154 code · 13 blank · 7 comment · 9 complexity · e897d17a6d809ba835a5a0196eb941ab MD5 · raw file

  1. /*
  2. * lcomplex.c
  3. * C99 complex nummbers for Lua
  4. * Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>
  5. * 02 Nov 2009 23:15:43
  6. * This code is hereby placed in the public domain.
  7. */
  8. #include <complex.h>
  9. #define Complex double complex
  10. #include "lua.h"
  11. #include "lauxlib.h"
  12. #define MYNAME "complex"
  13. #define MYTYPE MYNAME " number"
  14. #define MYVERSION MYTYPE " library for " LUA_VERSION " / Nov 2009"
  15. #define Z(i) Pget(L,i)
  16. #define O(i) luaL_optnumber(L,i,0)
  17. #define cadd(z,w) ((z)+(w))
  18. #define csub(z,w) ((z)-(w))
  19. #define cmul(z,w) ((z)*(w))
  20. #define cdiv(z,w) ((z)/(w))
  21. #define cneg(z) (-(z))
  22. #define cconj conj
  23. static Complex Pget(lua_State *L, int i)
  24. {
  25. switch (lua_type(L,i))
  26. {
  27. case LUA_TNUMBER:
  28. case LUA_TSTRING:
  29. return luaL_checknumber(L,i);
  30. default:
  31. return *((Complex*)luaL_checkudata(L,i,MYTYPE));
  32. }
  33. }
  34. static int pushcomplex(lua_State *L, Complex z)
  35. {
  36. Complex *p=lua_newuserdata(L,sizeof(Complex));
  37. *p=z;
  38. luaL_getmetatable(L,MYTYPE);
  39. lua_setmetatable(L,-2);
  40. return 1;
  41. }
  42. static int Leq(lua_State *L) /** __eq(z,w) */
  43. {
  44. lua_pushboolean(L,Z(1)==Z(2));
  45. return 1;
  46. }
  47. static int Ltostring(lua_State *L) /** tostring(z) */
  48. {
  49. Complex z=Z(1);
  50. double x=creal(z);
  51. double y=cimag(z);
  52. lua_settop(L,0);
  53. if (x!=0) lua_pushnumber(L,x);
  54. if (y!=0)
  55. {
  56. if (y==1)
  57. {
  58. if (x!=0) lua_pushliteral(L,"+");
  59. }
  60. else if (y==-1)
  61. lua_pushliteral(L,"-");
  62. else
  63. {
  64. if (y>0 && x!=0) lua_pushliteral(L,"+");
  65. lua_pushnumber(L,y);
  66. }
  67. lua_pushliteral(L,"i");
  68. }
  69. lua_concat(L,lua_gettop(L));
  70. return 1;
  71. }
  72. #define A(f,e) static int L##f(lua_State *L) { return pushcomplex(L,e); }
  73. #define B(f) A(f,c##f(Z(1),Z(2)))
  74. #define F(f) A(f,c##f(Z(1)))
  75. #define G(f) static int L##f(lua_State *L) { lua_pushnumber(L,c##f(Z(1))); return 1; }
  76. A(new,O(1)+O(2)*I) /** new(x,y) */
  77. B(add) /** __add(z,w) */
  78. B(div) /** __div(z,w) */
  79. B(mul) /** __mul(z,w) */
  80. B(sub) /** __sub(z,w) */
  81. F(neg) /** __unm(z) */
  82. G(abs) /** abs(z) */
  83. F(acos) /** acos(z) */
  84. F(acosh) /** acosh(z) */
  85. G(arg) /** arg(z) */
  86. F(asin) /** asin(z) */
  87. F(asinh) /** asinh(z) */
  88. F(atan) /** atan(z) */
  89. F(atanh) /** atanh(z) */
  90. F(conj) /** conj(z) */
  91. F(cos) /** cos(z) */
  92. F(cosh) /** cosh(z) */
  93. F(exp) /** exp(z) */
  94. G(imag) /** imag(z) */
  95. F(log) /** log(z) */
  96. B(pow) /** pow(z,w) */
  97. F(proj) /** proj(z) */
  98. G(real) /** real(z) */
  99. F(sin) /** sin(z) */
  100. F(sinh) /** sinh(z) */
  101. F(sqrt) /** sqrt(z) */
  102. F(tan) /** tan(z) */
  103. F(tanh) /** tanh(z) */
  104. static const luaL_Reg R[] =
  105. {
  106. { "__add", Ladd },
  107. { "__div", Ldiv },
  108. { "__eq", Leq },
  109. { "__mul", Lmul },
  110. { "__sub", Lsub },
  111. { "__unm", Lneg },
  112. { "abs", Labs },
  113. { "acos", Lacos },
  114. { "acosh", Lacosh },
  115. { "arg", Larg },
  116. { "asin", Lasin },
  117. { "asinh", Lasinh },
  118. { "atan", Latan },
  119. { "atanh", Latanh },
  120. { "conj", Lconj },
  121. { "cos", Lcos },
  122. { "cosh", Lcosh },
  123. { "exp", Lexp },
  124. { "imag", Limag },
  125. { "log", Llog },
  126. { "new", Lnew },
  127. { "pow", Lpow },
  128. { "proj", Lproj },
  129. { "real", Lreal },
  130. { "sin", Lsin },
  131. { "sinh", Lsinh },
  132. { "sqrt", Lsqrt },
  133. { "tan", Ltan },
  134. { "tanh", Ltanh },
  135. { "tostring", Ltostring},
  136. { NULL, NULL }
  137. };
  138. LUALIB_API int luaopen_complex(lua_State *L)
  139. {
  140. luaL_newmetatable(L,MYTYPE);
  141. lua_setglobal(L,MYNAME);
  142. luaL_register(L,MYNAME,R);
  143. lua_pushliteral(L,"version"); /** version */
  144. lua_pushliteral(L,MYVERSION);
  145. lua_settable(L,-3);
  146. lua_pushliteral(L,"__index");
  147. lua_pushvalue(L,-2);
  148. lua_settable(L,-3);
  149. lua_pushliteral(L,"I"); /** I */
  150. pushcomplex(L,I);
  151. lua_settable(L,-3);
  152. lua_pushliteral(L,"__pow"); /** __pow(z,w) */
  153. lua_pushliteral(L,"pow");
  154. lua_gettable(L,-3);
  155. lua_settable(L,-3);
  156. lua_pushliteral(L,"__tostring"); /** __tostring(z) */
  157. lua_pushliteral(L,"tostring");
  158. lua_gettable(L,-3);
  159. lua_settable(L,-3);
  160. return 1;
  161. }