Author: jisom
Date: Fri Mar 17 15:01:26 2006
New Revision: 11920

Modified:
   trunk/src/pmc/complex.pmc
   trunk/t/pmc/complex.t

Log:
More complex work, add get_pmc_keyed_int so you can use
a complex number with sprintf now.
Add sine, cosine, and arctangent.


Modified: trunk/src/pmc/complex.pmc
==============================================================================
--- trunk/src/pmc/complex.pmc   (original)
+++ trunk/src/pmc/complex.pmc   Fri Mar 17 15:01:26 2006
@@ -434,6 +434,26 @@
 
 /*
 
+=item C<PMC* get_pmc_keyed_int (INTVAL key)>
+
+Returns the requested number (real part for C<0> and imaginary for C<1>).
+
+=cut
+
+*/
+
+    PMC* get_pmc_keyed_int (INTVAL key) {
+        PMC *ret;
+        FLOATVAL val;
+
+        ret = pmc_new(INTERP, enum_class_Float);
+        val = DYNSELF.get_number_keyed_int(key);
+        VTABLE_set_number_native(INTERP, ret, val);
+        return ret;
+    }
+
+/*
+
 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
 
 Quick hack to emulate get_real() and get_imag():
@@ -1066,6 +1086,123 @@
         return d;
     }
 
+/*
+
+=item C<METHOD PMC* sin()>
+
+Returns the sine of SELF.
+
+=cut
+
+sin(a + bi) = sin(a)cosh(b)+i*cos(a)sinh(b)
+
+sin(z) = ((e ^ zi) - (e ^ -zi)) / (2i)
+sin(a + bi) = (exp(-b) * (cos( a) + i * sin( a)) -
+               exp( b) * (cos(-a) + i * sin(-a))) / 2i
+
+*/
+
+    METHOD PMC* sin() {
+        PMC *d = pmc_new(INTERP, SELF->vtable->base_type);
+        RE(d) = sin(RE(SELF)) * cosh(IM(SELF));
+        IM(d) = cos(RE(SELF)) * sinh(IM(SELF));
+        return d;
+    }
+
+    /*
+    This takes twice as long, but is correct
+    METHOD PMC* sin() {
+        PMC *d = pmc_new(INTERP, SELF->vtable->base_type);
+        PMC *e = pmc_new(INTERP, SELF->vtable->base_type);
+        RE(d) = -IM(SELF);
+        IM(d) = RE(SELF);
+        d = Parrot_Complex_exp(INTERP, d);
+        RE(e) = IM(SELF);
+        IM(e) = -RE(SELF);
+        e = Parrot_Complex_exp(INTERP, e);
+        d = Parrot_Complex_subtract_Complex(INTERP, d, e, d);
+        RE(e) = 0.0;
+        IM(e) = 2.0;
+        d = Parrot_Complex_divide_Complex(INTERP, d, e, d);
+        return d;
+    }
+    */
+
+/*
+
+=item C<METHOD PMC* cos()>
+
+Returns the cosine of SELF.  If the imaginary part of SELF is -0.0, unlike
+Math::Complex, this will return -0.0 instead of 0.0.
+
+=cut
+
+cos(z) = ((e ^ zi) + (e ^ -zi)) / 2
+
+cos(a + bi) = (exp(-b) * (cos( a) + i * sin( a)) +
+               exp( b) * (cos(-a) + i * sin(-a))) / 2
+
+I found this equation...  But it doesn't work right.  I can't explain why the
+if statement's necessary but it is...  It works and it's fairly quick.
+
+cos(a + bi) = cos(a) * cosh(b) + i * -sin(a) * sinh(b)
+
+*/
+
+    METHOD PMC* cos() {
+        PMC *d = pmc_new(INTERP, SELF->vtable->base_type);
+        RE(d) = cos(RE(SELF)) * cosh(IM(SELF));
+        IM(d) = sin(RE(SELF)) * sinh(IM(SELF));
+        if (RE(SELF))
+            IM(d) = -IM(d);
+        return d;
+    }   
+
+    /*
+    Same as with sin, this is slower
+    METHOD PMC* cos() {
+        PMC *d = pmc_new(INTERP, SELF->vtable->base_type);
+        PMC *e = pmc_new(INTERP, SELF->vtable->base_type);
+        RE(d) = -IM(SELF);
+        IM(d) = RE(SELF);
+        d = Parrot_Complex_exp(INTERP, d);
+        RE(e) = IM(SELF);
+        IM(e) = -RE(SELF);
+        e = Parrot_Complex_exp(INTERP, e);
+        d = Parrot_Complex_add_Complex(INTERP, d, e, d);
+        RE(e) = 2.0;
+        IM(e) = 0.0;
+        d = Parrot_Complex_divide_Complex(INTERP, d, e, d);
+        return d;
+    }
+    */
+
+
+/*
+
+=item C<METHOD PMC* atan()>
+
+Returns the arctangent of SELF.
+
+=cut
+
+arctan z = i/2 ln((i+z) / (i-z))
+
+*/
+
+    METHOD PMC* atan() {
+        PMC *d = pmc_new(INTERP, SELF->vtable->base_type);
+        PMC *e = pmc_new(INTERP, SELF->vtable->base_type);
+        RE(d) = RE(SELF);
+        IM(d) = 1 + IM(SELF);
+        RE(e) = -RE(SELF);
+        IM(e) = 1 - IM(SELF);
+        d = Parrot_Complex_divide_Complex(INTERP, d, e, d);
+        d = Parrot_Complex_ln(INTERP, d);
+        RE(e) = IM(d) / -2.0;
+        IM(e) = RE(d) / 2.0;
+        return e;
+    }
 
 /*
 
@@ -1089,8 +1226,8 @@
                      VTABLE_morph(INTERP, dest, SELF->vtable->base_type);
                  else
                      dest = pmc_new(INTERP, SELF->vtable->base_type);
-                 l = Parrot_Complex_multiply_Complex(INTERP, value,
-                     Parrot_Complex_ln(INTERP, SELF), l);
+                 l = Parrot_Complex_multiply_Complex(INTERP,
+                         Parrot_Complex_ln(INTERP, SELF), value, l);
                  dest = Parrot_Complex_exp(INTERP, l);
                  return dest;
              }
@@ -1101,9 +1238,7 @@
                  else
                      dest = pmc_new(INTERP, SELF->vtable->base_type);
                  l = Parrot_Complex_multiply(INTERP,
-                     Parrot_Complex_ln(INTERP, SELF),
-                     value,
-                     l);
+                         Parrot_Complex_ln(INTERP, SELF), value, l);
                  dest = Parrot_Complex_exp(INTERP, l);
                  return dest;
              }

Modified: trunk/t/pmc/complex.t
==============================================================================
--- trunk/t/pmc/complex.t       (original)
+++ trunk/t/pmc/complex.t       Fri Mar 17 15:01:26 2006
@@ -6,7 +6,7 @@
 use warnings;
 use lib qw( . lib ../lib ../../lib );
 use Test::More;
-use Parrot::Test tests => 28;
+use Parrot::Test tests => 32;
 
 =head1 NAME
 
@@ -797,8 +797,8 @@
 .macro DoIt(val)
     c = .val
        c2 = c.ln()
-    print c2
-    print "\n"
+       print c2
+       print "\n"
 .endm
 .sub main :main
        .local pmc c, c2
@@ -819,8 +819,8 @@
 .macro DoIt(val)
     c = .val
        c2 = c.exp()
-    print c2
-    print "\n"
+       print c2
+       print "\n"
 .endm
 .sub main :main
        .local pmc c, c2
@@ -899,3 +899,106 @@
 0+0i
 OUTPUT
 
+pir_output_is(<< 'CODE', << 'OUTPUT', "sprintf with a complex");
+.macro DoIt(fmt, number)
+       c = .number
+       $S0 = sprintf .fmt, c
+       print $S0
+.endm
+.sub main :main
+       .local pmc c, c2
+       c = new .Complex
+       .DoIt("%d%+di\n", "1.35+35.1i")
+       .DoIt("%.3f%+.3fi\n", "0+3.141592653589793i")
+.end
+CODE
+1+35i
+0.000+3.142i
+OUTPUT
+
+pir_output_is(<< 'CODE', << 'OUTPUT', "sin of complex numbers");
+.macro DoIt(val)
+    c = .val
+       c2 = sin c
+       print c2
+       print "\n"
+.endm
+.sub main :main
+       .local pmc c, c2
+    c = new .Complex
+       .DoIt("i")
+       .DoIt("2i")
+       .DoIt("2+2i")
+       .DoIt("1+i")
+.end
+CODE
+0+1.1752i
+0+3.62686i
+3.42095-1.50931i
+1.29846+0.634964i
+OUTPUT
+
+pir_output_is(<< 'CODE', << 'OUTPUT', "cos of complex numbers");
+.macro DoIt(val)
+    c = .val
+       c2 = cos c
+       print c2
+       print "\n"
+.endm
+.sub main :main
+       .local pmc c, c2
+    c = new .Complex
+    c2 = new .Complex
+       .DoIt("i")
+       .DoIt("2i")
+       .DoIt("1+i")
+       .DoIt(".5+.5i")
+       .DoIt("2+2i")
+       .DoIt("-2-2i")
+       .DoIt("-2+2i")
+       .DoIt("-2")
+       .DoIt("-2-0i")
+       .DoIt("2-2i")
+.end
+CODE
+1.54308+0i
+3.7622+0i
+0.83373-0.988898i
+0.989585-0.249826i
+-1.56563-3.29789i
+-1.56563-3.29789i
+-1.56563+3.29789i
+-0.416147+0i
+-0.416147-0i
+-1.56563+3.29789i
+OUTPUT
+
+pir_output_is(<< 'CODE', << 'OUTPUT', "atan of complex numbers");
+.macro DoIt(val)
+    c = .val
+       c2 = atan c
+       print c2
+       print "\n"
+.endm
+.sub main :main
+       .local pmc c, c2
+    c = new .Complex
+    c2 = new .Complex
+       .DoIt("1")
+       .DoIt("2")
+       .DoIt("2i")
+       .DoIt("2+2i")
+       .DoIt("4")
+       .DoIt("4i")
+       .DoIt("4+4i")
+.end
+CODE
+0.785398+0i
+1.10715+0i
+-1.5708+0.549306i
+1.31122+0.238878i
+1.32582+0i
+-1.5708+0.255413i
+1.44452+0.123674i
+OUTPUT
+

Reply via email to