module Util where

import Data.Ord (clamp)
import Prelude

boundedSucc :: (Eq a, Bounded a, Enum a) => a -> a
boundedSucc :: forall a. (Eq a, Bounded a, Enum a) => a -> a
boundedSucc a
e
    | a
e a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. Bounded a => a
maxBound = a
e
    | Bool
otherwise = a -> a
forall a. Enum a => a -> a
succ a
e

boundedPred :: (Eq a, Bounded a, Enum a) => a -> a
boundedPred :: forall a. (Eq a, Bounded a, Enum a) => a -> a
boundedPred a
e
    | a
e a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. Bounded a => a
minBound = a
e
    | Bool
otherwise = a -> a
forall a. Enum a => a -> a
pred a
e

boundedAdd :: Int -> Word -> Word
boundedAdd :: Int -> Word -> Word
boundedAdd Int
delta = Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word) -> (Word -> Int) -> Word -> Word
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => (a, a) -> a -> a
clamp @Int (Int
0, Int
forall a. Bounded a => a
maxBound) (Int -> Int) -> (Word -> Int) -> Word -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
delta) (Int -> Int) -> (Word -> Int) -> Word -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral

absDelta :: (Num a, Ord a) => a -> a -> a
absDelta :: forall a. (Num a, Ord a) => a -> a -> a
absDelta a
a a
b
    | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
b = a
a a -> a -> a
forall a. Num a => a -> a -> a
- a
b
    | Bool
otherwise = a
b a -> a -> a
forall a. Num a => a -> a -> a
- a
a