diff --git a/src/ChangeLog b/src/ChangeLog
index 401f04e77e196efaa648b686becd917c8d7b2c35..bcc046c3e035e2c5df0bf509ea5f7b426882b7e2 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -6,6 +6,7 @@ Fri Nov  1 15:47:48 1996  Fredrik Hubinette  <hubbe@tymin.blarg.com>
 	* some documentation about pike internals added
 	* htmlify_docs.pike fixed to handle internal docs
 	* mpz->powm fixed
+	* modules/math/math.c: sqrt optimized
 	
 Tue Oct 29 16:12:03 1996  Fredrik Hubinette  <hubbe@tymin.blarg.com>
 
diff --git a/src/modules/math/math.c b/src/modules/math/math.c
index baa0b35d78b5303ba0b64ecb73dfa0491557c6ea..844696cdee79e42a1de09d9bf6a0f1cd44215ac2 100644
--- a/src/modules/math/math.c
+++ b/src/modules/math/math.c
@@ -68,14 +68,19 @@ void f_sqrt(INT32 args)
 
   if(sp[-args].type==T_INT)
   {
-    INT32 a,b,c,q;
-    q=sp[-args].u.integer;
-    for(a=0,b=0x10000;a+1<b;)
+    unsigned INT32 n, b, s, y=0;
+    unsigned INT16 x=0;
+    
+    n=sp[-args].u.integer;
+    for(b=1<<(sizeof(INT32)*8-2); b; b>>=2)
     {
-      c=(a+b)/2;
-      if(c*c>q) b=c; else a=c;
+      x<<=1; s=b+y; y>>=1;
+      if(n>=s)
+      {
+	x|=1; y|=b; n-=s;
+      }
     }
-    sp[-args].u.integer=a;
+    sp[-args].u.integer=x;
   }
   else if(sp[-args].type==T_FLOAT)
   {
diff --git a/src/modules/math/testsuite.in b/src/modules/math/testsuite.in
index 44001823a24bd9919a07b70aa889b62ecf877c8e..6d8eefbb9f31119ffaf15212db87dbd6228472e7 100644
--- a/src/modules/math/testsuite.in
+++ b/src/modules/math/testsuite.in
@@ -26,7 +26,9 @@ test_true(cos(atan(1.0))<0.708)
 test_eq(4,sqrt(16))
 test_eq(4,sqrt(17))
 test_eq(4,sqrt(24))
+test_eq(sqrt(0x7fffffff),46340)
 test_eq(4.0,sqrt(16.0))
+test_any([[int e,i; for(e=0;e<100000;e++) { i=sqrt(e); if(i*i>e || (i+1)*(i+1)<e) return e; } return -1;]],-1)
 // - floor
 test_eq(17.0,floor(17.0))
 test_eq(17.0,floor(17.1))