lenstraECM :: Integer -> Integer -> Maybe Integer
lenstraECM number bound 
    | number `mod` 2 == 0 = Just 2
    | number `mod` 3 == 0 = Just 3
    | number `mod` 5 == 0 = Just 5
    | otherwise           = 
        let primes      = eratosthenesSieve bound
            primePowers = map (findHighestPower bound) primes
            upperBound  = (number - 1)
            curves      = filter (isElliptic number) $ map (\x -> MEC x 1) [1..upperBound]
        in lenstraECMLoop number primePowers curves
    where lenstraECMLoop _ _ [] = Nothing
          lenstraECMLoop number primePowers (ec:ecs)
              = if isNothing result then recurse else result
              where result  = lenstraECMTryEC number primePowers initP ec
                    recurse = lenstraECMLoop number primePowers ecs
                    initP   = Point 0 1
          lenstraECMTryEC _ [] _ _ = Nothing
          lenstraECMTryEC number (p:ps) accumPoint ec
              = either recurse Just result
              where recurse point = lenstraECMTryEC number ps point ec
                    result        = repeatedCubicLaw ec accumPoint p number
lenstraECM :: Integer -> Integer -> Maybe Integer
lenstraECM number bound 
    | number `mod` 2 == 0 = Just 2
    | number `mod` 3 == 0 = Just 3
    | number `mod` 5 == 0 = Just 5
    | otherwise           = 
        let primes      = eratosthenesSieve bound
            primePowers = map (findHighestPower bound) primes
            upperBound  = (number - 1)
            curves      = filter (isElliptic number) $ map (\x -> MEC x 1) [1..upperBound]
        in lenstraECMLoop number primePowers curves
    where lenstraECMLoop _ _ [] = Nothing
          lenstraECMLoop number primePowers (ec:ecs)
              = if isNothing result then recurse else result
              where result  = lenstraECMTryEC number primePowers initP ec
                    recurse = lenstraECMLoop number primePowers ecs
                    initP   = Point 0 1
          lenstraECMTryEC _ [] _ _ = Nothing
          lenstraECMTryEC number (p:ps) accumPoint ec
              = either recurse Just result
              where recurse point = lenstraECMTryEC number ps point ec
                    result        = repeatedCubicLaw ec accumPoint p number
lenstraECM number bound 
    | number `mod` 2 == 0 = Just 2
    | number `mod` 3 == 0 = Just 3
    | number `mod` 5 == 0 = Just 5
    | otherwise           = 
        let primes      = eratosthenesSieve bound
            primePowers = map (findHighestPower bound) primes
            upperBound  = (number - 1)
            curves      = filter (isElliptic number) $ map (\x -> MEC x 1) [1..upperBound]
        in lenstraECMLoop number primePowers curves
    where lenstraECMLoop _ _ [] = Nothing
          lenstraECMLoop number primePowers (ec:ecs)
              = if isNothing result then recurse else result
              where result  = lenstraECMTryEC number primePowers initP ec
                    recurse = lenstraECMLoop number primePowers ecs
                    initP   = Point 0 1
          lenstraECMTryEC _ [] _ _ = Nothing
          lenstraECMTryEC number (p:ps) accumPoint ec
              = either recurse Just result
              where recurse point = lenstraECMTryEC number ps point ec
                    result        = repeatedCubicLaw ec accumPoint p number