[前][次][番号順一覧][スレッド一覧]

ruby-changes:20453

From: yugui <ko1@a...>
Date: Sun, 10 Jul 2011 23:09:48 +0900 (JST)
Subject: [ruby-changes:20453] yugui:r32501: Release branch of Ruby 1.9.3.

yugui	2011-07-10 23:06:48 +0900 (Sun, 10 Jul 2011)

  New Revision: 32501

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=32501

  Log:
    Release branch of Ruby 1.9.3.

  Added directories:
    branches/ruby_1_9_3/

Index: ruby_1_9_3/complex.c
===================================================================
--- ruby_1_9_3/complex.c	(revision 0)
+++ ruby_1_9_3/complex.c	(revision 32501)
@@ -0,0 +1,1979 @@
+/*
+  complex.c: Coded by Tadayoshi Funaba 2008-2011
+
+  This implementation is based on Keiju Ishitsuka's Complex library
+  which is written in ruby.
+*/
+
+#include "ruby.h"
+#include "internal.h"
+#include <math.h>
+
+#define NDEBUG
+#include <assert.h>
+
+#define ZERO INT2FIX(0)
+#define ONE INT2FIX(1)
+#define TWO INT2FIX(2)
+
+VALUE rb_cComplex;
+
+static ID id_abs, id_abs2, id_arg, id_cmp, id_conj, id_convert,
+    id_denominator, id_divmod, id_eqeq_p, id_expt, id_fdiv,  id_floor,
+    id_idiv, id_imag, id_inspect, id_negate, id_numerator, id_quo,
+    id_real, id_real_p, id_to_f, id_to_i, id_to_r, id_to_s;
+
+#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
+
+#define binop(n,op) \
+inline static VALUE \
+f_##n(VALUE x, VALUE y)\
+{\
+    return rb_funcall(x, (op), 1, y);\
+}
+
+#define fun1(n) \
+inline static VALUE \
+f_##n(VALUE x)\
+{\
+    return rb_funcall(x, id_##n, 0);\
+}
+
+#define fun2(n) \
+inline static VALUE \
+f_##n(VALUE x, VALUE y)\
+{\
+    return rb_funcall(x, id_##n, 1, y);\
+}
+
+#define math1(n) \
+inline static VALUE \
+m_##n(VALUE x)\
+{\
+    return rb_funcall(rb_mMath, id_##n, 1, x);\
+}
+
+#define math2(n) \
+inline static VALUE \
+m_##n(VALUE x, VALUE y)\
+{\
+    return rb_funcall(rb_mMath, id_##n, 2, x, y);\
+}
+
+#define PRESERVE_SIGNEDZERO
+
+inline static VALUE
+f_add(VALUE x, VALUE y)
+{
+#ifndef PRESERVE_SIGNEDZERO
+    if (FIXNUM_P(y) && FIX2LONG(y) == 0)
+	return x;
+    else if (FIXNUM_P(x) && FIX2LONG(x) == 0)
+	return y;
+#endif
+    return rb_funcall(x, '+', 1, y);
+}
+
+inline static VALUE
+f_cmp(VALUE x, VALUE y)
+{
+    if (FIXNUM_P(x) && FIXNUM_P(y)) {
+	long c = FIX2LONG(x) - FIX2LONG(y);
+	if (c > 0)
+	    c = 1;
+	else if (c < 0)
+	    c = -1;
+	return INT2FIX(c);
+    }
+    return rb_funcall(x, id_cmp, 1, y);
+}
+
+inline static VALUE
+f_div(VALUE x, VALUE y)
+{
+    if (FIXNUM_P(y) && FIX2LONG(y) == 1)
+	return x;
+    return rb_funcall(x, '/', 1, y);
+}
+
+inline static VALUE
+f_gt_p(VALUE x, VALUE y)
+{
+    if (FIXNUM_P(x) && FIXNUM_P(y))
+	return f_boolcast(FIX2LONG(x) > FIX2LONG(y));
+    return rb_funcall(x, '>', 1, y);
+}
+
+inline static VALUE
+f_lt_p(VALUE x, VALUE y)
+{
+    if (FIXNUM_P(x) && FIXNUM_P(y))
+	return f_boolcast(FIX2LONG(x) < FIX2LONG(y));
+    return rb_funcall(x, '<', 1, y);
+}
+
+binop(mod, '%')
+
+inline static VALUE
+f_mul(VALUE x, VALUE y)
+{
+#ifndef PRESERVE_SIGNEDZERO
+    if (FIXNUM_P(y)) {
+	long iy = FIX2LONG(y);
+	if (iy == 0) {
+	    if (FIXNUM_P(x) || TYPE(x) == T_BIGNUM)
+		return ZERO;
+	}
+	else if (iy == 1)
+	    return x;
+    }
+    else if (FIXNUM_P(x)) {
+	long ix = FIX2LONG(x);
+	if (ix == 0) {
+	    if (FIXNUM_P(y) || TYPE(y) == T_BIGNUM)
+		return ZERO;
+	}
+	else if (ix == 1)
+	    return y;
+    }
+#endif
+    return rb_funcall(x, '*', 1, y);
+}
+
+inline static VALUE
+f_sub(VALUE x, VALUE y)
+{
+#ifndef PRESERVE_SIGNEDZERO
+    if (FIXNUM_P(y) && FIX2LONG(y) == 0)
+	return x;
+#endif
+    return rb_funcall(x, '-', 1, y);
+}
+
+fun1(abs)
+fun1(abs2)
+fun1(arg)
+fun1(conj)
+fun1(denominator)
+fun1(floor)
+fun1(imag)
+fun1(inspect)
+fun1(negate)
+fun1(numerator)
+fun1(real)
+fun1(real_p)
+
+inline static VALUE
+f_to_i(VALUE x)
+{
+    if (TYPE(x) == T_STRING)
+	return rb_str_to_inum(x, 10, 0);
+    return rb_funcall(x, id_to_i, 0);
+}
+inline static VALUE
+f_to_f(VALUE x)
+{
+    if (TYPE(x) == T_STRING)
+	return DBL2NUM(rb_str_to_dbl(x, 0));
+    return rb_funcall(x, id_to_f, 0);
+}
+
+fun1(to_r)
+fun1(to_s)
+
+fun2(divmod)
+
+inline static VALUE
+f_eqeq_p(VALUE x, VALUE y)
+{
+    if (FIXNUM_P(x) && FIXNUM_P(y))
+	return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
+    return rb_funcall(x, id_eqeq_p, 1, y);
+}
+
+fun2(expt)
+fun2(fdiv)
+fun2(idiv)
+fun2(quo)
+
+inline static VALUE
+f_negative_p(VALUE x)
+{
+    if (FIXNUM_P(x))
+	return f_boolcast(FIX2LONG(x) < 0);
+    return rb_funcall(x, '<', 1, ZERO);
+}
+
+#define f_positive_p(x) (!f_negative_p(x))
+
+inline static VALUE
+f_zero_p(VALUE x)
+{
+    switch (TYPE(x)) {
+      case T_FIXNUM:
+	return f_boolcast(FIX2LONG(x) == 0);
+      case T_BIGNUM:
+	return Qfalse;
+      case T_RATIONAL:
+      {
+	  VALUE num = RRATIONAL(x)->num;
+
+	  return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
+      }
+    }
+    return rb_funcall(x, id_eqeq_p, 1, ZERO);
+}
+
+#define f_nonzero_p(x) (!f_zero_p(x))
+
+inline static VALUE
+f_one_p(VALUE x)
+{
+    switch (TYPE(x)) {
+      case T_FIXNUM:
+	return f_boolcast(FIX2LONG(x) == 1);
+      case T_BIGNUM:
+	return Qfalse;
+      case T_RATIONAL:
+      {
+	  VALUE num = RRATIONAL(x)->num;
+	  VALUE den = RRATIONAL(x)->den;
+
+	  return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 1 &&
+			    FIXNUM_P(den) && FIX2LONG(den) == 1);
+      }
+    }
+    return rb_funcall(x, id_eqeq_p, 1, ONE);
+}
+
+inline static VALUE
+f_kind_of_p(VALUE x, VALUE c)
+{
+    return rb_obj_is_kind_of(x, c);
+}
+
+inline static VALUE
+k_numeric_p(VALUE x)
+{
+    return f_kind_of_p(x, rb_cNumeric);
+}
+
+inline static VALUE
+k_integer_p(VALUE x)
+{
+    return f_kind_of_p(x, rb_cInteger);
+}
+
+inline static VALUE
+k_fixnum_p(VALUE x)
+{
+    return f_kind_of_p(x, rb_cFixnum);
+}
+
+inline static VALUE
+k_bignum_p(VALUE x)
+{
+    return f_kind_of_p(x, rb_cBignum);
+}
+
+inline static VALUE
+k_float_p(VALUE x)
+{
+    return f_kind_of_p(x, rb_cFloat);
+}
+
+inline static VALUE
+k_rational_p(VALUE x)
+{
+    return f_kind_of_p(x, rb_cRational);
+}
+
+inline static VALUE
+k_complex_p(VALUE x)
+{
+    return f_kind_of_p(x, rb_cComplex);
+}
+
+#define k_exact_p(x) (!k_float_p(x))
+#define k_inexact_p(x) k_float_p(x)
+
+#define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
+#define k_exact_one_p(x) (k_exact_p(x) && f_one_p(x))
+
+#define get_dat1(x) \
+    struct RComplex *dat;\
+    dat = ((struct RComplex *)(x))
+
+#define get_dat2(x,y) \
+    struct RComplex *adat, *bdat;\
+    adat = ((struct RComplex *)(x));\
+    bdat = ((struct RComplex *)(y))
+
+inline static VALUE
+nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
+{
+    NEWOBJ(obj, struct RComplex);
+    OBJSETUP(obj, klass, T_COMPLEX);
+
+    obj->real = real;
+    obj->imag = imag;
+
+    return (VALUE)obj;
+}
+
+static VALUE
+nucomp_s_alloc(VALUE klass)
+{
+    return nucomp_s_new_internal(klass, ZERO, ZERO);
+}
+
+#if 0
+static VALUE
+nucomp_s_new_bang(int argc, VALUE *argv, VALUE klass)
+{
+    VALUE real, imag;
+
+    switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
+      case 1:
+	if (!k_numeric_p(real))
+	    real = f_to_i(real);
+	imag = ZERO;
+	break;
+      default:
+	if (!k_numeric_p(real))
+	    real = f_to_i(real);
+	if (!k_numeric_p(imag))
+	    imag = f_to_i(imag);
+	break;
+    }
+
+    return nucomp_s_new_internal(klass, real, imag);
+}
+#endif
+
+inline static VALUE
+f_complex_new_bang1(VALUE klass, VALUE x)
+{
+    assert(!k_complex_p(x));
+    return nucomp_s_new_internal(klass, x, ZERO);
+}
+
+inline static VALUE
+f_complex_new_bang2(VALUE klass, VALUE x, VALUE y)
+{
+    assert(!k_complex_p(x));
+    assert(!k_complex_p(y));
+    return nucomp_s_new_internal(klass, x, y);
+}
+
+#ifdef CANONICALIZATION_FOR_MATHN
+#define CANON
+#endif
+
+#ifdef CANON
+static int canonicalization = 0;
+
+RUBY_FUNC_EXPORTED void
+nucomp_canonicalization(int f)
+{
+    canonicalization = f;
+}
+#endif
+
+inline static void
+nucomp_real_check(VALUE num)
+{
+    switch (TYPE(num)) {
+      case T_FIXNUM:
+      case T_BIGNUM:
+      case T_FLOAT:
+      case T_RATIONAL:
+	break;
+      default:
+	if (!k_numeric_p(num) || !f_real_p(num))
+	    rb_raise(rb_eTypeError, "not a real");
+    }
+}
+
+inline static VALUE
+nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag)
+{
+#ifdef CANON
+#define CL_CANON
+#ifdef CL_CANON
+    if (k_exact_zero_p(imag) && canonicalization)
+	return real;
+#else
+    if (f_zero_p(imag) && canonicalization)
+	return real;
+#endif
+#endif
+    if (f_real_p(real) && f_real_p(imag))
+	return nucomp_s_new_internal(klass, real, imag);
+    else if (f_real_p(real)) {
+	get_dat1(imag);
+
+	return nucomp_s_new_internal(klass,
+				     f_sub(real, dat->imag),
+				     f_add(ZERO, dat->real));
+    }
+    else if (f_real_p(imag)) {
+	get_dat1(real);
+
+	return nucomp_s_new_internal(klass,
+				     dat->real,
+				     f_add(dat->imag, imag));
+    }
+    else {
+	get_dat2(real, imag);
+
+	return nucomp_s_new_internal(klass,
+				     f_sub(adat->real, bdat->imag),
+				     f_add(adat->imag, bdat->real));
+    }
+}
+
+/*
+ * call-seq:
+ *    Complex.rect(real[, imag])         ->  complex
+ *    Complex.rectangular(real[, imag])  ->  complex
+ *
+ * Returns a complex object which denotes the given rectangular form.
+ */
+static VALUE
+nucomp_s_new(int argc, VALUE *argv, VALUE klass)
+{
+    VALUE real, imag;
+
+    switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
+      case 1:
+	nucomp_real_check(real);
+	imag = ZERO;
+	break;
+      default:
+	nucomp_real_check(real);
+	nucomp_real_check(imag);
+	break;
+    }
+
+    return nucomp_s_canonicalize_internal(klass, real, imag);
+}
+
+inline static VALUE
+f_complex_new1(VALUE klass, VALUE x)
+{
+    assert(!k_complex_p(x));
+    return nucomp_s_canonicalize_internal(klass, x, ZERO);
+}
+
+inline static VALUE
+f_complex_new2(VALUE klass, VALUE x, VALUE y)
+{
+    assert(!k_complex_p(x));
+    return nucomp_s_canonicalize_internal(klass, x, y);
+}
+
+/*
+ * call-seq:
+ *    Complex(x[, y])  ->  numeric
+ *
+ * Returns x+i*y;
+ */
+static VALUE
+nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
+{
+    return rb_funcall2(rb_cComplex, id_convert, argc, argv);
+}
+
+#define imp1(n) \
+inline static VALUE \
+m_##n##_bang(VALUE x)\
+{\
+    return rb_math_##n(x);\
+}
+
+#define imp2(n) \
+inline static VALUE \
+m_##n##_bang(VALUE x, VALUE y)\
+{\
+    return rb_math_##n(x, y);\
+}
+
+imp2(atan2)
+imp1(cos)
+imp1(cosh)
+imp1(exp)
+imp2(hypot)
+
+#define m_hypot(x,y) m_hypot_bang((x),(y))
+
+static VALUE
+m_log_bang(VALUE x)
+{
+    return rb_math_log(1, &x);
+}
+
+imp1(sin)
+imp1(sinh)
+imp1(sqrt)
+
+static VALUE
+m_cos(VALUE x)
+{
+    if (f_real_p(x))
+	return m_cos_bang(x);
+    {
+	get_dat1(x);
+	return f_complex_new2(rb_cComplex,
+			      f_mul(m_cos_bang(dat->real),
+				    m_cosh_bang(dat->imag)),
+			      f_mul(f_negate(m_sin_bang(dat->real)),
+				    m_sinh_bang(dat->imag)));
+    }
+}
+
+static VALUE
+m_sin(VALUE x)
+{
+    if (f_real_p(x))
+	return m_sin_bang(x);
+    {
+	get_dat1(x);
+	return f_complex_new2(rb_cComplex,
+			      f_mul(m_sin_bang(dat->real),
+				    m_cosh_bang(dat->imag)),
+			      f_mul(m_cos_bang(dat->real),
+				    m_sinh_bang(dat->imag)));
+    }
+}
+
+#if 0
+static VALUE
+m_sqrt(VALUE x)
+{
+    if (f_real_p(x)) {
+	if (f_positive_p(x))
+	    return m_sqrt_bang(x);
+	return f_complex_new2(rb_cComplex, ZERO, m_sqrt_bang(f_negate(x)));
+    }
+    else {
+	get_dat1(x);
+
+	if (f_negative_p(dat->imag))
+	    return f_conj(m_sqrt(f_conj(x)));
+	else {
+	    VALUE a = f_abs(x);
+	    return f_complex_new2(rb_cComplex,
+				  m_sqrt_bang(f_div(f_add(a, dat->real), TWO)),
+				  m_sqrt_bang(f_div(f_sub(a, dat->real), TWO)));
+	}
+    }
+}
+#endif
+
+inline static VALUE
+f_complex_polar(VALUE klass, VALUE x, VALUE y)
+{
+    assert(!k_complex_p(x));
+    assert(!k_complex_p(y));
+    return nucomp_s_canonicalize_internal(klass,
+					  f_mul(x, m_cos(y)),
+					  f_mul(x, m_sin(y)));
+}
+
+/*
+ * call-seq:
+ *    Complex.polar(abs[, arg])  ->  complex
+ *
+ * Returns a complex object which denotes the given polar form.
+ *
+ *   Complex.polar(3, 0)           #=> (3.0+0.0i)
+ *   Complex.polar(3, Math::PI/2)  #=> (1.836909530733566e-16+3.0i)
+ *   Complex.polar(3, Math::PI)    #=> (-3.0+3.673819061467132e-16i)
+ *   Complex.polar(3, -Math::PI/2) #=> (1.836909530733566e-16-3.0i)
+ */
+static VALUE
+nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
+{
+    VALUE abs, arg;
+
+    switch (rb_scan_args(argc, argv, "11", &abs, &arg)) {
+      case 1:
+	nucomp_real_check(abs);
+	arg = ZERO;
+	break;
+      default:
+	nucomp_real_check(abs);
+	nucomp_real_check(arg);
+	break;
+    }
+    return f_complex_polar(klass, abs, arg);
+}
+
+/*
+ * call-seq:
+ *    cmp.real  ->  real
+ *
+ * Returns the real part.
+ */
+static VALUE
+nucomp_real(VALUE self)
+{
+    get_dat1(self);
+    return dat->real;
+}
+
+/*
+ * call-seq:
+ *    cmp.imag       ->  real
+ *    cmp.imaginary  ->  real
+ *
+ * Returns the imaginary part.
+ */
+static VALUE
+nucomp_imag(VALUE self)
+{
+    get_dat1(self);
+    return dat->imag;
+}
+
+/*
+ * call-seq:
+ *    -cmp  ->  complex
+ *
+ * Returns negation of the value.
+ */
+static VALUE
+nucomp_negate(VALUE self)
+{
+  get_dat1(self);
+  return f_complex_new2(CLASS_OF(self),
+			f_negate(dat->real), f_negate(dat->imag));
+}
+
+inline static VALUE
+f_addsub(VALUE self, VALUE other,
+	 VALUE (*func)(VALUE, VALUE), ID id)
+{
+    if (k_complex_p(other)) {
+	VALUE real, imag;
+
+	get_dat2(self, other);
+
+	real = (*func)(adat->real, bdat->real);
+	imag = (*func)(adat->imag, bdat->imag);
+
+	return f_complex_new2(CLASS_OF(self), real, imag);
+    }
+    if (k_numeric_p(other) && f_real_p(other)) {
+	get_dat1(self);
+
+	return f_complex_new2(CLASS_OF(self),
+			      (*func)(dat->real, other), dat->imag);
+    }
+    return rb_num_coerce_bin(self, other, id);
+}
+
+/*
+ * call-seq:
+ *    cmp + numeric  ->  complex
+ *
+ * Performs addition.
+ */
+static VALUE
+nucomp_add(VALUE self, VALUE other)
+{
+    return f_addsub(self, other, f_add, '+');
+}
+
+/*
+ * call-seq:
+ *    cmp - numeric  ->  complex
+ *
+ * Performs subtraction.
+ */
+static VALUE
+nucomp_sub(VALUE self, VALUE other)
+{
+    return f_addsub(self, other, f_sub, '-');
+}
+
+/*
+ * call-seq:
+ *    cmp * numeric  ->  complex
+ *
+ * Performs multiplication.
+ */
+static VALUE
+nucomp_mul(VALUE self, VALUE other)
+{
+    if (k_complex_p(other)) {
+	VALUE real, imag;
+
+	get_dat2(self, other);
+
+	real = f_sub(f_mul(adat->real, bdat->real),
+		     f_mul(adat->imag, bdat->imag));
+	imag = f_add(f_mul(adat->real, bdat->imag),
+		     f_mul(adat->imag, bdat->real));
+
+	return f_complex_new2(CLASS_OF(self), real, imag);
+    }
+    if (k_numeric_p(other) && f_real_p(other)) {
+	get_dat1(self);
+
+	return f_complex_new2(CLASS_OF(self),
+			      f_mul(dat->real, other),
+			      f_mul(dat->imag, other));
+    }
+    return rb_num_coerce_bin(self, other, '*');
+}
+
+inline static VALUE
+f_divide(VALUE self, VALUE other,
+	 VALUE (*func)(VALUE, VALUE), ID id)
+{
+    if (k_complex_p(other)) {
+	int flo;
+	get_dat2(self, other);
+
+	flo = (k_float_p(adat->real) || k_float_p(adat->imag) ||
+	       k_float_p(bdat->real) || k_float_p(bdat->imag));
+
+	if (f_gt_p(f_abs(bdat->real), f_abs(bdat->imag))) {
+	    VALUE r, n;
+
+	    r = (*func)(bdat->imag, bdat->real);
+	    n = f_mul(bdat->real, f_add(ONE, f_mul(r, r)));
+	    if (flo)
+		return f_complex_new2(CLASS_OF(self),
+				      (*func)(self, n),
+				      (*func)(f_negate(f_mul(self, r)), n));
+	    return f_complex_new2(CLASS_OF(self),
+				  (*func)(f_add(adat->real,
+						f_mul(adat->imag, r)), n),
+				  (*func)(f_sub(adat->imag,
+						f_mul(adat->real, r)), n));
+	}
+	else {
+	    VALUE r, n;
+
+	    r = (*func)(bdat->real, bdat->imag);
+	    n = f_mul(bdat->imag, f_add(ONE, f_mul(r, r)));
+	    if (flo)
+		return f_complex_new2(CLASS_OF(self),
+				      (*func)(f_mul(self, r), n),
+				      (*func)(f_negate(self), n));
+	    return f_complex_new2(CLASS_OF(self),
+				  (*func)(f_add(f_mul(adat->real, r),
+						adat->imag), n),
+				  (*func)(f_sub(f_mul(adat->imag, r),
+						adat->real), n));
+	}
+    }
+    if (k_numeric_p(other) && f_real_p(other)) {
+	get_dat1(self);
+
+	return f_complex_new2(CLASS_OF(self),
+			      (*func)(dat->real, other),
+			      (*func)(dat->imag, other));
+    }
+    return rb_num_coerce_bin(self, other, id);
+}
+
+#define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by 0")
+
+/*
+ * call-seq:
+ *    cmp / numeric     ->  complex
+ *    cmp.quo(numeric)  ->  complex
+ *
+ * Performs division.
+ *
+ * For example:
+ *
+ *     Complex(10.0) / 3  #=> (3.3333333333333335+(0/1)*i)
+ *     Complex(10)   / 3  #=> ((10/3)+(0/1)*i)  # not (3+0i)
+ */
+static VALUE
+nucomp_div(VALUE self, VALUE other)
+{
+    return f_divide(self, other, f_quo, id_quo);
+}
+
+#define nucomp_quo nucomp_div
+
+/*
+ * call-seq:
+ *    cmp.fdiv(numeric)  ->  complex
+ *
+ * Performs division as each part is a float, never returns a float.
+ *
+ * For example:
+ *
+ *     Complex(11,22).fdiv(3)  #=> (3.6666666666666665+7.333333333333333i)
+ */
+static VALUE
+nucomp_fdiv(VALUE self, VALUE other)
+{
+    return f_divide(self, other, f_fdiv, id_fdiv);
+}
+
+inline static VALUE
+f_reciprocal(VALUE x)
+{
+    return f_quo(ONE, x);
+}
+
+/*
+ * call-seq:
+ *    cmp ** numeric  ->  complex
+ *
+ * Performs exponentiation.
+ *
+ * For example:
+ *
+ *     Complex('i') ** 2             #=> (-1+0i)
+ *     Complex(-8) ** Rational(1,3)  #=> (1.0000000000000002+1.7320508075688772i)
+ */
+static VALUE
+nucomp_expt(VALUE self, VALUE other)
+{
+    if (k_numeric_p(other) && k_exact_zero_p(other))
+	return f_complex_new_bang1(CLASS_OF(self), ONE);
+
+    if (k_rational_p(other) && f_one_p(f_denominator(other)))
+	other = f_numerator(other); /* c14n */
+
+    if (k_complex_p(other)) {
+	get_dat1(other);
+
+	if (k_exact_zero_p(dat->imag))
+	    other = dat->real; /* c14n */
+    }
+
+    if (k_complex_p(other)) {
+	VALUE r, theta, nr, ntheta;
+
+	get_dat1(other);
+
+	r = f_abs(self);
+	theta = f_arg(self);
+
+	nr = m_exp_bang(f_sub(f_mul(dat->real, m_log_bang(r)),
+			      f_mul(dat->imag, theta)));
+	ntheta = f_add(f_mul(theta, dat->real),
+		       f_mul(dat->imag, m_log_bang(r)));
+	return f_complex_polar(CLASS_OF(self), nr, ntheta);
+    }
+    if (k_fixnum_p(other)) {
+	if (f_gt_p(other, ZERO)) {
+	    VALUE x, z;
+	    long n;
+
+	    x = self;
+	    z = x;
+	    n = FIX2LONG(other) - 1;
+
+	    while (n) {
+		long q, r;
+
+		while (1) {
+		    get_dat1(x);
+
+		    q = n / 2;
+		    r = n % 2;
+
+		    if (r)
+			break;
+
+		    x = f_complex_new2(CLASS_OF(self),
+				       f_sub(f_mul(dat->real, dat->real),
+					     f_mul(dat->imag, dat->imag)),
+				       f_mul(f_mul(TWO, dat->real), dat->imag));
+		    n = q;
+		}
+		z = f_mul(z, x);
+		n--;
+	    }
+	    return z;
+	}
+	return f_expt(f_reciprocal(self), f_negate(other));
+    }
+    if (k_numeric_p(other) && f_real_p(other)) {
+	VALUE r, theta;
+
+	if (k_bignum_p(other))
+	    rb_warn("in a**b, b may be too big");
+
+	r = f_abs(self);
+	theta = f_arg(self);
+
+	return f_complex_polar(CLASS_OF(self), f_expt(r, other),
+			       f_mul(theta, other));
+    }
+    return rb_num_coerce_bin(self, other, id_expt);
+}
+
+/*
+ * call-seq:
+ *    cmp == object  ->  true or false
+ *
+ * Returns true if cmp equals object numerically.
+ */
+static VALUE
+nucomp_eqeq_p(VALUE self, VALUE other)
+{
+    if (k_complex_p(other)) {
+	get_dat2(self, other);
+
+	return f_boolcast(f_eqeq_p(adat->real, bdat->real) &&
+			  f_eqeq_p(adat->imag, bdat->imag));
+    }
+    if (k_numeric_p(other) && f_real_p(other)) {
+	get_dat1(self);
+
+	return f_boolcast(f_eqeq_p(dat->real, other) && f_zero_p(dat->imag));
+    }
+    return f_eqeq_p(other, self);
+}
+
+/* :nodoc: */
+static VALUE
+nucomp_coerce(VALUE self, VALUE other)
+{
+    if (k_numeric_p(other) && f_real_p(other))
+	return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self), other), self);
+    if (TYPE(other) == T_COMPLEX)
+	return rb_assoc_new(other, self);
+
+    rb_raise(rb_eTypeError, "%s can't be coerced into %s",
+	     rb_obj_classname(other), rb_obj_classname(self));
+    return Qnil;
+}
+
+/*
+ * call-seq:
+ *    cmp.abs        ->  real
+ *    cmp.magnitude  ->  real
+ *
+ * Returns the absolute part of its polar form.
+ */
+static (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]