2 Copyright (C) 2004-2009, Parrot Foundation.
7 src/pmc/complex.pmc - Complex Numbers PMC Class
11 C<Complex> provides a representation of complex numbers. It handles
12 string parsing/generating and basic mathematical operations.
20 Equations used are sometimes listed. At times, multiple equations are given,
21 but those starting with => are the ones used
28 complex_parse_string(PARROT_INTERP, FLOATVAL *re, FLOATVAL *im, STRING *value)>
30 Parses the string in C<value> to produce a complex number, represented
31 by the real (C<*re>) and imaginary (C<*im>) parts. Raises an exception
32 if it cannot understand the string. The string should be of the form
33 C<a+bi> with optional spaces around C<+> and before C<i>. You can also
34 use C<j> instead of C<i>.
41 complex_parse_string(PARROT_INTERP, FLOATVAL *re, FLOATVAL *im, STRING *value) {
42 char * const str = Parrot_str_to_cstring(interp, value);
44 char *first_num_offset = str;
45 char *second_num_offset = NULL;
49 INTVAL first_num_minus = 0;
50 INTVAL second_num_minus = 0;
51 UINTVAL first_num_length, second_num_length;
53 /* walk the string and identify the real and imaginary parts */
56 /* first number is negative */
60 /* allow for an optional space */
67 while (*t >= '0' && *t <= '9')
71 /* this number has a decimal point */
75 while (*t >= '0' && *t <= '9')
79 /* save the length of the real part */
80 first_num_length = t - first_num_offset;
82 /* end of string; we only have a real part */
84 second_num_length = 0;
86 else if ((*t == 'i' || *t == 'j') && *(t+1) == 0) {
87 /* there is only an imaginary part, so the first number was
88 actually the imaginary part */
89 second_num_length = first_num_length;
91 second_num_offset = first_num_offset;
92 second_num_minus = first_num_minus;
95 /* this is useful if there is no number for
96 the imaginary part, like in "-i" */
100 /* skip an optional space */
104 /* expect "+" or "-" and the imaginary part */
105 if (*t == '+' || *t == '-') {
107 second_num_minus = (*t == '-');
110 /* skip another optional space */
114 /* save the beginning of the imaginary part */
115 second_num_offset = t;
118 while (*t >= '0' && *t <= '9')
122 /* this number has a decimal point */
126 while (*t >= '0' && *t <= '9')
130 /* save the length of the imaginary part */
131 second_num_length = t - second_num_offset;
133 /* allow for one more optional space */
137 /* verify that the string ends properly */
138 if ((*t != 'i' && *t != 'j') || (*(t+1) != 0)) {
139 /* imaginary part does not end in 'i' or 'j' */
140 Parrot_ex_throw_from_c_args(interp, NULL,
141 EXCEPTION_INVALID_STRING_REPRESENTATION,
142 "Complex: malformed string");
145 /* this is useful if there is no number for the
146 imaginary part, like in "2+i" */
149 /* all is OK, save the number */
152 /* "+" or "-" not found: error */
153 Parrot_str_free_cstring(str);
155 Parrot_ex_throw_from_c_args(interp, NULL,
156 EXCEPTION_INVALID_STRING_REPRESENTATION,
157 "Complex: malformed string");
161 /* now we have the offsets and the lengths we turn them into float values */
163 if (first_num_length) {
164 /* there is a real part, interpret it */
165 S = Parrot_str_new(interp, first_num_offset, first_num_length);
166 *re = Parrot_str_to_num(interp, S);
169 /* consider the real part 0.0 */
173 if (second_num_length) {
174 /* there is an imaginary part, interpret it */
175 S = Parrot_str_new(interp, second_num_offset, second_num_length);
176 *im = Parrot_str_to_num(interp, S);
179 /* consider the imaginary part 0.0 */
180 if (i) /* the string was something like "1+i" */
189 if (second_num_minus)
192 Parrot_str_free_cstring(str);
196 int_check_divide_zero(PARROT_INTERP, INTVAL value) {
198 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_DIV_BY_ZERO,
203 float_check_divide_zero(PARROT_INTERP, FLOATVAL value) {
204 if (FLOAT_IS_ZERO(value))
205 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_DIV_BY_ZERO,
210 complex_check_divide_zero(PARROT_INTERP, PMC *value) {
211 /* Throw an exception if we are dividing by zero. Check both the real part
212 * and the imaginary part.*/
213 if (FLOAT_IS_ZERO(VTABLE_get_number_keyed_int(interp, value, 0))
214 && FLOAT_IS_ZERO(VTABLE_get_number_keyed_int(interp, value, 1)))
215 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_DIV_BY_ZERO,
220 pmclass Complex auto_attrs {
222 ATTR FLOATVAL re; /* real part */
223 ATTR FLOATVAL im; /* imaginary part */
227 =item C<PMC *instantiate(PMC *sig)>
229 Create a new complex PMC with passed arguments according to pdd03.
235 VTABLE PMC *instantiate(PMC *sig) {
238 /* TODO -- really build this thing */
240 PMC *res = pmc_new(INTERP, enum_class_Complex);
243 int argcI = REG_INT(interp, 1);
244 int argcS = REG_INT(interp, 2);
245 int argcP = REG_INT(interp, 3);
246 int argcN = REG_INT(interp, 4);
249 * we can only allow 0..2 arguments of one kind. For
250 * mixed (e.g. N, P) args the order of arguments isn't fixed
253 re = VTABLE_get_number(INTERP, REG_PMC(interp, 5));
256 im = VTABLE_get_number(INTERP, REG_PMC(interp, 6));
257 /* TODO throw exception if argument mismatch */
260 re = REG_NUM(interp, 5);
263 im = REG_NUM(interp, 6);
266 re = REG_INT(interp, 5);
269 im = REG_INT(interp, 6);
271 else if (argcS == 1) {
272 complex_parse_string(INTERP, &RE(res), &IM(res), REG_STR(interp, 5));
284 =item C<opcode_t *invoke(void *next)>
286 Pythonic object constructor. SELF is a Complex Class object. Return a new
287 C<complex> object according to 2.1. Built-in Functions.
292 VTABLE opcode_t *invoke(void *next) {
293 const int argcP = REG_INT(interp, 3);
294 PMC * const res = pmc_new(INTERP, enum_class_Complex);
297 PMC * const arg = REG_PMC(interp, 5);
299 if (arg->vtable->base_type == enum_class_String)
300 VTABLE_set_string_native(INTERP, res, VTABLE_get_string(interp, arg));
302 SET_ATTR_re(INTERP, res, VTABLE_get_number(INTERP, arg));
304 else if (argcP == 2) {
305 SET_ATTR_re(INTERP, res, VTABLE_get_number(INTERP, REG_PMC(interp, 5)));
306 SET_ATTR_im(INTERP, res, VTABLE_get_number(INTERP, REG_PMC(interp, 6)));
309 REG_PMC(interp, 5) = res;
310 return (opcode_t *)next;
323 Initializes the complex number with the value 0+0i.
325 =item C<void init_pmc(PMC *initializer)>
327 Initializes the complex number with the specified initializer.
328 The initializer can be a string PMC or a numeric array with (real, imag)
330 =item C<PMC *clone()>
332 Creates an identical copy of the complex number.
339 SET_ATTR_re(INTERP, SELF, 0.0);
340 SET_ATTR_im(INTERP, SELF, 0.0);
343 VTABLE void init_pmc(PMC *initializer) {
344 const INTVAL arg_type = VTABLE_type(interp, initializer);
347 case enum_class_String:
348 SELF.set_string_native(VTABLE_get_string(interp, initializer));
350 case enum_class_FixedFloatArray:
351 case enum_class_ResizableFloatArray:
352 case enum_class_FixedIntegerArray:
353 case enum_class_ResizableIntegerArray:
354 if (VTABLE_get_integer(interp, initializer) == 2) {
355 FLOATVAL re = VTABLE_get_number_keyed_int(interp, initializer, 0);
356 FLOATVAL im = VTABLE_get_number_keyed_int(interp, initializer, 1);
357 SET_ATTR_re(INTERP, SELF, re);
358 SET_ATTR_im(INTERP, SELF, im);
361 /* else let it fall to default */
363 if (VTABLE_isa(interp, initializer, CONST_STRING(interp, "String"))) {
364 STRING * s = VTABLE_get_string(interp, initializer);
365 SELF.set_string_native(s);
368 Parrot_ex_throw_from_c_args(interp, NULL,
369 EXCEPTION_INVALID_OPERATION,
370 "Invalid Complex initializer");
375 VTABLE PMC *clone() {
376 PMC * const dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
379 GET_ATTR_re(INTERP, SELF, re);
380 GET_ATTR_im(INTERP, SELF, im);
381 SET_ATTR_re(INTERP, dest, re);
382 SET_ATTR_im(INTERP, dest, im);
389 =item C<INTVAL get_integer()>
391 Returns the modulus of the complex number as an integer.
393 =item C<FLOATVAL get_number()>
395 Returns the modulus of the complex number.
397 =item C<STRING *get_string()>
399 Returns the complex number as a string in the form C<a+bi>.
401 =item C<INTVAL get_bool()>
403 Returns true if the complex number is non-zero.
409 VTABLE INTVAL get_integer() {
410 const FLOATVAL f = SELF.get_number();
414 VTABLE FLOATVAL get_number() {
416 GET_ATTR_re(INTERP, SELF, re);
417 GET_ATTR_im(INTERP, SELF, im);
418 return sqrt(re * re + im * im);
421 VTABLE STRING *get_string() {
423 GET_ATTR_re(INTERP, SELF, re);
424 GET_ATTR_im(INTERP, SELF, im);
425 return Parrot_sprintf_c(INTERP, "%vg%+vgi", re, im);
428 VTABLE INTVAL get_bool() {
430 GET_ATTR_re(INTERP, SELF, re);
431 GET_ATTR_im(INTERP, SELF, im);
432 return !(FLOAT_IS_ZERO(re) && FLOAT_IS_ZERO(im));
437 =item C<INTVAL get_integer_keyed(PMC *key)>
439 =item C<INTVAL get_integer_keyed_str(STRING *key)>
441 =item C<FLOATVAL get_number_keyed(PMC *key)>
443 =item C<FLOATVAL get_number_keyed_str(STRING *key)>
445 =item C<PMC *get_pmc_keyed(PMC *key)>
447 =item C<PMC *get_pmc_keyed_str(STRING *key)>
449 Returns the requested number (real part for C<real> and imaginary for C<imag>).
455 VTABLE INTVAL get_integer_keyed(PMC *key) {
456 STRING * const s = VTABLE_get_string(INTERP, key);
457 return SELF.get_integer_keyed_str(s);
460 VTABLE INTVAL get_integer_keyed_str(STRING *key) {
461 const FLOATVAL f = SELF.get_number_keyed_str(key);
465 VTABLE FLOATVAL get_number_keyed(PMC *key) {
466 STRING * const s = VTABLE_get_string(INTERP, key);
467 return SELF.get_number_keyed_str(s);
470 VTABLE FLOATVAL get_number_keyed_str(STRING *key) {
472 if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "real"))) {
473 GET_ATTR_re(INTERP, SELF, value);
475 else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "imag"))) {
476 GET_ATTR_im(INTERP, SELF, value);
479 Parrot_ex_throw_from_c_args(interp, NULL,
480 EXCEPTION_INVALID_OPERATION, "Complex: key is neither 'real' or 'imag'");
484 VTABLE PMC *get_pmc_keyed(PMC *key) {
485 if (VTABLE_isa(interp, key, CONST_STRING(interp, "Integer"))) {
486 const INTVAL i = VTABLE_get_integer(interp, key);
487 return SELF.get_pmc_keyed_int(i);
490 STRING * const s = VTABLE_get_string(INTERP, key);
491 return SELF.get_pmc_keyed_str(s);
495 VTABLE PMC *get_pmc_keyed_str(STRING *key) {
496 PMC * const ret = pmc_new(INTERP, enum_class_Float);
497 const FLOATVAL val = SELF.get_number_keyed_str(key);
498 VTABLE_set_number_native(INTERP, ret, val);
504 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
506 Returns the requested number (real part for C<0> and imaginary for C<1>).
512 VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
513 PMC * const ret = pmc_new(INTERP, enum_class_Float);
514 const FLOATVAL val = SELF.get_number_keyed_int(key);
515 VTABLE_set_number_native(INTERP, ret, val);
521 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
523 Quick hack to emulate get_real() and get_imag():
525 key = 0 ... get real part
526 key = 1 ... get imag part
528 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL v)>
530 Set real or imag depending on key
536 VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
540 GET_ATTR_re(INTERP, SELF, f);
543 GET_ATTR_im(INTERP, SELF, f);
546 Parrot_ex_throw_from_c_args(interp, NULL,
547 EXCEPTION_INVALID_OPERATION, "Complex: key must be 0 or 1");
552 VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL v) {
555 SET_ATTR_re(INTERP, SELF, v);
558 SET_ATTR_im(INTERP, SELF, v);
561 Parrot_ex_throw_from_c_args(interp, NULL,
562 EXCEPTION_INVALID_OPERATION, "Complex: key must be 0 or 1");
567 =item C<void set_string_native(STRING *value)>
569 Parses the string C<value> into a complex number; raises an exception
572 =item C<void set_pmc(PMC *value)>
574 if C<value> is a Complex PMC then the complex number is set to its
575 value; otherwise C<value>'s string representation is parsed with
576 C<set_string_native()>.
578 =item C<void set_integer_native(INTVAL value)>
580 =item C<void set_number_native(FLOATVAL value)>
582 Sets the real part of the complex number to C<value> and the imaginary
589 VTABLE void set_string_native(STRING *value) {
591 complex_parse_string(INTERP, &re, &im, value);
592 SET_ATTR_re(INTERP, SELF, re);
593 SET_ATTR_im(INTERP, SELF, im);
596 VTABLE void set_pmc(PMC *value) {
597 if (VTABLE_isa(INTERP, value, CONST_STRING(INTERP, "Complex"))) {
599 GET_ATTR_re(INTERP, value, re);
600 GET_ATTR_im(INTERP, value, im);
601 SET_ATTR_re(INTERP, SELF, re);
602 SET_ATTR_im(INTERP, SELF, im);
605 VTABLE_set_string_native(INTERP, SELF, VTABLE_get_string(INTERP, value));
608 VTABLE void set_integer_native(INTVAL value) {
609 SELF.set_number_native((FLOATVAL)value);
612 VTABLE void set_number_native(FLOATVAL value) {
613 SET_ATTR_re(INTERP, SELF, value);
614 SET_ATTR_im(INTERP, SELF, 0.0);
619 =item C<void set_integer_keyed(PMC *key, INTVAL value)>
621 =item C<void set_integer_keyed_str(STRING *key, INTVAL value)>
623 =item C<void set_number_keyed(PMC *key, FLOATVAL value)>
625 =item C<void set_number_keyed_str(STRING *key, FLOATVAL value)>
627 =item C<void set_pmc_keyed(PMC *key, PMC *value)>
629 =item C<void set_pmc_keyed_str(STRING *key, PMC *value)>
631 Sets the requested number (real part for C<real> and imaginary for C<imag>)
638 VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
639 SELF.set_number_keyed(key, (FLOATVAL)value);
642 VTABLE void set_integer_keyed_str(STRING *key, INTVAL value) {
643 SELF.set_number_keyed_str(key, (FLOATVAL)value);
646 VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
647 if (VTABLE_isa(interp, key, CONST_STRING(interp, "Integer"))) {
648 const INTVAL i = VTABLE_get_integer(interp, key);
649 SELF.set_number_keyed_int(i, value);
652 STRING *s = VTABLE_get_string(INTERP, key);
653 SELF.set_number_keyed_str(s, value);
657 VTABLE void set_number_keyed_str(STRING *key, FLOATVAL value) {
658 if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "real"))) {
659 SET_ATTR_re(INTERP, SELF, value);
661 else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "imag"))) {
662 SET_ATTR_im(INTERP, SELF, value);
665 Parrot_ex_throw_from_c_args(interp, NULL,
666 EXCEPTION_INVALID_OPERATION, "Complex: key is neither 'real' or 'imag'");
669 VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
670 const FLOATVAL f = VTABLE_get_number(INTERP, value);
671 SELF.set_number_keyed(key, f);
674 VTABLE void set_pmc_keyed_str(STRING *key, PMC *value) {
675 const FLOATVAL f = VTABLE_get_number(INTERP, value);
676 SELF.set_number_keyed_str(key, f);
681 =item C<PMC *add(PMC *value, PMC *dest)>
683 =item C<PMC *add_int(INTVAL value, PMC *dest)>
685 =item C<PMC *add_float(FLOATVAL value, PMC *dest)>
687 Adds C<value> to the complex number, placing the result in C<dest>.
693 MULTI PMC *add(Complex value, PMC *dest) {
694 FLOATVAL self_re, self_im, val_re, val_im;
695 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
697 GET_ATTR_re(INTERP, SELF, self_re);
698 GET_ATTR_im(INTERP, SELF, self_im);
700 GET_ATTR_re(INTERP, value, val_re);
701 GET_ATTR_im(INTERP, value, val_im);
703 SET_ATTR_re(INTERP, dest, self_re + val_re);
704 SET_ATTR_im(INTERP, dest, self_im + val_im);
709 MULTI PMC *add(DEFAULT value, PMC *dest) {
711 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
713 GET_ATTR_re(INTERP, SELF, re);
714 GET_ATTR_im(INTERP, SELF, im);
715 SET_ATTR_re(INTERP, dest, re + VTABLE_get_number(INTERP, value));
716 SET_ATTR_im(INTERP, dest, im);
721 VTABLE PMC *add_int(INTVAL value, PMC *dest) {
722 return SELF.add_float((FLOATVAL)value, dest);
725 VTABLE PMC *add_float(FLOATVAL value, PMC *dest) {
727 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
729 GET_ATTR_re(INTERP, SELF, re);
730 GET_ATTR_im(INTERP, SELF, im);
731 SET_ATTR_re(INTERP, dest, re + value);
732 SET_ATTR_im(INTERP, dest, im);
737 MULTI void i_add(Complex value) {
738 FLOATVAL self_re, self_im, val_re, val_im;
740 GET_ATTR_re(INTERP, SELF, self_re);
741 GET_ATTR_im(INTERP, SELF, self_im);
743 GET_ATTR_re(INTERP, value, val_re);
744 GET_ATTR_im(INTERP, value, val_im);
746 SET_ATTR_re(INTERP, SELF, self_re + val_re);
747 SET_ATTR_im(INTERP, SELF, self_im + val_im);
750 MULTI void i_add(DEFAULT value) {
753 GET_ATTR_re(INTERP, SELF, re);
754 SET_ATTR_re(INTERP, SELF, re + VTABLE_get_number(INTERP, value));
757 VTABLE void i_add_int(INTVAL value) {
758 SELF.i_add_float((FLOATVAL)value);
761 VTABLE void i_add_float(FLOATVAL value) {
764 GET_ATTR_re(INTERP, SELF, re);
765 SET_ATTR_re(INTERP, SELF, re + value);
770 =item C<PMC *subtract(PMC *value, PMC *dest)>
772 =item C<PMC *subtract_int(INTVAL value, PMC *dest)>
774 =item C<PMC *subtract_float(FLOATVAL value, PMC *dest)>
776 Subtracts C<value> from the complex number, placing the result in C<dest>.
782 MULTI PMC *subtract(Complex value, PMC *dest) {
783 FLOATVAL self_re, self_im, val_re, val_im;
784 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
786 GET_ATTR_re(INTERP, SELF, self_re);
787 GET_ATTR_im(INTERP, SELF, self_im);
789 GET_ATTR_re(INTERP, value, val_re);
790 GET_ATTR_im(INTERP, value, val_im);
792 SET_ATTR_re(INTERP, dest, self_re - val_re);
793 SET_ATTR_im(INTERP, dest, self_im - val_im);
798 MULTI PMC *subtract(DEFAULT value, PMC *dest) {
800 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
802 GET_ATTR_re(INTERP, SELF, re);
803 GET_ATTR_im(INTERP, SELF, im);
804 SET_ATTR_re(INTERP, dest, re - VTABLE_get_number(INTERP, value));
805 SET_ATTR_im(INTERP, dest, im);
810 VTABLE PMC *subtract_int(INTVAL value, PMC *dest) {
811 return SELF.subtract_float((FLOATVAL)value, dest);
814 VTABLE PMC *subtract_float(FLOATVAL value, PMC *dest) {
816 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
818 GET_ATTR_re(INTERP, SELF, re);
819 GET_ATTR_im(INTERP, SELF, im);
820 SET_ATTR_re(INTERP, dest, re - value);
821 SET_ATTR_im(INTERP, dest, im);
826 MULTI void i_subtract(Complex value) {
827 FLOATVAL self_re, self_im, val_re, val_im;
829 GET_ATTR_re(INTERP, SELF, self_re);
830 GET_ATTR_im(INTERP, SELF, self_im);
832 GET_ATTR_re(INTERP, value, val_re);
833 GET_ATTR_im(INTERP, value, val_im);
835 SET_ATTR_re(INTERP, SELF, self_re - val_re);
836 SET_ATTR_im(INTERP, SELF, self_im - val_im);
839 MULTI void i_subtract(DEFAULT value) {
842 GET_ATTR_re(INTERP, SELF, re);
843 SET_ATTR_re(INTERP, SELF, re - VTABLE_get_number(INTERP, value));
846 VTABLE void i_subtract_int(INTVAL value) {
847 SELF.i_subtract_float((FLOATVAL) value);
850 VTABLE void i_subtract_float(FLOATVAL value) {
853 GET_ATTR_re(INTERP, SELF, re);
854 SET_ATTR_re(INTERP, SELF, re - value);
858 =item C<PMC *multiply(PMC *value, PMC *dest)>
860 =item C<PMC *multiply_int(INTVAL value, PMC *dest)>
862 =item C<PMC *multiply_float(FLOATVAL value, PMC *dest)>
864 Multiplies the complex number with C<value>, placing the result in C<dest>.
866 =item C<void i_multiply(PMC *value)>
868 =item C<void i_multiply_int(INTVAL value)>
870 =item C<void i_multiply_float(FLOATVAL value)>
872 Multiplies the complex number SELF inplace with C<value>.
880 (a+ib)(c+id)=(ac-bd)+i((a+b)(c+d)-ac-bd).
881 (a+bi)(c+di)=(ac-bd)+i(ad+bc)
884 MULTI PMC *multiply(Complex value, PMC *dest) {
887 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
889 GET_ATTR_re(INTERP, SELF, a);
890 GET_ATTR_im(INTERP, SELF, b);
891 GET_ATTR_re(INTERP, value, c);
892 GET_ATTR_im(INTERP, value, d);
893 SET_ATTR_re(INTERP, dest, a * c - b * d);
894 SET_ATTR_im(INTERP, dest, a * d + b * c);
899 MULTI PMC *multiply(DEFAULT value, PMC *dest) {
901 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
903 GET_ATTR_re(INTERP, SELF, re);
904 GET_ATTR_im(INTERP, SELF, im);
905 SET_ATTR_re(INTERP, dest, re * VTABLE_get_number(INTERP, value));
906 SET_ATTR_im(INTERP, dest, im * VTABLE_get_number(INTERP, value));
911 VTABLE PMC *multiply_int(INTVAL value, PMC *dest) {
912 return SELF.multiply_float((FLOATVAL) value, dest);
915 VTABLE PMC *multiply_float(FLOATVAL value, PMC *dest) {
917 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
919 GET_ATTR_re(INTERP, SELF, re);
920 GET_ATTR_im(INTERP, SELF, im);
921 SET_ATTR_re(INTERP, dest, re * value);
922 SET_ATTR_im(INTERP, dest, im * value);
927 MULTI void i_multiply(Complex value) {
930 GET_ATTR_re(INTERP, SELF, a);
931 GET_ATTR_im(INTERP, SELF, b);
932 GET_ATTR_re(INTERP, value, c);
933 GET_ATTR_im(INTERP, value, d);
934 SET_ATTR_re(INTERP, SELF, a * c - b * d);
935 SET_ATTR_im(INTERP, SELF, a * d + b * c);
938 MULTI void i_multiply(DEFAULT value) {
941 GET_ATTR_re(INTERP, SELF, re);
942 GET_ATTR_im(INTERP, SELF, im);
943 SET_ATTR_re(INTERP, SELF, re * VTABLE_get_number(INTERP, value));
944 SET_ATTR_im(INTERP, SELF, im * VTABLE_get_number(INTERP, value));
947 VTABLE void i_multiply_int(INTVAL value) {
950 GET_ATTR_re(INTERP, SELF, re);
951 GET_ATTR_im(INTERP, SELF, im);
952 SET_ATTR_re(INTERP, SELF, re * value);
953 SET_ATTR_im(INTERP, SELF, im * value);
956 VTABLE void i_multiply_float(FLOATVAL value) {
959 GET_ATTR_re(INTERP, SELF, re);
960 GET_ATTR_im(INTERP, SELF, im);
961 SET_ATTR_re(INTERP, SELF, re * value);
962 SET_ATTR_im(INTERP, SELF, im * value);
967 =item C<PMC *divide(PMC *value, PMC *dest)>
969 =item C<PMC *divide_int(INTVAL value, PMC *dest)>
971 =item C<PMC *divide_float(FLOATVAL value, PMC *dest)>
973 Divide the complex number by C<value>, placing the result in C<dest>.
975 =item C<void i_divide(PMC *value, PMC *dest)>
977 =item C<void i_divide_int(INTVAL value, PMC *dest)>
979 =item C<void i_divide_float(FLOATVAL value, PMC *dest)>
981 Divide the complex number C<SELF> by C<value> inplace.
983 Throws divide by zero exception if divisor is zero.
987 TODO: for better fp precision
988 http://docs.sun.com/source/806-3568/ncg_goldberg.html
990 (a + b(d/c)) / (c + d(d/c)) + i(b - a(d/c)) / (c + d(d/c)) if |d|<|c|
991 (b + a(c/d)) / (d + c(c/d)) + i(-a + b(c/d)) / (d + c(c/d)) if |d|>=|c|
995 MULTI PMC *divide(Complex value, PMC *dest) {
996 FLOATVAL mod, re, im;
997 FLOATVAL self_re, self_im, val_re, val_im;
999 complex_check_divide_zero(INTERP, value);
1000 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1002 GET_ATTR_re(INTERP, SELF, self_re);
1003 GET_ATTR_im(INTERP, SELF, self_im);
1004 GET_ATTR_re(INTERP, value, val_re);
1005 GET_ATTR_im(INTERP, value, val_im);
1007 /* a little speed optimisation: cache an intermediate number;
1008 I'm not sure the compiler does this */
1010 if (self_im == 0.0 && val_im == 0.0) {
1011 re = self_re / val_re;
1015 mod = (val_re * val_re + val_im * val_im);
1016 re = (self_re * val_re + self_im * val_im) / mod;
1017 im = (self_im * val_re - self_re * val_im) / mod;
1020 SET_ATTR_re(INTERP, dest, re);
1021 SET_ATTR_im(INTERP, dest, im);
1026 MULTI PMC *divide(DEFAULT value, PMC *dest) {
1028 const FLOATVAL d = VTABLE_get_number(INTERP, value);
1029 float_check_divide_zero(INTERP, d);
1030 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1032 GET_ATTR_re(INTERP, SELF, re);
1033 GET_ATTR_im(INTERP, SELF, im);
1035 SET_ATTR_re(INTERP, dest, re / d);
1036 SET_ATTR_im(INTERP, dest, im / d);
1041 VTABLE PMC *divide_int(INTVAL value, PMC *dest) {
1043 int_check_divide_zero(INTERP, value);
1044 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1046 GET_ATTR_re(INTERP, SELF, re);
1047 GET_ATTR_im(INTERP, SELF, im);
1049 SET_ATTR_re(INTERP, dest, re / value);
1050 SET_ATTR_im(INTERP, dest, im / value);
1055 VTABLE PMC *divide_float(FLOATVAL value, PMC *dest) {
1057 float_check_divide_zero(INTERP, value);
1058 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1060 GET_ATTR_re(INTERP, SELF, re);
1061 GET_ATTR_im(INTERP, SELF, im);
1063 SET_ATTR_re(INTERP, dest, re / value);
1064 SET_ATTR_im(INTERP, dest, im / value);
1069 MULTI void i_divide(Complex value) {
1071 FLOATVAL self_re, self_im, val_re, val_im;
1073 complex_check_divide_zero(INTERP, value);
1075 GET_ATTR_re(INTERP, SELF, self_re);
1076 GET_ATTR_im(INTERP, SELF, self_im);
1077 GET_ATTR_re(INTERP, value, val_re);
1078 GET_ATTR_im(INTERP, value, val_im);
1080 if (self_im == 0.0 && val_im == 0.0) {
1081 re = self_re / val_re;
1085 /* a little speed optimisation: cache an intermediate number;
1086 I'm not sure the compiler does this */
1087 const FLOATVAL mod = (val_re * val_re + val_im * val_im);
1088 re = (self_re * val_re + self_im * val_im) / mod;
1089 im = (self_im * val_re - self_re * val_im) / mod;
1092 SET_ATTR_re(INTERP, SELF, re);
1093 SET_ATTR_im(INTERP, SELF, im);
1097 MULTI void i_divide(DEFAULT value) {
1099 const FLOATVAL d = VTABLE_get_number(INTERP, value);
1100 float_check_divide_zero(INTERP, d);
1102 GET_ATTR_re(INTERP, SELF, re);
1103 GET_ATTR_im(INTERP, SELF, im);
1105 SET_ATTR_re(INTERP, SELF, re / d);
1106 SET_ATTR_im(INTERP, SELF, im / d);
1109 VTABLE void i_divide_int(INTVAL value) {
1111 int_check_divide_zero(INTERP, value);
1113 GET_ATTR_re(INTERP, SELF, re);
1114 GET_ATTR_im(INTERP, SELF, im);
1116 SET_ATTR_re(INTERP, SELF, re / value);
1117 SET_ATTR_im(INTERP, SELF, im / value);
1120 VTABLE void i_divide_float(FLOATVAL value) {
1122 float_check_divide_zero(INTERP, value);
1124 GET_ATTR_re(INTERP, SELF, re);
1125 GET_ATTR_im(INTERP, SELF, im);
1127 SET_ATTR_re(INTERP, SELF, re / value);
1128 SET_ATTR_im(INTERP, SELF, im / value);
1133 =item C<PMC *neg(PMC *dest)>
1137 Set C<dest> to the negated value of C<SELF>.
1143 VTABLE PMC *neg(PMC *dest) {
1145 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1147 GET_ATTR_re(INTERP, SELF, re);
1148 GET_ATTR_im(INTERP, SELF, im);
1150 SET_ATTR_re(INTERP, dest, -re);
1151 SET_ATTR_im(INTERP, dest, -im);
1156 VTABLE void i_neg() {
1158 GET_ATTR_re(INTERP, SELF, re);
1159 GET_ATTR_im(INTERP, SELF, im);
1160 SET_ATTR_re(INTERP, SELF, -re);
1161 SET_ATTR_im(INTERP, SELF, -im);
1166 =item C<INTVAL is_equal(PMC *value)>
1168 Compares the complex number with C<value> and returns true if they are equal.
1174 MULTI INTVAL is_equal(Complex value) {
1175 FLOATVAL self_re, self_im, val_re, val_im;
1176 GET_ATTR_re(INTERP, SELF, self_re);
1177 GET_ATTR_im(INTERP, SELF, self_im);
1178 GET_ATTR_re(INTERP, value, val_re);
1179 GET_ATTR_im(INTERP, value, val_im);
1180 return (INTVAL)(self_re == val_re && self_im == val_im);
1183 MULTI INTVAL is_equal(DEFAULT value) {
1185 GET_ATTR_re(INTERP, SELF, re);
1186 GET_ATTR_im(INTERP, SELF, im);
1191 return (re == VTABLE_get_number(INTERP, value));
1196 =item C<PMC *absolute(PMC *dest)>
1198 =item C<void i_absolute()>
1200 Sets C<dest> to the absolute value of SELF that is the distance from (0.0).
1208 TODO for better precision: hinted by vaxman according to "Numerical Recipes
1209 in Fortran 77", 2nd edition, Press, Vetterling, Teukolsky, Flannery,
1210 Cambridge University Press, 2001, pp. 171ff:
1213 |a+ib|=|a|*sqrt(1+(b/a)**2), if |a|>=|b|,
1214 |b|*sqrt(1+(a/b)**2) else.
1218 VTABLE PMC *absolute(PMC *dest) {
1220 GET_ATTR_re(INTERP, SELF, re);
1221 GET_ATTR_im(INTERP, SELF, im);
1222 d = sqrt(re*re + im*im);
1224 dest = pmc_new(INTERP,
1225 Parrot_get_ctx_HLL_type(INTERP, enum_class_Float));
1227 VTABLE_set_number_native(INTERP, dest, d);
1231 VTABLE void i_absolute() {
1233 GET_ATTR_re(INTERP, SELF, re);
1234 GET_ATTR_im(INTERP, SELF, im);
1235 d = sqrt(re*re + im*im);
1236 pmc_reuse(INTERP, SELF, enum_class_Float, 0);
1237 VTABLE_set_number_native(INTERP, SELF, d);
1242 =item C<METHOD ln()>
1244 Returns the natural logarithm of SELF as a PMC.
1248 ln z = ln |z| + i arg(z)
1249 |x + iy| = sqrt(x^2 + y^2)
1250 arg(x + iy) = atan2(y, x)
1257 ln(+-i) = +- (pi i)/2
1262 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1263 FLOATVAL re, im, result_re, result_im;
1264 GET_ATTR_re(INTERP, SELF, re);
1265 GET_ATTR_im(INTERP, SELF, im);
1267 /* This is necessary for atan2 to behave */
1271 result_re = log(sqrt(re*re + im*im));
1272 if (re == 0.0 && im == 0.0) /* atan2(0, 0) not portable */
1275 result_im = atan2(im, re);
1277 SET_ATTR_re(INTERP, d, result_re);
1278 SET_ATTR_im(INTERP, d, result_im);
1285 =item C<METHOD exp()>
1287 Returns e ^ SELF as a PMC.
1291 exp(a + bi) = exp(a) * (cos(b) + i * sin(b))
1296 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1298 GET_ATTR_re(INTERP, SELF, re);
1299 GET_ATTR_im(INTERP, SELF, im);
1303 SET_ATTR_re(INTERP, d, f * cos(im));
1305 /* If only sin(pi) worked. */
1306 if (im == 4.0 * atan(1.0)) {
1307 SET_ATTR_im(INTERP, d, 0.0);
1310 SET_ATTR_im(INTERP, d, f * sin(im));
1318 =item C<METHOD PMC *sin()>
1320 =item C<METHOD PMC *cos()>
1322 =item C<METHOD PMC *tan()>
1324 =item C<METHOD PMC *csc()>
1326 =item C<METHOD PMC *sec()>
1328 =item C<METHOD PMC *cot()>
1330 Returns C<FUNC>(SELF).
1334 => sin(a + bi) = sin(a)cosh(b)+i*cos(a)sinh(b)
1335 sin(z) = ((e ^ zi) - (e ^ -zi)) / (2i)
1336 => cos(a + bi) = cos(a) * cosh(b) - i * sin(a) * sinh(b)
1337 cos(z) = ((e ^ zi) + (e ^ -zi)) / 2
1344 sinh(a + bi) = sinh(a) * cos(b) + i * cosh(a) * sin(b)
1345 cosh(a + bi) = cosh(a) * cos(b) + i * sinh(a) * sin(b)
1350 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1351 FLOATVAL re, im, result_re, result_im;
1352 GET_ATTR_re(INTERP, SELF, re);
1353 GET_ATTR_im(INTERP, SELF, im);
1355 if (FLOAT_IS_ZERO(im)) {
1356 result_re = sin(re);
1359 else if (FLOAT_IS_ZERO(re)) {
1361 result_im = sinh(im);
1364 result_re = sin(re) * cosh(im);
1369 result_im = cos(re) * sinh(im);
1373 SET_ATTR_re(INTERP, d, result_re);
1374 SET_ATTR_im(INTERP, d, result_im);
1380 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1381 FLOATVAL re, im, result_re, result_im;
1382 GET_ATTR_re(INTERP, SELF, re);
1383 GET_ATTR_im(INTERP, SELF, im);
1385 if (FLOAT_IS_ZERO(re)) {
1386 result_re = cosh(im);
1389 else if (FLOAT_IS_ZERO(im)) {
1390 result_re = cos(re);
1394 result_re = cos(re) * cosh(im);
1395 result_im = -1.0 * sin(re) * sinh(im);
1398 SET_ATTR_re(INTERP, d, result_re);
1399 SET_ATTR_im(INTERP, d, result_im);
1405 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1406 PMC * const e = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1408 (PMC *d) = PCCINVOKE(INTERP, SELF, "sin");
1409 (PMC *e) = PCCINVOKE(INTERP, SELF, "cos");
1411 Parrot_Complex_multi_i_divide_Complex(INTERP, d, e);
1417 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1418 PMC * const e = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1419 (PMC *d) = PCCINVOKE(INTERP, SELF, "cos");
1420 (PMC *e) = PCCINVOKE(INTERP, SELF, "sin");
1422 Parrot_Complex_multi_i_divide_Complex(INTERP, d, e);
1428 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1429 PMC * const e = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1430 SET_ATTR_re(INTERP, d, 1.0);
1431 SET_ATTR_im(INTERP, d, 0.0);
1432 (PMC *e) = PCCINVOKE(INTERP, SELF, "cos");
1434 Parrot_Complex_multi_i_divide_Complex(INTERP, d, e);
1440 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1441 PMC * const e = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1443 SET_ATTR_re(INTERP, d, 1.0);
1444 SET_ATTR_im(INTERP, d, 0.0);
1446 (PMC *e) = PCCINVOKE(INTERP, SELF, "sin");
1448 Parrot_Complex_multi_i_divide_Complex(INTERP, d, e);
1455 =item C<METHOD PMC *asin()>
1457 =item C<METHOD PMC *acos()>
1459 =item C<METHOD PMC *atan()>
1461 =item C<METHOD PMC *acsc()>
1463 =item C<METHOD PMC *asec()>
1465 =item C<METHOD PMC *acot()>
1467 Returns the inverse function of SELF.
1471 => arcsin z = -i ln(iz + sqrt(1-z*z))
1472 => arccos z = pi/2 + i * ln(iz + sqrt(1 - z*z))
1473 arccos z = -i ln(z + sqrt(z*z-1))
1474 => arctan z = i/2 ln((i+z) / (i-z))
1475 arctan z = 1/2 i (ln(1-iz) - ln(1 + iz))
1477 => acot(z) = atan(1 / z)
1478 acot(z) = i/2 (ln((z - i) / z) - ln((z + i) / z))
1479 => asec(z) = acos(1 / z)
1480 asec(z) = 1/2 pi + i ln(sqrt(1 - 1/zz) + i/z)
1481 => acsc(z) = asin(1 / z)
1482 acsc(z) = -i ln(sqrt(1 - 1/zz + i/z))
1487 FLOATVAL d_re, d_im, e_re, e_im, self_re, self_im;
1488 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1489 PMC * e = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1490 GET_ATTR_re(INTERP, SELF, self_re);
1491 GET_ATTR_im(INTERP, SELF, self_im);
1493 e = Parrot_Complex_multi_multiply_Complex_PMC(INTERP, SELF, SELF, e);
1494 GET_ATTR_re(INTERP, e, e_re);
1495 GET_ATTR_im(INTERP, e, e_im);
1496 SET_ATTR_re(INTERP, e, 1.0 - e_re);
1497 SET_ATTR_im(INTERP, e, -e_im);
1499 (PMC *d) = PCCINVOKE(INTERP, e, "sqrt");
1500 GET_ATTR_re(INTERP, d, d_re);
1501 GET_ATTR_im(INTERP, d, d_im);
1502 SET_ATTR_re(INTERP, d, d_re - self_im);
1503 SET_ATTR_im(INTERP, d, d_im + self_re);
1505 (PMC *d) = PCCINVOKE(INTERP, d, "ln");
1506 GET_ATTR_re(INTERP, d, d_re);
1507 GET_ATTR_im(INTERP, d, d_im);
1508 SET_ATTR_re(INTERP, e, d_im);
1509 SET_ATTR_im(INTERP, e, d_re ? -d_re : 0.0);
1515 FLOATVAL d_re, d_im, e_re, e_im, self_re, self_im;
1516 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1517 PMC * e = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1518 GET_ATTR_re(INTERP, SELF, self_re);
1519 GET_ATTR_im(INTERP, SELF, self_im);
1521 e = Parrot_Complex_multi_multiply_Complex_PMC(INTERP, SELF, SELF, e);
1522 GET_ATTR_re(INTERP, e, e_re);
1523 GET_ATTR_im(INTERP, e, e_im);
1524 SET_ATTR_re(INTERP, e, 1.0 - e_re);
1525 SET_ATTR_im(INTERP, e, -e_im);
1527 (PMC *d) = PCCINVOKE(INTERP, e, "sqrt");
1528 GET_ATTR_re(INTERP, d, d_re);
1529 GET_ATTR_im(INTERP, d, d_im);
1530 SET_ATTR_re(INTERP, d, d_re + self_im);
1531 SET_ATTR_im(INTERP, d, d_im - self_re);
1533 (PMC *e) = PCCINVOKE(INTERP, d, "ln");
1534 GET_ATTR_re(INTERP, e, e_re);
1535 GET_ATTR_im(INTERP, e, e_im);
1536 SET_ATTR_re(INTERP, d, e_im + 2.0 * atan(1.0));
1537 SET_ATTR_im(INTERP, d, e_re ? -e_re : 0.0);
1543 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1544 PMC * const e = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1545 FLOATVAL re, im, d_re, d_im;
1546 GET_ATTR_re(INTERP, SELF, re);
1547 GET_ATTR_im(INTERP, SELF, im);
1549 SET_ATTR_re(INTERP, d, re);
1550 SET_ATTR_im(INTERP, d, 1 + im);
1551 SET_ATTR_re(INTERP, e, -re);
1552 SET_ATTR_im(INTERP, e, 1 - im);
1554 Parrot_Complex_multi_i_divide_Complex(INTERP, d, e);
1556 (PMC *d) = PCCINVOKE(INTERP, d, "ln");
1557 GET_ATTR_re(INTERP, d, d_re);
1558 GET_ATTR_im(INTERP, d, d_im);
1560 SET_ATTR_re(INTERP, e, (d_im ? d_im : -0.0) / -2.0);
1561 SET_ATTR_im(INTERP, e, d_re / 2.0);
1567 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1570 GET_ATTR_re(INTERP, SELF, re);
1571 GET_ATTR_im(INTERP, SELF, im);
1573 SET_ATTR_re(INTERP, d, re / (re * re + im * im));
1574 SET_ATTR_im(INTERP, d, -im / (re * re + im * im));
1576 (PMC *e) = PCCINVOKE(INTERP, d, "atan");
1581 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1584 GET_ATTR_re(INTERP, SELF, re);
1585 GET_ATTR_im(INTERP, SELF, im);
1587 SET_ATTR_re(INTERP, d, re / (re * re + im * im));
1588 SET_ATTR_im(INTERP, d, -im / (re * re + im * im));
1590 (PMC *e) = PCCINVOKE(INTERP, d, "asin");
1595 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1598 GET_ATTR_re(INTERP, SELF, re);
1599 GET_ATTR_im(INTERP, SELF, im);
1601 SET_ATTR_re(INTERP, d, re / (re * re + im * im));
1602 SET_ATTR_im(INTERP, d, -im / (re * re + im * im));
1604 (PMC *e) = PCCINVOKE(INTERP, d, "acos");
1610 =item C<METHOD PMC *sinh()>
1612 Returns the arctangent of SELF.
1614 =item C<METHOD PMC *cosh()>
1616 Returns the arcsine of SELF.
1618 =item C<METHOD PMC *tanh()>
1620 Returns the arccosine of SELF.
1624 tanh(z) = sinh(z) / cosh(z)
1629 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1631 GET_ATTR_re(INTERP, SELF, re);
1632 GET_ATTR_im(INTERP, SELF, im);
1634 SET_ATTR_re(INTERP, d, sinh(re) * cos(im));
1635 SET_ATTR_im(INTERP, d, im ? cosh(re) * sin(im) : 0.0);
1641 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1643 GET_ATTR_re(INTERP, SELF, re);
1644 GET_ATTR_im(INTERP, SELF, im);
1646 SET_ATTR_re(INTERP, d, cosh(re) * cos(im));
1647 if (re == 0.0 || im == 0.0) {
1648 SET_ATTR_im(INTERP, d, 0.0);
1651 SET_ATTR_im(INTERP, d, sinh(re) * sin(im));
1658 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1659 PMC * const e = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1661 (PMC *d) = PCCINVOKE(INTERP, SELF, "sinh");
1662 (PMC *e) = PCCINVOKE(INTERP, SELF, "cosh");
1664 Parrot_Complex_multi_i_divide_Complex(INTERP, d, e);
1671 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1673 (PMC *d) = PCCINVOKE(INTERP, SELF, "tanh");
1674 GET_ATTR_re(INTERP, d, re);
1675 GET_ATTR_im(INTERP, d, im);
1677 SET_ATTR_re(INTERP, d, re ? re / (re * re + im * im) : 0.0);
1678 SET_ATTR_im(INTERP, d, im ? -im / (re * re + im * im) : 0.0);
1685 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1687 (PMC *d) = PCCINVOKE(INTERP, SELF, "sinh");
1688 GET_ATTR_re(INTERP, d, re);
1689 GET_ATTR_im(INTERP, d, im);
1691 SET_ATTR_re(INTERP, d, re ? re / (re * re + im * im) : 0.0);
1692 SET_ATTR_im(INTERP, d, im ? -im / (re * re + im * im) : 0.0);
1699 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1701 (PMC *d) = PCCINVOKE(INTERP, SELF, "cosh");
1702 GET_ATTR_re(INTERP, d, re);
1703 GET_ATTR_im(INTERP, d, im);
1705 SET_ATTR_re(INTERP, d, re ? re / (re * re + im * im) : 0.0);
1706 SET_ATTR_im(INTERP, d, im ? -im / (re * re + im * im) : 0.0);
1713 =item C<METHOD PMC *asinh()>
1715 =item C<METHOD PMC *acosh()>
1717 =item C<METHOD PMC *atanh()>
1719 =item C<METHOD PMC *acsch()>
1721 =item C<METHOD PMC *asech()>
1723 =item C<METHOD PMC *acoth()>
1725 The inverse hyperbolic functions. Currently all broken, but for
1726 C<func(a+bi) = c+di>, C<|c|> and C<|d|> will be correct, confusingly enough.
1730 asinh z = -ln(sqrt(1+zz) - z)
1731 asinh z = ln(sqrt(zz + 1) + z)
1741 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1742 PMC * const e = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1744 GET_ATTR_re(INTERP, SELF, re);
1745 GET_ATTR_im(INTERP, SELF, im);
1746 SET_ATTR_re(INTERP, d, im);
1747 SET_ATTR_im(INTERP, d, -re);
1749 (PMC *d) = PCCINVOKE(INTERP, d, "asin");
1750 GET_ATTR_re(INTERP, d, re);
1751 GET_ATTR_im(INTERP, d, im);
1752 SET_ATTR_re(INTERP, e, -im);
1753 SET_ATTR_im(INTERP, e, re);
1760 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1761 PMC * const e = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1763 (PMC *d) = PCCINVOKE(INTERP, SELF, "acos");
1764 GET_ATTR_re(INTERP, d, re);
1765 GET_ATTR_im(INTERP, d, im);
1766 SET_ATTR_re(INTERP, e, -im);
1767 SET_ATTR_im(INTERP, e, re);
1774 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1775 PMC * const e = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1777 GET_ATTR_re(INTERP, SELF, re);
1778 GET_ATTR_im(INTERP, SELF, im);
1779 SET_ATTR_re(INTERP, d, im);
1780 SET_ATTR_im(INTERP, d, -re);
1782 (PMC *d) = PCCINVOKE(INTERP, d, "atan");
1783 GET_ATTR_re(INTERP, d, re);
1784 GET_ATTR_im(INTERP, d, im);
1785 SET_ATTR_re(INTERP, e, -im);
1786 SET_ATTR_im(INTERP, e, re);
1792 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1795 GET_ATTR_re(INTERP, SELF, re);
1796 GET_ATTR_im(INTERP, SELF, im);
1798 SET_ATTR_re(INTERP, d, re / (re * re + im * im));
1799 SET_ATTR_im(INTERP, d, -im / (re * re + im * im));
1801 (PMC *e) = PCCINVOKE(INTERP, d, "atanh");
1806 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1809 GET_ATTR_re(INTERP, SELF, re);
1810 GET_ATTR_im(INTERP, SELF, im);
1812 SET_ATTR_re(INTERP, d, re / (re * re + im * im));
1813 SET_ATTR_im(INTERP, d, -im / (re * re + im * im));
1815 (PMC *e) = PCCINVOKE(INTERP, d, "asinh");
1820 PMC * const d = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1823 GET_ATTR_re(INTERP, SELF, re);
1824 GET_ATTR_im(INTERP, SELF, im);
1826 SET_ATTR_re(INTERP, d, re / (re * re + im * im));
1827 SET_ATTR_im(INTERP, d, -im / (re * re + im * im));
1829 (PMC *e) = PCCINVOKE(INTERP, d, "acosh");
1835 =item C<PMC *pow(PMC *value, PMC *dest)>
1837 Return SELF to the C<value>th power and return result in C<dest>.
1839 =item C<METHOD PMC *sqrt()>
1841 Return the square root of SELF.
1845 TODO: mmd in other pmc's to allow .Integer ^ .Complex, etc.
1846 and i_pow, and pow_(float|int), etc
1848 x ^ y = exp(y * ln x))
1852 MULTI PMC *pow(Complex value, PMC *dest) {
1853 PMC *l = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1856 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1859 Parrot_PCCINVOKE(interp, SELF, CONST_STRING(interp, "ln"),
1862 l = Parrot_Complex_multi_multiply_Complex_PMC(INTERP,
1865 Parrot_PCCINVOKE(interp, l, CONST_STRING(interp, "exp"),
1871 MULTI PMC *pow(DEFAULT value, PMC *dest) {
1872 PMC *l = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1875 dest = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1877 Parrot_PCCINVOKE(interp, SELF, CONST_STRING(interp, "ln"),
1879 l = Parrot_Complex_multi_multiply_DEFAULT_PMC(INTERP, log, value, l);
1880 Parrot_PCCINVOKE(interp, l, CONST_STRING(interp, "exp"),
1887 PMC * const result = pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1888 const FLOATVAL absval = SELF.get_number();
1889 FLOATVAL sx, sy, rx, ry;
1890 GET_ATTR_re(INTERP, SELF, sx);
1891 GET_ATTR_im(INTERP, SELF, sy);
1893 rx = sqrt((absval + sx) / 2);
1894 ry = sqrt((absval - sx) / 2);
1897 SET_ATTR_re(INTERP, result, rx);
1898 SET_ATTR_im(INTERP, result, ry);
1899 RETURN(PMC *result);
1914 * c-file-style: "parrot"
1916 * vim: expandtab shiftwidth=4: