From 81a452ea86d5f54681df158162c2d30abe78e4b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se>
Date: Sat, 5 Jan 2008 23:48:31 +0100
Subject: [PATCH] * examples/next-prime.c: New file.

Rev: nettle/examples/next-prime.c:1.1
---
 examples/next-prime.c | 208 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 208 insertions(+)
 create mode 100644 examples/next-prime.c

diff --git a/examples/next-prime.c b/examples/next-prime.c
new file mode 100644
index 00000000..6273a1c6
--- /dev/null
+++ b/examples/next-prime.c
@@ -0,0 +1,208 @@
+/* next-prime.c
+ *
+ * Command line tool for prime search.
+ *
+ */
+ 
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2007 Niels Möller
+ *  
+ * The nettle library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ * 
+ * The nettle library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ * License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "bignum.h"
+
+#include "getopt.h"
+
+static void
+usage(void)
+{
+  fprintf(stderr, "Usage: next-prime [OPTIONS] number\n\n"
+	  "Options:\n"
+	  "      --help         Display this message.\n"
+	  "  -v, --verbose      Display timing information.\n"
+	  "      --factorial    Use factorial of input number.\n"
+	  "  -s  --sieve-limit  Number of primes to use for sieving.\n");
+}
+
+/* For timing */
+struct timing {
+  clock_t start;
+  clock_t sieve_start;
+  clock_t sieve_time;
+  clock_t fermat_start;
+  clock_t fermat_time;
+  unsigned fermat_count;
+  clock_t miller_start;
+  clock_t miller_time;
+  unsigned miller_count;
+  clock_t end;
+};
+
+static void
+progress(void *ctx, int c)
+{
+  struct timing *timing = (struct timing *) ctx;
+  clock_t now = clock();
+  switch (c)
+    {
+    case '.':
+      timing->sieve_time += (now - timing->sieve_start);
+      timing->fermat_count++;
+      timing->fermat_start = now;
+      break;
+    case ',':
+      timing->sieve_start = now;
+      timing->fermat_time += (now - timing->fermat_start);
+      break;
+    case '+':
+      timing->fermat_time += (now - timing->fermat_start);
+      timing->miller_count++;
+      timing->miller_start = now;
+      break;
+    case '*':
+      timing->sieve_start = now;
+      timing->miller_time += (now - timing->miller_start);
+      break;
+      
+    default:
+      abort();
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+  mpz_t n;
+  mpz_t p;
+
+  int c;
+  int verbose = 0;  
+  int factorial = 0;
+  int prime_limit = 200;
+
+  struct timing timing;
+
+  enum { OPT_FACTORIAL = -100, OPT_RANDOM };
+  static const struct option options[] =
+    {
+      /* Name, args, flag, val */
+      { "help", no_argument, NULL, '?' },
+      { "verbose", no_argument, NULL, 'v' },
+      { "factorial", no_argument, NULL, 'f' },
+      { "sieve-limit", required_argument, NULL, 's' },
+      { NULL, 0, NULL, 0}
+    };
+
+  while ( (c = getopt_long(argc, argv, "v?s:", options, NULL)) != -1)
+    switch (c)
+      {
+      case 'v':
+	verbose = 1;
+	break;
+      case '?':
+	usage();
+	return EXIT_FAILURE;
+      case 'f':
+	factorial = 1;
+	break;
+      case 's':
+	prime_limit = atoi(optarg);
+	if (prime_limit < 0)
+	  {
+	    usage();
+	    return EXIT_FAILURE;
+	  }
+	break;
+      default:
+	abort();
+	
+      }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argc != 1)
+    usage();
+
+  mpz_init(n);
+
+  if (factorial)
+    {
+      long arg;
+      char *end;
+      arg = strtol(argv[0], &end, 0);
+      if (*end || arg < 0)
+	{
+	  fprintf(stderr, "Invalid number.\n");
+	  return EXIT_FAILURE;
+	}
+      mpz_fac_ui(n, arg);
+    }
+  else if (mpz_set_str(n, argv[0], 0))
+    {
+      fprintf(stderr, "Invalid number.\n");
+      return EXIT_FAILURE;
+    }
+
+  if (mpz_cmp_ui(n, 2) <= 0)
+    {
+      printf("2\n");
+      return EXIT_SUCCESS;
+    }
+
+  mpz_init(p);
+
+  timing.fermat_count = timing.miller_count = 0;
+  timing.sieve_time = timing.fermat_time = timing.miller_time = 0;
+  timing.start = timing.sieve_start = clock();
+  nettle_next_prime(p, n, 25, prime_limit, &timing, verbose ? progress : NULL);
+  timing.end = clock();
+  
+  mpz_out_str(stdout, 10, p);
+  printf("\n");
+
+  if (verbose)
+    {
+      mpz_t d;
+      
+      mpz_init(d);
+      mpz_sub(d, p, n);
+
+      timing.miller_time += (timing.end - timing.miller_start);
+
+      gmp_fprintf(stderr, "bit size: %lu, diff: %Zd, total time: %.3g s\n",
+		  mpz_sizeinbase(p, 2), d,
+		  (double)(timing.end - timing.start) / CLOCKS_PER_SEC);
+
+      fprintf(stderr, "sieve time = %.3g s\n",
+	      (double)(timing.sieve_time) / CLOCKS_PER_SEC);
+      fprintf(stderr, "fermat count: %d, time: %.3g s\n",
+	      timing.fermat_count, (double)(timing.fermat_time) / CLOCKS_PER_SEC);
+      fprintf(stderr, "miller count: %d, time: %.3g s\n",
+	      timing.miller_count, (double)(timing.miller_time) / CLOCKS_PER_SEC);
+    }
+  return EXIT_SUCCESS;
+}
-- 
GitLab