diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-08-25 20:20:25 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-08-25 20:20:25 +0200 |
commit | 8f2e408448c2c2d16173f244448b8b9a1fcaf6d7 (patch) | |
tree | e7c0263d9470ac7f73e39613b7ed44f52874ce48 /sys/src/libmp | |
parent | 2dec35524e1c9205656ef0167f5d7486a3a34302 (diff) |
libmp: add mpnrand() function to generate uniform random number 0 ≤ x < n
Diffstat (limited to 'sys/src/libmp')
-rw-r--r-- | sys/src/libmp/port/mkfile | 1 | ||||
-rw-r--r-- | sys/src/libmp/port/mpnrand.c | 39 |
2 files changed, 40 insertions, 0 deletions
diff --git a/sys/src/libmp/port/mkfile b/sys/src/libmp/port/mkfile index 05ee9dd33..76fa25dd7 100644 --- a/sys/src/libmp/port/mkfile +++ b/sys/src/libmp/port/mkfile @@ -27,6 +27,7 @@ FILES=\ mpextendedgcd\ mpinvert\ mprand\ + mpnrand\ crt\ mptoi\ mptoui\ diff --git a/sys/src/libmp/port/mpnrand.c b/sys/src/libmp/port/mpnrand.c new file mode 100644 index 000000000..34ca63a2f --- /dev/null +++ b/sys/src/libmp/port/mpnrand.c @@ -0,0 +1,39 @@ +#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; +} |