{-# OPTIONS_GHC -fno-warn-orphans #-}
{-
The orphan instance could be fixed
by making this module mutually recursive with ToRational.hs,
but that's not worth the complication.
-}

module Algebra.ToInteger where

import qualified Number.Ratio as Ratio

import qualified Algebra.ToRational     as ToRational
import qualified Algebra.Field          as Field
import qualified Algebra.PrincipalIdealDomain as PID
import qualified Algebra.RealIntegral   as RealIntegral
import qualified Algebra.Ring           as Ring

import Number.Ratio (T((:%)), )

import Algebra.Field ((^-), )
import Algebra.Ring ((^), fromInteger, )

import Data.Int  (Int,  Int8,  Int16,  Int32,  Int64,  )
import Data.Word (Word, Word8, Word16, Word32, Word64, )

import qualified Prelude as P
import NumericPrelude.Base
import Prelude (Integer, Float, Double, )


{- |
The two classes 'Algebra.ToInteger.C' and 'Algebra.ToRational.C'
exist to allow convenient conversions,
primarily between the built-in types.
They should satisfy

>   fromInteger .  toInteger === id
>    toRational .  toInteger === toRational

Conversions must be lossless,
that is, they do not round in any way.
For rounding see "Algebra.RealRing".

I think that the RealIntegral superclass is too restrictive.
Non-negative numbers are not a ring,
but can be easily converted to Integers.
-}
class (ToRational.C a, RealIntegral.C a) => C a where
   toInteger :: a -> Integer


{-# NOINLINE [2] fromIntegral #-}
fromIntegral :: (C a, Ring.C b) => a -> b
fromIntegral :: a -> b
fromIntegral = Integer -> b
forall a. C a => Integer -> a
fromInteger (Integer -> b) -> (a -> Integer) -> a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Integer
forall a. C a => a -> Integer
toInteger


-- generated by GenerateRules.hs
{-# RULES
     "NP.fromIntegral :: Integer -> Int"     fromIntegral = P.fromIntegral :: Integer -> Int;
     "NP.fromIntegral :: Integer -> Integer" fromIntegral = P.fromIntegral :: Integer -> Integer;
     "NP.fromIntegral :: Integer -> Float"   fromIntegral = P.fromIntegral :: Integer -> Float;
     "NP.fromIntegral :: Integer -> Double"  fromIntegral = P.fromIntegral :: Integer -> Double;
     "NP.fromIntegral :: Int -> Int"         fromIntegral = P.fromIntegral :: Int -> Int;
     "NP.fromIntegral :: Int -> Integer"     fromIntegral = P.fromIntegral :: Int -> Integer;
     "NP.fromIntegral :: Int -> Float"       fromIntegral = P.fromIntegral :: Int -> Float;
     "NP.fromIntegral :: Int -> Double"      fromIntegral = P.fromIntegral :: Int -> Double;
     "NP.fromIntegral :: Int8 -> Int"        fromIntegral = P.fromIntegral :: Int8 -> Int;
     "NP.fromIntegral :: Int8 -> Integer"    fromIntegral = P.fromIntegral :: Int8 -> Integer;
     "NP.fromIntegral :: Int8 -> Float"      fromIntegral = P.fromIntegral :: Int8 -> Float;
     "NP.fromIntegral :: Int8 -> Double"     fromIntegral = P.fromIntegral :: Int8 -> Double;
     "NP.fromIntegral :: Int16 -> Int"       fromIntegral = P.fromIntegral :: Int16 -> Int;
     "NP.fromIntegral :: Int16 -> Integer"   fromIntegral = P.fromIntegral :: Int16 -> Integer;
     "NP.fromIntegral :: Int16 -> Float"     fromIntegral = P.fromIntegral :: Int16 -> Float;
     "NP.fromIntegral :: Int16 -> Double"    fromIntegral = P.fromIntegral :: Int16 -> Double;
     "NP.fromIntegral :: Int32 -> Int"       fromIntegral = P.fromIntegral :: Int32 -> Int;
     "NP.fromIntegral :: Int32 -> Integer"   fromIntegral = P.fromIntegral :: Int32 -> Integer;
     "NP.fromIntegral :: Int32 -> Float"     fromIntegral = P.fromIntegral :: Int32 -> Float;
     "NP.fromIntegral :: Int32 -> Double"    fromIntegral = P.fromIntegral :: Int32 -> Double;
     "NP.fromIntegral :: Int64 -> Int"       fromIntegral = P.fromIntegral :: Int64 -> Int;
     "NP.fromIntegral :: Int64 -> Integer"   fromIntegral = P.fromIntegral :: Int64 -> Integer;
     "NP.fromIntegral :: Int64 -> Float"     fromIntegral = P.fromIntegral :: Int64 -> Float;
     "NP.fromIntegral :: Int64 -> Double"    fromIntegral = P.fromIntegral :: Int64 -> Double;
     "NP.fromIntegral :: Word -> Int"        fromIntegral = P.fromIntegral :: Word -> Int;
     "NP.fromIntegral :: Word -> Integer"    fromIntegral = P.fromIntegral :: Word -> Integer;
     "NP.fromIntegral :: Word -> Float"      fromIntegral = P.fromIntegral :: Word -> Float;
     "NP.fromIntegral :: Word -> Double"     fromIntegral = P.fromIntegral :: Word -> Double;
     "NP.fromIntegral :: Word8 -> Int"       fromIntegral = P.fromIntegral :: Word8 -> Int;
     "NP.fromIntegral :: Word8 -> Integer"   fromIntegral = P.fromIntegral :: Word8 -> Integer;
     "NP.fromIntegral :: Word8 -> Float"     fromIntegral = P.fromIntegral :: Word8 -> Float;
     "NP.fromIntegral :: Word8 -> Double"    fromIntegral = P.fromIntegral :: Word8 -> Double;
     "NP.fromIntegral :: Word16 -> Int"      fromIntegral = P.fromIntegral :: Word16 -> Int;
     "NP.fromIntegral :: Word16 -> Integer"  fromIntegral = P.fromIntegral :: Word16 -> Integer;
     "NP.fromIntegral :: Word16 -> Float"    fromIntegral = P.fromIntegral :: Word16 -> Float;
     "NP.fromIntegral :: Word16 -> Double"   fromIntegral = P.fromIntegral :: Word16 -> Double;
     "NP.fromIntegral :: Word32 -> Int"      fromIntegral = P.fromIntegral :: Word32 -> Int;
     "NP.fromIntegral :: Word32 -> Integer"  fromIntegral = P.fromIntegral :: Word32 -> Integer;
     "NP.fromIntegral :: Word32 -> Float"    fromIntegral = P.fromIntegral :: Word32 -> Float;
     "NP.fromIntegral :: Word32 -> Double"   fromIntegral = P.fromIntegral :: Word32 -> Double;
     "NP.fromIntegral :: Word64 -> Int"      fromIntegral = P.fromIntegral :: Word64 -> Int;
     "NP.fromIntegral :: Word64 -> Integer"  fromIntegral = P.fromIntegral :: Word64 -> Integer;
     "NP.fromIntegral :: Word64 -> Float"    fromIntegral = P.fromIntegral :: Word64 -> Float;
     "NP.fromIntegral :: Word64 -> Double"   fromIntegral = P.fromIntegral :: Word64 -> Double;
  #-}


instance C Integer where {-#INLINE toInteger #-}; toInteger :: Integer -> Integer
toInteger = Integer -> Integer
forall a. a -> a
id

instance C Int     where {-#INLINE toInteger #-}; toInteger :: Int -> Integer
toInteger = Int -> Integer
forall a. Integral a => a -> Integer
P.toInteger
instance C Int8    where {-#INLINE toInteger #-}; toInteger :: Int8 -> Integer
toInteger = Int8 -> Integer
forall a. Integral a => a -> Integer
P.toInteger
instance C Int16   where {-#INLINE toInteger #-}; toInteger :: Int16 -> Integer
toInteger = Int16 -> Integer
forall a. Integral a => a -> Integer
P.toInteger
instance C Int32   where {-#INLINE toInteger #-}; toInteger :: Int32 -> Integer
toInteger = Int32 -> Integer
forall a. Integral a => a -> Integer
P.toInteger
instance C Int64   where {-#INLINE toInteger #-}; toInteger :: Int64 -> Integer
toInteger = Int64 -> Integer
forall a. Integral a => a -> Integer
P.toInteger

instance C Word    where {-#INLINE toInteger #-}; toInteger :: Word -> Integer
toInteger = Word -> Integer
forall a. Integral a => a -> Integer
P.toInteger
instance C Word8   where {-#INLINE toInteger #-}; toInteger :: Word8 -> Integer
toInteger = Word8 -> Integer
forall a. Integral a => a -> Integer
P.toInteger
instance C Word16  where {-#INLINE toInteger #-}; toInteger :: Word16 -> Integer
toInteger = Word16 -> Integer
forall a. Integral a => a -> Integer
P.toInteger
instance C Word32  where {-#INLINE toInteger #-}; toInteger :: Word32 -> Integer
toInteger = Word32 -> Integer
forall a. Integral a => a -> Integer
P.toInteger
instance C Word64  where {-#INLINE toInteger #-}; toInteger :: Word64 -> Integer
toInteger = Word64 -> Integer
forall a. Integral a => a -> Integer
P.toInteger


instance (C a, PID.C a) => ToRational.C (Ratio.T a) where
   toRational :: T a -> Rational
toRational (a
x:%a
y)   =  a -> Integer
forall a. C a => a -> Integer
toInteger a
x Integer -> Integer -> Rational
forall a. a -> a -> T a
:% a -> Integer
forall a. C a => a -> Integer
toInteger a
y


{-|
A prefix function of '(Algebra.Ring.^)'
with a parameter order that fits the needs of partial application
and function composition.
It has generalised exponent.

See: Argument order of @expNat@ on
<http://www.haskell.org/pipermail/haskell-cafe/2006-September/018022.html>
-}
ringPower :: (Ring.C a, C b) => b -> a -> a
ringPower :: b -> a -> a
ringPower b
exponent a
basis = a
basis a -> Integer -> a
forall a. C a => a -> Integer -> a
^ b -> Integer
forall a. C a => a -> Integer
toInteger b
exponent

{- |
A prefix function of '(Algebra.Field.^-)'.
It has a generalised exponent.
-}
fieldPower :: (Field.C a, C b) => b -> a -> a
fieldPower :: b -> a -> a
fieldPower b
exponent a
basis = a
basis a -> Integer -> a
forall a. C a => a -> Integer -> a
^- b -> Integer
forall a. C a => a -> Integer
toInteger b
exponent