/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1987
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:shlun.c 12.0$ */
/* $ACIS:shlun.c 12.0$ */
/* $Source: /ibm/acis/usr/src/lib/libc/ca/gen/RCS/shlun.c,v $ */

#ifndef lint
static char *rcsid = "$Header:shlun.c 12.0$";
#endif

/* SHIFT TWO LONGWORDS LEFT UNTIL NORMALIZED

The argument is a two-element vector of longwords. At least one 
bit must be set in one of the elements. The result is the number 
of leading zeros in the argument, and will range from 0 to 63, 
inclusive. As a side effect, the argument will be shifted left 
until its first bit is 1. 

The algorithm tests the argument repeatedly, and on the basis of 
the test conditionally shifts the argument left by decreasing 
amounts. The shift amounts are 32, 16, 8, 4, 2, and 1. Some 
combination of these shifts is guaranteed to normalize any 
argument except one which is all zeros. This possibility is not 
tested for.

The shift is a double-precision logical left shift, effected by 
a combination of single precision logical left and right shifts 
and logical 32-bit ors. */

#define X 0x80000000  /* Smallest longword with bit 0 = 1. */

int _shlun (q)
unsigned long q[2];

{unsigned long m;     /* Comparand to see if shift needed. */
 unsigned int s,k;    /* s (result) sums shift amounts;    */
                      /* k is shift amount.                */

/* m begins as the smallest value against which an argument which 
has a zero upper part will compare lower than; s is initially 0, 
and this is the result if the argument is already normalized; k 
is the (decreasing) shift amount, initially 32, for the maximum 
possible shift -- it will be halved until the argument is 
normalized, to a minimum of 1. 

The algorithm continues as long as q isn't normalized. At the end 
of each iteration, k is halved and a new comparand m is obtained 
by shifting the old m left by the new value of k. */

 for (m = 1, s = 0, k = 32; q[0] < X; k /= 2, m <<= k)

/* If q[0] is less than the current value of m, it needs shifting 
left by the current value of k, and s needs augmenting by k, to 
keep track of the total shift amount. */

  {if (q[0] < m)
    {q[0] = q[0]<<k | q[1] >> 32-k;
     q[1] <<= k;
     s += k;}}

/* The value of q is available to our caller as a side effect; 
the actual result is the sum of all the shifts, which is the 
normalizing amount. */

 return (s);}
