diff --git a/numeric.c b/numeric.c
index 634c2eb..4f9994c 100644
--- a/numeric.c
+++ b/numeric.c
@@ -3022,6 +3022,32 @@ fix_even_p(VALUE num)
     return Qtrue;
 }
 
+static VALUE
+fix_gcd(int argc, VALUE *argv, VALUE self) {
+  if ( argc != 1 ) {
+    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, 1);
+  } else {
+    /* Handle Fixnum#gcd(Fixnum) here. 
+     * Note: Cannot handle values <= FIXNUM_MIN here due to overflow during negation.
+     */
+    long a, b;
+
+    if ( FIXNUM_P(argv[0]) && (a = FIX2LONG(self)) > FIXNUM_MIN && (b = FIX2LONG(argv[0])) > FIXNUM_MIN ) {
+      long min = a < 0 ? - a : a;
+      long max = b < 0 ? - b : b;
+      while ( min > 0 ) {
+       long tmp = min;
+       min = max % min;
+       max = tmp;
+      }
+      return LONG2FIX(max);
+    } else {
+      /* Delegate to Integer#gcd. */
+      return rb_call_super(1, argv);
+    }
+  }
+}
+
 void
 Init_Numeric()
 {
@@ -3115,6 +3141,7 @@ Init_Numeric()
     rb_define_method(rb_cFixnum, "divmod", fix_divmod, 1);
     rb_define_method(rb_cFixnum, "quo", fix_quo, 1);
     rb_define_method(rb_cFixnum, "fdiv", fix_quo, 1);
+    rb_define_method(rb_cFixnum, "gcd", fix_gcd, -1);
     rb_define_method(rb_cFixnum, "**", fix_pow, 1);
 
     rb_define_method(rb_cFixnum, "abs", fix_abs, 0);

