xref: /inferno-os/libmp/port/mpright.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1  #include "os.h"
2  #include <mp.h>
3  #include "dat.h"
4  
5  // res = b >> shift
6  void
7  mpright(mpint *b, int shift, mpint *res)
8  {
9  	int d, l, r, i;
10  	mpdigit this, last;
11  
12  	res->sign = b->sign;
13  	if(b->top==0){
14  		res->top = 0;
15  		return;
16  	}
17  
18  	// a negative right shift is a left shift
19  	if(shift < 0){
20  		mpleft(b, -shift, res);
21  		return;
22  	}
23  
24  	if(res != b)
25  		mpbits(res, b->top*Dbits - shift);
26  	d = shift/Dbits;
27  	r = shift - d*Dbits;
28  	l = Dbits - r;
29  
30  	//  shift all the bits out == zero
31  	if(d>=b->top){
32  		res->top = 0;
33  		return;
34  	}
35  
36  	// special case digit shifts
37  	if(r == 0){
38  		for(i = 0; i < b->top-d; i++)
39  			res->p[i] = b->p[i+d];
40  	} else {
41  		last = b->p[d];
42  		for(i = 0; i < b->top-d-1; i++){
43  			this = b->p[i+d+1];
44  			res->p[i] = (this<<l) | (last>>r);
45  			last = this;
46  		}
47  		res->p[i++] = last>>r;
48  	}
49  	while(i > 0 && res->p[i-1] == 0)
50  		i--;
51  	res->top = i;
52  	if(i==0)
53  		res->sign = 1;
54  }
55