packages feed

affinely-extended (empty) → 0.1.0.0

raw patch · 4 files changed

+1198/−0 lines, 4 filesdep +basesetup-changed

Dependencies added: base

Files

+ LICENSE view
@@ -0,0 +1,19 @@+Copyright 2017 Clinton Mead++Permission is hereby granted, free of charge, to any person obtaining a copy of+this software and associated documentation files (the "Software"), to deal in+the Software without restriction, including without limitation the rights to+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies+of the Software, and to permit persons to whom the Software is furnished to do+so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ affinely-extended.cabal view
@@ -0,0 +1,39 @@+name:                 affinely-extended+version:              0.1.0.0+synopsis:             +description:+  A simply way to extend numerical types to add infinity.+  .+  Includes 4 data types:+  .+  1. Both infinities: GADT+  .+  2. Positive infinity only: GADT+  .+  3. Both infinities, represented as upper and lower bound of type (well almost)+  .+  4. Positive infinity only, represented as upper bound of type+  .+  There's also rewrite rules in an attempt to make this all work as efficiently as possible (although unbenchmarked and untested).+  .+license: MIT+license-file: LICENSE+homepage:             https://github.com/clintonmead/affinely-extended+author:               Clinton Mead+maintainer:           clintonmead@gmail.com+category:             Data+copyright:            Clinton Mead (2017)+build-type:           Simple+cabal-version:        >=1.10+tested-with: GHC == 8.0.2+bug-reports: https://github.com/clintonmead/affinely-extended/issues++source-repository head+  type: git+  location: https://github.com/clintonmead/affinely-extended.git++library+  exposed-modules: Data.AffinelyExtend+  build-depends:        base >= 4.7 && < 5+  hs-source-dirs:       src+  default-language:     Haskell2010
+ src/Data/AffinelyExtend.hs view
@@ -0,0 +1,1138 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+This package has four ways to extend any numerical type to add infinities:++1. Both infinities with GADT: 'AffinelyExtendBoth', creation: 'affinelyExtendBoth'+2. Positive infinity only with GADT: 'AffinelyExtendPos', creation: 'affinelyExtendPos'+3. Both infinities with upper/lower bounds as infinity: 'AffinelyExtendBoundedBoth', creation: 'affinelyExtendBoundedBoth'+4. Positive infinities only with upper bound as infinity: 'AffinelyExtendBoundedPos', creation: 'affinelyExtendBoundedPos'++The function 'affinelyExtend' is a generic creation function that calls one of the above based on the derived type of the output.++A few notes. Firstly, option 3, the 'AffinelyExtendBoundedBoth' option, does not actually use 'maxBound' and 'minBound' as+positive and negative infinity respectively, it actually takes the smallest absolute value 'maxBound' and 'minBound' as+positive infinity and the negation of that as negative infinity.++This means, for example, on an 'Int8', +127 is positive infinity, but -127 is negative infinity, not -128. So the valid finite+range for the type becomes [-126..126].++Storable and unboxed instances for bounded types (i.e. 'AffinelyExtendBoundedBoth' and 'AffinelyExtendBoundedPos') should be+trivial to create.++This package refers to the first two types, namely 'AffinelyExtendBoth' and 'AffinelyExtendPos' as unpacked types. When they're used+directly, packing and unpacking is just 'id', but when the bounded types are used, they are unpacked into these types and packed back+into themselves.++For most operations, the bounded types simply unpack to the unbounded types, perform the unpacked operation, and then pack themselves.++But there's two optimisations to this process++1. For operations like 'negate', there is no need for special checking for infinities, so the unbounded types just apply negate directly+to their own representation.+2. There's rewrite rules that remove 'unpack . pack' sequences.++There's competing advantages to both formats. The bounded formats obviously take up less storage space, and can perform some operations+like 'negate' without a pattern match.++However, chains of operations on the  "packed" bounded types that do need to check for infinity will check everytime, because there's+no way for the compiler to disguish between and operation that has overflowed and "accidently" became infinity and actual infinity.++So the rewrite rules are intended to help chains of operations use the "unpacked" represenation, which hopefully should reduce the+infinity checks to the first operation in the sequence (as after that the compiler should be able to statically prove at compile time+that the latter operations are/are not infinities.++This package is currently without a test suite and needs more documentation, so if you find any bugs, please report them.+-}+module Data.AffinelyExtend (+  AffinelyExtend(NegativeInfinity, Finite, PositiveInfinity), affinelyExtend,+  AffinelyExtendBoth, affinelyExtendBoth,+  AffinelyExtendPos, affinelyExtendPos,+  AffinelyExtendBoundedBoth, affinelyExtendBoundedBoth,+  AffinelyExtendBoundedPos, affinelyExtendBoundedPos,+  CanAffinelyExtend, isPos, isNegInf, isInf, isFinite, BaseType, UnpackType, affinelyExtend_c, unpack_c, unpackBoth_c,+  CanAffinelyExtendPos, unpackPos_c,+  HasPositiveInfinity, posInf,+  HasBothInfinities, negInf+) where++import Control.Exception.Base (assert)+import GHC.Exts (Constraint)+import Data.Maybe (maybeToList)+import Control.Applicative ((<|>))++data AffinelyExtend (hasNegativeInfinity :: Bool) a where+  NegativeInfinity :: AffinelyExtend True a+  Finite :: a -> AffinelyExtend h a+  PositiveInfinity :: AffinelyExtend h a++type AffinelyExtendBoth a = AffinelyExtend True a+type AffinelyExtendPos a = AffinelyExtend False a++newtype AffinelyExtendBoundedBoth a = AffinelyExtendBoundedBoth { getAffinelyExtendBounded :: a }+newtype AffinelyExtendBoundedPos a = AffinelyExtendBoundedPos { getAffinelyExtendBoundedPos :: a }++class HasPositiveInfinity a where+  posInf :: a++class HasPositiveInfinity a => HasBothInfinities a where+  negInf :: a++unwrappedPosInf :: (Bounded a, Ord a, Num a) => a+unwrappedPosInf = min maxBound (negate minBound)++unwrappedNegInf :: (Bounded a, Ord a, Num a) => a+unwrappedNegInf = negate unwrappedPosInf++unwrappedPosInfPos :: (Bounded a) => a+unwrappedPosInfPos = maxBound++instance HasPositiveInfinity (AffinelyExtendBoth a) where+  posInf = PositiveInfinity++instance HasBothInfinities (AffinelyExtendBoth a) where+  negInf = NegativeInfinity++instance HasPositiveInfinity (AffinelyExtendPos a) where+  posInf = PositiveInfinity++instance (Bounded a, Ord a, Num a) => HasPositiveInfinity (AffinelyExtendBoundedBoth a) where+  posInf = AffinelyExtendBoundedBoth unwrappedPosInf++instance (Bounded a, Ord a, Num a) => HasBothInfinities (AffinelyExtendBoundedBoth a) where+  negInf = AffinelyExtendBoundedBoth unwrappedNegInf++instance (Eq a, Bounded a) => HasPositiveInfinity (AffinelyExtendBoundedPos a) where+  posInf = AffinelyExtendBoundedPos unwrappedPosInfPos++instance HasPositiveInfinity Float where+  posInf = 1 / 0++instance HasBothInfinities Float where+  negInf = (-1) / 0++instance HasPositiveInfinity Double where+  posInf = 1 / 0++instance HasBothInfinities Double where+  negInf = (-1) / 0++unpackSameBaseType :: (Eq a, HasBothInfinities a, BaseType a ~ a) => a -> AffinelyExtendBoth (BaseType a)+unpackSameBaseType x = if+  | x == posInf -> PositiveInfinity+  | x == negInf -> NegativeInfinity+  | otherwise -> Finite x++class CanAffinelyExtend a where+  type BaseType a+  affinelyExtend_c :: BaseType a -> a++  type UnpackType a+  type UnpackType a = AffinelyExtendBoth (BaseType a)++  unpack_c :: a -> UnpackType a+  default unpack_c :: (UnpackType a ~ AffinelyExtendBoth (BaseType a)) => a -> UnpackType a+  unpack_c = unpackBoth_c++  unpackBoth_c :: a -> AffinelyExtendBoth (BaseType a)+  default unpackBoth_c :: (Eq a, HasBothInfinities a, BaseType a ~ a) => a -> AffinelyExtendBoth (BaseType a)+  unpackBoth_c = unpackSameBaseType++  isPos :: a -> Bool+  isPos x = case (unpackBoth x) of+    PositiveInfinity -> True+    _ -> False++  isNegInf :: a -> Bool+  isNegInf x = case (unpackBoth x) of+     NegativeInfinity -> True+     _ -> False++  isInf :: a -> Bool+  isInf x = isPos x || isNegInf x++  isFinite :: a -> Bool+  isFinite = not . isInf++instance CanAffinelyExtend (AffinelyExtendBoth a) where+  type BaseType (AffinelyExtendBoth a) = a+  affinelyExtend_c = Finite+  unpackBoth_c = id++instance CanAffinelyExtend (AffinelyExtendPos a) where+  type BaseType (AffinelyExtendPos a) = a+  type UnpackType (AffinelyExtendPos a) = AffinelyExtendPos a++  unpack_c = unpackPos_c++  affinelyExtend_c = Finite+  unpackBoth_c = \case+    Finite x -> Finite x+    PositiveInfinity -> PositiveInfinity++  isPos = \case+    PositiveInfinity -> True+    _ -> False+  isNegInf _ = False+  isInf = isPos+  isFinite = not . isInf+++{-# INLINE [1] isPosBounded #-}+isPosBounded :: (Ord a, Num a, Bounded a) => AffinelyExtendBoundedBoth a -> Bool+isPosBounded = applyToBounded (== unwrappedPosInf)++{-# INLINE [1] isNegInfBounded #-}+isNegInfBounded :: (Ord a, Num a, Bounded a) => AffinelyExtendBoundedBoth a -> Bool+isNegInfBounded = applyToBounded (== unwrappedNegInf)++{-# INLINE [1] isInfBounded #-}+isInfBounded :: (Ord a, Num a, Bounded a) => AffinelyExtendBoundedBoth a -> Bool+isInfBounded = applyToBounded (\x -> abs x == unwrappedPosInf)++{-# INLINE [1] isFiniteBounded #-}+isFiniteBounded :: (Ord a, Num a, Bounded a) => AffinelyExtendBoundedBoth a -> Bool+isFiniteBounded = applyToBounded (\x -> abs x /= unwrappedPosInf)++{-# RULES+"isPosBounded/pack" forall x. isPosBounded (packBoth x) = isPos x+"isNegInfBounded/pack" forall x. isNegInfBounded (packBoth x) = isNegInf x+"isInfBounded/pack" forall x. isInfBounded (packBoth x) = isInf x+"isFiniteBounded/pack" forall x. isFiniteBounded (packBoth x) = isFinite x+#-}++instance (Ord a, Bounded a, Num a) => CanAffinelyExtend (AffinelyExtendBoundedBoth a) where+  type BaseType (AffinelyExtendBoundedBoth a) = a+  affinelyExtend_c = AffinelyExtendBoundedBoth+  unpackBoth_c (AffinelyExtendBoundedBoth x) = if+    | x == unwrappedPosInf -> PositiveInfinity+    | x == unwrappedNegInf -> NegativeInfinity+    | otherwise -> Finite x++  isPos = isPosBounded+  isNegInf = isNegInfBounded++  isInf = isInfBounded+  isFinite = isFiniteBounded++{-# INLINE [1] isPosInfBoundedPos #-}+isPosInfBoundedPos :: (Eq a, Bounded a) => AffinelyExtendBoundedPos a -> Bool+isPosInfBoundedPos = applyToBounded (== unwrappedPosInfPos)++{-# INLINE [1] isFiniteBoundedPos #-}+isFiniteBoundedPos :: (Eq a, Bounded a) => AffinelyExtendBoundedPos a -> Bool+isFiniteBoundedPos = applyToBounded (/= unwrappedPosInfPos)++{-# RULES+"isPosInfBoundedPos/pack" forall x. isPosInfBoundedPos (packPos x) = isPos x+"isFiniteBoundedPos/pack" forall x. isFiniteBoundedPos (packPos x) = isFinite x+#-}++instance (Eq a, Bounded a) => CanAffinelyExtend (AffinelyExtendBoundedPos a) where+  type BaseType (AffinelyExtendBoundedPos a) = a+  type UnpackType (AffinelyExtendBoundedPos a) = AffinelyExtendPos a++  unpack_c = unpackPos_c++  affinelyExtend_c = AffinelyExtendBoundedPos+  unpackBoth_c (AffinelyExtendBoundedPos x) = if+    | x == unwrappedPosInfPos -> PositiveInfinity+    | otherwise -> Finite x++  isPos = isPosInfBoundedPos++  isNegInf _ = False++  isInf = isPos+  isFinite = isFiniteBoundedPos++instance CanAffinelyExtendPos (AffinelyExtendPos a) where+  unpackPos_c = id++instance (Eq a, Bounded a) => CanAffinelyExtendPos (AffinelyExtendBoundedPos a) where+  unpackPos_c (AffinelyExtendBoundedPos x) = if+    | x == unwrappedPosInfPos -> PositiveInfinity+    | otherwise -> Finite x++instance CanAffinelyExtend Float where+  type BaseType Float = Float+  affinelyExtend_c = id+  unpackBoth_c = unpackSameBaseType++instance CanAffinelyExtend Double where+  type BaseType Double = Double+  affinelyExtend_c = id+  unpackBoth_c = unpackSameBaseType++-- Packing++{-# INLINE [1] affinelyExtend #-}+affinelyExtend :: CanAffinelyExtend a => BaseType a -> a+affinelyExtend = affinelyExtend_c++affinelyExtendBoth :: a -> AffinelyExtendBoth a+affinelyExtendBoth = affinelyExtend++affinelyExtendPos :: a -> AffinelyExtendPos a+affinelyExtendPos = affinelyExtend++affinelyExtendBoundedBoth :: (Ord a, Bounded a, Num a) => a -> AffinelyExtendBoundedBoth a+affinelyExtendBoundedBoth = affinelyExtend++affinelyExtendBoundedPos :: (Eq a, Bounded a) => a -> AffinelyExtendBoundedPos a+affinelyExtendBoundedPos = affinelyExtend++{-# INLINE unpack #-}+unpack :: CanAffinelyExtend a => a -> UnpackType a+unpack = unpack_c++{-# INLINE [1] unpackBoth #-}+unpackBoth :: CanAffinelyExtend a => a -> AffinelyExtendBoth (BaseType a)+unpackBoth = unpackBoth_c++class (CanAffinelyExtend a) => CanAffinelyExtendPos a where+  unpackPos_c :: a -> AffinelyExtendPos (BaseType a)++{-# INLINE [1] unpackPos #-}+unpackPos :: (CanAffinelyExtendPos a) => a -> AffinelyExtendPos (BaseType a)+unpackPos = unpackPos_c++{-# INLINE [1] packBoth #-}+packBoth :: (HasBothInfinities a, CanAffinelyExtend a) => AffinelyExtendBoth (BaseType a) -> a+packBoth = \case+  Finite x -> affinelyExtend x+  PositiveInfinity -> posInf+  NegativeInfinity -> negInf++{-# INLINE [1] packPos #-}+packPos :: (HasPositiveInfinity a, CanAffinelyExtend a) => AffinelyExtendPos (BaseType a)-> a+packPos = \case+  Finite x -> affinelyExtend x+  PositiveInfinity -> posInf++class CanAffinelyPack t where+  type CanAffinelyPackConstraint t a :: Constraint+  pack_c :: (CanAffinelyPackConstraint t a) => t (BaseType a) -> a++instance CanAffinelyPack (AffinelyExtend True) where+  type CanAffinelyPackConstraint (AffinelyExtend True) a = (HasBothInfinities a, CanAffinelyExtend a)+  pack_c = packBoth++instance CanAffinelyPack (AffinelyExtend False) where+  type CanAffinelyPackConstraint (AffinelyExtend False) a = (HasPositiveInfinity a, CanAffinelyExtend a)+  pack_c = packPos+++{-# INLINE pack #-}+pack :: (CanAffinelyPack t, CanAffinelyPackConstraint t a) => t (BaseType a) -> a+pack = pack_c+++{-# RULES+"unpackBoth/packBoth" forall x. unpackBoth (packBoth x) = x+"unpackPos/packPos" forall x. unpackPos (packPos x) = x+#-}++class GetRawVal a where+  getRawVal :: a -> BaseType a+  setRawVal :: BaseType a -> a++instance GetRawVal (AffinelyExtendBoundedBoth a) where+  getRawVal (AffinelyExtendBoundedBoth x) = x+  setRawVal = AffinelyExtendBoundedBoth++instance GetRawVal (AffinelyExtendBoundedPos a) where+  getRawVal (AffinelyExtendBoundedPos x) = x+  setRawVal = AffinelyExtendBoundedPos++applyThroughBounded :: GetRawVal a => (BaseType a -> BaseType a) -> a -> a+applyThroughBounded f = setRawVal . (applyToBounded f)++applyToBounded :: GetRawVal a => (BaseType a -> b) -> a -> b+applyToBounded f = f . getRawVal++apply2ThroughBounded :: GetRawVal a => (BaseType a -> BaseType a -> BaseType a) -> a -> a -> a+apply2ThroughBounded f x y = setRawVal (apply2ToBounded f x y)++apply2ToBounded :: GetRawVal a => (BaseType a -> BaseType a -> b) -> a -> a -> b+apply2ToBounded f x y = f (getRawVal x) (getRawVal y)+++applyAffine :: (UnpackType a ~ b, b ~ t (BaseType a), CanAffinelyExtend a, CanAffinelyPack t, CanAffinelyPackConstraint t a) => (b -> b) -> a -> a+applyAffine f = pack . f . unpack++applyAffine2 :: (UnpackType a ~ b, b ~ t (BaseType a), CanAffinelyExtend a, CanAffinelyPack t, CanAffinelyPackConstraint t a) => (b -> b -> b) -> a -> a -> a+applyAffine2 f x y = pack (f (unpack x) (unpack y))++applyAffineOutPair2 :: (UnpackType a ~ b, b ~ t (BaseType a), CanAffinelyExtend a, CanAffinelyPack t, CanAffinelyPackConstraint t a) => (b -> b -> (b, b)) -> a -> a -> (a, a)+applyAffineOutPair2 f x y = let (x', y') = f (unpack x) (unpack y) in (pack x', pack y')++applyAffineNoPack :: (UnpackType a ~ b, b ~ t (BaseType a), CanAffinelyExtend a) => (b -> c) -> a -> c+applyAffineNoPack f = f . unpack+++-- Eq++instance Eq a => Eq (AffinelyExtendBoth a) where+  x == y = case (x,y) of+    (Finite x, Finite y) -> x == y+    (PositiveInfinity, PositiveInfinity) -> True+    (NegativeInfinity, NegativeInfinity) -> True+    _ -> False++  x /= y = case (x,y) of+    (Finite x, Finite y) -> x /= y+    (PositiveInfinity, PositiveInfinity) -> False+    (NegativeInfinity, NegativeInfinity) -> False+    _ -> True++instance Eq a => Eq (AffinelyExtendPos a) where+  x == y = case (x,y) of+    (Finite x, Finite y) -> x == y+    (PositiveInfinity, PositiveInfinity) -> True+    _ -> False++  x /= y = case (x,y) of+    (Finite x, Finite y) -> x /= y+    (PositiveInfinity, PositiveInfinity) -> False+    _ -> True++{-# INLINE [1] eqBounded #-}+eqBounded :: (GetRawVal a, Eq (BaseType a)) => a -> a -> Bool+eqBounded = apply2ToBounded (==)++{-# RULES+"eqBounded/pack" forall x y. (packPos x) `eqBounded` (packPos y) = x == y+"eqBounded/pack" forall x y. (packBoth x) `eqBounded` (packBoth y) = x == y+#-}++{-# INLINE [1] neqBounded #-}+neqBounded :: (GetRawVal a, Eq (BaseType a)) => a -> a -> Bool+neqBounded = apply2ToBounded (/=)++{-# RULES+"neqBounded/pack" forall x y. (packPos x) `neqBounded` (packPos y) = x /= y+"neqBounded/pack" forall x y. (packBoth x) `neqBounded` (packBoth y) = x /= y+#-}++instance Eq a => Eq (AffinelyExtendBoundedBoth a) where+  (==) = eqBounded+  (/=) = neqBounded++instance Eq a => Eq (AffinelyExtendBoundedPos a) where+  (==) = eqBounded+  (/=) = neqBounded++-- Ord++instance Ord a => Ord (AffinelyExtendBoth a) where+  x `compare` y = case (x,y) of+    (Finite x, Finite y) -> x `compare` y+    (PositiveInfinity, PositiveInfinity) -> EQ+    (NegativeInfinity, NegativeInfinity) -> EQ+    (_, PositiveInfinity) -> LT+    (PositiveInfinity, _) -> GT+    (NegativeInfinity, _) -> LT+    (_, NegativeInfinity) -> GT++  x < y = case (x,y) of+    (Finite x, Finite y) -> x < y+    (PositiveInfinity, _) -> False+    (_, NegativeInfinity) -> False+    _ -> True++  x <= y = case (x,y) of+    (Finite x, Finite y) -> x <= y+    (_, PositiveInfinity) -> True+    (NegativeInfinity, _) -> True+    _ -> False++  x > y = case (x,y) of+    (Finite x, Finite y) -> x > y+    (_, PositiveInfinity) -> False+    (NegativeInfinity, _) -> False+    _ -> True++  x >= y = case (x,y) of+    (Finite x, Finite y) -> x >= y+    (PositiveInfinity, _) -> True+    (_, NegativeInfinity) -> True+    _ -> False++  min x y = case (x, y) of+    (Finite x, Finite y) -> Finite (min x y)+    (_, PositiveInfinity) -> x+    (PositiveInfinity, _) -> y+    _ -> NegativeInfinity++  max x y = case (x, y) of+    (Finite x, Finite y) -> Finite (max x y)+    (_, NegativeInfinity) -> x+    (NegativeInfinity, _) -> y+    _ -> PositiveInfinity++instance Ord a => Ord (AffinelyExtendPos a) where+  x `compare` y = case (x,y) of+    (Finite x, Finite y) -> x `compare` y+    (PositiveInfinity, PositiveInfinity) -> EQ+    (Finite _, PositiveInfinity) -> LT+    (PositiveInfinity, Finite _) -> GT++  x < y = case (x,y) of+    (Finite x, Finite y) -> x < y+    (PositiveInfinity, _) -> False+    _ -> True++  x <= y = case (x,y) of+    (Finite x, Finite y) -> x <= y+    (_, PositiveInfinity) -> True+    _ -> False++  x > y = case (x,y) of+    (Finite x, Finite y) -> x > y+    (_, PositiveInfinity) -> False+    _ -> True++  x >= y = case (x,y) of+    (Finite x, Finite y) -> x >= y+    (PositiveInfinity, _) -> True+    _ -> False++  min x y = case (x, y) of+    (Finite x, Finite y) -> Finite (min x y)+    (_, PositiveInfinity) -> x+    (PositiveInfinity, _) -> y++  max x y = case (x, y) of+    (Finite x, Finite y) -> Finite (max x y)+    _ -> PositiveInfinity++{-# INLINE [1] compareBounded #-}+compareBounded :: (GetRawVal a, Ord (BaseType a)) => a -> a -> Ordering+compareBounded = apply2ToBounded compare++{-# RULES+"compareBounded/pack" forall x y. (packPos x) `compareBounded` (packPos y) = x `compare` y+"compareBounded/pack" forall x y. (packBoth x) `compareBounded` (packBoth y) = x `compare` y+#-}++{-# INLINE [1] ltBounded #-}+ltBounded :: (GetRawVal a, Ord (BaseType a)) => a -> a -> Bool+ltBounded = apply2ToBounded (<)++{-# RULES+"ltBounded/pack" forall x y. (packPos x) `ltBounded` (packPos y) = x < y+"ltBounded/pack" forall x y. (packBoth x) `ltBounded` (packBoth y) = x < y+#-}++{-# INLINE [1] gtBounded #-}+gtBounded :: (GetRawVal a, Ord (BaseType a)) => a -> a -> Bool+gtBounded = apply2ToBounded (>)++{-# RULES+"gtBounded/pack" forall x y. (packPos x) `gtBounded` (packPos y) = x > y+"gtBounded/pack" forall x y. (packBoth x) `gtBounded` (packBoth y) = x > y+#-}++{-# INLINE [1] lteBounded #-}+lteBounded :: (GetRawVal a, Ord (BaseType a)) => a -> a -> Bool+lteBounded = apply2ToBounded (<=)++{-# RULES+"lteBounded/pack" forall x y. (packPos x) `lteBounded` (packPos y) = x <= y+"lteBounded/pack" forall x y. (packBoth x) `lteBounded` (packBoth y) = x <= y+#-}++{-# INLINE [1] gteBounded #-}+gteBounded :: (GetRawVal a, Ord (BaseType a)) => a -> a -> Bool+gteBounded = apply2ToBounded (>=)++{-# RULES+"gteBounded/pack" forall x y. (packPos x) `gteBounded` (packPos y) = x >= y+"gteBounded/pack" forall x y. (packBoth x) `gteBounded` (packBoth y) = x >= y+#-}++{-# INLINE [1] maxBounded #-}+maxBounded :: (GetRawVal a, Ord (BaseType a)) => a -> a -> a+maxBounded = apply2ThroughBounded max++{-# RULES+"maxBounded/pack" forall x y. maxBounded (packPos x) (packPos y) = max x y+"maxBounded/pack" forall x y. maxBounded (packBoth x) (packBoth y) = max x y+#-}++{-# INLINE [1] minBounded #-}+minBounded :: (GetRawVal a, Ord (BaseType a)) => a -> a -> a+minBounded = apply2ThroughBounded min++{-# RULES+"minBounded/pack" forall x y. minBounded (packPos x) (packPos y) = min x y+"minBounded/pack" forall x y. minBounded (packBoth x) (packBoth y) = min x y+#-}++instance Ord a => Ord (AffinelyExtendBoundedBoth a) where+  compare = compareBounded+  (<) = ltBounded+  (>) = gtBounded+  (<=) = lteBounded+  (>=) = gteBounded+  min = minBounded+  max = maxBounded++instance Ord a => Ord (AffinelyExtendBoundedPos a) where+  compare = compareBounded+  (<) = ltBounded+  (>) = gtBounded+  (<=) = lteBounded+  (>=) = gteBounded+  min = minBounded+  max = maxBounded++-- Show+++showsPosInf :: ShowS+showsPosInf = shows (posInf :: Double)++showsNegInf :: ShowS+showsNegInf = shows (negInf :: Double)++strPosInf = showsPosInf ""+strNegInf = showsNegInf ""++instance Show a => Show (AffinelyExtendBoth a) where+  showsPrec _ = \case+    (Finite x) -> shows x+    PositiveInfinity -> showsPosInf+    NegativeInfinity -> showsNegInf++instance Show a => Show (AffinelyExtendPos a) where+  showsPrec _ = \case+    (Finite x) -> shows x+    PositiveInfinity -> showsPosInf++instance (Ord a, Bounded a, Num a, Show a) => Show (AffinelyExtendBoundedBoth a) where+  showsPrec _ x = if+    | isPos x -> showsPosInf+    | isNegInf x -> showsNegInf+    | otherwise -> shows x++instance (Eq a, Bounded a, Show a) => Show (AffinelyExtendBoundedPos a) where+  showsPrec _ x = if+    | isFinite x -> shows x+    | otherwise -> showsPosInf++-- Read++readsPrecInfGeneric :: forall a. (CanAffinelyExtend a, Read (BaseType a)) => (ReadS a) -> Int -> ReadS a+readsPrecInfGeneric infParse n s =+  let+    ordinaryParse :: [(BaseType a, String)]+    ordinaryParse = readsPrec n s+  in+    case ordinaryParse of+      (_:_) -> map (\(x,y) -> (affinelyExtend x, y)) ordinaryParse+      _ -> infParse s++maybeTake :: Eq a => [a] -> [a] -> Maybe [a]+maybeTake findStr str =+  let+    (toCheck, rest) = splitAt (length findStr) str+  in+    if (toCheck == findStr) then Just rest else Nothing++maybeTakeVal :: Eq a => b -> [a] -> [a] -> Maybe (b, [a])+maybeTakeVal v findStr str = do+  r <- maybeTake findStr str+  return (v, r)++maybeParseShow :: Show a => a -> String -> Maybe (a, String)+maybeParseShow v str = maybeTakeVal v (show v) str++maybeParsePosInf :: (HasPositiveInfinity a, Show a) => String -> Maybe (a, String)+maybeParsePosInf = maybeParseShow posInf++maybeParseNegInf :: (HasBothInfinities a, Show a) => String -> Maybe (a, String)+maybeParseNegInf = maybeParseShow negInf++parseBothInf :: (CanAffinelyExtend a, HasBothInfinities a, Show a) => ReadS a+parseBothInf s = maybeToList (maybeParsePosInf s <|> maybeParseNegInf s)++parsePosInf :: (CanAffinelyExtend a, HasPositiveInfinity a, Show a) => ReadS a+parsePosInf = maybeToList . maybeParsePosInf++readBothInf :: (Read (BaseType a), CanAffinelyExtend a, HasBothInfinities a, Show a) => Int -> ReadS a+readBothInf = readsPrecInfGeneric parseBothInf++readPosInf :: (Read (BaseType a), CanAffinelyExtend a, HasPositiveInfinity a, Show a) => Int -> ReadS a+readPosInf = readsPrecInfGeneric parsePosInf++instance (Show a, Read a) => Read (AffinelyExtendBoth a) where+  readsPrec = readBothInf++instance (Show a, Read a) => Read (AffinelyExtendPos a) where+  readsPrec = readPosInf++instance (Bounded a, Ord a, Num a, Read a, Show a) => Read (AffinelyExtendBoundedBoth a) where+  readsPrec = readBothInf++instance (Bounded a, Eq a, Read a, Show a) => Read (AffinelyExtendBoundedPos a) where+  readsPrec = readPosInf++-- Enum++toEnum' :: (CanAffinelyExtend a, Enum (BaseType a)) => Int -> a+toEnum' x = affinelyExtend (toEnum x)++fromEnum' :: (CanAffinelyExtend a, Enum (BaseType a)) => a -> Int+fromEnum' x = case (unpackBoth x) of+  Finite x -> fromEnum x+  _ -> error "Can't 'fromEnum' an infinity"++succ' :: (CanAffinelyExtend a, Enum (BaseType a)) => a -> a+succ' x = case unpackBoth x of+  Finite x -> affinelyExtend (succ x)+  _ -> x++pred' :: (CanAffinelyExtend a, Enum (BaseType a)) => a -> a+pred' x = case unpackBoth x of+  Finite x -> affinelyExtend (pred x)+  _ -> x++enumFrom' :: (CanAffinelyExtend a, Enum (BaseType a)) => a -> [a]+enumFrom' x = case unpackBoth x of+  Finite x -> map affinelyExtend (enumFrom x)+  _ -> repeat x++enumFromThen' :: (CanAffinelyExtend a, Enum (BaseType a)) => a -> a -> [a]+enumFromThen' x y = case (unpackBoth x, unpackBoth y) of+  (Finite x, Finite y) -> map affinelyExtend (enumFromThen x y)+  _ -> error "Can't enumFromThen an infinity."++enumFromTo' :: (CanAffinelyExtend a, Enum (BaseType a)) => a -> a -> [a]+enumFromTo' x y = case (unpackBoth x, unpackBoth y) of+  (Finite x, Finite y) -> map affinelyExtend (enumFromTo x y)+  (Finite x, PositiveInfinity) -> map affinelyExtend (enumFrom x)+  (Finite _, NegativeInfinity) -> []+  (NegativeInfinity, Finite _) -> repeat x+  (NegativeInfinity, PositiveInfinity) -> repeat x+  (PositiveInfinity, NegativeInfinity) -> []+  (PositiveInfinity, Finite _) -> []+  _ -> error "Can't enumFromTo identical infinities."++enumFromThenTo' :: (CanAffinelyExtend a, Enum (BaseType a), Ord (BaseType a)) => a -> a -> a -> [a]+enumFromThenTo' x y z = case (unpackBoth x, unpackBoth y, unpackBoth z) of+  (Finite x, Finite y, Finite z) -> map affinelyExtend (enumFromThenTo x y z)+  (Finite x, Finite y, PositiveInfinity) -> if (x <= y) then map affinelyExtend (enumFromThen x y) else []+  (Finite x, Finite y, NegativeInfinity) -> if (x >= y) then map affinelyExtend (enumFromThen x y) else []+  _ -> error "Can't enumFromThen infinity."++instance (Ord a, Enum a) => Enum (AffinelyExtendBoth a) where+  toEnum = toEnum'+  fromEnum = fromEnum'+  succ = succ'+  pred = pred'+  enumFrom = enumFrom'+  enumFromThen = enumFromThen'+  enumFromThenTo = enumFromThenTo'++instance (Ord a, Enum a) => Enum (AffinelyExtendPos a) where+  toEnum = toEnum'+  fromEnum = fromEnum'+  succ = succ'+  pred = pred'+  enumFrom = enumFrom'+  enumFromThen = enumFromThen'+  enumFromThenTo = enumFromThenTo'++instance (Bounded a, Ord a, Enum a, Num a) => Enum (AffinelyExtendBoundedBoth a) where+  toEnum = toEnum'+  fromEnum = fromEnum'+  succ = succ'+  pred = pred'+  enumFrom = enumFrom'+  enumFromThen = enumFromThen'+  enumFromThenTo = enumFromThenTo'++instance (Bounded a, Ord a, Enum a, Num a) => Enum (AffinelyExtendBoundedPos a) where+  toEnum = toEnum'+  fromEnum = fromEnum'+  succ = succ'+  pred = pred'+  enumFrom = enumFrom'+  enumFromThen = enumFromThen'+  enumFromThenTo = enumFromThenTo'+-- Num+++signToInf :: (Ord a, Num a, Num b, HasBothInfinities b) => a -> b+signToInf x = case (x `compare` 0) of+  GT -> posInf+  LT -> negInf+  EQ -> 0++signToNegInf :: (Ord a, Num a, Num b, HasBothInfinities b) => a -> b+signToNegInf x = case (x `compare` 0) of+  GT -> negInf+  LT -> posInf+  EQ -> 0++signToInfPos :: (Ord a, Num a, Num b, HasPositiveInfinity b) => a -> b+signToInfPos x = case (x `compare` 0) of+  GT -> posInf+  EQ -> 0+  LT -> error "Operation produced negative infinity for type with only positive infinity."++signToInfDivide :: (Ord a, Num a, Num b, HasBothInfinities b) => a -> b+signToInfDivide x = case (x `compare` 0) of+  GT -> posInf+  LT -> negInf+  EQ -> error "Can't divide by 0"++signToNegInfDivide :: (Ord a, Num a, Num b, HasBothInfinities b) => a -> b+signToNegInfDivide x = case (x `compare` 0) of+  GT -> negInf+  LT -> posInf+  EQ -> error "Can't divide by 0"++signToInfDividePos :: (Ord a, Num a, Num b, HasPositiveInfinity b) => a -> b+signToInfDividePos x =  case (x `compare` 0) of+  GT -> posInf+  LT -> error "Operation produced negative infinity for type with only positive infinity."+  EQ -> error "Can't divide by 0"+++instance (Ord a, Num a) => Num (AffinelyExtendBoth a) where+  x + y = case (x,y) of+    (Finite x, Finite y) -> Finite (x + y)+    (_, Finite _) -> x+    (Finite _, _) -> y+    (PositiveInfinity, PositiveInfinity) -> PositiveInfinity+    (NegativeInfinity, NegativeInfinity) -> NegativeInfinity+    _ -> error "Can't add positive and negative infinity"++  x - y = case (x,y) of+    (Finite x, Finite y) -> Finite (x - y)+    (_, Finite _) -> x+    (Finite _, _) -> negate y+    (PositiveInfinity, NegativeInfinity) -> PositiveInfinity+    (NegativeInfinity, PositiveInfinity) -> NegativeInfinity+    _ -> error "Can't subtract identical infinities"++  x * y = case (x,y) of+    (Finite x, Finite y) -> Finite (x * y)+    (Finite x, PositiveInfinity) -> signToInf x+    (PositiveInfinity, Finite y) -> signToInf y+    (Finite x, NegativeInfinity) -> signToNegInf x+    (NegativeInfinity, Finite y) -> signToNegInf y+    (PositiveInfinity, PositiveInfinity) -> PositiveInfinity+    (PositiveInfinity, NegativeInfinity) -> NegativeInfinity+    (NegativeInfinity, PositiveInfinity) -> NegativeInfinity+    (NegativeInfinity, NegativeInfinity) -> PositiveInfinity++  signum = \case+    Finite x -> Finite (signum x)+    PositiveInfinity -> 1+    NegativeInfinity -> -1++  fromInteger = Finite . fromInteger++  negate = \case+    Finite x -> Finite (negate x)+    PositiveInfinity -> NegativeInfinity+    NegativeInfinity -> PositiveInfinity++  abs = \case+    Finite x -> Finite (abs x)+    _ -> PositiveInfinity++instance (Ord a, Num a) => Num (AffinelyExtendPos a) where+  x + y = case (x,y) of+    (Finite x, Finite y) -> Finite (x + y)+    _ -> PositiveInfinity++  x - y = case (x,y) of+    (Finite x, Finite y) -> Finite (x - y)+    (_, Finite _) -> PositiveInfinity+    (_, PositiveInfinity) -> error "Can't subtract positive infinity from type with no negative infinity"++  x * y = case (x,y) of+    (Finite x, Finite y) -> Finite (x * y)+    (Finite x, PositiveInfinity) -> signToInfPos x+    (PositiveInfinity, Finite y) -> signToInfPos y+    (PositiveInfinity, PositiveInfinity) -> PositiveInfinity++  signum = \case+    Finite x -> Finite (signum x)+    PositiveInfinity -> 1++  fromInteger = Finite . fromInteger++  negate x = case x of+    Finite x -> Finite (negate x)+    PositiveInfinity -> error "Can't negate positive infinity with type with no negative infinity"++  abs = \case+    Finite x -> Finite (abs x)+    PositiveInfinity -> PositiveInfinity++{-# INLINE [1] fromIntegerGeneric #-}+fromIntegerGeneric :: (Ord (BaseType a), Num (BaseType a), CanAffinelyExtend a) => Integer -> a+fromIntegerGeneric = affinelyExtend . fromInteger++{-# INLINE [1] negateBounded #-}+negateBounded :: (Ord (BaseType a), Num (BaseType a), CanAffinelyExtend a, GetRawVal a) => a -> a+negateBounded = applyThroughBounded negate++{-# INLINE [1] signumBounded #-}+signumBounded :: (Ord (BaseType a), Num (BaseType a), CanAffinelyExtend a, GetRawVal a) => a -> a+signumBounded = applyThroughBounded signum++{-# INLINE [1] absBounded #-}+absBounded :: (Ord (BaseType a), Num (BaseType a), CanAffinelyExtend a, GetRawVal a) => a -> a+absBounded = applyThroughBounded abs++instance (Ord a, Num a, Bounded a) => Num (AffinelyExtendBoundedBoth a) where+  (+) = applyAffine2 (+)+  (*) = applyAffine2 (*)+  (-) = applyAffine2 (-)++  negate = negateBounded+  signum = signumBounded++  fromInteger = fromIntegerGeneric++  abs = absBounded++instance (Ord a, Num a, Bounded a) => Num (AffinelyExtendBoundedPos a) where+  (+) = applyAffine2 (+)+  (*) = applyAffine2 (*)+  (-) = applyAffine2 (-)++  negate = negateBounded+  signum = signumBounded++  fromInteger = fromIntegerGeneric++  abs = absBounded++{-# RULES+"negate/packBoth" forall x. negateBounded (packBoth x) = packBoth (negate x)+"negate/packBoth" forall x. negateBounded (packPos x) = packPos (negate x)+"signum/packBoth" forall x. signumBounded (packBoth x) = packBoth (signum x)+"signum/packBoth" forall x. signumBounded (packPos x) = packPos (signum x)+"abs/packBoth" forall x. absBounded (packBoth x) = packBoth (abs x)+"abs/packBoth" forall x. absBounded (packPos x) = packPos (abs x)+"unpackBoth/fromInteger" forall x. unpackBoth (fromIntegerGeneric x) = fromInteger x+"unpackBoth/fromInteger" forall x. unpackPos (fromIntegerGeneric x) = fromInteger x+#-}++-- Real++instance (Real a) => Real (AffinelyExtendBoth a) where+  toRational x = case x of+    Finite x -> toRational x+    _ -> error "Can't toRational an infinite number"++instance (Real a) => Real (AffinelyExtendPos a) where+  toRational x = case x of+    Finite x -> toRational x+    _ -> error "Can't toRational an infinite number"++instance (Real a, Bounded a) => Real (AffinelyExtendBoundedBoth a) where+  toRational = applyAffineNoPack toRational++instance (Real a, Bounded a) => Real (AffinelyExtendBoundedPos a) where+  toRational = applyAffineNoPack toRational++-- Fractional++instance (Ord a, Fractional a) => Fractional (AffinelyExtendBoth a) where+  x / y = case (x,y) of+    (Finite x, Finite y) -> Finite (x / y)+    (Finite _, _) -> 0+    (PositiveInfinity, Finite y) -> signToInfDivide y+    (NegativeInfinity, Finite y) -> signToNegInfDivide y+    _ -> error "Can't divide infinities"++  recip = \case+    (Finite x) -> (Finite (recip x))+    _ -> 0++  fromRational = affinelyExtend . fromRational++instance (Ord a, Fractional a) => Fractional (AffinelyExtendPos a) where+  x / y = case (x,y) of+    (Finite x, Finite y) -> Finite (x / y)+    (Finite _, PositiveInfinity) -> 0+    (PositiveInfinity, Finite y) -> signToInfDividePos y+    (PositiveInfinity, PositiveInfinity) -> error "Can't divide infinities"++  recip = \case+    (Finite x) -> (Finite (recip x))+    _ -> 0++  fromRational = affinelyExtend . fromRational++instance (Ord a, Bounded a, Fractional a) => Fractional (AffinelyExtendBoundedBoth a) where+  (/) = applyAffine2 (/)+  recip = applyAffine recip+  fromRational = fromRationalGeneric++instance (Ord a, Bounded a, Fractional a) => Fractional (AffinelyExtendBoundedPos a) where+  (/) = applyAffine2 (/)+  recip = applyAffine recip+  fromRational = fromRationalGeneric++{-# INLINE [1] fromRationalGeneric #-}+fromRationalGeneric :: (Ord (BaseType a), Num (BaseType a), Fractional (BaseType a), CanAffinelyExtend a) => Rational -> a+fromRationalGeneric = affinelyExtend . fromRational++{-# RULES+"unpackBoth/fromRational" forall x. unpackBoth (fromRationalGeneric x) = fromRational x+#-}+++instance Integral a => Integral (AffinelyExtendBoth a) where+  quot x y = case (x,y) of+    (Finite x, Finite y) -> Finite (x `quot` y)+    (Finite _, _) -> 0+    (PositiveInfinity, Finite y) -> signToInfDivide y+    (NegativeInfinity, Finite y) -> signToNegInfDivide y+    _ -> error "Can't 'quot' two infinities"++  rem x y = case (x,y) of+    (Finite x, Finite y) -> Finite (x `rem` y)+    (Finite _, _) -> x+    _ -> error "Can't have infinity as first argument of 'rem'"++  div x y = case (x,y) of+    (Finite x, Finite y) -> Finite (x `div` y)+    (Finite _, _) -> 0+    (PositiveInfinity, Finite y) -> signToInfDivide y+    (NegativeInfinity, Finite y) -> signToNegInfDivide y+    _ -> error "Can't 'div' two infinities"++  mod x y = case (x,y) of+    (Finite x, Finite y) -> Finite (x `mod` y)+    (Finite x', PositiveInfinity) -> if (x' >= 0) then x else error "Can't 'mod' with mixed signs and one infinity."+    (Finite x', NegativeInfinity) -> if (x' <= 0) then x else error "Can't 'mod' with mixed signs and one infinity."+    _ -> error "Can't have infinity as first argument of 'mod'"++  quotRem x y = case (x,y) of+    (Finite x, Finite y) -> let (x', y') = (x `quotRem` y) in (Finite x', Finite y')+    (Finite _, _) -> (0, x)+    (PositiveInfinity, Finite y) -> (signToInfDivide y, error "Can't have infinity as first argument of 'rem'")+    (NegativeInfinity, Finite y) -> (signToNegInfDivide y, error "Can't have infinity as first argument of 'rem'")+    _ -> error "Can't 'quotRem' two infinities"++  divMod x y = case (x,y) of+    (Finite x, Finite y) -> let (x', y') = (x `divMod` y) in (Finite x', Finite y')+    (Finite x', PositiveInfinity) -> (0, if (x' >= 0) then x else error "Can't 'mod' with mixed signs and one infinity.")+    (Finite x', NegativeInfinity) -> (0, if (x' <= 0) then x else error "Can't 'mod' with mixed signs and one infinity.")+    (PositiveInfinity, Finite y) -> (signToInfDivide y, error "Can't have infinity as first argument of 'mod'")+    (NegativeInfinity, Finite y) -> (signToNegInfDivide y, error "Can't have infinity as first argument of 'mod'")+    _ -> error "Can't 'divMod' two infinities"++  toInteger = \case+    (Finite x) -> toInteger x+    _ -> error "Can't 'toInteger' infinity"++instance Integral a => Integral (AffinelyExtendPos a) where+  quot x y = case (x,y) of+    (Finite x, Finite y) -> Finite (x `quot` y)+    (Finite _, PositiveInfinity) -> 0+    (PositiveInfinity, Finite y) -> signToInfDividePos y+    (PositiveInfinity, PositiveInfinity) -> error "Can't 'quot' two infinities"++  rem x y = case (x,y) of+    (Finite x, Finite y) -> Finite (x `rem` y)+    (Finite _, PositiveInfinity) -> x+    (PositiveInfinity, _) -> error "Can't have infinity as first argument of 'rem'"++  div x y = case (x,y) of+    (Finite x, Finite y) -> Finite (x `div` y)+    (Finite _, PositiveInfinity) -> 0+    (PositiveInfinity, Finite y) -> signToInfDividePos y+    (PositiveInfinity, PositiveInfinity) -> error "Can't 'div' two infinities"++  mod x y = case (x,y) of+    (Finite x, Finite y) -> Finite (x `mod` y)+    (Finite _, PositiveInfinity) -> x+    (PositiveInfinity, _) -> error "Can't have infinity as first argument of 'mod'"++  quotRem x y = case (x,y) of+    (Finite x, Finite y) -> let (x', y') = (x `quotRem` y) in (Finite x', Finite y')+    (Finite _, PositiveInfinity) -> (0, x)+    (PositiveInfinity, Finite y) -> (signToInfDividePos y, error "Can't have infinity as first argument of 'rem'")+    (PositiveInfinity, PositiveInfinity) -> error "Can't 'quotRem' two infinities"++  divMod x y = case (x,y) of+    (Finite x, Finite y) -> let (x', y') = (x `divMod` y) in (Finite x', Finite y')+    (Finite x', PositiveInfinity) -> (0, if (x' >= 0) then x else error "Can't 'mod' with mixed signs and one infinity.")+    (PositiveInfinity, Finite y) -> (signToInfDividePos y, error "Can't have infinity as first argument of 'mod'")+    (PositiveInfinity, PositiveInfinity) -> error "Can't 'divMod' two infinities"++  toInteger = \case+    (Finite x) -> toInteger x+    PositiveInfinity -> error "Can't 'toInteger' infinity"++{-# INLINE [1] remBounded #-}+remBounded :: (GetRawVal a, CanAffinelyExtend a, Integral (BaseType a)) => a -> a -> a+remBounded x y = assert (isFinite x) (apply2ThroughBounded rem x y)++{-# INLINE [1] modBounded #-}+modBounded :: (GetRawVal a, CanAffinelyExtend a, Integral (BaseType a)) => a -> a -> a+modBounded x y = assert (isFinite x) (apply2ThroughBounded mod x y)++{-# INLINE [1] toIntegerBounded #-}+toIntegerBounded :: (GetRawVal a, CanAffinelyExtend a, Integral (BaseType a)) => a -> Integer+toIntegerBounded x = assert (isFinite x) (toInteger (getRawVal x))++instance (Bounded a, Integral a) => Integral (AffinelyExtendBoundedBoth a) where+  quot = applyAffine2 quot++  rem = remBounded++  div = applyAffine2 div++  mod = modBounded++  quotRem = applyAffineOutPair2 quotRem+  divMod = applyAffineOutPair2 divMod++  toInteger = toIntegerBounded++instance (Bounded a, Integral a) => Integral (AffinelyExtendBoundedPos a) where+  quot = applyAffine2 quot++  rem = remBounded++  div = applyAffine2 div++  mod = modBounded++  quotRem = applyAffineOutPair2 quotRem+  divMod = applyAffineOutPair2 divMod++  toInteger = toIntegerBounded++{-# RULES+"rem/packBoth" forall x y. remBounded (packBoth x) (packBoth y) = packBoth (rem x y)+"rem/packPos" forall x y. remBounded (packPos x) (packPos y) = packPos (rem x y)+"mod/packBoth" forall x y. modBounded (packBoth x) (packBoth y) = packBoth (mod x y)+"mod/packPos" forall x y. modBounded (packPos x) (packPos y) = packPos (mod x y)+"toInteger/packBoth" forall x. toIntegerBounded (packBoth x) = toInteger x+"toInteger/packPos" forall x. toIntegerBounded (packPos x) = toInteger x+#-}