Date: Mon, 19 Apr 1999 17:50:23 +0200
From: rainer storn <rainer.storn@hl.siemens.de>
Newsgroups: comp.dsp
Subject: Square root computation
THIS WORK IS PLACED IN THE PUBLIC DOMAIN

Name: Square root computation

Category: Algorithmic Trick

Application: e.g. Magnitude computation

Advantages: Simple and fast

Introduction:

Once in a while the square root of data has to be computed on a DSP. A method that comes to mind is polynomial approximation of the square root function. A much simpler method, however is the usage of Newton’s method or, if division is a problem, successive approximation.

The Trick:

1) Newton’s method:

Newton’s method states that if you want to find the zero of a function f(x) you may start at some guessing point x1 and compute the next guessing point for the zero x2 according to

x2 = x1 - f(x1)/f´(x1)    (1)

In the next step make x1 := x2 and repeat equation (1) etc. until the difference between x1 and x2 is sufficiently small. Newton’s method does not alway converge, but if it does, it converges fast. In the special case of the square root computation Newton’s method is guaranteed to converge.

Let’s say you want to compute x = sqrt(z) then make

f(x) = x*x - z.  (2)

If we compute f(x) = 0 we immediately see, that x must be the square root of z.

Now plug (2) into (1) to get

x2 = x1 - 0.5*x1 - 0.5*z/x1
   = 0.5*(x1 - z/x1);

which is the recursive equation to be used.

The starting value for x1 is not critical but the closer it is to the real zero the better. I usually use x1 = z.

2) Successive approximation:

If division is a problem, then successive approximation might be the right choice to compute sqrt(x). Successive approximation basically does a binary search to find the square root. A little C-style pseudocode might best explain how it is done:

//----y = sqrt(y)---------
  a = 2^ceil(b/2); //b is the wordlength you are using
  y = a;           //a is the first estimation value for sqrt(x)
  for (i=0; i<ceil(b/2); i++)   //each iteration achieves one bit
  {                             //of accuracy
     a    = a*0.5;
     diff = x - y*y;
     if (diff > 0)
     {
        y = y + a;
     }
     else if (diff < 0)
     {
       y = y - a;
     }
   }

Again, there might be better choices for the starting point but the one given is safe.

Rainer Storn