-- |
-- Module      : Math.OEIS.HybridInteger
-- Copyright   : (c) Eric Bailey, 2020-2024
--
-- License     : MIT
-- Maintainer  : eric@ericb.me
-- Stability   : experimental
-- Portability : POSIX
--
-- See 'Math.OEIS.a082949'.
module Math.OEIS.HybridInteger where

import Data.Function (on)
import Math.NumberTheory.Primes (Prime, unPrime)

-- | A number of the form \(p^{q}q^{p}\), with distinct primes \(p\) and \(q\).
data HybridInteger
  = HybridInteger (Prime Integer) (Prime Integer)

instance Show HybridInteger where
  show :: HybridInteger -> String
show (HybridInteger Prime Integer
p Prime Integer
q) =
    String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show (Prime Integer -> Integer
forall a. Prime a -> a
unPrime Prime Integer
p) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
", " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show (Prime Integer -> Integer
forall a. Prime a -> a
unPrime Prime Integer
q) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

instance Eq HybridInteger where
  == :: HybridInteger -> HybridInteger -> Bool
(==) = Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Integer -> Integer -> Bool)
-> (HybridInteger -> Integer)
-> HybridInteger
-> HybridInteger
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` HybridInteger -> Integer
hybridIntegerValue

instance Ord HybridInteger where
  <= :: HybridInteger -> HybridInteger -> Bool
(<=) = Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
(<=) (Integer -> Integer -> Bool)
-> (HybridInteger -> Integer)
-> HybridInteger
-> HybridInteger
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` HybridInteger -> Integer
hybridIntegerValue

-- | The integer value of a 'HybridInteger', i.e. \(p^{q}q^{p}\).
hybridIntegerValue :: HybridInteger -> Integer
hybridIntegerValue :: HybridInteger -> Integer
hybridIntegerValue (HybridInteger Prime Integer
p Prime Integer
q) = Integer
p' Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
q' Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
q' Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
p'
  where
    p' :: Integer
p' = Prime Integer -> Integer
forall a. Prime a -> a
unPrime Prime Integer
p
    q' :: Integer
q' = Prime Integer -> Integer
forall a. Prime a -> a
unPrime Prime Integer
q