+#define START 0
+#define STOP 1
+
+static double Time_F(int s)
+{
+ double ret;
+#ifdef TIMES
+ static struct tms tstart, tend;
+
+ if (s == START) {
+ times(&tstart);
+ return (0);
+ } else {
+ times(&tend);
+ ret = ((double)(tend.tms_utime - tstart.tms_utime)) / HZ;
+ return ((ret < 1e-3) ? 1e-3 : ret);
+ }
+#else /* !times() */
+ static struct timeb tstart, tend;
+ long i;
+
+ if (s == START) {
+ ftime(&tstart);
+ return (0);
+ } else {
+ ftime(&tend);
+ i = (long)tend.millitm - (long)tstart.millitm;
+ ret = ((double)(tend.time - tstart.time)) + ((double)i) / 1000.0;
+ return ((ret < 0.001) ? 0.001 : ret);
+ }
+#endif
+}
+
+#define NUM_SIZES 7
+#if NUM_START > NUM_SIZES
+# error "NUM_START > NUM_SIZES"
+#endif
+static int sizes[NUM_SIZES] = { 128, 256, 512, 1024, 2048, 4096, 8192 };
+
+static int mul_c[NUM_SIZES] =
+ { 8 * 8 * 8 * 8 * 8 * 8, 8 * 8 * 8 * 8 * 8, 8 * 8 * 8 * 8, 8 * 8 * 8,
+ 8 * 8, 8, 1
+};
+
+/*
+ * static int sizes[NUM_SIZES]={59,179,299,419,539};
+ */
+
+#define RAND_SEED(string) { const char str[] = string; RAND_seed(string, sizeof str); }
+
+void do_mul_exp(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx);
+
+int main(int argc, char **argv)
+{
+ BN_CTX *ctx;
+ BIGNUM *a, *b, *c, *r;
+
+#if 1
+ if (!CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0))
+ abort();
+#endif
+
+ ctx = BN_CTX_new();
+ a = BN_new();
+ b = BN_new();
+ c = BN_new();
+ r = BN_new();
+
+ while (!RAND_status())
+ /* not enough bits */
+ RAND_SEED("I demand a manual recount!");
+
+ do_mul_exp(r, a, b, c, ctx);
+ return 0;
+}
+
+void do_mul_exp(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx)
+{
+ int i, k;
+ double tm;
+ long num;
+
+ num = BASENUM;
+ for (i = NUM_START; i < NUM_SIZES; i++) {
+#ifdef C_PRIME
+# ifdef TEST_SQRT
+ if (!BN_set_word(a, 64))
+ goto err;
+ if (!BN_set_word(b, P_MOD_64))
+ goto err;
+# define ADD a
+# define REM b
+# else
+# define ADD NULL
+# define REM NULL
+# endif
+ if (!BN_generate_prime(c, sizes[i], 0, ADD, REM, genprime_cb, NULL))
+ goto err;
+ putc('\n', stderr);
+ fflush(stderr);
+#endif
+
+ for (k = 0; k < num; k++) {
+ if (k % 50 == 0) { /* Average over num/50 different choices of
+ * random numbers. */
+ if (!BN_pseudo_rand(a, sizes[i], 1, 0))
+ goto err;
+
+ if (!BN_pseudo_rand(b, sizes[i], 1, 0))
+ goto err;
+
+#ifndef C_PRIME
+ if (!BN_pseudo_rand(c, sizes[i], 1, 1))
+ goto err;
+#endif
+
+#ifdef TEST_SQRT
+ if (!BN_mod_sqr(a, a, c, ctx))
+ goto err;
+ if (!BN_mod_sqr(b, b, c, ctx))
+ goto err;