diff --git a/Data/ByteString/Base16.hs b/Data/ByteString/Base16.hs
--- a/Data/ByteString/Base16.hs
+++ b/Data/ByteString/Base16.hs
@@ -1,11 +1,11 @@
-{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE BangPatterns, MagicHash #-}
 
 -- |
 -- Module      : Data.ByteString.Base16
 -- Copyright   : (c) 2011 MailRank, Inc.
 --
 -- License     : BSD
--- Maintainer  : bos@mailrank.com
+-- Maintainer  : bos@serpentine.com
 -- Stability   : experimental
 -- Portability : GHC
 --
@@ -17,16 +17,16 @@
     , decode
     ) where
 
-import Control.Monad (forM_)
-import Data.Bits ((.&.), shiftL, shiftR)
 import Data.ByteString.Char8 (empty)
 import Data.ByteString.Internal (ByteString(..), createAndTrim', unsafeCreate)
-import Data.Word (Word8)
+import Data.Bits (shiftL)
 import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)
-import Foreign.Marshal.Alloc (mallocBytes)
 import Foreign.Ptr (Ptr, minusPtr, plusPtr)
 import Foreign.Storable (peek, poke)
 import System.IO.Unsafe (unsafePerformIO)
+import GHC.Prim
+import GHC.Types
+import GHC.Word
 
 -- | Encode a string into base16 form.  The result will always be a
 -- multiple of 2 bytes in length.
@@ -47,16 +47,45 @@
     go s d | s == e = return ()
            | otherwise = do
       x <- peek8 s
-      poke d =<< (peek (digits `plusPtr` (x `shiftR` 4)) :: IO Word8)
-      poke (d `plusPtr` 1) =<< (peek (digits `plusPtr` (x .&. 0xf)) :: IO Word8)
+      poke d (tlookup tableHi x)
+      poke (d `plusPtr` 1) (tlookup tableLo x)
       go (s `plusPtr` 1) (d `plusPtr` 2)
-  digits :: Ptr Word8
-  !digits = unsafePerformIO $ do
-             ptr <- mallocBytes 16
-             forM_ (zip [0..] "0123456789abcdef") $ \(i,c) ->
-               poke (ptr `plusPtr` i) ((fromIntegral (fromEnum c)) :: Word8)
-             return ptr
-  {-# NOINLINE digits #-}
+    tlookup :: Addr# -> Int -> Word8
+    tlookup table (I# index) = W8# (indexWord8OffAddr# table index)
+    !tableLo =
+      "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66\
+      \\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x61\x62\x63\x64\x65\x66"#
+    !tableHi =
+      "\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\
+      \\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\x31\
+      \\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\x32\
+      \\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\
+      \\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34\
+      \\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\x35\
+      \\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36\
+      \\x37\x37\x37\x37\x37\x37\x37\x37\x37\x37\x37\x37\x37\x37\x37\x37\
+      \\x38\x38\x38\x38\x38\x38\x38\x38\x38\x38\x38\x38\x38\x38\x38\x38\
+      \\x39\x39\x39\x39\x39\x39\x39\x39\x39\x39\x39\x39\x39\x39\x39\x39\
+      \\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\
+      \\x62\x62\x62\x62\x62\x62\x62\x62\x62\x62\x62\x62\x62\x62\x62\x62\
+      \\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\
+      \\x64\x64\x64\x64\x64\x64\x64\x64\x64\x64\x64\x64\x64\x64\x64\x64\
+      \\x65\x65\x65\x65\x65\x65\x65\x65\x65\x65\x65\x65\x65\x65\x65\x65\
+      \\x66\x66\x66\x66\x66\x66\x66\x66\x66\x66\x66\x66\x66\x66\x66\x66"#
 
 -- | Decode a string from base16 form. The first element of the
 -- returned tuple contains the decoded data. The second element starts
@@ -78,11 +107,6 @@
     go s d | s == e = let len = e `minusPtr` sptr
                       in return (0, len `div` 2, ps sfp (soff+len) (slen-len))
            | otherwise = do
-      let hex w
-              | w >= 48 && w <= 57  = w - 48
-              | w >= 97 && w <= 102 = w - 97 + 10
-              | w >= 65 && w <= 70  = w - 65 + 10
-              | otherwise           = 0xff
       hi <- hex `fmap` peek8 s
       lo <- hex `fmap` peek8 (s `plusPtr` 1)
       if lo == 0xff || hi == 0xff
@@ -91,6 +115,25 @@
         else do
           poke d . fromIntegral $ lo + (hi `shiftL` 4)
           go (s `plusPtr` 2) (d `plusPtr` 1)
+
+    hex (I# index) = W8# $ indexWord8OffAddr# table index
+    !table =
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xff\xff\xff\xff\xff\xff\
+        \\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
+        \\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"#
 
 peek8 :: Ptr Word8 -> IO Int
 peek8 p = fromIntegral `fmap` peek p
diff --git a/Data/ByteString/Base16/Lazy.hs b/Data/ByteString/Base16/Lazy.hs
--- a/Data/ByteString/Base16/Lazy.hs
+++ b/Data/ByteString/Base16/Lazy.hs
@@ -5,7 +5,7 @@
 -- Copyright   : (c) 2011 MailRank, Inc.
 --
 -- License     : BSD
--- Maintainer  : bos@mailrank.com
+-- Maintainer  : bos@serpentine.com
 -- Stability   : experimental
 -- Portability : GHC
 --
diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -18,11 +18,11 @@
 # Get involved!
 
 Please report bugs via the
-[bitbucket issue tracker](http://github.com/mailrank/base16-bytestring).
+[github issue tracker](http://github.com/bos/base16-bytestring).
 
-Master [github repository](http://github.com/mailrank/base16-bytestring):
+Master [github repository](http://github.com/bos/base16-bytestring):
 
-* `git clone git://github.com/mailrank/base16-bytestring.git`
+* `git clone git://github.com/bos/base16-bytestring.git`
 
 There's also a [Mercurial mirror](http://bitbucket.org/bos/base16-bytestring):
 
@@ -34,4 +34,4 @@
 # Authors
 
 This library is written and maintained by Bryan O'Sullivan,
-<bos@mailrank.com>.
+<bos@serpentine.com>.
diff --git a/base16-bytestring.cabal b/base16-bytestring.cabal
--- a/base16-bytestring.cabal
+++ b/base16-bytestring.cabal
@@ -1,9 +1,9 @@
 name:                base16-bytestring
-version:             0.1.1.2
-synopsis:            Fast base16 (hex) encoding and deconding for ByteStrings
-description:         Fast base16 (hex) encoding and deconding for ByteStrings
-homepage:            http://github.com/mailrank/base16-bytestring
-bug-reports:         http://github.com/mailrank/base16-bytestring/issues
+version:             0.1.1.3
+synopsis:            Fast base16 (hex) encoding and decoding for ByteStrings
+description:         Fast base16 (hex) encoding and decoding for ByteStrings
+homepage:            http://github.com/bos/base16-bytestring
+bug-reports:         http://github.com/bos/base16-bytestring/issues
 license:             BSD3
 license-file:        LICENSE
 copyright:           Copyright 2011 MailRank, Inc.
@@ -23,14 +23,15 @@
   
   build-depends:
     base == 4.*,
-    bytestring == 0.9.*
+    bytestring == 0.9.*,
+    ghc-prim
 
   ghc-options: -Wall -funbox-strict-fields
   ghc-prof-options: -auto-all
 
 source-repository head
   type:     git
-  location: http://github.com/mailrank/base16-bytestring
+  location: http://github.com/bos/base16-bytestring
 
 source-repository head
   type:     mercurial
