mandelbrotImageGenerator :: IO MandelFun
mandelbrotImageGenerator = do
    state    <- newState (ix2 0 0)
    stateRef <- newIORef state
    return $ mandelbrotImage stateRef
  where
    mandelbrotImage :: IORef MandelState -> MandelFun
    mandelbrotImage stateRef lowx lowy highx highy viewx viewy depth = do
        let sh     =  ix2 viewy viewx
        state      <- updateState stateRef sh
        let mbmapH =  manMBmapH state
            mbmapD =  manMBmapD state
            mcs    =  manMCs state
            mzs    =  manMZs state
        mandelbrot lowx' lowy' highx' highy' viewx' viewy' depth' mcs mzs
        zs     <- unsafeFreezeMArray mzs
        prettyMandelbrot depth' zs mbmapD
        bmapD  <- unsafeFreezeMArray mbmapD
        loadHostP bmapD mbmapH
        bmapH  <- unsafeFreezeMVec sh mbmapH
        return (convertBitmap bmapH)
      where
        lowx', lowy', highx', highy' :: R
        lowx'  = realToFrac lowx
        lowy'  = realToFrac lowy
        highx' = realToFrac highx
        highy' = realToFrac highy
        viewx', viewy', depth' :: Int32
        viewx' = fromIntegral viewx
        viewy' = fromIntegral viewy
        depth' = fromIntegral depth

    convertBitmap :: Bitmap UF -> Bitmap F
    convertBitmap bmap =
        let VUF.V_Word32 v = UF.toUnboxedForeign bmap
            (fp, _)        = V.unsafeToForeignPtr0 v
        in
          F.fromForeignPtr (extent bmap) fp

    newState :: DIM2 -> IO MandelState
    newState sh = do
        mbmapH <- newMVec (size sh)
        mbmapD <- newMArray sh
        mcs    <- newMArray sh
        mzs    <- newMArray sh
        return $ MandelState sh mbmapH mbmapD mcs mzs

    updateState :: IORef MandelState -> DIM2 -> IO MandelState
    updateState stateRef sh = do
        state <- readIORef stateRef
        if manDim state == sh
          then return state
          else do state' <- newState sh
                  writeIORef stateRef state'
                  return state'
mandelbrotImageGenerator :: IO MandelFun
mandelbrotImageGenerator = do
    state    <- newState (ix2 0 0)
    stateRef <- newIORef state
    return $ mandelbrotImage stateRef
  where
    mandelbrotImage :: IORef MandelState -> MandelFun
    mandelbrotImage stateRef lowx lowy highx highy viewx viewy depth = do
        let sh     =  ix2 viewy viewx
        state      <- updateState stateRef sh
        let mbmapH =  manMBmapH state
            mbmapD =  manMBmapD state
            mcs    =  manMCs state
            mzs    =  manMZs state
        mandelbrot lowx' lowy' highx' highy' viewx' viewy' depth' mcs mzs
        zs     <- unsafeFreezeMArray mzs
        prettyMandelbrot depth' zs mbmapD
        bmapD  <- unsafeFreezeMArray mbmapD
        loadHostP bmapD mbmapH
        bmapH  <- unsafeFreezeMVec sh mbmapH
        return (convertBitmap bmapH)
      where
        lowx', lowy', highx', highy' :: R
        lowx'  = realToFrac lowx
        lowy'  = realToFrac lowy
        highx' = realToFrac highx
        highy' = realToFrac highy
        viewx', viewy', depth' :: Int32
        viewx' = fromIntegral viewx
        viewy' = fromIntegral viewy
        depth' = fromIntegral depth

    convertBitmap :: Bitmap UF -> Bitmap F
    convertBitmap bmap =
        let VUF.V_Word32 v = UF.toUnboxedForeign bmap
            (fp, _)        = V.unsafeToForeignPtr0 v
        in
          F.fromForeignPtr (extent bmap) fp

    newState :: DIM2 -> IO MandelState
    newState sh = do
        mbmapH <- newMVec (size sh)
        mbmapD <- newMArray sh
        mcs    <- newMArray sh
        mzs    <- newMArray sh
        return $ MandelState sh mbmapH mbmapD mcs mzs

    updateState :: IORef MandelState -> DIM2 -> IO MandelState
    updateState stateRef sh = do
        state <- readIORef stateRef
        if manDim state == sh
          then return state
          else do state' <- newState sh
                  writeIORef stateRef state'
                  return state'
mandelbrotImageGenerator = do
    state    <- newState (ix2 0 0)
    stateRef <- newIORef state
    return $ mandelbrotImage stateRef
  where
    mandelbrotImage :: IORef MandelState -> MandelFun
    mandelbrotImage stateRef lowx lowy highx highy viewx viewy depth = do
        let sh     =  ix2 viewy viewx
        state      <- updateState stateRef sh
        let mbmapH =  manMBmapH state
            mbmapD =  manMBmapD state
            mcs    =  manMCs state
            mzs    =  manMZs state
        mandelbrot lowx' lowy' highx' highy' viewx' viewy' depth' mcs mzs
        zs     <- unsafeFreezeMArray mzs
        prettyMandelbrot depth' zs mbmapD
        bmapD  <- unsafeFreezeMArray mbmapD
        loadHostP bmapD mbmapH
        bmapH  <- unsafeFreezeMVec sh mbmapH
        return (convertBitmap bmapH)
      where
        lowx', lowy', highx', highy' :: R
        lowx'  = realToFrac lowx
        lowy'  = realToFrac lowy
        highx' = realToFrac highx
        highy' = realToFrac highy
        viewx', viewy', depth' :: Int32
        viewx' = fromIntegral viewx
        viewy' = fromIntegral viewy
        depth' = fromIntegral depth

    convertBitmap :: Bitmap UF -> Bitmap F
    convertBitmap bmap =
        let VUF.V_Word32 v = UF.toUnboxedForeign bmap
            (fp, _)        = V.unsafeToForeignPtr0 v
        in
          F.fromForeignPtr (extent bmap) fp

    newState :: DIM2 -> IO MandelState
    newState sh = do
        mbmapH <- newMVec (size sh)
        mbmapD <- newMArray sh
        mcs    <- newMArray sh
        mzs    <- newMArray sh
        return $ MandelState sh mbmapH mbmapD mcs mzs

    updateState :: IORef MandelState -> DIM2 -> IO MandelState
    updateState stateRef sh = do
        state <- readIORef stateRef
        if manDim state == sh
          then return state
          else do state' <- newState sh
                  writeIORef stateRef state'
                  return state'