# 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 +