Skip to content

Instantly share code, notes, and snippets.

@formalism
Created March 22, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save formalism/f6efc93df8e90cfd39b0 to your computer and use it in GitHub Desktop.
Save formalism/f6efc93df8e90cfd39b0 to your computer and use it in GitHub Desktop.
Forward DCT implemented in Haskell. Familiarize myself how to use mutable vector in ST monad. DCT algorithm might contain bugs :). Modified from ijgjpeg fdctflt.
module DctQuant where
import Prelude hiding (mapM_, read)
import Data.Vector.Mutable
import Data.Vector
import Control.Monad.ST
import Control.Monad.Primitive (PrimMonad, PrimState)
fdct :: PrimMonad m => Vector Float -> m (MVector (PrimState m) Float)
fdct vi = do
v <- new 64
flip mapM_ (fromList [0..7])
(\i ->
let elemptr = Data.Vector.slice i 8 vi
tmp0 = elemptr ! 0 + elemptr ! 7
tmp7 = elemptr ! 0 - elemptr ! 7
tmp1 = elemptr ! 1 + elemptr ! 6
tmp6 = elemptr ! 1 - elemptr ! 6
tmp2 = elemptr ! 2 + elemptr ! 5
tmp5 = elemptr ! 2 - elemptr ! 5
tmp3 = elemptr ! 3 + elemptr ! 4
tmp4 = elemptr ! 3 - elemptr ! 4
-- even part
tmp10 = tmp0 + tmp3
tmp13 = tmp0 - tmp3
tmp11 = tmp1 + tmp2
tmp12 = tmp1 - tmp2
z1 = (tmp12 + tmp13) * 0.707106781
-- odd part
tmp10' = tmp4 + tmp5
tmp11' = tmp5 + tmp6
tmp12' = tmp6 + tmp7
z5 = (tmp10'-tmp12') * 0.382683433
z2 = 0.541196100 * tmp10'+z5
z4 = 1.306562965 * tmp12'+z5
z3 = tmp11' * 0.707106781 :: Float
z11 = tmp7 + z3
z13 = tmp7 - z3 in
do
write v (i*8+0) (tmp10+tmp11-8.0*128) -- phase 3
write v (i*8+4) (tmp10-tmp11)
write v (i*8+2) (tmp13+z1)
write v (i*8+6) (tmp13-z1)
write v (i*8+5) (z13+z2)
write v (i*8+3) (z13-z2)
write v (i*8+1) (z11+z4)
write v (i*8+7) (z11-z4))
-- phase 2: process columns
flip mapM_ (fromList [0..7])
(\i ->
do
t0 <- read v (8*0+i)
t1 <- read v (8*1+i)
t2 <- read v (8*2+i)
t3 <- read v (8*3+i)
t4 <- read v (8*4+i)
t5 <- read v (8*5+i)
t6 <- read v (8*6+i)
t7 <- read v (8*7+i)
let tmp0 = t0+t7
tmp7 = t0-t7
tmp1 = t1+t6
tmp6 = t1-t6
tmp2 = t2+t5
tmp5 = t2-t5
tmp3 = t3+t4
tmp4 = t3-t4
-- even part
tmp10 = tmp0+tmp3
tmp13 = tmp0-tmp3
tmp11 = tmp1+tmp2
tmp12 = tmp1-tmp2
z1 = (tmp12+tmp13)*0.707106781 -- c4
tmp10' = tmp4+tmp5
tmp11' = tmp5+tmp6
tmp12' = tmp6+tmp7
z5 = (tmp10'-tmp12')*0.382683433
z2 = 0.541196100*tmp10'+z5
z4 = 1.306562965*tmp12'+z5
z3 = tmp11'*0.707106781
z11 = tmp7+z3
z13 = tmp7-z3
write v (8*0+i) (tmp10+tmp11)
write v (8*4+i) (tmp10-tmp11)
write v (8*2+i) (tmp13+z1)
write v (8*6+i) (tmp13-z1)
write v (8*5+i) (z13+z2)
write v (8*3+i) (z13-z2)
write v (8*1+i) (z11+z4)
write v (8*7+i) (z11-z4))
return v
-- How to use:
-- let mat = Prelude.map (fromIntegral::Int->Float) [1,2,3,4,5,6,7,8,
-- 9,10,11,12,13,14,15,16,
-- 9,10,11,12,13,14,15,16,
-- 9,10,11,12,13,14,15,16,
-- 9,10,11,12,13,14,15,16,
-- 9,10,11,12,13,14,15,16,
-- 9,10,11,12,13,14,15,16,
-- 9,10,11,12,13,14,15,16]
-- main = runST $ ((fdct $ fromList mat) >>= freeze)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment