content: module Control.Exception.Common where
  
  -- import Control.Exception.Safe (Exception, MonadThrow, SomeException, throwM)
  import Control.Exception
  import Control.Monad.Catch (MonadThrow (..))
  import Data.Typeable -- (TypeRep, Typeable, typeRep)
  
  import Data.Sparse.Utils
  
  
  -- | Errors associated with partial functions
  data PartialFunctionError = EmptyList String deriving (Eq, Typeable)
  instance Show PartialFunctionError where
    show (EmptyList s) = unwords [s, ": empty list"]
  instance Exception PartialFunctionError
  
  
  -- | Input errors
  data InputError = NonNegError String Int deriving (Eq, Typeable)
  instance Show InputError where
    show (NonNegError s i) = unwords [s, ": parameter must be nonnegative, instead I got", show i]
  instance Exception InputError
  
  
  
  -- | Out of bounds index errors
  data OutOfBoundsIndexError i = OOBIxError String i
                               | OOBIxsError String [i]
                               | OOBNoCompatRows String (i,i) deriving (Eq, Typeable)
  instance Show i => Show (OutOfBoundsIndexError i) where
    show (OOBIxError e i) = unwords [e, ": index", show i,"out of bounds"]
    show (OOBIxsError e ixs) = unwords [e, ":, indices", show ixs, "out of bounds"]
    show (OOBNoCompatRows e ij) = unwords [e, ": no compatible rows for indices", show ij]
  instance (Show i, Typeable i) => Exception (OutOfBoundsIndexError i)
  
  checkIxBound :: MonadThrow m => String -> Int -> UB -> m a -> m a
  checkIxBound e i n ff
    | not (inBounds0 n i) = throwM (OOBIxError e i)
    | otherwise = ff
  
      
  
  -- | Operand size mismatch errors
  data OperandSizeMismatch = DotSizeMismatch Int Int
                           | NonTriangularException String
                           | MatVecSizeMismatchException String (Int, Int) Int deriving (Eq, Typeable)
  instance Show OperandSizeMismatch where
    show (DotSizeMismatch na nb) = unwords ["<.> : Incompatible dimensions : ", show na, show nb]
    show (NonTriangularException s )= unwords [s, ": Matrix must be triangular"]
    show (MatVecSizeMismatchException s dm o) = unwords [s, ": Matrix-vector dimensions are incompatible: Matrix is",show dm,", whereas vector is",show o]
  instance Exception OperandSizeMismatch
  
  
  
  
  -- | Matrix exceptions
  data MatrixException i = HugeConditionNumber String i
                         | NeedsPivoting String String deriving (Eq, Typeable)
  instance Show i => Show (MatrixException i) where
    show (HugeConditionNumber s x) = unwords [s, ": Rank-deficient system: condition number", show x]
    show (NeedsPivoting s1 s2) = unwords [s1, ":", s2, "is close to 0. Permute the rows to obtain a nonzero diagonal"]
  instance (Show i, Typeable i) => Exception (MatrixException i)
  
  
  
  -- | Numerical iteration errors
  data IterationException a = NotConvergedE String Int a 
                            | DivergingE String Int a a
                            | IterE String String
                            deriving (Eq, Typeable)
  instance Show a => Show (IterationException a) where
    show (NotConvergedE s niters x) = unwords [s, ": Could not converge within",show niters, "iterations; final state:", show x]
    show (DivergingE s niters x0 x1) = unwords [s, ": Diverging at iteration #", show niters, "; latest state:",show x0, "; previous state:",show x1]
    -- show (NotConvergedToExpectedE s niters x x0) = unwords [s, ": Could not converge within",show niters, "iterations; final state:", show x, "expected state:", show x0]
  instance (Show a, Typeable a) => Exception (IterationException a)
  