We could work with `off_t' throughout, but in fact we might be asked for
a /very/ large stream, and it turns out that there's a rather convenient
multiprecision integer library just waiting to be used.
#include <mLib/report.h>
#include <mLib/sub.h>
#include <mLib/report.h>
#include <mLib/sub.h>
+#include "mp.h"
+#include "mpint.h"
+#include "mplimits.h"
+#include "mptext.h"
+
#include "fipstest.h"
#include "grand.h"
#include "maurer.h"
#include "fipstest.h"
#include "grand.h"
#include "maurer.h"
/*----- Miscellaneous static data -----------------------------------------*/
static FILE *outfp;
/*----- Miscellaneous static data -----------------------------------------*/
static FILE *outfp;
-static size_t outsz = 0;
static unsigned maurer_lo = 5, maurer_hi = 8;
static int argc;
static unsigned maurer_lo = 5, maurer_hi = 8;
static int argc;
break;
case 'z': {
char *p;
break;
case 'z': {
char *p;
- outsz = strtoul(optarg, &p, 0);
- if (!outsz)
+ outsz = mp_readstring(outsz, optarg, &p, 0);
+ if (!outsz || MP_NEGP(outsz))
die(EXIT_FAILURE, "bad number `%s'", optarg);
switch (*p) {
die(EXIT_FAILURE, "bad number `%s'", optarg);
switch (*p) {
- case 'G': case 'g': outsz *= 1024;
- case 'M': case 'm': outsz *= 1024;
- case 'K': case 'k': outsz *= 1024;
+ case 'G': case 'g': outsz = mp_lsl(outsz, outsz, 10);
+ case 'M': case 'm': outsz = mp_lsl(outsz, outsz, 10);
+ case 'K': case 'k': outsz = mp_lsl(outsz, outsz, 10);
-static int generate(grand *r, size_t outsz,
+static int generate(grand *r, mp *outsz,
int (*func)(const void *buf, size_t sz, void *p),
void *p)
{
static char kmg[] = { ' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 0 };
unsigned percent = 0;
int (*func)(const void *buf, size_t sz, void *p),
void *p)
{
static char kmg[] = { ' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 0 };
unsigned percent = 0;
+ mp *kb = MP_ZERO, *t = MP_NEW;
+ dstr d = DSTR_INIT;
time_t last;
static char baton[] = "-\\|/";
char *bp;
time_t last;
static char baton[] = "-\\|/";
char *bp;
signal(SIGPIPE, SIG_IGN);
#endif
signal(SIGPIPE, SIG_IGN);
#endif
+ while (!outsz || MP_CMP(kb, <, outsz)) {
- size_t sz = sizeof(buf);
+ size_t sz = sizeof(buf), left;
clock_t c_start, c_stop;
/* --- Emit a bufferful (or less) of data --- */
if (outsz) {
clock_t c_start, c_stop;
/* --- Emit a bufferful (or less) of data --- */
if (outsz) {
- if (sz > outsz - kb)
- sz = outsz - kb;
+ t = mp_sub(t, outsz, kb);
+ assert(!MP_NEGP(t));
+ if (MP_CMP(t, <=, MP_SIZET_MAX)) {
+ left = mp_tosizet(t);
+ if (sz > left) sz = left;
+ }
}
c_start = clock();
r->ops->fill(r, buf, sz);
}
c_start = clock();
r->ops->fill(r, buf, sz);
clk += c_stop - c_start;
if (func && (rc = func(buf, sz, p)) != 0)
return (rc);
clk += c_stop - c_start;
if (func && (rc = func(buf, sz, p)) != 0)
return (rc);
+ t = mp_fromsizet(t, sz);
+ kb = mp_add(kb, kb, t);
/* --- Update the display --- */
if (flags & f_progress) {
/* --- Update the display --- */
if (flags & f_progress) {
unsigned up = 0;
if (percent > 100)
up = 1;
if (!outsz) {
unsigned up = 0;
if (percent > 100)
up = 1;
if (!outsz) {
- if (difftime(t, last) > 1.0) {
+ if (difftime(now, last) > 1.0) {
up = 1;
}
if (up)
fputs(" ] ", stderr);
} else {
up = 1;
}
if (up)
fputs(" ] ", stderr);
} else {
- unsigned pc = kb * 100.0 / outsz;
- if (pc > percent || percent > 100 || difftime(t, last) > 1.0) {
+ unsigned pc;
+ t = mp_fromulong(t, 100);
+ t = mp_mul(t, t, kb);
+ mp_div(&t, 0, t, outsz);
+ assert(!MP_NEGP(t) && MP_CMP(t, <, MP_UINT_MAX));
+ pc = mp_touint(t);
+ if (pc > percent || percent > 100 || difftime(now, last) > 1.0) {
if (percent > 100)
percent = 0;
percent &= ~1;
if (percent > 100)
percent = 0;
percent &= ~1;
- while (q > 8192 && kk[1]) {
- q >>= 10;
+ t = mp_add(t, kb, MP_ZERO);
+ while (mp_bits(t) >= 14) {
+ t = mp_lsr(t, t, 10);
- fprintf(stderr, "%4i%c\r[", (int)q, *kk);
+ DRESET(&d);
+ mp_writedstr(t, &d, 10);
+ fprintf(stderr, "%4s%c\r[", d.buf, *kk);
if (outsz) {
unsigned pc;
for (pc = 0; pc < (percent & ~1); pc += 2)
putc('.', stderr);
}
if (outsz) {
unsigned pc;
for (pc = 0; pc < (percent & ~1); pc += 2)
putc('.', stderr);
}
-
- /* --- Terminate the loop --- */
-
- } while (!outsz || kb < outsz);
if (flags & f_progress)
fputc('\n', stderr);
if (flags & f_timer) {
if (flags & f_progress)
fputc('\n', stderr);
if (flags & f_timer) {
- fprintf(stderr, "generated %lu bytes ", (unsigned long)outsz);
+ DRESET(&d);
+ dstr_puts(&d, "generated ");
+ mp_writedstr(kb, &d, 10);
+ dstr_puts(&d, " bytes ");
- fputs("too quickly to measure\n", stderr);
+ dstr_puts(&d, "too quickly to measure\n");
double sec = (double)clk/CLOCKS_PER_SEC;
double sec = (double)clk/CLOCKS_PER_SEC;
- double bps = (outsz << 3)/sec;
+ unsigned long sh;
+ double bps;
+
+ MP_SHRINK(kb);
+ switch (MP_LEN(kb)) {
+ case 0: out = 0; break;
+ case 1: out = kb->v[0]; break;
+ default:
+ sh = mp_bits(kb) - MPW_BITS;
+ t = mp_lsr(t, kb, sh);
+ out = ldexp(t->v[0], sh);
+ break;
+ }
+ bps = (8*out)/sec;
for (kk = kmg; bps > 1024 && kk[1]; kk++, bps /= 1024)
;
for (kk = kmg; bps > 1024 && kk[1]; kk++, bps /= 1024)
;
- fprintf(stderr, "in %g secs (%g %cb/s)\n", sec, bps, *kk);
+ dstr_putf(&d, "in %g secs (%g %cb/s)\n", sec, bps, *kk);
+ fwrite(d.buf, 1, d.len, stderr);
+
+ mp_drop(t);
+ DDESTROY(&d);
if (flags & f_fips) {
octet buf[FIPSTEST_BUFSZ];
unsigned rc;
if (flags & f_fips) {
octet buf[FIPSTEST_BUFSZ];
unsigned rc;
- generate(r, sizeof(buf), genbuf, &p);
+ t = mp_fromsizet(MP_NEW, sizeof(buf));
+ generate(r, t, genbuf, &p);
+ mp_drop(t);
rc = fipstest(buf);
if (rc & FIPSTEST_MONOBIT)
moan("failed monobit test");
rc = fipstest(buf);
if (rc & FIPSTEST_MONOBIT)
moan("failed monobit test");
size_t bufsz;
unsigned i;
unsigned rc = 0;
size_t bufsz;
unsigned i;
unsigned rc = 0;
genmaurer_ctx g;
static struct { double x; const char *sig; } sigtab[] = {
genmaurer_ctx g;
static struct { double x; const char *sig; } sigtab[] = {
maurer_init(&g.m[i], i + maurer_lo);
bufsz = (100 * maurer_hi) << maurer_hi;
maurer_init(&g.m[i], i + maurer_lo);
bufsz = (100 * maurer_hi) << maurer_hi;
- generate(r, bufsz, genmaurer, &g);
+ t = mp_fromsizet(MP_NEW, bufsz);
+ generate(r, t, genmaurer, &g);
+ mp_drop(t);
for (i = maurer_lo; i <= maurer_hi; i++) {
double z = maurer_done(&g.m[i - maurer_lo]);
for (i = maurer_lo; i <= maurer_hi; i++) {
double z = maurer_done(&g.m[i - maurer_lo]);