# New Ticket Created by  Ion Alexandru Morega 
# Please include the string:  [perl #30535]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=30535 >


whoops, forgot the file :)
---------
This is the new classes/complex.pmc, tests included. It supports string
parsing (in the form "a + bi", see the docs for more), string-keyed
access to "real" and "imag" and simple numerical operations. However,
the function get_number (it should return the modulus) is not
implemented, because I couldn't find sqrt() anywhere. Is it OK if I use
the one in the standard library?

enjoy,
alexm


diff -rNu parrot/MANIFEST my_parrot/MANIFEST
--- parrot/MANIFEST	2004-06-27 18:00:22.000000000 +0300
+++ my_parrot/MANIFEST	2004-06-29 22:03:25.000000000 +0300
@@ -33,6 +33,7 @@
 classes/bigint.pmc                                []
 classes/boolean.pmc                               []
 classes/closure.pmc                               []
+classes/complex.pmc                               []
 classes/compiler.pmc                              []
 classes/continuation.pmc                          []
 classes/coroutine.pmc                             []
@@ -2714,6 +2715,7 @@
 t/pmc/array.t                                     []
 t/pmc/bigint.t                                    []
 t/pmc/boolean.t                                   []
+t/pmc/complex.t                                   []
 t/pmc/coroutine.t                                 []
 t/pmc/delegate.t                                  []
 t/pmc/env.t                                       []
diff -rNu parrot/classes/complex.pmc my_parrot/classes/complex.pmc
--- parrot/classes/complex.pmc	1970-01-01 02:00:00.000000000 +0200
+++ my_parrot/classes/complex.pmc	2004-06-29 22:01:57.000000000 +0300
@@ -0,0 +1,632 @@
+/*
+Copyright: 2003 The Perl Foundation.  All Rights Reserved.
+$Id: string.pmc,v 1.0 2004/06/21 20:31:57 alexm Exp $
+
+=head1 NAME
+
+classes/complex.pmc - Complex Numbers PMC Class
+
+=head1 DESCRIPTION
+
+C<Complex> provides a representation of complex numbers. It handles
+string parsing/generating and basic mathematical operations.
+
+=head2 Functions
+
+=over 4
+
+=cut
+
+*/
+
+#include "parrot/parrot.h"
+
+
+#define RE(obj) (((FLOATVAL*)PMC_struct_val(obj))[0])
+#define IM(obj) (((FLOATVAL*)PMC_struct_val(obj))[1])
+
+
+/*
+
+=item C<static void
+complex_parse_string (Parrot_Interp interp,
+        FLOATVAL *re, FLOATVAL *im, STRING *value)>
+
+Parses the string in C<value> to produce a complex number, represented by the real
+(C<*re>) and imaginary (C<*im>) parts. Raises an exception if it cannot understand
+the string.
+The string should be of the form C<a+bi> with optional spaces around C<+> and before C<i>. You can also use C<j> instead of C<i>.
+
+=cut
+
+*/
+
+static void
+complex_parse_string (Parrot_Interp interp,
+        FLOATVAL *re, FLOATVAL *im, STRING *value) {
+    char *str;
+    INTVAL first_num_length, second_num_length;
+    INTVAL first_num_minus, second_num_minus, i;
+    char *first_num_offset, *second_num_offset, *t;
+    STRING *S;
+
+    t = str = string_to_cstring(interp, value);
+    i = 0;
+    first_num_offset = str;
+    first_num_minus = second_num_minus = 0;
+
+    /* walk the string and identify the real and imaginary parts */
+
+    if(*t == '-') {
+        /* first number is negative */
+        t++;
+        first_num_minus = 1;
+        if(*t == ' ') t++; /* allow for an optional space */
+        first_num_offset = t;
+    }
+    while(*t >= '0' && *t <= '9') t++; /* skip digits */
+    if(*t == '.') {
+        /* this number has a decimal point */
+        t++;
+        while(*t >= '0' && *t <= '9') t++; /* skip digits */
+    }
+    /* save the length of the real part */
+    first_num_length = t - first_num_offset;
+
+    if(*t == 0) {
+        /* end of string; we only have a real part */
+        second_num_length = 0;
+    }
+    else if( (*t == 'i' || *t == 'j') && *(t+1) == 0 ) {
+        /* there is only an imaginary part, so the first number was
+            actually the imaginary part */
+        second_num_length = first_num_length;
+        first_num_length = 0;
+        second_num_offset = first_num_offset;
+        second_num_minus = first_num_minus;
+        /* this is useful if there is no number for
+            the imaginary part, like in "-i" */
+        i = 1;
+    }
+    else {
+        if(*t == ' ') t++; /* skip an optional space */
+        /* expect "+" or "-" and the imaginary part */
+        if(*t == '+' || *t == '-') {
+            second_num_minus = (*t == '-'); /* save the sign */
+            t++;
+            if(*t == ' ') t++; /* skip another optional space */
+
+            /* save the beginning of the imaginary part */
+            second_num_offset = t;
+            while(*t >= '0' && *t <= '9') t++; /* skip digits */
+            if(*t == '.') {
+                /* this number has a decimal point */
+                t++;
+                while(*t >= '0' && *t <= '9') t++; /* skip digits */
+            }
+            /* save the length of the imaginary part */
+            second_num_length = t - second_num_offset;
+            
+            if(*t == ' ') t++; /* allow for one more optional space */
+            
+            /* verify that the string ends properly */
+            if( (*t != 'i' && *t != 'j') || (*(t+1) != 0) ) {
+                /* imaginary part does not end in 'i' or 'j' */
+                internal_exception(INVALID_STRING_REPRESENTATION,
+                    "Complex: malformed string\n");
+                first_num_length = second_num_length = 0;
+            }
+            /* this is useful if there is no number for the
+                imaginary part, like in "2+i" */
+            i = 1;
+
+            /* all is OK, save the number */
+        }
+        else {
+            /* "+" or "-" not found: error */
+            internal_exception(INVALID_STRING_REPRESENTATION,
+                "Complex: malformed string\n");
+            first_num_length = second_num_length = 0;
+        }
+    }
+
+    /* now we have the offsets and the lengths;
+        we turn them into float values */
+
+    if(first_num_length) {
+        /* there is a real part, interpret it */
+        S = string_from_cstring(interp,
+                first_num_offset, first_num_length);
+        *re = string_to_num(interp, S);
+    }
+    else {
+        /* consider the real part 0.0 */
+        *re = 0.0;
+    }
+
+    if(second_num_length) {
+        /* there is an imaginary part, interpret it */
+        S = string_from_cstring(interp,
+                second_num_offset, second_num_length);
+        *im = string_to_num(interp, S);
+    }
+    else {
+        /* consider the imaginary part 0.0 */
+        if(i) /* the string was something like "1+i" */
+            *im = 1.0;
+        else
+            *im = 0.0;
+    }
+    if(first_num_minus) *re = - *re;
+    if(second_num_minus) *im = - *im;
+
+    string_cstring_free(str);
+}
+
+/*
+
+=item C<static FLOATVAL*
+complex_locate_keyed_num(Parrot_Interp interp, PMC* self, STRING *key)>
+
+Interpret the string C<key>; valid keys are C<real> and C<imag>,
+representing the real and imaginary parts of the complex number.
+
+=cut
+
+*/
+
+static FLOATVAL*
+complex_locate_keyed_num(Parrot_Interp interp, PMC* self, STRING *key) {
+    /* do imag first since real can be read much faster anyway */
+    STRING *imag = string_from_cstring(interp, "imag", 4);
+    if(0 == string_equal(interp, key, imag))
+        return &IM(self);
+    STRING *real = string_from_cstring(interp, "real", 4);
+    if(0 == string_equal(interp, key, real))
+        return &RE(self);
+    internal_exception(KEY_NOT_FOUND,
+        "Complex: key is neither 'real' or 'imag'\n");
+    return NULL;
+}
+
+pmclass Complex {
+
+/*
+
+=back
+
+=head2 Methods
+
+=over 4
+
+=item C<void init()>
+
+Initializes the complex number with the value 0+0i.
+
+=item C<void init_pmc (PMC* initializer)>
+
+Initializes the complex number with the specified values.
+(not implemented)
+
+=item C<void destroy ()>
+
+Cleans up.
+
+=item C<PMC* clone ()>
+
+Creates an identical copy of the complex number.
+
+=cut
+
+*/
+
+    void init () {
+        /* XXX should check if mem_sys_allocate failed */
+        FLOATVAL* data = (FLOATVAL*)mem_sys_allocate(2 * sizeof(FLOATVAL));
+        PMC_struct_val(SELF) = data;
+        PObj_active_destroy_SET(SELF);
+        RE(SELF) = IM(SELF) = 0.0;
+    }
+
+    void init_pmc (PMC* initializer) {
+        /* XXX not implemented */
+        DYNSELF.init();
+    }
+
+    void destroy () {
+        mem_sys_free(PMC_struct_val(SELF));
+    }
+
+    void morph (INTVAL type) {
+        if (SELF->vtable->base_type == type)
+            return;
+        SUPER(type);
+    }
+
+    PMC* clone () {
+        PMC* dest = pmc_new_noinit(INTERP, SELF->vtable->base_type);
+        FLOATVAL* data = (FLOATVAL*)mem_sys_allocate(2 * sizeof(FLOATVAL));
+        PMC_struct_val(dest) = data;
+        PObj_active_destroy_SET(dest);
+        RE(dest) = RE(SELF);
+        IM(dest) = IM(SELF);
+        return dest;
+    }
+
+/*
+
+=item C<INTVAL get_integer ()>
+
+Returns the modulus of the complex number as an integer.
+
+=item C<FLOATVAL get_number ()>
+
+Returns the modulus of the complex number.
+
+=item C<STRING* get_string ()>
+
+Returns the complex number as a string in the form C<a+bi>.
+
+=item C<INTVAL get_bool ()>
+
+Returns true if the complex number is non-zero.
+
+=cut
+
+*/
+
+    INTVAL get_integer () {
+        return (INTVAL)(DYNSELF.get_number());
+    }
+
+    FLOATVAL get_number () {
+        /* XXX calculate modulus */
+        return (FLOATVAL)0;
+    }
+
+    STRING* get_string () {
+        STRING *s;
+        if(IM(SELF) >= 0)
+            s = Parrot_sprintf_c(INTERP,
+                    "%vg+%vgi", RE(SELF), IM(SELF));
+        else
+            s = Parrot_sprintf_c(INTERP,
+                    "%vg-%vgi", RE(SELF), -IM(SELF));
+        return s;
+    }
+
+    INTVAL get_bool () {
+        return (INTVAL)(RE(SELF) != 0.0 || IM(SELF) != 0.0);
+    }
+
+/*
+
+=item C<INTVAL get_integer_keyed (PMC* key)>
+
+=item C<INTVAL get_integer_keyed_str (STRING* key)>
+
+=item C<FLOATVAL get_number_keyed (PMC* key)>
+
+=item C<FLOATVAL get_number_keyed_str (STRING* key)>
+
+=item C<PMC* get_pmc_keyed (PMC* key)>
+
+=item C<PMC* get_pmc_keyed_str (STRING* key)>
+
+Returns the requested number (real part for C<real> and imaginary for C<imag>).
+
+=cut
+
+*/
+
+    INTVAL get_integer_keyed (PMC* key) {
+        STRING* s = VTABLE_get_string(INTERP, key);
+        return DYNSELF.get_integer_keyed_str(s);
+    }
+
+    INTVAL get_integer_keyed_str (STRING* key) {
+        return (INTVAL)(DYNSELF.get_number_keyed_str(key));
+    }
+
+    FLOATVAL get_number_keyed (PMC* key) {
+        STRING* s = VTABLE_get_string(INTERP, key);
+        return DYNSELF.get_number_keyed_str(s);
+    }
+
+    FLOATVAL get_number_keyed_str (STRING* key) {
+        FLOATVAL *num = complex_locate_keyed_num(INTERP, SELF, key);
+        if(num)
+            return *num;
+        return 0.0;
+    }
+
+    PMC* get_pmc_keyed (PMC* key) {
+        STRING* s = VTABLE_get_string(INTERP, key);
+        return DYNSELF.get_pmc_keyed_str(s);
+    }
+
+    PMC* get_pmc_keyed_str (STRING* key) {
+        PMC *ret;
+        FLOATVAL val;
+
+        ret = pmc_new(INTERP, enum_class_Float);
+        val = DYNSELF.get_number_keyed_str(key);
+        VTABLE_set_number_native(INTERP, ret, val);
+        return ret;
+    }
+
+/*
+
+=item C<void set_string_native (STRING* value)>
+
+Parses the string C<value> into a complex number; raises an exception on failure.
+
+=item C<void set_pmc (PMC* value)>
+
+if C<value> is a Complex PMC then the complex number is set to its value; otherwise
+C<value>'s string representation is parsed with C<set_string_native()>.
+
+=item C<void set_integer_native (INTVAL value)>
+
+=item C<void set_number_native (FLOATVAL value)>
+
+Sets the real part of the complex number to C<value> and the imaginary
+part to C<0.0>
+
+=cut
+
+*/
+
+    void set_string_native (STRING* value) {
+        complex_parse_string(INTERP, &RE(SELF), &IM(SELF), value);
+    }
+
+    void set_pmc (PMC* value) {
+        if(value->vtable->base_type == enum_class_Complex) {
+            RE(SELF) = RE(value);
+            IM(SELF) = IM(value);
+        }
+        else {
+            DYNSELF.set_string_native(VTABLE_get_string(INTERP, value));
+        }
+    }
+
+    void set_integer_native (INTVAL value) {
+        DYNSELF.set_number_native(value);
+    }
+
+    void set_number_native (FLOATVAL value) {
+        RE(SELF) = value;
+        IM(SELF) = 0.0;
+    }
+
+/*
+
+=item C<void set_integer_keyed (PMC* key, INTVAL value)>
+
+=item C<void set_integer_keyed_str (STRING* key, INTVAL value)>
+
+=item C<void set_number_keyed (PMC* key, FLOATVAL value)>
+
+=item C<void set_number_keyed_str (STRING* key, FLOATVAL value)>
+
+=item C<void set_pmc_keyed (PMC* key, PMC* value)>
+
+=item C<void set_pmc_keyed_str (STRING* key, PMC* value)>
+
+Sets the requested number (real part for C<real> and imaginary for C<imag>)
+to C<value>.
+
+=cut
+
+*/
+
+    void set_integer_keyed (PMC* key, INTVAL value) {
+        DYNSELF.set_number_keyed(key, value);
+    }
+
+    void set_integer_keyed_str (STRING* key, INTVAL value) {
+        DYNSELF.set_number_keyed_str(key, value);
+    }
+
+    void set_number_keyed (PMC* key, FLOATVAL value) {
+        STRING* s = VTABLE_get_string(INTERP, key);
+        return DYNSELF.set_number_keyed_str(s, value);
+    }
+
+    void set_number_keyed_str (STRING* key, FLOATVAL value) {
+        FLOATVAL *num = complex_locate_keyed_num(INTERP, SELF, key);
+        if(num)
+            *num = value;
+    }
+
+    void set_pmc_keyed (PMC* key, PMC* value) {
+        FLOATVAL f = VTABLE_get_number(INTERP, value);
+        DYNSELF.set_number_keyed(key, f);
+    }
+
+    void set_pmc_keyed_str (STRING* key, PMC* value) {
+        FLOATVAL f = VTABLE_get_number(INTERP, value);
+        DYNSELF.set_number_keyed_str(key, f);
+    }
+
+/*
+
+=item C<void add (PMC* value, PMC* dest)>
+
+=item C<void add_int (INTVAL value, PMC* dest)>
+
+=item C<void add_float (FLOATVAL value, PMC* dest)>
+
+Adds C<value> to the complex number, placing the result in C<dest>.
+
+=cut
+
+*/
+
+    void add (PMC* value, PMC* dest) {
+        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        RE(dest) = RE(SELF) + RE(value);
+        IM(dest) = IM(SELF) + IM(value);
+    }
+
+    void add_int (INTVAL value, PMC* dest) {
+        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        RE(dest) = RE(SELF) + value;
+        IM(dest) = IM(SELF);
+    }
+
+    void add_float (FLOATVAL value, PMC* dest) {
+        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        RE(dest) = RE(SELF) + value;
+        IM(dest) = IM(SELF);
+    }
+
+/*
+
+=item C<void subtract (PMC* value, PMC* dest)>
+
+=item C<void subtract_int (INTVAL value, PMC* dest)>
+
+=item C<void subtract_float (FLOATVAL value, PMC* dest)>
+
+Subtracts C<value> from the complex number, placing the result in C<dest>.
+
+=cut
+
+*/
+
+    void subtract (PMC* value, PMC* dest) {
+        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        RE(dest) = RE(SELF) - RE(value);
+        IM(dest) = IM(SELF) - IM(value);
+    }
+
+    void subtract_int (INTVAL value, PMC* dest) {
+        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        RE(dest) = RE(SELF) - value;
+        IM(dest) = IM(SELF);
+    }
+
+    void subtract_float (FLOATVAL value, PMC* dest) {
+        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        RE(dest) = RE(SELF) - value;
+        IM(dest) = IM(SELF);
+    }
+
+/*
+
+=item C<void multiply (PMC* value, PMC* dest)>
+
+=item C<void multiply_int (INTVAL value, PMC* dest)>
+
+=item C<void multiply_float (FLOATVAL value, PMC* dest)>
+
+Multiplies the complex number with C<value>, placing the result in C<dest>.
+
+=cut
+
+*/
+
+    void multiply (PMC* value, PMC* dest) {
+        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        FLOATVAL re = RE(SELF) * RE(value) - IM(SELF) * IM(value);
+        FLOATVAL im = IM(SELF) * RE(value) + RE(SELF) * IM(value);
+        RE(dest) = re;
+        IM(dest) = im;
+    }
+
+    void multiply_int (INTVAL value, PMC* dest) {
+        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        RE(dest) = RE(SELF) * value;
+        IM(dest) = IM(SELF) * value;
+    }
+
+    void multiply_float (FLOATVAL value, PMC* dest) {
+        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        RE(dest) = RE(SELF) * value;
+        IM(dest) = IM(SELF) * value;
+    }
+
+/*
+
+=item C<void divide (PMC* value, PMC* dest)>
+
+=item C<void divide_int (INTVAL value, PMC* dest)>
+
+=item C<void divide_float (FLOATVAL value, PMC* dest)>
+
+Divide the complex number by C<value>, placing the result in C<dest>.
+
+=cut
+
+*/
+
+    void divide (PMC* value, PMC* dest) {
+        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        /* a little speed optimisation: cache an intermediate number;
+            i'm not sure the compiler does this */
+        FLOATVAL mod = (RE(value) * RE(value) + IM(value) * IM(value));
+
+        FLOATVAL re =
+            (RE(SELF) * RE(value) + IM(SELF) * IM(value)) / mod;
+
+        FLOATVAL im =
+            (IM(SELF) * RE(value) - RE(SELF) * IM(value)) / mod;
+
+        RE(dest) = re;
+        IM(dest) = im;
+    }
+
+    void divide_int (INTVAL value, PMC* dest) {
+        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        RE(dest) = RE(SELF) / value;
+        IM(dest) = IM(SELF) / value;
+    }
+
+    void divide_float (FLOATVAL value, PMC* dest) {
+        VTABLE_morph(INTERP, dest, enum_class_Complex);
+        RE(dest) = RE(SELF) / value;
+        IM(dest) = IM(SELF) / value;
+    }
+
+/*
+
+=item C<INTVAL is_equal (PMC* value)>
+
+Compares the complex number with C<value> and returs true if they are equal.
+
+=cut
+
+*/
+
+    INTVAL is_equal (PMC* value) {
+        if(value->vtable->base_type == enum_class_Complex)
+            return (INTVAL)(
+                    RE(SELF) == RE(value) &&
+                    IM(SELF) == IM(value)
+                );
+        if(IM(SELF) != 0.0)
+            return (INTVAL)0;
+        return (RE(SELF) == VTABLE_get_number(INTERP, value));
+    }
+
+}
+
+/*
+
+=back
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+*/
diff -rNu parrot/t/pmc/complex.t my_parrot/t/pmc/complex.t
--- parrot/t/pmc/complex.t	1970-01-01 02:00:00.000000000 +0200
+++ my_parrot/t/pmc/complex.t	2004-06-29 22:02:05.000000000 +0300
@@ -0,0 +1,519 @@
+#! perl -w
+# Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
+# $Id: float.t,v 1.3 2004/03/08 00:20:09 chromatic Exp $
+
+=head1 NAME
+
+t/pmc/complex.t - Complex Numbers
+
+=head1 SYNOPSIS
+
+	% perl t/pmc/complex.t
+
+=head1 DESCRIPTION
+
+Tests the Complex PMC.
+
+=cut
+
+use Parrot::Test tests => 10;
+use Test::More;
+
+my $fp_equality_macro = <<'ENDOFMACRO';
+.macro fp_eq (	J, K, L )
+	save	N0
+	save	N1
+	save	N2
+
+	set	N0, .J
+	set	N1, .K
+	sub	N2, N1,N0
+	abs	N2, N2
+	gt	N2, 0.000001, .$FPEQNOK
+
+	restore N2
+	restore	N1
+	restore	N0
+	branch	.L
+.local $FPEQNOK:
+	restore N2
+	restore	N1
+	restore	N0
+.endm
+.macro fp_ne(	J,K,L)
+	save	N0
+	save	N1
+	save	N2
+
+	set	N0, .J
+	set	N1, .K
+	sub	N2, N1,N0
+	abs	N2, N2
+	lt	N2, 0.000001, .$FPNENOK
+
+	restore	N2
+	restore	N1
+	restore	N0
+	branch	.L
+.local $FPNENOK:
+	restore	N2
+	restore	N1
+	restore	N0
+.endm
+ENDOFMACRO
+
+
+output_is(<<'CODE', <<'OUTPUT', "String parsing");
+    new P0, .Complex
+    new P1, .String
+
+	set P0, "4"
+	print P0
+    print "\n"
+
+	set P0, "3.14"
+	print P0
+    print "\n"
+
+	set P0, ".5"
+	print P0
+    print "\n"
+
+	set P0, "-13"
+	print P0
+    print "\n"
+
+	set P0, "-.3"
+	print P0
+    print "\n"
+
+	set P0, "i"
+	print P0
+    print "\n"
+
+	set P0, "-i"
+	print P0
+    print "\n"
+
+	set P0, ".3i"
+	print P0
+    print "\n"
+
+	set P0, "2 + 3i"
+	print P0
+    print "\n"
+
+	set P0, "4 + 3.5i"
+	print P0
+    print "\n"
+
+	set P0, "2 + .1 i"
+	print P0
+    print "\n"
+
+	set P0, "10 - i"
+	print P0
+    print "\n"
+
+	set P0, "5 - .3i"
+	print P0
+    print "\n"
+
+	set P1, "-4-i"
+	assign P0, P1
+	print P0
+    print "\n"
+
+	set P1, "- 20 - .5 i"
+	assign P0, P1
+	print P0
+    print "\n"
+
+	set P1, "-13 +2i"
+	assign P0, P1
+	print P0
+    print "\n"
+
+	end
+CODE
+4+0i
+3.14+0i
+0.5+0i
+-13+0i
+-0.3+0i
+0+1i
+0-1i
+0+0.3i
+2+3i
+4+3.5i
+2+0.1i
+10-1i
+5-0.3i
+-4-1i
+-20-0.5i
+-13+2i
+OUTPUT
+
+output_is(<<'CODE', <<'OUTPUT', "add");
+	new P0, .Complex
+	new P1, .Complex
+	new P2, .Float
+
+    set P0, "1 + i"
+    add P0, P0, P0
+    print P0
+    print "\n"
+
+    set P0, "1 - i"
+    set P1, "1 + i"
+    add P0, P0, P1
+    print P0
+    print "\n"
+    print P1
+    print "\n"
+
+    set P0, "-i"
+    set P1, "1"
+    add P1, P0, P1
+    print P0
+    print "\n"
+    print P1
+    print "\n"
+
+#    set P0, "2 + i"
+#    set P2, 3.3
+#    add P1, P0, P2
+#    print P1
+#    print "\n"
+
+    set P0, "3 + 5i"
+    add P1, P0, 2
+    print P1
+    print "\n"
+
+    set P0, "2 + 2i"
+    add P1, P0, -2.0
+    print P1
+    print "\n"
+
+    end
+CODE
+2+2i
+2+0i
+1+1i
+0-1i
+1-1i
+5+5i
+0+2i
+OUTPUT
+
+output_is(<<'CODE', <<'OUTPUT', "substract");
+	new P0, .Complex
+	new P1, .Complex
+	new P2, .Float
+
+    set P0, "1 + i"
+    sub P0, P0, P0
+    print P0
+    print "\n"
+
+    set P0, "1 - i"
+    set P1, "1 + i"
+    sub P0, P0, P1
+    print P0
+    print "\n"
+    print P1
+    print "\n"
+
+    set P0, "-i"
+    set P1, "1"
+    sub P1, P0, P1
+    print P0
+    print "\n"
+    print P1
+    print "\n"
+
+#    set P0, "1 - 4i"
+#    set P2, -1.0
+#    sub P1, P0, P2
+#    print P1
+#    print "\n"
+
+    set P0, "- 2 - 2i"
+    sub P1, P0, -4
+    print P1
+    print "\n"
+
+    set P0, "3 + i"
+    sub P1, P0, 1.2
+    print P1
+    print "\n"
+
+    end
+CODE
+0+0i
+0-2i
+1+1i
+0-1i
+-1-1i
+2-2i
+1.8+1i
+OUTPUT
+
+output_is(<<'CODE', <<'OUTPUT', "multiply");
+	new P0, .Complex
+	new P1, .Complex
+	new P2, .Float
+
+    set P0, "2 + 3i"
+    mul P0, P0, P0
+    print P0
+    print "\n"
+
+    set P0, "5 - 2i"
+    set P1, "5 + 2i"
+    mul P0, P0, P1
+    print P0
+    print "\n"
+    print P1
+    print "\n"
+
+    set P0, "3i"
+    set P1, "2 - i"
+    mul P1, P0, P1
+    print P0
+    print "\n"
+    print P1
+    print "\n"
+
+#    set P0, "2 - 2i"
+#    set P2, 0.5
+#    mul P1, P0, P2
+#    print P1
+#    print "\n"
+
+    set P0, "1 - i"
+    mul P1, P0, 2
+    print P1
+    print "\n"
+
+    set P0, "-1 + i"
+    mul P1, P0, -1.0
+    print P1
+    print "\n"
+
+    end
+CODE
+-5+12i
+29+0i
+5+2i
+0+3i
+3+6i
+2-2i
+1-1i
+OUTPUT
+
+output_is(<<'CODE', <<'OUTPUT', "divide");
+	new P0, .Complex
+	new P1, .Complex
+	new P2, .Float
+
+    set P0, "2 + 3i"
+    div P0, P0, P0
+    print P0
+    print "\n"
+
+    set P0, "3 + 5i"
+    set P1, "5 - 3i"
+    div P0, P0, P1
+    print P0
+    print "\n"
+    print P1
+    print "\n"
+
+    set P0, "25"
+    set P1, "3 + 4i"
+    div P1, P0, P1
+    print P0
+    print "\n"
+    print P1
+    print "\n"
+
+#    set P0, "-3 + 6i"
+#    set P2, 3.0
+#    div P1, P0, P2
+#    print P1
+#    print "\n"
+
+    set P0, "-2 + 3i"
+    div P1, P0, 2
+    print P1
+    print "\n"
+
+    set P0, "2 - 3i"
+    div P1, P0, 0.5
+    print P1
+    print "\n"
+
+    end
+CODE
+1+0i
+0+1i
+5-3i
+25+0i
+3-4i
+-1+1.5i
+4-6i
+OUTPUT
+
+SKIP: {
+  skip("modulus not implemented", 1);
+output_is(<<'CODE', <<'OUTPUT', "get int/num/bool");
+        new P0, .Complex
+        set P0, "1.6 - .9i"
+        print P0
+        print "\n"
+
+        set I0, P0
+        print I0
+        print "\n"
+
+        set N0, P0
+        print N0
+        print "\n"
+
+        if P0, TRUE
+        print "not "
+TRUE:   print "true\n"
+
+        set P0, "0"
+        unless P0, FALSE
+        print "not "
+FALSE:  print "false\n"
+
+        end
+CODE
+1.6-0.9i
+2
+2.5
+true
+false
+OUTPUT
+}
+
+output_is(<<"CODE", <<'OUTPUT', "get keyed");
[EMAIL PROTECTED] $fp_equality_macro ]}
+        new P0, .Complex
+        new P1, .String
+        set P0, "- 3.3 + 1.2i"
+        set P1, "imag"
+
+        set N0, P0["real"]
+        set N1, P0["imag"]
+        set N2, P0[P1]
+        print "N0 "
+        .fp_ne( N0, -3.3, BAD1)
+        print "N1 "
+        .fp_ne( N1, 1.2, BAD1)
+        print "N2 "
+        .fp_ne( N2, 1.2, BAD1)
+        branch OK1
+
+BAD1:   print "not "
+OK1:    print "OK\\n"
+
+        set P2, P0["real"]
+        set P3, P0[P1]
+        print P2
+        print "\\n"
+        print P3
+        print "\\n"
+
+        set I0, P0["real"]
+        set I1, P0[P1]
+        print I0
+        print "\\n"
+        print I1
+        print "\\n"
+
+        end
+CODE
+N0 N1 N2 OK
+-3.3
+1.2
+-3
+1
+OUTPUT
+
+output_is(<<'CODE', <<'OUTPUT', "set int/num");
+    new P0, .Complex
+
+    set P0, "3 + 4i"
+    set P0, -2
+    print P0
+    print "\n"
+
+    set P0, "2 + 5i"
+    set P0, .4
+    print P0
+    print "\n"
+
+    end
+CODE
+-2+0i
+0.4+0i
+OUTPUT
+
+output_is(<<'CODE', <<'OUTPUT', "set keyed");
+    new P0, .Complex
+    new P1, .String
+    new P2, .String
+    set P1, "real"
+
+    set P0[P1], 1
+    set P0["imag"], 4
+    print P0
+    print "\n"
+
+    set P0[P1], 3.2
+    set P0["imag"], -2.3
+    print P0
+    print "\n"
+
+    set P2, ".5"
+    set P0[P1], P2
+    set P2, 6
+    set P0["imag"], P2
+    print P0
+    print "\n"
+
+    end
+CODE
+1+4i
+3.2-2.3i
+0.5+6i
+OUTPUT
+
+output_is(<<'CODE', <<'OUTPUT', "is_equal");
+    new P0, .Complex
+    new P1, .Complex
+
+    set P0, "2 + 3i"
+    set P1["real"], 2
+    set P1["imag"], 3
+
+    eq P0, P1, OK1
+    print "not "
+OK1:print "ok1\n"
+
+    set P1, 0
+    ne P0, P1, OK2
+    print "not "
+OK2:print "ok2\n"
+
+    end
+CODE
+ok1
+ok2
+OUTPUT
+

Reply via email to