117683Spst/* mpn_lshift -- Shift left low level.
239291Sfenner
317683SpstCopyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
417683Spst
517683SpstThis file is part of the GNU MP Library.
617683Spst
717683SpstThe GNU MP Library is free software; you can redistribute it and/or modify
817683Spstit under the terms of the GNU Lesser General Public License as published by
917683Spstthe Free Software Foundation; either version 2.1 of the License, or (at your
1017683Spstoption) any later version.
1117683Spst
1217683SpstThe GNU MP Library is distributed in the hope that it will be useful, but
1317683SpstWITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1417683Spstor FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
1517683SpstLicense for more details.
1617683Spst
1717683SpstYou should have received a copy of the GNU Lesser General Public License
1817683Spstalong with the GNU MP Library; see the file COPYING.LIB.  If not, write to
1917683Spstthe Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
2017683SpstMA 02111-1307, USA. */
2117683Spst
2217683Spst#include <config.h>
2317683Spst#include "gmp-impl.h"
2417683Spst
2517683Spst/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left
2617683Spst   and store the USIZE least significant digits of the result at WP.
2717683Spst   Return the bits shifted out from the most significant digit.
2817683Spst
2917683Spst   Argument constraints:
3017683Spst   1. 0 < CNT < BITS_PER_MP_LIMB
3117683Spst   2. If the result is to be written over the input, WP must be >= UP.
3217683Spst*/
3317683Spst
3417683Spstmp_limb_t
35127664Sbms#if __STDC__
36214518Srpaulompn_lshift (register mp_ptr wp,
3717683Spst	    register mp_srcptr up, mp_size_t usize,
3817683Spst	    register unsigned int cnt)
3975107Sfenner#else
4075107Sfennermpn_lshift (wp, up, usize, cnt)
4175107Sfenner     register mp_ptr wp;
4275107Sfenner     register mp_srcptr up;
43127664Sbms     mp_size_t usize;
44127664Sbms     register unsigned int cnt;
45127664Sbms#endif
46214518Srpaulo{
47214518Srpaulo  register mp_limb_t high_limb, low_limb;
48214518Srpaulo  register unsigned sh_1, sh_2;
49214518Srpaulo  register mp_size_t i;
50214518Srpaulo  mp_limb_t retval;
51214518Srpaulo
52214518Srpaulo#ifdef DEBUG
53214518Srpaulo  if (usize == 0 || cnt == 0)
5417683Spst    abort ();
55183102Scsjp#endif
56127664Sbms
5717683Spst  sh_1 = cnt;
5817683Spst#if 0
5917683Spst  if (sh_1 == 0)
6017683Spst    {
61235426Sdelphij      if (wp != up)
6217683Spst	{
63127664Sbms	  /* Copy from high end to low end, to allow specified input/output
6498530Sfenner	     overlapping.  */
6598530Sfenner	  for (i = usize - 1; i >= 0; i--)
6617683Spst	    wp[i] = up[i];
6717683Spst	}
6817683Spst      return 0;
6917683Spst    }
7017683Spst#endif
71146768Ssam
72146768Ssam  wp += 1;
73146768Ssam  sh_2 = BITS_PER_MP_LIMB - sh_1;
74146768Ssam  i = usize - 1;
7517683Spst  low_limb = up[i];
7617683Spst  retval = low_limb >> sh_2;
77127664Sbms  high_limb = low_limb;
78251129Sdelphij  while (--i >= 0)
79251129Sdelphij    {
80251129Sdelphij      low_limb = up[i];
81251129Sdelphij      wp[i] = (high_limb << sh_1) | (low_limb >> sh_2);
82251129Sdelphij      high_limb = low_limb;
83251129Sdelphij    }
84251129Sdelphij  wp[i] = high_limb << sh_1;
85251129Sdelphij
86251129Sdelphij  return retval;
87251129Sdelphij}
88251129Sdelphij