summaryrefslogtreecommitdiff
path: root/sys/src/libmp/port/mpsel.c
blob: a145b9d06a02c044f27175ffcf096f6bc0fbab6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "os.h"
#include <mp.h>
#include "dat.h"

// res = s != 0 ? b1 : b2
void
mpsel(int s, mpint *b1, mpint *b2, mpint *res)
{
	mpdigit d;
	int n, m, i;

	res->flags |= (b1->flags | b2->flags) & MPtimesafe;
	if((res->flags & MPtimesafe) == 0){
		mpassign(s ? b1 : b2, res);
		return;
	}
	res->flags &= ~MPnorm;

	n = b1->top;
	m = b2->top;
	mpbits(res, Dbits*(n >= m ? n : m));
	res->top = n >= m ? n : m;

	s = (-s^s|s)>>(sizeof(s)*8-1);
	res->sign = (b1->sign & s) | (b2->sign & ~s);

	d = -((mpdigit)s & 1);

	i = 0;
	while(i < n && i < m){
		res->p[i] = (b1->p[i] & d) | (b2->p[i] & ~d);
		i++;
	}
	while(i < n){
		res->p[i] = b1->p[i] & d;
		i++;
	}
	while(i < m){
		res->p[i] = b2->p[i] & ~d;
		i++;
	}
}