/*
   This file is part of Numerix.  Numerix is free software; you can
   redistribute it and/or modify it under the terms of the GNU General
   Public License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   USA 
*/

/* +------------------------------------------------------------------------+
   |                                                                        |
   |                      Entiers de longueur arbitraire                    |
   |                                                                        |
   |                                Décalages                               |
   |                                                                        |
   +------------------------------------------------------------------------+ */

/* M. Quercia, 31/01/2001 */

#include "long_int.h"
#include "long_int-s.h"

             /* +-------------------------------------+
                |  c <- a >> compte, la >= compte/HW  |
                +-------------------------------------+ */

#ifndef have_sn_shr
void xn(shr)(naturel a, longueur la, longueur compte, naturel c) {
  longueur l1 = compte/HW, l2 = compte%HW;
  longueur i,j;
  ndouble ret;

  /* décale les chiffres de a */
  if (l2) {
    for (i=l1+1, j=0; i<la; i++, j++) {
      ret = (((ndouble)a[i]) << HW) + (ndouble)a[i-1];
      c[j] = ret >> l2;
    }
    c[j] = a[i-1] >> l2;
  }
  else xn(move)(c,a+l1,la-l1);
}
#endif

                     /* +--------------------+
                        |  c <- a << compte  |
                        +--------------------+ */

#ifndef have_sn_shl
void xn(shl)(naturel a, longueur la, longueur compte, naturel c) {
  longueur l1 = compte/HW, l2 = compte%HW, l3 = HW-l2;
  longueur i,j;
  ndouble ret;

  /* décale les chiffres de a */
  if (l2) {
    for (ret=0, i=la-1, j=la+l1; i>=0; i--, j--) {
      ret  = (ret << HW) + (ndouble)a[i];
      c[j] = ret >> l3;
    }
    c[l1] = ret << l2;
  }
  else {xn(move)(c+l1,a,la); c[la+l1] = 0;}

  /* complète c par des zéros */
  xn(clear)(c,l1);
}
#endif

                      /* +-------------------+
                         |  décalage dans Z  |
                         +-------------------+ */

#ifndef have_sz_shift
void xz(shift)(entier *a, longueur compte, entier *c) {
  longueur la = Lg(a), lc;

  if (compte > 0) {
    lc = la + compte/HW + 1;
    xn(shl)(a->val,la,compte,c->val);
  } else if (compte < 0) {
    compte = -compte;
    lc = la - compte/HW;
    if (lc > 0) xn(shr)(a->val,la,compte,c->val);
  } else {
    lc = la;
    xn(move)(c->val,a->val,la);
  }
  make_head(c,lc,Signe(a));
}
#endif
