Index: src/ops/experimental.ops
===================================================================
--- src/ops/experimental.ops	(revision 20901)
+++ src/ops/experimental.ops	(working copy)
@@ -163,10 +163,65 @@
   goto NEXT();
 }
 
-=back
+=item B<sign>(inout INT)
 
+=item B<sign>(inout NUM)
+
+=item B<sign>(invar PMC)
+
+Set $1 to the sign of its value (1 for $1 > 0, -1 for $1 < 0, 0 for $1 == 0)
+
+=item B<sign>(out INT, in INT)
+
+=item B<sign>(out NUM, in NUM)
+
+=item B<sign>(out PMC, invar PMC)
+
+Set $1 to the sign of $2's value.
+
+=item B<n_sign>(out PMC, invar PMC)
+
+Create new $1 as the sign of $2.
+
 =cut
 
+inline op sign(inout INT) :base_core {
+  $1 = $1 > 0 ? 1 : $1 < 0 ? -1 : 0;
+  goto NEXT();
+}
+
+inline op sign(inout NUM) :base_core {
+  $1 = $1 > 0 ? 1 : $1 < 0 ? -1 : 0;
+  goto NEXT();
+}
+
+inline op sign(invar PMC) :base_core {
+  $1->vtable->i_sign(interp, $1);
+  goto NEXT();
+}
+
+inline op sign(out INT, in INT) :base_core {
+  $1 = $2 > 0 ? 1 : ( $2 < 0 ? -1 : 0 );
+  goto NEXT();
+}
+
+inline op sign(out NUM, in NUM) :base_core {
+  $1 = $2 > 0 ? 1 : ( $2 < 0 ? -1 : 0 );
+  goto NEXT();
+}
+
+inline op sign(out PMC, invar PMC) :base_core {
+  $1 = $2->vtable->sign(interp, $2, $1);
+  goto NEXT();
+}
+
+inline op n_sign(out PMC, invar PMC) :base_core {
+  $1 = $2->vtable->sign(interp, $2, NULL);
+  goto NEXT();
+}
+
+=back
+
 ###############################################################################
 
 =head2 Misc other ops
Index: src/pmc/complex.pmc
===================================================================
--- src/pmc/complex.pmc	(revision 20901)
+++ src/pmc/complex.pmc	(working copy)
@@ -1090,6 +1090,43 @@
 
 /*
 
+=item C<PMC *sign(PMC *dest)>
+
+=item C<void i_sign()>
+
+Sets C<dest> to the sign of SELF's value.
+
+=cut
+
+*/
+
+    PMC *sign(PMC *dest) {
+        if (dest)
+            VTABLE_morph(INTERP, dest, enum_class_Complex);  // or exception?
+        else
+            dest = pmc_new(INTERP, enum_class_Complex);
+
+        if(FLOAT_IS_ZERO(RE(SELF)) && FLOAT_IS_ZERO(IM(SELF))) {
+            RE(dest) = IM(dest) = 0;
+        } else {
+                    /* SELF / |SELF| */
+	    FLOATVAL abs_val = sqrt(RE(SELF)*RE(SELF) + IM(SELF)*IM(SELF));
+            RE(dest) = RE(SELF) / abs_val;
+            IM(dest) = IM(SELF) / abs_val;
+        }
+        return dest;
+    }
+
+    void i_sign() {
+        if (FLOAT_IS_ZERO(RE(SELF)) && FLOAT_IS_ZERO(IM(SELF)))
+            return;
+        FLOATVAL abs_val = sqrt(RE(SELF)*RE(SELF) + IM(SELF)*IM(SELF));
+        RE(SELF) /= abs_val;
+        IM(SELF) /= abs_val;
+    }
+
+/*
+
 =item C<METHOD PMC *ln()>
 
 Returns the natural logorithm of SELF.
Index: src/pmc/bigint.pmc
===================================================================
--- src/pmc/bigint.pmc	(revision 20901)
+++ src/pmc/bigint.pmc	(working copy)
@@ -261,6 +261,18 @@
 }
 
 static void
+bigint_sign(PARROT_INTERP, PMC *self, PMC *dest)
+{
+    long sign;
+    if (dest)
+        VTABLE_morph(interp, dest, enum_class_BigInt);
+    else
+        dest = pmc_new(interp, enum_class_BigInt);
+    sign = (long) mpz_sgn(BN(self));
+    mpz_set_si(BN(dest), sign);
+}
+
+static void
 bigint_neg(PARROT_INTERP, PMC *self, PMC *dest)
 {
     VTABLE_morph(interp, dest, enum_class_BigInt);
@@ -1132,6 +1144,32 @@
 
 /*
 
+=item C<PMC *sign(PMC *dest)>
+
+=item C<void i_sign()>
+
+Sets C<dest> to the sign of SELF's value.
+
+=cut
+
+*/
+
+    PMC *sign(PMC *dest) {
+        if (dest)
+            VTABLE_morph(INTERP, dest, enum_class_BigInt);
+        else
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        bigint_sign(INTERP, SELF, dest);
+        return dest;
+    }
+
+    void i_sign() {
+        bigint_sign(INTERP, SELF, SELF);
+    }
+
+
+/*
+
 =item C<PMC *neg(PMC *dest)>
 
 =item C<void i_neg()>
Index: src/pmc/float.pmc
===================================================================
--- src/pmc/float.pmc	(revision 20901)
+++ src/pmc/float.pmc	(working copy)
@@ -368,6 +368,44 @@
 
 /*
 
+=item C<PMC *sign(PMC *desg)>
+
+=item C<void i_sign()>
+
+Sets C<dest> to the sign of SELF's value.
+
+=cut
+
+*/
+
+    PMC *sign(PMC *dest) {
+        FLOATVAL a = DYNSELF.get_number();
+        if (a > 0) {
+           a = 1;
+        } else if (a < 0) {
+           a = -1;
+        } else {
+           a = 0;
+        }
+        if (!dest)
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        VTABLE_set_number_native(INTERP, dest, a);
+        return dest;
+    }
+
+    void i_sign() {
+        FLOATVAL a = DYNSELF.get_number();
+        if (a > 0) {
+           a = 1;
+        } else if (a < 0) {
+           a = -1;
+        } else {
+           a = 0;
+        }
+        VTABLE_set_number_native(INTERP, SELF, a);
+    }
+
+/*
 =item C<void freeze(visit_info *info)>
 
 Used to archive the number.
Index: src/pmc/integer.pmc
===================================================================
--- src/pmc/integer.pmc	(revision 20901)
+++ src/pmc/integer.pmc	(working copy)
@@ -1245,6 +1245,33 @@
 
 /*
 
+=item C<PMC *sign(PMC *dest)>
+
+=item C<void i_sign()>
+
+Sets C<dest> to the sign of SELF's value.
+
+=cut
+
+*/
+
+    PMC *sign(PMC *dest) {
+        INTVAL a = DYNSELF.get_integer();
+        a = a > 0 ? 1 : a < 0 ? -1 : 0;
+        if (!dest)
+            dest = pmc_new(INTERP, SELF->vtable->base_type);
+        VTABLE_set_integer_native(INTERP, dest, a);
+        return dest;
+    }
+
+    void i_sign() {
+        INTVAL a = DYNSELF.get_integer();
+        a = a > 0 ? 1 : a < 0 ? -1 : 0;
+        VTABLE_set_integer_native(INTERP, SELF, a);
+    }
+
+/*
+
 =item C<STRING *get_as_base(INTVAL base)>
 
 Converts and returns the integer in base C<base>.
Index: vtable.tbl
===================================================================
--- vtable.tbl	(revision 20901)
+++ vtable.tbl	(working copy)
@@ -214,6 +214,9 @@
 PMC* neg(PMC* dest)
 void i_neg() :write
 
+PMC* sign(PMC* dest)
+void i_sign() :write
+
 [BITWISE]
 PMC* bitwise_or(PMC* value, PMC* dest)          MMD_BOR
 PMC* bitwise_or_int(INTVAL value, PMC* dest)    MMD_BOR_INT
Index: CREDITS
===================================================================
--- CREDITS	(revision 20901)
+++ CREDITS	(working copy)
@@ -608,3 +608,6 @@
 N: Alek Storm
 E: alek.storm@gmail.com
 D: Fixed object vtable method overrides in PIR
+
+N: Joerg Plate
+E: patterner@patterner.de
Index: t/pmc/complex.t
===================================================================
--- t/pmc/complex.t	(revision 20901)
+++ t/pmc/complex.t	(working copy)
@@ -7,7 +7,7 @@
 use lib qw( . lib ../lib ../../lib );
 use Test::More;
 use Parrot::Config;
-use Parrot::Test tests => 53;
+use Parrot::Test tests => 54;
 
 =head1 NAME
 
@@ -1914,6 +1914,23 @@
 done
 OUTPUT
 
+pasm_output_is( <<'CODE', <<'OUTPUT', "sign of complex numbers" );
+    new P0, 'Complex'
+    set P0, "0"
+    new P1, 'Undef'
+    sign P1, P0
+    print P1
+    print "\n"
+    set P0, "3 + 4i"
+    sign P0
+    print P0
+    print "\n"
+    end
+CODE
+0+0i
+0.6+0.8i
+OUTPUT
+
 # Local Variables:
 #   mode: cperl
 #   cperl-indent-level: 4
Index: t/pmc/bigint.t
===================================================================
--- t/pmc/bigint.t	(revision 20901)
+++ t/pmc/bigint.t	(working copy)
@@ -25,7 +25,7 @@
 =cut
 
 if ( $PConfig{gmp} ) {
-    plan tests => 44;
+    plan tests => 45;
 }
 else {
     plan skip_all => "No BigInt Lib configured";
@@ -1132,6 +1132,29 @@
 ok
 OUT
 
+pasm_output_is( <<'CODE', <<'OUT', "sign of bigints" );
+   new P0, 'BigInt'
+   set P0, 99999999
+   new P1, 'Undef'
+   sign P1, P0
+   print P1
+   print "\n"
+   set P0, 0
+   sign P1, P0
+   print P1
+   print "\n"
+   set P0, -99999999
+   sign P1, P0
+   set I1, P1
+   print I1
+   print "\n"
+   end
+CODE
+1
+0
+-1
+OUT
+
 # Local Variables:
 #   mode: cperl
 #   cperl-indent-level: 4
Index: t/op/01-parse_ops.t
===================================================================
--- t/op/01-parse_ops.t	(revision 20901)
+++ t/op/01-parse_ops.t	(working copy)
@@ -62,6 +62,7 @@
     not
     print
     set
+    sign
     slice
     titlecase
     typeof
Index: t/op/arithmetics.t
===================================================================
--- t/op/arithmetics.t	(revision 20901)
+++ t/op/arithmetics.t	(working copy)
@@ -6,7 +6,7 @@
 use warnings;
 use lib qw( . lib ../lib ../../lib );
 use Test::More;
-use Parrot::Test tests => 26;
+use Parrot::Test tests => 27;
 
 =head1 NAME
 
@@ -634,6 +634,41 @@
 ok 5
 OUTPUT
 
+pasm_output_is( <<'CODE', <<OUTPUT, "sign of native numbers and native integers" );
+        set I0, -2
+        sign I0
+        print I0 
+        print "\n"
+        set I0, 0
+        sign I1, I0
+        print I1 
+        print "\n"
+        set I0, 3
+        sign I1, I0
+        print I1 
+        print "\n"
+        set N0, -3.2
+        sign N0
+        print N0 
+        print "\n"
+        set N0, 0.0
+        sign N1, N0
+        print N1 
+        print "\n"
+        set N0, 1.5
+        sign N1, N0
+        print N1 
+        print "\n"
+        end
+CODE
+-1
+0
+1
+-1.000000
+0.000000
+1.000000
+OUTPUT
+
 pasm_output_is( <<'CODE', <<OUTPUT, "gcd(int,int,int)" );
         set I0, 125
         set I1, 15
