xref: /inferno-os/libmp/port/mpright.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 #include "os.h"
2 #include <mp.h>
3 #include "dat.h"
4 
5 // res = b >> shift
6 void
mpright(mpint * b,int shift,mpint * res)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