aticPrimePower
  :: Integer
  -> Integer
  -> Integer
  -> Prime Integer
  -> Word
  -> [Integer]
solveQuadraticPrimePower a b c p = go
  where
    go :: Word -> [Integer]
    go 0 = [0]
    go 1 = solveQuadraticPrime a b c p
    go k = concatMap (liftRoot k) (go (k - 1))

    -- Hensel lifting
    -- https://en.wikipedia.org/wiki/Hensel%27s_lemma#Hensel_lifting
    liftRoot :: Word -> Integer -> [Integer]
    liftRoot k r = case recipMod (2 * a * r + b) pk of
      Nothing -> case fr of
        0 -> map (\i -> r + pk `quot` p' * i) [0 .. p' - 1]
        _ -> []
      Just invDeriv -> [(r - fr * invDeriv) `mod` pk]
      where
        pk = p' ^ k
        fr = (a * r * r + b * r + c) `mod` pk

    p' :: Integer
    p' = unPrime p

solveQua
solveQuadraticPrimePower
  :: Integer
  -> Integer
  -> Integer
  -> Prime Integer
  -> Word
  -> [Integer]
solveQuadraticPrimePower a b c p = go
  where
    go :: Word -> [Integer]
    go 0 = [0]
    go 1 = solveQuadraticPrime a b c p
    go k = concatMap (liftRoot k) (go (k - 1))

    -- Hensel lifting
    -- https://en.wikipedia.org/wiki/Hensel%27s_lemma#Hensel_lifting
    liftRoot :: Word -> Integer -> [Integer]
    liftRoot k r = case recipMod (2 * a * r + b) pk of
      Nothing -> case fr of
        0 -> map (\i -> r + pk `quot` p' * i) [0 .. p' - 1]
        _ -> []
      Just invDeriv -> [(r - fr * invDeriv) `mod` pk]
      where
        pk = p' ^ k
        fr = (a * r * r + b * r + c) `mod` pk

    p' :: Integer
    p' = unPrime p
solveQuadraticPrimePower a b c p = go
  where
    go :: Word -> [Integer]
    go 0 = [0]
    go 1 = solveQuadraticPrime a b c p
    go k = concatMap (liftRoot k) (go (k - 1))

    -- Hensel lifting
    -- https://en.wikipedia.org/wiki/Hensel%27s_lemma#Hensel_lifting
    liftRoot :: Word -> Integer -> [Integer]
    liftRoot k r = case recipMod (2 * a * r + b) pk of
      Nothing -> case fr of
        0 -> map (\i -> r + pk `quot` p' * i) [0 .. p' - 1]
        _ -> []
      Just invDeriv -> [(r - fr * invDeriv) `mod` pk]
      where
        pk = p' ^ k
        fr = (a * r * r + b * r + c) `mod` pk

    p' :: Integer
    p' = unPrime p