Primes.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.numbers.primes;

  18. import java.util.List;

  19. /**
  20.  * Methods related to prime numbers in the range of <code>int</code>.
  21.  * <ul>
  22.  * <li>primality test</li>
  23.  * <li>prime number generation</li>
  24.  * <li>factorization</li>
  25.  * </ul>
  26.  */
  27. public final class Primes {
  28.     /** Exception message format when an argument is too small. */
  29.     static final String NUMBER_TOO_SMALL = "%d is smaller than the minimum (%d)";

  30.     /**
  31.      * Utility class.
  32.      */
  33.     private Primes() {}

  34.     /**
  35.      * Primality test: tells if the argument is a (provable) prime or not.
  36.      * <p>
  37.      * It uses the Miller-Rabin probabilistic test in such a way that a result is guaranteed:
  38.      * it uses the firsts prime numbers as successive base (see Handbook of applied cryptography
  39.      * by Menezes, table 4.1).
  40.      *
  41.      * @param n Number to test.
  42.      * @return true if {@code n} is prime. All numbers &lt; 2 return false.
  43.      */
  44.     public static boolean isPrime(int n) {
  45.         if (n < 2) {
  46.             return false;
  47.         }

  48.         for (final int p : SmallPrimes.PRIMES) {
  49.             if (0 == (n % p)) {
  50.                 return n == p;
  51.             }
  52.         }
  53.         return SmallPrimes.millerRabinPrimeTest(n);
  54.     }

  55.     /**
  56.      * Return the smallest prime greater than or equal to n.
  57.      *
  58.      * @param n Positive number.
  59.      * @return the smallest prime greater than or equal to {@code n}.
  60.      * @throws IllegalArgumentException if n &lt; 0.
  61.      */
  62.     public static int nextPrime(int n) {
  63.         if (n < 0) {
  64.             throw new IllegalArgumentException(String.format(NUMBER_TOO_SMALL, n, 0));
  65.         }
  66.         if (n <= 2) {
  67.             return 2;
  68.         }
  69.         n |= 1; // make sure n is odd

  70.         if (isPrime(n)) {
  71.             return n;
  72.         }

  73.         // prepare entry in the +2, +4 loop:
  74.         // n should not be a multiple of 3
  75.         final int rem = n % 3;
  76.         if (0 == rem) { // if n % 3 == 0
  77.             n += 2; // n % 3 == 2
  78.         } else if (1 == rem) { // if n % 3 == 1
  79.             n += 4; // n % 3 == 2
  80.         }
  81.         while (true) { // this loop skips all multiple of 3
  82.             if (isPrime(n)) {
  83.                 return n;
  84.             }
  85.             n += 2; // n % 3 == 1
  86.             if (isPrime(n)) {
  87.                 return n;
  88.             }
  89.             n += 4; // n % 3 == 2
  90.         }
  91.     }

  92.     /**
  93.      * Prime factors decomposition.
  94.      *
  95.      * @param n Number to factorize: must be &ge; 2.
  96.      * @return the list of prime factors of {@code n}.
  97.      * @throws IllegalArgumentException if n &lt; 2.
  98.      */
  99.     public static List<Integer> primeFactors(int n) {
  100.         if (n < 2) {
  101.             throw new IllegalArgumentException(String.format(NUMBER_TOO_SMALL, n, 2));
  102.         }
  103.         return SmallPrimes.trialDivision(n);
  104.     }
  105. }