2 Copyright (C) 2004-2010, 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.
16 Equations used are sometimes listed. At times, multiple equations are given,
17 but those starting with => are the ones used
25 /* HEADERIZER HFILE: none */
26 /* HEADERIZER BEGIN: static */
27 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
29 static void complex_check_divide_zero(PARROT_INTERP, ARGIN(PMC *value))
30 __attribute__nonnull__(1)
31 __attribute__nonnull__(2);
33 static void complex_parse_string(PARROT_INTERP,
37 __attribute__nonnull__(1)
38 __attribute__nonnull__(2)
39 __attribute__nonnull__(3)
40 __attribute__nonnull__(4)
44 static void float_check_divide_zero(PARROT_INTERP, FLOATVAL value)
45 __attribute__nonnull__(1);
47 static void int_check_divide_zero(PARROT_INTERP, INTVAL value)
48 __attribute__nonnull__(1);
50 #define ASSERT_ARGS_complex_check_divide_zero __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
51 PARROT_ASSERT_ARG(interp) \
52 , PARROT_ASSERT_ARG(value))
53 #define ASSERT_ARGS_complex_parse_string __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
54 PARROT_ASSERT_ARG(interp) \
55 , PARROT_ASSERT_ARG(re) \
56 , PARROT_ASSERT_ARG(im) \
57 , PARROT_ASSERT_ARG(value))
58 #define ASSERT_ARGS_float_check_divide_zero __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
59 PARROT_ASSERT_ARG(interp))
60 #define ASSERT_ARGS_int_check_divide_zero __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
61 PARROT_ASSERT_ARG(interp))
62 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
63 /* HEADERIZER END: static */
67 =item C<static void complex_parse_string(PARROT_INTERP, FLOATVAL *re, FLOATVAL
70 Parses the string in C<value> to produce a complex number, represented
71 by the real (C<*re>) and imaginary (C<*im>) parts. Raises an exception
72 if it cannot understand the string. The string should be of the form
73 C<a+bi> with optional spaces around C<+> and before C<i>. You can also
74 use C<j> instead of C<i>.
78 We have a conflict among our coding standards here. Our 100-character line
79 limit meant that the following function declaration had to be split over two
80 lines. However, that leads to t/codingstd/pmc_docs.t reporting that this
81 function lacks documentation -- reporting due to differences in whitespacing
82 between '=item' and function declaration.
87 complex_parse_string(PARROT_INTERP,
88 ARGOUT(FLOATVAL *re), ARGOUT(FLOATVAL *im), ARGIN(STRING *value))
90 ASSERT_ARGS(complex_parse_string)
92 char * const str = Parrot_str_to_cstring(interp, value);
94 char *first_num_offset = str;
95 char *second_num_offset = NULL;
99 INTVAL first_num_minus = 0;
100 INTVAL second_num_minus = 0;
101 UINTVAL first_num_length, second_num_length;
103 /* walk the string and identify the real and imaginary parts */
106 /* first number is negative */
110 /* allow for an optional space */
113 first_num_offset = t;
117 while (*t >= '0' && *t <= '9')
121 /* this number has a decimal point */
125 while (*t >= '0' && *t <= '9')
129 /* save the length of the real part */
130 first_num_length = t - first_num_offset;
132 /* end of string; we only have a real part */
134 second_num_length = 0;
136 else if ((*t == 'i' || *t == 'j') && *(t+1) == 0) {
137 /* there is only an imaginary part, so the first number was
138 actually the imaginary part */
139 second_num_length = first_num_length;
140 first_num_length = 0;
141 second_num_offset = first_num_offset;
142 second_num_minus = first_num_minus;
145 /* this is useful if there is no number for
146 the imaginary part, like in "-i" */
150 /* skip an optional space */
154 /* expect "+" or "-" and the imaginary part */
155 if (*t == '+' || *t == '-') {
157 second_num_minus = (*t == '-');
160 /* skip another optional space */
164 /* save the beginning of the imaginary part */
165 second_num_offset = t;
168 while (*t >= '0' && *t <= '9')
172 /* this number has a decimal point */
176 while (*t >= '0' && *t <= '9')
180 /* save the length of the imaginary part */
181 second_num_length = t - second_num_offset;
183 /* allow for one more optional space */
187 /* verify that the string ends properly */
188 if ((*t != 'i' && *t != 'j') || (*(t+1) != 0)) {
189 /* imaginary part does not end in 'i' or 'j' */
190 Parrot_ex_throw_from_c_args(interp, NULL,
191 EXCEPTION_INVALID_STRING_REPRESENTATION,
192 "Complex: malformed string");
195 /* this is useful if there is no number for the
196 imaginary part, like in "2+i" */
199 /* all is OK, save the number */
202 /* "+" or "-" not found: error */
203 Parrot_str_free_cstring(str);
205 Parrot_ex_throw_from_c_args(interp, NULL,
206 EXCEPTION_INVALID_STRING_REPRESENTATION,
207 "Complex: malformed string");
211 /* now we have the offsets and the lengths we turn them into float values */
213 if (first_num_length) {
214 /* there is a real part, interpret it */
215 S = Parrot_str_new(interp, first_num_offset, first_num_length);
216 *re = Parrot_str_to_num(interp, S);
219 /* consider the real part 0.0 */
223 if (second_num_length) {
224 /* there is an imaginary part, interpret it */
225 S = Parrot_str_new(interp, second_num_offset, second_num_length);
226 *im = Parrot_str_to_num(interp, S);
229 /* consider the imaginary part 0.0 */
230 if (i) /* the string was something like "1+i" */
239 if (second_num_minus)
242 Parrot_str_free_cstring(str);
247 =item C<static void int_check_divide_zero(PARROT_INTERP, INTVAL value)>
254 int_check_divide_zero(PARROT_INTERP, INTVAL value)
256 ASSERT_ARGS(int_check_divide_zero)
259 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_DIV_BY_ZERO,
265 =item C<static void float_check_divide_zero(PARROT_INTERP, FLOATVAL value)>
272 float_check_divide_zero(PARROT_INTERP, FLOATVAL value)
274 ASSERT_ARGS(float_check_divide_zero)
276 if (FLOAT_IS_ZERO(value))
277 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_DIV_BY_ZERO,
283 =item C<static void complex_check_divide_zero(PARROT_INTERP, PMC *value)>
290 complex_check_divide_zero(PARROT_INTERP, ARGIN(PMC *value))
292 ASSERT_ARGS(complex_check_divide_zero)
294 /* Throw an exception if we are dividing by zero. Check both the real part
295 * and the imaginary part.*/
297 if (FLOAT_IS_ZERO(VTABLE_get_number_keyed_int(interp, value, 0))
298 && FLOAT_IS_ZERO(VTABLE_get_number_keyed_int(interp, value, 1)))
299 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_DIV_BY_ZERO,
304 pmclass Complex provides complex provides scalar auto_attrs {
306 ATTR FLOATVAL re; /* real part */
307 ATTR FLOATVAL im; /* imaginary part */
319 Initializes the complex number with the value 0+0i.
321 =item C<void init_pmc(PMC *initializer)>
323 Initializes the complex number with the specified initializer.
324 The initializer can be a string PMC or a numeric array with (real, imag)
326 =item C<PMC *clone()>
328 Creates an identical copy of the complex number.
335 SET_ATTR_re(INTERP, SELF, 0.0);
336 SET_ATTR_im(INTERP, SELF, 0.0);
339 VTABLE void init_pmc(PMC *initializer) {
340 const INTVAL arg_type = VTABLE_type(INTERP, initializer);
343 case enum_class_String:
344 SELF.set_string_native(VTABLE_get_string(INTERP, initializer));
346 case enum_class_FixedFloatArray:
347 case enum_class_ResizableFloatArray:
348 case enum_class_FixedIntegerArray:
349 case enum_class_ResizableIntegerArray:
350 if (VTABLE_get_integer(INTERP, initializer) == 2) {
351 const FLOATVAL re = VTABLE_get_number_keyed_int(INTERP, initializer, 0);
352 const FLOATVAL im = VTABLE_get_number_keyed_int(INTERP, initializer, 1);
353 SET_ATTR_re(INTERP, SELF, re);
354 SET_ATTR_im(INTERP, SELF, im);
357 /* else let it fall to default */
359 if (VTABLE_isa(INTERP, initializer, CONST_STRING(INTERP, "String"))) {
360 STRING * const s = VTABLE_get_string(INTERP, initializer);
361 SELF.set_string_native(s);
364 Parrot_ex_throw_from_c_args(INTERP, NULL,
365 EXCEPTION_INVALID_OPERATION,
366 "Invalid Complex initializer");
371 VTABLE PMC *clone() {
372 PMC * const dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
375 GET_ATTR_re(INTERP, SELF, re);
376 GET_ATTR_im(INTERP, SELF, im);
377 SET_ATTR_re(INTERP, dest, re);
378 SET_ATTR_im(INTERP, dest, im);
385 =item C<void freeze(PMC *visit)>
387 =item C<void thaw(PMC *visit)>
389 Serialize/deserialize this object for bytecode.
395 VTABLE void freeze(PMC *visit) {
400 GET_ATTR_re(INTERP, SELF, re);
401 VTABLE_push_float(INTERP, visit, re);
403 GET_ATTR_im(INTERP, SELF, im);
404 VTABLE_push_float(INTERP, visit, im);
407 VTABLE void thaw(PMC *visit) {
412 re = VTABLE_shift_float(INTERP, visit);
413 SET_ATTR_re(INTERP, SELF, re);
415 im = VTABLE_shift_float(INTERP, visit);
416 SET_ATTR_im(INTERP, SELF, im);
421 =item C<INTVAL get_integer()>
423 Returns the modulus of the complex number as an integer.
425 =item C<FLOATVAL get_number()>
427 Returns the modulus of the complex number.
429 =item C<STRING *get_string()>
431 Returns the complex number as a string in the form C<a+bi>.
433 =item C<INTVAL get_bool()>
435 Returns true if the complex number is non-zero.
441 VTABLE INTVAL get_integer() {
442 const FLOATVAL f = SELF.get_number();
446 VTABLE FLOATVAL get_number() {
448 GET_ATTR_re(INTERP, SELF, re);
449 GET_ATTR_im(INTERP, SELF, im);
450 return sqrt(re * re + im * im);
453 VTABLE STRING *get_string() {
455 GET_ATTR_re(INTERP, SELF, re);
456 GET_ATTR_im(INTERP, SELF, im);
457 return Parrot_sprintf_c(INTERP, "%vg%+vgi", re, im);
460 VTABLE INTVAL get_bool() {
462 GET_ATTR_re(INTERP, SELF, re);
463 GET_ATTR_im(INTERP, SELF, im);
464 return !(FLOAT_IS_ZERO(re) && FLOAT_IS_ZERO(im));
469 =item C<INTVAL get_integer_keyed(PMC *key)>
471 =item C<INTVAL get_integer_keyed_str(STRING *key)>
473 =item C<FLOATVAL get_number_keyed(PMC *key)>
475 =item C<FLOATVAL get_number_keyed_str(STRING *key)>
477 =item C<PMC *get_pmc_keyed(PMC *key)>
479 =item C<PMC *get_pmc_keyed_str(STRING *key)>
481 Returns the requested number (real part for C<real> and imaginary for C<imag>).
487 VTABLE INTVAL get_integer_keyed(PMC *key) {
488 STRING * const s = VTABLE_get_string(INTERP, key);
489 return SELF.get_integer_keyed_str(s);
492 VTABLE INTVAL get_integer_keyed_str(STRING *key) {
493 const FLOATVAL f = SELF.get_number_keyed_str(key);
497 VTABLE FLOATVAL get_number_keyed(PMC *key) {
498 STRING * const s = VTABLE_get_string(INTERP, key);
499 return SELF.get_number_keyed_str(s);
502 VTABLE FLOATVAL get_number_keyed_str(STRING *key) {
504 if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "real"))) {
505 GET_ATTR_re(INTERP, SELF, value);
507 else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "imag"))) {
508 GET_ATTR_im(INTERP, SELF, value);
511 Parrot_ex_throw_from_c_args(INTERP, NULL,
512 EXCEPTION_INVALID_OPERATION, "Complex: key is neither 'real' or 'imag'");
516 VTABLE PMC *get_pmc_keyed(PMC *key) {
517 if (VTABLE_isa(INTERP, key, CONST_STRING(INTERP, "Integer"))) {
518 const INTVAL i = VTABLE_get_integer(INTERP, key);
519 return SELF.get_pmc_keyed_int(i);
522 STRING * const s = VTABLE_get_string(INTERP, key);
523 return SELF.get_pmc_keyed_str(s);
527 VTABLE PMC *get_pmc_keyed_str(STRING *key) {
528 PMC * const ret = Parrot_pmc_new(INTERP, enum_class_Float);
529 const FLOATVAL val = SELF.get_number_keyed_str(key);
530 VTABLE_set_number_native(INTERP, ret, val);
536 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
538 Returns the requested number (real part for C<0> and imaginary for C<1>).
544 VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
545 PMC * const ret = Parrot_pmc_new(INTERP, enum_class_Float);
546 const FLOATVAL val = SELF.get_number_keyed_int(key);
547 VTABLE_set_number_native(INTERP, ret, val);
553 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
555 Quick hack to emulate get_real() and get_imag():
557 key = 0 ... get real part
558 key = 1 ... get imag part
560 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL v)>
562 Set real or imag depending on key
568 VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
572 GET_ATTR_re(INTERP, SELF, f);
575 GET_ATTR_im(INTERP, SELF, f);
578 Parrot_ex_throw_from_c_args(INTERP, NULL,
579 EXCEPTION_INVALID_OPERATION, "Complex: key must be 0 or 1");
584 VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL v) {
587 SET_ATTR_re(INTERP, SELF, v);
590 SET_ATTR_im(INTERP, SELF, v);
593 Parrot_ex_throw_from_c_args(INTERP, NULL,
594 EXCEPTION_INVALID_OPERATION, "Complex: key must be 0 or 1");
599 =item C<void set_string_native(STRING *value)>
601 Parses the string C<value> into a complex number; raises an exception
604 =item C<void set_pmc(PMC *value)>
606 if C<value> is a Complex PMC then the complex number is set to its
607 value; otherwise C<value>'s string representation is parsed with
608 C<set_string_native()>.
610 =item C<void set_integer_native(INTVAL value)>
612 =item C<void set_number_native(FLOATVAL value)>
614 Sets the real part of the complex number to C<value> and the imaginary
621 VTABLE void set_string_native(STRING *value) {
623 complex_parse_string(INTERP, &re, &im, value);
624 SET_ATTR_re(INTERP, SELF, re);
625 SET_ATTR_im(INTERP, SELF, im);
628 VTABLE void set_pmc(PMC *value) {
629 if (VTABLE_isa(INTERP, value, CONST_STRING(INTERP, "Complex"))) {
631 GET_ATTR_re(INTERP, value, re);
632 GET_ATTR_im(INTERP, value, im);
633 SET_ATTR_re(INTERP, SELF, re);
634 SET_ATTR_im(INTERP, SELF, im);
637 VTABLE_set_string_native(INTERP, SELF, VTABLE_get_string(INTERP, value));
640 VTABLE void set_integer_native(INTVAL value) {
641 SELF.set_number_native((FLOATVAL)value);
644 VTABLE void set_number_native(FLOATVAL value) {
645 SET_ATTR_re(INTERP, SELF, value);
646 SET_ATTR_im(INTERP, SELF, 0.0);
651 =item C<void set_integer_keyed(PMC *key, INTVAL value)>
653 =item C<void set_integer_keyed_str(STRING *key, INTVAL value)>
655 =item C<void set_number_keyed(PMC *key, FLOATVAL value)>
657 =item C<void set_number_keyed_str(STRING *key, FLOATVAL value)>
659 =item C<void set_pmc_keyed(PMC *key, PMC *value)>
661 =item C<void set_pmc_keyed_str(STRING *key, PMC *value)>
663 Sets the requested number (real part for C<real> and imaginary for C<imag>)
670 VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
671 SELF.set_number_keyed(key, (FLOATVAL)value);
674 VTABLE void set_integer_keyed_str(STRING *key, INTVAL value) {
675 SELF.set_number_keyed_str(key, (FLOATVAL)value);
678 VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
679 if (VTABLE_isa(INTERP, key, CONST_STRING(INTERP, "Integer"))) {
680 const INTVAL i = VTABLE_get_integer(INTERP, key);
681 SELF.set_number_keyed_int(i, value);
684 STRING *s = VTABLE_get_string(INTERP, key);
685 SELF.set_number_keyed_str(s, value);
689 VTABLE void set_number_keyed_str(STRING *key, FLOATVAL value) {
690 if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "real"))) {
691 SET_ATTR_re(INTERP, SELF, value);
693 else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "imag"))) {
694 SET_ATTR_im(INTERP, SELF, value);
697 Parrot_ex_throw_from_c_args(INTERP, NULL,
698 EXCEPTION_INVALID_OPERATION, "Complex: key is neither 'real' or 'imag'");
701 VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
702 const FLOATVAL f = VTABLE_get_number(INTERP, value);
703 SELF.set_number_keyed(key, f);
706 VTABLE void set_pmc_keyed_str(STRING *key, PMC *value) {
707 const FLOATVAL f = VTABLE_get_number(INTERP, value);
708 SELF.set_number_keyed_str(key, f);
713 =item C<PMC *add(PMC *value, PMC *dest)>
715 =item C<PMC *add_int(INTVAL value, PMC *dest)>
717 =item C<PMC *add_float(FLOATVAL value, PMC *dest)>
719 Adds C<value> to the complex number, placing the result in C<dest>.
725 MULTI PMC *add(Complex value, PMC *dest) {
726 FLOATVAL self_re, self_im, val_re, val_im;
727 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
729 GET_ATTR_re(INTERP, SELF, self_re);
730 GET_ATTR_im(INTERP, SELF, self_im);
732 GET_ATTR_re(INTERP, value, val_re);
733 GET_ATTR_im(INTERP, value, val_im);
735 SET_ATTR_re(INTERP, dest, self_re + val_re);
736 SET_ATTR_im(INTERP, dest, self_im + val_im);
741 MULTI PMC *add(DEFAULT value, PMC *dest) {
743 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
745 GET_ATTR_re(INTERP, SELF, re);
746 GET_ATTR_im(INTERP, SELF, im);
747 SET_ATTR_re(INTERP, dest, re + VTABLE_get_number(INTERP, value));
748 SET_ATTR_im(INTERP, dest, im);
753 VTABLE PMC *add_int(INTVAL value, PMC *dest) {
754 return SELF.add_float((FLOATVAL)value, dest);
757 VTABLE PMC *add_float(FLOATVAL value, PMC *dest) {
759 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
761 GET_ATTR_re(INTERP, SELF, re);
762 GET_ATTR_im(INTERP, SELF, im);
763 SET_ATTR_re(INTERP, dest, re + value);
764 SET_ATTR_im(INTERP, dest, im);
769 MULTI void i_add(Complex value) {
770 FLOATVAL self_re, self_im, val_re, val_im;
772 GET_ATTR_re(INTERP, SELF, self_re);
773 GET_ATTR_im(INTERP, SELF, self_im);
775 GET_ATTR_re(INTERP, value, val_re);
776 GET_ATTR_im(INTERP, value, val_im);
778 SET_ATTR_re(INTERP, SELF, self_re + val_re);
779 SET_ATTR_im(INTERP, SELF, self_im + val_im);
782 MULTI void i_add(DEFAULT value) {
785 GET_ATTR_re(INTERP, SELF, re);
786 SET_ATTR_re(INTERP, SELF, re + VTABLE_get_number(INTERP, value));
789 VTABLE void i_add_int(INTVAL value) {
790 SELF.i_add_float((FLOATVAL)value);
793 VTABLE void i_add_float(FLOATVAL value) {
796 GET_ATTR_re(INTERP, SELF, re);
797 SET_ATTR_re(INTERP, SELF, re + value);
802 =item C<PMC *subtract(PMC *value, PMC *dest)>
804 =item C<PMC *subtract_int(INTVAL value, PMC *dest)>
806 =item C<PMC *subtract_float(FLOATVAL value, PMC *dest)>
808 Subtracts C<value> from the complex number, placing the result in C<dest>.
814 MULTI PMC *subtract(Complex value, PMC *dest) {
815 FLOATVAL self_re, self_im, val_re, val_im;
816 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
818 GET_ATTR_re(INTERP, SELF, self_re);
819 GET_ATTR_im(INTERP, SELF, self_im);
821 GET_ATTR_re(INTERP, value, val_re);
822 GET_ATTR_im(INTERP, value, val_im);
824 SET_ATTR_re(INTERP, dest, self_re - val_re);
825 SET_ATTR_im(INTERP, dest, self_im - val_im);
830 MULTI PMC *subtract(DEFAULT value, PMC *dest) {
832 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
834 GET_ATTR_re(INTERP, SELF, re);
835 GET_ATTR_im(INTERP, SELF, im);
836 SET_ATTR_re(INTERP, dest, re - VTABLE_get_number(INTERP, value));
837 SET_ATTR_im(INTERP, dest, im);
842 VTABLE PMC *subtract_int(INTVAL value, PMC *dest) {
843 return SELF.subtract_float((FLOATVAL)value, dest);
846 VTABLE PMC *subtract_float(FLOATVAL value, PMC *dest) {
848 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
850 GET_ATTR_re(INTERP, SELF, re);
851 GET_ATTR_im(INTERP, SELF, im);
852 SET_ATTR_re(INTERP, dest, re - value);
853 SET_ATTR_im(INTERP, dest, im);
858 MULTI void i_subtract(Complex value) {
859 FLOATVAL self_re, self_im, val_re, val_im;
861 GET_ATTR_re(INTERP, SELF, self_re);
862 GET_ATTR_im(INTERP, SELF, self_im);
864 GET_ATTR_re(INTERP, value, val_re);
865 GET_ATTR_im(INTERP, value, val_im);
867 SET_ATTR_re(INTERP, SELF, self_re - val_re);
868 SET_ATTR_im(INTERP, SELF, self_im - val_im);
871 MULTI void i_subtract(DEFAULT value) {
874 GET_ATTR_re(INTERP, SELF, re);
875 SET_ATTR_re(INTERP, SELF, re - VTABLE_get_number(INTERP, value));
878 VTABLE void i_subtract_int(INTVAL value) {
879 SELF.i_subtract_float((FLOATVAL) value);
882 VTABLE void i_subtract_float(FLOATVAL value) {
885 GET_ATTR_re(INTERP, SELF, re);
886 SET_ATTR_re(INTERP, SELF, re - value);
890 =item C<PMC *multiply(PMC *value, PMC *dest)>
892 =item C<PMC *multiply_int(INTVAL value, PMC *dest)>
894 =item C<PMC *multiply_float(FLOATVAL value, PMC *dest)>
896 Multiplies the complex number with C<value>, placing the result in C<dest>.
898 =item C<void i_multiply(PMC *value)>
900 =item C<void i_multiply_int(INTVAL value)>
902 =item C<void i_multiply_float(FLOATVAL value)>
904 Multiplies the complex number SELF inplace with C<value>.
912 (a+ib)(c+id)=(ac-bd)+i((a+b)(c+d)-ac-bd).
913 (a+bi)(c+di)=(ac-bd)+i(ad+bc)
916 MULTI PMC *multiply(Complex value, PMC *dest) {
919 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
921 GET_ATTR_re(INTERP, SELF, a);
922 GET_ATTR_im(INTERP, SELF, b);
923 GET_ATTR_re(INTERP, value, c);
924 GET_ATTR_im(INTERP, value, d);
925 SET_ATTR_re(INTERP, dest, a * c - b * d);
926 SET_ATTR_im(INTERP, dest, a * d + b * c);
931 MULTI PMC *multiply(DEFAULT value, PMC *dest) {
933 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
935 GET_ATTR_re(INTERP, SELF, re);
936 GET_ATTR_im(INTERP, SELF, im);
937 SET_ATTR_re(INTERP, dest, re * VTABLE_get_number(INTERP, value));
938 SET_ATTR_im(INTERP, dest, im * VTABLE_get_number(INTERP, value));
943 VTABLE PMC *multiply_int(INTVAL value, PMC *dest) {
944 return SELF.multiply_float((FLOATVAL) value, dest);
947 VTABLE PMC *multiply_float(FLOATVAL value, PMC *dest) {
949 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
951 GET_ATTR_re(INTERP, SELF, re);
952 GET_ATTR_im(INTERP, SELF, im);
953 SET_ATTR_re(INTERP, dest, re * value);
954 SET_ATTR_im(INTERP, dest, im * value);
959 MULTI void i_multiply(Complex value) {
962 GET_ATTR_re(INTERP, SELF, a);
963 GET_ATTR_im(INTERP, SELF, b);
964 GET_ATTR_re(INTERP, value, c);
965 GET_ATTR_im(INTERP, value, d);
966 SET_ATTR_re(INTERP, SELF, a * c - b * d);
967 SET_ATTR_im(INTERP, SELF, a * d + b * c);
970 MULTI void i_multiply(DEFAULT value) {
973 GET_ATTR_re(INTERP, SELF, re);
974 GET_ATTR_im(INTERP, SELF, im);
975 SET_ATTR_re(INTERP, SELF, re * VTABLE_get_number(INTERP, value));
976 SET_ATTR_im(INTERP, SELF, im * VTABLE_get_number(INTERP, value));
979 VTABLE void i_multiply_int(INTVAL value) {
982 GET_ATTR_re(INTERP, SELF, re);
983 GET_ATTR_im(INTERP, SELF, im);
984 SET_ATTR_re(INTERP, SELF, re * value);
985 SET_ATTR_im(INTERP, SELF, im * value);
988 VTABLE void i_multiply_float(FLOATVAL value) {
991 GET_ATTR_re(INTERP, SELF, re);
992 GET_ATTR_im(INTERP, SELF, im);
993 SET_ATTR_re(INTERP, SELF, re * value);
994 SET_ATTR_im(INTERP, SELF, im * value);
999 =item C<PMC *divide(PMC *value, PMC *dest)>
1001 =item C<PMC *divide_int(INTVAL value, PMC *dest)>
1003 =item C<PMC *divide_float(FLOATVAL value, PMC *dest)>
1005 Divide the complex number by C<value>, placing the result in C<dest>.
1007 =item C<void i_divide(PMC *value, PMC *dest)>
1009 =item C<void i_divide_int(INTVAL value, PMC *dest)>
1011 =item C<void i_divide_float(FLOATVAL value, PMC *dest)>
1013 Divide the complex number C<SELF> by C<value> inplace.
1015 Throws divide by zero exception if divisor is zero.
1019 TODO: for better fp precision
1020 http://docs.sun.com/source/806-3568/ncg_goldberg.html
1022 (a + b(d/c)) / (c + d(d/c)) + i(b - a(d/c)) / (c + d(d/c)) if |d|<|c|
1023 (b + a(c/d)) / (d + c(c/d)) + i(-a + b(c/d)) / (d + c(c/d)) if |d|>=|c|
1027 MULTI PMC *divide(Complex value, PMC *dest) {
1028 FLOATVAL mod, re, im;
1029 FLOATVAL self_re, self_im, val_re, val_im;
1031 complex_check_divide_zero(INTERP, value);
1032 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1034 GET_ATTR_re(INTERP, SELF, self_re);
1035 GET_ATTR_im(INTERP, SELF, self_im);
1036 GET_ATTR_re(INTERP, value, val_re);
1037 GET_ATTR_im(INTERP, value, val_im);
1039 /* a little speed optimisation: cache an intermediate number;
1040 I'm not sure the compiler does this */
1042 if (self_im == 0.0 && val_im == 0.0) {
1043 re = self_re / val_re;
1047 mod = (val_re * val_re + val_im * val_im);
1048 re = (self_re * val_re + self_im * val_im) / mod;
1049 im = (self_im * val_re - self_re * val_im) / mod;
1052 SET_ATTR_re(INTERP, dest, re);
1053 SET_ATTR_im(INTERP, dest, im);
1058 MULTI PMC *divide(DEFAULT value, PMC *dest) {
1060 const FLOATVAL d = VTABLE_get_number(INTERP, value);
1061 float_check_divide_zero(INTERP, d);
1062 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1064 GET_ATTR_re(INTERP, SELF, re);
1065 GET_ATTR_im(INTERP, SELF, im);
1067 SET_ATTR_re(INTERP, dest, re / d);
1068 SET_ATTR_im(INTERP, dest, im / d);
1073 VTABLE PMC *divide_int(INTVAL value, PMC *dest) {
1075 int_check_divide_zero(INTERP, value);
1076 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1078 GET_ATTR_re(INTERP, SELF, re);
1079 GET_ATTR_im(INTERP, SELF, im);
1081 SET_ATTR_re(INTERP, dest, re / value);
1082 SET_ATTR_im(INTERP, dest, im / value);
1087 VTABLE PMC *divide_float(FLOATVAL value, PMC *dest) {
1089 float_check_divide_zero(INTERP, value);
1090 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1092 GET_ATTR_re(INTERP, SELF, re);
1093 GET_ATTR_im(INTERP, SELF, im);
1095 SET_ATTR_re(INTERP, dest, re / value);
1096 SET_ATTR_im(INTERP, dest, im / value);
1101 MULTI void i_divide(Complex value) {
1103 FLOATVAL self_re, self_im, val_re, val_im;
1105 complex_check_divide_zero(INTERP, value);
1107 GET_ATTR_re(INTERP, SELF, self_re);
1108 GET_ATTR_im(INTERP, SELF, self_im);
1109 GET_ATTR_re(INTERP, value, val_re);
1110 GET_ATTR_im(INTERP, value, val_im);
1112 if (self_im == 0.0 && val_im == 0.0) {
1113 re = self_re / val_re;
1117 /* a little speed optimisation: cache an intermediate number;
1118 I'm not sure the compiler does this */
1119 const FLOATVAL mod = (val_re * val_re + val_im * val_im);
1120 re = (self_re * val_re + self_im * val_im) / mod;
1121 im = (self_im * val_re - self_re * val_im) / mod;
1124 SET_ATTR_re(INTERP, SELF, re);
1125 SET_ATTR_im(INTERP, SELF, im);
1129 MULTI void i_divide(DEFAULT value) {
1131 const FLOATVAL d = VTABLE_get_number(INTERP, value);
1132 float_check_divide_zero(INTERP, d);
1134 GET_ATTR_re(INTERP, SELF, re);
1135 GET_ATTR_im(INTERP, SELF, im);
1137 SET_ATTR_re(INTERP, SELF, re / d);
1138 SET_ATTR_im(INTERP, SELF, im / d);
1141 VTABLE void i_divide_int(INTVAL value) {
1143 int_check_divide_zero(INTERP, value);
1145 GET_ATTR_re(INTERP, SELF, re);
1146 GET_ATTR_im(INTERP, SELF, im);
1148 SET_ATTR_re(INTERP, SELF, re / value);
1149 SET_ATTR_im(INTERP, SELF, im / value);
1152 VTABLE void i_divide_float(FLOATVAL value) {
1154 float_check_divide_zero(INTERP, value);
1156 GET_ATTR_re(INTERP, SELF, re);
1157 GET_ATTR_im(INTERP, SELF, im);
1159 SET_ATTR_re(INTERP, SELF, re / value);
1160 SET_ATTR_im(INTERP, SELF, im / value);
1165 =item C<PMC *neg(PMC *dest)>
1169 Set C<dest> to the negated value of C<SELF>.
1175 VTABLE PMC *neg(PMC *dest) {
1177 dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1179 GET_ATTR_re(INTERP, SELF, re);
1180 GET_ATTR_im(INTERP, SELF, im);
1182 SET_ATTR_re(INTERP, dest, -re);
1183 SET_ATTR_im(INTERP, dest, -im);
1188 VTABLE void i_neg() {
1190 GET_ATTR_re(INTERP, SELF, re);
1191 GET_ATTR_im(INTERP, SELF, im);
1192 SET_ATTR_re(INTERP, SELF, -re);
1193 SET_ATTR_im(INTERP, SELF, -im);
1198 =item C<INTVAL is_equal(PMC *value)>
1200 Compares the complex number with C<value> and returns true if they are equal.
1206 MULTI INTVAL is_equal(Complex value) {
1207 FLOATVAL self_re, self_im, val_re, val_im;
1208 GET_ATTR_re(INTERP, SELF, self_re);
1209 GET_ATTR_im(INTERP, SELF, self_im);
1210 GET_ATTR_re(INTERP, value, val_re);
1211 GET_ATTR_im(INTERP, value, val_im);
1212 return (INTVAL)(self_re == val_re && self_im == val_im);
1215 MULTI INTVAL is_equal(DEFAULT value) {
1217 GET_ATTR_re(INTERP, SELF, re);
1218 GET_ATTR_im(INTERP, SELF, im);
1223 return (re == VTABLE_get_number(INTERP, value));
1228 =item C<PMC *absolute(PMC *dest)>
1230 =item C<void i_absolute()>
1232 Sets C<dest> to the absolute value of SELF that is the distance from (0.0).
1240 TODO for better precision: hinted by vaxman according to "Numerical Recipes
1241 in Fortran 77", 2nd edition, Press, Vetterling, Teukolsky, Flannery,
1242 Cambridge University Press, 2001, pp. 171ff:
1245 |a+ib|=|a|*sqrt(1+(b/a)**2), if |a|>=|b|,
1246 |b|*sqrt(1+(a/b)**2) else.
1250 VTABLE PMC *absolute(PMC *dest) {
1252 GET_ATTR_re(INTERP, SELF, re);
1253 GET_ATTR_im(INTERP, SELF, im);
1254 d = sqrt(re*re + im*im);
1256 dest = Parrot_pmc_new(INTERP,
1257 Parrot_get_ctx_HLL_type(INTERP, enum_class_Float));
1259 VTABLE_set_number_native(INTERP, dest, d);
1263 VTABLE void i_absolute() {
1265 GET_ATTR_re(INTERP, SELF, re);
1266 GET_ATTR_im(INTERP, SELF, im);
1267 d = sqrt(re*re + im*im);
1268 Parrot_pmc_reuse(INTERP, SELF, enum_class_Float, 0);
1269 VTABLE_set_number_native(INTERP, SELF, d);
1274 =item C<METHOD ln()>
1276 Returns the natural logarithm of SELF as a PMC.
1280 ln z = ln |z| + i arg(z)
1281 |x + iy| = sqrt(x^2 + y^2)
1282 arg(x + iy) = atan2(y, x)
1289 ln(+-i) = +- (pi i)/2
1294 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1295 FLOATVAL re, im, result_re, result_im;
1296 GET_ATTR_re(INTERP, SELF, re);
1297 GET_ATTR_im(INTERP, SELF, im);
1299 /* This is necessary for atan2 to behave */
1303 result_re = log(sqrt(re*re + im*im));
1304 if (re == 0.0 && im == 0.0) /* atan2(0, 0) not portable */
1307 result_im = atan2(im, re);
1309 SET_ATTR_re(INTERP, d, result_re);
1310 SET_ATTR_im(INTERP, d, result_im);
1317 =item C<METHOD exp()>
1319 Returns e ^ SELF as a PMC.
1323 exp(a + bi) = exp(a) * (cos(b) + i * sin(b))
1328 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1330 GET_ATTR_re(INTERP, SELF, re);
1331 GET_ATTR_im(INTERP, SELF, im);
1335 SET_ATTR_re(INTERP, d, f * cos(im));
1337 /* If only sin(pi) worked. */
1338 if (im == 4.0 * atan(1.0)) {
1339 SET_ATTR_im(INTERP, d, 0.0);
1342 SET_ATTR_im(INTERP, d, f * sin(im));
1350 =item C<METHOD PMC *sin()>
1352 =item C<METHOD PMC *cos()>
1354 =item C<METHOD PMC *tan()>
1356 =item C<METHOD PMC *csc()>
1358 =item C<METHOD PMC *sec()>
1360 =item C<METHOD PMC *cot()>
1362 Returns C<FUNC>(SELF).
1366 => sin(a + bi) = sin(a)cosh(b)+i*cos(a)sinh(b)
1367 sin(z) = ((e ^ zi) - (e ^ -zi)) / (2i)
1368 => cos(a + bi) = cos(a) * cosh(b) - i * sin(a) * sinh(b)
1369 cos(z) = ((e ^ zi) + (e ^ -zi)) / 2
1376 sinh(a + bi) = sinh(a) * cos(b) + i * cosh(a) * sin(b)
1377 cosh(a + bi) = cosh(a) * cos(b) + i * sinh(a) * sin(b)
1382 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1383 FLOATVAL re, im, result_re, result_im;
1384 GET_ATTR_re(INTERP, SELF, re);
1385 GET_ATTR_im(INTERP, SELF, im);
1387 if (FLOAT_IS_ZERO(im)) {
1388 result_re = sin(re);
1391 else if (FLOAT_IS_ZERO(re)) {
1393 result_im = sinh(im);
1396 result_re = sin(re) * cosh(im);
1401 result_im = cos(re) * sinh(im);
1405 SET_ATTR_re(INTERP, d, result_re);
1406 SET_ATTR_im(INTERP, d, result_im);
1412 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1413 FLOATVAL re, im, result_re, result_im;
1414 GET_ATTR_re(INTERP, SELF, re);
1415 GET_ATTR_im(INTERP, SELF, im);
1417 if (FLOAT_IS_ZERO(re)) {
1418 result_re = cosh(im);
1421 else if (FLOAT_IS_ZERO(im)) {
1422 result_re = cos(re);
1426 result_re = cos(re) * cosh(im);
1427 result_im = -1.0 * sin(re) * sinh(im);
1430 SET_ATTR_re(INTERP, d, result_re);
1431 SET_ATTR_im(INTERP, d, result_im);
1437 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1438 PMC * const e = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1440 (PMC *d) = PCCINVOKE(INTERP, SELF, "sin");
1441 (PMC *e) = PCCINVOKE(INTERP, SELF, "cos");
1443 Parrot_Complex_multi_i_divide_Complex(INTERP, d, e);
1449 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1450 PMC * const e = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1451 (PMC *d) = PCCINVOKE(INTERP, SELF, "cos");
1452 (PMC *e) = PCCINVOKE(INTERP, SELF, "sin");
1454 Parrot_Complex_multi_i_divide_Complex(INTERP, d, e);
1460 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1461 PMC * const e = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1462 SET_ATTR_re(INTERP, d, 1.0);
1463 SET_ATTR_im(INTERP, d, 0.0);
1464 (PMC *e) = PCCINVOKE(INTERP, SELF, "cos");
1466 Parrot_Complex_multi_i_divide_Complex(INTERP, d, e);
1472 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1473 PMC * const e = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1475 SET_ATTR_re(INTERP, d, 1.0);
1476 SET_ATTR_im(INTERP, d, 0.0);
1478 (PMC *e) = PCCINVOKE(INTERP, SELF, "sin");
1480 Parrot_Complex_multi_i_divide_Complex(INTERP, d, e);
1487 =item C<METHOD PMC *asin()>
1489 =item C<METHOD PMC *acos()>
1491 =item C<METHOD PMC *atan()>
1493 =item C<METHOD PMC *acsc()>
1495 =item C<METHOD PMC *asec()>
1497 =item C<METHOD PMC *acot()>
1499 Returns the inverse function of SELF.
1503 => arcsin z = -i ln(iz + sqrt(1-z*z))
1504 => arccos z = pi/2 + i * ln(iz + sqrt(1 - z*z))
1505 arccos z = -i ln(z + sqrt(z*z-1))
1506 => arctan z = i/2 ln((i+z) / (i-z))
1507 arctan z = 1/2 i (ln(1-iz) - ln(1 + iz))
1509 => acot(z) = atan(1 / z)
1510 acot(z) = i/2 (ln((z - i) / z) - ln((z + i) / z))
1511 => asec(z) = acos(1 / z)
1512 asec(z) = 1/2 pi + i ln(sqrt(1 - 1/zz) + i/z)
1513 => acsc(z) = asin(1 / z)
1514 acsc(z) = -i ln(sqrt(1 - 1/zz + i/z))
1519 FLOATVAL d_re, d_im, e_re, e_im, self_re, self_im;
1520 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1521 PMC * e = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1522 GET_ATTR_re(INTERP, SELF, self_re);
1523 GET_ATTR_im(INTERP, SELF, self_im);
1525 e = Parrot_Complex_multi_multiply_Complex_PMC(INTERP, SELF, SELF, e);
1526 GET_ATTR_re(INTERP, e, e_re);
1527 GET_ATTR_im(INTERP, e, e_im);
1528 SET_ATTR_re(INTERP, e, 1.0 - e_re);
1529 SET_ATTR_im(INTERP, e, -e_im);
1531 (PMC *d) = PCCINVOKE(INTERP, e, "sqrt");
1532 GET_ATTR_re(INTERP, d, d_re);
1533 GET_ATTR_im(INTERP, d, d_im);
1534 SET_ATTR_re(INTERP, d, d_re - self_im);
1535 SET_ATTR_im(INTERP, d, d_im + self_re);
1537 (PMC *d) = PCCINVOKE(INTERP, d, "ln");
1538 GET_ATTR_re(INTERP, d, d_re);
1539 GET_ATTR_im(INTERP, d, d_im);
1540 SET_ATTR_re(INTERP, e, d_im);
1541 SET_ATTR_im(INTERP, e, d_re ? -d_re : 0.0);
1547 FLOATVAL d_re, d_im, e_re, e_im, self_re, self_im;
1548 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1549 PMC * e = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1550 GET_ATTR_re(INTERP, SELF, self_re);
1551 GET_ATTR_im(INTERP, SELF, self_im);
1553 e = Parrot_Complex_multi_multiply_Complex_PMC(INTERP, SELF, SELF, e);
1554 GET_ATTR_re(INTERP, e, e_re);
1555 GET_ATTR_im(INTERP, e, e_im);
1556 SET_ATTR_re(INTERP, e, 1.0 - e_re);
1557 SET_ATTR_im(INTERP, e, -e_im);
1559 (PMC *d) = PCCINVOKE(INTERP, e, "sqrt");
1560 GET_ATTR_re(INTERP, d, d_re);
1561 GET_ATTR_im(INTERP, d, d_im);
1562 SET_ATTR_re(INTERP, d, d_re + self_im);
1563 SET_ATTR_im(INTERP, d, d_im - self_re);
1565 (PMC *e) = PCCINVOKE(INTERP, d, "ln");
1566 GET_ATTR_re(INTERP, e, e_re);
1567 GET_ATTR_im(INTERP, e, e_im);
1568 SET_ATTR_re(INTERP, d, e_im + 2.0 * atan(1.0));
1569 SET_ATTR_im(INTERP, d, e_re ? -e_re : 0.0);
1575 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1576 PMC * const e = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1577 FLOATVAL re, im, d_re, d_im;
1578 GET_ATTR_re(INTERP, SELF, re);
1579 GET_ATTR_im(INTERP, SELF, im);
1581 SET_ATTR_re(INTERP, d, re);
1582 SET_ATTR_im(INTERP, d, 1 + im);
1583 SET_ATTR_re(INTERP, e, -re);
1584 SET_ATTR_im(INTERP, e, 1 - im);
1586 Parrot_Complex_multi_i_divide_Complex(INTERP, d, e);
1588 (PMC *d) = PCCINVOKE(INTERP, d, "ln");
1589 GET_ATTR_re(INTERP, d, d_re);
1590 GET_ATTR_im(INTERP, d, d_im);
1592 SET_ATTR_re(INTERP, e, (d_im ? d_im : -0.0) / -2.0);
1593 SET_ATTR_im(INTERP, e, d_re / 2.0);
1599 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1602 GET_ATTR_re(INTERP, SELF, re);
1603 GET_ATTR_im(INTERP, SELF, im);
1605 SET_ATTR_re(INTERP, d, re / (re * re + im * im));
1606 SET_ATTR_im(INTERP, d, -im / (re * re + im * im));
1608 (PMC *e) = PCCINVOKE(INTERP, d, "atan");
1613 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1616 GET_ATTR_re(INTERP, SELF, re);
1617 GET_ATTR_im(INTERP, SELF, im);
1619 SET_ATTR_re(INTERP, d, re / (re * re + im * im));
1620 SET_ATTR_im(INTERP, d, -im / (re * re + im * im));
1622 (PMC *e) = PCCINVOKE(INTERP, d, "asin");
1627 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1630 GET_ATTR_re(INTERP, SELF, re);
1631 GET_ATTR_im(INTERP, SELF, im);
1633 SET_ATTR_re(INTERP, d, re / (re * re + im * im));
1634 SET_ATTR_im(INTERP, d, -im / (re * re + im * im));
1636 (PMC *e) = PCCINVOKE(INTERP, d, "acos");
1642 =item C<METHOD PMC *sinh()>
1644 Returns the arctangent of SELF.
1646 =item C<METHOD PMC *cosh()>
1648 Returns the arcsine of SELF.
1650 =item C<METHOD PMC *tanh()>
1652 Returns the arccosine of SELF.
1656 tanh(z) = sinh(z) / cosh(z)
1661 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1663 GET_ATTR_re(INTERP, SELF, re);
1664 GET_ATTR_im(INTERP, SELF, im);
1666 SET_ATTR_re(INTERP, d, sinh(re) * cos(im));
1667 SET_ATTR_im(INTERP, d, im ? cosh(re) * sin(im) : 0.0);
1673 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1675 GET_ATTR_re(INTERP, SELF, re);
1676 GET_ATTR_im(INTERP, SELF, im);
1678 SET_ATTR_re(INTERP, d, cosh(re) * cos(im));
1679 if (re == 0.0 || im == 0.0) {
1680 SET_ATTR_im(INTERP, d, 0.0);
1683 SET_ATTR_im(INTERP, d, sinh(re) * sin(im));
1690 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1691 PMC * const e = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1693 (PMC *d) = PCCINVOKE(INTERP, SELF, "sinh");
1694 (PMC *e) = PCCINVOKE(INTERP, SELF, "cosh");
1696 Parrot_Complex_multi_i_divide_Complex(INTERP, d, e);
1703 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1705 (PMC *d) = PCCINVOKE(INTERP, SELF, "tanh");
1706 GET_ATTR_re(INTERP, d, re);
1707 GET_ATTR_im(INTERP, d, im);
1709 SET_ATTR_re(INTERP, d, re ? re / (re * re + im * im) : 0.0);
1710 SET_ATTR_im(INTERP, d, im ? -im / (re * re + im * im) : 0.0);
1717 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1719 (PMC *d) = PCCINVOKE(INTERP, SELF, "sinh");
1720 GET_ATTR_re(INTERP, d, re);
1721 GET_ATTR_im(INTERP, d, im);
1723 SET_ATTR_re(INTERP, d, re ? re / (re * re + im * im) : 0.0);
1724 SET_ATTR_im(INTERP, d, im ? -im / (re * re + im * im) : 0.0);
1731 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1733 (PMC *d) = PCCINVOKE(INTERP, SELF, "cosh");
1734 GET_ATTR_re(INTERP, d, re);
1735 GET_ATTR_im(INTERP, d, im);
1737 SET_ATTR_re(INTERP, d, re ? re / (re * re + im * im) : 0.0);
1738 SET_ATTR_im(INTERP, d, im ? -im / (re * re + im * im) : 0.0);
1745 =item C<METHOD PMC *asinh()>
1747 =item C<METHOD PMC *acosh()>
1749 =item C<METHOD PMC *atanh()>
1751 =item C<METHOD PMC *acsch()>
1753 =item C<METHOD PMC *asech()>
1755 =item C<METHOD PMC *acoth()>
1757 The inverse hyperbolic functions. Currently all broken, but for
1758 C<func(a+bi) = c+di>, C<|c|> and C<|d|> will be correct, confusingly enough.
1762 asinh z = -ln(sqrt(1+zz) - z)
1763 asinh z = ln(sqrt(zz + 1) + z)
1773 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1774 PMC * const e = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1776 GET_ATTR_re(INTERP, SELF, re);
1777 GET_ATTR_im(INTERP, SELF, im);
1778 SET_ATTR_re(INTERP, d, im);
1779 SET_ATTR_im(INTERP, d, -re);
1781 (PMC *d) = PCCINVOKE(INTERP, d, "asin");
1782 GET_ATTR_re(INTERP, d, re);
1783 GET_ATTR_im(INTERP, d, im);
1784 SET_ATTR_re(INTERP, e, -im);
1785 SET_ATTR_im(INTERP, e, re);
1792 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1793 PMC * const e = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1795 (PMC *d) = PCCINVOKE(INTERP, SELF, "acos");
1796 GET_ATTR_re(INTERP, d, re);
1797 GET_ATTR_im(INTERP, d, im);
1798 SET_ATTR_re(INTERP, e, -im);
1799 SET_ATTR_im(INTERP, e, re);
1806 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1807 PMC * const e = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1809 GET_ATTR_re(INTERP, SELF, re);
1810 GET_ATTR_im(INTERP, SELF, im);
1811 SET_ATTR_re(INTERP, d, im);
1812 SET_ATTR_im(INTERP, d, -re);
1814 (PMC *d) = PCCINVOKE(INTERP, d, "atan");
1815 GET_ATTR_re(INTERP, d, re);
1816 GET_ATTR_im(INTERP, d, im);
1817 SET_ATTR_re(INTERP, e, -im);
1818 SET_ATTR_im(INTERP, e, re);
1824 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1827 GET_ATTR_re(INTERP, SELF, re);
1828 GET_ATTR_im(INTERP, SELF, im);
1830 SET_ATTR_re(INTERP, d, re / (re * re + im * im));
1831 SET_ATTR_im(INTERP, d, -im / (re * re + im * im));
1833 (PMC *e) = PCCINVOKE(INTERP, d, "atanh");
1838 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1841 GET_ATTR_re(INTERP, SELF, re);
1842 GET_ATTR_im(INTERP, SELF, im);
1844 SET_ATTR_re(INTERP, d, re / (re * re + im * im));
1845 SET_ATTR_im(INTERP, d, -im / (re * re + im * im));
1847 (PMC *e) = PCCINVOKE(INTERP, d, "asinh");
1852 PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1855 GET_ATTR_re(INTERP, SELF, re);
1856 GET_ATTR_im(INTERP, SELF, im);
1858 SET_ATTR_re(INTERP, d, re / (re * re + im * im));
1859 SET_ATTR_im(INTERP, d, -im / (re * re + im * im));
1861 (PMC *e) = PCCINVOKE(INTERP, d, "acosh");
1867 =item C<METHOD PMC *pow(PMC *value)>
1869 Raise SELF to the power of value. Replacement for the old pow() vtable, which
1872 TODO: Requires testing
1874 =item C<METHOD PMC *sqrt()>
1876 Return the square root of SELF.
1880 TODO: mmd in other pmc's to allow .Integer ^ .Complex, etc.
1881 and i_pow, and pow_(float|int), etc
1883 x ^ y = exp(y * ln x))
1887 METHOD pow(PMC * value) {
1888 PMC *l = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1890 PMC *dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1892 Parrot_pcc_invoke_method_from_c_args(INTERP, SELF, CONST_STRING(INTERP, "ln"),
1895 l = VTABLE_multiply(INTERP, log, value, l);
1897 Parrot_pcc_invoke_method_from_c_args(INTERP, l, CONST_STRING(INTERP, "exp"),
1903 PMC * const result = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
1904 const FLOATVAL absval = SELF.get_number();
1905 FLOATVAL sx, sy, rx, ry;
1906 GET_ATTR_re(INTERP, SELF, sx);
1907 GET_ATTR_im(INTERP, SELF, sy);
1909 rx = sqrt((absval + sx) / 2);
1910 ry = sqrt((absval - sx) / 2);
1913 SET_ATTR_re(INTERP, result, rx);
1914 SET_ATTR_im(INTERP, result, ry);
1915 RETURN(PMC *result);
1930 * c-file-style: "parrot"
1932 * vim: expandtab shiftwidth=4: