shithub: riscv

ref: 8f2e408448c2c2d16173f244448b8b9a1fcaf6d7
dir: /sys/src/libmp/port/mpnrand.c/

View raw version
#include "os.h"
#include <mp.h>
#include <libsec.h>
#include "dat.h"

/* return uniform random [0..n-1] */
mpint*
mpnrand(mpint *n, void (*gen)(uchar*, int), mpint *b)
{
	mpint *m;
	int bits;

	/* m = 2^bits - 1 */
	bits = mpsignif(n);
	m = mpnew(bits+1);
	if(m == nil)
		sysfatal("mpnrand: %r");
	mpleft(mpone, bits, m);
	mpsub(m, mpone, m);

	if(b == nil){
		b = mpnew(bits);
		if(b == nil)
			sysfatal("mpnrand: %r");
	}

	/* m = m - (m % n) */
	mpmod(m, n, b);
	mpsub(m, b, m);

	do {
		mprand(bits, gen, b);
	} while(mpcmp(b, m) >= 0);

	mpmod(b, n, b);
	mpfree(m);

	return b;
}