{-|

Module      : Data.Prime
Description : prime number tools
Copyright   : (C) 2021 Jonathan Lamothe
License     : GPLv3 (or later)
Maintainer  : jonathan@jlamothe.net
Stability   : stable

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

-}

module Data.Prime (primes, isPrime, isComposite) where

-- | a list of all prime numbers
primes :: [Integer]
primes :: [Integer]
primes = Integer -> [Integer] -> [Integer]
f Integer
2 [] where
  f :: Integer -> [Integer] -> [Integer]
f Integer
n [Integer]
ps = if Integer -> [Integer] -> Bool
checkPrimes Integer
n [Integer]
ps
    then Integer
n Integer -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
: Integer -> [Integer] -> [Integer]
f (Integer -> Integer
forall a. Enum a => a -> a
succ Integer
n) ([Integer]
ps [Integer] -> [Integer] -> [Integer]
forall a. [a] -> [a] -> [a]
++ [Integer
n])
    else Integer -> [Integer] -> [Integer]
f (Integer -> Integer
forall a. Enum a => a -> a
succ Integer
n) [Integer]
ps

-- | checks to see if a given number is prime
isPrime :: Integral n => n -> Bool
isPrime :: n -> Bool
isPrime n
n = if n
n n -> n -> Bool
forall a. Ord a => a -> a -> Bool
< n
2
  then Bool
False
  else Integer -> [Integer] -> Bool
checkPrimes (n -> Integer
forall a. Integral a => a -> Integer
toInteger n
n) [Integer]
primes

-- | checks to see if a given number is composite
isComposite :: Integral n => n -> Bool
isComposite :: n -> Bool
isComposite n
n = if n
n n -> n -> Bool
forall a. Ord a => a -> a -> Bool
< n
2
  then Bool
False
  else Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Integer -> [Integer] -> Bool
checkPrimes (n -> Integer
forall a. Integral a => a -> Integer
toInteger n
n) [Integer]
primes

checkPrimes :: Integer -> [Integer] -> Bool
checkPrimes :: Integer -> [Integer] -> Bool
checkPrimes Integer
_ [] = Bool
True
checkPrimes Integer
n (Integer
p:[Integer]
ps)
  | Integer
p Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
p Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
n      = Bool
True
  | Integer
n Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
p Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = Bool
False
  | Bool
otherwise      = Integer -> [Integer] -> Bool
checkPrimes Integer
n [Integer]
ps

--jl