{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE BlockArguments, LambdaCase #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE BangPatterns #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Data.Word.Adler32 (

	A, fromWord32, toWord32, step, initial

	) where

import Prelude hiding (uncurry)
import Data.Bits
import Data.Word

step :: (Int, A) -> Word8 -> (Int, A)
step :: (Int, A) -> Word8 -> (Int, A)
step (Int
n, A Word32
a Word32
b) Word8
w = case Int
n of
	Int
0 -> (Int
5551, Word32 -> Word32 -> A
A (( Word32
a Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w) Word32 -> Word32 -> Word32
forall a. Integral a => a -> a -> a
`mod` Word32
65521) ((Word32
b Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32
a Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w) Word32 -> Word32 -> Word32
forall a. Integral a => a -> a -> a
`mod` Word32
65521))
	Int
_ -> (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1, Word32 -> Word32 -> A
A (Word32
a Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w) (Word32
b Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32
a Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w))

data A = A !Word32 !Word32 deriving (Int -> A -> ShowS
[A] -> ShowS
A -> String
(Int -> A -> ShowS) -> (A -> String) -> ([A] -> ShowS) -> Show A
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> A -> ShowS
showsPrec :: Int -> A -> ShowS
$cshow :: A -> String
show :: A -> String
$cshowList :: [A] -> ShowS
showList :: [A] -> ShowS
Show, A -> A -> Bool
(A -> A -> Bool) -> (A -> A -> Bool) -> Eq A
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: A -> A -> Bool
== :: A -> A -> Bool
$c/= :: A -> A -> Bool
/= :: A -> A -> Bool
Eq)

initial :: (Int, A)
initial :: (Int, A)
initial = (Int
5551, Word32 -> Word32 -> A
A Word32
1 Word32
0)

fromWord32 :: Word32 -> A
fromWord32 :: Word32 -> A
fromWord32 Word32
w = Word32 -> Word32 -> A
A (Word32
w Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0xffff) (Word32
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
16)

toWord32 :: A -> Word32
toWord32 :: A -> Word32
toWord32 = (Word32 -> Word32 -> Word32) -> A -> Word32
forall a. (Word32 -> Word32 -> a) -> A -> a
uncurry Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
(.|.) (A -> Word32) -> (A -> A) -> A -> Word32
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word32 -> Word32) -> A -> A
first (Word32 -> Word32 -> Word32
forall a. Integral a => a -> a -> a
`mod` Word32
65521) (A -> A) -> (A -> A) -> A -> A
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word32 -> Word32) -> A -> A
second ((Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
16) (Word32 -> Word32) -> (Word32 -> Word32) -> Word32 -> Word32
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word32 -> Word32 -> Word32
forall a. Integral a => a -> a -> a
`mod` Word32
65521))

first :: (Word32 -> Word32) -> A -> A
first :: (Word32 -> Word32) -> A -> A
first Word32 -> Word32
f (A Word32
a Word32
b) = Word32 -> Word32 -> A
A (Word32 -> Word32
f Word32
a) Word32
b

second :: (Word32 -> Word32) -> A -> A
second :: (Word32 -> Word32) -> A -> A
second Word32 -> Word32
f (A Word32
a Word32
b) = Word32 -> Word32 -> A
A Word32
a (Word32 -> Word32
f Word32
b)

uncurry :: (Word32 -> Word32 -> a) -> A -> a
uncurry :: forall a. (Word32 -> Word32 -> a) -> A -> a
uncurry Word32 -> Word32 -> a
f (A Word32
a Word32
b) = Word32 -> Word32 -> a
f Word32
a Word32
b