release 0.1.13
[liba.git] / lua / src / complex.c
blobd916c94d566eb500ccc1455719227d5ad7a8b2e2
1 /***
2 complex number
3 @module liba.complex
4 */
6 #include "complex.h"
7 #include "a/complex.h"
9 static int liba_complex_isok(lua_State *L, int idx)
11 int ok = 0;
12 if (lua_getmetatable(L, idx))
14 lua_registry_get(L, liba_complex_new);
15 ok = lua_rawequal(L, -1, -2);
16 lua_pop(L, 2);
18 return ok;
21 static int liba_complex_from(lua_State *L, a_complex *z, int idx)
23 int type = lua_type(L, idx);
24 switch (type)
26 case LUA_TNUMBER:
27 z->real = (a_float)lua_tonumber(L, idx);
28 z->imag = 0;
29 break;
30 case LUA_TSTRING:
31 a_complex_parse(z, lua_tostring(L, idx));
32 break;
33 case LUA_TUSERDATA:
34 if (liba_complex_isok(L, idx))
36 *z = *(a_complex *)lua_touserdata(L, idx);
37 break;
39 A_FALLTHROUGH;
40 default:
41 z->real = 0;
42 z->imag = 0;
44 return type;
47 static a_complex *liba_complex_new_(lua_State *L)
49 a_complex *const ctx = lua_newclass(L, a_complex);
50 lua_registry_get(L, liba_complex_new);
51 lua_setmetatable(L, -2);
52 return ctx;
55 static int liba_complex_tostring(lua_State *L)
57 a_complex const *const ctx = (a_complex const *)lua_touserdata(L, 1);
58 if (ctx)
60 lua_pushfstring(L, "(%f,%f)", (double)ctx->real, (double)ctx->imag);
61 return 1;
63 return 0;
66 /***
67 constructor for complex number from real and imaginary parts
68 @tparam[opt] number|string|a.complex real real part of complex number
69 @tparam[opt] number imag imaginary part of complex number
70 @treturn a.complex complex number userdata
71 @function new
73 int liba_complex_new(lua_State *L)
75 a_complex z = A_COMPLEX_C(0.0, 0.0);
76 int const top = lua_gettop(L);
77 if (top >= 1)
79 int const type = liba_complex_from(L, &z, 1);
80 if (type == LUA_TNUMBER && top >= 2)
82 z.imag = (a_float)lua_tonumber(L, 2);
85 *liba_complex_new_(L) = z;
86 return 1;
89 /***
90 constructor for complex number from rectangular Cartesian components
91 @tparam[opt] number real real part of complex number
92 @tparam[opt] number imag imaginary part of complex number
93 @treturn a.complex complex number userdata
94 @function rect
96 int liba_complex_rect(lua_State *L)
98 a_float real = 0, imag = 0;
99 int const top = lua_gettop(L);
100 if (top >= 1) { real = (a_float)lua_tonumber(L, 1); }
101 if (top >= 2) { imag = (a_float)lua_tonumber(L, 2); }
102 a_complex_rect(liba_complex_new_(L), real, imag);
103 return 1;
106 /***
107 constructor for complex number from polar form
108 @tparam[opt] number rho a distance from a reference point
109 @tparam[opt] number theta an angle from a reference direction
110 @treturn a.complex complex number userdata
111 @function polar
113 int liba_complex_polar(lua_State *L)
115 a_float rho = 0, theta = 0;
116 int const top = lua_gettop(L);
117 if (top >= 1) { rho = (a_float)lua_tonumber(L, 1); }
118 if (top >= 2) { theta = (a_float)lua_tonumber(L, 2); }
119 a_complex_polar(liba_complex_new_(L), rho, theta);
120 return 1;
123 /***
124 complex number x is equal to complex number y
125 @tparam a.complex x complex number on the left
126 @tparam a.complex y complex number on the right
127 @treturn bool result of comparison
128 @function eq
130 int liba_complex_eq(lua_State *L)
132 if (lua_gettop(L) >= 2)
134 a_complex x, y;
135 liba_complex_from(L, &x, 1);
136 liba_complex_from(L, &y, 2);
137 lua_pushboolean(L, a_complex_eq(x, y));
138 return 1;
140 return 0;
143 /***
144 complex number x is not equal to complex number y
145 @tparam a.complex x complex number on the left
146 @tparam a.complex y complex number on the right
147 @treturn bool result of comparison
148 @function ne
150 int liba_complex_ne(lua_State *L)
152 if (lua_gettop(L) >= 2)
154 a_complex x, y;
155 liba_complex_from(L, &x, 1);
156 liba_complex_from(L, &y, 2);
157 lua_pushboolean(L, a_complex_ne(x, y));
158 return 1;
160 return 0;
163 #undef F1
164 #define F1(func) \
165 int liba_complex_##func(lua_State *L) \
167 if (lua_gettop(L) >= 1) \
169 a_complex z; \
170 liba_complex_from(L, &z, 1); \
171 z.real = a_complex_##func(z); \
172 lua_pushnumber(L, (lua_Number)z.real); \
173 return 1; \
175 return 0; \
177 /***
178 computes the natural logarithm of magnitude of a complex number
179 @tparam a.complex z complex number userdata
180 @treturn number log|z|
181 @function logabs
183 F1(logabs)
184 /***
185 computes the squared magnitude of a complex number
186 @tparam a.complex z complex number userdata
187 @treturn number a^2+b^2
188 @function abs2
190 F1(abs2)
191 /***
192 computes the magnitude of a complex number
193 @tparam a.complex z complex number userdata
194 @treturn number sqrt{a^2+b^2}
195 @function abs
197 F1(abs)
198 /***
199 computes the phase angle of a complex number
200 @tparam a.complex z complex number userdata
201 @treturn number arctan(b/a)
202 @function arg
204 F1(arg)
205 #undef F1
206 #define F1(func) \
207 int liba_complex_##func(lua_State *L) \
209 if (lua_gettop(L) >= 1) \
211 a_complex z, *ctx; \
212 ctx = liba_complex_new_(L); \
213 liba_complex_from(L, &z, 1); \
214 a_complex_##func(ctx, z); \
215 return 1; \
217 return 0; \
219 /***
220 computes the projection on Riemann sphere
221 @tparam a.complex z complex number userdata
222 @treturn a.complex complex number userdata
223 @function proj
225 F1(proj)
226 /***
227 computes the complex conjugate
228 @tparam a.complex z complex number userdata
229 @treturn a.complex complex number userdata
230 @function conj
232 F1(conj)
233 /***
234 computes the complex negative
235 @tparam a.complex z complex number userdata
236 @treturn a.complex complex number userdata
237 @function unm
239 F1(neg)
240 /***
241 inverse of a complex number
242 @tparam a.complex z complex number userdata
243 @treturn a.complex complex number userdata
244 @function inv
246 F1(inv)
247 #undef F1
248 #define F1(func) \
249 int liba_complex_##func(lua_State *L) \
251 if (lua_gettop(L) >= 2) \
253 a_complex x, y, *ctx; \
254 ctx = liba_complex_new_(L); \
255 liba_complex_from(L, &x, 1); \
256 liba_complex_from(L, &y, 2); \
257 a_complex_##func(ctx, x, y); \
258 return 1; \
260 return 0; \
262 #undef F2
263 #define F2(func) \
264 int liba_complex_##func(lua_State *L) \
266 if (lua_gettop(L) >= 2) \
268 a_complex x, y, *ctx = liba_complex_new_(L); \
269 liba_complex_from(L, &x, 1); \
270 if (liba_complex_from(L, &y, 2) == LUA_TNUMBER) \
272 a_complex_##func##_real(ctx, x, y.real); \
274 else { a_complex_##func(ctx, x, y); } \
275 return 1; \
277 return 0; \
279 /***
280 addition of complex numbers
281 @tparam a.complex x complex number userdata
282 @tparam a.complex y complex number userdata
283 @treturn a.complex complex number userdata
284 @function add
286 F2(add)
287 /***
288 subtraction of complex numbers
289 @tparam a.complex x complex number userdata
290 @tparam a.complex y complex number userdata
291 @treturn a.complex complex number userdata
292 @function sub
294 F2(sub)
295 /***
296 multiplication of complex numbers
297 @tparam a.complex x complex number userdata
298 @tparam a.complex y complex number userdata
299 @treturn a.complex complex number userdata
300 @function mul
302 F2(mul)
303 /***
304 division of complex numbers
305 @tparam a.complex x complex number userdata
306 @tparam a.complex y complex number userdata
307 @treturn a.complex complex number userdata
308 @function div
310 F2(div)
311 /***
312 complex number z raised to complex power a
313 @tparam a.complex z complex number userdata
314 @tparam a.complex a complex number userdata
315 @treturn a.complex complex number userdata
316 @function pow
318 F1(pow)
319 /***
320 computes the complex base-b logarithm
321 @tparam a.complex z complex number userdata
322 @tparam a.complex b complex number userdata
323 @treturn a.complex complex number userdata
324 @function logb
326 F1(logb)
327 #undef F1
328 #define F1(func) \
329 int liba_complex_##func(lua_State *L) \
331 if (lua_gettop(L) >= 1) \
333 a_complex z, *ctx; \
334 ctx = liba_complex_new_(L); \
335 liba_complex_from(L, &z, 1); \
336 a_complex_##func(ctx, z); \
337 return 1; \
339 return 0; \
341 #undef F2
342 #define F2(func) \
343 int liba_complex_##func(lua_State *L) \
345 if (lua_gettop(L) >= 1) \
347 a_complex z, *ctx = liba_complex_new_(L); \
348 int type = liba_complex_from(L, &z, 1); \
349 if (type == LUA_TNUMBER) \
351 a_complex_##func##_real(ctx, z.real); \
353 else { a_complex_##func(ctx, z); } \
354 return 1; \
356 return 0; \
358 /***
359 computes the complex base-e exponential
360 @tparam a.complex z complex number userdata
361 @treturn a.complex complex number userdata
362 @function exp
364 F1(exp)
365 /***
366 computes the complex natural logarithm
367 @tparam a.complex z complex number userdata
368 @treturn a.complex complex number userdata
369 @function log
371 F1(log)
372 /***
373 computes the complex square root
374 @tparam a.complex z complex number userdata
375 @treturn a.complex complex number userdata
376 @function sqrt
378 F2(sqrt)
379 /***
380 computes the complex base-2 logarithm
381 @tparam a.complex z complex number userdata
382 @treturn a.complex complex number userdata
383 @function log2
385 F1(log2)
386 /***
387 computes the complex base-10 logarithm
388 @tparam a.complex z complex number userdata
389 @treturn a.complex complex number userdata
390 @function log10
392 F1(log10)
393 /***
394 computes the complex sine
395 @tparam a.complex z complex number userdata
396 @treturn a.complex complex number userdata
397 @function sin
399 F1(sin)
400 /***
401 computes the complex cosine
402 @tparam a.complex z complex number userdata
403 @treturn a.complex complex number userdata
404 @function cos
406 F1(cos)
407 /***
408 computes the complex tangent
409 @tparam a.complex z complex number userdata
410 @treturn a.complex complex number userdata
411 @function tan
413 F1(tan)
414 /***
415 computes the complex secant
416 @tparam a.complex z complex number userdata
417 @treturn a.complex complex number userdata
418 @function sec
420 F1(sec)
421 /***
422 computes the complex cosecant
423 @tparam a.complex z complex number userdata
424 @treturn a.complex complex number userdata
425 @function csc
427 F1(csc)
428 /***
429 computes the complex cotangent
430 @tparam a.complex z complex number userdata
431 @treturn a.complex complex number userdata
432 @function cot
434 F1(cot)
435 /***
436 computes the complex arc sine
437 @tparam a.complex z complex number userdata
438 @treturn a.complex complex number userdata
439 @function asin
441 F2(asin)
442 /***
443 computes the complex arc cosine
444 @tparam a.complex z complex number userdata
445 @treturn a.complex complex number userdata
446 @function acos
448 F2(acos)
449 /***
450 computes the complex arc tangent
451 @tparam a.complex z complex number userdata
452 @treturn a.complex complex number userdata
453 @function atan
455 F1(atan)
456 /***
457 computes the complex arc secant
458 @tparam a.complex z complex number userdata
459 @treturn a.complex complex number userdata
460 @function asec
462 F2(asec)
463 /***
464 computes the complex arc cosecant
465 @tparam a.complex z complex number userdata
466 @treturn a.complex complex number userdata
467 @function acsc
469 F2(acsc)
470 /***
471 computes the complex arc cotangent
472 @tparam a.complex z complex number userdata
473 @treturn a.complex complex number userdata
474 @function acot
476 F1(acot)
477 /***
478 computes the complex hyperbolic sine
479 @tparam a.complex z complex number userdata
480 @treturn a.complex complex number userdata
481 @function sinh
483 F1(sinh)
484 /***
485 computes the complex hyperbolic cosine
486 @tparam a.complex z complex number userdata
487 @treturn a.complex complex number userdata
488 @function cosh
490 F1(cosh)
491 /***
492 computes the complex hyperbolic tangent
493 @tparam a.complex z complex number userdata
494 @treturn a.complex complex number userdata
495 @function tanh
497 F1(tanh)
498 /***
499 computes the complex hyperbolic secant
500 @tparam a.complex z complex number userdata
501 @treturn a.complex complex number userdata
502 @function sech
504 F1(sech)
505 /***
506 computes the complex hyperbolic cosecant
507 @tparam a.complex z complex number userdata
508 @treturn a.complex complex number userdata
509 @function csch
511 F1(csch)
512 /***
513 computes the complex hyperbolic cotangent
514 @tparam a.complex z complex number userdata
515 @treturn a.complex complex number userdata
516 @function coth
518 F1(coth)
519 /***
520 computes the complex arc hyperbolic sine
521 @tparam a.complex z complex number userdata
522 @treturn a.complex complex number userdata
523 @function asinh
525 F1(asinh)
526 /***
527 computes the complex arc hyperbolic cosine
528 @tparam a.complex z complex number userdata
529 @treturn a.complex complex number userdata
530 @function acosh
532 F2(acosh)
533 /***
534 computes the complex arc hyperbolic tangent
535 @tparam a.complex z complex number userdata
536 @treturn a.complex complex number userdata
537 @function atanh
539 F2(atanh)
540 /***
541 computes the complex arc hyperbolic secant
542 @tparam a.complex z complex number userdata
543 @treturn a.complex complex number userdata
544 @function asech
546 F1(asech)
547 /***
548 computes the complex arc hyperbolic cosecant
549 @tparam a.complex z complex number userdata
550 @treturn a.complex complex number userdata
551 @function acsch
553 F1(acsch)
554 /***
555 computes the complex arc hyperbolic cotangent
556 @tparam a.complex z complex number userdata
557 @treturn a.complex complex number userdata
558 @function acoth
560 F1(acoth)
562 static int liba_complex_set(lua_State *L)
564 a_complex *const ctx = (a_complex *)lua_touserdata(L, 1);
565 switch (a_hash_bkdr(lua_tostring(L, 2), 0))
567 case 0x0F6133A2: // real
568 ctx->real = (a_float)luaL_checknumber(L, 3);
569 break;
570 case 0x0E2E9172: // imag
571 ctx->imag = (a_float)luaL_checknumber(L, 3);
572 break;
573 case 0x001E0FA9: // rho
575 a_float const rho = (a_float)luaL_checknumber(L, 3);
576 a_float const theta = a_complex_arg(*ctx);
577 a_complex_polar(ctx, rho, theta);
578 break;
580 case 0x0240D1F6: // theta
582 a_float const theta = (a_float)luaL_checknumber(L, 3);
583 a_float const rho = a_complex_abs(*ctx);
584 a_complex_polar(ctx, rho, theta);
585 break;
587 case 0x0CD3E0FC: // __eq
588 case 0x906DF07D: // __len
589 case 0x90705068: // __unm
590 case 0x906B0E8D: // __add
591 case 0x906FCDE0: // __sub
592 case 0x906E3BB4: // __mul
593 case 0x906BDA49: // __div
594 case 0x906F01C8: // __pow
595 case 0xE8859EEB: // __name
596 case 0xA65758B2: // __index
597 case 0xAEB551C6: // __newindex
598 case 0x5DA21A54: // __tostring
599 break;
600 default:
601 lua_getmetatable(L, 1);
602 lua_replace(L, 1);
603 lua_rawset(L, 1);
605 return 0;
608 static int liba_complex_get(lua_State *L)
610 a_complex const *const ctx = (a_complex const *)lua_touserdata(L, 1);
611 switch (a_hash_bkdr(lua_tostring(L, 2), 0))
613 case 0x0F6133A2: // real
614 lua_pushnumber(L, (lua_Number)ctx->real);
615 break;
616 case 0x0E2E9172: // imag
617 lua_pushnumber(L, (lua_Number)ctx->imag);
618 break;
619 case 0x001E0FA9: // rho
620 lua_pushnumber(L, (lua_Number)a_complex_abs(*ctx));
621 break;
622 case 0x0240D1F6: // theta
623 lua_pushnumber(L, (lua_Number)a_complex_arg(*ctx));
624 break;
625 case 0xA65758B2: // __index
626 lua_registry_get(L, liba_complex_new);
627 lua_num_set(L, -1, "real", ctx->real);
628 lua_num_set(L, -1, "imag", ctx->imag);
629 lua_num_set(L, -1, "rho", a_complex_abs(*ctx));
630 lua_num_set(L, -1, "theta", a_complex_arg(*ctx));
631 break;
632 default:
633 lua_getmetatable(L, 1);
634 lua_replace(L, 1);
635 lua_rawget(L, 1);
637 return 1;
640 static int liba_complex_(lua_State *L)
642 lua_pushcfunction(L, liba_complex_new);
643 lua_replace(L, 1);
644 lua_call(L, lua_gettop(L) - 1, 1);
645 return 1;
648 int luaopen_liba_complex(lua_State *L)
650 static lua_fun const funcs[] = {
651 {"new", liba_complex_new},
652 {"rect", liba_complex_rect},
653 {"polar", liba_complex_polar},
654 {"eq", liba_complex_eq},
655 {"ne", liba_complex_ne},
656 {"logabs", liba_complex_logabs},
657 {"proj", liba_complex_proj},
658 {"conj", liba_complex_conj},
659 {"abs2", liba_complex_abs2},
660 {"abs", liba_complex_abs},
661 {"arg", liba_complex_arg},
662 {"unm", liba_complex_neg},
663 {"add", liba_complex_add},
664 {"sub", liba_complex_sub},
665 {"mul", liba_complex_mul},
666 {"div", liba_complex_div},
667 {"inv", liba_complex_inv},
668 {"pow", liba_complex_pow},
669 {"exp", liba_complex_exp},
670 {"log", liba_complex_log},
671 {"log2", liba_complex_log2},
672 {"log10", liba_complex_log10},
673 {"logb", liba_complex_logb},
674 {"sqrt", liba_complex_sqrt},
675 {"sin", liba_complex_sin},
676 {"cos", liba_complex_cos},
677 {"tan", liba_complex_tan},
678 {"sec", liba_complex_sec},
679 {"csc", liba_complex_csc},
680 {"cot", liba_complex_cot},
681 {"asin", liba_complex_asin},
682 {"acos", liba_complex_acos},
683 {"atan", liba_complex_atan},
684 {"asec", liba_complex_asec},
685 {"acsc", liba_complex_acsc},
686 {"acot", liba_complex_acot},
687 {"sinh", liba_complex_sinh},
688 {"cosh", liba_complex_cosh},
689 {"tanh", liba_complex_tanh},
690 {"sech", liba_complex_sech},
691 {"csch", liba_complex_csch},
692 {"coth", liba_complex_coth},
693 {"asinh", liba_complex_asinh},
694 {"acosh", liba_complex_acosh},
695 {"atanh", liba_complex_atanh},
696 {"asech", liba_complex_asech},
697 {"acsch", liba_complex_acsch},
698 {"acoth", liba_complex_acoth},
700 lua_createtable(L, 0, A_LEN(funcs));
701 lua_fun_reg(L, -1, funcs, A_LEN(funcs));
702 lua_createtable(L, 0, 1);
703 lua_fun_set(L, -1, "__call", liba_complex_);
704 lua_setmetatable(L, -2);
706 static lua_fun const metas[] = {
707 {"__tostring", liba_complex_tostring},
708 {"__newindex", liba_complex_set},
709 {"__index", liba_complex_get},
710 {"__len", liba_complex_abs},
711 {"__unm", liba_complex_neg},
712 {"__add", liba_complex_add},
713 {"__sub", liba_complex_sub},
714 {"__mul", liba_complex_mul},
715 {"__div", liba_complex_div},
716 {"__pow", liba_complex_pow},
717 {"__eq", liba_complex_eq},
719 lua_createtable(L, 0, A_LEN(metas) + A_LEN(funcs) + 1);
720 lua_fun_reg(L, -1, metas, A_LEN(metas));
721 lua_fun_reg(L, -1, funcs, A_LEN(funcs));
722 lua_str_set(L, -1, "__name", "a.complex");
723 lua_registry_set(L, liba_complex_new);
725 return 1;