/*1bern_modp_util.h: number-theoretic utility functions23Copyright (C) 2008, 2009, David Harvey45This file is part of the bernmm package (version 1.1).67bernmm is released under a BSD-style license. See the README file in8the source distribution for details.9*/101112#ifndef BERNMM_BERN_MODP_UTIL_H13#define BERNMM_BERN_MODP_UTIL_H141516#include <vector>17#include <cassert>18#include <climits>192021#if ULONG_MAX == 4294967295U22#define ULONG_BITS 3223#elif ULONG_MAX == 18446744073709551615U24#define ULONG_BITS 6425#else26#error Oops! Unsigned long is neither 32 nor 64 bits.27#error You need to update bern_modp_util.h.28#endif293031namespace bernmm {323334/*35Same as NTL's PowerMod, but also accepts an _ninv_ parameter, which is the36same as the ninv parameter for NTL's MulMod routines, i.e. should have37ninv = 1 / ((double) n).3839(Implementation is adapted from ZZ.c in NTL 5.4.1.)40*/41long PowerMod(long a, long ee, long n, double ninv);424344/*45Represents the factorisation of an integer n into distinct prime factors.4647(Very naive implementation!)48*/49class Factorisation50{51protected:52/*53Finds distinct prime factors of m in the range k < p <= m.54Assumes that m does not have any prime factors p <= k.55Appends factors found to _factors_.56*/57void helper(long k, long m);5859public:60// the integer61long n;6263// the distinct factors (in increasing order)64std::vector<long> factors;6566// initialises with given integer67Factorisation(long n);68};69707172class PrimeTable73{74private:75std::vector<long> data; // bit-vector; 0 means prime, 1 means composite7677// read bit from index i78inline bool get(long i) const79{80return (data[i / ULONG_BITS] >> (i % ULONG_BITS)) & 1;81}8283// set bit at index i84inline void set(long i)85{86data[i / ULONG_BITS] |= (1L << (i % ULONG_BITS));87}888990public:91// initialise with primes up to given bound92PrimeTable(long bound);9394// test whether n is prime by table lookup95inline bool is_prime(long n) const96{97return !get(n);98}99100// returns smallest prime p that is larger than n101long next_prime(long n) const102{103for (n++; !is_prime(n); n++);104return n;105}106};107108109110/*111Returns 1 if n is prime.112*/113int is_prime(long n);114115116/*117Returns smallest prime larger than p.118*/119long next_prime(long p);120121122/*123Computes order of x mod p, given the factorisation F of p-1.124*/125long order(long x, long p, double pinv, const Factorisation& F);126127128/*129Finds the smallest primitive root mod p, given the factorisation F of p-1.130*/131long primitive_root(long p, double pinv, const Factorisation& F);132133134}; // end namespace135136137#endif138139// end of file ================================================================140141142