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 +