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
+