All Downloads are FREE. Search and download functionalities are using the official Maven repository.

spire.math.prime.FactorHeap.scala Maven / Gradle / Ivy

The newest version!
package spire
package math.prime

import SieveUtil._

/**
 * Simple heap implementation for storing Factors.
 *
 * The heap can hold at most ~2B items, which means we can't store
 * more than this many prime factors.
 *
 * Note that "fast factors" don't end up in this heap, so the number
 * of primes we can sieve is actaully the max heap size + the number
 * of fast factors.
 *
 * The sieve implementation itself uses a cutoff, so to test primality
 * of numbers <= K, we need to be able to store prime factors up to
 * sqrt(K) in our heap. Since our heap can hold ~2B prime factors,
 * this means the theoretical upper bound on our segmented sieve is
 * (~2Bth prime)^2.
 *
 * In practice the sieve will slow down to the point of not being
 * useful far before we could reach this limit.
 */
class FactorHeap {

  private[this] var arr: Array[Factor] = new Array[Factor](8)
  private[this] var len: Int = 0

  override def toString: String =
    arr.filter(_ != null).map(_.next).mkString("FactorHeap(", ", ", ")")

  def isEmpty: Boolean = len == 0

  def nonEmpty: Boolean = len > 0

  def size: Int = len

  def resizeIfNecessary(): Unit =
    if (len >= arr.length) {
      val arr2 = new Array[Factor](arr.length * 2)
      System.arraycopy(arr, 0, arr2, 0, arr.length)
      arr = arr2
    }

  def +=(factor: Factor): Unit = {
    len += 1
    resizeIfNecessary()
    var i = len
    while (i > 1) {
      val j = i >>> 1
      val fj = arr(j)
      if (factor.next >= fj.next) { arr(i) = factor; return () }
      arr(i) = fj
      i = j
    }
    arr(i) = factor
  }

  def dequeue(): Factor = {
    if (len == 0) throw new NoSuchElementException("empty heap")
    val result = arr(1)
    val last = arr(len)
    len -= 1 // points to last valid slot

    var i = 1
    var j = 2
    while (len >= j) {
      if (j < len && arr(j).next > arr(j + 1).next) j += 1
      val cv = arr(j)
      if (last.next <= cv.next) { arr(i) = last; return result }
      arr(i) = cv
      i = j
      j *= 2
    }
    arr(i) = last
    result
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy