packages feed

primes 0.1.1 → 0.1.1.1

raw patch · 4 files changed

+92/−37 lines, 4 filesdep ~basesetup-changedPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

Files

Data/Numbers/Primes.hs view
@@ -1,7 +1,7 @@ -- | -- Module      : Data.Numbers.Primes -- Copyright   : Sebastian Fischer--- License     : PublicDomain+-- License     : BSD3 --  -- Maintainer  : Sebastian Fischer (sebf@informatik.uni-kiel.de) -- Stability   : experimental@@ -16,43 +16,93 @@ --  module Data.Numbers.Primes ( primes, wheelSieve ) where --- |+-- |  -- This global constant is an infinite list of prime numbers. It is--- generated by a lazy wheel sieve and shared among different--- applications. If you are concerned about the memory requirements of--- sharing many primes you can call the function @wheelSieve@--- directly.+-- generated by a lazy wheel sieve and shared across the whole program+-- run. If you are concerned about the memory requirements of sharing+-- many primes you can call the function @wheelSieve@ directly. --  primes :: [Integer] primes = wheelSieve 6 --- |+-- |  -- This function returns an infinite list of prime numbers by sieving -- with a wheel that cancels the multiples of the first @n@ primes -- where @n@ is the argument given to @wheelSieve@. Don't use too--- large wheels because computing them is more expensive than--- sieving. The number @6@ is a good value to pass to this function.+-- large wheels. The number @6@ is a good value to pass to this+-- function. Larger wheels improve the run time at the cost of higher+-- memory requirements. --  wheelSieve :: Int        -- ^ number of primes canceled by the wheel            -> [Integer]  -- ^ infinite list of primes-wheelSieve k = reverse ps ++ sieve (spin p (cycle ns)) Empty- where (p:ps,ns)     = wheel k-       spin n (x:xs) = n : spin (n+x) xs-+wheelSieve k = reverse ps ++ map head (sieve p (cycle ns))+ where (p:ps,ns) = wheel k  -- Auxiliary Definitions ------------------------------------------------------------------------------ --- Sieves a list of prime candidates using a lazy priority queue.+-- Sieves prime candidates by computing composites from the result of+-- a recursive call with identical arguments. We could use sharing+-- instead of a recursive call with identical arguments but that would+-- lead to much higher memory requirements. The results of the+-- different calls are consumed at different speeds and we want to+-- avoid multiple far apart pointers into the result list to avoid+-- retaining everything in between. ---sieve :: [Integer] -> Queue -> [Integer]-sieve (n:ns) Empty = n : sieve ns (enqueue (map (n*) (n:ns)) Empty)-sieve (n:ns) queue-  | m == n      = sieve ns (enqueue ms q)-  | m < n       = sieve (n:ns) (enqueue ms q)-  | otherwise   = n : sieve ns (enqueue (map (n*) (n:ns)) queue)- where (m:ms,q) = dequeue queue+-- Each list in the result starts with a prime. To obtain composites+-- that need to be cancelled, one can multiply all elements of the+-- list with its head.+-- +sieve :: Integer -> [Integer] -> [[Integer]]+sieve p ns@(m:ms) = spin p ns : sieveComps (p+m) ms (composites p ns) +-- Composites are stored in increasing order in a priority queue. The+-- queue has an associated feeder which is used to avoid filling it+-- with entries that will only be used again much later. +-- +type Composites = (Queue,[[Integer]])++-- The feeder is computed from the result of a call to 'sieve'.+-- +composites :: Integer -> [Integer] -> Composites+composites p ns = (Empty, map comps (spin p ns : sieve p ns))+ where comps xs@(x:_) = map (x*) xs++-- We can split all composites into the next and remaining+-- composites. We use the feeder when appropriate and discard equal+-- entries to not return a composite twice.+-- +splitComposites :: Composites -> (Integer,Composites)+splitComposites (Empty, xs:xss) = splitComposites (Fork xs [], xss)+splitComposites (queue, xss@((x:xs):yss))+  | x < z     = (x, discard x (enqueue xs queue, yss))+  | otherwise = (z, discard z (enqueue zs queue', xss))+ where (z:zs,queue') = dequeue queue++-- Drops all occurrences of the given element.+--+discard :: Integer -> Composites -> Composites+discard n ns | n == m    = discard n ms+             | otherwise = ns+ where (m,ms) = splitComposites ns++-- This is the actual sieve. It discards candidates that are+-- composites and yields lists which start with a prime and contain+-- all factors of the composites that need to be dropped.+--+sieveComps :: Integer -> [Integer] -> Composites -> [[Integer]]+sieveComps cand ns@(m:ms) xs+  | cand == comp = sieveComps (cand+m) ms ys+  | cand <  comp = spin cand ns : sieveComps (cand+m) ms xs+  | otherwise    = sieveComps cand ns ys+ where (comp,ys) = splitComposites xs++-- This function computes factors of composites of primes by spinning+-- a wheel.+-- +spin :: Integer -> [Integer] -> [Integer]+spin x (y:ys) = x : spin (x+y) ys+ -- A wheel consists of a list of primes whose multiples are canceled -- and the actual wheel that is rolled for canceling. --@@ -83,12 +133,11 @@   | otherwise      = cancel m p n (x+y:zs)  where nx = n + x - -- We use a special version of priority queues implemented as /pairing/ -- /heaps/ (see /Purely Functional Data Structures/ by Chris Okasaki). ----- The queue stores non-empty lists of multiples; the first element is--- used as priority.+-- The queue stores non-empty lists of composites; the first element+-- is used as priority. -- data Queue = Empty | Fork [Integer] [Queue] @@ -96,15 +145,17 @@ enqueue ns = merge (Fork ns [])  merge :: Queue -> Queue -> Queue-merge Empty y = y; merge x Empty = x-merge x y | prio x <= prio y = join x y-          | otherwise        = join y x- where prio (Fork (n:_) _)   = n-       join (Fork ns qs) q   = Fork ns (q:qs)+merge Empty y                        = y+merge x     Empty                    = x+merge x     y     | prio x <= prio y = join x y+                  | otherwise        = join y x+ where prio (Fork (n:_) _) = n+       join (Fork ns qs) q = Fork ns (q:qs)  dequeue :: Queue -> ([Integer], Queue) dequeue (Fork ns qs) = (ns,mergeAll qs)  mergeAll :: [Queue] -> Queue-mergeAll [] = Empty; mergeAll [x] = x+mergeAll []       = Empty+mergeAll [x]      = x mergeAll (x:y:qs) = merge (merge x y) (mergeAll qs)
− Setup.hs
@@ -1,4 +0,0 @@-import Distribution.Simple--main = defaultMain-
+ Setup.lhs view
@@ -0,0 +1,8 @@+#! /usr/bin/env runhaskell++> module Main (main) where+>+> import Distribution.Simple (defaultMain)+>+> main :: IO ()+> main = defaultMain
primes.cabal view
@@ -1,5 +1,5 @@ Name:          primes-Version:       0.1.1+Version:       0.1.1.1 Cabal-Version: >= 1.6 Synopsis:      Efficient, purely functional generation of prime numbers Description:@@ -10,7 +10,7 @@   by Melissa O'Neil.  Category:      Algorithms, Numerical-License:       PublicDomain+License:       BSD3 License-File:  LICENSE Author:        Sebastian Fischer Maintainer:    Sebastian Fischer@@ -22,7 +22,7 @@ Extra-Source-Files: README  Library-  Build-Depends:    base+  Build-Depends:    base == 4.*   Exposed-Modules:  Data.Numbers.Primes   Ghc-Options:      -Wall -fno-warn-incomplete-patterns