00001 /* 00002 00003 The BLAH library, a container library 00004 Copyright (C) 1997-2004 The CDG Team <cdg@nats.informatik.uni-hamburg.de> 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 00020 Contact: blah@nats.informatik.uni-hamburg.de 00021 00022 $Id: primes.c,v 1.7 2004/03/23 14:21:58 micha Exp $ 00023 00024 */ 00025 00026 /* ---------------------------------------------------------------------- 00027 * @defgroup Prime Primes 00028 * Primes is a module that makes use of Rabin's Probablistic Primetest-Algorithm 00029 * for generating the prime numbers equal to the Hash table entries 00030 * @{ 00031 */ 00032 00033 /* ----INCLUDES------------------------------------------------------- */ 00034 #include <math.h> 00035 #include <time.h> 00036 #include "blah.h" 00037 00038 #if !HAVE_DECL_DRAND48 00039 #define drand48() ((double) rand() / (double) RAND_MAX) 00040 #define srand48(x) (srand((x))) 00041 #endif 00042 00043 /* ---------------------------------------------------------------------- 00044 * addition in a modulo. 00045 * 00046 * @param x the first element used in addition. 00047 * @param y the second element used in addition 00048 * @param m the modulud function 00049 * @returns the added result. 00050 */ 00051 static unsigned long addMod(unsigned long x,unsigned long y,unsigned long m) 00052 { 00053 return ((x + y) % m); 00054 } 00055 00056 /* ---------------------------------------------------------------------- 00057 * multiplication in a modulo. 00058 * 00059 * @param x the first element used in multiplication. 00060 * @param y the second element used in multiplication. 00061 * @param m the modulo function. 00062 * @returns the multiplied result. 00063 */ 00064 static unsigned long multMod(unsigned long x, unsigned long y, unsigned long m) 00065 { 00066 unsigned long sum; 00067 00068 if (x < y) 00069 return (multMod(y, x, m)); 00070 00071 for (sum = 0; y; y = y >> 1, x = addMod(x, x, m)) { 00072 if (y & 1) 00073 sum = addMod(sum, x, m); 00074 } 00075 00076 return sum; 00077 } 00078 00079 /* ---------------------------------------------------------------------- 00080 * exponent in a modulo. 00081 * 00082 * @param x the base function. 00083 * @param y the exponent function. 00084 * @param m the modulo function. 00085 * @returns the result - x raised to the exponential y. 00086 */ 00087 static unsigned long powMod(unsigned long x, unsigned long y, unsigned long m) 00088 { 00089 unsigned long prod; 00090 00091 for (prod = 1; y; y = y >> 1, x = multMod(x, x, m)) { 00092 if (y & 1) 00093 prod = multMod(prod, x, m); 00094 00095 } 00096 return prod; 00097 } 00098 00099 /* ---------------------------------------------------------------------- 00100 * Rabin's probablistic primetest-algorithm 00101 * 00102 * @param number ... 00103 * @param times ... 00104 * @returns true if number is a prime by testing it a few times 00105 */ 00106 int primeRabin(unsigned long number, unsigned long times) 00107 { 00108 unsigned long i; 00109 int flag; 00110 double x; 00111 00112 for (i = 0, flag = 1; flag && i < times; i++) { 00113 x = floor(drand48() * (number - 1)) + 1; 00114 flag = (powMod((long unsigned) x, number - 1, number) == 1); 00115 } 00116 00117 return flag; 00118 } 00119 00120 /* ---------------------------------------------------------------------- 00121 * returns the next prime after a given number. 00122 */ 00123 unsigned long primeNext(unsigned long number, unsigned long times) 00124 { 00125 srand48(time(NULL)); 00126 00127 while (!primeRabin(number, times)) 00128 number++; 00129 return number; 00130 }