2 complex.c: Coded by Tadayoshi Funaba 2008
4 This implementation is based on Keiju Ishitsuka's Complex library
5 which is written in ruby.
15 #define COMPLEX_NAME "Complex"
18 #define ZERO INT2FIX(0)
19 #define ONE INT2FIX(1)
20 #define TWO INT2FIX(2)
24 static ID id_Unify
, id_abs
, id_abs2
, id_arg
, id_atan2_bang
, id_cmp
,
25 id_conjugate
, id_convert
, id_cos
, id_denominator
, id_divmod
,
26 id_equal_p
, id_exact_p
, id_exp_bang
, id_expt
, id_floor
, id_format
,
27 id_hypot
, id_idiv
, id_inspect
, id_log_bang
, id_negate
, id_new
, id_new_bang
,
28 id_numerator
, id_polar
, id_quo
, id_scalar_p
, id_sin
, id_sqrt
, id_to_f
,
29 id_to_i
, id_to_r
, id_to_s
, id_truncate
;
31 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
35 f_##n(VALUE x, VALUE y)\
37 return rb_funcall(x, op, 1, y);\
44 return rb_funcall(x, id_##n, 0);\
49 f_##n(VALUE x, VALUE y)\
51 return rb_funcall(x, id_##n, 1, y);\
58 return rb_funcall(rb_mMath, id_##n, 1, x);\
63 m_##n(VALUE x, VALUE y)\
65 return rb_funcall(rb_mMath, id_##n, 2, x, y);\
69 f_add(VALUE x
, VALUE y
)
75 else if (FIXNUM_P(x
)) {
79 return rb_funcall(x
, '+', 1, y
);
83 f_cmp(VALUE x
, VALUE y
)
85 if (FIXNUM_P(x
) && FIXNUM_P(y
)) {
86 long c
= FIX2LONG(x
) - FIX2LONG(y
);
93 return rb_funcall(x
, id_cmp
, 1, y
);
97 f_div(VALUE x
, VALUE y
)
99 if (FIXNUM_P(y
) && FIX2LONG(y
) == 1)
101 return rb_funcall(x
, '/', 1, y
);
105 f_gt_p(VALUE x
, VALUE y
)
107 if (FIXNUM_P(x
) && FIXNUM_P(y
))
108 return f_boolcast(FIX2LONG(x
) > FIX2LONG(y
));
109 return rb_funcall(x
, '>', 1, y
);
113 f_lt_p(VALUE x
, VALUE y
)
115 if (FIXNUM_P(x
) && FIXNUM_P(y
))
116 return f_boolcast(FIX2LONG(x
) < FIX2LONG(y
));
117 return rb_funcall(x
, '<', 1, y
);
123 f_mul(VALUE x
, VALUE y
)
126 long _iy
= FIX2LONG(y
);
128 if (TYPE(x
) == T_FLOAT
)
129 return rb_float_new(0.0);
136 else if (FIXNUM_P(x
)) {
137 long _ix
= FIX2LONG(x
);
139 if (TYPE(y
) == T_FLOAT
)
140 return rb_float_new(0.0);
147 return rb_funcall(x
, '*', 1, y
);
151 f_sub(VALUE x
, VALUE y
)
154 if (FIX2LONG(y
) == 0)
156 return rb_funcall(x
, '-', 1, y
);
182 f_equal_p(VALUE x
, VALUE y
)
184 if (FIXNUM_P(x
) && FIXNUM_P(y
))
185 return f_boolcast(FIX2LONG(x
) == FIX2LONG(y
));
186 return rb_funcall(x
, id_equal_p
, 1, y
);
194 f_negative_p(VALUE x
)
197 return f_boolcast(FIX2LONG(x
) < 0);
198 return rb_funcall(x
, '<', 1, ZERO
);
205 return f_boolcast(FIX2LONG(x
) == 0);
206 return rb_funcall(x
, id_equal_p
, 1, ZERO
);
213 return f_boolcast(FIX2LONG(x
) == 1);
214 return rb_funcall(x
, id_equal_p
, 1, ONE
);
218 f_kind_of_p(VALUE x
, VALUE c
)
220 return rb_obj_is_kind_of(x
, c
);
226 return f_kind_of_p(x
, rb_cNumeric
);
232 return f_kind_of_p(x
, rb_cInteger
);
238 return f_kind_of_p(x
, rb_cFloat
);
242 k_rational_p(VALUE x
)
244 return f_kind_of_p(x
, rb_cRational
);
250 return f_kind_of_p(x
, rb_cComplex
);
268 nucomp_s_generic_p(VALUE klass
, VALUE x
)
270 return f_generic_p(x
);
273 #define get_dat1(x) \
274 struct RComplex *dat;\
275 dat = ((struct RComplex *)(x))
277 #define get_dat2(x,y) \
278 struct RComplex *adat, *bdat;\
279 adat = ((struct RComplex *)(x));\
280 bdat = ((struct RComplex *)(y))
283 nucomp_s_new_internal(VALUE klass
, VALUE real
, VALUE image
)
285 NEWOBJ(obj
, struct RComplex
);
286 OBJSETUP(obj
, klass
, T_COMPLEX
);
295 nucomp_s_alloc(VALUE klass
)
297 return nucomp_s_new_internal(klass
, ZERO
, ZERO
);
301 nucomp_s_new_bang(int argc
, VALUE
*argv
, VALUE klass
)
305 switch (rb_scan_args(argc
, argv
, "11", &real
, &image
)) {
307 if (!k_numeric_p(real
))
312 if (!k_numeric_p(real
))
314 if (!k_numeric_p(image
))
315 image
= f_to_i(image
);
319 return nucomp_s_new_internal(klass
, real
, image
);
323 f_complex_new_bang1(VALUE klass
, VALUE x
)
325 return nucomp_s_new_internal(klass
, x
, ZERO
);
329 f_complex_new_bang2(VALUE klass
, VALUE x
, VALUE y
)
331 return nucomp_s_new_internal(klass
, x
, y
);
334 #define f_unify_p(klass) rb_const_defined(klass, id_Unify)
337 nucomp_real_check(VALUE num
)
346 rb_raise(rb_eArgError
, "not a real");
351 nucomp_s_canonicalize_internal(VALUE klass
, VALUE real
, VALUE image
)
355 if (f_zero_p(image
) && f_unify_p(klass
) &&
356 !k_float_p(real
) && !k_float_p(image
))
359 if (f_zero_p(image
) && f_unify_p(klass
))
362 else if (f_scalar_p(real
) && f_scalar_p(image
))
363 return nucomp_s_new_internal(klass
, real
, image
);
364 else if (f_scalar_p(real
)) {
367 return nucomp_s_new_internal(klass
,
368 f_sub(real
, dat
->image
),
369 f_add(ZERO
, dat
->real
));
371 else if (f_scalar_p(image
)) {
374 return nucomp_s_new_internal(klass
,
376 f_add(dat
->image
, image
));
379 get_dat2(real
, image
);
381 return nucomp_s_new_internal(klass
,
382 f_sub(adat
->real
, bdat
->image
),
383 f_add(adat
->image
, bdat
->real
));
389 nucomp_s_canonicalize(int argc
, VALUE
*argv
, VALUE klass
)
393 switch (rb_scan_args(argc
, argv
, "11", &real
, &image
)) {
399 nucomp_real_check(real
);
400 nucomp_real_check(image
);
402 return nucomp_s_canonicalize_internal(klass
, real
, image
);
407 nucomp_s_new(int argc
, VALUE
*argv
, VALUE klass
)
411 switch (rb_scan_args(argc
, argv
, "11", &real
, &image
)) {
417 nucomp_real_check(real
);
418 nucomp_real_check(image
);
420 return nucomp_s_canonicalize_internal(klass
, real
, image
);
424 f_complex_new1(VALUE klass
, VALUE x
)
426 assert(!k_complex_p(x
));
427 return nucomp_s_canonicalize_internal(klass
, x
, ZERO
);
431 f_complex_new2(VALUE klass
, VALUE x
, VALUE y
)
433 assert(!k_complex_p(x
));
434 return nucomp_s_canonicalize_internal(klass
, x
, y
);
438 nucomp_f_complex(int argc
, VALUE
*argv
, VALUE klass
)
440 return rb_funcall2(rb_cComplex
, id_convert
, argc
, argv
);
443 extern VALUE
math_atan2(VALUE obj
, VALUE x
, VALUE y
);
444 extern VALUE
math_cos(VALUE obj
, VALUE x
);
445 extern VALUE
math_cosh(VALUE obj
, VALUE x
);
446 extern VALUE
math_exp(VALUE obj
, VALUE x
);
447 extern VALUE
math_hypot(VALUE obj
, VALUE x
, VALUE y
);
448 extern VALUE
math_log(int argc
, VALUE
*argv
);
449 extern VALUE
math_sin(VALUE obj
, VALUE x
);
450 extern VALUE
math_sinh(VALUE obj
, VALUE x
);
451 extern VALUE
math_sqrt(VALUE obj
, VALUE x
);
453 #define m_atan2_bang(x,y) math_atan2(Qnil,x,y)
454 #define m_cos_bang(x) math_cos(Qnil,x)
455 #define m_cosh_bang(x) math_cosh(Qnil,x)
456 #define m_exp_bang(x) math_exp(Qnil,x)
457 #define m_hypot(x,y) math_hypot(Qnil,x,y)
462 return math_log(1, &x
);
465 #define m_sin_bang(x) math_sin(Qnil,x)
466 #define m_sinh_bang(x) math_sinh(Qnil,x)
467 #define m_sqrt_bang(x) math_sqrt(Qnil,x)
475 return m_cos_bang(x
);
476 return f_complex_new2(rb_cComplex
,
477 f_mul(m_cos_bang(dat
->real
),
478 m_cosh_bang(dat
->image
)),
479 f_mul(f_negate(m_sin_bang(dat
->real
)),
480 m_sinh_bang(dat
->image
)));
489 return m_sin_bang(x
);
490 return f_complex_new2(rb_cComplex
,
491 f_mul(m_sin_bang(dat
->real
),
492 m_cosh_bang(dat
->image
)),
493 f_mul(m_cos_bang(dat
->real
),
494 m_sinh_bang(dat
->image
)));
500 if (f_generic_p(x
)) {
501 if (!f_negative_p(x
))
502 return m_sqrt_bang(x
);
503 return f_complex_new2(rb_cComplex
, ZERO
, m_sqrt_bang(f_negate(x
)));
508 if (f_negative_p(dat
->image
))
509 return f_conjugate(m_sqrt(f_conjugate(x
)));
512 return f_complex_new2(rb_cComplex
,
513 m_sqrt_bang(f_div(f_add(a
, dat
->real
), TWO
)),
514 m_sqrt_bang(f_div(f_sub(a
, dat
->real
), TWO
)));
520 nucomp_s_polar(VALUE klass
, VALUE abs
, VALUE arg
)
522 return f_complex_new2(klass
,
523 f_mul(abs
, m_cos(arg
)),
524 f_mul(abs
, m_sin(arg
)));
528 nucomp_real(VALUE self
)
535 nucomp_image(VALUE self
)
542 nucomp_add(VALUE self
, VALUE other
)
544 switch (TYPE(other
)) {
552 return f_complex_new2(CLASS_OF(self
),
553 f_add(dat
->real
, other
), dat
->image
);
559 get_dat2(self
, other
);
561 real
= f_add(adat
->real
, bdat
->real
);
562 image
= f_add(adat
->image
, bdat
->image
);
564 return f_complex_new2(CLASS_OF(self
), real
, image
);
567 return rb_num_coerce_bin(self
, other
, '+');
572 nucomp_sub(VALUE self
, VALUE other
)
574 switch (TYPE(other
)) {
582 return f_complex_new2(CLASS_OF(self
),
583 f_sub(dat
->real
, other
), dat
->image
);
589 get_dat2(self
, other
);
591 real
= f_sub(adat
->real
, bdat
->real
);
592 image
= f_sub(adat
->image
, bdat
->image
);
594 return f_complex_new2(CLASS_OF(self
), real
, image
);
597 return rb_num_coerce_bin(self
, other
, '-');
602 nucomp_mul(VALUE self
, VALUE other
)
604 switch (TYPE(other
)) {
612 return f_complex_new2(CLASS_OF(self
),
613 f_mul(dat
->real
, other
),
614 f_mul(dat
->image
, other
));
620 get_dat2(self
, other
);
622 real
= f_sub(f_mul(adat
->real
, bdat
->real
),
623 f_mul(adat
->image
, bdat
->image
));
624 image
= f_add(f_mul(adat
->real
, bdat
->image
),
625 f_mul(adat
->image
, bdat
->real
));
627 return f_complex_new2(CLASS_OF(self
), real
, image
);
630 return rb_num_coerce_bin(self
, other
, '*');
635 nucomp_div(VALUE self
, VALUE other
)
637 switch (TYPE(other
)) {
645 return f_complex_new2(CLASS_OF(self
),
646 f_div(dat
->real
, other
),
647 f_div(dat
->image
, other
));
651 get_dat2(self
, other
);
653 if (TYPE(adat
->real
) == T_FLOAT
||
654 TYPE(adat
->image
) == T_FLOAT
||
655 TYPE(bdat
->real
) == T_FLOAT
||
656 TYPE(bdat
->image
) == T_FLOAT
) {
657 VALUE magn
= m_hypot(bdat
->real
, bdat
->image
);
658 VALUE tmp
= f_complex_new_bang2(CLASS_OF(self
),
659 f_div(bdat
->real
, magn
),
660 f_div(bdat
->image
, magn
));
661 return f_div(f_mul(self
, f_conjugate(tmp
)), magn
);
663 return f_div(f_mul(self
, f_conjugate(other
)), f_abs2(other
));
666 return rb_num_coerce_bin(self
, other
, '/');
671 nucomp_quo(VALUE self
, VALUE other
)
675 return f_div(f_complex_new2(CLASS_OF(self
),
676 f_quo(dat
->real
, ONE
),
677 f_quo(dat
->image
, ONE
)), other
);
681 nucomp_fdiv(VALUE self
, VALUE other
)
685 return f_div(f_complex_new2(CLASS_OF(self
),
687 f_to_f(dat
->image
)), other
);
691 nucomp_expt(VALUE self
, VALUE other
)
694 return f_complex_new_bang1(CLASS_OF(self
), ONE
);
696 if (k_rational_p(other
) && f_one_p(f_denominator(other
)))
697 other
= f_numerator(other
); /* good? */
699 switch (TYPE(other
)) {
702 if (f_gt_p(other
, ZERO
)) {
707 n
= f_sub(other
, ONE
);
709 while (!f_zero_p(n
)) {
712 while (a
= f_divmod(n
, TWO
),
713 f_zero_p(RARRAY_PTR(a
)[1])) {
716 x
= f_complex_new2(CLASS_OF(self
),
717 f_sub(f_mul(dat
->real
, dat
->real
),
718 f_mul(dat
->image
, dat
->image
)),
719 f_mul(f_mul(TWO
, dat
->real
), dat
->image
));
720 n
= RARRAY_PTR(a
)[0];
727 return f_expt(f_div(f_to_r(ONE
), self
), f_negate(other
));
734 r
= RARRAY_PTR(a
)[0];
735 theta
= RARRAY_PTR(a
)[1];
736 return nucomp_s_polar(CLASS_OF(self
), f_expt(r
, other
),
737 f_mul(theta
, other
));
741 VALUE a
, r
, theta
, ore
, oim
, nr
, ntheta
;
746 r
= RARRAY_PTR(a
)[0];
747 theta
= RARRAY_PTR(a
)[1];
751 nr
= m_exp_bang(f_sub(f_mul(ore
, m_log_bang(r
)),
753 ntheta
= f_add(f_mul(theta
, ore
), f_mul(oim
, m_log_bang(r
)));
754 return nucomp_s_polar(CLASS_OF(self
), nr
, ntheta
);
757 return rb_num_coerce_bin(self
, other
, id_expt
);
762 nucomp_equal_p(VALUE self
, VALUE other
)
764 switch (TYPE(other
)) {
772 return f_boolcast(f_equal_p(dat
->real
, other
) && f_zero_p(dat
->image
));
776 get_dat2(self
, other
);
778 return f_boolcast(f_equal_p(adat
->real
, bdat
->real
) &&
779 f_equal_p(adat
->image
, bdat
->image
));
782 return f_equal_p(other
, self
);
787 nucomp_coerce(VALUE self
, VALUE other
)
789 switch (TYPE(other
)) {
794 return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self
), other
), self
);
797 rb_raise(rb_eTypeError
, "%s can't be coerced into %s",
798 rb_obj_classname(other
), rb_obj_classname(self
));
803 nucomp_abs(VALUE self
)
806 return m_hypot(dat
->real
, dat
->image
);
810 nucomp_abs2(VALUE self
)
813 return f_add(f_mul(dat
->real
, dat
->real
),
814 f_mul(dat
->image
, dat
->image
));
818 nucomp_arg(VALUE self
)
821 return m_atan2_bang(dat
->image
, dat
->real
);
825 nucomp_polar(VALUE self
)
827 return rb_assoc_new(f_abs(self
), f_arg(self
));
831 nucomp_conjugate(VALUE self
)
834 return f_complex_new2(CLASS_OF(self
), dat
->real
, f_negate(dat
->image
));
839 nucomp_real_p(VALUE self
)
845 nucomp_complex_p(VALUE self
)
851 nucomp_exact_p(VALUE self
)
854 return f_boolcast(f_exact_p(dat
->real
) && f_exact_p(dat
->image
));
858 nucomp_inexact_p(VALUE self
)
860 return f_boolcast(!nucomp_exact_p(self
));
864 extern VALUE
rb_lcm(VALUE x
, VALUE y
);
867 nucomp_denominator(VALUE self
)
870 return rb_lcm(f_denominator(dat
->real
), f_denominator(dat
->image
));
874 nucomp_numerator(VALUE self
)
880 cd
= f_denominator(self
);
881 return f_complex_new2(CLASS_OF(self
),
882 f_mul(f_numerator(dat
->real
),
883 f_div(cd
, f_denominator(dat
->real
))),
884 f_mul(f_numerator(dat
->image
),
885 f_div(cd
, f_denominator(dat
->image
))));
889 nucomp_hash(VALUE self
)
892 return f_xor(dat
->real
, dat
->image
);
897 #define HAVE_SIGNBIT 1
907 return f_boolcast(signbit(RFLOAT_VALUE(x
)));
912 (void)snprintf(s
, sizeof s
, "%.0f", RFLOAT_VALUE(x
));
914 return f_boolcast(s
[0] == '-');
918 return f_negative_p(x
);
924 return f_boolcast(f_zero_p(x
) && !f_signbit(x
));
928 f_tpositive_p(VALUE x
)
930 return f_boolcast(!f_signbit(x
));
934 nucomp_to_s(VALUE self
)
936 VALUE s
, rezero
, impos
;
940 rezero
= f_tzero_p(dat
->real
);
941 impos
= f_tpositive_p(dat
->image
);
946 s
= f_to_s(dat
->real
);
947 rb_str_cat2(s
, !impos
? "-" : "+");
950 if (k_rational_p(dat
->image
) &&
951 !f_one_p(f_denominator(dat
->image
))) {
953 rb_str_concat(s
, f_to_s(rezero
? dat
->image
: f_abs(dat
->image
)));
954 rb_str_cat2(s
, ")i");
957 rb_str_concat(s
, f_to_s(rezero
? dat
->image
: f_abs(dat
->image
)));
965 nucomp_inspect(VALUE self
)
971 s
= rb_str_new2("Complex(");
972 rb_str_concat(s
, f_inspect(dat
->real
));
973 rb_str_cat2(s
, ", ");
974 rb_str_concat(s
, f_inspect(dat
->image
));
981 nucomp_marshal_dump(VALUE self
)
984 return rb_assoc_new(dat
->real
, dat
->image
);
988 nucomp_marshal_load(VALUE self
, VALUE a
)
991 dat
->real
= RARRAY_PTR(a
)[0];
992 dat
->image
= RARRAY_PTR(a
)[1];
999 rb_complex_raw(VALUE x
, VALUE y
)
1001 return nucomp_s_new_internal(rb_cComplex
, x
, y
);
1005 rb_complex_new(VALUE x
, VALUE y
)
1007 return nucomp_s_canonicalize_internal(rb_cComplex
, x
, y
);
1010 static VALUE
nucomp_s_convert(int argc
, VALUE
*argv
, VALUE klass
);
1013 rb_Complex(VALUE x
, VALUE y
)
1018 return nucomp_s_convert(2, a
, rb_cComplex
);
1022 nucomp_scalar_p(VALUE self
)
1028 nucomp_to_i(VALUE self
)
1032 if (k_float_p(dat
->image
) || !f_zero_p(dat
->image
)) {
1033 VALUE s
= f_to_s(self
);
1034 rb_raise(rb_eRangeError
, "can't convert %s into Integer",
1037 return f_to_i(dat
->real
);
1041 nucomp_to_f(VALUE self
)
1045 if (k_float_p(dat
->image
) || !f_zero_p(dat
->image
)) {
1046 VALUE s
= f_to_s(self
);
1047 rb_raise(rb_eRangeError
, "can't convert %s into Float",
1050 return f_to_f(dat
->real
);
1054 nucomp_to_r(VALUE self
)
1058 if (k_float_p(dat
->image
) || !f_zero_p(dat
->image
)) {
1059 VALUE s
= f_to_s(self
);
1060 rb_raise(rb_eRangeError
, "can't convert %s into Rational",
1063 return f_to_r(dat
->real
);
1067 nilclass_to_c(VALUE self
)
1069 return rb_complex_new1(INT2FIX(0));
1073 numeric_to_c(VALUE self
)
1075 return rb_complex_new1(self
);
1078 static VALUE comp_pat1
, comp_pat2
, a_slash
, a_dot_and_an_e
,
1079 null_string
, underscores_pat
, an_underscore
;
1081 #define DIGITS "(?:\\d(?:_\\d|\\d)*)"
1082 #define NUMERATOR "(?:" DIGITS "?\\.)?" DIGITS "(?:[eE][-+]?" DIGITS ")?"
1083 #define DENOMINATOR "[-+]?" DIGITS
1084 #define NUMBER "[-+]?" NUMERATOR "(?:\\/" DENOMINATOR ")?"
1085 #define NUMBERNOS NUMERATOR "(?:\\/" DENOMINATOR ")?"
1086 #define PATTERN1 "\\A((" NUMBER ")|\\((" NUMBER ")\\))?[iIjJ]"
1087 #define PATTERN2 "\\A(" NUMBER ")(([-+])(?:(" NUMBERNOS ")|\\((" NUMBER ")\\))?[iIjJ])?"
1092 static const char comp_pat1_source
[] = PATTERN1
;
1093 static const char comp_pat2_source
[] = PATTERN2
;
1094 static const char underscores_pat_source
[] = "_+";
1096 if (comp_pat1
) return;
1098 comp_pat1
= rb_reg_new(comp_pat1_source
, sizeof comp_pat1_source
- 1, 0);
1099 rb_global_variable(&comp_pat1
);
1101 comp_pat2
= rb_reg_new(comp_pat2_source
, sizeof comp_pat2_source
- 1, 0);
1102 rb_global_variable(&comp_pat2
);
1104 a_slash
= rb_str_new2("/");
1105 rb_global_variable(&a_slash
);
1107 a_dot_and_an_e
= rb_str_new2(".eE");
1108 rb_global_variable(&a_dot_and_an_e
);
1110 null_string
= rb_str_new2("");
1111 rb_global_variable(&null_string
);
1113 underscores_pat
= rb_reg_new(underscores_pat_source
,
1114 sizeof underscores_pat_source
- 1, 0);
1115 rb_global_variable(&underscores_pat
);
1117 an_underscore
= rb_str_new2("_");
1118 rb_global_variable(&an_underscore
);
1121 #define id_strip rb_intern("strip")
1122 #define f_strip(x) rb_funcall(x, id_strip, 0)
1124 #define id_match rb_intern("match")
1125 #define f_match(x,y) rb_funcall(x, id_match, 1, y)
1127 #define id_aref rb_intern("[]")
1128 #define f_aref(x,y) rb_funcall(x, id_aref, 1, y)
1130 #define id_post_match rb_intern("post_match")
1131 #define f_post_match(x) rb_funcall(x, id_post_match, 0)
1133 #define id_split rb_intern("split")
1134 #define f_split(x,y) rb_funcall(x, id_split, 1, y)
1136 #define id_include_p rb_intern("include?")
1137 #define f_include_p(x,y) rb_funcall(x, id_include_p, 1, y)
1139 #define id_count rb_intern("count")
1140 #define f_count(x,y) rb_funcall(x, id_count, 1, y)
1142 #define id_gsub_bang rb_intern("gsub!")
1143 #define f_gsub_bang(x,y,z) rb_funcall(x, id_gsub_bang, 2, y, z)
1146 string_to_c_internal(VALUE self
)
1152 if (RSTRING_LEN(s
) == 0)
1153 return rb_assoc_new(Qnil
, self
);
1156 VALUE m
, sr
, si
, re
, r
, i
;
1158 m
= f_match(comp_pat1
, s
);
1161 si
= f_aref(m
, INT2FIX(1));
1163 si
= rb_str_new2("1");
1165 si
= f_aref(m
, INT2FIX(2));
1167 si
= f_aref(m
, INT2FIX(3));
1169 re
= f_post_match(m
);
1172 m
= f_match(comp_pat2
, s
);
1174 return rb_assoc_new(Qnil
, self
);
1176 sr
= f_aref(m
, INT2FIX(1));
1177 if (NIL_P(f_aref(m
, INT2FIX(2))))
1182 si
= f_aref(m
, INT2FIX(3));
1183 t
= f_aref(m
, INT2FIX(4));
1185 t
= f_aref(m
, INT2FIX(5));
1187 t
= rb_str_new2("1");
1188 rb_str_concat(si
, t
);
1190 re
= f_post_match(m
);
1195 if (f_include_p(sr
, a_slash
))
1197 else if (f_gt_p(f_count(sr
, a_dot_and_an_e
), INT2FIX(0)))
1203 if (f_include_p(si
, a_slash
))
1205 else if (f_gt_p(f_count(si
, a_dot_and_an_e
), INT2FIX(0)))
1210 return rb_assoc_new(rb_complex_new2(r
, i
), re
);
1215 string_to_c_strict(VALUE self
)
1217 VALUE a
= string_to_c_internal(self
);
1218 if (NIL_P(RARRAY_PTR(a
)[0]) || RSTRING_LEN(RARRAY_PTR(a
)[1]) > 0) {
1219 VALUE s
= f_inspect(self
);
1220 rb_raise(rb_eArgError
, "invalid value for Complex: %s",
1223 return RARRAY_PTR(a
)[0];
1226 #define id_gsub rb_intern("gsub")
1227 #define f_gsub(x,y,z) rb_funcall(x, id_gsub, 2, y, z)
1230 string_to_c(VALUE self
)
1232 VALUE s
, a
, backref
;
1234 backref
= rb_backref_get();
1235 rb_match_busy(backref
);
1237 s
= f_gsub(self
, underscores_pat
, an_underscore
);
1238 a
= string_to_c_internal(s
);
1240 rb_backref_set(backref
);
1242 if (!NIL_P(RARRAY_PTR(a
)[0]))
1243 return RARRAY_PTR(a
)[0];
1244 return rb_complex_new1(INT2FIX(0));
1248 nucomp_s_convert(int argc
, VALUE
*argv
, VALUE klass
)
1250 VALUE a1
, a2
, backref
;
1252 rb_scan_args(argc
, argv
, "02", &a1
, &a2
);
1254 backref
= rb_backref_get();
1255 rb_match_busy(backref
);
1263 a1
= string_to_c_strict(a1
);
1273 a2
= string_to_c_strict(a2
);
1277 rb_backref_set(backref
);
1284 if (!k_float_p(dat
->image
) && f_zero_p(dat
->image
))
1294 if (!k_float_p(dat
->image
) && f_zero_p(dat
->image
))
1301 if (NIL_P(a2
) || f_zero_p(a2
))
1309 return nucomp_s_new(argc
, argv2
, klass
);
1315 #define id_Complex rb_intern("Complex")
1318 numeric_re(VALUE self
)
1320 return rb_Complex1(self
);
1324 numeric_im(VALUE self
)
1326 return rb_Complex2(ZERO
, self
);
1330 numeric_real(VALUE self
)
1336 numeric_image(VALUE self
)
1341 #define id_PI rb_intern("PI")
1344 numeric_arg(VALUE self
)
1346 if (!f_negative_p(self
))
1348 return rb_const_get(rb_mMath
, id_PI
);
1352 numeric_polar(VALUE self
)
1354 return rb_assoc_new(f_abs(self
), f_arg(self
));
1358 numeric_conjugate(VALUE self
)
1368 assert(fprintf(stderr
, "assert() is now active\n"));
1370 id_Unify
= rb_intern("Unify");
1371 id_abs
= rb_intern("abs");
1372 id_abs2
= rb_intern("abs2");
1373 id_arg
= rb_intern("arg");
1374 id_atan2_bang
= rb_intern("atan2!");
1375 id_cmp
= rb_intern("<=>");
1376 id_conjugate
= rb_intern("conjugate");
1377 id_convert
= rb_intern("convert");
1378 id_cos
= rb_intern("cos");
1379 id_denominator
= rb_intern("denominator");
1380 id_divmod
= rb_intern("divmod");
1381 id_equal_p
= rb_intern("==");
1382 id_exact_p
= rb_intern("exact?");
1383 id_exp_bang
= rb_intern("exp!");
1384 id_expt
= rb_intern("**");
1385 id_floor
= rb_intern("floor");
1386 id_format
= rb_intern("format");
1387 id_hypot
= rb_intern("hypot");
1388 id_idiv
= rb_intern("div");
1389 id_inspect
= rb_intern("inspect");
1390 id_log_bang
= rb_intern("log!");
1391 id_negate
= rb_intern("-@");
1392 id_new
= rb_intern("new");
1393 id_new_bang
= rb_intern("new!");
1394 id_numerator
= rb_intern("numerator");
1395 id_polar
= rb_intern("polar");
1396 id_quo
= rb_intern("quo");
1397 id_scalar_p
= rb_intern("scalar?");
1398 id_sin
= rb_intern("sin");
1399 id_sqrt
= rb_intern("sqrt");
1400 id_to_f
= rb_intern("to_f");
1401 id_to_i
= rb_intern("to_i");
1402 id_to_r
= rb_intern("to_r");
1403 id_to_s
= rb_intern("to_s");
1404 id_truncate
= rb_intern("truncate");
1406 rb_cComplex
= rb_define_class(COMPLEX_NAME
, rb_cNumeric
);
1408 rb_define_alloc_func(rb_cComplex
, nucomp_s_alloc
);
1409 rb_funcall(rb_cComplex
, rb_intern("private_class_method"), 1,
1410 ID2SYM(rb_intern("allocate")));
1412 rb_define_singleton_method(rb_cComplex
, "generic?", nucomp_s_generic_p
, 1);
1414 rb_define_singleton_method(rb_cComplex
, "new!", nucomp_s_new_bang
, -1);
1415 rb_funcall(rb_cComplex
, rb_intern("private_class_method"), 1,
1416 ID2SYM(rb_intern("new!")));
1418 rb_define_singleton_method(rb_cComplex
, "new", nucomp_s_new
, -1);
1419 rb_funcall(rb_cComplex
, rb_intern("private_class_method"), 1,
1420 ID2SYM(rb_intern("new")));
1423 rb_define_singleton_method(rb_cComplex
, "rect", nucomp_s_new
, -1);
1424 rb_define_singleton_method(rb_cComplex
, "rectangular", nucomp_s_new
, -1);
1426 rb_define_singleton_method(rb_cComplex
, "polar", nucomp_s_polar
, 2);
1428 rb_define_global_function(COMPLEX_NAME
, nucomp_f_complex
, -1);
1430 rb_undef_method(rb_cComplex
, "<");
1431 rb_undef_method(rb_cComplex
, "<=");
1432 rb_undef_method(rb_cComplex
, "<=>");
1433 rb_undef_method(rb_cComplex
, ">");
1434 rb_undef_method(rb_cComplex
, ">=");
1435 rb_undef_method(rb_cComplex
, "between?");
1436 rb_undef_method(rb_cComplex
, "divmod");
1437 rb_undef_method(rb_cComplex
, "floor");
1438 rb_undef_method(rb_cComplex
, "ceil");
1439 rb_undef_method(rb_cComplex
, "modulo");
1440 rb_undef_method(rb_cComplex
, "round");
1441 rb_undef_method(rb_cComplex
, "step");
1442 rb_undef_method(rb_cComplex
, "truncate");
1445 rb_undef_method(rb_cComplex
, "//");
1448 rb_define_method(rb_cComplex
, "real", nucomp_real
, 0);
1449 rb_define_method(rb_cComplex
, "image", nucomp_image
, 0);
1450 rb_define_method(rb_cComplex
, "imag", nucomp_image
, 0);
1452 rb_define_method(rb_cComplex
, "+", nucomp_add
, 1);
1453 rb_define_method(rb_cComplex
, "-", nucomp_sub
, 1);
1454 rb_define_method(rb_cComplex
, "*", nucomp_mul
, 1);
1455 rb_define_method(rb_cComplex
, "/", nucomp_div
, 1);
1456 rb_define_method(rb_cComplex
, "quo", nucomp_quo
, 1);
1457 rb_define_method(rb_cComplex
, "fdiv", nucomp_fdiv
, 1);
1458 rb_define_method(rb_cComplex
, "**", nucomp_expt
, 1);
1460 rb_define_method(rb_cComplex
, "==", nucomp_equal_p
, 1);
1461 rb_define_method(rb_cComplex
, "coerce", nucomp_coerce
, 1);
1463 rb_define_method(rb_cComplex
, "abs", nucomp_abs
, 0);
1465 rb_define_method(rb_cComplex
, "magnitude", nucomp_abs
, 0);
1467 rb_define_method(rb_cComplex
, "abs2", nucomp_abs2
, 0);
1468 rb_define_method(rb_cComplex
, "arg", nucomp_arg
, 0);
1469 rb_define_method(rb_cComplex
, "angle", nucomp_arg
, 0);
1470 rb_define_method(rb_cComplex
, "polar", nucomp_polar
, 0);
1471 rb_define_method(rb_cComplex
, "conjugate", nucomp_conjugate
, 0);
1472 rb_define_method(rb_cComplex
, "conj", nucomp_conjugate
, 0);
1474 rb_define_method(rb_cComplex
, "~", nucomp_conjugate
, 0); /* gcc */
1478 rb_define_method(rb_cComplex
, "real?", nucomp_real_p
, 0);
1479 rb_define_method(rb_cComplex
, "complex?", nucomp_complex_p
, 0);
1480 rb_define_method(rb_cComplex
, "exact?", nucomp_exact_p
, 0);
1481 rb_define_method(rb_cComplex
, "inexact?", nucomp_inexact_p
, 0);
1484 rb_define_method(rb_cComplex
, "numerator", nucomp_numerator
, 0);
1485 rb_define_method(rb_cComplex
, "denominator", nucomp_denominator
, 0);
1487 rb_define_method(rb_cComplex
, "hash", nucomp_hash
, 0);
1489 rb_define_method(rb_cComplex
, "to_s", nucomp_to_s
, 0);
1490 rb_define_method(rb_cComplex
, "inspect", nucomp_inspect
, 0);
1492 rb_define_method(rb_cComplex
, "marshal_dump", nucomp_marshal_dump
, 0);
1493 rb_define_method(rb_cComplex
, "marshal_load", nucomp_marshal_load
, 1);
1497 rb_define_method(rb_cComplex
, "scalar?", nucomp_scalar_p
, 0);
1498 rb_define_method(rb_cComplex
, "to_i", nucomp_to_i
, 0);
1499 rb_define_method(rb_cComplex
, "to_f", nucomp_to_f
, 0);
1500 rb_define_method(rb_cComplex
, "to_r", nucomp_to_r
, 0);
1501 rb_define_method(rb_cNilClass
, "to_c", nilclass_to_c
, 0);
1502 rb_define_method(rb_cNumeric
, "to_c", numeric_to_c
, 0);
1506 rb_define_method(rb_cString
, "to_c", string_to_c
, 0);
1508 rb_define_singleton_method(rb_cComplex
, "convert", nucomp_s_convert
, -1);
1509 rb_funcall(rb_cComplex
, rb_intern("private_class_method"), 1,
1510 ID2SYM(rb_intern("convert")));
1514 rb_define_method(rb_cNumeric
, "re", numeric_re
, 0);
1515 rb_define_method(rb_cNumeric
, "im", numeric_im
, 0);
1516 rb_define_method(rb_cNumeric
, "real", numeric_real
, 0);
1517 rb_define_method(rb_cNumeric
, "image", numeric_image
, 0);
1518 rb_define_method(rb_cNumeric
, "imag", numeric_image
, 0);
1519 rb_define_method(rb_cNumeric
, "arg", numeric_arg
, 0);
1520 rb_define_method(rb_cNumeric
, "angle", numeric_arg
, 0);
1521 rb_define_method(rb_cNumeric
, "polar", numeric_polar
, 0);
1522 rb_define_method(rb_cNumeric
, "conjugate", numeric_conjugate
, 0);
1523 rb_define_method(rb_cNumeric
, "conj", numeric_conjugate
, 0);
1525 rb_define_const(rb_cComplex
, "I",
1526 f_complex_new_bang2(rb_cComplex
, ZERO
, ONE
));