packages feed

stdio (empty) → 0.1.0.0

raw patch · 150 files changed

+71652/−0 lines, 150 filesdep +HUnitdep +QuickCheckdep +basesetup-changed

Dependencies added: HUnit, QuickCheck, base, case-insensitive, deepseq, exceptions, ghc-prim, hashable, hspec, integer-gmp, integer-simple, primitive, quickcheck-instances, scientific, stdio, stm, template-haskell, time, transformers, word8

Files

+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for stdio++## 0.1.0.0  -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2017, winter++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of winter nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,125 @@+Haskell stdio: haskell standard input and output+================================================++[![Linux Build Status](https://img.shields.io/travis/haskell-stdio/stdio/master.svg?label=Linux%20build)](https://travis-ci.org/haskell-stdio/stdio)+[![Windows Build Status](https://img.shields.io/appveyor/ci/winterland1989/stdio-7usux/master.svg?label=Windows%20build)](https://ci.appveyor.com/project/winterland1989/stdio-7usux/branch/master)++Welcome! Haskell stdio is a complete I/O toolkit powered by libuv, it features a multi-core io multiplexer and various improvements on packed data types. This project is still in infancy. Please join in!++```+    __  _____   _____ __ __ ________    __       _______________  ________ +   / / / /   | / ___// //_// ____/ /   / /      / ___/_  __/ __ \/  _/ __ \+  / /_/ / /| | \__ \/ ,<  / __/ / /   / /       \__ \ / / / / / // // / / /+ / __  / ___ |___/ / /| |/ /___/ /___/ /___    ___/ // / / /_/ // // /_/ / +/_/ /_/_/  |_/____/_/ |_/_____/_____/_____/   /____//_/ /_____/___/\____/+```++Install+-------++On windows we have bundled libuv source, so no extra steps to be taken.++On \*nix platforms, you should install libuv library first, you can use your distribution's package manager if available, for example:++```+# on debian/ubuntu, make sure to use 1.x+apt-get install libuv1-dev  libuv1++# on MacOS, we recommend brew+brew install libuv++...+```++Currently **the minimum version requirement for libuv is v1.14**. If your package manager's libuv doesn't meet this requirement, you can also build libuv from source following the guide [here](https://github.com/libuv/libuv#build-instructions), e.g.++```+git clone https://github.com/libuv/libuv.git +cd libuv +git checkout tags/v1.24.0   # depend on your own need, any version >= 1.14 will work.+sh autogen.sh +./configure +make +sudo make install +```++After manually building and installing, you may need to modify your `LIBRARY_PATH/CPATH` if necessary. Now installing stdio is as easy as any other haskell packages.  ++```+cabal install stdio+```++Now you can fire GHCi and play around, or read the [project overview](https://haskell-stdio.github.io/stdio), [haddock](https://haskell-stdio.github.io/stdio/haddock/).++Examples+--------+++ hello world++```+import Std.IO.StdStream+import qualified Std.Data.Text as T++main = do+    -- read stdin and write to stdout, but with our new IO manager!+    input <- readLineStd+    printStd (T.validate input)+```+++ tcp echo server++```+import Std.IO.TCP+import Std.IO.Buffered+import Control.Monad++main = do+    startServer defaultServerConfig+        { serverAddr = SockAddrInet 8888 inetAny+        , serverWorker = echo+        }+  where+    echo uvs = forever $ do+        i <- newBufferedInput uvs 4096+        o <- newBufferedOutput uvs 4096+        readBuffer i >>= writeBuffer o+        flushBuffer o+```++Now try `nc -v 127.0.0.1 8888`.+++ logging++```+import Std.IO.Logger+import qualified Std.Data.Builder as B+import Control.Concurrent++main = withStdLogger $ do+    debug $ "hello world! PI ~=" >> B.double pi     -- debug level won't be immediately flushed+    forkIO $ do+        fatal "fatal message will trigger a log flush"+```+++ file system operatations++```+import           Std.IO.FileSystem+import           Std.IO.Resource+import           Std.IO.StdStream++main = do+    -- create a temp directory+    tempdir <- mkdtemp "temp"   +    let filename = "temp" <> "/test"+        flags = O_RDWR .|. O_CREAT      -- create if not exist+        mode = DEFAULT_MODE++    -- file is a 'Resource', use 'withResource' to automatically manage it+    withResource (initUVFile filename flags mode) $ \ f -> do+        o <- newBufferedOutput file 4096+        writeBuffer o "hello world!"+        flushBuffer o++    stat filename >>= printStd+```
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMainWithHooks autoconfUserHooks
+ Std/Data/Array.hs view
@@ -0,0 +1,615 @@+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE CPP                    #-}+{-# LANGUAGE FlexibleContexts       #-}+{-# LANGUAGE FlexibleInstances      #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE KindSignatures         #-}+{-# LANGUAGE MagicHash              #-}+{-# LANGUAGE MultiParamTypeClasses  #-}+{-# LANGUAGE ScopedTypeVariables    #-}+{-# LANGUAGE TypeFamilies           #-}+{-# LANGUAGE UnboxedTuples          #-}+{-# LANGUAGE UnliftedFFITypes       #-}++{-|+Module      : Std.Data.Array+Description : Fast boxed and unboxed arrays+Copyright   : (c) Dong Han, 2017+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++Unified unboxed and boxed array operations using functional dependencies.++All operations are NOT bound checked, if you need checked operations please use "Std.Data.Array.Checked".+It exports exactly same APIs so that you can switch between without pain.++Some mnemonics:++  * 'newArr', 'newArrWith' return mutable array, 'readArr', 'writeArr' works on them, 'setArr' fill elements+     with offset and length.++  * 'indexArr' works on immutable one, use 'indexArr'' to avoid indexing thunk.++  * The order of arguements of 'copyArr', 'copyMutableArr' and 'moveArr' are always target and its offset+    come first, and source and source offset follow, copying length comes last.++-}++module Std.Data.Array (+  -- * Arr typeclass+    Arr(..)+  , RealWorld+  -- * Boxed array type+  , Array(..)+  , MutableArray(..)+  , SmallArray(..)+  , SmallMutableArray(..)+  , uninitialized+  -- * Primitive array type+  , PrimArray(..)+  , MutablePrimArray(..)+  , Prim(..)+  , newPinnedPrimArray, newAlignedPinnedPrimArray+  , copyPrimArrayToPtr, copyMutablePrimArrayToPtr, copyPtrToMutablePrimArray+  , primArrayContents, mutablePrimArrayContents, withPrimArrayContents, withMutablePrimArrayContents+  , isPrimArrayPinned, isMutablePrimArrayPinned+  -- * Unlifted array type+  , UnliftedArray(..)+  , MutableUnliftedArray(..)+  , PrimUnlifted(..)+  -- * The 'ArrayException' type+  , ArrayException(..)+  -- * Cast between primitive arrays+  , castArray+  , castMutableArray+  ) where++import           Control.Exception            (ArrayException (..), throw)+import           Control.Monad.Primitive+import           Data.Primitive.Array+import           Data.Primitive.ByteArray+import           Data.Primitive.PrimArray+import           Data.Primitive.Ptr           (copyPtrToMutablePrimArray)+import           Data.Primitive.SmallArray+import           Data.Primitive.Types+import           Data.Primitive.UnliftedArray+import           GHC.Prim+import           GHC.Ptr                      (Ptr (..))+import           GHC.ST+import           GHC.Types+import           Std.Data.PrimArray.Cast++-- | Bottom value (@throw ('UndefinedElement' "Data.Array.uninitialized")@)+-- for initialize new boxed array('Array', 'SmallArray'..).+--+-- NOTE: These functions may segfault when used with indices which are out of bounds.+uninitialized :: a+uninitialized = throw (UndefinedElement "Data.Array.uninitialized")++-- | A typeclass to unify box & unboxed, mutable & immutable array operations.+--+-- Most of these functions simply wrap their primitive counterpart, if there's no primitive ones,+-- we polyfilled using other operations to get the same semantics.+--+-- One exception is that 'shrinkMutableArr' only perform closure resizing on 'PrimArray' because+-- current RTS support only that, 'shrinkMutableArr' will do nothing on other array type.+--+-- It's reasonable to trust GHC with specializing & inlining these polymorphric functions.+-- They are used across this package and perform identical to their monomophric counterpart.+--+class Arr (marr :: * -> * -> *) (arr :: * -> * ) a | arr -> marr, marr -> arr where++    -- | Make a new array with given size.+    --+    -- For boxed array, all elements are 'uninitialized' which shall not be accessed.+    -- For primitive array, elements are just random garbage.+    newArr :: (PrimMonad m, PrimState m ~ s) => Int -> m (marr s a)++    -- | Make a new array and fill it with an initial value.+    newArrWith :: (PrimMonad m, PrimState m ~ s) => Int -> a -> m (marr s a)++    -- | Index mutable array in a primitive monad.+    readArr :: (PrimMonad m, PrimState m ~ s) => marr s a -> Int -> m a++    -- | Write mutable array in a primitive monad.+    writeArr :: (PrimMonad m, PrimState m ~ s) => marr s a -> Int -> a -> m ()++    -- | Fill mutable array with a given value.+    setArr :: (PrimMonad m, PrimState m ~ s) => marr s a -> Int -> Int -> a -> m ()++    -- | Index immutable array, which is a pure operation. This operation often+    -- result in an indexing thunk for lifted arrays, use 'indexArr\'' or 'indexArrM'+    -- if that's not desired.+    indexArr :: arr a -> Int -> a++    -- | Index immutable array, pattern match on the unboxed unit tuple to force+    -- indexing (without forcing the element).+    indexArr' :: arr a -> Int -> (# a #)++    -- | Index immutable array in a primitive monad, this helps in situations that+    -- you want your indexing result is not a thunk referencing whole array.+    indexArrM :: (Monad m) => arr a -> Int -> m a++    -- | Safely freeze mutable array by make a immutable copy of its slice.+    freezeArr :: (PrimMonad m, PrimState m ~ s) => marr s a -> Int -> Int -> m (arr a)++    -- | Safely thaw immutable array by make a mutable copy of its slice.+    thawArr :: (PrimMonad m, PrimState m ~ s) => arr a -> Int -> Int -> m (marr s a)++    -- | In place freeze a mutable array, the original mutable array can not be used+    -- anymore.+    unsafeFreezeArr :: (PrimMonad m, PrimState m ~ s) => marr s a -> m (arr a)++    -- | In place thaw a immutable array, the original immutable array can not be used+    -- anymore.+    unsafeThawArr :: (PrimMonad m, PrimState m ~ s) => arr a -> m (marr s a)++    -- | Copy a slice of immutable array to mutable array at given offset.+    copyArr ::  (PrimMonad m, PrimState m ~ s) => marr s a -> Int -> arr a -> Int -> Int -> m ()++    -- | Copy a slice of mutable array to mutable array at given offset.+    -- The two mutable arrays shall no be the same one.+    copyMutableArr :: (PrimMonad m, PrimState m ~ s) => marr s a -> Int -> marr s a -> Int -> Int -> m ()++    -- | Copy a slice of mutable array to mutable array at given offset.+    -- The two mutable arrays may be the same one.+    moveArr :: (PrimMonad m, PrimState m ~ s) => marr s a -> Int -> marr s a -> Int -> Int -> m ()++    -- | Create immutable copy.+    cloneArr :: arr a -> Int -> Int -> arr a++    -- | Create mutable copy.+    cloneMutableArr :: (PrimMonad m, PrimState m ~ s) => marr s a -> Int -> Int -> m (marr s a)++    -- | Resize mutable array to given size.+    resizeMutableArr :: (PrimMonad m, PrimState m ~ s) => marr s a -> Int -> m (marr s a)++    -- | Shrink mutable array to given size. This operation only works on primitive arrays.+    -- For boxed array, this is a no-op, e.g. 'sizeOfMutableArr' will not change.+    shrinkMutableArr :: (PrimMonad m, PrimState m ~ s) => marr s a -> Int -> m ()++    -- | Is two mutable array are reference equal.+    sameMutableArr :: marr s a -> marr s a -> Bool++    -- | Size of immutable array.+    sizeofArr :: arr a -> Int++    -- | Size of mutable array.+    sizeofMutableArr :: (PrimMonad m, PrimState m ~ s) => marr s a -> m Int++    -- | Is two immutable array are referencing the same one.+    --+    -- Note that 'sameArr' 's result may change depending on compiler's optimizations, for example+    -- @let arr = runST ... in arr `sameArr` arr@ may return false if compiler decides to+    -- inline it.+    --+    -- See https://ghc.haskell.org/trac/ghc/ticket/13908 for more background.+    --+    sameArr :: arr a -> arr a -> Bool++instance Arr MutableArray Array a where+    newArr n = newArray n uninitialized+    {-# INLINE newArr #-}+    newArrWith = newArray+    {-# INLINE newArrWith #-}+    readArr = readArray+    {-# INLINE readArr #-}+    writeArr = writeArray+    {-# INLINE writeArr #-}+    setArr marr s l x = go s+      where+        !sl = s + l+        go !i | i >= sl = return ()+              | otherwise = writeArray marr i x >> go (i+1)+    {-# INLINE setArr #-}+    indexArr = indexArray+    {-# INLINE indexArr #-}+    indexArr' (Array arr#) (I# i#) = indexArray# arr# i#+    {-# INLINE indexArr' #-}+    indexArrM = indexArrayM+    {-# INLINE indexArrM #-}+    freezeArr = freezeArray+    {-# INLINE freezeArr #-}+    thawArr = thawArray+    {-# INLINE thawArr #-}+    unsafeFreezeArr = unsafeFreezeArray+    {-# INLINE unsafeFreezeArr #-}+    unsafeThawArr = unsafeThawArray+    {-# INLINE unsafeThawArr #-}++    copyArr = copyArray+    {-# INLINE copyArr #-}+    copyMutableArr = copyMutableArray+    {-# INLINE copyMutableArr #-}++    moveArr marr1 s1 marr2 s2 l+        | l <= 0 = return ()+        | sameMutableArray marr1 marr2 =+            case compare s1 s2 of+                LT ->+                    let !d = s2 - s1+                        !s2l = s2 + l+                        go !i | i >= s2l = return ()+                              | otherwise = do x <- readArray marr2 i+                                               writeArray marr1 (i-d) x+                                               go (i+1)+                    in go s2++                EQ -> return ()++                GT ->+                    let !d = s1 - s2+                        go !i | i < s2 = return ()+                              | otherwise = do x <- readArray marr2 i+                                               writeArray marr1 (i+d) x+                                               go (i-1)+                    in go (s2+l-1)+        | otherwise = copyMutableArray marr1 s1 marr2 s2 l+    {-# INLINE moveArr #-}++    cloneArr = cloneArray+    {-# INLINE cloneArr #-}+    cloneMutableArr = cloneMutableArray+    {-# INLINE cloneMutableArr #-}++    resizeMutableArr marr n = do+        marr' <- newArray n uninitialized+        copyMutableArray marr' 0 marr 0 (sizeofMutableArray marr)+        return marr'+    {-# INLINE resizeMutableArr #-}+    shrinkMutableArr _ _ = return ()+    {-# INLINE shrinkMutableArr #-}++    sameMutableArr = sameMutableArray+    {-# INLINE sameMutableArr #-}+    sizeofArr = sizeofArray+    {-# INLINE sizeofArr #-}+    sizeofMutableArr = return . sizeofMutableArray+    {-# INLINE sizeofMutableArr #-}++    sameArr (Array arr1#) (Array arr2#) = isTrue# (+        sameMutableArray# (unsafeCoerce# arr1#) (unsafeCoerce# arr2#))+    {-# INLINE sameArr #-}++instance Arr SmallMutableArray SmallArray a where+    newArr n = newSmallArray n uninitialized+    {-# INLINE newArr #-}+    newArrWith = newSmallArray+    {-# INLINE newArrWith #-}+    readArr = readSmallArray+    {-# INLINE readArr #-}+    writeArr = writeSmallArray+    {-# INLINE writeArr #-}+    setArr marr s l x = go s+      where+        !sl = s + l+        go !i | i >= sl = return ()+              | otherwise = writeSmallArray marr i x >> go (i+1)+    {-# INLINE setArr #-}+    indexArr = indexSmallArray+    {-# INLINE indexArr #-}+    indexArr' (SmallArray arr#) (I# i#) = indexSmallArray# arr# i#+    {-# INLINE indexArr' #-}+    indexArrM = indexSmallArrayM+    {-# INLINE indexArrM #-}+    freezeArr = freezeSmallArray+    {-# INLINE freezeArr #-}+    thawArr = thawSmallArray+    {-# INLINE thawArr #-}+    unsafeFreezeArr = unsafeFreezeSmallArray+    {-# INLINE unsafeFreezeArr #-}+    unsafeThawArr = unsafeThawSmallArray+    {-# INLINE unsafeThawArr #-}++    copyArr = copySmallArray+    {-# INLINE copyArr #-}+    copyMutableArr = copySmallMutableArray+    {-# INLINE copyMutableArr #-}++    moveArr marr1 s1 marr2 s2 l+        | l <= 0 = return ()+        | sameMutableArr marr1 marr2 =+            case compare s1 s2 of+                LT ->+                    let !d = s2 - s1+                        !s2l = s2 + l+                        go !i | i >= s2l = return ()+                              | otherwise = do x <- readSmallArray marr2 i+                                               writeSmallArray marr1 (i-d) x+                                               go (i+1)+                    in go s2++                EQ -> return ()++                GT ->+                    let !d = s1 - s2+                        go !i | i < s2 = return ()+                              | otherwise = do x <- readSmallArray marr2 i+                                               writeSmallArray marr1 (i+d) x+                                               go (i-1)+                    in go (s2+l-1)+        | otherwise = copySmallMutableArray marr1 s1 marr2 s2 l+    {-# INLINE moveArr #-}++    cloneArr = cloneSmallArray+    {-# INLINE cloneArr #-}+    cloneMutableArr = cloneSmallMutableArray+    {-# INLINE cloneMutableArr #-}++    resizeMutableArr marr n = do+        marr' <- newSmallArray n uninitialized+        copySmallMutableArray marr' 0 marr 0 (sizeofSmallMutableArray marr)+        return marr'+    {-# INLINE resizeMutableArr #-}+    shrinkMutableArr _ _ = return ()+    {-# INLINE shrinkMutableArr #-}++    sameMutableArr (SmallMutableArray smarr1#) (SmallMutableArray smarr2#) =+        isTrue# (sameSmallMutableArray# smarr1# smarr2#)+    {-# INLINE sameMutableArr #-}+    sizeofArr = sizeofSmallArray+    {-# INLINE sizeofArr #-}+    sizeofMutableArr = return . sizeofSmallMutableArray+    {-# INLINE sizeofMutableArr #-}++    sameArr (SmallArray arr1#) (SmallArray arr2#) = isTrue# (+        sameSmallMutableArray# (unsafeCoerce# arr1#) (unsafeCoerce# arr2#))+    {-# INLINE sameArr #-}++instance Prim a => Arr MutablePrimArray PrimArray a where+    newArr = newPrimArray+    {-# INLINE newArr #-}+    newArrWith n x = do+        marr <- newPrimArray n+        setPrimArray marr 0 n x+        return marr+    {-# INLINE newArrWith #-}+    readArr = readPrimArray+    {-# INLINE readArr #-}+    writeArr = writePrimArray+    {-# INLINE writeArr #-}+    setArr = setPrimArray+    {-# INLINE setArr #-}+    indexArr = indexPrimArray+    {-# INLINE indexArr #-}+    indexArr' arr i = (# indexPrimArray arr i #)+    {-# INLINE indexArr' #-}+    indexArrM arr i = return (indexPrimArray arr i)+    {-# INLINE indexArrM #-}+    freezeArr marr s l = do+        marr' <- newPrimArray l+        copyMutablePrimArray marr' 0 marr s l+        unsafeFreezePrimArray marr'+    {-# INLINE freezeArr #-}+    thawArr arr s l = do+        marr' <- newPrimArray l+        copyPrimArray marr' 0 arr s l+        return marr'+    {-# INLINE thawArr #-}+    unsafeFreezeArr = unsafeFreezePrimArray+    {-# INLINE unsafeFreezeArr #-}+    unsafeThawArr = unsafeThawPrimArray+    {-# INLINE unsafeThawArr #-}++    copyArr = copyPrimArray+    {-# INLINE copyArr #-}+    copyMutableArr = copyMutablePrimArray+    {-# INLINE copyMutableArr #-}++    moveArr (MutablePrimArray dst) doff (MutablePrimArray src) soff n =+        moveByteArray (MutableByteArray dst) (doff*siz) (MutableByteArray src) (soff*siz) (n*siz)+      where siz = sizeOf (undefined :: a)+    {-# INLINE moveArr #-}++    cloneArr arr s l = runST (do+            marr <- newPrimArray l+            copyPrimArray marr 0 arr s l+            unsafeFreezePrimArray marr+        )+    {-# INLINE cloneArr #-}+    cloneMutableArr marr s l = do+        marr' <- newPrimArray l+        copyMutablePrimArray marr' 0 marr s l+        return marr'+    {-# INLINE cloneMutableArr #-}++    resizeMutableArr = resizeMutablePrimArray+    {-# INLINE resizeMutableArr #-}+    shrinkMutableArr = shrinkMutablePrimArray+    {-# INLINE shrinkMutableArr #-}++    sameMutableArr = sameMutablePrimArray+    {-# INLINE sameMutableArr #-}+    sizeofArr = sizeofPrimArray+    {-# INLINE sizeofArr #-}+    sizeofMutableArr = getSizeofMutablePrimArray+    {-# INLINE sizeofMutableArr #-}++    sameArr (PrimArray ba1#) (PrimArray ba2#) =+        isTrue# (sameMutableByteArray# (unsafeCoerce# ba1#) (unsafeCoerce# ba2#))+    {-# INLINE sameArr #-}++instance PrimUnlifted a => Arr MutableUnliftedArray UnliftedArray a where+    newArr = unsafeNewUnliftedArray+    {-# INLINE newArr #-}+    newArrWith = newUnliftedArray+    {-# INLINE newArrWith #-}+    readArr = readUnliftedArray+    {-# INLINE readArr #-}+    writeArr = writeUnliftedArray+    {-# INLINE writeArr #-}+    setArr marr s l x = go s+      where+        !sl = s + l+        go !i | i >= sl = return ()+              | otherwise = writeUnliftedArray marr i x >> go (i+1)+    {-# INLINE setArr #-}+    indexArr = indexUnliftedArray+    {-# INLINE indexArr #-}+    indexArr' arr i = (# indexUnliftedArray arr i #)+    {-# INLINE indexArr' #-}+    indexArrM = indexUnliftedArrayM+    {-# INLINE indexArrM #-}+    freezeArr = freezeUnliftedArray+    {-# INLINE freezeArr #-}+    thawArr = thawUnliftedArray+    {-# INLINE thawArr #-}+    unsafeFreezeArr = unsafeFreezeUnliftedArray+    {-# INLINE unsafeFreezeArr #-}+    unsafeThawArr (UnliftedArray arr#) = primitive ( \ s0# ->+            let (# s1#, marr# #) = unsafeThawArray# (unsafeCoerce# arr#) s0#+                                                        -- ArrayArray# and Array# use the same representation+            in (# s1#, MutableUnliftedArray (unsafeCoerce# marr#) #)    -- so this works+        )+    {-# INLINE unsafeThawArr #-}++    copyArr = copyUnliftedArray+    {-# INLINE copyArr #-}+    copyMutableArr = copyMutableUnliftedArray+    {-# INLINE copyMutableArr #-}++    moveArr marr1 s1 marr2 s2 l+        | l <= 0 = return ()+        | sameMutableUnliftedArray marr1 marr2 =+            case compare s1 s2 of+                LT ->+                    let !d = s2 - s1+                        !s2l = s2 + l+                        go !i | i >= s2l = return ()+                              | otherwise = do x <- readUnliftedArray marr2 i+                                               writeUnliftedArray marr1 (i-d) x+                                               go (i+1)+                    in go s2++                EQ -> return ()++                GT ->+                    let !d = s1 - s2+                        go !i | i < s2 = return ()+                              | otherwise = do x <- readUnliftedArray marr2 i+                                               writeUnliftedArray marr1 (i+d) x+                                               go (i-1)+                    in go (s2+l-1)+        | otherwise = copyMutableUnliftedArray marr1 s1 marr2 s2 l+    {-# INLINE moveArr #-}++    cloneArr = cloneUnliftedArray+    {-# INLINE cloneArr #-}+    cloneMutableArr = cloneMutableUnliftedArray+    {-# INLINE cloneMutableArr #-}++    resizeMutableArr marr n = do+        marr' <- newUnliftedArray n uninitialized+        copyMutableUnliftedArray marr' 0 marr 0 (sizeofMutableUnliftedArray marr)+        return marr'+    {-# INLINE resizeMutableArr #-}+    shrinkMutableArr _ _ = return ()+    {-# INLINE shrinkMutableArr #-}++    sameMutableArr = sameMutableUnliftedArray+    {-# INLINE sameMutableArr #-}+    sizeofArr = sizeofUnliftedArray+    {-# INLINE sizeofArr #-}+    sizeofMutableArr = return . sizeofMutableUnliftedArray+    {-# INLINE sizeofMutableArr #-}++    sameArr (UnliftedArray arr1#) (UnliftedArray arr2#) = isTrue# (+        sameMutableArrayArray# (unsafeCoerce# arr1#) (unsafeCoerce# arr2#))+    {-# INLINE sameArr #-}++--------------------------------------------------------------------------------++-- | Create a /pinned/ byte array of the specified size,+-- The garbage collector is guaranteed not to move it.+newPinnedPrimArray :: forall m a. (PrimMonad m, Prim a) => Int -> m (MutablePrimArray (PrimState m) a)+{-# INLINE newPinnedPrimArray #-}+newPinnedPrimArray n = do+    (MutableByteArray mba#) <- newPinnedByteArray (n*siz)+    return (MutablePrimArray mba#)+  where siz = sizeOf (undefined :: a)++-- | Create a /pinned/ primitive array of the specified size and respect given primitive type's+-- alignment. The garbage collector is guaranteed not to move it.+--+newAlignedPinnedPrimArray+  :: forall m a. (PrimMonad m, Prim a) => Int -> m (MutablePrimArray (PrimState m) a)+{-# INLINE newAlignedPinnedPrimArray #-}+newAlignedPinnedPrimArray n = do+    (MutableByteArray mba#) <- newAlignedPinnedByteArray (n*siz) align+    return (MutablePrimArray mba#)+  where siz = sizeOf (undefined :: a)+        align = alignment (undefined :: a)++-- | Yield a pointer to the array's data.+--+-- This operation is only safe on /pinned/ primitive arrays allocated by 'newPinnedPrimArray' or+-- 'newAlignedPinnedPrimArray', and you have to make sure the 'PrimArray' can outlive the 'Ptr'.+--+primArrayContents :: PrimArray a -> Ptr a+{-# INLINE primArrayContents #-}+primArrayContents (PrimArray ba) =+    let addr# = byteArrayContents# ba in Ptr addr#++-- | Yield a pointer to the array's data.+--+-- This operation is only safe on /pinned/ primitive arrays allocated by 'newPinnedPrimArray' or+-- 'newAlignedPinnedPrimArray'. and you have to make sure the 'PrimArray' can outlive the 'Ptr'.+--+mutablePrimArrayContents :: MutablePrimArray s a -> Ptr a+{-# INLINE mutablePrimArrayContents #-}+mutablePrimArrayContents (MutablePrimArray mba#) =+    let addr# = byteArrayContents# (unsafeCoerce# mba#) in Ptr addr#++-- | Yield a pointer to the array's data and do computation with it.+--+-- This operation is only safe on /pinned/ primitive arrays allocated by 'newPinnedPrimArray' or+-- 'newAlignedPinnedPrimArray'.+--+-- Don't pass a forever loop to this function, see <https://ghc.haskell.org/trac/ghc/ticket/14346 #14346>.+withPrimArrayContents :: PrimArray a -> (Ptr a -> IO b) -> IO b+{-# INLINE withPrimArrayContents #-}+withPrimArrayContents (PrimArray ba#) f = do+    let addr# = byteArrayContents# ba#+        ptr = Ptr addr#+    b <- f ptr+    primitive_ (touch# ba#)+    return b++-- | Yield a pointer to the array's data and do computation with it.+--+-- This operation is only safe on /pinned/ primitive arrays allocated by 'newPinnedPrimArray' or+-- 'newAlignedPinnedPrimArray'.+--+-- Don't pass a forever loop to this function, see <https://ghc.haskell.org/trac/ghc/ticket/14346 #14346>.+withMutablePrimArrayContents :: MutablePrimArray RealWorld a -> (Ptr a -> IO b) -> IO b+{-# INLINE withMutablePrimArrayContents #-}+withMutablePrimArrayContents (MutablePrimArray mba#) f = do+    let addr# = byteArrayContents# (unsafeCoerce# mba#)+        ptr = Ptr addr#+    b <- f ptr+    primitive_ (touch# mba#)+    return b++-- | Check if a primitive array is pinned.+--+isPrimArrayPinned :: PrimArray a -> Bool+{-# INLINE isPrimArrayPinned #-}+isPrimArrayPinned (PrimArray ba#) = tagToEnum# (isByteArrayPinned# ba#)++-- | Check if a mutable primitive array is pinned.+--+isMutablePrimArrayPinned :: MutablePrimArray s a -> Bool+{-# INLINE isMutablePrimArrayPinned #-}+isMutablePrimArrayPinned (MutablePrimArray mba#) =+    tagToEnum# (isByteArrayPinned# (unsafeCoerce# mba#))+++-- | Cast between arrays+--+castArray :: (Arr marr arr a, Cast a b) => arr a -> arr b+castArray = unsafeCoerce#++castMutableArray :: (Arr marr arr a, Cast a b) => marr s a -> marr s b+castMutableArray = unsafeCoerce#
+ Std/Data/Array/Checked.hs view
@@ -0,0 +1,275 @@+{-# LANGUAGE TypeFamilies  #-}+{-# LANGUAGE UnboxedTuples #-}++{-|+Module      : Std.Data.Array.Checked+Description : Bounded checked boxed and unboxed arrays+Copyright   : (c) Dong Han, 2017-2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provides exactly the same API with "Std.Data.Array", but will throw an 'IndexOutOfBounds'+'ArrayException' on bound check failure, it's useful when debugging array algorithms: just swap this+module with "Std.Data.Array", segmentation faults caused by out bound access will be turned into exceptions+with more informations.++-}+module Std.Data.Array.Checked+  ( -- * Arr typeclass re-export+    A.Arr+  , RealWorld+    -- * Bound checked array operations+  , newArr+  , newArrWith+  , readArr+  , writeArr+  , setArr+  , indexArr+  , indexArr'+  , indexArrM+  , freezeArr+  , thawArr+  , copyArr+  , copyMutableArr+  , moveArr+  , cloneArr+  , cloneMutableArr+  , resizeMutableArr+  , shrinkMutableArr+  -- * No bound checked operations+  , A.unsafeFreezeArr+  , A.unsafeThawArr+  , A.sameMutableArr+  , A.sizeofArr+  , A.sizeofMutableArr+  , A.sameArr+  -- * Boxed array type+  , A.Array(..)+  , A.MutableArray(..)+  , A.SmallArray(..)+  , A.SmallMutableArray(..)+  , A.uninitialized+  -- * Primitive array type+  , A.PrimArray(..)+  , A.MutablePrimArray(..)+  -- * Bound checked primitive array operations+  , newPinnedPrimArray, newAlignedPinnedPrimArray+  , copyPrimArrayToPtr, copyMutablePrimArrayToPtr, copyPtrToMutablePrimArray+  -- * No bound checked primitive array operations+  , A.primArrayContents, A.mutablePrimArrayContents, A.withPrimArrayContents, A.withMutablePrimArrayContents+  , A.isPrimArrayPinned, A.isMutablePrimArrayPinned+  -- * Unlifted array type+  , A.UnliftedArray(..)+  , A.MutableUnliftedArray(..)+  , A.PrimUnlifted(..)+  -- * The 'ArrayException' type+  , ArrayException(..)+  ) where++import           Control.Exception       (ArrayException (..), throw)+import           Control.Monad.Primitive+import           Data.Primitive.Types+import           GHC.Ptr                 (Ptr (..))+import           GHC.Stack+import qualified Std.Data.Array          as A++check :: HasCallStack => Bool -> a -> a+{-# INLINE check #-}+check True  x = x+check False _ = throw (IndexOutOfBounds $ show callStack)++newArr :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+       => Int -> m (marr s a)+newArr n = check  (n>=0) (A.newArr n)+{-# INLINE newArr #-}++newArrWith :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+           => Int -> a -> m (marr s a)+newArrWith n x = check  (n>=0) (A.newArrWith n x)+{-# INLINE newArrWith #-}++readArr :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+        => marr s a -> Int -> m a+readArr marr i = do+    siz <- A.sizeofMutableArr marr+    check+        (i>=0 && i<siz)+        (A.readArr marr i)+{-# INLINE readArr #-}++writeArr :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+         => marr s a -> Int -> a -> m ()+writeArr marr i x = do+    siz <- A.sizeofMutableArr marr+    check+        (i>=0 && i<siz)+        (A.writeArr marr i x)+{-# INLINE writeArr #-}++setArr :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+       => marr s a -> Int -> Int -> a -> m ()+setArr marr s l x = do+    siz <- A.sizeofMutableArr marr+    check+        (s>=0 && l>=0 && (s+l)<=siz)+        (A.setArr marr s l x)+{-# INLINE setArr #-}++indexArr :: (A.Arr marr arr a, HasCallStack)+         => arr a -> Int -> a+indexArr arr i = check+    (i>=0 && i<A.sizeofArr arr)+    (A.indexArr arr i)+{-# INLINE indexArr #-}++indexArr' :: (A.Arr marr arr a, HasCallStack)+          => arr a -> Int -> (# a #)+indexArr' arr i =+    if (i>=0 && i<A.sizeofArr arr)+    then A.indexArr' arr i+    else throw (IndexOutOfBounds $ show callStack)+{-# INLINE indexArr' #-}++indexArrM :: (A.Arr marr arr a, Monad m, HasCallStack)+          => arr a -> Int -> m a+indexArrM arr i = check+    (i>=0 && i<A.sizeofArr arr)+    (A.indexArrM arr i)+{-# INLINE indexArrM #-}++freezeArr :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+          => marr s a -> Int -> Int -> m (arr a)+freezeArr marr s l = do+    siz <- A.sizeofMutableArr marr+    check+        (s>=0 && l>=0 && (s+l)<=siz)+        (A.freezeArr marr s l)+{-# INLINE freezeArr #-}++thawArr :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+        => arr a -> Int -> Int -> m (marr s a)+thawArr arr s l = check+    (s>=0 && l>=0 && (s+l)<=A.sizeofArr arr)+    (A.thawArr arr s l)+{-# INLINE thawArr #-}++copyArr :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+        => marr s a -> Int -> arr a -> Int -> Int -> m ()+copyArr marr s1 arr s2 l = do+    siz <- A.sizeofMutableArr marr+    check+        (s1>=0 && s2>=0 && l>=0 && (s2+l)<=A.sizeofArr arr && (s1+l)<=siz)+        (A.copyArr marr s1 arr s2 l)+{-# INLINE copyArr #-}++copyMutableArr :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+               => marr s a -> Int -> marr s a -> Int -> Int -> m ()+copyMutableArr marr1 s1 marr2 s2 l = do+    siz1 <- A.sizeofMutableArr marr1+    siz2 <- A.sizeofMutableArr marr2+    check+        (s1>=0 && s2>=0 && l>=0 && (s2+l)<=siz2 && (s1+l)<=siz1)+        (A.copyMutableArr marr1 s1 marr2 s2 l)+{-# INLINE copyMutableArr #-}++moveArr :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+        => marr s a -> Int -> marr s a -> Int -> Int -> m ()+moveArr marr1 s1 marr2 s2 l = do+    siz1 <- A.sizeofMutableArr marr1+    siz2 <- A.sizeofMutableArr marr2+    check+        (s1>=0 && s2>=0 && l>=0 && (s2+l)<=siz2 && (s1+l)<=siz1)+        (A.copyMutableArr marr1 s1 marr2 s2 l)+{-# INLINE moveArr #-}++cloneArr :: (A.Arr marr arr a, HasCallStack)+         => arr a -> Int -> Int -> arr a+cloneArr arr s l = check+    (s>=0 && l>=0 && (s+l)<=A.sizeofArr arr)+    (A.cloneArr arr s l)+{-# INLINE cloneArr #-}++cloneMutableArr :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+                => marr s a -> Int -> Int -> m (marr s a)+cloneMutableArr marr s l = do+    siz <- A.sizeofMutableArr marr+    check+        (s>=0 && l>=0 && (s+l)<=siz)+        (A.cloneMutableArr marr s l)+{-# INLINE cloneMutableArr #-}++resizeMutableArr :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+                 => marr s a -> Int -> m (marr s a)+resizeMutableArr marr n = check+    (n>=0)+    (A.resizeMutableArr marr n)+{-# INLINE resizeMutableArr #-}++-- | New size should be >= 0, and <= original size.+--+shrinkMutableArr :: (A.Arr marr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+                 => marr s a -> Int -> m ()+shrinkMutableArr marr n = do+    siz <- A.sizeofMutableArr marr+    check+        (n>=0 && n<=siz)+        (A.shrinkMutableArr marr n)+{-# INLINE shrinkMutableArr #-}++--------------------------------------------------------------------------------++-- | Create a /pinned/ byte array of the specified size,+-- The garbage collector is guaranteed not to move it.+newPinnedPrimArray :: (PrimMonad m, Prim a, HasCallStack)+                   => Int -> m (A.MutablePrimArray (PrimState m) a)+{-# INLINE newPinnedPrimArray #-}+newPinnedPrimArray n =+    check  (n>=0) (A.newPinnedPrimArray n)++-- | Create a /pinned/ primitive array of the specified size and respect given primitive type's+-- alignment. The garbage collector is guaranteed not to move it.+--+newAlignedPinnedPrimArray :: (PrimMonad m, Prim a, HasCallStack)+                          => Int -> m (A.MutablePrimArray (PrimState m) a)+{-# INLINE newAlignedPinnedPrimArray #-}+newAlignedPinnedPrimArray n =+    check  (n>=0) (A.newAlignedPinnedPrimArray n)++copyPrimArrayToPtr :: (PrimMonad m, Prim a, HasCallStack)+                   => Ptr a+                   -> A.PrimArray a+                   -> Int+                   -> Int+                   -> m ()+{-# INLINE copyPrimArrayToPtr #-}+copyPrimArrayToPtr ptr arr s l = check+    (s>=0 && l>=0 && (s+l)<=A.sizeofArr arr)+    (A.copyPrimArrayToPtr ptr arr s l)++copyMutablePrimArrayToPtr :: (PrimMonad m, Prim a, HasCallStack)+                          => Ptr a+                          -> A.MutablePrimArray (PrimState m) a+                          -> Int+                          -> Int+                          -> m ()+{-# INLINE copyMutablePrimArrayToPtr #-}+copyMutablePrimArrayToPtr ptr marr s l = do+    siz <- A.sizeofMutableArr marr+    check+        (s>=0 && l>=0 && (s+l)<=siz)+        (A.copyMutablePrimArrayToPtr ptr marr s l)++copyPtrToMutablePrimArray :: (PrimMonad m, Prim a, HasCallStack)+                            => A.MutablePrimArray (PrimState m) a+                            -> Int+                            -> Ptr a+                            -> Int+                            -> m ()+{-# INLINE copyPtrToMutablePrimArray #-}+copyPtrToMutablePrimArray marr s ptr l = do+    siz <- A.sizeofMutableArr marr+    check+        (s>=0 && l>=0 && (s+l)<=siz)+        (A.copyPtrToMutablePrimArray marr s ptr l)
+ Std/Data/Builder.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UnboxedTuples       #-}++{-|+Module      : Std.Data.Builder+Description : Efficient serialization/format.+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++A 'Builder' records a buffer writing function, which can be 'mappend' in O(1) via composition. This module provides many functions to turn basic data types into 'Builder's, which can used to build strict 'Bytes' or list of 'Bytes' chunks.++-}++module Std.Data.Builder+  ( -- * Builder type+    Builder+  , append+   -- * Running builders+  , buildBytes+  , buildBytesWith+  , buildBytesList+  , buildBytesListWith+  , buildAndRun+  , buildAndRunWith+    -- * Basic buiders+  , bytes+  , ensureN+  , atMost+  , writeN+   -- * Pritimive builders+  , encodePrim+  , encodePrimLE+  , encodePrimBE+  -- * More builders+  , stringUTF8, charUTF8, string7, char7, string8, char8, text+  -- * Numeric builders+  -- ** Integral type formatting+  , IFormat(..)+  , defaultIFormat+  , Padding(..)+  , int+  , intWith+  , integer+  -- ** Fixded size hexidecimal formatting+  , hex, heX+  -- ** IEEE float formating+  , FFormat(..)+  , double+  , doubleWith+  , float+  , floatWith+  , scientific+  , scientificWith+  ) where++import           Std.Data.Builder.Base+import           Std.Data.Builder.Numeric
+ Std/Data/Builder/Base.hs view
@@ -0,0 +1,509 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE UnboxedTuples       #-}++{-|+Module      : Std.Data.Builder.Base+Description : Efficient serialization/format.+Copyright   : (c) Dong Han, 2017-2019+              (c) Tao He, 2018-2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++A 'Builder' records a buffer writing function, which can be 'mappend' in O(1) via composition.+In stdio a 'Builder' are designed to deal with different 'AllocateStrategy', it affects how+'Builder' react when writing across buffer boundaries:++  * When building a short strict 'Bytes' with 'buildBytes/buildByteswith',+    we do a 'DoubleBuffer'.++  * When building a large lazy @[Bytes]@ with 'buildBytesList/buildBytesListwith',+    we do an 'InsertChunk'.++  * When building and consuming are interlaced with 'buildAndRun/buildAndRunWith',+    we do an 'OneShotAction'.++Most of the time using combinators from this module to build 'Builder' s is enough,+but in case of rolling something shining from the ground, keep an eye on correct+'AllocateStrategy' handling.++-}++module Std.Data.Builder.Base+  ( -- * Builder type+    AllocateStrategy(..)+  , Buffer(..)+  , BuildStep+  , Builder(..)+  , append+   -- * Running a builder+  , buildBytes+  , buildBytesWith+  , buildBytesList+  , buildBytesListWith+  , buildAndRun+  , buildAndRunWith+    -- * Basic buiders+  , bytes+  , ensureN+  , atMost+  , writeN+   -- * Boundary handling+  , doubleBuffer+  , insertChunk+  , oneShotAction+   -- * Pritimive builders+  , encodePrim+  , encodePrimLE+  , encodePrimBE+  -- * More builders+  , stringModifiedUTF8, charModifiedUTF8, stringUTF8, charUTF8, string7, char7, string8, char8, text+  ) where++import           Control.Monad+import           Control.Monad.Primitive+import           Control.Monad.ST+import           Control.Monad.ST.Unsafe            (unsafeInterleaveST)+import           Data.Bits                          (shiftL, shiftR, (.&.))+import           Data.Monoid                        (Monoid (..))+import           Data.Primitive.PrimArray           (MutablePrimArray (..))+import           Data.Primitive.Ptr                 (copyPtrToMutablePrimArray)+import           Data.Semigroup                     (Semigroup (..))+import           Data.String                        (IsString (..))+import           Data.Word+import           Data.Int+import           GHC.CString                        (unpackCString#)+import           GHC.Prim+import           GHC.Ptr+import           GHC.Types+import qualified Std.Data.Array                     as A+import           Std.Data.PrimArray.UnalignedAccess+import qualified Std.Data.Text.Base                 as T+import qualified Std.Data.Text.UTF8Codec            as T+import qualified Std.Data.Vector.Base               as V+import           System.IO.Unsafe++-- | 'AllocateStrategy' will decide how each 'BuildStep' proceed when previous buffer is not enough.+--+data AllocateStrategy s+    = DoubleBuffer       -- Double the buffer and continue building+    | InsertChunk {-# UNPACK #-} !Int   -- Insert a new chunk and continue building+    | OneShotAction (V.Bytes -> ST s ())  -- Freeze current chunk and perform action with it.+                                        -- Use the 'V.Bytes' argument outside the action is dangerous+                                        -- since we will reuse the buffer after action finished.++-- | Helper type to help ghc unpack+--+data Buffer s = Buffer {-# UNPACK #-} !(A.MutablePrimArray s Word8)  -- ^ the buffer content+                       {-# UNPACK #-} !Int  -- ^ writing offset++-- | @BuilderStep@ is a function that fill buffer under given conditions.+--+type BuildStep s = Buffer s -> ST s [V.Bytes]++-- | @Builder@ is a monad to help compose @BuilderStep@. With next @BuilderStep@ continuation,+-- we can do interesting things like perform some action, or interleave the build process.+--+-- Notes on 'IsString' instance: @Builder ()@'s 'IsString' instance use 'stringModifiedUTF8',+-- which is different from 'stringUTF8' in that it DOES NOT PROVIDE UTF8 GUARANTEES! :+--+-- * @\NUL@ will be written as @\xC0 \x80@.+-- * @\xD800@ ~ @\xDFFF@ will be encoded in three bytes as normal UTF-8 codepoints.+--+newtype Builder a = Builder+    { runBuilder :: forall s. AllocateStrategy s -> (a -> BuildStep s) -> BuildStep s}++instance Functor Builder where+    {-# INLINE fmap #-}+    fmap f (Builder b) = Builder (\ al k -> b al (k . f))+    {-# INLINE (<$) #-}+    a <$ (Builder b) = Builder (\ al k -> b al (\ _ -> k a))++instance Applicative Builder where+    {-# INLINE pure #-}+    pure x = Builder (\ _ k -> k x)+    {-# INLINE (<*>) #-}+    (Builder f) <*> (Builder b) = Builder (\ al k -> f al ( \ ab -> b al (k . ab)))+    {-# INLINE (*>) #-}+    (*>) = append++instance Monad Builder where+    {-# INLINE (>>=) #-}+    (Builder b) >>= f = Builder (\ al k -> b al ( \ a -> runBuilder (f a) al k))+    {-# INLINE (>>) #-}+    (>>) = append++instance Semigroup (Builder ()) where+    (<>) = append+    {-# INLINE (<>) #-}++instance Monoid (Builder ()) where+    mempty = pure ()+    {-# INLINE mempty #-}+    mappend = append+    {-# INLINE mappend #-}+    mconcat = foldr append (pure ())+    {-# INLINE mconcat #-}++instance (a ~ ()) => IsString (Builder a) where+    {-# INLINE fromString #-}+    fromString = stringModifiedUTF8++-- | Encode string with modified UTF-8 encoding, will be rewritten to a memcpy if possible.+stringModifiedUTF8 :: String -> Builder ()+{-# INLINE CONLIKE [1] stringModifiedUTF8 #-}+{-# RULES+    "stringModifiedUTF8/addrLiteral" forall addr . stringModifiedUTF8 (unpackCString# addr) = addrLiteral addr+  #-}+stringModifiedUTF8 = mapM_ charModifiedUTF8++-- | Turn 'Char' into 'Builder' with Modified UTF8 encoding+--+-- '\NUL' is encoded as two bytes @C0 80@ , '\xD800' ~ '\xDFFF' is encoded as a three bytes normal UTF-8 codepoint.+charModifiedUTF8 :: Char -> Builder ()+{-# INLINE charModifiedUTF8 #-}+charModifiedUTF8 chr = do+    ensureN 4+    Builder (\ _  k (Buffer mba i) -> do+        i' <- T.encodeCharModifiedUTF8 mba i chr+        k () (Buffer mba i'))++addrLiteral :: Addr# -> Builder ()+{-# INLINE addrLiteral #-}+addrLiteral addr# = copy addr#+  where+    len = fromIntegral . unsafeDupablePerformIO $ V.c_strlen addr#+    copy addr# = do+        ensureN len+        Builder (\ _  k (Buffer mba i) -> do+           copyPtrToMutablePrimArray mba i (Ptr addr#) len+           k () (Buffer mba (i + len)))++append :: Builder a -> Builder b -> Builder b+{-# INLINE append #-}+append (Builder f) (Builder g) = Builder (\ al k -> f al ( \ _ ->  g al k))++--------------------------------------------------------------------------------++-- | Write a 'V.Bytes'.+bytes :: V.Bytes -> Builder ()+{-# INLINE bytes #-}+bytes bs@(V.PrimVector arr s l) = Builder (\ strategy k buffer@(Buffer buf offset) ->+    case strategy of+        DoubleBuffer -> copy strategy k buffer+        InsertChunk chunkSiz+            | l <= chunkSiz `shiftR` 1 ->+                copy strategy k buffer -- the copy limit is half the chunk size+            | offset /= 0 ->+                 insertChunk chunkSiz 0 (\ buffer' -> (bs:) `fmap` k () buffer') buffer+            | otherwise -> (bs:) `fmap` k () buffer+        OneShotAction action -> do+            chunkSiz <- A.sizeofMutableArr buf+            case () of+                _+                    | l <= chunkSiz `shiftR` 1 ->+                        copy strategy k buffer+                    | offset /= 0 ->+                        oneShotAction action 0 (\ buffer' -> action bs >> k () buffer') buffer+                    | otherwise -> action bs >> k () buffer)+  where+    copy :: forall s a. AllocateStrategy s -> (() -> BuildStep s) -> BuildStep s+    copy strategy k =+        runBuilder (ensureN l) strategy ( \ _ (Buffer buf offset) -> do+                A.copyArr buf offset arr s l+                k () (Buffer buf (offset+l)))+    {-# INLINE copy #-}++-- | Ensure that there are at least @n@ many elements available.+ensureN :: Int -> Builder ()+{-# INLINE ensureN #-}+ensureN !n = Builder $ \ strategy k buffer@(Buffer buf offset) -> do+    siz <- A.sizeofMutableArr buf  -- You may think doing this will be slow+                                   -- but this value lives in CPU cache for most of the time+    if siz - offset >= n+    then k () buffer+    else handleBoundary strategy n k buffer+  where+    {-# NOINLINE handleBoundary #-} -- Don't inline this branchy code+    handleBoundary DoubleBuffer n k buffer = doubleBuffer n (k ()) buffer+    handleBoundary (InsertChunk chunkSiz) n k buffer = insertChunk chunkSiz n (k ()) buffer+    handleBoundary (OneShotAction action) n k buffer = oneShotAction action n (k ()) buffer++--------------------------------------------------------------------------------+--+-- Handle chunk boundary++doubleBuffer :: Int -> BuildStep s -> BuildStep s+doubleBuffer !wantSiz k buffer@(Buffer buf offset) = do+    !siz <- A.sizeofMutableArr buf+    let !siz' = max (offset + wantSiz `shiftL` 1)+                    (siz `shiftL` 1)+    buf' <- A.resizeMutableArr buf siz'   -- double the buffer+    k (Buffer buf' offset)                 -- continue building+{-# INLINE doubleBuffer #-}++insertChunk :: Int -> Int -> BuildStep s -> BuildStep s+{-# INLINE insertChunk #-}+insertChunk !chunkSiz !wantSiz k buffer@(Buffer buf offset) = do+    !siz <- A.sizeofMutableArr buf+    case () of+        _+            | offset /= 0 -> do     -- this is certainly hold, but we still guard it+                when (offset < siz)+                    (A.shrinkMutableArr buf offset)            -- shrink old buffer if not full+                arr <- A.unsafeFreezeArr buf                   -- popup old buffer+                buf' <- A.newArr (max wantSiz chunkSiz)        -- make a new buffer+                xs <- unsafeInterleaveST (k (Buffer buf' 0))  -- delay the rest building process+                let v = V.fromArr arr 0 offset+                v `seq` return (v : xs)+            | wantSiz <= siz -> k (Buffer buf 0)+            | otherwise -> do+                buf' <- A.newArr wantSiz        -- make a new buffer+                k (Buffer buf' 0 )++oneShotAction :: (V.Bytes -> ST s ()) -> Int -> BuildStep s -> BuildStep s+{-# INLINE oneShotAction #-}+oneShotAction action !wantSiz k buffer@(Buffer buf offset) = do+    !siz <- A.sizeofMutableArr buf+    case () of+        _+            | offset /= 0 -> do+                arr <- A.unsafeFreezeArr buf             -- popup old buffer+                action (V.PrimVector arr 0 offset)+                if wantSiz <= siz+                then k (Buffer buf 0)                    -- continue building with old buf+                else do+                    buf' <- A.newArr wantSiz             -- make a new buffer+                    k (Buffer buf' 0)+            | wantSiz <= siz -> k (Buffer buf 0)+            | otherwise -> do+                buf' <- A.newArr wantSiz                -- make a new buffer+                k (Buffer buf' 0 )++--------------------------------------------------------------------------------++-- | shortcut to 'buildBytesWith' 'V.defaultInitSize'.+buildBytes :: Builder a -> V.Bytes+{-# INLINE buildBytes #-}+buildBytes = buildBytesWith V.defaultInitSize++-- | run Builder with 'DoubleBuffer' strategy, which is suitable+-- for building short bytes.+buildBytesWith :: Int -> Builder a -> V.Bytes+{-# INLINABLE buildBytesWith #-}+buildBytesWith initSiz (Builder b) = runST $ do+    buf <- A.newArr initSiz+    [bs] <- b DoubleBuffer lastStep (Buffer buf 0 )+    return bs+  where+    lastStep _ (Buffer buf offset) = do+        siz <- A.sizeofMutableArr buf+        when (offset < siz) (A.shrinkMutableArr buf offset)+        arr <- A.unsafeFreezeArr buf+        return [V.PrimVector arr 0 offset]++-- | shortcut to 'buildBytesListWith' 'V.defaultChunkSize'.+buildBytesList :: Builder a -> [V.Bytes]+{-# INLINE buildBytesList #-}+buildBytesList = buildBytesListWith  V.smallChunkSize V.defaultChunkSize++-- | run Builder with 'InsertChunk' strategy, which is suitable+-- for building lazy bytes chunks.+buildBytesListWith :: Int -> Int -> Builder a -> [V.Bytes]+{-# INLINABLE buildBytesListWith #-}+buildBytesListWith initSiz chunkSiz (Builder b) = runST $ do+    buf <- A.newArr initSiz+    b (InsertChunk chunkSiz) lastStep (Buffer buf 0)+  where+    lastStep _ (Buffer buf offset) = do+        arr <- A.unsafeFreezeArr buf+        return [V.PrimVector arr 0 offset]++-- | shortcut to 'buildAndRunWith' 'V.defaultChunkSize'.+buildAndRun :: (V.Bytes -> IO ()) -> Builder a -> IO ()+buildAndRun = buildAndRunWith V.defaultChunkSize++-- | run Builder with 'OneShotAction' strategy, which is suitable+-- for doing effects while building.+buildAndRunWith :: Int -> (V.Bytes -> IO ()) -> Builder a -> IO ()+buildAndRunWith chunkSiz action (Builder b) = do+    buf <- A.newArr chunkSiz+    _ <- stToIO (b (OneShotAction (\ bs -> ioToPrim (action bs))) lastStep (Buffer buf 0))+    return ()+  where+    lastStep :: a -> BuildStep RealWorld+    lastStep _ (Buffer buf offset) = do+        arr <- A.unsafeFreezeArr buf+        ioToPrim (action (V.PrimVector arr 0 offset))+        return [] -- to match the silly return type+{-# INLINABLE buildAndRun #-}++--------------------------------------------------------------------------------++atMost :: Int  -- ^ size bound+       -> (forall s. A.MutablePrimArray s Word8 -> Int -> ST s Int)  -- ^ the writer which return a new offset+                                                                       -- for next write+       -> Builder ()+{-# INLINE atMost #-}+atMost n f = ensureN n `append`+    Builder (\ _  k (Buffer buf offset ) ->+        f buf offset >>= \ offset' -> k () (Buffer buf offset'))++writeN :: Int  -- ^ size bound+       -> (forall s. A.MutablePrimArray s Word8 -> Int -> ST s ())  -- ^ the writer which return a new offset+                                                                    -- for next write+       -> Builder ()+{-# INLINE writeN #-}+writeN n f = ensureN n `append`+    Builder (\ _  k (Buffer buf offset ) ->+        f buf offset >> k () (Buffer buf (offset+n)))++-- | write primitive types in host byte order.+encodePrim :: forall a. UnalignedAccess a => a -> Builder ()+{-# INLINE encodePrim #-}+{-# SPECIALIZE INLINE encodePrim :: Word -> Builder () #-}+{-# SPECIALIZE INLINE encodePrim :: Word64 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrim :: Word32 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrim :: Word16 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrim :: Word8 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrim :: Int -> Builder () #-}+{-# SPECIALIZE INLINE encodePrim :: Int64 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrim :: Int32 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrim :: Int16 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrim :: Int8 -> Builder () #-}+encodePrim x = do+    ensureN n+    Builder (\ _  k (Buffer (MutablePrimArray mba#) i@(I# i#)) -> do+        primitive_ (writeWord8ArrayAs mba# i# x)+        k () (Buffer (MutablePrimArray mba#) (i + n)))+  where+    n = (getUnalignedSize (unalignedSize :: UnalignedSize a))++-- | write primitive types with little endianess.+encodePrimLE :: forall a. UnalignedAccess (LE a) => a -> Builder ()+{-# INLINE encodePrimLE #-}+{-# SPECIALIZE INLINE encodePrimLE :: Word -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimLE :: Word64 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimLE :: Word32 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimLE :: Word16 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimLE :: Int -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimLE :: Int64 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimLE :: Int32 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimLE :: Int16 -> Builder () #-}+encodePrimLE = encodePrim . LE++-- | write primitive types with big endianess.+encodePrimBE :: forall a. UnalignedAccess (BE a) => a -> Builder ()+{-# INLINE encodePrimBE #-}+{-# SPECIALIZE INLINE encodePrimBE :: Word -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimBE :: Word64 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimBE :: Word32 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimBE :: Word16 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimBE :: Int -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimBE :: Int64 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimBE :: Int32 -> Builder () #-}+{-# SPECIALIZE INLINE encodePrimBE :: Int16 -> Builder () #-}+encodePrimBE = encodePrim . BE++--------------------------------------------------------------------------------++-- | Turn 'String' into 'Builder' with UTF8 encoding+--+-- Illegal codepoints will be written as 'T.replacementChar's.+--+-- Note, if you're trying to write string literals builders, and you know it doen't contain+-- '\NUL' or surrgate codepoints, then you can open 'OverloadedStrings' and use 'Builder''s+-- 'IsString' instance, it can save an extra UTF-8 validation.+--+-- This function will be rewritten into a memcpy if possible, (running a fast UTF-8 validation+-- at runtime first).+stringUTF8 :: String -> Builder ()+{-# INLINE CONLIKE [1] stringUTF8 #-}+{-# RULES+    "stringUTF8/addrUTF8" forall addr . stringUTF8 (unpackCString# addr) = addrUTF8 addr+  #-}+stringUTF8 = mapM_ charUTF8++addrUTF8 :: Addr# -> Builder ()+{-# INLINABLE addrUTF8 #-}+addrUTF8 addr# = validateAndCopy addr#+  where+    len = fromIntegral . unsafeDupablePerformIO $ V.c_strlen addr#+    valid = unsafeDupablePerformIO $ T.c_utf8_validate_addr addr# len+    validateAndCopy addr#+        | valid == 0 = mapM_ charUTF8 (unpackCString# addr#)+        | otherwise = do+            ensureN len+            Builder (\ _  k (Buffer mba i) -> do+               copyPtrToMutablePrimArray mba i (Ptr addr#) len+               k () (Buffer mba (i + len)))++-- | Turn 'Char' into 'Builder' with UTF8 encoding+--+-- Illegal codepoints will be written as 'T.replacementChar's.+charUTF8 :: Char -> Builder ()+{-# INLINE charUTF8 #-}+charUTF8 chr = do+    ensureN 4+    Builder (\ _  k (Buffer mba i) -> do+        i' <- T.encodeChar mba i chr+        k () (Buffer mba i'))++-- | Turn 'String' into 'Builder' with ASCII7 encoding+--+-- Codepoints beyond @'\x7F'@ will be chopped.+string7 :: String -> Builder ()+{-# INLINE string7 #-}+string7 = mapM_ char7++-- | Turn 'Char' into 'Builder' with ASCII7 encoding+--+-- Codepoints beyond @'\x7F'@ will be chopped.+char7 :: Char -> Builder ()+{-# INLINE char7 #-}+char7 chr = do+    ensureN 1+    Builder (\ _  k (Buffer mba@(MutablePrimArray mba#) i@(I# i#)) -> do+        let x = V.c2w chr .&. 0x7F+        primitive_ (writeWord8ArrayAs mba# i# x)+        k () (Buffer mba (i+1)))++-- | Turn 'String' into 'Builder' with ASCII8 encoding+--+-- Codepoints beyond @'\xFF'@ will be chopped.+-- Note, this encoding is NOT compatible with UTF8 encoding, i.e. bytes written+-- by this builder may not be legal UTF8 encoding bytes.+string8 :: String -> Builder ()+{-# INLINE string8 #-}+string8 = mapM_ char8++-- | Turn 'Char' into 'Builder' with ASCII8 encoding+--+-- Codepoints beyond @'\xFF'@ will be chopped.+-- Note, this encoding is NOT compatible with UTF8 encoding, i.e. bytes written+-- by this builder may not be legal UTF8 encoding bytes.+char8 :: Char -> Builder ()+{-# INLINE char8 #-}+char8 chr = do+    ensureN 1+    Builder (\ _  k (Buffer mba@(MutablePrimArray mba#) i@(I# i#)) -> do+        let x = V.c2w chr+        primitive_ (writeWord8ArrayAs mba# i# x)+        k () (Buffer mba (i+1)))++-- | Write UTF8 encoded 'Text' using 'Builder'.+--+-- Note, if you're trying to write string literals builders,+-- please open 'OverloadedStrings' and use 'Builder's 'IsString' instance,+-- it will be rewritten into a memcpy.+text :: T.Text -> Builder ()+{-# INLINE text #-}+text (T.Text bs) = bytes bs
+ Std/Data/Builder/Numeric.hs view
@@ -0,0 +1,744 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE UnboxedTuples       #-}+{-# LANGUAGE UnliftedFFITypes    #-}++{-|+Module      : Std.Data.Builder.Numeric+Description : Textual numeric builders.+Copyright   : (c) Dong Han, 2017-2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++Textual numeric builders.++-}++module Std.Data.Builder.Numeric (+  -- * Integral type formatting+    IFormat(..)+  , defaultIFormat+  , Padding(..)+  , int+  , intWith+  , integer+  -- * Fixded size hexidecimal formatting+  , hex, heX+  -- * IEEE float formating+  , FFormat(..)+  , double+  , doubleWith+  , float+  , floatWith+  , scientific+  , scientificWith+  -- * Misc+  , grisu3+  , grisu3_sp+  , i2wDec, i2wHex, i2wHeX+  , countDigits+) where++import           Control.Monad+import           Control.Monad.ST+import           Data.Bits+import           Data.Char+import           Data.Int+import qualified Data.List                           as List+import           Data.Primitive.Addr+import           Data.Primitive.ByteArray+import           Data.Primitive.PrimArray+import qualified Data.Scientific                     as Sci+import           Data.Word+import           GHC.Exts+import           GHC.Float+import           GHC.Integer+import           GHC.Types+import           Std.Data.Builder.Base+import           Std.Data.Builder.Numeric.DigitTable+import           Std.Data.Text.Base+import           Std.Foreign.PrimArray+import           System.IO.Unsafe+#ifdef INTEGER_GMP+import           GHC.Integer.GMP.Internals+#endif+import           GHC.Float                           (roundTo)++--------------------------------------------------------------------------------++-- | Integral formatting options.+--+data IFormat = IFormat+    { width       :: Int              -- ^ total width, only effective with padding options+    , padding     :: Padding        -- ^ padding options+    , postiveSign :: Bool       -- ^ show @+@ when the number is positive+    } deriving (Show, Eq, Ord)++-- | @defaultIFormat = IFormat 0 NoPadding False Decimal@+defaultIFormat :: IFormat+defaultIFormat = IFormat 0 NoPadding False++data Padding = NoPadding | ZeroPadding | LeftSpacePadding | RightSpacePadding deriving (Show, Eq, Ord)++-- | @int = intWith defaultIFormat@+int :: (Integral a, Bounded a) => a -> Builder ()+int = intWith defaultIFormat++-- | Format a 'Bounded' 'Integral' type like @Int@ or @Word16@ into decimal ASCII digits.+intWith :: (Integral a, Bounded a)+        => IFormat+        -> a+        -> Builder ()+{-# INLINE[1] intWith #-}+{-# RULES "intWith'/Int8"    intWith = intWith' :: IFormat -> Int8    -> Builder () #-}+{-# RULES "intWith'/Int"     intWith = intWith' :: IFormat -> Int     -> Builder () #-}+{-# RULES "intWith'/Int16"   intWith = intWith' :: IFormat -> Int16   -> Builder () #-}+{-# RULES "intWith'/Int32"   intWith = intWith' :: IFormat -> Int32   -> Builder () #-}+{-# RULES "intWith'/Int64"   intWith = intWith' :: IFormat -> Int64   -> Builder () #-}+{-# RULES "intWith'/Word"    intWith = positiveInt  :: IFormat -> Word    -> Builder () #-}+{-# RULES "intWith'/Word8"   intWith = positiveInt  :: IFormat -> Word8   -> Builder () #-}+{-# RULES "intWith'/Word16"  intWith = positiveInt  :: IFormat -> Word16  -> Builder () #-}+{-# RULES "intWith'/Word32"  intWith = positiveInt  :: IFormat -> Word32  -> Builder () #-}+{-# RULES "intWith'/Word64"  intWith = positiveInt  :: IFormat -> Word64  -> Builder () #-}+intWith = intWith'++intWith' :: (Integral a, Bounded a) => IFormat -> a -> Builder ()+{-# SPECIALIZE INLINE intWith' :: IFormat -> Int   -> Builder () #-}+{-# SPECIALIZE INLINE intWith' :: IFormat -> Int8  -> Builder () #-}+{-# SPECIALIZE INLINE intWith' :: IFormat -> Int16 -> Builder () #-}+{-# SPECIALIZE INLINE intWith' :: IFormat -> Int32 -> Builder () #-}+{-# SPECIALIZE INLINE intWith' :: IFormat -> Int64 -> Builder () #-}+intWith' format@(IFormat width padding _) i+    | i < 0 =+        if i == minBound            -- can't directly negate in this case+        then do+            let (q, r) = i `quotRem` 10+                !qq = -q            -- all digits except last one+                !rr = i2wDec (-r)      -- last digits+                !n = countDigits qq+                !n' = n + 2         -- extra two bytes: minus and last digit+            if width > n'+            then case padding of+                NoPadding ->+                    writeN n' $ \marr off -> do+                        writePrimArray marr off minus                       -- leading minus+                        let off' = off + 1+                        writePositiveDec marr off' n qq                      -- digits+                        let off'' = off' + n+                        writePrimArray marr off'' rr                        -- last digit+                ZeroPadding ->+                    writeN width $ \marr off -> do+                        let !leadingN = width-n'+                        writePrimArray marr off minus                   -- leading minus+                        let off' = off + 1+                        setPrimArray marr off' leadingN zero            -- leading zeros+                        let off'' = off' + leadingN+                        writePositiveDec marr off'' n qq                 -- digits+                        let off''' = off'' + n+                        writePrimArray marr off''' rr                   -- last digit+                LeftSpacePadding ->+                    writeN width $ \marr off -> do+                        let !leadingN = width-n'+                        setPrimArray marr off leadingN space            -- leading spaces+                        let off' = off + leadingN+                        writePrimArray marr off' minus                  -- leading minus+                        let off'' = off' + 1+                        writePositiveDec marr off'' n qq                 -- digits+                        let off''' = off'' + n+                        writePrimArray marr off''' rr                   -- last digit+                RightSpacePadding ->+                    writeN width $ \marr off -> do+                        let !trailingN = width-n'+                        writePrimArray marr off minus                   -- leading minus+                        let off' = off + 1+                        writePositiveDec marr off' n qq                  -- digits+                        let off'' = off' + n+                        writePrimArray marr off'' rr                    -- last digit+                        let off''' = off'' + 1+                        setPrimArray marr off''' trailingN space        -- trailing spaces+            else+                writeN n' $ \marr off -> do+                    writePrimArray marr off minus                       -- leading minus+                    let off' = off + 1+                    writePositiveDec marr off' n qq                      -- digits+                    let off'' = off' + n+                    writePrimArray marr off'' rr                        -- last digit+        else do+            let !qq = -i+                !n = countDigits qq+                !n' = n + 1  -- extra byte: minus+            if width > n'+            then case padding of+                NoPadding ->+                    writeN n' $ \marr off -> do+                        writePrimArray marr off minus                       -- leading minus+                        let off' = off + 1+                        writePositiveDec marr off' n qq                      -- digits+                ZeroPadding ->+                    writeN width $ \marr off -> do+                        let !leadingN = width-n'+                        writePrimArray marr off minus                   -- leading minus+                        let off' = off + 1+                        setPrimArray marr off' leadingN zero            -- leading zeros+                        let off'' = off' + leadingN+                        writePositiveDec marr off'' n qq                 -- digits+                LeftSpacePadding ->+                    writeN width $ \marr off -> do+                        let !leadingN = width-n'+                        setPrimArray marr off leadingN space            -- leading spaces+                        let off' = off + leadingN+                        writePrimArray marr off' minus                  -- leading minus+                        let off'' = off' + 1+                        writePositiveDec marr off'' n qq                 -- digits+                RightSpacePadding ->+                    writeN width $ \marr off -> do+                        let !trailingN = width-n'+                        writePrimArray marr off minus                   -- leading minus+                        let off' = off + 1+                        writePositiveDec marr off' n qq                  -- digits+                        let off'' = off' + n+                        setPrimArray marr off'' trailingN space         -- trailing spaces+            else+                writeN n' $ \marr off -> do+                    writePrimArray marr off minus                       -- leading minus+                    let off' = off + 1+                    writePositiveDec marr off' n qq                      -- digits+    | otherwise = positiveInt format i++positiveInt :: (Integral a) => IFormat -> a -> Builder ()+{-# SPECIALIZE INLINE positiveInt :: IFormat -> Int    -> Builder () #-}+{-# SPECIALIZE INLINE positiveInt :: IFormat -> Int8   -> Builder () #-}+{-# SPECIALIZE INLINE positiveInt :: IFormat -> Int16  -> Builder () #-}+{-# SPECIALIZE INLINE positiveInt :: IFormat -> Int32  -> Builder () #-}+{-# SPECIALIZE INLINE positiveInt :: IFormat -> Int64  -> Builder () #-}+{-# SPECIALIZE INLINE positiveInt :: IFormat -> Word   -> Builder () #-}+{-# SPECIALIZE INLINE positiveInt :: IFormat -> Word8  -> Builder () #-}+{-# SPECIALIZE INLINE positiveInt :: IFormat -> Word16 -> Builder () #-}+{-# SPECIALIZE INLINE positiveInt :: IFormat -> Word32 -> Builder () #-}+{-# SPECIALIZE INLINE positiveInt :: IFormat -> Word64 -> Builder () #-}+positiveInt (IFormat width padding ps) i =+    let !n = countDigits i+    in if ps+        then+            let n' = n+1+            in if width > n'+            then case padding of+                NoPadding ->+                    writeN n' $ \marr off -> do+                        writePrimArray marr off plus                    -- leading plus+                        let off' = off + 1+                        writePositiveDec marr off' n i                   -- digits+                ZeroPadding ->+                    writeN width $ \marr off -> do+                        let !leadingN = width-n'+                        writePrimArray marr off plus                    -- leading plus+                        let off' = off + 1+                        setPrimArray marr off' leadingN zero            -- leading zeros+                        let off'' = off' + leadingN+                        writePositiveDec marr off'' n i                  -- digits+                LeftSpacePadding ->+                    writeN width $ \marr off -> do+                        let !leadingN = width-n'+                        setPrimArray marr off leadingN space            -- leading spaces+                        let off' = off + leadingN+                        writePrimArray marr off' plus                   -- leading plus+                        let off'' = off' + 1+                        writePositiveDec marr off'' n i                  -- digits+                RightSpacePadding ->+                    writeN width $ \marr off -> do+                        let !trailingN = width-n'+                        writePrimArray marr off plus                    -- leading plus+                        let off' = off + 1+                        writePositiveDec marr off' n i                   -- digits+                        let off'' = off' + n+                        setPrimArray marr off'' trailingN space         -- trailing spaces+            else+                writeN n' $ \marr off -> do+                    writePrimArray marr off plus                        -- leading plus+                    let off' = off + 1+                    writePositiveDec marr off' n i                       -- digits++        else if width > n+            then case padding of+                NoPadding ->+                    writeN n $ \marr off -> do+                        writePositiveDec marr off n i                    -- digits+                ZeroPadding ->+                    writeN width $ \marr off -> do+                        let !leadingN = width-n+                        setPrimArray marr off leadingN zero             -- leading zeros+                        let off' = off + leadingN+                        writePositiveDec marr off' n i                   -- digits+                LeftSpacePadding ->+                    writeN width $ \marr off -> do+                        let !leadingN = width-n+                        setPrimArray marr off leadingN space            -- leading spaces+                        let off' = off + leadingN+                        writePositiveDec marr off' n i                   -- digits+                RightSpacePadding ->+                    writeN width $ \marr off -> do+                        let !trailingN = width-n+                        writePositiveDec marr off n i                    -- digits+                        let off' = off + n+                        setPrimArray marr off' trailingN space          -- trailing spaces+            else+                writeN n $ \marr off -> do+                    writePositiveDec marr off n i                        -- digits++writePositiveDec :: (Integral a)+                => forall s. MutablePrimArray s Word8       -- ^ The buffer+                -> Int                                      -- ^ writing offset+                -> Int                                      -- ^ total digits+                -> a                                        -- ^ the value+                -> ST s ()+{-# INLINE writePositiveDec #-}+writePositiveDec marr off0 ds = go (off0 + ds - 1)+  where+    go off v+        | v >= 100 = do+            let (q, r) = v `quotRem` 100+            write2 off r+            go (off - 2) q+        | v < 10    = writePrimArray marr off (i2wDec v)+        | otherwise = write2 off v+    write2 off i0 = do+        let i = fromIntegral i0; j = i + i+        writePrimArray marr off $ indexOffAddr decDigitTable (j + 1)+        writePrimArray marr (off - 1) $ indexOffAddr decDigitTable j+++--------------------------------------------------------------------------------+-- Below is an implementation of formatting integer, the main+-- idea is borrowed from base (GHC.Show).++#include "MachDeps.h"+#if SIZEOF_HSWORD == 4+#define DIGITS       9+#define BASE         1000000000+#elif SIZEOF_HSWORD == 8+#define DIGITS       18+#define BASE         1000000000000000000+#else+#error Please define DIGITS and BASE+-- DIGITS should be the largest integer such that+--     10^DIGITS < 2^(SIZEOF_HSWORD * 8 - 1)+-- BASE should be 10^DIGITS.+#endif++-- | Format a 'Integer' into decimal ASCII digits.+integer :: Integer -> Builder ()+#ifdef INTEGER_GMP+integer (S# i#) = int (I# i#)+#endif+-- Divide and conquer implementation of string conversion+integer n0+    | n0 < 0    = encodePrim minus >> integer' (-n0)+    | otherwise = integer' n0+  where+    integer' :: Integer -> Builder ()+    integer' n+        | n < BASE  = jhead (fromInteger n)+        | otherwise = jprinth (jsplitf (BASE*BASE) n)++    -- Convert a number that has been split into digits in base BASE^2+    -- this includes a last splitting step and then conversion of digits+    -- that all fit into a machine word.+    jprinth :: [Integer] -> Builder ()+    jprinth (n:ns) =+        case n `quotRemInteger` BASE of+        (# q', r' #) ->+            let q = fromInteger q'+                r = fromInteger r'+            in if q > 0 then jhead q >> jblock r >> jprintb ns+                        else jhead r >> jprintb ns+    jprinth [] = errorWithoutStackTrace "jprinth []"++    jprintb :: [Integer] -> Builder ()+    jprintb []     = return ()+    jprintb (n:ns) = case n `quotRemInteger` BASE of+                        (# q', r' #) ->+                            let q = fromInteger q'+                                r = fromInteger r'+                            in jblock q >> jblock r >> jprintb ns++    -- Convert an integer that fits into a machine word. Again, we have two+    -- functions, one that drops leading zeros (jhead) and one that doesn't+    -- (jblock)+    jhead :: Int -> Builder ()+    jhead = int+    jblock :: Int -> Builder ()+    jblock d = writeN DIGITS $ \ marr off -> writePositiveDec marr off DIGITS d++    -- Split n into digits in base p. We first split n into digits+    -- in base p*p and then split each of these digits into two.+    -- Note that the first 'digit' modulo p*p may have a leading zero+    -- in base p that we need to drop - this is what jsplith takes care of.+    -- jsplitb the handles the remaining digits.+    jsplitf :: Integer -> Integer -> [Integer]+    jsplitf p n+        | p > n     = [n]+        | otherwise = jsplith p (jsplitf (p*p) n)++    jsplith :: Integer -> [Integer] -> [Integer]+    jsplith p (n:ns) =+        case n `quotRemInteger` p of+        (# q, r #) ->+            if q > 0 then q : r : jsplitb p ns+                     else     r : jsplitb p ns+    jsplith _ [] = errorWithoutStackTrace "jsplith: []"++    jsplitb :: Integer -> [Integer] -> [Integer]+    jsplitb _ []     = []+    jsplitb p (n:ns) = case n `quotRemInteger` p of+                       (# q, r #) ->+                           q : r : jsplitb p ns++--------------------------------------------------------------------------------++-- | Count how many decimal digits an integer has.+countDigits :: (Integral a) => a -> Int+{-# INLINE countDigits #-}+countDigits v0+  | fromIntegral v64 == v0 = go 1 v64+  | otherwise              = goBig 1 (fromIntegral v0)+  where v64 = fromIntegral v0+        goBig !k (v :: Integer)+           | v > big   = goBig (k + 19) (v `quot` big)+           | otherwise = go k (fromIntegral v)+        big = 10000000000000000000+        go !k (v :: Word64)+           | v < 10    = k+           | v < 100   = k + 1+           | v < 1000  = k + 2+           | v < 1000000000000 =+               k + if v < 100000000+                   then if v < 1000000+                        then if v < 10000+                             then 3+                             else 4 + fin v 100000+                        else 6 + fin v 10000000+                   else if v < 10000000000+                        then 8 + fin v 1000000000+                        else 10 + fin v 100000000000+           | otherwise = go (k + 12) (v `quot` 1000000000000)+        fin v n = if v >= n then 1 else 0++minus, plus, zero, space :: Word8+{-# INLINE plus #-}+{-# INLINE minus #-}+{-# INLINE zero #-}+{-# INLINE space #-}+plus = 43+minus = 45+zero = 48+space = 32++-- | Decimal digit to ASCII digit.+i2wDec :: (Integral a) => a -> Word8+{-# INLINE i2wDec #-}+i2wDec v = zero + fromIntegral v++-- | Decimal digit to ASCII char.+i2cDec :: (Integral a) => a -> Char+{-# INLINE i2cDec #-}+i2cDec v = chr . fromIntegral $ zero + fromIntegral v++-- | Hexadecimal digit to ASCII char.+i2wHex :: (Integral a) => a -> Word8+{-# INLINE i2wHex #-}+i2wHex v+    | v <= 9    = zero + fromIntegral v+    | otherwise = 87 + fromIntegral v       -- fromEnum 'a' - 10++-- | Hexadecimal digit to UPPERCASED ASCII char.+i2wHeX :: (Integral a) => a -> Word8+{-# INLINE i2wHeX #-}+i2wHeX v+    | v <= 9    = zero + fromIntegral v+    | otherwise = 55 + fromIntegral v       -- fromEnum 'A' - 10++--------------------------------------------------------------------------------++-- | Format a 'FiniteBits' 'Integral' type into hex nibbles.+hex :: forall a. (FiniteBits a, Integral a) => a -> Builder ()+{-# SPECIALIZE INLINE hex :: Int    -> Builder () #-}+{-# SPECIALIZE INLINE hex :: Int8   -> Builder () #-}+{-# SPECIALIZE INLINE hex :: Int16  -> Builder () #-}+{-# SPECIALIZE INLINE hex :: Int32  -> Builder () #-}+{-# SPECIALIZE INLINE hex :: Int64  -> Builder () #-}+{-# SPECIALIZE INLINE hex :: Word   -> Builder () #-}+{-# SPECIALIZE INLINE hex :: Word8  -> Builder () #-}+{-# SPECIALIZE INLINE hex :: Word16 -> Builder () #-}+{-# SPECIALIZE INLINE hex :: Word32 -> Builder () #-}+{-# SPECIALIZE INLINE hex :: Word64 -> Builder () #-}+hex w = writeN hexSize (go w (hexSize-2))+  where+    bitSize = finiteBitSize (undefined :: a)+    hexSize = (bitSize+3) `unsafeShiftR` 2+    go !v !d marr off+        | d > 0 = do+            let !i = fromIntegral v .&. 0xFF; !j = i + i+            writePrimArray marr (off + d) $ indexOffAddr hexDigitTable j+            writePrimArray marr (off + d + 1) $ indexOffAddr hexDigitTable (j+1)+            go (v `unsafeShiftR` 8) (d-2) marr off+        | d == 0 = do+            let !i = fromIntegral v .&. 0xFF; !j = i + i+            writePrimArray marr off $ indexOffAddr hexDigitTable j+            writePrimArray marr (off + 1) $ indexOffAddr hexDigitTable (j+1)+        | d < 0  = do         -- for FiniteBits instances which has extra bits+            let !i = fromIntegral v .&. 0x0F :: Int+            writePrimArray marr off $ i2wHex i+++-- | The UPPERCASED version of 'hex'.+heX :: forall a. (FiniteBits a, Integral a) => a -> Builder ()+{-# SPECIALIZE INLINE heX :: Int    -> Builder () #-}+{-# SPECIALIZE INLINE heX :: Int8   -> Builder () #-}+{-# SPECIALIZE INLINE heX :: Int16  -> Builder () #-}+{-# SPECIALIZE INLINE heX :: Int32  -> Builder () #-}+{-# SPECIALIZE INLINE heX :: Int64  -> Builder () #-}+{-# SPECIALIZE INLINE heX :: Word   -> Builder () #-}+{-# SPECIALIZE INLINE heX :: Word8  -> Builder () #-}+{-# SPECIALIZE INLINE heX :: Word16 -> Builder () #-}+{-# SPECIALIZE INLINE heX :: Word32 -> Builder () #-}+{-# SPECIALIZE INLINE heX :: Word64 -> Builder () #-}+heX w = writeN hexSize (go w (hexSize-2))+  where+    bitSize = finiteBitSize (undefined :: a)+    hexSize = (bitSize+3) `unsafeShiftR` 2+    go !v !d marr off+        | d > 0 = do+            let !i = fromIntegral v .&. 0xFF; !j = i + i+            writePrimArray marr (off + d) $ indexOffAddr hexDigitTableUpper j+            writePrimArray marr (off + d + 1) $ indexOffAddr hexDigitTableUpper (j+1)+            go (v `unsafeShiftR` 8) (d-2) marr off+        | d == 0 = do+            let !i = fromIntegral v .&. 0xFF; !j = i + i+            writePrimArray marr off $ indexOffAddr hexDigitTableUpper j+            writePrimArray marr (off + 1) $ indexOffAddr hexDigitTableUpper (j+1)+        | d < 0  = do         -- for FiniteBits instances which has extra bits+            let !i = fromIntegral v .&. 0x0F :: Int+            writePrimArray marr off $ i2wHeX i++--------------------------------------------------------------------------------++-- Floating point numbers+-------------------------++-- | Control the rendering of floating point numbers.+data FFormat = Exponent -- ^ Scientific notation (e.g. @2.3e123@).+             | Fixed    -- ^ Standard decimal notation.+             | Generic  -- ^ Use decimal notation for values between @0.1@ and+                        -- @9,999,999@, and scientific notation otherwise.+           deriving (Enum, Read, Show)++-- | Decimal encoding of an IEEE 'Float'.+--+-- Using standard decimal notation for arguments whose absolute value lies+-- between @0.1@ and @9,999,999@, and scientific notation otherwise.+float :: Float -> Builder ()+{-# INLINE float #-}+float = floatWith Generic Nothing++-- | Decimal encoding of an IEEE 'Double'.+--+-- Using standard decimal notation for arguments whose absolute value lies+-- between @0.1@ and @9,999,999@, and scientific notation otherwise.+double :: Double -> Builder ()+{-# INLINE double #-}+double = doubleWith Generic Nothing++-- | Format single-precision float using drisu3 with dragon4 fallback.+floatWith :: FFormat+          -> Maybe Int  -- ^ Number of decimal places to render.+          -> Float+          -> Builder ()+{-# INLINE floatWith #-}+floatWith fmt decs x+    | isNaN x                   = "NaN"+    | isInfinite x              = if x < 0 then "-Infinity" else "Infinity"+    | x < 0                     = char8 '-' >> doFmt fmt decs (digits (-x))+    | isNegativeZero x          = char8 '-' >> doFmt fmt decs ([0], 0)+    | x == 0                    = doFmt fmt decs ([0], 0)+    | otherwise                 = doFmt fmt decs (digits x) -- Grisu only handles strictly positive finite numbers.+  where+    digits y = case grisu3_sp y of Just r  -> r+                                   Nothing -> floatToDigits 10 y++-- | Format double-precision float using drisu3 with dragon4 fallback.+doubleWith :: FFormat+           -> Maybe Int  -- ^ Number of decimal places to render.+           -> Double+           -> Builder ()+{-# INLINE doubleWith #-}+doubleWith fmt decs x+    | isNaN x                   = "NaN"+    | isInfinite x              = if x < 0 then "-Infinity" else "Infinity"+    | x < 0                     = char8 '-' >> doFmt fmt decs (digits (-x))+    | isNegativeZero x          = char8 '-' >> doFmt fmt decs ([0], 0)+    | x == 0                    = doFmt fmt decs ([0], 0)+    | otherwise                 = doFmt fmt decs (digits x) -- Grisu only handles strictly positive finite numbers.+  where+    digits y = case grisu3 y of Just r  -> r+                                Nothing -> floatToDigits 10 y++-- | Worker function to do formatting.+doFmt :: FFormat+      -> Maybe Int -- ^ Number of decimal places to render.+      -> ([Int], Int) -- ^ List of digits and exponent+      -> Builder ()+{-# INLINABLE doFmt #-}+doFmt format decs (is, e) =+    let ds = map i2cDec is+    in case format of+        Generic ->+            doFmt (if e < 0 || e > 7 then Exponent else Fixed) decs (is,e)+        Exponent ->+            case decs of+                Nothing ->+                    let show_e' = int (e-1)+                    in case ds of+                        "0"     -> "0.0e0"+                        [d]     -> char8 d >> ".0e" >> show_e'+                        (d:ds') -> char8 d >> char8 '.' >>+                                        string8 ds' >> char8 'e' >> show_e'+                        []      -> error "doFmt/Exponent: []"+                Just dec+                    | dec <= 0 ->+                    -- decimal point as well (ghc trac #15115).+                    -- Note that this handles negative precisions as well for consistency+                    -- (see ghc trac #15509).+                        case is of+                            [0] -> "0e0"+                            _ -> do+                                let (ei,is') = roundTo 10 1 is+                                    n:_ = map i2cDec (if ei > 0 then init is' else is')+                                char8 n+                                char8 'e'+                                int (e-1+ei)+                Just dec ->+                    let dec' = max dec 1 in+                    case is of+                        [0] -> do+                                char8 '0'+                                char8 '.'+                                replicateM dec' $ char8 '0'+                                char8 'e'+                                char8 '0'+                        _ -> do+                            let (ei,is') = roundTo 10 (dec'+1) is+                                (d:ds') = map i2cDec (if ei > 0 then init is' else is')+                            char8 d+                            char8 '.'+                            string8 ds'+                            char8 'e'+                            int (e-1+ei)+        Fixed ->+            let mk0 ls = case ls of { "" -> char8 '0' ; _ -> string8 ls}+            in case decs of+                Nothing+                    | e <= 0    -> do+                                char8 '0'+                                char8 '.'+                                replicateM (-e) $ char8 '0'+                                string8 ds+                    | otherwise ->+                        let f 0 s    rs  = mk0 (reverse s) >> char8 '.' >> mk0 rs+                            f n s    ""  = f (n-1) ('0':s) ""+                            f n s (r:rs) = f (n-1) (r:s) rs+                        in f e "" ds+                Just dec ->+                    let dec' = max dec 0+                    in if e >= 0+                        then+                            let (ei,is') = roundTo 10 (dec' + e) is+                                (ls,rs)  = splitAt (e+ei) (map i2cDec is')+                            in mk0 ls >>+                                (unless (List.null rs) $ char8 '.' >> string8 rs)+                        else+                            let (ei,is') = roundTo 10 dec' (List.replicate (-e) 0 ++ is)+                                d:ds' = map i2cDec (if ei > 0 then is' else 0:is')+                            in char8 d >>+                                (unless (List.null ds') $ char8 '.' >> string8 ds')++ ------------------------------------------------------------------------------+-- Conversion of 'Float's and 'Double's to ASCII in decimal using Grisu3+------------------------------------------------------------------------++#define GRISU3_SINGLE_BUF_LEN 10+#define GRISU3_DOUBLE_BUF_LEN 18++foreign import ccall unsafe "static grisu3" c_grisu3+    :: Double+    -> MBA# Word8   -- ^ char*+    -> MBA# Int     -- ^ Int+    -> MBA# Int     -- ^ Int+    -> IO Int++-- | Decimal encoding of a 'Double'.+grisu3 :: Double -> Maybe ([Int], Int)+{-# INLINE grisu3 #-}+grisu3 d = unsafePerformIO $+    withMutableByteArrayUnsafe GRISU3_DOUBLE_BUF_LEN $ \ pBuf -> do+        (len, (e, success)) <- withPrimUnsafe' $ \ pLen ->+            withPrimUnsafe' $ \ pE ->+                c_grisu3 (realToFrac d) pBuf pLen pE+        if success == 0 -- grisu3 fail+        then return Nothing+        else do+            buf <- forM [0..len-1] $ \ i -> do+                w8 <- readByteArray (MutableByteArray pBuf) i :: IO Word8+                return (fromIntegral w8)+            let !e' = e + len+            return $ Just (buf, e')++foreign import ccall unsafe "static grisu3_sp" c_grisu3_sp+    :: Float+    -> MBA# Word8   -- ^ char*+    -> MBA# Int     -- ^ Int+    -> MBA# Int     -- ^ Int+    -> IO Int++-- | Decimal encoding of a 'Float'.+grisu3_sp :: Float -> Maybe ([Int], Int)+{-# INLINE grisu3_sp #-}+grisu3_sp d = unsafePerformIO $+    withMutableByteArrayUnsafe GRISU3_SINGLE_BUF_LEN $ \ pBuf -> do+        (len, (e, success)) <- withPrimUnsafe' $ \ pLen ->+            withPrimUnsafe' $ \ pE ->+                c_grisu3_sp (realToFrac d) pBuf pLen pE+        if success == 0 -- grisu3 fail+        then return Nothing+        else do+            buf <- forM [0..len-1] $ \ i -> do+                w8 <- readByteArray (MutableByteArray pBuf) i :: IO Word8+                return (fromIntegral w8)+            let !e' = e + len+            return $ Just (buf, e')++--------------------------------------------------------------------------------++-- | A @Builder@ which renders a scientific number to full+-- precision, using standard decimal notation for arguments whose+-- absolute value lies between @0.1@ and @9,999,999@, and scientific+-- notation otherwise.+scientific :: Sci.Scientific -> Builder ()+{-# INLINE scientific #-}+scientific = scientificWith Generic Nothing++-- | Like 'scientific' but provides rendering options.+scientificWith :: FFormat+               -> Maybe Int  -- ^ Number of decimal places to render.+               -> Sci.Scientific+               -> Builder ()+{-# INLINE scientificWith #-}+scientificWith fmt decs scntfc+   | scntfc < 0 = char8 '-' <> doFmt fmt decs (Sci.toDecimalDigits (-scntfc))+   | otherwise  =              doFmt fmt decs (Sci.toDecimalDigits   scntfc)
+ Std/Data/Builder/Numeric/DigitTable.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE NoCPP     #-}++{-|+Module      : Std.Data.Builder.Numeric.DigitTable+Description : Numeric to ASCII digits table.+Copyright   : (c) Dong Han, 2017-2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++-}+module Std.Data.Builder.Numeric.DigitTable where++import           Data.Primitive.Addr++decDigitTable :: Addr+decDigitTable = Addr "0001020304050607080910111213141516171819\+                     \2021222324252627282930313233343536373839\+                     \4041424344454647484950515253545556575859\+                     \6061626364656667686970717273747576777879\+                     \8081828384858687888990919293949596979899"#++hexDigitTable :: Addr+hexDigitTable = Addr "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\+                     \202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\+                     \404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f\+                     \606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f\+                     \808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f\+                     \a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf\+                     \c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf\+                     \e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"#++hexDigitTableUpper :: Addr+hexDigitTableUpper = Addr "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\+                          \202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\+                          \404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\+                          \606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\+                          \808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\+                          \A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\+                          \C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\+                          \E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"#
+ Std/Data/CBytes.hs view
@@ -0,0 +1,374 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE UnliftedFFITypes #-}+{-# LANGUAGE BangPatterns #-}+{-|+Module      : Std.Data.CBytes+Description : Null-ternimated byte string.+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provide 'CBytes' with some useful instances \/ functions, A 'CBytes' is a+wrapper for immutable null-terminated string.+The main design target of this type is to ease the bridging of C FFI APIs, since most+of the unix APIs use null-terminated string. On windows you're encouraged to use a+compatibility layer like 'WideCharToMultiByte/MultiByteToWideChar' and keep the same+interface, e.g. libuv do this when deal with file paths.++We neither guarantee to store length info, nor support O(1) slice for 'CBytes':+This will defeat the purpose of null-terminated string which is to save memory,+We do save the length if it's created on GHC heap though. If you need advance editing,+convert a 'CBytes' to 'V.Bytes' with 'toBytes' and use vector combinators.+Use 'fromBytes' to convert it back.++It can be used with @OverloadedString@, literal encoding is UTF-8 with some modifications:+@\NUL@ char is encoded to 'C0 80', and '\xD800' ~ '\xDFFF' is encoded as a three bytes+normal utf-8 codepoint. This is also how ghc compile string literal into binaries,+thus we can use rewrite-rules to construct 'CBytes' value in O(1) without wasting runtime heap.++Note most of the unix API is not unicode awared though, you may find a `scandir` call+return a filename which is not proper encoded in any unicode encoding at all.+But still, UTF-8 is recommanded to be used everywhere, and we use UTF-8 assumption in+various places, such as displaying 'CBytes' and literals encoding above.++-}++module Std.Data.CBytes+  ( CBytes+  , create+  , pack+  , unpack+  , null , length+  , empty, append, concat+  , toBytes, fromBytes, fromText+  , fromCStringMaybe, fromCString, fromCStringN+  , withCBytes+  ) where++import           Control.Monad+import           Control.Monad.Primitive+import           Control.Monad.ST+import           Data.Bits+import           Data.Foldable           (foldlM)+import           Data.Hashable           (Hashable(..),+                                            hashByteArrayWithSalt, hashPtrWithSalt)+import qualified Data.List               as List+import           Data.Monoid             (Monoid (..))+import           Data.Semigroup          (Semigroup (..))+import           Data.String             (IsString (..))+import           Data.Primitive.PrimArray+import           Data.Word+import           Foreign.C+import           Foreign.Storable        (peekElemOff)+import           GHC.CString+import           GHC.Ptr+import           Prelude                 hiding (all, any, appendFile, break,+                                          concat, concatMap, drop, dropWhile,+                                          elem, filter, foldl, foldl1, foldr,+                                          foldr1, getContents, getLine, head,+                                          init, interact, last, length, lines,+                                          map, maximum, minimum, notElem, null,+                                          putStr, putStrLn, readFile, replicate,+                                          reverse, scanl, scanl1, scanr, scanr1,+                                          span, splitAt, tail, take, takeWhile,+                                          unlines, unzip, writeFile, zip,+                                          zipWith)+import           Std.Data.Array+import qualified Std.Data.Text           as T+import           Std.Data.Text.UTF8Codec (encodeCharModifiedUTF8)+import qualified Std.Data.Vector.Base    as V+import           Std.IO.Exception+import           System.IO.Unsafe        (unsafeDupablePerformIO)++-- | A efficient wrapper for immutable null-terminated string which can be+-- automatically freed by ghc garbage collector.+--+data CBytes+    = CBytesOnHeap  {-# UNPACK #-} !(PrimArray Word8)   -- ^ On heap pinned 'PrimArray'+                                                        -- there's an invariance that this array's+                                                        -- length is always shrinked to contain content+                                                        -- and \NUL terminator+    | CBytesLiteral {-# UNPACK #-} !CString             -- ^ String literals with static address++-- | Create a 'CBytes' with IO action.+--+-- User only have to do content initialization and return the content length,+-- 'create' takes the responsibility to add the '\NUL' ternimator.+create :: HasCallStack+       => Int  -- ^ capacity n, including the '\NUL' terminator+       -> (CString -> IO Int)  -- ^ initialization function,+                               -- write the pointer, return the length (<= n-1)+       -> IO CBytes+{-# INLINE create #-}+create n fill = do+    mba <- newPinnedPrimArray n :: IO (MutablePrimArray RealWorld Word8)+    l <- withMutablePrimArrayContents mba (fill . castPtr)+    writePrimArray mba l 0 -- the '\NUL' ternimator+    shrinkMutablePrimArray mba (l+1)+    CBytesOnHeap <$> unsafeFreezePrimArray mba++instance Show CBytes where+    show = unpack++instance Read CBytes where+    readsPrec p s = [(pack x, r) | (x, r) <- readsPrec p s]++instance Eq CBytes where+    cbyteA == cbyteB = unsafeDupablePerformIO $+        withCBytes cbyteA $ \ pA ->+        withCBytes cbyteB $ \ pB ->+            if pA == pB+            then return True+            else do+                r <- c_strcmp pA pB+                return (r == 0)++instance Ord CBytes where+    cbyteA `compare` cbyteB = unsafeDupablePerformIO $+        withCBytes cbyteA $ \ pA ->+        withCBytes cbyteB $ \ pB ->+            if pA == pB+            then return EQ+            else do+                r <- c_strcmp pA pB+                return (r `compare` 0)++instance Semigroup CBytes where+    (<>) = append++instance Monoid CBytes where+    {-# INLINE mempty #-}+    mempty  = empty+    {-# INLINE mappend #-}+    mappend = append+    {-# INLINE mconcat #-}+    mconcat = concat++instance Hashable CBytes where+    hashWithSalt salt (CBytesOnHeap pa@(PrimArray ba#)) = unsafeDupablePerformIO $ do+        V.c_fnv_hash_ba ba# 0 (sizeofPrimArray pa - 1) salt+    hashWithSalt salt (CBytesLiteral p@(Ptr addr#)) = unsafeDupablePerformIO $ do+        len <- c_strlen p+        V.c_fnv_hash_addr addr# (fromIntegral len) salt++append :: CBytes -> CBytes -> CBytes+{-# INLINABLE append #-}+append strA strB+    | lenA == 0 = strB+    | lenB == 0 = strA+    | otherwise = unsafeDupablePerformIO $ do+        mpa <- newPinnedPrimArray (lenA+lenB+1)+        withCBytes strA $ \ pa ->+            withCBytes strB $ \ pb -> do+                copyPtrToMutablePrimArray mpa 0    (castPtr pa) lenA+                copyPtrToMutablePrimArray mpa lenA (castPtr pb) lenB+                writePrimArray mpa (lenA + lenB) 0     -- the \NUL terminator+                pa <- unsafeFreezePrimArray mpa+                return (CBytesOnHeap pa)+  where+    lenA = length strA+    lenB = length strB++empty :: CBytes+{-# NOINLINE empty #-}+empty = CBytesLiteral (Ptr "\0"#)++concat :: [CBytes] -> CBytes+{-# INLINABLE concat #-}+concat bs = case pre 0 0 bs of+    (0, _) -> empty+    (1, _) -> let Just b = List.find (not . null) bs in b -- there must be a not empty CBytes+    (_, l) -> runST $ do+        buf <- newPinnedPrimArray (l+1)+        copy bs 0 buf+        writePrimArray buf l 0 -- the \NUL terminator+        CBytesOnHeap <$> unsafeFreezePrimArray buf+  where+    -- pre scan to decide if we really need to copy and calculate total length+    -- we don't accumulate another result list, since it's rare to got empty+    pre :: Int -> Int -> [CBytes] -> (Int, Int)+    pre !nacc !lacc [] = (nacc, lacc)+    pre !nacc !lacc (b:bs)+        | length b <= 0 = pre nacc lacc bs+        | otherwise     = pre (nacc+1) (length b + lacc) bs++    copy :: [CBytes] -> Int -> MutablePrimArray s Word8 -> ST s ()+    copy [] !_ !_       = return ()+    copy (b:bs) !i !mba = do+        let l = length b+        when (l /= 0) (case b of+            CBytesOnHeap ba ->+                copyPrimArray mba i ba 0 l+            CBytesLiteral p ->+                copyPtrToMutablePrimArray mba i (castPtr p) l)+        copy bs (i+l) mba++instance IsString CBytes where+    {-# INLINE fromString #-}+    fromString = pack++{-# RULES+    "CBytes pack/unpackCString#" forall addr# .+        pack (unpackCString# addr#) = CBytesLiteral (Ptr addr#)+ #-}+{-# RULES+    "CBytes pack/unpackCStringUtf8#" forall addr# .+        pack (unpackCStringUtf8# addr#) = CBytesLiteral (Ptr addr#)+ #-}++-- | Pack a 'String' into null-terminated 'CBytes'.+--+-- '\NUL' is encoded as two bytes @C0 80@ , '\xD800' ~ '\xDFFF' is encoded as a three bytes normal UTF-8 codepoint.+pack :: String -> CBytes+{-# INLINE CONLIKE [1] pack #-}+pack s = runST $ do+    mba <- newPinnedPrimArray V.defaultInitSize+    (SP2 i mba') <- foldlM go (SP2 0 mba) s+    writePrimArray mba' i 0     -- the \NUL terminator+    shrinkMutablePrimArray mba' (i+1)+    ba <- unsafeFreezePrimArray mba'+    return (CBytesOnHeap ba)+  where+    -- It's critical that this function get specialized and unboxed+    -- Keep an eye on its core!+    go :: SP2 s -> Char -> ST s (SP2 s)+    go (SP2 i mba) !c     = do+        siz <- getSizeofMutablePrimArray mba+        if i < siz - 4  -- we need at least 5 bytes for safety due to extra '\0' byte+        then do+            i' <- encodeCharModifiedUTF8 mba i c+            return (SP2 i' mba)+        else do+            let !siz' = siz `shiftL` 1+            !mba' <- resizeMutablePrimArray mba siz'+            i' <- encodeCharModifiedUTF8 mba' i c+            return (SP2 i' mba')+++data SP2 s = SP2 {-# UNPACK #-}!Int {-# UNPACK #-}!(MutablePrimArray s Word8)++unpack :: CBytes -> String+{-# INLINABLE unpack #-}+-- TODO: rewrite with our own decoder+unpack cbytes = unsafeDupablePerformIO . withCBytes cbytes $ \ (Ptr addr#) ->+    return (unpackCStringUtf8# addr#)++--------------------------------------------------------------------------------++null :: CBytes -> Bool+{-# INLINE null #-}+null (CBytesOnHeap pa) = indexPrimArray pa 0 == 0+null (CBytesLiteral p) = unsafeDupablePerformIO (peekElemOff p 0) == 0++length :: CBytes -> Int+{-# INLINE length #-}+length (CBytesOnHeap pa) = sizeofPrimArray pa - 1+length (CBytesLiteral p) = fromIntegral $ unsafeDupablePerformIO (c_strlen p)++-- | /O(1)/, (/O(n)/ in case of literal), convert to 'V.Bytes', which can be+-- processed by vector combinators.+--+-- NOTE: the '\NUL' ternimator is not included.+toBytes :: CBytes -> V.Bytes+{-# INLINABLE toBytes #-}+toBytes cbytes@(CBytesOnHeap pa) = V.PrimVector pa 0 l+  where l = length cbytes+toBytes cbytes@(CBytesLiteral p) = V.create (l+1) (\ mpa -> do+    copyPtrToMutablePrimArray mpa 0 (castPtr p) l+    writePrimArray mpa l 0)    -- the \NUL terminator+  where l = length cbytes++-- | /O(n)/, convert from 'V.Bytes', allocate pinned memory and+-- add the '\NUL' ternimator+fromBytes :: V.Bytes -> CBytes+{-# INLINABLE fromBytes #-}+fromBytes (V.Vec arr s l) =  runST (do+        mpa <- newPinnedPrimArray (l+1)+        copyPrimArray mpa 0 arr s l+        writePrimArray mpa l 0     -- the \NUL terminator+        pa <- unsafeFreezePrimArray mpa+        return (CBytesOnHeap pa))++-- | /O(n)/, convert from 'T.Text', allocate pinned memory and+-- add the '\NUL' ternimator+fromText :: T.Text -> CBytes+{-# INLINABLE fromText #-}+fromText = fromBytes . T.getUTF8Bytes++--------------------------------------------------------------------------------++-- | Copy a 'CString' type into a 'CBytes', return Nothing if the pointer is NULL.+--+--  After copying you're free to free the 'CString' 's memory.+--+fromCStringMaybe :: HasCallStack => CString -> IO (Maybe CBytes)+{-# INLINABLE fromCStringMaybe #-}+fromCStringMaybe cstring =+    if cstring == nullPtr+    then return Nothing+    else do+        len <- fromIntegral <$> c_strlen cstring+        mpa <- newPinnedPrimArray (len+1)+        copyPtrToMutablePrimArray mpa 0 (castPtr cstring) len+        writePrimArray mpa len 0     -- the \NUL terminator+        pa <- unsafeFreezePrimArray mpa+        return (Just (CBytesOnHeap pa))+++-- | Same with 'fromCStringMaybe', but throw 'InvalidArgument' when meet a null pointer.+--+fromCString :: HasCallStack+            => CString+            -> IO CBytes+{-# INLINABLE fromCString #-}+fromCString cstring =+    if cstring == nullPtr+    then throwIO (InvalidArgument+        (IOEInfo "" "unexpected null pointer" callStack))+    else do+        len <- fromIntegral <$> c_strlen cstring+        mpa <- newPinnedPrimArray (len+1)+        copyPtrToMutablePrimArray mpa 0 (castPtr cstring) len+        writePrimArray mpa len 0     -- the \NUL terminator+        pa <- unsafeFreezePrimArray mpa+        return (CBytesOnHeap pa)++-- | Same with 'fromCString', but only take N bytes (and append a null byte as terminator).+--+fromCStringN :: HasCallStack+            => CString+            -> Int+            -> IO CBytes+{-# INLINABLE fromCStringN #-}+fromCStringN cstring len =+    if cstring == nullPtr+    then throwIO (InvalidArgument+        (IOEInfo "" "unexpected null pointer" callStack))+    else do+        mpa <- newPinnedPrimArray (len+1)+        copyPtrToMutablePrimArray mpa 0 (castPtr cstring) len+        writePrimArray mpa len 0     -- the \NUL terminator+        pa <- unsafeFreezePrimArray mpa+        return (CBytesOnHeap pa)++-- | Pass 'CBytes' to foreign function as a @const char*@.+--+-- Don't pass a forever loop to this function, see <https://ghc.haskell.org/trac/ghc/ticket/14346 #14346>.+withCBytes :: CBytes -> (CString -> IO a) -> IO a+{-# INLINABLE withCBytes #-}+withCBytes (CBytesOnHeap pa) f = withPrimArrayContents pa (f . castPtr)+withCBytes (CBytesLiteral ptr) f = f ptr++--------------------------------------------------------------------------------++c_strcmp :: CString -> CString -> IO CInt+{-# INLINE c_strcmp #-}+c_strcmp (Ptr a#) (Ptr b#) = V.c_strcmp a# b#++c_strlen :: CString -> IO CSize+{-# INLINE c_strlen #-}+c_strlen (Ptr a#) = V.c_strlen a#
+ Std/Data/Parser.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Std.Data.Parser+Description : Efficient deserialization/parse.+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provide a simple resumable 'Parser', which is suitable for binary protocol and simple textual protocol parsing.++You can use 'Alternative' instance to do backtracking, each branch will either succeed and may consume some input, or fail without consume anything. It's recommend to use 'peek' to avoid backtracking if possible to get high performance.++-}+module Std.Data.Parser+  ( -- * Parser types+    Result+  , Parser+    -- * Running a parser+  , parse, parse', parseChunk, parseChunks, finishParsing+  , runAndKeepTrack+    -- * Basic parsers+  , ensureN, endOfInput+    -- * Primitive decoders+  , decodePrim, decodePrimLE, decodePrimBE+    -- * More parsers+  , scan, scanChunks, peekMaybe, peek, satisfy, satisfyWith+  , word8, anyWord8, endOfLine, skip, skipWhile, skipSpaces+  , take, takeTill, takeWhile, takeWhile1, bytes, bytesCI+  , text+    -- * Numeric parsers+    -- ** Decimal+  , uint, int+    -- ** Hex+  , hex+    -- ** Fractional+  , rational+  , float, double+  , scientific+  , scientifically+  ) where++import           Std.Data.Parser.Base+import           Std.Data.Parser.Numeric+import           Prelude hiding (take, takeWhile)
+ Std/Data/Parser/Base.hs view
@@ -0,0 +1,596 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Std.Data.Parser.Base+Description : Efficient deserialization/parse.+Copyright   : (c) Dong Han, 2017-2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provide a simple resumable 'Parser', which is suitable for binary protocol and simple textual protocol parsing.++You can use 'Alternative' instance to do backtracking, each branch will either succeed and may consume some input, or fail without consume anything. It's recommend to use 'peek' to avoid backtracking if possible to get high performance.++-}++module Std.Data.Parser.Base+  ( -- * Parser types+    Result(..)+  , ParseStep+  , Parser(..)+    -- * Running a parser+  , parse, parse', parseChunk, parseChunks, finishParsing+  , runAndKeepTrack+    -- * Basic parsers+  , ensureN, endOfInput+    -- * Primitive decoders+  , decodePrim, decodePrimLE, decodePrimBE+    -- * More parsers+  , scan, scanChunks, peekMaybe, peek, satisfy, satisfyWith+  , word8, char8, anyWord8, endOfLine, skip, skipWhile, skipSpaces+  , take, takeTill, takeWhile, takeWhile1, bytes, bytesCI+  , text+  ) where++import           Control.Applicative+import           Control.Monad+import qualified Control.Monad.Fail                 as Fail+import qualified Data.CaseInsensitive               as CI+import qualified Data.Primitive.PrimArray           as A+import           Data.Int+import           Data.Word+import           Data.Word8                         (isSpace)+import           GHC.Types+import           Prelude                            hiding (take, takeWhile)+import           Std.Data.PrimArray.UnalignedAccess+import qualified Std.Data.Text.Base                 as T+import qualified Std.Data.Vector.Base               as V+import qualified Std.Data.Vector.Extra              as V++-- | Simple parsing result, that represent respectively:+--+-- * success: the remaining unparsed data and the parsed value+--+-- * failure: the remaining unparsed data and the error message+--+-- * partial: that need for more input data, supply empty bytes to indicate 'endOfInput'+--+data Result a+    = Success !V.Bytes a+    | Failure !V.Bytes String+    | Partial (V.Bytes -> Result a)++instance Functor Result where+    fmap f (Success s a)   = Success s (f a)+    fmap _ (Failure s msg) = Failure s msg+    fmap f (Partial k)     = Partial (fmap f . k)++instance Show a => Show (Result a) where+    show (Success _ a)    = "Success " ++ show a+    show (Partial _)      = "Partial _"+    show (Failure _ errs) = "Failure: " ++ show errs++type ParseStep r = V.Bytes -> Result r++-- | Simple CPSed parser+--+newtype Parser a = Parser { runParser :: forall r .  (a -> ParseStep r) -> ParseStep r }++instance Functor Parser where+    fmap f (Parser pa) = Parser (\ k -> pa (\ a -> k (f a)))+    {-# INLINE fmap #-}+    a <$ Parser pb = Parser (\ k -> pb (\ _ -> k a))+    {-# INLINE (<$) #-}++instance Applicative Parser where+    pure x = Parser (\ k -> k x)+    {-# INLINE pure #-}+    Parser pf <*> Parser pa = Parser (\ k -> pf (\ f  -> pa (k . f)))+    {-# INLINE (<*>) #-}++instance Monad Parser where+    return = pure+    {-# INLINE return #-}+    Parser pa >>= f = Parser (\ k -> pa (\ a -> runParser (f a) k))+    {-# INLINE (>>=) #-}+    fail str = Parser (\ _ input -> Failure input str)+    {-# INLINE fail #-}++instance Fail.MonadFail Parser where+    fail str = Parser (\ _ input -> Failure input str)+    {-# INLINE fail #-}++instance MonadPlus Parser where+    mzero = empty+    {-# INLINE mzero #-}+    mplus = (<|>)+    {-# INLINE mplus #-}++instance Alternative Parser where+    empty = Parser (\ _ input -> Failure input "Std.Data.Parser.Base(Alternative).empty")+    {-# INLINE empty #-}+    f <|> g = do+        (r, bs) <- runAndKeepTrack f+        case r of+            Success input x -> Parser (\ k _ -> k x input)+            Failure _ _     -> pushBack bs >> g+            _               -> error "Std.Data.Parser.Base: impossible"+    {-# INLINE (<|>) #-}+++-- | Parse the complete input, without resupplying+parse :: Parser a -> V.Bytes -> Either String a+{-# INLINE parse #-}+parse (Parser p) input = snd $ finishParsing (p (flip Success) input)++-- | Parse the complete input, without resupplying, return the rest bytes+parse' :: Parser a -> V.Bytes -> (V.Bytes, Either String a)+{-# INLINE parse' #-}+parse' (Parser p) input = finishParsing (p (flip Success) input)++-- | Parse an input chunk+parseChunk :: Parser a -> V.Bytes -> Result a+{-# INLINE parseChunk #-}+parseChunk (Parser p) = p (flip Success)++-- | Finish parsing and fetch result, feed empty bytes if it's 'Partial' result.+finishParsing :: Result a -> (V.Bytes, Either String a)+{-# INLINABLE finishParsing #-}+finishParsing r = case r of+    Success rest a    -> (rest, Right a)+    Failure rest errs -> (rest, Left errs)+    Partial f         -> finishParsing (f V.empty)++-- | Run a parser with an initial input string, and a monadic action+-- that can supply more input if needed.+--+-- Note, once the monadic action return empty bytes, parsers will stop drawing+-- more bytes (take it as 'endOfInput').+parseChunks :: Monad m => m V.Bytes -> Parser a -> V.Bytes -> m (V.Bytes, Either String a)+{-# INLINABLE parseChunks #-}+parseChunks m (Parser p) input = go m (p (flip Success) input)+  where+    go m r = case r of+        Partial f -> do+            inp <- m+            if V.null inp+            then go (return V.empty) (f V.empty)+            else go m (f inp)+        Success rest a    -> return (rest, Right a)+        Failure rest errs -> return (rest, Left errs)++-- | Run a parser and keep track of all the input it consumes.+-- Once it's finished, return the final result (always 'Success' or 'Failure') and+-- all consumed chunks.+--+runAndKeepTrack :: Parser a -> Parser (Result a, [V.Bytes])+{-# INLINE runAndKeepTrack #-}+runAndKeepTrack (Parser pa) = Parser $ \ k0 input ->+    let r0 = pa (\ a input' -> Success input' a) input in go [] r0 k0+  where+    go !acc r k0 = case r of+        Partial k        -> Partial (\ input -> go (input:acc) (k input) k0)+        Success input' _ -> k0 (r, reverse acc) input'+        Failure input' _ -> k0 (r, reverse acc) input'++pushBack :: [V.Bytes] -> Parser ()+{-# INLINE pushBack #-}+pushBack [] = return ()+pushBack bs = Parser (\ k input -> k () (V.concat (input : bs)))++-- | Ensure that there are at least @n@ bytes available. If not, the+-- computation will escape with 'Partial'.+ensureN :: Int -> Parser ()+{-# INLINE ensureN #-}+ensureN n0 = Parser $ \ ks input -> do+    let l = V.length input+    if l >= n0+    then ks () input+    else Partial (go n0 ks [input] l)+  where+    go n0 ks acc l = \ !input' -> do+        let l' = V.length input'+        if l' == 0+        then Failure+            (V.concat (reverse (input':acc)))+            "Std.Data.Parser.Base.ensureN: Not enough bytes"+        else do+            let l'' = l + l'+            if l'' < n0+            then Partial (go n0 ks (input':acc) l'')+            else do+                let input'' = V.concat (reverse (input':acc))+                ks () input''++-- | Test whether all input has been consumed, i.e. there are no remaining+-- undecoded bytes.+endOfInput :: Parser Bool+{-# INLINE endOfInput #-}+endOfInput = Parser $ \ k inp ->+    if V.null inp+    then Partial (\ inp' -> k (V.null inp') inp')+    else k False inp++decodePrim :: forall a. UnalignedAccess a => Parser a+{-# INLINE decodePrim #-}+{-# SPECIALIZE INLINE decodePrim :: Parser Word   #-}+{-# SPECIALIZE INLINE decodePrim :: Parser Word64 #-}+{-# SPECIALIZE INLINE decodePrim :: Parser Word32 #-}+{-# SPECIALIZE INLINE decodePrim :: Parser Word16 #-}+{-# SPECIALIZE INLINE decodePrim :: Parser Word8  #-}+{-# SPECIALIZE INLINE decodePrim :: Parser Int   #-}+{-# SPECIALIZE INLINE decodePrim :: Parser Int64 #-}+{-# SPECIALIZE INLINE decodePrim :: Parser Int32 #-}+{-# SPECIALIZE INLINE decodePrim :: Parser Int16 #-}+{-# SPECIALIZE INLINE decodePrim :: Parser Int8  #-}+decodePrim = do+    ensureN n+    Parser (\ k (V.PrimVector (A.PrimArray ba#) i@(I# i#) len) ->+        let !r = indexWord8ArrayAs ba# i#+        in k r (V.PrimVector (A.PrimArray ba#) (i+n) (len-n)))+  where+    n = (getUnalignedSize (unalignedSize :: UnalignedSize a))++decodePrimLE :: forall a. UnalignedAccess (LE a) => Parser a+{-# INLINE decodePrimLE #-}+{-# SPECIALIZE INLINE decodePrimLE :: Parser Word   #-}+{-# SPECIALIZE INLINE decodePrimLE :: Parser Word64 #-}+{-# SPECIALIZE INLINE decodePrimLE :: Parser Word32 #-}+{-# SPECIALIZE INLINE decodePrimLE :: Parser Word16 #-}+{-# SPECIALIZE INLINE decodePrimLE :: Parser Int   #-}+{-# SPECIALIZE INLINE decodePrimLE :: Parser Int64 #-}+{-# SPECIALIZE INLINE decodePrimLE :: Parser Int32 #-}+{-# SPECIALIZE INLINE decodePrimLE :: Parser Int16 #-}+decodePrimLE = getLE <$> decodePrim++decodePrimBE :: forall a. UnalignedAccess (BE a) => Parser a+{-# INLINE decodePrimBE #-}+{-# SPECIALIZE INLINE decodePrimBE :: Parser Word   #-}+{-# SPECIALIZE INLINE decodePrimBE :: Parser Word64 #-}+{-# SPECIALIZE INLINE decodePrimBE :: Parser Word32 #-}+{-# SPECIALIZE INLINE decodePrimBE :: Parser Word16 #-}+{-# SPECIALIZE INLINE decodePrimBE :: Parser Int   #-}+{-# SPECIALIZE INLINE decodePrimBE :: Parser Int64 #-}+{-# SPECIALIZE INLINE decodePrimBE :: Parser Int32 #-}+{-# SPECIALIZE INLINE decodePrimBE :: Parser Int16 #-}+decodePrimBE = getBE <$> decodePrim++-- | A stateful scanner.  The predicate consumes and transforms a+-- state argument, and each transformed state is passed to successive+-- invocations of the predicate on each byte of the input until one+-- returns 'Nothing' or the input ends.+--+-- This parser does not fail.  It will return an empty string if the+-- predicate returns 'Nothing' on the first byte of input.+--+scan :: s -> (s -> Word8 -> Maybe s) -> Parser V.Bytes+{-# INLINE scan #-}+scan s0 f = scanChunks s0 f'+  where+    f' st (V.Vec arr s l) = go f st arr s s (s+l)+    go f !st arr off !i !end+        | i < end = do+            let !w = A.indexPrimArray arr i+            case f st w of+                Just st' -> go f st' arr off (i+1) end+                _        ->+                    let !len1 = i - off+                        !len2 = end - off+                    in Right (V.Vec arr off len1, V.Vec arr i len2)+        | otherwise = Left st++-- | Similar to 'scan', but working on 'V.Bytes' chunks, The predicate+-- consumes a 'V.Bytes' chunk and transforms a state argument,+-- and each transformed state is passed to successive invocations of+-- the predicate on each chunk of the input until one chunk got splited to+-- @Right (V.Bytes, V.Bytes)@ or the input ends.+--+scanChunks :: s -> (s -> V.Bytes -> Either s (V.Bytes, V.Bytes)) -> Parser V.Bytes+{-# INLINE scanChunks #-}+scanChunks s0 consume = Parser (go s0 [])+  where+    go s acc k inp =+        case consume s inp of+            Left s' -> do+                let acc' = inp : acc+                Partial (go' s' acc' k)+            Right (want,rest) ->+                k (V.concat (reverse (want:acc))) rest+    go' s acc k inp+        | V.null inp = k (V.concat (reverse acc)) inp+        | otherwise =+            case consume s inp of+                Left s' -> do+                    let acc' = inp : acc+                    Partial (go' s' acc' k)+                Right (want,rest) ->+                    k (V.concat (reverse (want:acc))) rest+++--------------------------------------------------------------------------------++-- | Match any byte, to perform lookahead. Returns 'Nothing' if end of+-- input has been reached. Does not consume any input.+--+peekMaybe :: Parser (Maybe Word8)+{-# INLINE peekMaybe #-}+peekMaybe = do+    e <- endOfInput+    if e then return Nothing+         else Just <$> peek++-- | Match any byte, to perform lookahead.  Does not consume any+-- input, but will fail if end of input has been reached.+--+peek :: Parser Word8+{-# INLINE peek #-}+peek = do+    ensureN 1+    Parser (\ k inp -> k (V.unsafeHead inp) inp)++-- | The parser @satisfy p@ succeeds for any byte for which the+-- predicate @p@ returns 'True'. Returns the byte that is actually+-- parsed.+--+-- >digit = satisfy isDigit+-- >    where isDigit w = w >= 48 && w <= 57+--+satisfy :: (Word8 -> Bool) -> Parser Word8+{-# INLINE satisfy #-}+satisfy p = do+    ensureN 1+    Parser (\ k inp ->+        let w = V.unsafeHead inp+        in if p w+            then k w (V.unsafeTail inp)+            else Failure inp "Std.Data.Parser.Base.satisfy")++-- | The parser @satisfyWith f p@ transforms a byte, and succeeds if+-- the predicate @p@ returns 'True' on the transformed value. The+-- parser returns the transformed byte that was parsed.+--+satisfyWith :: (Word8 -> a) -> (a -> Bool) -> Parser a+{-# INLINE satisfyWith #-}+satisfyWith f p = do+    ensureN 1+    Parser (\ k inp ->+        let w = f (V.unsafeHead inp)+        in if p w+            then k w (V.unsafeTail inp)+            else Failure inp "Std.Data.Parser.Base.satisfyWith")++-- | Match a specific byte.+--+word8 :: Word8 -> Parser ()+{-# INLINE word8 #-}+word8 w' = do+    ensureN 1+    Parser (\ k inp ->+        let w = V.unsafeHead inp+        in if w == w'+            then k () (V.unsafeTail inp)+            else Failure inp "Std.Data.Parser.Base.word8")++-- | Match a specific 8bit char.+--+char8 :: Char -> Parser ()+{-# INLINE char8 #-}+char8 c = do+    let !w' = V.c2w c+    ensureN 1+    Parser (\ k inp ->+        let w = V.unsafeHead inp+        in if w == w'+            then k () (V.unsafeTail inp)+            else Failure inp "Std.Data.Parser.Base.char8")++-- | Match any byte.+--+anyWord8 :: Parser Word8+{-# INLINE anyWord8 #-}+anyWord8 = decodePrim++-- | Match either a single newline byte @\'\\n\'@, or a carriage+-- return followed by a newline byte @\"\\r\\n\"@.+endOfLine :: Parser ()+{-# INLINE endOfLine #-}+endOfLine = do+    w <- decodePrim :: Parser Word8+    case w of+        10 -> return ()+        13 -> word8 10+        _  -> fail "endOfLine"++--------------------------------------------------------------------------------++-- | 'skip' N bytes.+--+skip :: Int -> Parser ()+{-# INLINE skip #-}+skip n+    | n <= 0 = return ()        -- we use unsafe slice, guard negative n here+    | otherwise =+        Parser (\ k inp ->+            let l = V.length inp+            in if l >= n+                then k () (V.unsafeDrop n inp)+                else Partial (go k (n-l)))+  where+    go k !n inp =+        let l = V.length inp+        in if l >= n+            then k () (V.unsafeDrop n inp)+            else if l == 0+                then Failure inp "Std.Data.Parser.Base.skip"+                else Partial (go k (n-l))++-- | Skip past input for as long as the predicate returns 'True'.+--+skipWhile :: (Word8 -> Bool) -> Parser ()+{-# INLINE skipWhile #-}+skipWhile p =+    Parser (\ k inp ->+        let rest = V.dropWhile p inp+        in if V.null rest+            then Partial (go k p)+            else k () rest)+  where+    go k p inp =+        let rest = V.dropWhile p inp    -- If we ever enter 'Partial', empty input+        in k () rest                    -- means 'endOfInput'++-- | Skip over white space using 'isSpace'.+--+skipSpaces :: Parser ()+{-# INLINE skipSpaces #-}+skipSpaces = skipWhile isSpace++take :: Int -> Parser V.Bytes+{-# INLINE take #-}+take n+    | n <= 0 = return V.empty   -- we use unsafe slice, guard negative n here+    | otherwise =+        Parser (\ k inp ->+            let l = V.length inp+            in if l >= n+                then k (V.unsafeTake n inp) (V.unsafeDrop n inp)+                else Partial (go k (n-l) [inp]))+  where+    go k !n acc inp =+        let l = V.length inp+        in if l >= n+            then+                let !r = V.concat (reverse (V.unsafeTake n inp:acc))+                in k r (V.unsafeDrop n inp)+            else if l == 0+                then Failure inp "Std.Data.Parser.Base.take: Not enough bytes"+                else Partial (go k (n-l) (inp:acc))++-- | Consume input as long as the predicate returns 'False' or reach the end of input,+-- and return the consumed input.+--+takeTill :: (Word8 -> Bool) -> Parser V.Bytes+{-# INLINE takeTill #-}+takeTill p = Parser (\ k inp ->+    let (want, rest) = V.break p inp+    in if V.null rest+        then Partial (go k [want])+        else k want rest)+  where+    go k acc inp =+        if V.null inp+        then k (V.concat (reverse acc)) inp+        else+            let (want, rest) = V.break p inp+                acc' = want : acc+            in if V.null rest+                then Partial (go k acc')+                else k (V.concat (reverse acc')) rest++-- | Consume input as long as the predicate returns 'True' or reach the end of input,+-- and return the consumed input.+--+takeWhile :: (Word8 -> Bool) -> Parser V.Bytes+{-# INLINE takeWhile #-}+takeWhile p = Parser (\ k inp ->+    let (want, rest) = V.span p inp+    in if V.null rest+        then Partial (go k [want])+        else k want rest)+  where+    go k acc inp =+        if V.null inp+        then k (V.concat (reverse acc)) inp+        else+            let (want, rest) = V.span p inp+                acc' = want : acc+            in if V.null rest+                then Partial (go k acc')+                else k (V.concat (reverse acc')) rest++-- | Similar to 'takeWhile', but requires the predicate to succeed on at least one byte+-- of input: it will fail if the predicate never returns 'True' or reach the end of input+--+takeWhile1 :: (Word8 -> Bool) -> Parser V.Bytes+{-# INLINE takeWhile1 #-}+takeWhile1 p = do+    bs <- takeWhile p+    if V.null bs then fail "Std.Data.Parser.Base.takeWhile1" else return bs+++-- | @bytes s@ parses a sequence of bytes that identically match @s@.+--+bytes :: V.Bytes -> Parser ()+{-# INLINE bytes #-}+bytes bs = do+    let n = V.length bs+    Parser (\ k inp ->+        let l = V.length inp+        in if l >= n+            then+                if bs == (V.unsafeTake n inp)+                    then k () (V.unsafeDrop n inp)+                    else Failure inp "Std.Data.Parser.Base.bytes"+            else+                if inp == (V.unsafeTake l bs)+                    then Partial (go k (n-l) (V.unsafeDrop l bs))+                    else Failure inp "Std.Data.Parser.Base.bytes")+  where+    go k !n !bs inp =+        let l = V.length inp+        in if l >= n+            then+                if bs == (V.unsafeTake n inp)+                    then k () (V.unsafeDrop n inp)+                    else Failure inp "Std.Data.Parser.Base.bytes"+            else if l == 0+                then Failure inp "Std.Data.Parser.Base.bytes: Not enough bytes"+                else+                    if inp == (V.unsafeTake l bs)+                        then Partial (go k (n-l) (V.unsafeDrop l bs))+                        else Failure inp "Std.Data.Parser.Base.bytes"++-- | Same as 'bytes' but ignoring case.+bytesCI :: V.Bytes -> Parser ()+{-# INLINE bytesCI #-}+bytesCI bs = do+    let n = V.length bs'+    Parser (\ k inp ->+        let l = V.length inp+        in if l >= n+            then+                if bs' == CI.foldCase (V.unsafeTake n inp)+                    then k () (V.unsafeDrop n inp)+                    else Failure inp "Std.Data.Parser.Base.bytesCI"+            else+                if CI.foldCase inp == V.unsafeTake l bs'+                    then Partial (go k (n-l) (V.unsafeDrop l bs'))+                    else Failure inp "Std.Data.Parser.Base.bytesCI")+  where+    bs' = CI.foldCase bs+    go k !n !bs inp =+        let l = V.length inp+        in if l >= n+            then+                if bs == CI.foldCase (V.unsafeTake n inp)+                    then k () (V.unsafeDrop n inp)+                    else Failure inp "Std.Data.Parser.Base.bytesCI"+            else if l == 0+                then Failure inp "Std.Data.Parser.Base.bytesCI: Not enough bytes"+                else+                    if CI.foldCase inp == V.unsafeTake l bs+                        then Partial (go k (n-l) (V.unsafeDrop l bs))+                        else Failure inp "Std.Data.Parser.Base.bytesCI"++-- | @text s@ parses a sequence of UTF8 bytes that identically match @s@.+--+text :: T.Text -> Parser ()+{-# INLINE text #-}+text (T.Text bs) = bytes bs
+ Std/Data/Parser/Numeric.hs view
@@ -0,0 +1,221 @@+{-# LANGUAGE BangPatterns #-}++{-|+Module      : Std.Data.Parser.Numeric+Description : Textual numeric parsers.+Copyright   : (c) Dong Han, 2017-2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++Textual numeric parsers.++-}++module Std.Data.Parser.Numeric+  ( -- * decimal+    uint, int+    -- * hex+  , hex+    -- * fractional+  , rational+  , float, double+  , scientific+  , scientifically+  ) where++import           Control.Applicative+import           Control.Monad+import           Data.Bits+import           Data.Int+import qualified Data.Primitive.PrimArray as A+import qualified Data.Scientific          as Sci+import           Data.Word+import           Data.Word8               (isDigit, isHexDigit)+import           Foreign.Ptr              (IntPtr)+import           Std.Data.Parser.Base     (Parser)+import qualified Std.Data.Parser.Base     as P+import qualified Std.Data.Vector.Base     as V+import qualified Std.Data.Vector.Extra    as V++minus, plus, littleE, bigE, dot :: Word8+minus    = 45+plus     = 43+littleE = 101+bigE    = 69+dot      = 46++-- | Parse and decode an unsigned hex number.  The hex digits+-- @\'a\'@ through @\'f\'@ may be upper or lower case.+--+-- This parser does not accept a leading @\"0x\"@ string, and consider+-- sign bit part of the binary hex nibbles, i.e.+-- 'parse hex "0xFF" == Right (-1 :: Int8)'+--+hex :: (Integral a, Bits a) => Parser a+{-# INLINE hex #-}+{-# SPECIALIZE INLINE hex :: Parser Int    #-}+{-# SPECIALIZE INLINE hex :: Parser Int64  #-}+{-# SPECIALIZE INLINE hex :: Parser Int32  #-}+{-# SPECIALIZE INLINE hex :: Parser Int16  #-}+{-# SPECIALIZE INLINE hex :: Parser Int8   #-}+{-# SPECIALIZE INLINE hex :: Parser Word   #-}+{-# SPECIALIZE INLINE hex :: Parser Word64 #-}+{-# SPECIALIZE INLINE hex :: Parser Word32 #-}+{-# SPECIALIZE INLINE hex :: Parser Word16 #-}+{-# SPECIALIZE INLINE hex :: Parser Word8  #-}+{-# SPECIALIZE INLINE hex :: Parser IntPtr #-}+hex = do+    (V.Vec arr s l) <- P.takeWhile1 isHexDigit+    return $! hexLoop arr s (l-1) 0+  where+    hexLoop arr !i !j !acc+        | j == 0 = acc .|. w2iHex (A.indexPrimArray arr i)+        | otherwise =+            let acc' = acc .|. w2iHex (A.indexPrimArray arr i) `unsafeShiftL` (j*4)+            in hexLoop arr (i+1) (j-1) acc'++w2iHex :: (Integral a) => Word8 -> a+{-# INLINE w2iHex #-}+w2iHex w+    | w <= 57              = fromIntegral w - 48+    | 65 <= w && w <= 70   = fromIntegral w - 55+    | 97 <= w && w <= 102  = fromIntegral w - 87+++-- | Parse and decode an unsigned decimal number.+uint :: Integral a => Parser a+{-# INLINE uint #-}+{-# SPECIALIZE INLINE uint :: Parser Int    #-}+{-# SPECIALIZE INLINE uint :: Parser Int64  #-}+{-# SPECIALIZE INLINE uint :: Parser Int32  #-}+{-# SPECIALIZE INLINE uint :: Parser Int16  #-}+{-# SPECIALIZE INLINE uint :: Parser Int8   #-}+{-# SPECIALIZE INLINE uint :: Parser Word   #-}+{-# SPECIALIZE INLINE uint :: Parser Word64 #-}+{-# SPECIALIZE INLINE uint :: Parser Word32 #-}+{-# SPECIALIZE INLINE uint :: Parser Word16 #-}+{-# SPECIALIZE INLINE uint :: Parser Word8  #-}+uint = do+    (V.Vec arr s l) <- P.takeWhile1 isDigit+    return $! decLoop arr s (l-1) 0+  where+    decLoop arr !i !j !acc+        | j == 0 = acc*10 + w2iDec (A.indexPrimArray arr i)+        | otherwise =+            let acc' = acc*10 + w2iDec (A.indexPrimArray arr i)+            in decLoop arr (i+1) (j-1) acc'++w2iDec :: (Integral a) => Word8 -> a+{-# INLINE w2iDec #-}+w2iDec w = fromIntegral w - 48++-- | Parse a decimal number with an optional leading @\'+\'@ or @\'-\'@ sign+-- character.+int :: Integral a => Parser a+{-# INLINE int #-}+{-# SPECIALIZE INLINE int :: Parser Int    #-}+{-# SPECIALIZE INLINE int :: Parser Int64  #-}+{-# SPECIALIZE INLINE int :: Parser Int32  #-}+{-# SPECIALIZE INLINE int :: Parser Int16  #-}+{-# SPECIALIZE INLINE int :: Parser Int8   #-}+{-# SPECIALIZE INLINE int :: Parser Word   #-}+{-# SPECIALIZE INLINE int :: Parser Word64 #-}+{-# SPECIALIZE INLINE int :: Parser Word32 #-}+{-# SPECIALIZE INLINE int :: Parser Word16 #-}+{-# SPECIALIZE INLINE int :: Parser Word8  #-}+int = do+    w <- P.peek+    if w == minus+        then P.skip 1 >> negate <$> uint+        else if w == plus then P.skip 1 >> uint else uint++-- | Parse a rational number.+--+-- The syntax accepted by this parser is the same as for 'double'.+--+-- /Note/: this parser is not safe for use with inputs from untrusted+-- sources.  An input with a suitably large exponent such as+-- @"1e1000000000"@ will cause a huge 'Integer' to be allocated,+-- resulting in what is effectively a denial-of-service attack.+--+-- In most cases, it is better to use 'double' or 'scientific'+-- instead.+--+rational :: Fractional a => Parser a+{-# INLINE rational #-}+rational = scientifically realToFrac++-- | Parse a rational number and round to 'Double'.+--+-- This parser accepts an optional leading sign character, followed by+-- at least one decimal digit.  The syntax similar to that accepted by+-- the 'read' function, with the exception that a trailing @\'.\'@ or+-- @\'e\'@ /not/ followed by a number is not consumed.+--+-- Examples with behaviour identical to 'read':+--+-- >parseOnly double "3"     == Right ("",1,3.0)+-- >parseOnly double "3.1"   == Right ("",3,3.1)+-- >parseOnly double "3e4"   == Right ("",3,30000.0)+-- >parseOnly double "3.1e4" == Right ("",5,31000.0)+--+-- >parseOnly double ".3"    == Left (".3",0,"takeWhile1")+-- >parseOnly double "e3"    == Left ("e3",0,"takeWhile1")+--+-- Examples of differences from 'read':+--+-- >parseOnly double "3.foo" == Right (".foo",1,3.0)+-- >parseOnly double "3e"    == Right ("e",1,3.0)+--+-- This function does not accept string representations of \"NaN\" or+-- \"Infinity\".+--+double :: Parser Double+{-# INLINE double #-}+double = scientifically Sci.toRealFloat++-- | Parse a rational number and round to 'Float'.+--+-- Single precision version of 'double'.+float :: Parser Float+{-# INLINE float #-}+float = scientifically Sci.toRealFloat++-- | Parse a scientific number.+--+-- The syntax accepted by this parser is the same as for 'double'.+--+scientific :: Parser Sci.Scientific+{-# INLINE scientific #-}+scientific = scientifically id++-- | Parse a scientific number and convert to result using a user supply function.+--+-- The syntax accepted by this parser is the same as for 'double'.+--+scientifically :: (Sci.Scientific -> a) -> Parser a+{-# INLINE scientifically #-}+scientifically h = do+    sign <- P.peek+    when (sign == plus || sign == minus) (P.skip 1)+    intPart <- uint+    sci <- (do (V.Vec arr s l) <- P.word8 dot >> P.takeWhile1 isDigit+               let intPart' = intPart * (10 ^ l)+                   fracPart = decLoop arr s (l-1) 0+               parseE (intPart' + fracPart) l+           ) <|> (parseE intPart 0)++    if sign /= minus then return $! h sci else return $! h (negate sci)+  where+    {-# INLINE parseE #-}+    parseE c e =+        (do _ <- P.satisfy (\w -> w ==  littleE || w == bigE)+            (Sci.scientific c . (subtract e) <$> int)) <|> return (Sci.scientific c (negate e))++    decLoop arr !i !j !acc+        | j == 0 = acc*10 + w2iDec (A.indexPrimArray arr i)+        | otherwise =+            let acc' = acc*10 + w2iDec (A.indexPrimArray arr i)+            in decLoop arr (i+1) (j-1) acc'
+ Std/Data/PrimArray/BitTwiddle.hs view
@@ -0,0 +1,174 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE UnliftedFFITypes #-}++{-|+Module      : Std.Data.PrimArray.BitTwiddle+Description : Primitive bits twiddling+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module implement some bit twiddling with ghc primitives.++We currently didn't use all functions from this module though: the performance is not+catching up c version yet. But this module and relevant benchmarks are kept in hope+that once we have fully SIMD support in GHC, we might optimize these functions further+to compete with c.++Reference:++    * https://graphics.stanford.edu/~seander/bithacks.html+    * https://jameshfisher.github.io/2017/01/24/bitwise-check-for-zero-byte.html++-}++module Std.Data.PrimArray.BitTwiddle where++import GHC.Prim+import GHC.Types+import GHC.Word+import Data.Primitive.PrimArray++-- we need to know word size+#include "MachDeps.h"++#if SIZEOF_HSWORD == 4+# define CAST_OFFSET_WORD_TO_BYTE(x) (x `uncheckedIShiftL#` 2#)+# define CAST_OFFSET_BYTE_TO_WORD(x) (x `uncheckedIShiftRA#` 2#)+#else+# define CAST_OFFSET_WORD_TO_BYTE(x) (x `uncheckedIShiftL#` 3#)+# define CAST_OFFSET_BYTE_TO_WORD(x) (x `uncheckedIShiftRA#` 3#)+#endif++isOffsetAligned# :: Int# -> Bool+{-# INLINE isOffsetAligned# #-}+isOffsetAligned# s# = isTrue# ((SIZEOF_HSWORD# -# 1#) `andI#` s# ==# 0#)++mkMask# :: Word# -> Word#+{-# INLINE mkMask# #-}+mkMask# w8# =+#if SIZEOF_HSWORD == 4+    let w16# = w8# `or#` (w8# `uncheckedShiftL#` 8#)+    in w16# `or#` (w16# `uncheckedShiftL#` 16#)+#else+    let w16# = w8# `or#` (w8# `uncheckedShiftL#` 8#)+        w32# = w16# `or#` (w16# `uncheckedShiftL#` 16#)+    in w32# `or#` (w32# `uncheckedShiftL#` 32#)+#endif++-- https://jameshfisher.github.io/2017/01/24/bitwise-check-for-zero-byte.html+--+nullByteMagic# :: Word# -> Word#+{-# INLINE nullByteMagic# #-}+nullByteMagic# w# =+#if SIZEOF_HSWORD == 4+    (w# `minusWord#` 0x01010101##) `and#` (not# w#) `and#` 0x80808080##+#else+    (w# `minusWord#` 0x0101010101010101##) `and#` (not# w#) `and#` 0x8080808080808080##+#endif++-- | Search a word8 in array.+--+-- Currently this function is ~4 times slow than c version, so we didn't use it.+--+memchr :: PrimArray Word8 -- array+       -> Word8           -- target+       -> Int             -- start offset+       -> Int             -- search length+       -> Int+{-# INLINE memchr #-}+memchr (PrimArray ba#) (W8# c#) (I# s#) (I# siz#) =+    I# (memchr# ba# c# s# siz#)++-- | The unboxed version of 'memchr'+--+memchr# :: ByteArray# -> Word# -> Int# -> Int# -> Int#+{-# NOINLINE memchr# #-}+memchr# ba# c# s# siz# = beforeAlignedLoop# ba# c# s# (s# +# siz#)+  where+    beforeAlignedLoop# :: ByteArray# -> Word# -> Int# -> Int# -> Int#+    beforeAlignedLoop# ba# c# s# end#+        | isTrue# (s# >=# end#) = -1#+        | isTrue# (c# `eqWord#` indexWord8Array# ba# s#) = s#+        | isOffsetAligned# s# = alignedLoop# ba# (mkMask# c#)+                                           CAST_OFFSET_BYTE_TO_WORD(s#)+                                           CAST_OFFSET_BYTE_TO_WORD(end#)+                                           end#+        | otherwise = beforeAlignedLoop# ba# c# (s# +# 1#) end#++    alignedLoop# :: ByteArray# -> Word# -> Int# -> Int# -> Int# -> Int#+    alignedLoop# ba# mask# s# end# end_#+        | isTrue# (s# >=# end#) = afterAlignedLoop# ba# (mask# `and#` 0xFF##)+                                                    CAST_OFFSET_WORD_TO_BYTE(s#)+                                                    end_#+        | otherwise = case indexWordArray# ba# s# of+            w# ->+                case nullByteMagic# (mask# `xor#` w#) of+                    0## -> alignedLoop# ba# mask# (s# +# 1#) end# end_#+                    _   -> afterAlignedLoop# ba# (mask# `and#` 0xFF##)+                                             CAST_OFFSET_WORD_TO_BYTE(s#)+                                             end_#++    afterAlignedLoop# :: ByteArray# -> Word# -> Int# -> Int# -> Int#+    afterAlignedLoop# ba# c# s# end#+        | isTrue# (s# >=# end#) = -1#+        | isTrue# (c# `eqWord#` indexWord8Array# ba# s#) = s#+        | otherwise = afterAlignedLoop# ba# c# (s# +# 1#) end#++-- | Search a word8 array in reverse order.+--+-- This function is used in @elemIndexEnd@, since there's no c equivalent.+--+memchrReverse :: PrimArray Word8  -- array+              -> Word8            -- target+              -> Int              -- start offset+              -> Int              -- search length+              -> Int+{-# INLINE memchrReverse #-}+memchrReverse (PrimArray ba#) (W8# c#) (I# s#) (I# siz#) =+    I# (memchr# ba# c# s# siz#)++-- | The unboxed version of 'memchrReverse'+--+memchrReverse# :: ByteArray# -> Word# -> Int# -> Int# -> Int#+{-# NOINLINE memchrReverse# #-}+memchrReverse# ba# c# s# siz# = beforeAlignedLoop# ba# c# s# (s# -# siz#)+  where+    beforeAlignedLoop# :: ByteArray# -> Word# -> Int# -> Int# -> Int#+    beforeAlignedLoop# ba# c# s# end#+        | isTrue# (s# <# end#) = -1#+        | isTrue# (c# `eqWord#` indexWord8Array# ba# s#) = s#+        | isOffsetAligned# s# = alignedLoop# ba# (mkMask# c#)+                                           CAST_OFFSET_BYTE_TO_WORD(s#)+                                           CAST_OFFSET_BYTE_TO_WORD(end#)+                                           end#+        | otherwise = beforeAlignedLoop# ba# c# (s# -# 1#) end#++    alignedLoop# :: ByteArray# -> Word# -> Int# -> Int# -> Int# -> Int#+    alignedLoop# ba# mask# s# end# end_#+        | isTrue# (s# <# end#) = afterAlignedLoop# ba# (mask# `and#` 0xFF##)+                                                   CAST_OFFSET_WORD_TO_BYTE(s#)+                                                   end_#+        | otherwise = case indexWordArray# ba# s# of+            w# ->+                case nullByteMagic# (mask# `xor#` w#) of+                    0## -> alignedLoop# ba# mask# (s# -# 1#) end# end_#+                    _   -> afterAlignedLoop# ba# (mask# `and#` 0xFF##)+                                             CAST_OFFSET_WORD_TO_BYTE(s#)+                                             end_#++    afterAlignedLoop# :: ByteArray# -> Word# -> Int# -> Int# -> Int#+    afterAlignedLoop# ba# c# s# end#+        | isTrue# (s# <# end#) = -1#+        | isTrue# (c# `eqWord#` indexWord8Array# ba# s#) = s#+        | otherwise = afterAlignedLoop# ba# c# (s# -# 1#) end#+++--------------------------------------------------------------------------------++-- HsInt hs_memchr(uint8_t *a, HsInt aoff, uint8_t b, HsInt n);+foreign import ccall unsafe "hs_memchr" c_memchr ::+    ByteArray# -> Int -> Word8 -> Int -> Int
+ Std/Data/PrimArray/Cast.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE DefaultSignatures     #-}+{-# LANGUAGE MagicHash             #-}+{-# LANGUAGE MultiParamTypeClasses #-}++{-|+Module      : Std.Data.PrimArray.Cast+Description : Primitive casting+Copyright   : Haskell Foundation, (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module is borrowed from basement's Cast module with conditional instances removed. The purpose of 'Cast' is to provide primitive types which share the same byte size, so that arrays and vectors parameterized by them can be safely coerced without breaking the index bounds. You can also use it to directly cast primitives just like @reinterpret_cast@. A 'Coercible' based instance is also provide for convenience.++-}++module Std.Data.PrimArray.Cast+    ( Cast(..)+    ) where++import           GHC.Prim+import           GHC.Types+import           GHC.Int+import           GHC.Word+import           GHC.IntWord64+import           GHC.Float+import           Data.Coerce++#include "MachDeps.h"++-- | `Cast` between primitive types of the same size.+--+class Cast source destination where+    cast :: source -> destination++instance {-# OVERLAPPABLE #-} Coercible a b => Cast a b where+    cast = coerce++instance Cast Int8  Word8 where+    cast (I8# i) = W8# (narrow8Word# (int2Word# i))+instance Cast Int16 Word16 where+    cast (I16# i) = W16# (narrow16Word# (int2Word# i))+instance Cast Int32 Word32 where+    cast (I32# i) = W32# (narrow32Word# (int2Word# i))+instance Cast Int64 Word64 where+#if WORD_SIZE_IN_BITS < 64+    cast (I64# i) = W64# (int64ToWord64# i)+#else+    cast (I64# i) = W64# (int2Word# i)+#endif+instance Cast Int   Word where+    cast (I# i) = W# (int2Word# i)++instance Cast Word8  Int8 where+    cast (W8# i) = I8# (narrow8Int# (word2Int# i))+instance Cast Word16 Int16 where+    cast (W16# i) = I16# (narrow16Int# (word2Int# i))+instance Cast Word32 Int32 where+    cast (W32# i) = I32# (narrow32Int# (word2Int# i))+instance Cast Word64 Int64 where+#if WORD_SIZE_IN_BITS < 64+    cast (W64# i) = I64# (word64ToInt64# i)+#else+    cast (W64# i) = I64# (word2Int# i)+#endif+instance Cast Word   Int where+    cast (W# w) = I# (word2Int# w)++instance Cast Word64 Double where+    cast = castWord64ToDouble+instance Cast Word32 Float where+    cast = castWord32ToFloat+instance Cast Double Word64 where+    cast = castDoubleToWord64+instance Cast Float Word32 where+    cast = castFloatToWord32++instance Cast Int64 Double where+    cast = castWord64ToDouble . cast+instance Cast Int32 Float where+    cast = castWord32ToFloat . cast+instance Cast Double Int64 where+    cast = cast . castDoubleToWord64+instance Cast Float Int32 where+    cast = cast . castFloatToWord32
+ Std/Data/PrimArray/QQ.hs view
@@ -0,0 +1,458 @@+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE BangPatterns #-}++{-|+Module      : Std.Data.PrimArray.QQ+Description : Extra stuff for PrimArray related literals+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provides functions for writing 'PrimArray' related literals 'QuasiQuote'.++-}++module Std.Data.PrimArray.QQ+  ( -- * PrimArray literal quoters+    arrASCII+  , arrW8, arrW16, arrW32, arrW64, arrWord+  , arrI8, arrI16, arrI32, arrI64, arrInt+   -- * quoter helpers+  , asciiLiteral+  , utf8Literal+  , word8Literal+  , word16Literal+  , word32Literal+  , word64Literal+  , wordLiteral+  , int8Literal+  , int16Literal+  , int32Literal+  , int64Literal+  , intLiteral+  , word8ArrayFromAddr+  , word16ArrayFromAddr+  , word32ArrayFromAddr+  , word64ArrayFromAddr+  , wordArrayFromAddr+  , int8ArrayFromAddr+  , int16ArrayFromAddr+  , int32ArrayFromAddr+  , int64ArrayFromAddr+  , intArrayFromAddr+  ) where++#include "MachDeps.h"++import           Control.Monad+import           Data.Bits+import           Data.Char                 (ord)+import           Data.Primitive.PrimArray+import           GHC.Prim+import           GHC.Ptr+import           GHC.Types+import           Data.Word+import           Data.Int+import           Language.Haskell.TH+import           Language.Haskell.TH.Quote+import           Std.Data.Array+import           Control.Monad.ST++-- | Construct data with ASCII encoded literals.+--+-- Example usage:+--+-- @+-- arrASCII :: QuasiQuoter+-- arrASCII = QuasiQuoter+--     (asciiLiteral $ \ len addr -> [| word8ArrayFromAddr $(len) $(addr) |])+--     ...+--+-- word8ArrayFromAddr :: Int -> Addr# -> PrimArray Word8+-- {-# INLINE word8ArrayFromAddr #-}+-- word8ArrayFromAddr l addr# = runST $ do+--     mba <- newPrimArray (I# l)+--     copyPtrToMutablePrimArray mba 0 (Ptr addr#) l+--     unsafeFreezePrimArray mba+-- @+--+asciiLiteral :: (ExpQ -> ExpQ -> ExpQ) -- ^ Construction function which receive a byte+                                       --   length 'Int' and a 'Addr#' 'LitE' expression.+             -> String                 -- ^ Quoter input+             -> ExpQ                   -- ^ Final Quoter+asciiLiteral k str = k (return . LitE  . IntegerL . fromIntegral $ length str)+                       ((LitE . StringPrimL) `fmap` check str)+  where+    check :: String -> Q [Word8]+    check [] = return []+    check (c:cs) = do+        when (ord c > 0xFF) $+            fail $ "character '" ++ [c] ++ "' is have out of range in ASCII literal:" ++ str+        cs' <- check cs+        return (fromIntegral (ord c):cs')++arrASCII :: QuasiQuoter+arrASCII = QuasiQuoter+    (asciiLiteral $ \ len addr -> [| word8ArrayFromAddr $(len) $(addr) |])+    (error "Cannot use arrASCII as a pattern")+    (error "Cannot use arrASCII as a type")+    (error "Cannot use arrASCII as a dec")++word8ArrayFromAddr :: Int -> Addr# -> PrimArray Word8+{-# INLINE word8ArrayFromAddr #-}+word8ArrayFromAddr l addr# = runST $ do+    mba <- newPrimArray l+    copyPtrToMutablePrimArray mba 0 (Ptr addr#) l+    unsafeFreezePrimArray mba++int8ArrayFromAddr :: Int -> Addr# -> PrimArray Int8+int8ArrayFromAddr l addr# = castArray (word8ArrayFromAddr l addr#)++-- | Construct data with UTF-8 encoded literals.+--+-- Smiliar to 'asciIILiteral', the+--+utf8Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+utf8Literal k str = k (return . LitE  . IntegerL . fromIntegral $ length str)+                      ((LitE . StringPrimL) `fmap` check str)+  where+    check :: String -> Q [Word8]+    check [] = return []+    check (c:cs) = case ord c of+        n+            | n <= 0x0000007F -> do+                let w = fromIntegral n+                ws <- check cs+                return (w:ws)+            | n <= 0x000007FF -> do+                let w1 = fromIntegral $ 0xC0 .|. (n `shiftR` 6)+                    w2 = fromIntegral $ 0x80 .|. (n .&. 0x3F)+                ws <- check cs+                return (w1:w2:ws)+            | n <= 0x0000D7FF -> do+                let w1 = fromIntegral $ 0xE0 .|. (n `shiftR` 12)+                    w2 = fromIntegral $ 0x80 .|. (n `shiftR` 6 .&. 0x3F)+                    w3 = fromIntegral $ 0x80 .|. (n .&. 0x3F)+                ws <- check cs+                return (w1:w2:w3:ws)+            | n <= 0x0000DFFF -> do+                fail $ "character '" ++ [c] ++ "' is have out of range in UTF-8 literal:" ++ str+            | n <= 0x0000FFFF -> do+                let w1 = fromIntegral $ 0xE0 .|. (n `shiftR` 12)+                    w2 = fromIntegral $ 0x80 .|. (n `shiftR` 6 .&. 0x3F)+                    w3 = fromIntegral $ 0x80 .|. (n .&. 0x3F)+                ws <- check cs+                return (w1:w2:w3:ws)+            | n <= 0x0010FFFF -> do+                let w1 = fromIntegral $ 0xF0 .|. (n `shiftR` 18)+                    w2 = fromIntegral $ 0x80 .|. (n `shiftR` 12 .&. 0x3F)+                    w3 = fromIntegral $ 0x80 .|. (n `shiftR` 6 .&. 0x3F)+                    w4 = fromIntegral $ 0x80 .|. (n .&. 0x3F)+                ws <- check cs+                return (w1:w2:w3:w4:ws)+            | otherwise ->+                fail $ "character '" ++ [c] ++ "' is have out of range in UTF-8 literal:" ++ str+++vectorLiteral :: ([Integer] -> Q [Word8]) -> (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+vectorLiteral f k str = do+    (len, ws) <- parse str+    k (return . LitE  . IntegerL .fromIntegral $ len) $ (return . LitE . StringPrimL) ws+  where+    parse :: String -> Q (Int, [Word8])+    parse str = do+        case (readList :: ReadS [Integer]) ("[" ++ str ++ "]") of+            [(is, "")] -> (length is, ) `fmap` f is+            _ -> do _ <- fail $ "can't parse vector literal:" ++ str+                    return (0, [])++--------------------------------------------------------------------------------++word8Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+word8Literal k str = vectorLiteral checkW8 k str+  where+    checkW8 :: [Integer] -> Q [Word8]+    checkW8 [] = return []+    checkW8 (i:is) = do+        when (i<0 || i > 0xFF) $+            fail $ "integer " ++ show i ++ " is out of Word8 range in literal:" ++ str+        ws <- checkW8 is+        let w = fromIntegral (i .&. 0xFF)+        return (w:ws)++arrW8 :: QuasiQuoter+arrW8 = QuasiQuoter+    (word8Literal $ \ len addr -> [| word8ArrayFromAddr $(len) $(addr) |])+    (error "Cannot use arrW8 as a pattern")+    (error "Cannot use arrW8 as a type")+    (error "Cannot use arrW8 as a dec")++int8Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+int8Literal k str = vectorLiteral checkI8 k str+  where+    checkI8 :: [Integer] -> Q [Word8]+    checkI8 [] = return []+    checkI8 (i:is) = do+        when (i< (-0x80) || i > 0x7F) $+            fail $ "integer " ++ show i ++ " is out of Int8 range in literal:" ++ str+        ws <- checkI8 is+        let w = fromIntegral (i .&. 0xFF)+        return (w:ws)++arrI8 :: QuasiQuoter+arrI8 = QuasiQuoter+    (int8Literal $ \ len addr -> [| int8ArrayFromAddr $(len) $(addr) |])+    (error "Cannot use arrI8 as a pattern")+    (error "Cannot use arrI8 as a type")+    (error "Cannot use arrI8 as a dec")++--------------------------------------------------------------------------------++word16Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+word16Literal k str = vectorLiteral checkW16 k str+  where+    checkW16 :: [Integer] -> Q [Word8]+    checkW16 [] = return []+    checkW16 (i:is) = do+        when (i<0 || i > 0xFFFF) $+            fail $ "integer " ++ show i ++ " is out of word16 range in literal:" ++ str+        ws <- checkW16 is+        let w1 = fromIntegral (i .&. 0xFF)+            w2 = fromIntegral (i `shiftR` 8 .&. 0xFF)+#ifdef WORDS_BIGENDIAN+        return (w2:w1:ws)+#else+        return (w1:w2:ws)+#endif++arrW16 :: QuasiQuoter+arrW16 = QuasiQuoter+    (word16Literal $ \ len addr -> [| word16ArrayFromAddr $(len) $(addr) |])+    (error "Cannot use arrW16 as a pattern")+    (error "Cannot use arrW16 as a type")+    (error "Cannot use arrW16 as a dec")++word16ArrayFromAddr :: Int -> Addr# -> PrimArray Word16+{-# INLINE word16ArrayFromAddr #-}+word16ArrayFromAddr l addr# = runST $ do+    mba <- newArr l+    copyPtrToMutablePrimArray mba 0 (Ptr addr#) l+    unsafeFreezePrimArray mba++int16ArrayFromAddr :: Int -> Addr# -> PrimArray Int16+int16ArrayFromAddr l addr# = castArray (word16ArrayFromAddr l addr#)++int16Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+int16Literal k str = vectorLiteral checkI16 k str+  where+    checkI16 :: [Integer] -> Q [Word8]+    checkI16 [] = return []+    checkI16 (i:is) = do+        when (i<(-0x8000) || i>0x7FFF) $+            fail $ "integer " ++ show i ++ " is out of int16 range in literal:" ++ str+        ws <- checkI16 is+        let w1 = fromIntegral (i .&. 0xFF)+            w2 = fromIntegral (i `shiftR` 8 .&. 0xFF)+#ifdef WORDS_BIGENDIAN+        return (w2:w1:ws)+#else+        return (w1:w2:ws)+#endif++arrI16 :: QuasiQuoter+arrI16 = QuasiQuoter+    (word16Literal $ \ len addr -> [| int16ArrayFromAddr $(len) $(addr) |])+    (error "Cannot use arrI16 as a pattern")+    (error "Cannot use arrI16 as a type")+    (error "Cannot use arrI16 as a dec")+--------------------------------------------------------------------------------++word32Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+word32Literal k str = vectorLiteral checkW32 k str+  where+    checkW32 :: [Integer] -> Q [Word8]+    checkW32 [] = return []+    checkW32 (i:is) = do+        when (i<0 || i > 0xFFFFFFFF) $+            fail $ "integer " ++ show i ++ " is out of word32 range in literal:" ++ str+        ws <- checkW32 is+        let w1 = fromIntegral (i .&. 0xFF)+            w2 = fromIntegral (i `shiftR` 8 .&. 0xFF)+            w3 = fromIntegral (i `shiftR` 16 .&. 0xFF)+            w4 = fromIntegral (i `shiftR` 24 .&. 0xFF)+#ifdef WORDS_BIGENDIAN+        return (w4:w3:w2:w1:ws)+#else+        return (w1:w2:w3:w4:ws)+#endif++arrW32 :: QuasiQuoter+arrW32 = QuasiQuoter+    (word32Literal $ \ len addr -> [| word32ArrayFromAddr $(len) $(addr) |])+    (error "Cannot use arrW32 as a pattern")+    (error "Cannot use arrW32 as a type")+    (error "Cannot use arrW32 as a dec")++word32ArrayFromAddr :: Int -> Addr# -> PrimArray Word32+{-# INLINE word32ArrayFromAddr #-}+word32ArrayFromAddr l addr# = runST $ do+    mba <- newArr l+    copyPtrToMutablePrimArray mba 0 (Ptr addr#) l+    unsafeFreezePrimArray mba++int32ArrayFromAddr :: Int -> Addr# -> PrimArray Int32+int32ArrayFromAddr l addr# = castArray (word32ArrayFromAddr l addr#)++int32Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+int32Literal k str = vectorLiteral checkI32 k str+  where+    checkI32 :: [Integer] -> Q [Word8]+    checkI32 [] = return []+    checkI32 (i:is) = do+        when (i<(-0x80000000) || i>0x7FFFFFFF) $+            fail $ "integer " ++ show i ++ " is out of int32 range in literal:" ++ str+        ws <- checkI32 is+        let w1 = fromIntegral (i .&. 0xFF)+            w2 = fromIntegral (i `shiftR` 8 .&. 0xFF)+            w3 = fromIntegral (i `shiftR` 16 .&. 0xFF)+            w4 = fromIntegral (i `shiftR` 24 .&. 0xFF)+#ifdef WORDS_BIGENDIAN+        return (w4:w3:w2:w1:ws)+#else+        return (w1:w2:w3:w4:ws)+#endif++arrI32 :: QuasiQuoter+arrI32 = QuasiQuoter+    (int32Literal $ \ len addr -> [| int32ArrayFromAddr $(len) $(addr) |])+    (error "Cannot use arrI32 as a pattern")+    (error "Cannot use arrI32 as a type")+    (error "Cannot use arrI32 as a dec")++--------------------------------------------------------------------------------++word64Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+word64Literal k str = vectorLiteral checkW64 k str+  where+    checkW64 :: [Integer] -> Q [Word8]+    checkW64 [] = return []+    checkW64 (i:is) = do+        when (i<0 || i > 0xFFFFFFFFFFFFFFFF) $+            fail $ "integer " ++ show i ++ " is out of word64 range in literal:" ++ str+        ws <- checkW64 is+        let w1 = fromIntegral (i .&. 0xFF)+            w2 = fromIntegral (i `shiftR` 8 .&. 0xFF)+            w3 = fromIntegral (i `shiftR` 16 .&. 0xFF)+            w4 = fromIntegral (i `shiftR` 24 .&. 0xFF)+            w5 = fromIntegral (i `shiftR` 32 .&. 0xFF)+            w6 = fromIntegral (i `shiftR` 40 .&. 0xFF)+            w7 = fromIntegral (i `shiftR` 48 .&. 0xFF)+            w8 = fromIntegral (i `shiftR` 56 .&. 0xFF)+#ifdef WORDS_BIGENDIAN+        return (w8:w7:w6:w5:w4:w3:w2:w1:ws)+#else+        return (w1:w2:w3:w4:w5:w6:w7:w8:ws)+#endif++arrW64 :: QuasiQuoter+arrW64 = QuasiQuoter+    (word64Literal $ \ len addr -> [| word64ArrayFromAddr $(len) $(addr) |])+    (error "Cannot use arrW64 as a pattern")+    (error "Cannot use arrW64 as a type")+    (error "Cannot use arrW64 as a dec")++word64ArrayFromAddr :: Int -> Addr# -> PrimArray Word64+{-# INLINE word64ArrayFromAddr #-}+word64ArrayFromAddr l addr# = runST $ do+    mba <- newArr l+    copyPtrToMutablePrimArray mba 0 (Ptr addr#) l+    unsafeFreezePrimArray mba++int64ArrayFromAddr :: Int -> Addr# -> PrimArray Int64+int64ArrayFromAddr l addr# = castArray (word64ArrayFromAddr l addr#)++int64Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+int64Literal k str = vectorLiteral checkI64 k str+  where+    checkI64 :: [Integer] -> Q [Word8]+    checkI64 [] = return []+    checkI64 (i:is) = do+        when (i<(-0x8000000000000000) || i > 0x7FFFFFFFFFFFFFFF) $+            fail $ "integer " ++ show i ++ " is out of int64 range in literal:" ++ str+        ws <- checkI64 is+        let w1 = fromIntegral (i .&. 0xFF)+            w2 = fromIntegral (i `shiftR` 8 .&. 0xFF)+            w3 = fromIntegral (i `shiftR` 16 .&. 0xFF)+            w4 = fromIntegral (i `shiftR` 24 .&. 0xFF)+            w5 = fromIntegral (i `shiftR` 32 .&. 0xFF)+            w6 = fromIntegral (i `shiftR` 40 .&. 0xFF)+            w7 = fromIntegral (i `shiftR` 48 .&. 0xFF)+            w8 = fromIntegral (i `shiftR` 56 .&. 0xFF)+#ifdef WORDS_BIGENDIAN+        return (w8:w7:w6:w5:w4:w3:w2:w1:ws)+#else+        return (w1:w2:w3:w4:w5:w6:w7:w8:ws)+#endif++arrI64 :: QuasiQuoter+arrI64 = QuasiQuoter+    (int64Literal $ \ len addr -> [| int64ArrayFromAddr $(len) $(addr) |])+    (error "Cannot use arrI64 as a pattern")+    (error "Cannot use arrI64 as a type")+    (error "Cannot use arrI64 as a dec")++--------------------------------------------------------------------------------++wordArrayFromAddr :: Int -> Addr# -> PrimArray Word+wordArrayFromAddr l addr# =+#if SIZEOF_HSWORD == 8+    unsafeCoerce# (word64ArrayFromAddr l addr#)+#else+    unsafeCoerce# (word32ArrayFromAddr l addr#)+#endif++intArrayFromAddr :: Int -> Addr# -> PrimArray Int+intArrayFromAddr l addr# =+#if SIZEOF_HSWORD == 8+    unsafeCoerce# (int64ArrayFromAddr l addr#)+#else+    unsafeCoerce# (int32ArrayFromAddr l addr#)+#endif++wordLiteral :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+wordLiteral =+#if SIZEOF_HSWORD == 8+    word64Literal+#else+    word32Literal+#endif++intLiteral :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+intLiteral =+#if SIZEOF_HSWORD == 8+    int64Literal+#else+    int32Literal+#endif++arrWord :: QuasiQuoter+arrWord = QuasiQuoter+    (wordLiteral $ \ len addr -> [| wordArrayFromAddr $(len) $(addr) |])+    (error "Cannot use arrWord as a pattern")+    (error "Cannot use arrWord as a type")+    (error "Cannot use arrWord as a dec")++arrInt :: QuasiQuoter+arrInt = QuasiQuoter+    (intLiteral $ \ len addr -> [| intArrayFromAddr $(len) $(addr) |])+    (error "Cannot use arrInt as a pattern")+    (error "Cannot use arrInt as a type")+    (error "Cannot use arrInt as a dec")++--------------------------------------------------------------------------------
+ Std/Data/PrimArray/UnalignedAccess.hs view
@@ -0,0 +1,807 @@+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE CPP               #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MagicHash         #-}+{-# LANGUAGE UnboxedTuples     #-}++{-|+Module      : Std.Data.PrimArray.UnalignedAccess+Description : unaligned access for primitive arrays+Copyright   : (c) Dong Han, 2017-2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module implements unaligned element access with ghc primitives (> 8.6).+-}++module Std.Data.PrimArray.UnalignedAccess where++import           GHC.Int+import           GHC.Prim+import           GHC.Types+import           GHC.Word+import           GHC.Float (stgFloatToWord32, stgWord32ToFloat, stgWord64ToDouble, stgDoubleToWord64)++-- toggle these defs to test different implements+#define USE_BSWAP+-- #define USE_SHIFT++--------------------------------------------------------------------------------++newtype UnalignedSize a = UnalignedSize { getUnalignedSize :: Int } deriving (Show, Eq)++-- | Primitive types which can be unaligned accessed+--+class UnalignedAccess a where+    unalignedSize :: UnalignedSize a+    writeWord8ArrayAs :: MutableByteArray# s -> Int# -> a -> State# s -> State# s+    readWord8ArrayAs  :: MutableByteArray# s -> Int# -> State# s -> (# State# s, a #)+    indexWord8ArrayAs :: ByteArray# -> Int# -> a++instance UnalignedAccess Word8 where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 1+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (W8# x#) = writeWord8Array# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8Array# mba# i# s0 in (# s1, W8# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = W8# (indexWord8Array# ba# i#)++instance UnalignedAccess Int8 where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 1+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (I8# x#) = writeInt8Array# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readInt8Array# mba# i# s0 in (# s1, I8# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = I8# (indexInt8Array# ba# i#)++-- | little endianess wrapper+--+newtype LE a = LE { getLE :: a } deriving (Show, Eq)++-- | big endianess wrapper+--+newtype BE a = BE { getBE :: a } deriving (Show, Eq)++#define USE_HOST_IMPL(END) \+    {-# INLINE writeWord8ArrayAs #-}; \+    writeWord8ArrayAs mba# i# (END x) = writeWord8ArrayAs mba# i# x; \+    {-# INLINE readWord8ArrayAs #-}; \+    readWord8ArrayAs mba# i# s0 = \+        let !(# s1, x #) = readWord8ArrayAs mba# i# s0 in (# s1, END x #); \+    {-# INLINE indexWord8ArrayAs #-}; \+    indexWord8ArrayAs ba# i# = END (indexWord8ArrayAs ba# i#);++--------------------------------------------------------------------------------++instance UnalignedAccess Word16 where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 2+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (W16# x#) = writeWord8ArrayAsWord16# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsWord16# mba# i# s0 in (# s1, W16# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = W16# (indexWord8ArrayAsWord16# ba# i#)++instance UnalignedAccess (LE Word16) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 2+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (W16# x#)) s0# =+        let s1# = writeWord8Array# mba# i# x# s0#+        in        writeWord8Array# mba# (i# +# 1#) (uncheckedShiftRL# x# 8#) s1#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, w1# #) = readWord8Array# mba# i# s0+            !(# s2, w2# #) = readWord8Array# mba# (i# +# 1#) s1+        in (# s2, LE (W16# (uncheckedShiftL# w2# 8# `or#` w1#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let w1# = indexWord8Array# ba# i#+            w2# = indexWord8Array# ba# (i# +# 1#)+        in LE (W16# (uncheckedShiftL# w2# 8# `or#` w1#))+#else+    USE_HOST_IMPL(LE)+#endif++instance UnalignedAccess (BE Word16) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 2+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    USE_HOST_IMPL(BE)+#else+-- on X86 we use bswap+-- TODO: find out if arch64 support this+#if (defined(i386_HOST_ARCH) || defined(x86_64_HOST_ARCH)) && defined(USE_BSWAP)+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (W16# x#)) = writeWord8ArrayAsWord16# mba# i# (byteSwap16# x#)+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsWord16# mba# i# s0+        in (# s1, BE (W16# (byteSwap16# x#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = BE (W16# (byteSwap16# (indexWord8ArrayAsWord16# ba# i#)))+#else+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (W16# x#)) s0# =+        let s1# = writeWord8Array# mba# i# (uncheckedShiftRL# x# 8#) s0#+        in        writeWord8Array# mba# (i# +# 1#) x# s1#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, w2# #) = readWord8Array# mba# i# s0+            !(# s2, w1# #) = readWord8Array# mba# (i# +# 1#) s1+        in (# s2, BE (W16# (uncheckedShiftL# w2# 8# `or#`  w1#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let w2# = indexWord8Array# ba# i#+            w1# = indexWord8Array# ba# (i# +# 1#)+        in BE (W16# (uncheckedShiftL# w2# 8# `or#`  w1#))+#endif+#endif++--------------------------------------------------------------------------------++instance UnalignedAccess Word32 where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (W32# x#) =  writeWord8ArrayAsWord32# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsWord32# mba# i# s0 in (# s1, W32# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = W32# (indexWord8ArrayAsWord32# ba# i#)+++instance UnalignedAccess (LE Word32) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (W32# x#)) s0# =+        let s1# = writeWord8Array# mba# i# x# s0#+            s2# = writeWord8Array# mba# (i# +# 1#) (uncheckedShiftRL# x# 8#) s1#+            s3# = writeWord8Array# mba# (i# +# 2#) (uncheckedShiftRL# x# 16#) s2#+        in        writeWord8Array# mba# (i# +# 3#) (uncheckedShiftRL# x# 24#) s3#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, w1# #) = readWord8Array# mba# i# s0+            !(# s2, w2# #) = readWord8Array# mba# (i# +# 1#) s1+            !(# s3, w3# #) = readWord8Array# mba# (i# +# 2#) s2+            !(# s4, w4# #) = readWord8Array# mba# (i# +# 3#) s3+        in (# s4, LE (W32# ((uncheckedShiftL# w4# 24#) `or#`+                    (uncheckedShiftL# w3# 16#) `or#`+                        (uncheckedShiftL# w2# 8#) `or#` w1#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let w1# = indexWord8Array# ba# i#+            w2# = indexWord8Array# ba# (i# +# 1#)+            w3# = indexWord8Array# ba# (i# +# 2#)+            w4# = indexWord8Array# ba# (i# +# 3#)+        in LE (W32# ((uncheckedShiftL# w4# 24#) `or#`+                    (uncheckedShiftL# w3# 16#) `or#`+                        (uncheckedShiftL# w2# 8#) `or#` w1#))+#else+    USE_HOST_IMPL(LE)+#endif++instance UnalignedAccess (BE Word32) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    USE_HOST_IMPL(BE)+#else+-- on X86 we use bswap+-- TODO: find out if arch64 support this+#if (defined(i386_HOST_ARCH) || defined(x86_64_HOST_ARCH)) && defined(USE_BSWAP)+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (W32# x#)) = writeWord8ArrayAsWord32# mba# i# (byteSwap32# x#)+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsWord32# mba# i# s0+        in (# s1, BE (W32# (byteSwap32# x#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = BE (W32# (byteSwap32# (indexWord8ArrayAsWord32# ba# i#)))+#else+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (W32# x#)) s0# =+        let s1# = writeWord8Array# mba# i# (uncheckedShiftRL# x# 24#) s0#+            s2# = writeWord8Array# mba# (i# +# 1#) (uncheckedShiftRL# x# 16#) s1#+            s3# = writeWord8Array# mba# (i# +# 2#) (uncheckedShiftRL# x# 8#) s2#+        in        writeWord8Array# mba# (i# +# 3#) x# s3#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, w4# #) = readWord8Array# mba# i# s0+            !(# s2, w3# #) = readWord8Array# mba# (i# +# 1#) s1+            !(# s3, w2# #) = readWord8Array# mba# (i# +# 2#) s2+            !(# s4, w1# #) = readWord8Array# mba# (i# +# 3#) s3+        in (# s4, BE (W32# ((uncheckedShiftL# w4# 24#) `or#`+                    (uncheckedShiftL# w3# 16#) `or#`+                        (uncheckedShiftL# w2# 8#) `or#` w1#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let w4# = indexWord8Array# ba# i#+            w3# = indexWord8Array# ba# (i# +# 1#)+            w2# = indexWord8Array# ba# (i# +# 2#)+            w1# = indexWord8Array# ba# (i# +# 3#)+        in BE (W32# ((uncheckedShiftL# w4# 24#) `or#`+                    (uncheckedShiftL# w3# 16#) `or#`+                        (uncheckedShiftL# w2# 8#) `or#` w1#))+#endif+#endif++--------------------------------------------------------------------------------++instance UnalignedAccess Word64 where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (W64# x#) =  writeWord8ArrayAsWord64# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsWord64# mba# i# s0 in (# s1, W64# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = W64# (indexWord8ArrayAsWord64# ba# i#)+++instance UnalignedAccess (LE Word64) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (W64# x#)) s0# =+        let s1# = writeWord8Array# mba# i# x# s0#+            s2# = writeWord8Array# mba# (i# +# 1#) (uncheckedShiftRL# x# 8#) s1#+            s3# = writeWord8Array# mba# (i# +# 2#) (uncheckedShiftRL# x# 16#) s2#+            s4# = writeWord8Array# mba# (i# +# 3#) (uncheckedShiftRL# x# 24#) s3#+            s5# = writeWord8Array# mba# (i# +# 4#) (uncheckedShiftRL# x# 32#) s4#+            s6# = writeWord8Array# mba# (i# +# 5#) (uncheckedShiftRL# x# 40#) s5#+            s7# = writeWord8Array# mba# (i# +# 6#) (uncheckedShiftRL# x# 48#) s6#+        in        writeWord8Array# mba# (i# +# 7#) (uncheckedShiftRL# x# 56#) s7#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, w1# #) = readWord8Array# mba# i# s0+            !(# s2, w2# #) = readWord8Array# mba# (i# +# 1#) s1+            !(# s3, w3# #) = readWord8Array# mba# (i# +# 2#) s2+            !(# s4, w4# #) = readWord8Array# mba# (i# +# 3#) s3+            !(# s5, w5# #) = readWord8Array# mba# (i# +# 4#) s4+            !(# s6, w6# #) = readWord8Array# mba# (i# +# 5#) s5+            !(# s7, w7# #) = readWord8Array# mba# (i# +# 6#) s6+            !(# s8, w8# #) = readWord8Array# mba# (i# +# 7#) s7+        in (# s8, LE (W64# ((uncheckedShiftL# w8# 56#) `or#`+                    (uncheckedShiftL# w7# 48#) `or#`+                        (uncheckedShiftL# w6# 40#) `or#`+                            (uncheckedShiftL# w5# 32#) `or#`+                                (uncheckedShiftL# w4# 24#) `or#`+                                    (uncheckedShiftL# w3# 16#) `or#`+                                        (uncheckedShiftL# w2# 8#) `or#` w1#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let w1# = indexWord8Array# ba# i#+            w2# = indexWord8Array# ba# (i# +# 1#)+            w3# = indexWord8Array# ba# (i# +# 2#)+            w4# = indexWord8Array# ba# (i# +# 3#)+            w5# = indexWord8Array# ba# (i# +# 4#)+            w6# = indexWord8Array# ba# (i# +# 5#)+            w7# = indexWord8Array# ba# (i# +# 6#)+            w8# = indexWord8Array# ba# (i# +# 7#)+        in LE (W64# ((uncheckedShiftL# w8# 56#) `or#`+                    (uncheckedShiftL# w7# 48#) `or#`+                        (uncheckedShiftL# w6# 40#) `or#`+                            (uncheckedShiftL# w5# 32#) `or#`+                                (uncheckedShiftL# w4# 24#) `or#`+                                    (uncheckedShiftL# w3# 16#) `or#`+                                        (uncheckedShiftL# w2# 8#) `or#` w1#))+#else+    USE_HOST_IMPL(LE)+#endif++instance UnalignedAccess (BE Word64) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    USE_HOST_IMPL(BE)+#else+-- on X86 we use bswap+-- TODO: find out if arch64 support this+#if (defined(i386_HOST_ARCH) || defined(x86_64_HOST_ARCH)) && defined(USE_BSWAP)+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (W64# x#)) = writeWord8ArrayAsWord64# mba# i# (byteSwap64# x#)+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsWord64# mba# i# s0+        in (# s1, BE (W64# (byteSwap64# x#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = BE (W64# (byteSwap64# (indexWord8ArrayAsWord64# ba# i#)))+#else+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (W64# x#)) s0# =+        let s1# = writeWord8Array# mba# i# (uncheckedShiftRL# x# 56#) s0#+            s2# = writeWord8Array# mba# (i# +# 1#) (uncheckedShiftRL# x# 48#) s1#+            s3# = writeWord8Array# mba# (i# +# 2#) (uncheckedShiftRL# x# 40#) s2#+            s4# = writeWord8Array# mba# (i# +# 3#) (uncheckedShiftRL# x# 32#) s3#+            s5# = writeWord8Array# mba# (i# +# 4#) (uncheckedShiftRL# x# 24#) s4#+            s6# = writeWord8Array# mba# (i# +# 5#) (uncheckedShiftRL# x# 16#) s5#+            s7# = writeWord8Array# mba# (i# +# 6#) (uncheckedShiftRL# x# 8#) s6#+        in        writeWord8Array# mba# (i# +# 7#) x# s7#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, w8# #) = readWord8Array# mba# i# s0+            !(# s2, w7# #) = readWord8Array# mba# (i# +# 1#) s1+            !(# s3, w6# #) = readWord8Array# mba# (i# +# 2#) s2+            !(# s4, w5# #) = readWord8Array# mba# (i# +# 3#) s3+            !(# s5, w4# #) = readWord8Array# mba# (i# +# 4#) s4+            !(# s6, w3# #) = readWord8Array# mba# (i# +# 5#) s5+            !(# s7, w2# #) = readWord8Array# mba# (i# +# 6#) s6+            !(# s8, w1# #) = readWord8Array# mba# (i# +# 7#) s7+        in (# s8, BE (W64# ((uncheckedShiftL# w8# 56#) `or#`+                    (uncheckedShiftL# w7# 48#) `or#`+                        (uncheckedShiftL# w6# 40#) `or#`+                            (uncheckedShiftL# w5# 32#) `or#`+                                (uncheckedShiftL# w4# 24#) `or#`+                                    (uncheckedShiftL# w3# 16#) `or#`+                                        (uncheckedShiftL# w2# 8#) `or#` w1#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let w8# = indexWord8Array# ba# i#+            w7# = indexWord8Array# ba# (i# +# 1#)+            w6# = indexWord8Array# ba# (i# +# 2#)+            w5# = indexWord8Array# ba# (i# +# 3#)+            w4# = indexWord8Array# ba# (i# +# 4#)+            w3# = indexWord8Array# ba# (i# +# 5#)+            w2# = indexWord8Array# ba# (i# +# 6#)+            w1# = indexWord8Array# ba# (i# +# 7#)+        in BE (W64# ((uncheckedShiftL# w8# 56#) `or#`+                    (uncheckedShiftL# w7# 48#) `or#`+                        (uncheckedShiftL# w6# 40#) `or#`+                            (uncheckedShiftL# w5# 32#) `or#`+                                (uncheckedShiftL# w4# 24#) `or#`+                                    (uncheckedShiftL# w3# 16#) `or#`+                                        (uncheckedShiftL# w2# 8#) `or#` w1#))+#endif+#endif++--------------------------------------------------------------------------------++instance UnalignedAccess Word where+#if SIZEOF_HSWORD == 4+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+#else+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+#endif+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (W# x#) = writeWord8ArrayAsWord# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsWord# mba# i# s0 in (# s1, W# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = W# (indexWord8ArrayAsWord# ba# i#)++instance UnalignedAccess (LE Word) where+#if SIZEOF_HSWORD == 4+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (W# x#)) = writeWord8ArrayAs mba# i# (LE (W32# x#))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, LE (W32# x#) #) = readWord8ArrayAs mba# i# s0 in (# s1, LE (W# x#) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = case (indexWord8ArrayAs ba# i#) of (LE (W32# x#)) -> LE (W# x#)+#else+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (W# x#)) = writeWord8ArrayAs mba# i# (LE (W64# x#))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, LE (W64# x#) #) = readWord8ArrayAs mba# i# s0 in (# s1, LE (W# x#) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = case (indexWord8ArrayAs ba# i#) of (LE (W64# x#)) -> LE (W# x#)+#endif++instance UnalignedAccess (BE Word) where+#if SIZEOF_HSWORD == 4+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (W# x#)) = writeWord8ArrayAs mba# i# (BE (W32# x#))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, BE (W32# x#) #) = readWord8ArrayAs mba# i# s0 in (# s1, BE (W# x#) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = case (indexWord8ArrayAs ba# i#) of (BE (W32# x#)) -> BE (W# x#)+#else+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (W# x#)) = writeWord8ArrayAs mba# i# (BE (W64# x#))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, BE (W64# x#) #) = readWord8ArrayAs mba# i# s0 in (# s1, BE (W# x#) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = case (indexWord8ArrayAs ba# i#) of (BE (W64# x#)) -> BE (W# x#)+#endif++--------------------------------------------------------------------------------++instance UnalignedAccess Int16 where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 2+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (I16# x#) = writeWord8ArrayAsInt16# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsInt16# mba# i# s0 in (# s1, I16# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = I16# (indexWord8ArrayAsInt16# ba# i#)++instance UnalignedAccess (LE Int16) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 2+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (I16# x#)) =+        writeWord8ArrayAs mba# i# (LE (W16# (int2Word# x#)))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, LE (W16# x#) #) = readWord8ArrayAs mba# i# s0+        in (# s1, LE (I16# (narrow16Int# (word2Int# x#))) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let LE (W16# x#) = indexWord8ArrayAs ba# i#+        in LE (I16# (narrow16Int# (word2Int# x#)))+#else+    USE_HOST_IMPL(LE)+#endif++instance UnalignedAccess (BE Int16) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 2+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    USE_HOST_IMPL(BE)+#else+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (I16# x#)) =+        writeWord8ArrayAs mba# i# (BE (W16# (int2Word# x#)))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, BE (W16# x#) #) = readWord8ArrayAs mba# i# s0+        in (# s1, BE (I16# (narrow16Int# (word2Int# x#))) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let BE (W16# x#) = indexWord8ArrayAs ba# i#+        in BE (I16# (narrow16Int# (word2Int# x#)))+#endif++--------------------------------------------------------------------------------++instance UnalignedAccess Int32 where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (I32# x#) = writeWord8ArrayAsInt32# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsInt32# mba# i# s0 in (# s1, I32# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = I32# (indexWord8ArrayAsInt32# ba# i#)++instance UnalignedAccess (LE Int32) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (I32# x#)) =+        writeWord8ArrayAs mba# i# (LE (W32# (int2Word# x#)))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, LE (W32# x#) #) = readWord8ArrayAs mba# i# s0+        in (# s1, LE (I32# (narrow32Int# (word2Int# x#))) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let LE (W32# x#) = indexWord8ArrayAs ba# i#+        in LE (I32# (narrow32Int# (word2Int# x#)))+#else+    USE_HOST_IMPL(LE)+#endif++instance UnalignedAccess (BE Int32) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    USE_HOST_IMPL(BE)+#else+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (I32# x#)) =+        writeWord8ArrayAs mba# i# (BE (W32# (int2Word# x#)))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, BE (W32# x#) #) = readWord8ArrayAs mba# i# s0+        in (# s1, BE (I32# (narrow32Int# (word2Int# x#))) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let BE (W32# x#) = indexWord8ArrayAs ba# i#+        in BE (I32# (narrow32Int# (word2Int# x#)))+#endif++--------------------------------------------------------------------------------++instance UnalignedAccess Int64 where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (I64# x#) = writeWord8ArrayAsInt64# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsInt64# mba# i# s0 in (# s1, I64# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = I64# (indexWord8ArrayAsInt64# ba# i#)++instance UnalignedAccess (LE Int64) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (I64# x#)) =+        writeWord8ArrayAs mba# i# (LE (W64# (int2Word# x#)))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, LE (W64# x#) #) = readWord8ArrayAs mba# i# s0+        in (# s1, LE (I64# (word2Int# x#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let LE (W64# x#) = indexWord8ArrayAs ba# i#+        in LE (I64# (word2Int# x#))+#else+    USE_HOST_IMPL(LE)+#endif++instance UnalignedAccess (BE Int64) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    USE_HOST_IMPL(BE)+#else+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (I64# x#)) =+        writeWord8ArrayAs mba# i# (BE (W64# (int2Word# x#)))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, BE (W64# x#) #) = readWord8ArrayAs mba# i# s0+        in (# s1, BE (I64# (word2Int# x#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let BE (W64# x#) = indexWord8ArrayAs ba# i#+        in BE (I64# (word2Int# x#))+#endif++--------------------------------------------------------------------------------++instance UnalignedAccess Int where+#if SIZEOF_HSWORD == 4+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+#else+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+#endif+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (I# x#) = writeWord8ArrayAsInt# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsInt# mba# i# s0 in (# s1, I# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = I# (indexWord8ArrayAsInt# ba# i#)++instance UnalignedAccess (LE Int) where+#if SIZEOF_HSWORD == 4+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (I# x#)) = writeWord8ArrayAs mba# i# (LE (I32# x#))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, LE (I32# x#) #) = readWord8ArrayAs mba# i# s0 in (# s1, LE (I# x#) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = case (indexWord8ArrayAs ba# i#) of (LE (I32# x#)) -> LE (I# x#)+#else+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (I# x#)) = writeWord8ArrayAs mba# i# (LE (I64# x#))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, LE (I64# x#) #) = readWord8ArrayAs mba# i# s0 in (# s1, LE (I# x#) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = case (indexWord8ArrayAs ba# i#) of (LE (I64# x#)) -> LE (I# x#)+#endif++instance UnalignedAccess (BE Int) where+#if SIZEOF_HSWORD == 4+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (I# x#)) = writeWord8ArrayAs mba# i# (BE (I32# x#))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, BE (I32# x#) #) = readWord8ArrayAs mba# i# s0 in (# s1, BE (I# x#) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = case (indexWord8ArrayAs ba# i#) of (BE (I32# x#)) -> BE (I# x#)+#else+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (I# x#)) = writeWord8ArrayAs mba# i# (BE (I64# x#))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, BE (I64# x#) #) = readWord8ArrayAs mba# i# s0 in (# s1, BE (I# x#) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = case (indexWord8ArrayAs ba# i#) of (BE (I64# x#)) -> BE (I# x#)+#endif++--------------------------------------------------------------------------------++instance UnalignedAccess Float where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (F# x#) = writeWord8ArrayAsFloat# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsFloat# mba# i# s0 in (# s1, F# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = F# (indexWord8ArrayAsFloat# ba# i#)++instance UnalignedAccess (LE Float) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (F# x#)) =+        writeWord8ArrayAs mba# i# (LE (W32# (stgFloatToWord32 x#)))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, LE (W32# x#) #) = readWord8ArrayAs mba# i# s0+        in (# s1, LE (F# (stgWord32ToFloat x#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let LE (W32# x#) = indexWord8ArrayAs ba# i#+        in LE (F# (stgWord32ToFloat x#))+#else+    USE_HOST_IMPL(LE)+#endif++instance UnalignedAccess (BE Float) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    USE_HOST_IMPL(BE)+#else+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (F# x#)) =+        writeWord8ArrayAs mba# i# (BE (W32# (stgFloatToWord32 x#)))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, BE (W32# x#) #) = readWord8ArrayAs mba# i# s0+        in (# s1, BE (F# (stgWord32ToFloat x#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let BE (W32# x#) = indexWord8ArrayAs ba# i#+        in BE (F# (stgWord32ToFloat x#))+#endif++--------------------------------------------------------------------------------++instance UnalignedAccess Double where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (D# x#) = writeWord8ArrayAsDouble# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsDouble# mba# i# s0 in (# s1, D# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = D# (indexWord8ArrayAsDouble# ba# i#)++instance UnalignedAccess (LE Double) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 8+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (D# x#)) =+        writeWord8ArrayAs mba# i# (LE (W64# (stgDoubleToWord64 x#)))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, LE (W64# x#) #) = readWord8ArrayAs mba# i# s0+        in (# s1, LE (D# (stgWord64ToDouble x#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let LE (W64# x#) = indexWord8ArrayAs ba# i#+        in LE (D# (stgWord64ToDouble x#))+#else+    USE_HOST_IMPL(LE)+#endif++instance UnalignedAccess (BE Double) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    USE_HOST_IMPL(BE)+#else+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (D# x#)) =+        writeWord8ArrayAs mba# i# (BE (W64# (stgDoubleToWord64 x#)))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, BE (W64# x#) #) = readWord8ArrayAs mba# i# s0+        in (# s1, BE (D# (stgWord64ToDouble x#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let BE (W64# x#) = indexWord8ArrayAs ba# i#+        in BE (D# (stgWord64ToDouble x#))+#endif++--------------------------------------------------------------------------------++instance UnalignedAccess Char where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (C# x#) = writeWord8ArrayAsWideChar# mba# i# x#+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, x# #) = readWord8ArrayAsWideChar# mba# i# s0 in (# s1, C# x# #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# = C# (indexWord8ArrayAsWideChar# ba# i#)++instance UnalignedAccess (LE Char) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (LE (C# x#)) =+        writeWord8ArrayAs mba# i# (LE (I32# (ord# x#)))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, LE (I32# x#) #) = readWord8ArrayAs mba# i# s0+        in (# s1, LE (C# (chr# x#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let LE (I32# x#) = indexWord8ArrayAs ba# i#+        in LE (C# (chr# x#))+#else+    USE_HOST_IMPL(LE)+#endif++instance UnalignedAccess (BE Char) where+    {-# INLINE unalignedSize #-}+    unalignedSize = UnalignedSize 4+#if defined(WORDS_BIGENDIAN) || defined(USE_SHIFT)+    USE_HOST_IMPL(BE)+#else+    {-# INLINE writeWord8ArrayAs #-}+    writeWord8ArrayAs mba# i# (BE (C# x#)) =+        writeWord8ArrayAs mba# i# (BE (I32# (ord# x#)))+    {-# INLINE readWord8ArrayAs #-}+    readWord8ArrayAs mba# i# s0 =+        let !(# s1, BE (I32# x#) #) = readWord8ArrayAs mba# i# s0+        in (# s1, BE (C# (chr# x#)) #)+    {-# INLINE indexWord8ArrayAs #-}+    indexWord8ArrayAs ba# i# =+        let BE (I32# x#) = indexWord8ArrayAs ba# i#+        in BE (C# (chr# x#))+#endif+
+ Std/Data/PrimIORef.hs view
@@ -0,0 +1,196 @@+{-# LANGUAGE MagicHash, UnboxedTuples #-}++{-|+Module      :  Std.Data.PrimIORef+Copyright   :  (c) Dong Han 2017~2019+License     :  BSD-style++Maintainer  :  winterland1989@gmail.com+Stability   :  experimental+Portability :  portable++This package provide fast unboxed references for IO monad and atomic operations for 'Counter' type. Unboxed reference is implemented using single cell MutableByteArray s to eliminate indirection overhead which MutVar# s a carry, on the otherhand unboxed reference only support limited type(instances of Prim class).++Atomic operations on 'Counter' type are implemented using fetch-and-add primitives, which is much faster than a CAS loop(@atomicModifyIORef@). Beside basic atomic counter usage, you can also leverage idempotence of @and 0@, @or (-1)@ to make a concurrent flag.+-}++++module Std.Data.PrimIORef+  ( -- * Unboxed IO references+    PrimIORef+  , newPrimIORef+  , readPrimIORef+  , writePrimIORef+  , modifyPrimIORef+    -- * Atomic operations for @PrimIORef Int@+  , Counter+  , newCounter+    -- ** return value BEFORE atomic operation+  , atomicAddCounter+  , atomicSubCounter+  , atomicAndCounter+  , atomicNandCounter+  , atomicOrCounter+  , atomicXorCounter+    -- ** return value AFTER atomic operation+  , atomicAddCounter'+  , atomicSubCounter'+  , atomicAndCounter'+  , atomicNandCounter'+  , atomicOrCounter'+  , atomicXorCounter'+    -- ** without returning+  , atomicAddCounter_+  , atomicSubCounter_+  , atomicAndCounter_+  , atomicNandCounter_+  , atomicOrCounter_+  , atomicXorCounter_+  ) where++import Data.Primitive.Types+import Data.Primitive.ByteArray+import GHC.Prim+import GHC.Types+import GHC.ST+import GHC.IO(stToIO)+import Std.Data.PrimSTRef.Base++-- | A mutable variable in the IO monad which can hold an instance of 'Prim'.+newtype PrimIORef a = PrimIORef (PrimSTRef RealWorld a)++-- | Build a new 'PrimIORef'+newPrimIORef :: Prim a => a -> IO (PrimIORef a)+newPrimIORef init = PrimIORef `fmap` stToIO (newPrimSTRef init)+{-# INLINE newPrimIORef #-}++-- | Read the value of an 'PrimIORef'+readPrimIORef :: Prim a => PrimIORef a -> IO a+readPrimIORef (PrimIORef ref) = stToIO (readPrimSTRef ref)+{-# INLINE readPrimIORef #-}++-- | Write a new value into an 'PrimIORef'+writePrimIORef :: Prim a => PrimIORef a -> a -> IO ()+writePrimIORef (PrimIORef ref) x = stToIO (writePrimSTRef ref x)+{-# INLINE writePrimIORef #-}++-- | Mutate the contents of an 'IORef'.+--+--  Unboxed reference is always strict on the value it hold.+modifyPrimIORef :: Prim a => PrimIORef a -> (a -> a) -> IO ()+modifyPrimIORef ref f = readPrimIORef ref >>= writePrimIORef ref . f+{-# INLINE modifyPrimIORef #-}++-- | Alias for 'PrimIORef Int' which support several atomic operations.+type Counter = PrimIORef Int++-- | Build a new 'Counter'+newCounter :: Int -> IO Counter+newCounter = newPrimIORef+{-# INLINE newCounter #-}++-- | Atomically add a 'Counter', return the value AFTER added.+atomicAddCounter' :: Counter -> Int -> IO Int+atomicAddCounter' (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchAddIntArray# mba# 0# x# s1# in (# s2#, (I# (res# +# x#)) #)++-- | Atomically add a 'Counter', return the value BEFORE added.+atomicAddCounter :: Counter -> Int -> IO Int+atomicAddCounter (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchAddIntArray# mba# 0# x# s1# in (# s2#, (I# res#) #)++-- | Atomically add a 'Counter'.+atomicAddCounter_ :: Counter -> Int -> IO ()+atomicAddCounter_ (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, _ #) = fetchAddIntArray# mba# 0# x# s1# in (# s2#, () #)+{-# INLINE atomicAddCounter_ #-}+++-- | Atomically sub a 'Counter', return the value AFTER subbed.+atomicSubCounter' :: Counter -> Int -> IO Int+atomicSubCounter' (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchSubIntArray# mba# 0# x# s1# in (# s2#, (I# (res# -# x#)) #)++-- | Atomically sub a 'Counter', return the value BEFORE subbed.+atomicSubCounter :: Counter -> Int -> IO Int+atomicSubCounter (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchSubIntArray# mba# 0# x# s1# in (# s2#, (I# res#) #)++-- | Atomically sub a 'Counter'+atomicSubCounter_ :: Counter -> Int -> IO ()+atomicSubCounter_ (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, _ #) = fetchSubIntArray# mba# 0# x# s1# in (# s2#, () #)+{-# INLINE atomicSubCounter_ #-}++-- | Atomically and a 'Counter', return the value AFTER anded.+atomicAndCounter' :: Counter -> Int -> IO Int+atomicAndCounter' (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchAndIntArray# mba# 0# x# s1# in (# s2#, (I# (res# `andI#` x#)) #)+{-# INLINE atomicAndCounter' #-}++-- | Atomically and a 'Counter', return the value BEFORE anded.+atomicAndCounter :: Counter -> Int -> IO Int+atomicAndCounter (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchAndIntArray# mba# 0# x# s1# in (# s2#, (I# res#) #)+{-# INLINE atomicAndCounter #-}++-- | Atomically and a 'Counter'+atomicAndCounter_ :: Counter -> Int -> IO ()+atomicAndCounter_ (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchAndIntArray# mba# 0# x# s1# in (# s2#, () #)+{-# INLINE atomicAndCounter_ #-}++-- | Atomically nand a 'Counter', return the value AFTER nanded.+atomicNandCounter' :: Counter -> Int -> IO Int+atomicNandCounter' (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchNandIntArray# mba# 0# x# s1# in (# s2#, (I# (notI# (res# `andI#` x#))) #)+{-# INLINE atomicNandCounter' #-}++-- | Atomically nand a 'Counter', return the value BEFORE nanded.+atomicNandCounter :: Counter -> Int -> IO Int+atomicNandCounter (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchNandIntArray# mba# 0# x# s1# in (# s2#, (I# res#) #)+{-# INLINE atomicNandCounter #-}++-- | Atomically nand a 'Counter'+atomicNandCounter_ :: Counter -> Int -> IO ()+atomicNandCounter_ (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchNandIntArray# mba# 0# x# s1# in (# s2#, () #)+{-# INLINE atomicNandCounter_ #-}++-- | Atomically or a 'Counter', return the value AFTER ored.+atomicOrCounter' :: Counter -> Int -> IO Int+atomicOrCounter' (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchOrIntArray# mba# 0# x# s1# in (# s2#, (I# (res# `orI#` x#)) #)+{-# INLINE atomicOrCounter' #-}++-- | Atomically or a 'Counter', return the value BEFORE ored.+atomicOrCounter :: Counter -> Int -> IO Int+atomicOrCounter (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchOrIntArray# mba# 0# x# s1# in (# s2#, (I# res#) #)+{-# INLINE atomicOrCounter #-}++-- | Atomically or a 'Counter'+atomicOrCounter_ :: Counter -> Int -> IO ()+atomicOrCounter_ (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchOrIntArray# mba# 0# x# s1# in (# s2#, () #)+{-# INLINE atomicOrCounter_ #-}++-- | Atomically xor a 'Counter', return the value AFTER xored.+atomicXorCounter' :: Counter -> Int -> IO Int+atomicXorCounter' (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchXorIntArray# mba# 0# x# s1# in (# s2#, (I# (res# `xorI#` x#)) #)+{-# INLINE atomicXorCounter' #-}++-- | Atomically xor a 'Counter', return the value BEFORE xored.+atomicXorCounter :: Counter -> Int -> IO Int+atomicXorCounter (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchXorIntArray# mba# 0# x# s1# in (# s2#, (I# res#) #)+{-# INLINE atomicXorCounter #-}++-- | Atomically xor a 'Counter'+atomicXorCounter_ :: Counter -> Int -> IO ()+atomicXorCounter_ (PrimIORef (PrimSTRef (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->+    let (# s2#, res# #) = fetchXorIntArray# mba# 0# x# s1# in (# s2#, () #)+{-# INLINE atomicXorCounter_ #-}
+ Std/Data/PrimSTRef.hs view
@@ -0,0 +1,22 @@+{-|+Module      :  Std.Data.PrimSTRef+Copyright   :  (c) Dong Han 2017~2019+License     :  BSD-style++Maintainer  :  winterland1989@gmail.com+Stability   :  experimental+Portability :  portable++This module provide fast unboxed references for ST monad. Unboxed reference is implemented using single cell MutableByteArray s to eliminate indirection overhead which MutVar# s a carry, on the otherhand unboxed reference only support limited type(instances of Prim class).+-}++module Std.Data.PrimSTRef+  ( -- * Unboxed ST references+    PrimSTRef+  , newPrimSTRef+  , readPrimSTRef+  , writePrimSTRef+  , modifyPrimSTRef+  ) where++import Std.Data.PrimSTRef.Base
+ Std/Data/PrimSTRef/Base.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE MagicHash #-}++{-|+Module      :  Std.Data.PrimSTRef.Base+Copyright   :  (c) Dong Han 2017~2019+License     :  BSD-style++Maintainer  :  winterland1989@gmail.com+Stability   :  experimental+Portability :  portable++Internal module for 'Std.Data.PrimSTRef' and 'Std.Data.PrimIORef'.+-}+++module Std.Data.PrimSTRef.Base+  ( -- * Unboxed ST references+    PrimSTRef(..)+  , newPrimSTRef+  , readPrimSTRef+  , writePrimSTRef+  , modifyPrimSTRef+  ) where++import Data.Primitive.Types+import Data.Primitive.ByteArray+import GHC.Prim+import GHC.ST+import GHC.Types++-- | A mutable variable in the ST monad which can hold an instance of 'Prim'.+--+newtype PrimSTRef s a = PrimSTRef (MutableByteArray s)++-- | Build a new 'PrimSTRef'+--+newPrimSTRef :: Prim a => a -> ST s (PrimSTRef s a)+newPrimSTRef init = do+     mba <- newByteArray (I# (sizeOf# init))+     writeByteArray mba 0 init+     return (PrimSTRef mba)+{-# INLINE newPrimSTRef #-}++-- | Read the value of an 'PrimSTRef'+--+readPrimSTRef :: Prim a => PrimSTRef s a -> ST s a+readPrimSTRef (PrimSTRef mba) = readByteArray mba 0+{-# INLINE readPrimSTRef #-}++-- | Write a new value into an 'PrimSTRef'+--+writePrimSTRef :: Prim a => PrimSTRef s a -> a -> ST s ()+writePrimSTRef (PrimSTRef mba) x = writeByteArray mba 0 x+{-# INLINE writePrimSTRef #-}++-- | Mutate the contents of an 'PrimSTRef'.+--+--  Unboxed reference is always strict on the value it hold.+--+modifyPrimSTRef :: Prim a => PrimSTRef s a -> (a -> a) -> ST s ()+modifyPrimSTRef ref f = readPrimSTRef ref >>= writePrimSTRef ref . f+{-# INLINE modifyPrimSTRef #-}
+ Std/Data/Text.hs view
@@ -0,0 +1,149 @@+{-# LANGUAGE MagicHash, UnboxedTuples #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE UnliftedFFITypes #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE PatternSynonyms #-}++{-|+Module      : Std.Data.Text+Description : Unicode text processing+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++A 'Text' simply wraps a 'Bytes' that are UTF-8 encoded codepoints, you can use 'validate' \/ 'validateMaybe' to construct a 'Text'.++-}++module Std.Data.Text (+  -- * Text type+    Text, getUTF8Bytes+  , validate, validateMaybe+  -- * Basic creating+  , empty, singleton, copy+  -- * Building text+  , replicate, cycleN+  -- * Conversion between list+  , pack, packN, packR, packRN+  , unpack, unpackR+  -- * Conversion between codepoint vector+  , fromVector+  , toVector+  -- * Basic interface+  , null+  , length+  , append+  , map', imap'+  , foldl', ifoldl'+  , foldr', ifoldr'+  , concat, concatMap+    -- ** Special folds+  , count, all, any+  -- * Searching by equality+  , elem, notElem+  -- * Slice manipulation+  , cons, snoc+  , uncons, unsnoc+  , headMaybe, tailMayEmpty+  , lastMaybe, initMayEmpty+  , inits, tails+  , take, drop, takeR, dropR+  , slice+  , splitAt+  , takeWhile, takeWhileR, dropWhile, dropWhileR, dropAround+  , break, span+  , breakR, spanR, breakOn, breakOnAll+  , group, groupBy+  , stripPrefix, stripSuffix+  , split, splitWith, splitOn+  , isPrefixOf, isSuffixOf, isInfixOf+  , commonPrefix+  , words, lines, unwords, unlines+  , padLeft, padRight+  -- * Transform+  , reverse+  , intersperse+  , intercalate+  , intercalateElem+  , transpose+  -- * Search+  -- ** element-wise search+  , find, findR+  , filter, partition+  -- * Unicode processing+    -- ** normalization+  , NormalizationResult(..), NormalizeMode(..)+  , isNormalized, isNormalizedTo, normalize, normalizeTo+    -- ** Case conversion+    -- $case+  , Locale, localeDefault, localeLithuanian, localeTurkishAndAzeriLatin+  , caseFold, caseFoldWith, toLower, toLowerWith, toUpper, toUpperWith, toTitle, toTitleWith+    -- ** Unicode category+  , isCategory, spanCategory+  , Category+  , categoryLetterUppercase+  , categoryLetterLowercase+  , categoryLetterTitlecase+  , categoryLetterOther+  , categoryLetter+  , categoryCaseMapped++  , categoryMarkNonSpacing+  , categoryMarkSpacing+  , categoryMarkEnclosing+  , categoryMark++  , categoryNumberDecimal+  , categoryNumberLetter+  , categoryNumberOther+  , categoryNumber++  , categoryPunctuationConnector+  , categoryPunctuationDash+  , categoryPunctuationOpen+  , categoryPunctuationClose+  , categoryPunctuationInitial+  , categoryPunctuationFinal+  , categoryPunctuationOther+  , categoryPunctuation++  , categorySymbolMath+  , categorySymbolCurrency+  , categorySymbolModifier+  , categorySymbolOther+  , categorySymbol++  , categorySeparatorSpace+  , categorySeparatorLine+  , categorySeparatorParagraph+  , categorySeparator+  , categoryControl+  , categoryFormat+  , categorySurrogate+  , categoryPrivateUse+  , categoryUnassigned+  , categoryCompatibility+  , categoryIgnoreGraphemeCluste+  , categoryIscntrl++  , categoryIsprint+  , categoryIsspace+  , categoryIsblank+  , categoryIsgraph+  , categoryIspunct+  , categoryIsalnum+  , categoryIsalpha+  , categoryIsupper+  , categoryIslower+  , categoryIsdigit+  , categoryIsxdigit+ ) where++import           Std.Data.Text.Base+import           Std.Data.Text.Search+import           Std.Data.Text.Extra+import           Prelude                  ()++
+ Std/Data/Text/Base.hs view
@@ -0,0 +1,987 @@+{-# LANGUAGE MagicHash, UnboxedTuples #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE UnliftedFFITypes #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE CPP #-}++{-|+Module      : Std.Data.Text.Base+Description : Unicode text processing+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++A 'Text' wrap a 'Bytes' which will be interpreted using UTF-8 encoding. User should always use 'validate' to construt a 'Text' (instead of using construtor directly or coercing), otherwise illegal UTF-8 encoded codepoints will cause undefined behaviours.++-}++module Std.Data.Text.Base (+  -- * Text type+    Text(..)+  -- * Building text+  , validate+  , validateMaybe+  , replicate+  , cycleN+  , indexMaybe, charByteIndex, indexMaybeR, charByteIndexR+  -- * Basic creating+  , empty, singleton, copy+  -- * Conversion between list+  , pack, packN, packR, packRN+  , unpack, unpackR+  -- * Conversion between codepoint vector+  , fromVector+  , toVector+  -- * Basic interface+  , null+  , length+  , append+  , map', imap'+  , foldl', ifoldl'+  , foldr', ifoldr'+  , concat, concatMap+    -- ** Special folds+  , count, all, any+    -- ** normalization+  , NormalizationResult(..), NormalizeMode(..)+  , isNormalized, isNormalizedTo, normalize, normalizeTo+    -- ** Case conversion+    -- $case+  , Locale, localeDefault, localeLithuanian, localeTurkishAndAzeriLatin+  , caseFold, caseFoldWith, toLower, toLowerWith, toUpper, toUpperWith, toTitle, toTitleWith+    -- ** Unicode category+  , isCategory, spanCategory+  , Category+  , categoryLetterUppercase+  , categoryLetterLowercase+  , categoryLetterTitlecase+  , categoryLetterOther+  , categoryLetter+  , categoryCaseMapped++  , categoryMarkNonSpacing+  , categoryMarkSpacing+  , categoryMarkEnclosing+  , categoryMark++  , categoryNumberDecimal+  , categoryNumberLetter+  , categoryNumberOther+  , categoryNumber++  , categoryPunctuationConnector+  , categoryPunctuationDash+  , categoryPunctuationOpen+  , categoryPunctuationClose+  , categoryPunctuationInitial+  , categoryPunctuationFinal+  , categoryPunctuationOther+  , categoryPunctuation++  , categorySymbolMath+  , categorySymbolCurrency+  , categorySymbolModifier+  , categorySymbolOther+  , categorySymbol++  , categorySeparatorSpace+  , categorySeparatorLine+  , categorySeparatorParagraph+  , categorySeparator+  , categoryControl+  , categoryFormat+  , categorySurrogate+  , categoryPrivateUse+  , categoryUnassigned+  , categoryCompatibility+  , categoryIgnoreGraphemeCluste+  , categoryIscntrl++  , categoryIsprint+  , categoryIsspace+  , categoryIsblank+  , categoryIsgraph+  , categoryIspunct+  , categoryIsalnum+  , categoryIsalpha+  , categoryIsupper+  , categoryIslower+  , categoryIsdigit+  , categoryIsxdigit+  -- * Misc+  , c_utf8_validate_ba+  , c_utf8_validate_addr+ ) where++import           Control.DeepSeq+import           Control.Monad.ST+import           Control.Monad+import           Data.Bits+import           Data.Char          hiding (toLower, toUpper, toTitle)+import           Data.Foldable            (foldlM)+import           Data.Hashable            (Hashable(..))+import qualified Data.List                as List+import           Data.Primitive.PrimArray+import           Data.Typeable+import           Data.String              (IsString(..))+import           Data.Word+import           Foreign.C.Types          (CSize(..))+import           GHC.Exts                 (build)+import           GHC.Ptr+import           GHC.Types+import           GHC.Stack+import           GHC.CString              (unpackCString#)+import           Std.Data.Array+import           Std.Data.Text.UTF8Codec+import           Std.Data.Text.UTF8Rewind+import           Std.Data.Vector.Base     (Bytes, PrimVector(..), c_strlen)+import qualified Std.Data.Vector.Base     as V+import qualified Std.Data.Vector.Extra    as V+import qualified Std.Data.Vector.Search   as V+import           Std.Foreign.PrimArray+import           System.IO.Unsafe (unsafeDupablePerformIO)++import           Prelude                       hiding (concat, concatMap,+                                                elem, notElem, null, length, map,+                                                foldl, foldl1, foldr, foldr1,+                                                maximum, minimum, product, sum,+                                                all, any, replicate, traverse)++-- | 'Text' represented as UTF-8 encoded 'Bytes'+--+newtype Text = Text+    { getUTF8Bytes :: Bytes -- ^ Extract UTF-8 encoded 'Bytes' from 'Text'+    }++instance Eq Text where+    Text b1 == Text b2 = b1 == b2+    {-# INLINE (==) #-}++instance Ord Text where+    Text b1 `compare` Text b2 = b1 `compare` b2 -- UTF-8 encoding property+    {-# INLINE compare #-}++instance Show Text where+    showsPrec p t = showsPrec p (unpack t)++instance Read Text where+    readsPrec p str = [ (pack x, y) | (x, y) <- readsPrec p str ]++instance NFData Text where+    rnf (Text bs) = rnf bs++instance Hashable Text where+    {-# INLINE hashWithSalt #-}+    hashWithSalt salt (Text bs) = hashWithSalt salt bs++instance IsString Text where+    {-# INLINE fromString #-}+    fromString = pack++packStringAddr :: Addr# -> Text+{-# INLINABLE packStringAddr #-}+packStringAddr addr# = validateAndCopy addr#+  where+    len = fromIntegral . unsafeDupablePerformIO $ c_strlen addr#+    valid = unsafeDupablePerformIO $ c_utf8_validate_addr addr# len+    validateAndCopy addr#+        | valid == 0 = pack (unpackCString# addr#)+        | otherwise  = runST $ do+            marr <- newPrimArray len+            copyPtrToMutablePrimArray marr 0 (Ptr addr#) len+            arr <- unsafeFreezePrimArray marr+            return $ Text (PrimVector arr 0 len)++-- | /O(n)/ Get the nth codepoint from 'Text'.+indexMaybe :: Text -> Int -> Maybe Char+{-# INLINABLE indexMaybe #-}+indexMaybe (Text (V.PrimVector ba s l)) n+    | n < 0 = Nothing+    | otherwise = go s 0+  where+    !end = s + l+    go !i !j+        | i >= end = Nothing+        | j >= n = let !c = decodeChar_ ba i in Just c+        | otherwise =+            let l = decodeCharLen ba i in go (i+l) (j+1)++-- | /O(n)/ Find the nth codepoint's byte index (pointing to the nth char's begining byte).+--+-- The index is only meaningful to the whole byte slice, if there's less than n codepoints,+-- the index will point to next byte after the end.+charByteIndex :: Text -> Int -> Int+{-# INLINABLE charByteIndex #-}+charByteIndex (Text (V.PrimVector ba s l)) n+    | n < 0 = s+    | otherwise = go s 0+  where+    !end = s + l+    go !i !j+        | i >= end = i+        | j >= n = i+        | otherwise =+            let l = decodeCharLen ba i in go (i+l) (j+1)++-- | /O(n)/ Get the nth codepoint from 'Text' counting from the end.+indexMaybeR :: Text -> Int -> Maybe Char+{-# INLINABLE indexMaybeR #-}+indexMaybeR (Text (V.PrimVector ba s l)) n+    | n < 0 = Nothing+    | otherwise = go (s+l-1) 0+  where+    go !i !j+        | i < s = Nothing+        | j >= n = let !c = decodeCharReverse_ ba i in Just c+        | otherwise =+            let l = decodeCharLenReverse ba i in go (i-l) (j+1)++-- | /O(n)/ Find the nth codepoint's byte index from the end+-- (pointing to the previous char's ending byte).+--+-- The index is only meaningful to the whole byte slice, if there's less than n codepoints,+-- the index will point to previous byte before the start.+charByteIndexR :: Text -> Int -> Int+{-# INLINABLE charByteIndexR #-}+charByteIndexR (Text (V.PrimVector ba s l)) n+    | n < 0 = s+l+    | otherwise = go (s+l-1) 0+  where+    go !i !j+        | i < s = i+        | j >= n = i+        | otherwise =+            let l = decodeCharLenReverse ba i in go (i-l) (j+1)++--------------------------------------------------------------------------------++-- | /O(n)/ Validate a sequence of bytes is UTF-8 encoded.+--+-- Throw error in case of invalid codepoint.+--+validate :: HasCallStack => Bytes -> Text+{-# INLINE validate #-}+validate bs@(V.PrimVector (PrimArray ba#) (I# s#) l@(I# l#))+    | l == 0 = Text bs+    | c_utf8_validate_ba ba# s# l# > 0 = Text bs+    | otherwise = error "invalid UTF8 bytes"++validateMaybe :: Bytes -> Maybe Text+{-# INLINE validateMaybe #-}+validateMaybe bs@(V.PrimVector (PrimArray ba#) (I# s#) l@(I# l#))+    | l == 0 = Just (Text bs)+    | c_utf8_validate_ba ba# s# l# > 0 = Just (Text bs)+    | otherwise = Nothing++foreign import ccall unsafe "text.h utf8_validate"+    c_utf8_validate_ba :: BA# Word8 -> Int# -> Int# -> Int+foreign import ccall unsafe "text.h utf8_validate_addr"+    c_utf8_validate_addr :: Addr# -> Int -> IO Int++--------------------------------------------------------------------------------++-- | /O(n)/ Convert a string into a text+--+-- Alias for @'packN' 'defaultInitSize'@.+pack :: String -> Text+pack = packN V.defaultInitSize+{-# INLINE CONLIKE [1] pack #-}+{-# RULES+    "pack/packStringAddr" forall addr . pack (unpackCString# addr) = packStringAddr addr+  #-}++-- | /O(n)/ Convert a list into a text with an approximate size(in bytes, not codepoints).+--+-- If the encoded bytes length is larger than the size given, we simply double the buffer size+-- and continue building.+--+-- This function is a /good consumer/ in the sense of build/foldr fusion.+--+packN :: Int -> String -> Text+{-# INLINE packN #-}+packN n0 = \ ws0 ->+    Text (V.create' (max 4 n0) (\ marr -> foldlM go (V.IPair 0 marr) ws0))+  where+    -- It's critical that this function get specialized and unboxed+    -- Keep an eye on its core!+    go :: V.IPair (MutablePrimArray s Word8) -> Char -> ST s (V.IPair (MutablePrimArray s Word8))+    go (V.IPair i marr) !c = do+        siz <- getSizeofMutablePrimArray marr+        if i < siz - 3  -- we need at least 4 bytes for safety+        then do+            i' <- encodeChar marr i c+            return (V.IPair i' marr)+        else do+            let !siz' = siz `shiftL` 1+            !marr' <- resizeMutablePrimArray marr siz'+            i' <- encodeChar marr' i c+            return (V.IPair i' marr')++-- | /O(n)/ Alias for @'packRN' 'defaultInitSize'@.+--+packR :: String -> Text+{-# INLINE packR #-}+packR = packRN V.defaultInitSize++-- | /O(n)/ 'packN' in reverse order.+--+-- This function is a /good consumer/ in the sense of build/foldr fusion.+--+packRN :: Int -> String -> Text+{-# INLINE packRN #-}+packRN n0 = \ ws0 -> runST (do let n = max 4 n0+                               marr <- newArr n+                               (V.IPair i marr') <- foldM go (V.IPair n marr) ws0+                               ba <- unsafeFreezeArr marr'+                               return $! Text (V.fromArr ba i (sizeofArr ba-i))+                           )+  where+    go :: V.IPair (MutablePrimArray s Word8) -> Char -> ST s (V.IPair (MutablePrimArray s Word8))+    go (V.IPair i marr) !c = do+        n <- sizeofMutableArr marr+        let l = encodeCharLength c+        if i >= l+        then do encodeChar marr (i-l) c+                return (V.IPair (i-l) marr)+        else do let !n' = n `shiftL` 1  -- double the buffer+                !marr' <- newArr n'+                copyMutableArr marr' (n+i) marr i (n-i)+                let i' = n+i-l+                encodeChar marr' i' c+                return (V.IPair i' marr')++-- | /O(n)/ Convert text to a char list.+--+-- Unpacking is done lazily. i.e. we will retain reference to the array until all element are consumed.+--+-- This function is a /good producer/ in the sense of build/foldr fusion.+unpack :: Text -> String+{-# INLINE [1] unpack #-}+unpack (Text (V.PrimVector ba s l)) = go s+  where+    !end = s + l+    go !idx+        | idx >= end = []+        | otherwise = let (# c, i #) = decodeChar ba idx in c : go (idx + i)++unpackFB :: Text -> (Char -> a -> a) -> a -> a+{-# INLINE [0] unpackFB #-}+unpackFB (Text (V.PrimVector ba s l)) k z = go s+  where+    !end = s + l+    go !idx+        | idx >= end = z+        | otherwise = let (# c, i #) = decodeChar ba idx in c `k` go (idx + i)++{-# RULES+"unpack" [~1] forall t . unpack t = build (\ k z -> unpackFB t k z)+"unpackFB" [1] forall t . unpackFB t (:) [] = unpack t+ #-}++-- | /O(n)/ Convert text to a list in reverse order.+--+-- This function is a /good producer/ in the sense of build/foldr fusion.+unpackR :: Text -> String+{-# INLINE [1] unpackR #-}+unpackR (Text (V.PrimVector ba s l)) = go (s+l-1)+  where+    go !idx+        | idx < s = []+        | otherwise = let (# c, i #) = decodeCharReverse ba idx in c : go (idx - i)++unpackRFB :: Text -> (Char -> a -> a) -> a -> a+{-# INLINE [0] unpackRFB #-}+unpackRFB (Text (V.PrimVector ba s l)) k z = go (s+l-1)+  where+    go !idx+        | idx < s = z+        | otherwise = let (# c, i #) = decodeCharReverse ba idx in c `k` go (idx - i)++{-# RULES+"unpackR" [~1] forall t . unpackR t = build (\ k z -> unpackRFB t k z)+"unpackRFB" [1] forall t . unpackRFB t (:) [] = unpackR t+ #-}++-- | /O(1)/. Single char text.+singleton :: Char -> Text+{-# INLINABLE singleton #-}+singleton c = Text $ V.createN 4 $ \ marr -> encodeChar marr 0 c++-- | /O(1)/. Empty text.+empty :: Text+{-# INLINABLE empty #-}+empty = Text V.empty++-- | /O(n)/. Copy a text from slice.+copy :: Text -> Text+{-# INLINE copy #-}+copy (Text bs) = Text (V.copy bs)++--------------------------------------------------------------------------------+-- * Basic interface++-- | /O(m+n)/+--+-- There's no need to guard empty vector because we guard them for you, so+-- appending empty text are no-ops.+append :: Text -> Text -> Text+append ta tb = Text ( getUTF8Bytes ta `V.append` getUTF8Bytes tb )+{-# INLINE append #-}++-- | /O(1)/ Test whether a text is empty.+null :: Text -> Bool+{-# INLINABLE null #-}+null (Text bs) = V.null bs++-- |  /O(n)/ The char length of a text.+length :: Text -> Int+{-# INLINABLE length #-}+length (Text (V.PrimVector ba s l)) = go s 0+  where+    !end = s + l+    go !i !acc | i >= end = acc+               | otherwise = let j = decodeCharLen ba i in go (i+j) (1+acc)++--------------------------------------------------------------------------------+-- * Transformations+--+-- | /O(n)/ 'map' @f@ @t@ is the 'Text' obtained by applying @f@ to+-- each char of @t@. Performs replacement on invalid scalar values.+map' :: (Char -> Char) -> Text -> Text+{-# INLINE map' #-}+map' f (Text (V.PrimVector arr s l)) | l == 0 = empty+                                     | otherwise = Text (V.create' (l+3) (go s 0))+  where+    end = s + l+    -- the 3 bytes buffer is here for optimizing ascii mapping+    -- we do resize if less than 4 bytes left when building+    -- to save us from pre-checking encoding char length everytime+    go :: Int -> Int -> MutablePrimArray s Word8 -> ST s (V.IPair (MutablePrimArray s Word8))+    go !i !j !marr+        | i >= end = return (V.IPair j marr)+        | otherwise = do+            let (# c, d #) = decodeChar arr i+            j' <- encodeChar marr j (f c)+            let !i' = i + d+            siz <- sizeofMutableArr marr+            if  j' < siz - 3+            then go i' j' marr+            else do+                let !siz' = siz `shiftL` 1+                !marr' <- resizeMutablePrimArray marr siz'+                go i' j' marr'++-- | Strict mapping with index.+imap' :: (Int -> Char -> Char) -> Text -> Text+{-# INLINE imap' #-}+imap' f (Text (V.PrimVector arr s l)) | l == 0 = empty+                                      | otherwise = Text (V.create' (l+3) (go s 0 0))+  where+    end = s + l+    go :: Int -> Int -> Int -> MutablePrimArray s Word8 -> ST s (V.IPair (MutablePrimArray s Word8))+    go !i !j !k !marr+        | i >= end = return (V.IPair j marr)+        | otherwise = do+            let (# c, d #) = decodeChar arr i+            j' <- encodeChar marr j (f k c)+            let !i' = i + d+                !k' = k + 1+            siz <- sizeofMutableArr marr+            if  j' < siz - 3+            then go i' j' k' marr+            else do+                let !siz' = siz `shiftL` 1+                !marr' <- resizeMutablePrimArray marr siz'+                go i' j' k' marr'++--------------------------------------------------------------------------------+--+-- Strict folds+--++-- | Strict left to right fold.+foldl' :: (b -> Char -> b) -> b -> Text -> b+{-# INLINE foldl' #-}+foldl' f z (Text (V.PrimVector arr s l)) = go z s+  where+    !end = s + l+    -- tail recursive; traverses array left to right+    go !acc !i | i < end  = case decodeChar arr i of+                                (# x, d #) -> go (f acc x) (i + d)+               | otherwise = acc++-- | Strict left to right fold with index.+ifoldl' :: (b -> Int ->  Char -> b) -> b -> Text -> b+{-# INLINE ifoldl' #-}+ifoldl' f z (Text (V.PrimVector arr s l)) = go z s 0+  where+    !end = s + l+    go !acc !i !k | i < end  = case decodeChar arr i of+                                    (# x, d #) -> go (f acc k x) (i + d) (k + 1)+                  | otherwise = acc++-- | Strict right to left fold+foldr' :: (Char -> b -> b) -> b -> Text -> b+{-# INLINE foldr' #-}+foldr' f z (Text (V.PrimVector arr s l)) = go z (s+l-1)+  where+    -- tail recursive; traverses array right to left+    go !acc !i | i >= s    = case decodeCharReverse arr i of+                                (# x, d #) -> go (f x acc) (i - d)+               | otherwise = acc++-- | Strict right to left fold with index+--+-- NOTE: the index is counting from 0, not backwards+ifoldr' :: (Int -> Char -> b -> b) -> b -> Text -> b+{-# INLINE ifoldr' #-}+ifoldr' f z (Text (V.PrimVector arr s l)) = go z (s+l-1) 0+  where+    go !acc !i !k | i >= s    = case decodeCharReverse arr i of+                                    (# x, d #) -> go (f k x acc) (i - d) (k + 1)+                  | otherwise = acc+++-- | /O(n)/ Concatenate a list of text.+--+-- Note: 'concat' have to force the entire list to filter out empty text and calculate+-- the length for allocation.+concat :: [Text] -> Text+concat = Text . V.concat . coerce+{-# INLINE concat #-}++-- | Map a function over a text and concatenate the results+concatMap :: (Char -> Text) -> Text -> Text+{-# INLINE concatMap #-}+concatMap f = concat . foldr' ((:) . f) []++-- | /O(n)/ 'count' returns count of an element from a text.+count :: Char -> Text -> Int+{-# INLINE count #-}+count c (Text v)+    | encodeCharLength c == 1 = let w = V.c2w c in V.count w v+    | otherwise = let (Text pat) = singleton c+                  in List.length $ V.indices pat v False++-- | /O(n)/ Applied to a predicate and a text, 'any' determines+-- if any chars of the text satisfy the predicate.+any :: (Char -> Bool) -> Text -> Bool+{-# INLINE any #-}+any f (Text (V.PrimVector arr s l))+    | l <= 0    = False+    | otherwise = case decodeChar arr s of+                    (# x0, d #) -> go (f x0) (s+d)+  where+    !end = s+l+    go !acc !i | acc       = True+               | i >= end  = acc+               | otherwise = case decodeChar arr i of+                                (# x, d #) -> go (acc || f x) (i+d)++-- | /O(n)/ Applied to a predicate and text, 'all' determines+-- if all chars of the text satisfy the predicate.+all :: (Char -> Bool) -> Text -> Bool+{-# INLINE all #-}+all f (Text (V.PrimVector arr s l))+    | l <= 0    = True+    | otherwise = case decodeChar arr s of+                    (# x0, d #) -> go (f x0) (s+d)+  where+    !end = s+l+    go !acc !i | not acc   = False+               | i >= end  = acc+               | otherwise = case decodeChar arr i of+                                (# x, d #) -> go (acc && f x) (i+d)++--------------------------------------------------------------------------------+--+-- Building text++-- | /O(n)/ 'replicate' char n time.+--+replicate :: Int -> Char -> Text+{-# INLINE replicate #-}+replicate 0 _ = empty+replicate n c = Text (V.create siz (go 0))+  where+    !csiz = encodeCharLength c+    !siz = n * csiz+    go :: Int -> MutablePrimArray s Word8 -> ST s ()+    go 0 marr = encodeChar marr 0 c >> go csiz marr+    go i marr | i >= siz = return ()+              | otherwise = do copyChar' csiz marr i marr (i-csiz)+                               go (i+csiz) marr++-- | /O(n*m)/ 'cycleN' a text n times.+cycleN :: Int -> Text -> Text+{-# INLINE cycleN #-}+cycleN 0 _ = empty+cycleN n (Text v) = Text (V.cycleN n v)++--------------------------------------------------------------------------------+-- Convert between codepoint vector and text++-- | /O(n)/ convert from a char vector.+fromVector :: V.PrimVector Char -> Text+{-# INLINE fromVector #-}+fromVector (V.PrimVector arr s l) = Text (V.createN l (go s 0))+  where+    end = s+l+    go !i !j !marr+        | i >= l = return j+        | otherwise = do+            let c = indexPrimArray arr i+            j' <- encodeChar marr j c+            go (i+1) j' marr++-- | /O(n)/ convert to a char vector.+toVector :: Text -> V.PrimVector Char+{-# INLINE toVector #-}+toVector (Text (V.PrimVector arr s l)) = V.createN (l*4) (go s 0)+  where+    end = s+l+    go !i !j !marr+        | i >= l = return j+        | otherwise = do+            let (# c, n #) = decodeChar arr i+            writePrimArray marr j c+            go (i+n) (j+1) marr++-- ----------------------------------------------------------------------------+-- ** Normalization+--+-- $normalization++-- | Check if a string is stable in the NFC (Normalization Form C).+isNormalized :: Text -> NormalizationResult+{-# INLINE isNormalized #-}+isNormalized = isNormalizedTo NFC++{-|+Check if a string is stable in the specified Unicode Normalization+Form.++This function can be used as a preprocessing step, before attempting to+normalize a string. Normalization is a very expensive process, it is often+cheaper to first determine if the string is unstable in the requested+normalization form.++The result of the check will be YES if the string is stable and MAYBE or NO+if it is unstable. If the result is MAYBE, the string does not necessarily+have to be normalized.++If the result is unstable, the offset parameter is set to the offset for the+first unstable code point. If the string is stable, the offset is equivalent+to the length of the string in bytes.++For more information, please review [Unicode Standard Annex #15 - Unicode+Normalization Forms](http://www.unicode.org/reports/tr15/).+-}+isNormalizedTo :: NormalizeMode -> Text -> NormalizationResult+isNormalizedTo nmode (Text (V.PrimVector (PrimArray arr#) (I# s#) l@(I# l#)))+    | l == 0 = NormalizedYes+    | otherwise =+        let nflag = normalizeModeToFlag nmode+        in toNormalizationResult (utf8_isnormalized arr# s# l# nflag)++-- | Normalize a string to NFC (Normalization Form C).+normalize :: Text -> Text+{-# INLINE normalize #-}+normalize = normalizeTo NFC++{-|+Normalize a string to the specified Unicode Normalization Form.++The Unicode standard defines two standards for equivalence between+characters: canonical and compatibility equivalence. Canonically equivalent+characters and sequence represent the same abstract character and must be+rendered with the same appearance and behavior. Compatibility equivalent+characters have a weaker equivalence and may be rendered differently.++Unicode Normalization Forms are formally defined standards that can be used+to test whether any two strings of characters are equivalent to each other.+This equivalence may be canonical or compatibility.++The algorithm puts all combining marks into a specified order and uses the+rules for decomposition and composition to transform the string into one of+four Unicode Normalization Forms. A binary comparison can then be used to+determine equivalence.+-}+normalizeTo :: NormalizeMode -> Text -> Text+normalizeTo nmode (Text (V.PrimVector (PrimArray arr#) (I# s#) l@(I# l#)))+    | l == 0 = empty+    | otherwise = unsafeDupablePerformIO $ do+        let nflag = normalizeModeToFlag nmode+            l'@(I# l'#) = utf8_normalize_length arr# s# l# nflag+        when (l' < 0) (error "impossible happened!")+        pa@(MutablePrimArray marr#) <- newArr l'+        utf8_normalize arr# s# l# marr# l'# nflag+        arr' <- unsafeFreezeArr pa+        let !v = V.fromArr arr' 0 l'+        return (Text v)++-- functions below will return error if the source ByteArray# is empty+--+foreign import ccall unsafe utf8_isnormalized ::+    BA# Word8 -> Int# -> Int# -> CSize -> Int+foreign import ccall unsafe utf8_normalize ::+    BA# Word8 -> Int# -> Int# -> MBA# Word8 -> Int# -> CSize -> IO ()+foreign import ccall unsafe utf8_normalize_length ::+    BA# Word8 -> Int# -> Int# -> CSize -> Int++-- ----------------------------------------------------------------------------+-- ** Case conversions++-- $case++-- | Remove case distinction from UTF-8 encoded text with default locale.+caseFold :: Text -> Text+caseFold = caseFoldWith localeDefault++{-|+Remove case distinction from UTF-8 encoded text.++Case folding is the process of eliminating differences between code points+concerning case mapping. It is most commonly used for comparing strings in a+case-insensitive manner. Conversion is fully compliant with the Unicode 7.0+standard.++Although similar to lowercasing text, there are significant differences.+For one, case folding does _not_ take locale into account when converting.+In some cases, case folding can be up to 20% faster than lowercasing the+same text, but the result cannot be treated as correct lowercased text.++Only two locale-specific exception are made when case folding text.+In Turkish, U+0049 LATIN CAPITAL LETTER I maps to U+0131 LATIN SMALL LETTER+DOTLESS I and U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE maps to U+0069+LATIN SMALL LETTER I.++Although most code points can be case folded without changing length, there are notable+exceptions. For example, U+0130 (LATIN CAPITAL LETTER I WITH DOT ABOVE) maps+to "U+0069 U+0307" (LATIN SMALL LETTER I and COMBINING DOT ABOVE) when+converted to lowercase.++Only a handful of scripts make a distinction between upper- and lowercase.+In addition to modern scripts, such as Latin, Greek, Armenian and Cyrillic,+a few historic or archaic scripts have case. The vast majority of scripts+do not have case distinctions.+-}++caseFoldWith :: Locale -> Text -> Text+caseFoldWith locale (Text (V.PrimVector (PrimArray arr#) (I# s#) l@(I# l#)))+    | l == 0 = empty+    | otherwise = unsafeDupablePerformIO $ do+        let l'@(I# l'#) = utf8_casefold_length arr# s# l# locale+        when (l' < 0) (error "impossible happened!")+        pa@(MutablePrimArray marr#) <- newArr l'+        utf8_casefold arr# s# l# marr# l'# locale+        arr' <- unsafeFreezeArr pa+        let !v = V.fromArr arr' 0 l'+        return (Text v)++-- | Convert UTF-8 encoded text to lowercase with default locale.+toLower :: Text -> Text+toLower = toLowerWith localeDefault++{-|+Convert UTF-8 encoded text to lowercase.++This function allows conversion of UTF-8 encoded strings to lowercase+without first changing the encoding to UTF-32. Conversion is fully compliant+with the Unicode 7.0 standard.++Although most code points can be converted to lowercase with changing length,+there are notable exceptions. For example, U+0130 (LATIN CAPITAL LETTER I WITH DOT+ABOVE) maps to "U+0069 U+0307" (LATIN SMALL LETTER I and COMBINING DOT+ABOVE) when converted to lowercase.++Only a handful of scripts make a distinction between upper- and lowercase.+In addition to modern scripts, such as Latin, Greek, Armenian and Cyrillic,+a few historic or archaic scripts have case. The vast majority of scripts do+not have case distinctions.++Case mapping is not reversible. That is, @toUpper(toLower(x)) != toLower(toUpper(x))@.++Certain code points (or combinations of code points) apply rules+based on the locale. For more information about these exceptional+code points, please refer to the Unicode standard:+ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt+-}+toLowerWith :: Locale -> Text -> Text+toLowerWith locale (Text (V.PrimVector (PrimArray arr#) (I# s#) l@(I# l#)))+    | l == 0 = empty+    | otherwise = unsafeDupablePerformIO $ do+        let l'@(I# l'#) = utf8_tolower_length arr# s# l# locale+        when (l' < 0) (error "impossible happened!")+        pa@(MutablePrimArray marr#) <- newArr l'+        utf8_tolower arr# s# l# marr# l'# locale+        arr' <- unsafeFreezeArr pa+        let !v = V.fromArr arr' 0 l'+        return (Text v)++-- | Convert UTF-8 encoded text to uppercase with default locale.+toUpper :: Text -> Text+toUpper = toUpperWith localeDefault++{-|+Convert UTF-8 encoded text to uppercase.++Conversion is fully compliant with the Unicode 7.0 standard.++Although most code points can be converted without changing length, there are notable+exceptions. For example, U+00DF (LATIN SMALL LETTER SHARP S) maps to+"U+0053 U+0053" (LATIN CAPITAL LETTER S and LATIN CAPITAL LETTER S) when+converted to uppercase.++Only a handful of scripts make a distinction between upper and lowercase.+In addition to modern scripts, such as Latin, Greek, Armenian and Cyrillic,+a few historic or archaic scripts have case. The vast majority of scripts+do not have case distinctions.++Case mapping is not reversible. That is, @toUpper(toLower(x)) != toLower(toUpper(x))@.++Certain code points (or combinations of code points) apply rules+based on the locale. For more information about these exceptional+code points, please refer to the Unicode standard:+ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt+-}+toUpperWith :: Locale -> Text -> Text+toUpperWith locale (Text (V.PrimVector (PrimArray arr#) (I# s#) l@(I# l#)))+    | l == 0 = empty+    | otherwise = unsafeDupablePerformIO $ do+        let l'@(I# l'#) = utf8_toupper_length arr# s# l# locale+        when (l' < 0) (error "impossible happened!")+        pa@(MutablePrimArray marr#) <- newArr l'+        utf8_toupper arr# s# l# marr# l'# locale+        arr' <- unsafeFreezeArr pa+        let !v = V.fromArr arr' 0 l'+        return (Text v)++-- | Convert UTF-8 encoded text to titlecase with default locale.+toTitle :: Text -> Text+toTitle = toTitleWith localeDefault++{-|+Convert UTF-8 encoded text to titlecase.++This function allows conversion of UTF-8 encoded strings to titlecase.+Conversion is fully compliant with the Unicode 7.0 standard.++Titlecase requires a bit more explanation than uppercase and lowercase,+because it is not a common text transformation. Titlecase uses uppercase+for the first letter of each word and lowercase for the rest. Words are+defined as "collections of code points with general category Lu, Ll, Lt, Lm+or Lo according to the Unicode database".++Effectively, any type of punctuation can break up a word, even if this is+not grammatically valid. This happens because the titlecasing algorithm+does not and cannot take grammar rules into account.++@+Text                                 | Titlecase+-------------------------------------|-------------------------------------+The running man                      | The Running Man+NATO Alliance                        | Nato Alliance+You're amazing at building libraries | You'Re Amazing At Building Libraries+@++Although most code points can be converted to titlecase without changing length,+there are notable exceptions. For example, U+00DF (LATIN SMALL LETTER SHARP S) maps to+"U+0053 U+0073" (LATIN CAPITAL LETTER S and LATIN SMALL LETTER S) when+converted to titlecase.++Certain code points (or combinations of code points) apply rules+based on the locale. For more information about these exceptional+code points, please refer to the Unicode standard:+ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt+-}++toTitleWith :: Locale -> Text -> Text+toTitleWith locale (Text (V.PrimVector (PrimArray arr#) (I# s#) l@(I# l#)))+    | l == 0 = empty+    | otherwise = unsafeDupablePerformIO $ do+        let l'@(I# l'#) = utf8_totitle_length arr# s# l# locale+        when (l' < 0) (error "impossible happened!")+        pa@(MutablePrimArray marr#) <- newArr l'+        utf8_totitle arr# s# l# marr# l'# locale+        arr' <- unsafeFreezeArr pa+        let !v = V.fromArr arr' 0 l'+        return (Text v)++-- functions below will return error if the source ByteArray# is empty+foreign import ccall unsafe utf8_casefold ::+    BA# Word8 -> Int# -> Int# -> MBA# Word8 -> Int# -> Locale -> IO ()+foreign import ccall unsafe utf8_casefold_length ::+    BA# Word8 -> Int# -> Int# -> Locale -> Int++foreign import ccall unsafe utf8_tolower ::+    BA# Word8 -> Int# -> Int# -> MBA# Word8 -> Int# -> Locale -> IO ()+foreign import ccall unsafe utf8_tolower_length ::+    BA# Word8 -> Int# -> Int# -> Locale -> Int++foreign import ccall unsafe utf8_toupper ::+    BA# Word8 -> Int# -> Int# -> MBA# Word8 -> Int# -> Locale -> IO ()+foreign import ccall unsafe utf8_toupper_length ::+    BA# Word8 -> Int# -> Int# -> Locale -> Int++foreign import ccall unsafe utf8_totitle ::+    BA# Word8 -> Int# -> Int# -> MBA# Word8 -> Int# -> Locale -> IO ()+foreign import ccall unsafe utf8_totitle_length ::+    BA# Word8 -> Int# -> Int# -> Locale -> Int++{-|+Check if the input string conforms to the category specified by the+flags.++This function can be used to check if the code points in a string are part+of a category. Valid flags are members of the "list of categories".+The category for a code point is defined as part of the entry in UnicodeData.txt,+the data file for the Unicode code point database.++By default, the function will treat grapheme clusters as a single code+point. This means that the following string:++@+Code point | Canonical combining class | General category      | Name+---------- | ------------------------- | --------------------- | ----------------------+U+0045     | 0                         | Lu (Uppercase letter) | LATIN CAPITAL LETTER E+U+0300     | 230                       | Mn (Non-spacing mark) | COMBINING GRAVE ACCENT+@++Will match with 'categoryLetterUppercase' in its entirety, because+the COMBINING GRAVE ACCENT is treated as part of the grapheme cluster. This+is useful when e.g. creating a text parser, because you do not have to+normalize the text first.++If this is undesired behavior, specify the 'UTF8_CATEGORY_IGNORE_GRAPHEME_CLUSTER' flag.++In order to maintain backwards compatibility with POSIX functions+like `isdigit` and `isspace`, compatibility flags have been provided. Note,+however, that the result is only guaranteed to be correct for code points+in the Basic Latin range, between U+0000 and 0+007F. Combining a+compatibility flag with a regular category flag will result in undefined+behavior.+-}++isCategory :: Category -> Text -> Bool+isCategory c (Text (V.PrimVector arr@(PrimArray arr#) s@(I# s#) l@(I# l#)))+    | l == 0 = True+    | otherwise = utf8_iscategory arr# s# l# c == l++{-|+Try to match as many code points with the matching category flags as possible+and return the prefix and suffix.+-}+spanCategory :: Category -> Text -> (Text, Text)+spanCategory c (Text (V.PrimVector arr@(PrimArray arr#) s@(I# s#) l@(I# l#)))+    | l == 0 = (empty, empty)+    | otherwise =+        let i = utf8_iscategory arr# s# l# c+        in (Text (V.PrimVector arr s i), Text (V.PrimVector arr (s+i) (l-i)))++-- functions below will return error if the source ByteArray# is empty+foreign import ccall utf8_iscategory :: BA# Word8 -> Int# -> Int# -> Category -> Int
+ Std/Data/Text/Extra.hs view
@@ -0,0 +1,595 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE TypeApplications #-}++{-|+Module      : Std.Data.Text.Extra+Description : Fast text slice manipulation+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++Various combinators works on 'Text's.++-}++module Std.Data.Text.Extra (+  -- * Slice manipulation+    cons, snoc+  , uncons, unsnoc+  , headMaybe, tailMayEmpty+  , lastMaybe, initMayEmpty+  , inits, tails+  , take, drop, takeR, dropR+  , slice+  , splitAt+  , takeWhile, takeWhileR, dropWhile, dropWhileR, dropAround+  , break, span+  , breakR, spanR, breakOn+  , breakOnAll, breakOnAllOverlapping+  , group, groupBy+  , stripPrefix, stripSuffix+  , split, splitWith, splitOn+  , isPrefixOf, isSuffixOf, isInfixOf+  , commonPrefix+  , words, lines, unwords, unlines+  , padLeft, padRight+  -- * Transform+  , reverse+  , intersperse+  , intercalate+  , intercalateElem+  , transpose+  ) where++import Data.Primitive.PrimArray+import qualified Std.Data.Vector.Base as V+import qualified Std.Data.Vector.Extra as V+import qualified Std.Data.Vector.Search as V+import Data.Coerce+import qualified Data.List as List+import Std.Data.Text.Base+import Std.Data.Text.UTF8Codec+import Std.Data.Text.Search+import           Control.Monad.ST+import           GHC.Stack+import           Data.Char+import           Data.Word+import           Prelude                       hiding (concat, concatMap,+                                                elem, notElem, null, length, map,+                                                foldl, foldl1, foldr, foldr1,+                                                maximum, minimum, product, sum,+                                                all, any, replicate, traverse,+                                                take, drop, splitAt,+                                                takeWhile, dropWhile,+                                                break, span, reverse,+                                                words, lines, unwords, unlines)+++--------------------------------------------------------------------------------+-- Slice manipulation++-- | /O(n)/ 'cons' is analogous to (:) for lists, but of different+-- complexity, as it requires making a copy.+cons :: Char -> Text -> Text+{-# INLINABLE cons #-}+cons c (Text (V.PrimVector ba s l)) = Text (V.createN (4 + l) (\ mba -> do+    i <- encodeChar mba 0 c+    copyPrimArray mba i ba s l+    return $! i + l))++-- | /O(n)/ Append a char to the end of a text.+snoc :: Text -> Char -> Text+{-# INLINABLE snoc #-}+snoc (Text (V.PrimVector ba s l)) c = Text (V.createN (4 + l) (\ mba -> do+    copyPrimArray mba 0 ba s l+    encodeChar mba l c))++-- | /O(1)/ Extract the head and tail of a text, return 'Nothing'+-- if it is empty.+uncons :: Text -> Maybe (Char, Text)+{-# INLINE uncons #-}+uncons (Text (V.PrimVector ba s l))+    | l == 0  = Nothing+    | otherwise =+        let (# c, i #) = decodeChar ba s+        in Just (c, Text (V.PrimVector ba (s+i) (l-i)))++-- | /O(1)/ Extract the init and last of a text, return 'Nothing'+-- if text is empty.+unsnoc :: Text -> Maybe (Text, Char)+{-# INLINE unsnoc #-}+unsnoc (Text (V.PrimVector ba s l))+    | l == 0  = Nothing+    | otherwise =+        let (# c, i #) = decodeCharReverse ba (s + l - 1)+        in Just (Text (V.PrimVector ba s (l-i)), c)++-- | /O(1)/ Extract the first char of a text.+headMaybe :: Text -> Maybe Char+{-# INLINABLE headMaybe #-}+headMaybe t = case uncons t of { Just (c, _) -> Just c; _ -> Nothing }++-- | /O(1)/ Extract the chars after the head of a text.+--+-- NOTE: 'tailMayEmpty' return empty text in the case of an empty text.+tailMayEmpty :: Text -> Text+{-# INLINABLE tailMayEmpty #-}+tailMayEmpty t = case uncons t of { Nothing -> empty; Just (_, t) -> t }++-- | /O(1)/ Extract the last char of a text.+lastMaybe :: Text -> Maybe Char+{-# INLINABLE lastMaybe #-}+lastMaybe t = case unsnoc t of { Just (_, c) -> Just c; _ -> Nothing }++-- | /O(1)/ Extract the chars before of the last one.+--+-- NOTE: 'initMayEmpty' return empty text in the case of an empty text.+initMayEmpty :: Text -> Text+{-# INLINABLE initMayEmpty #-}+initMayEmpty t = case unsnoc t of { Just (t, _) -> t; _ -> empty }++-- | /O(n)/ Return all initial segments of the given text, empty first.+inits :: Text -> [Text]+{-# INLINABLE inits #-}+inits t = go t [t]+  where go t acc = case unsnoc t of Just (t', _) -> go t' (t':acc)+                                    Nothing      -> acc++-- | /O(n)/ Return all final segments of the given text, whole text first.+tails :: Text -> [Text]+{-# INLINABLE tails #-}+tails t = t : case uncons t of Just (_, t') -> tails t'+                               Nothing      -> []++-- | /O(1)/ 'take' @n@, applied to a text @xs@, returns the prefix+-- of @xs@ of length @n@, or @xs@ itself if @n > 'length' xs@.+take :: Int -> Text -> Text+{-# INLINABLE take #-}+take n t@(Text (V.PrimVector ba s l))+    | n <= 0 = empty+    | otherwise = case charByteIndex t n of i -> Text (V.PrimVector ba s (i-s))++-- | /O(1)/ 'drop' @n xs@ returns the suffix of @xs@ after the first @n@+-- char, or @[]@ if @n > 'length' xs@.+drop :: Int -> Text -> Text+{-# INLINABLE drop #-}+drop n t@(Text (V.PrimVector ba s l))+    | n <= 0 = t+    | otherwise = case charByteIndex t n of i -> Text (V.PrimVector ba i (l+s-i))++-- | /O(1)/ 'takeR' @n@, applied to a text @xs@, returns the suffix+-- of @xs@ of length @n@, or @xs@ itself if @n > 'length' xs@.+takeR :: Int -> Text -> Text+{-# INLINABLE takeR #-}+takeR n t@(Text (V.PrimVector ba s l))+    | n <= 0 = empty+    | otherwise = case charByteIndexR t n of i -> Text (V.PrimVector ba (i+1) (s+l-1-i))++-- | /O(1)/ 'dropR' @n xs@ returns the prefix of @xs@ before the last @n@+-- char, or @[]@ if @n > 'length' xs@.+dropR :: Int -> Text -> Text+{-# INLINABLE dropR #-}+dropR n t@(Text (V.PrimVector ba s l))+    | n <= 0 = t+    | otherwise = case charByteIndexR t n of i -> Text (V.PrimVector ba s (i-s+1))++-- | /O(1)/ Extract a sub-range text with give start index and length.+--+-- This function is a total function just like 'take/drop', index/length+-- exceeds range will be ingored, e.g.+--+-- @+-- slice 1 3 "hello"   == "ell"+-- slice -1 -1 "hello" == ""+-- slice -2 2 "hello"  == ""+-- slice 2 10 "hello"  == "llo"+-- @+--+-- This holds for all x y: @slice x y vs == drop x . take (x+y) vs@+slice :: Int -> Int -> Text -> Text+{-# INLINE slice #-}+slice x y t | y <= 0 = empty+            | end <= 0 = empty+            | x <= 0 = take end t+            | otherwise = take y (drop x t)+  where+    !end = x + y++-- | /O(n)/ 'splitAt' @n xs@ is equivalent to @('take' n xs, 'drop' n xs)@.+splitAt :: Int -> Text -> (Text, Text)+{-# INLINE splitAt #-}+splitAt n t@(Text (V.PrimVector ba s l))+    | n <= 0 = (empty, t)+    | otherwise = case charByteIndex t n of+        i -> (Text (V.PrimVector ba s (i-s)), Text (V.PrimVector ba i (s+l-i)))+++-- | /O(n)/ Applied to a predicate @p@ and a text @t@,+-- returns the longest prefix (possibly empty) of @t@ of elements that+-- satisfy @p@.+takeWhile :: (Char -> Bool) -> Text -> Text+{-# INLINE takeWhile #-}+takeWhile f t@(Text (V.PrimVector arr s l)) =+    let !i = findIndex (not . f) t in Text (V.PrimVector arr s (i-s))++-- | /O(n)/ Applied to a predicate @p@ and a text @t@,+-- returns the longest suffix (possibly empty) of @t@ of elements that+-- satisfy @p@.+takeWhileR :: (Char -> Bool) -> Text -> Text+{-# INLINE takeWhileR #-}+takeWhileR f t@(Text (V.PrimVector arr s l)) =+    let !i = findIndexR (not . f) t in Text (V.PrimVector arr (i+1) (s+l-i-1))++-- | /O(n)/ Applied to a predicate @p@ and a text @vs@,+-- returns the suffix (possibly empty) remaining after 'takeWhile' @p vs@.+dropWhile :: (Char -> Bool) -> Text -> Text+{-# INLINE dropWhile #-}+dropWhile f t@(Text (V.PrimVector arr s l)) =+    let !i = findIndex (not . f) t in Text (V.PrimVector arr i (s+l-i))++-- | /O(n)/ Applied to a predicate @p@ and a text @vs@,+-- returns the prefix (possibly empty) remaining before 'takeWhileR' @p vs@.+dropWhileR :: (Char -> Bool) -> Text -> Text+{-# INLINE dropWhileR #-}+dropWhileR f t@(Text (V.PrimVector arr s l)) =+    let !i = findIndexR (not . f) t in Text (V.PrimVector arr s (i-s+1))++-- | /O(n)/ @dropAround f = dropWhile f . dropWhileR f@+dropAround :: (Char -> Bool) -> Text -> Text+{-# INLINE dropAround #-}+dropAround f = dropWhileR f . dropWhile f++-- | /O(n)/ Split the text into the longest prefix of elements that do not satisfy the predicate and the rest without copying.+break :: (Char -> Bool) -> Text -> (Text, Text)+{-# INLINE break #-}+break f t@(Text (V.PrimVector arr s l)) =+    let !i = findIndex f t+    in (Text (V.PrimVector arr s (i-s)), Text (V.PrimVector arr i (s+l-i)))++-- | /O(n)/ Split the text into the longest prefix of elements that satisfy the predicate and the rest without copying.+span :: (Char -> Bool) -> Text -> (Text, Text)+{-# INLINE span #-}+span f t@(Text (V.PrimVector arr s l)) =+    let !i = findIndex (not . f) t+    in (Text (V.PrimVector arr s (i-s)), Text (V.PrimVector arr i (s+l-i)))++-- | 'breakR' behaves like 'break' but from the end of the text.+--+-- @breakR p == spanR (not.p)@+breakR :: (Char -> Bool) -> Text -> (Text, Text)+{-# INLINE breakR #-}+breakR f t@(Text (V.PrimVector arr s l)) =+    let !i = findIndexR f t+    in (Text (V.PrimVector arr s (i-s+1)), Text (V.PrimVector arr (i+1) (s+l-i-1)))++-- | 'spanR' behaves like 'span' but from the end of the text.+spanR :: (Char -> Bool) -> Text -> (Text, Text)+{-# INLINE spanR #-}+spanR f t@(Text (V.PrimVector arr s l)) =+    let !i = findIndexR (not . f) t+    in (Text (V.PrimVector arr s (i-s+1)), Text (V.PrimVector arr (i+1) (s+l-i-1)))++-- | Break a text on a subtext, returning a pair of the part of the+-- text prior to the match, and the rest of the text, e.g.+--+-- > break "wor" "hello, world" = ("hello, ", "world")+--+breakOn :: Text -> Text -> (Text, Text)+{-# INLINE breakOn #-}+breakOn (Text needle) (Text haystack) =+    case V.breakOn needle haystack of (v1, v2) -> (Text v1, Text v2)++-- | O(n+m) Find all non-overlapping instances of needle in haystack. Each element of the returned list consists of a pair:+--+--   * The entire string prior to the kth match (i.e. the prefix)+--   * The kth match, followed by the remainder of the string+--+-- Examples:+--+-- @+-- breakOnAll "::" ""+-- ==> []+-- breakOnAll "/" "a/b/c/"+-- ==> [("a", "/b/c/"), ("a/b", "/c/"), ("a/b/c", "/")]+-- @+--+-- The result list is lazy, search is performed when you force the list.+breakOnAll :: Text  -- ^ needle to search for+           -> Text  -- ^ haystack in which to search+           -> [(Text, Text)]+{-# INLINE breakOnAll #-}+breakOnAll (Text needle) (Text haystack@(V.PrimVector arr s l)) =+    List.map breaker (V.indices needle haystack False)+  where+    breaker i = (Text (V.PrimVector arr s (i-s)), Text (V.PrimVector arr i (s+l-i)))++-- | Overlapping version of 'breakOnAll'.+breakOnAllOverlapping :: Text -> Text -> [(Text, Text)]+{-# INLINE breakOnAllOverlapping #-}+breakOnAllOverlapping (Text needle) (Text haystack@(V.PrimVector arr s l)) =+    List.map breaker (V.indicesOverlapping needle haystack False)+  where+    breaker i = (Text (V.PrimVector arr s (i-s)), Text (V.PrimVector arr i (s+l-i)))++-- | The group function takes a text and returns a list of texts such that the concatenation of the result is equal to the argument. Moreover, each sublist in the result contains only equal elements. For example,+--+-- @+-- group "Mississippi" = ["M","i","ss","i","ss","i","pp","i"]+-- @+--+-- It is a special case of 'groupBy', which allows the programmer to supply their own equality test.+group :: Text -> [Text]+{-# INLINE group #-}+group = groupBy (==)++-- | The 'groupBy' function is the non-overloaded version of 'group'.+groupBy :: (Char -> Char -> Bool) -> Text -> [Text]+{-# INLINE groupBy #-}+groupBy f (Text (V.PrimVector arr s l))+    | l == 0    = []+    | otherwise = Text (V.PrimVector arr s (s'-s)) : groupBy f (Text (V.PrimVector arr s' (l+s-s')))+  where+    (# c0, s0 #) = decodeChar arr s+    end = s + l+    s' = go arr (s+s0)+    go arr !i+        | i >= end = i+        | otherwise = let (# c1, s1 #) = decodeChar arr i+                      in if f c0 c1 then go arr (i+s1) else i++-- | /O(n)/ The 'stripPrefix' function takes two texts and returns 'Just'+-- the remainder of the second iff the first is its prefix, and otherwise+-- 'Nothing'.+--+stripPrefix :: Text -> Text -> Maybe Text+{-# INLINE stripPrefix #-}+stripPrefix = coerce (V.stripPrefix @V.PrimVector @Word8)+++-- | O(n) The 'stripSuffix' function takes two texts and returns Just the remainder of the second iff the first is its suffix, and otherwise Nothing.+stripSuffix :: Text -> Text -> Maybe Text+{-# INLINE stripSuffix #-}+stripSuffix = coerce (V.stripSuffix @V.PrimVector @Word8)++-- | /O(n)/ Break a text into pieces separated by the delimiter element+-- consuming the delimiter. I.e.+--+-- > split '\n' "a\nb\nd\ne" == ["a","b","d","e"]+-- > split 'a'  "aXaXaXa"    == ["","X","X","X",""]+-- > split 'x'  "x"          == ["",""]+--+-- and+--+-- > intercalate [c] . split c == id+-- > split == splitWith . (==)+--+-- NOTE, this function behavior different with bytestring's. see+-- <https://github.com/haskell/bytestring/issues/56 #56>.+split :: Char -> Text -> [Text]+{-# INLINE split #-}+split x = splitWith (==x)++-- | /O(n)/ Splits a text into components delimited by+-- separators, where the predicate returns True for a separator char.+-- The resulting components do not contain the separators.  Two adjacent+-- separators result in an empty component in the output.  eg.+--+-- > splitWith (=='a') "aabbaca" == ["","","bb","c",""]+-- > splitWith (=='a') []        == [""]+--+splitWith :: (Char -> Bool) -> Text -> [Text]+{-# INLINE splitWith #-}+splitWith f (Text (V.PrimVector arr s l)) = go s s+  where+    !end = s + l+    go !p !q | q >= end  = let !v = V.PrimVector arr p (q-p) in [Text v]+             | f c       = let !v = V.PrimVector arr p (q-p) in Text v:go (q+n) (q+n)+             | otherwise = go p (q+n)+        where (# c, n #) = decodeChar arr q++-- | /O(m+n)/ Break haystack into pieces separated by needle.+--+-- Note: An empty needle will essentially split haystack element+-- by element.+--+-- Examples:+--+-- >>> splitOn "\r\n" "a\r\nb\r\nd\r\ne"+-- ["a","b","d","e"]+--+-- >>> splitOn "aaa"  "aaaXaaaXaaaXaaa"+-- ["","X","X","X",""]+--+-- >>> splitOn "x"  "x"+-- ["",""]+--+-- and+--+-- > intercalate s . splitOn s         == id+-- > splitOn (singleton c)             == split (==c)+splitOn :: Text -> Text -> [Text]+{-# INLINE splitOn #-}+splitOn = coerce (V.splitOn @V.PrimVector @Word8)++-- | The 'isPrefix' function returns 'True' if the first argument is a prefix of the second.+isPrefixOf :: Text -> Text -> Bool+{-# INLINE isPrefixOf #-}+isPrefixOf = coerce (V.isPrefixOf @V.PrimVector @Word8)++-- | /O(n)/ The 'isSuffixOf' function takes two text and returns 'True'+-- if the first is a suffix of the second.+isSuffixOf :: Text -> Text -> Bool+{-# INLINE isSuffixOf #-}+isSuffixOf = coerce (V.isSuffixOf @V.PrimVector @Word8)++-- | Check whether one text is a subtext of another.+--+-- @needle `isInfixOf` haystack === null haystack || indices needle haystake /= []@.+isInfixOf :: Text -> Text -> Bool+{-# INLINE isInfixOf #-}+isInfixOf = coerce (V.isInfixOf @V.PrimVector @Word8)++-- | /O(n)/ Find the longest non-empty common prefix of two strings+-- and return it, along with the suffixes of each string at which they+-- no longer match. e.g.+--+-- >>> commonPrefix "foobar" "fooquux"+-- ("foo","bar","quux")+--+-- >>> commonPrefix "veeble" "fetzer"+-- ("","veeble","fetzer")+commonPrefix :: Text -> Text -> (Text, Text, Text)+{-# INLINE commonPrefix #-}+commonPrefix = coerce (V.commonPrefix @V.PrimVector @Word8)++-- | /O(n)/ Breaks a 'Bytes' up into a list of words, delimited by unicode space.+words ::  Text -> [Text]+{-# INLINE words #-}+words (Text (V.PrimVector arr s l)) = go s s+  where+    !end = s + l+    go !s' !i | i >= end =+                    if s' == end+                    then []+                    else let !v = V.PrimVector arr s' (end-s') in [Text v]+              | otherwise =+                    let (# c, n #) = decodeChar arr i+                    in if isSpace c+                        then if s' == i+                            then go (i+n) (i+n)+                            else let !v = V.PrimVector arr s' (i-s') in Text v : go (i+n) (i+n)+                        else go s' (i+n)++-- | /O(n)/ Breaks a text up into a list of lines, delimited by ascii @\n@.+lines :: Text -> [Text]+{-# INLINE lines #-}+lines = coerce V.lines++-- | /O(n)/ Joins words with ascii space.+unwords :: [Text] -> Text+{-# INLINE unwords #-}+unwords = coerce V.unwords++-- | /O(n)/ Joins lines with ascii @\n@.+unlines :: [Text] -> Text+{-# INLINE unlines #-}+unlines = coerce V.unlines++-- | Add padding to the left so that the whole text's length is at least n.+padLeft :: Int -> Char -> Text -> Text+{-# INLINE padLeft #-}+padLeft n c t@(Text (V.PrimVector arr s l))+    | n <= tsiz = t+    | otherwise =+        let psiz = (n-tsiz)*csiz+            siz = psiz + l+        in Text (V.create siz (\ marr -> do+            encodeChar marr 0 c+            go marr csiz psiz+            copyPrimArray marr (siz-l) arr s l))+  where+    tsiz = length t+    csiz = encodeCharLength c+    go marr s psiz+        | s >= psiz = return ()+        | otherwise = copyChar' csiz marr s marr (s-csiz) >> go marr (s+csiz) psiz++-- | Add padding to the right so that the whole text's length is at least n.+padRight :: Int -> Char -> Text -> Text+{-# INLINE padRight #-}+padRight n c t@(Text (V.PrimVector arr s l))+    | n <= tsiz = t+    | otherwise =+        let psiz = (n-tsiz)*csiz+            siz = psiz + l+        in Text (V.create siz (\ marr -> do+            copyPrimArray marr 0 arr s l+            encodeChar marr l c+            go marr (l+csiz) siz))+  where+    tsiz = length t+    csiz = encodeCharLength c+    go marr s siz+        | s >= siz = return ()+        | otherwise = copyChar' csiz marr s marr (s-csiz) >> go marr (s+csiz) siz+++--------------------------------------------------------------------------------+-- Transform++-- | /O(n)/ The 'intersperse' function takes a character and places it+-- between the characters of a 'Text'. Performs replacement on invalid scalar values.+--+intersperse :: Char -> Text -> Text+{-# INLINE intersperse #-}+intersperse c = \ t@(Text (V.PrimVector ba s l)) ->+    let tlen = length t+    in if length t < 2+    then t+    else (runST (do+            mbaC <- newPrimArray 4 -- encoded char buf+            clen <- encodeChar mbaC 0 c+            shrinkMutablePrimArray mbaC clen+            baC <- unsafeFreezePrimArray mbaC+            let e = decodeCharLenReverse ba (s+l-1)+            return . Text $ V.create (l + (tlen-1) * clen) (go baC ba s 0 (s+l-e))+        ))+  where+    go :: PrimArray Word8  -- the encode char buf+       -> PrimArray Word8  -- the original text+       -> Int              -- decoding index of original text+       -> Int              -- writing index of new buf+       -> Int              -- the end of decoding index+       -> MutablePrimArray s Word8 -- the new buf+       -> ST s ()+    go !baC !ba !i !j !end !mba+        | i >= end = do+            let l = decodeCharLen ba i+            copyChar l mba j ba i+        | otherwise = do+            let l = decodeCharLen ba i+            copyChar l mba j ba i+            let i' = i + l+                j' = j + l+            let clen = sizeofPrimArray baC+            copyChar clen mba j' baC 0+            go baC ba i' (j'+clen) end mba++-- | /O(n)/ Reverse the characters of a string.+reverse :: Text -> Text+{-# INLINE reverse #-}+reverse = \ (Text (V.PrimVector ba s l)) -> Text $ V.create l (go ba s l (s+l))+  where+    go :: PrimArray Word8 -> Int -> Int -> Int -> MutablePrimArray s Word8 -> ST s ()+    go !ba !i !j !end !mba+        | i >= end = return ()+        | otherwise = do+            let l = decodeCharLen ba i+                j' = j - l+            copyChar l mba j' ba i+            go ba (i+l) j' end mba++-- | /O(n)/ The 'intercalate' function takes a 'Text' and a list of+-- 'Text's and concatenates the list after interspersing the first+-- argument between each element of the list.+intercalate :: Text -> [Text] -> Text+{-# INLINE intercalate #-}+intercalate s = concat . List.intersperse s++intercalateElem :: Char -> [Text] -> Text+{-# INLINE intercalateElem #-}+intercalateElem c = concat . List.intersperse (singleton c)++-- | The 'transpose' function transposes the rows and columns of its+-- text argument.+--+transpose :: [Text] -> [Text]+{-# INLINE transpose #-}+transpose ts = List.map pack . List.transpose . List.map unpack $ ts+
+ Std/Data/Text/Search.hs view
@@ -0,0 +1,143 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UnboxedTuples       #-}+++{-|+Module      : Std.Data.Text.Search+Description : Searching text+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++-}++module Std.Data.Text.Search (+  -- * element-wise search+    elem, notElem+  -- * Searching by equality+  , findIndices+  , find, findR+  , findIndex+  , findIndexR+  , filter, partition+  ) where+++import           Control.Monad.ST+import           Data.Word+import           Prelude                 hiding (elem, notElem, filter, partition)+import           Std.Data.Array+import           Std.Data.Text.Base+import           Std.Data.Text.UTF8Codec+import qualified Std.Data.Vector.Base    as V++findIndices :: (Char -> Bool) -> Text -> [Int]+{-# INLINE findIndices #-}+findIndices f (Text (V.PrimVector arr s l)) = go 0 s+  where+    !end = s + l+    go !i !p | p >= end  = []+             | f x       = i : go (i+1) (p+off)+             | otherwise = go (i+1) (p+off)+        where (# x, off #) = decodeChar arr p++-- | /O(n)/ find the first char matching the predicate in a text+-- from left to right, if there isn't one, return the index point to the end of the byte slice.+find :: (Char -> Bool)+     -> Text+     -> (Int, Int, Maybe Char)  -- ^ (char index, byte index, matching char)+{-# INLINE find #-}+find f (Text (V.PrimVector arr s l)) = go 0 s+  where+    !end = s + l+    go !i !j | j >= end  = (i, j, Nothing)+             | otherwise =+                let (# x, off #) = decodeChar arr j+                in if f x+                    then (i, j, Just x)+                    else go (i+1) (j+off)++-- | /O(n)/ find the first char matching the predicate in a text+-- from right to left, if there isn't one, return the index point to the end of the byte slice.+--+findR :: (Char -> Bool) -> Text -> (Int, Int, Maybe Char)+{-# INLINE findR #-}+findR f (Text (V.PrimVector arr s l)) = go 0 (s+l-1)+  where+    go !i !j | j < s     = (i, j, Nothing)+             | otherwise =+                let (# x, off #) = decodeCharReverse arr j+                in if f x+                    then (i, j, Just x)+                    else go (i+1) (j-off)++--------------------------------------------------------------------------------++-- | /O(n)/ find the index of the byte slice.+findIndex :: (Char -> Bool) -> Text -> Int+{-# INLINE findIndex #-}+findIndex f t = case find f t of (_, i, _) -> i++-- | /O(n)/ find the index of the byte slice in reverse order.+findIndexR ::  (Char -> Bool) -> Text -> Int+{-# INLINE findIndexR #-}+findIndexR f t = case findR f t of (_, i, _) -> i++-- | /O(n)/ 'filter', applied to a predicate and a text,+-- returns a text containing those chars that satisfy the+-- predicate.+filter :: (Char -> Bool) -> Text -> Text+{-# INLINE filter #-}+filter f (Text (V.PrimVector arr s l)) = Text (V.createN l (go s 0))+  where+    !end = s + l+    go :: Int -> Int -> MutablePrimArray s Word8 -> ST s Int+    go !i !j marr+        | i >= end = return j+        | otherwise =+            let (# x, off #) = decodeChar arr i+            in if f x+                then do+                    copyChar off marr j arr i+                    go (i+off) (j+off) marr+                else go (i+off) j marr++-- | /O(n)/ The 'partition' function takes a predicate, a text, returns+-- a pair of text with codepoints which do and do not satisfy the+-- predicate, respectively; i.e.,+--+-- > partition p txt == (filter p txt, filter (not . p) txt)+partition :: (Char -> Bool) -> Text -> (Text, Text)+{-# INLINE partition #-}+partition f (Text (V.PrimVector arr s l))+    | l == 0    = (empty, empty)+    | otherwise = let !(bs1, bs2) = V.createN2 l l (go 0 0 s) in (Text bs1, Text bs2)+  where+    !end = s + l+    go :: Int -> Int -> Int -> MutablePrimArray s Word8 -> MutablePrimArray s Word8 -> ST s (Int, Int)+    go !i !j !p !mba0 !mba1+        | p >= end   = return (i, j)+        | otherwise =+            let (# x, off #) = decodeChar arr p+            in if f x+                then copyChar off mba0 i arr p >> go (i+off) j (p+off) mba0 mba1+                else copyChar off mba1 j arr p >> go i (j+off) (p+off) mba0 mba1++--------------------------------------------------------------------------------+-- Searching by equality++-- | /O(n)/ 'elem' test if given char is in given text.+elem :: Char -> Text -> Bool+{-# INLINE elem #-}+elem x t = case find (x==) t of (_,_,Nothing) -> False+                                _             -> True++-- | /O(n)/ @not . elem@+notElem ::  Char -> Text -> Bool+{-# INLINE notElem #-}+notElem x = not . elem x
+ Std/Data/Text/UTF8Codec.hs view
@@ -0,0 +1,356 @@+{-# LANGUAGE BangPatterns  #-}+{-# LANGUAGE MagicHash     #-}+{-# LANGUAGE UnboxedTuples #-}++{-|+Module      : Std.Data.Text.UTF8Codec+Description : UTF-8 codecs and helpers.+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++UTF-8 codecs and helpers.++-}++module Std.Data.Text.UTF8Codec where++import           Control.Monad.Primitive+import           Data.Primitive.ByteArray+import           Data.Primitive.PrimArray+import           GHC.Prim+import           GHC.ST+import           GHC.Types+import           GHC.Word++-- | Return a codepoint's encoded length in bytes+--+-- If the codepoint is invalid, we return 3(encoded bytes length of replacement char @\U+FFFD@).+--+encodeCharLength :: Char -> Int+{-# INLINE encodeCharLength #-}+encodeCharLength n+    | n <= '\x00007F' = 1+    | n <= '\x0007FF' = 2+    | n <= '\x00FFFF' = 3+    | n <= '\x10FFFF' = 4+    | otherwise = 3++-- | Encode a 'Char' into bytes, write 'replacementChar' for invalid unicode codepoint.+--+-- This function assumed there're enough space for encoded bytes, and return the advanced index.+encodeChar :: MutablePrimArray s Word8 -> Int -> Char -> ST s Int+{-# INLINE encodeChar #-}+encodeChar (MutablePrimArray mba#) (I# i#) (C# c#) = ST (\ s# ->+    let !(# s1#, j# #) = encodeChar# mba# i# c# s# in (# s1#, I# j# #))++-- | The unboxed version of 'encodeChar'.+--+-- This function is marked as @NOINLINE@ to reduce code size, and stop messing up simplifier+-- due to too much branches.+encodeChar# :: MutableByteArray# s -> Int# -> Char# -> State# s -> (# State# s, Int# #)+{-# NOINLINE encodeChar# #-} -- codesize vs speed choice here+encodeChar# mba# i# c# = case (int2Word# (ord# c#)) of+    n#+        | isTrue# (n# `leWord#` 0x0000007F##) -> \ s# ->+            let s1# = writeWord8Array# mba# i# n# s#+            in (# s1#, i# +# 1# #)+        | isTrue# (n# `leWord#` 0x000007FF##) -> \ s# ->+            let s1# = writeWord8Array# mba# i# (0xC0## `or#` (n# `uncheckedShiftRL#` 6#)) s#+                s2# = writeWord8Array# mba# (i# +# 1#) (0x80## `or#` (n# `and#` 0x3F##)) s1#+            in (# s2#, i# +# 2# #)+        | isTrue# (n# `leWord#` 0x0000D7FF##) -> \ s# ->+            let s1# = writeWord8Array# mba# i# (0xE0## `or#` (n# `uncheckedShiftRL#` 12#)) s#+                s2# = writeWord8Array# mba# (i# +# 1#) (0x80## `or#` ((n# `uncheckedShiftRL#` 6#) `and#` 0x3F##)) s1#+                s3# = writeWord8Array# mba# (i# +# 2#) (0x80## `or#` (n# `and#` 0x3F##)) s2#+            in (# s3#, i# +# 3# #)+        | isTrue# (n# `leWord#` 0x0000DFFF##) -> \ s# -> -- write replacement char \U+FFFD+            let s1# = writeWord8Array# mba# i# 0xEF## s#+                s2# = writeWord8Array# mba# (i# +# 1#) 0xBF## s1#+                s3# = writeWord8Array# mba# (i# +# 2#) 0xBD## s2#+            in (# s3#, i# +# 3# #)+        | isTrue# (n# `leWord#` 0x0000FFFF##) -> \ s# ->+            let s1# = writeWord8Array# mba# i# (0xE0## `or#` (n# `uncheckedShiftRL#` 12#)) s#+                s2# = writeWord8Array# mba# (i# +# 1#) (0x80## `or#` ((n# `uncheckedShiftRL#` 6#) `and#` 0x3F##)) s1#+                s3# = writeWord8Array# mba# (i# +# 2#) (0x80## `or#` (n# `and#` 0x3F##)) s2#+            in (# s3#, i# +# 3# #)+        | isTrue# (n# `leWord#` 0x0010FFFF##) -> \ s# ->+            let s1# = writeWord8Array# mba# i# (0xF0## `or#` (n# `uncheckedShiftRL#` 18#)) s#+                s2# = writeWord8Array# mba# (i# +# 1#) (0x80## `or#` ((n# `uncheckedShiftRL#` 12#) `and#` 0x3F##)) s1#+                s3# = writeWord8Array# mba# (i# +# 2#) (0x80## `or#` ((n# `uncheckedShiftRL#` 6#) `and#` 0x3F##)) s2#+                s4# = writeWord8Array# mba# (i# +# 3#) (0x80## `or#` (n# `and#` 0x3F##)) s3#+            in (# s4#, i# +# 4# #)+        | otherwise -> \ s# -> -- write replacement char \U+FFFD+            let s1# = writeWord8Array# mba# i#  0xEF## s#+                s2# = writeWord8Array# mba# (i# +# 1#) 0xBF## s1#+                s3# = writeWord8Array# mba# (i# +# 2#) 0xBD## s2#+            in (# s3#, i# +# 3# #)+++-- | Encode a 'Char' into bytes with non-standard UTF-8 encoding(Used in "Data.CBytes").+--+-- '\NUL' is encoded as two bytes @C0 80@ , '\xD800' ~ '\xDFFF' is encoded as a three bytes normal UTF-8 codepoint.+-- This function assumed there're enough space for encoded bytes, and return the advanced index.+encodeCharModifiedUTF8 :: (PrimMonad m) => MutablePrimArray (PrimState m) Word8 -> Int -> Char -> m Int+{-# INLINE encodeCharModifiedUTF8 #-}+encodeCharModifiedUTF8 (MutablePrimArray mba#) (I# i#) (C# c#) = primitive (\ s# ->+    let !(# s1#, j# #) = encodeCharModifiedUTF8# mba# i# c# s# in (# s1#, I# j# #))++-- | The unboxed version of 'encodeCharModifiedUTF8'.+encodeCharModifiedUTF8# :: MutableByteArray# s -> Int# -> Char# -> State# s -> (# State# s, Int# #)+{-# NOINLINE encodeCharModifiedUTF8# #-} -- codesize vs speed choice here+encodeCharModifiedUTF8# mba# i# c# = case (int2Word# (ord# c#)) of+    n#+        | isTrue# (n# `eqWord#` 0x00000000##) -> \ s# ->    -- encode \NUL as \xC0 \x80+            let s1# = writeWord8Array# mba# i# 0xC0## s#+                s2# = writeWord8Array# mba# (i# +# 1#) 0x80## s1#+            in (# s2#, i# +# 2# #)+        | isTrue# (n# `leWord#` 0x0000007F##) -> \ s# ->+            let s1# = writeWord8Array# mba# i# n# s#+            in (# s1#, i# +# 1# #)+        | isTrue# (n# `leWord#` 0x000007FF##) -> \ s# ->+            let s1# = writeWord8Array# mba# i# (0xC0## `or#` (n# `uncheckedShiftRL#` 6#)) s#+                s2# = writeWord8Array# mba# (i# +# 1#) (0x80## `or#` (n# `and#` 0x3F##)) s1#+            in (# s2#, i# +# 2# #)+        | isTrue# (n# `leWord#` 0x0000FFFF##) -> \ s# ->    -- \xD800 ~ \xDFFF is encoded as normal UTF-8 codepoints+            let s1# = writeWord8Array# mba# i# (0xE0## `or#` (n# `uncheckedShiftRL#` 12#)) s#+                s2# = writeWord8Array# mba# (i# +# 1#) (0x80## `or#` ((n# `uncheckedShiftRL#` 6#) `and#` 0x3F##)) s1#+                s3# = writeWord8Array# mba# (i# +# 2#) (0x80## `or#` (n# `and#` 0x3F##)) s2#+            in (# s3#, i# +# 3# #)+        | otherwise -> \ s# ->+            let s1# = writeWord8Array# mba# i# (0xF0## `or#` (n# `uncheckedShiftRL#` 18#)) s#+                s2# = writeWord8Array# mba# (i# +# 1#) (0x80## `or#` ((n# `uncheckedShiftRL#` 12#) `and#` 0x3F##)) s1#+                s3# = writeWord8Array# mba# (i# +# 2#) (0x80## `or#` ((n# `uncheckedShiftRL#` 6#) `and#` 0x3F##)) s2#+                s4# = writeWord8Array# mba# (i# +# 3#) (0x80## `or#` (n# `and#` 0x3F##)) s3#+            in (# s4#, i# +# 4# #)++--------------------------------------------------------------------------------++-- | Decode a 'Char' from bytes+--+-- This function assumed all bytes are UTF-8 encoded, and the index param point to the+-- beginning of a codepoint, the decoded character and the advancing offset are returned.+--+-- It's annoying to use unboxed tuple here but we really don't want allocation even if+-- GHC can't optimize it away.+decodeChar :: PrimArray Word8 -> Int -> (# Char, Int #)+{-# INLINE decodeChar #-}+decodeChar (PrimArray ba#) (I# idx#) =+    let !(# c#, i# #) = decodeChar# ba# idx# in (# C# c#, I# i# #)++decodeChar_ :: PrimArray Word8 -> Int -> Char+{-# INLINE decodeChar_ #-}+decodeChar_ (PrimArray ba#) (I# idx#) =+    let !(# c#, i# #) = decodeChar# ba# idx# in C# c#++-- | The unboxed version of 'decodeChar'+--+-- This function is marked as @NOINLINE@ to reduce code size, and stop messing up simplifier+-- due to too much branches.+decodeChar# :: ByteArray# -> Int# -> (# Char#, Int# #)+{-# NOINLINE decodeChar# #-} -- This branchy code make GHC impossible to fuse, DON'T inline+decodeChar# ba# idx# = case indexWord8Array# ba# idx# of+    w1#+        | isTrue# (w1# `leWord#` 0x7F##) -> (# chr1# w1#, 1# #)+        | isTrue# (w1# `leWord#` 0xDF##) ->+            let w2# = indexWord8Array# ba# (idx# +# 1#)+            in (# chr2# w1# w2#, 2# #)+        | isTrue# (w1# `leWord#` 0xEF##) ->+            let w2# = indexWord8Array# ba# (idx# +# 1#)+                w3# = indexWord8Array# ba# (idx# +# 2#)+            in (# chr3# w1# w2# w3#, 3# #)+        | otherwise ->+            let w2# = indexWord8Array# ba# (idx# +# 1#)+                w3# = indexWord8Array# ba# (idx# +# 2#)+                w4# = indexWord8Array# ba# (idx# +# 3#)+            in (# chr4# w1# w2# w3# w4#, 4# #)++-- | Decode a codepoint's length in bytes+--+-- This function assumed all bytes are UTF-8 encoded, and the index param point to the+-- beginning of a codepoint.+--+decodeCharLen :: PrimArray Word8 -> Int -> Int+{-# INLINE decodeCharLen #-}+decodeCharLen (PrimArray ba#) (I# idx#) =+    let i# = decodeCharLen# ba# idx# in I# i#++-- | The unboxed version of 'decodeCharLen'+--+-- This function is marked as @NOINLINE@ to reduce code size, and stop messing up simplifier+-- due to too much branches.+decodeCharLen# :: ByteArray# -> Int# -> Int#+{-# INLINE decodeCharLen# #-} -- This branchy code make GHC impossible to fuse, DON'T inline+decodeCharLen# ba# idx# = case indexWord8Array# ba# idx# of+    w1#+        | isTrue# (w1# `leWord#` 0x7F##) -> 1#+        | isTrue# (w1# `leWord#` 0xDF##) -> 2#+        | isTrue# (w1# `leWord#` 0xEF##) -> 3#+        | otherwise -> 4#++-- | Decode a 'Char' from bytes in rerverse order.+--+-- This function assumed all bytes are UTF-8 encoded, and the index param point to the end+-- of a codepoint, the decoded character and the backward advancing offset are returned.+--+decodeCharReverse :: PrimArray Word8 -> Int -> (# Char, Int #)+{-# INLINE decodeCharReverse #-}+decodeCharReverse (PrimArray ba#) (I# idx#) =+    let !(# c#, i# #) = decodeCharReverse# ba# idx# in (# C# c#, I# i# #)++decodeCharReverse_ :: PrimArray Word8 -> Int -> Char+{-# INLINE decodeCharReverse_ #-}+decodeCharReverse_ (PrimArray ba#) (I# idx#) =+    let !(# c#, i# #) = decodeCharReverse# ba# idx# in C# c#++-- | The unboxed version of 'decodeCharReverse'+--+-- This function is marked as @NOINLINE@ to reduce code size, and stop messing up simplifier+-- due to too much branches.+decodeCharReverse# :: ByteArray# -> Int# -> (# Char#, Int# #)+{-# NOINLINE decodeCharReverse# #-} -- This branchy code make GHC impossible to fuse, DON'T inline+decodeCharReverse# ba# idx# =+    let w1# = indexWord8Array# ba# idx#+    in if isContinueByte# w1#+    then+        let w2# = indexWord8Array# ba# (idx# -# 1#)+        in if isContinueByte# w2#+        then+            let w3# = indexWord8Array# ba# (idx# -# 2#)+            in if isContinueByte# w3#+            then+                let w4# = indexWord8Array# ba# (idx# -# 3#)+                in (# chr4# w4# w3# w2# w1#, 4# #)+            else (# chr3# w3# w2# w1#, 3# #)+        else  (# chr2# w2# w1#, 2# #)+    else (# chr1# w1#, 1# #)+++-- | Decode a codepoint's length in bytes in reverse order.+--+-- This function assumed all bytes are UTF-8 encoded, and the index param point to the end+-- of a codepoint.+--+decodeCharLenReverse :: PrimArray Word8 -> Int -> Int+{-# INLINE decodeCharLenReverse #-}+decodeCharLenReverse (PrimArray ba#) (I# idx#) =+    let i# = decodeCharLenReverse# ba# idx# in I# i#++-- | The unboxed version of 'decodeCharLenReverse'+--+-- This function is marked as @NOINLINE@ to reduce code size, and stop messing up simplifier+-- due to too much branches.+decodeCharLenReverse# :: ByteArray# -> Int# -> Int#+{-# NOINLINE decodeCharLenReverse# #-} -- This branchy code make GHC impossible to fuse, DON'T inline+decodeCharLenReverse# ba# idx# =+    let w1# = indexWord8Array# ba# idx#+    in if isContinueByte# w1#+    then+        let w2# = indexWord8Array# ba# (idx# -# 1#)+        in if isContinueByte# w2#+        then+            let w3# = indexWord8Array# ba# (idx# -# 2#)+            in if isContinueByte# w3#+            then 4#+            else 3#+        else 2#+    else 1#++--------------------------------------------------------------------------------++between# :: Word# -> Word# -> Word# -> Bool+{-# INLINE between# #-}+between# w# l# h# = isTrue# (w# `geWord#` l#) && isTrue# (w# `leWord#` h#)++isContinueByte# :: Word# -> Bool+{-# INLINE isContinueByte# #-}+isContinueByte# w# = isTrue# (and# w# 0xC0## `eqWord#` 0x80##)++chr1# :: Word# -> Char#+{-# INLINE chr1# #-}+chr1# x1# = chr# y1#+  where+    !y1# = word2Int# x1#++chr2# :: Word# -> Word# -> Char#+{-# INLINE chr2# #-}+chr2# x1# x2# = chr# (z1# +# z2#)+  where+    !y1# = word2Int# x1#+    !y2# = word2Int# x2#+    !z1# = uncheckedIShiftL# (y1# -# 0xC0#) 6#+    !z2# = y2# -# 0x80#++chr3# :: Word# -> Word# -> Word# -> Char#+{-# INLINE chr3# #-}+chr3# x1# x2# x3# = chr# (z1# +# z2# +# z3#)+  where+    !y1# = word2Int# x1#+    !y2# = word2Int# x2#+    !y3# = word2Int# x3#+    !z1# = uncheckedIShiftL# (y1# -# 0xE0#) 12#+    !z2# = uncheckedIShiftL# (y2# -# 0x80#) 6#+    !z3# = y3# -# 0x80#++chr4# :: Word# -> Word# -> Word# -> Word# -> Char#+{-# INLINE chr4# #-}+chr4# x1# x2# x3# x4# = chr# (z1# +# z2# +# z3# +# z4#)+  where+    !y1# = word2Int# x1#+    !y2# = word2Int# x2#+    !y3# = word2Int# x3#+    !y4# = word2Int# x4#+    !z1# = uncheckedIShiftL# (y1# -# 0xF0#) 18#+    !z2# = uncheckedIShiftL# (y2# -# 0x80#) 12#+    !z3# = uncheckedIShiftL# (y3# -# 0x80#) 6#+    !z4# = y4# -# 0x80#++--------------------------------------------------------------------------------++-- | Unrolled copy loop for copying a utf8-encoded codepoint from source array to target array.+--+copyChar :: Int                       -- copy length, must be 1, 2, 3 or 4+         -> MutablePrimArray s Word8  -- target array+         -> Int                       -- writing offset+         -> PrimArray Word8           -- source array+         -> Int                       -- reading offset+         -> ST s ()+{-# INLINE copyChar #-}+copyChar !l !mba !j !ba !i = case l of+    1 -> do writePrimArray mba j $ indexPrimArray ba i+    2 -> do writePrimArray mba j $ indexPrimArray ba i+            writePrimArray mba (j+1) $ indexPrimArray ba (i+1)+    3 -> do writePrimArray mba j $ indexPrimArray ba i+            writePrimArray mba (j+1) $ indexPrimArray ba (i+1)+            writePrimArray mba (j+2) $ indexPrimArray ba (i+2)+    _ -> do writePrimArray mba j $ indexPrimArray ba i+            writePrimArray mba (j+1) $ indexPrimArray ba (i+1)+            writePrimArray mba (j+2) $ indexPrimArray ba (i+2)+            writePrimArray mba (j+3) $ indexPrimArray ba (i+3)++-- | Unrolled copy loop for copying a utf8-encoded codepoint from source array to target array.+--+copyChar' :: Int                       -- copy length, must be 1, 2, 3 or 4+          -> MutablePrimArray s Word8  -- target array+          -> Int                       -- writing offset+          -> MutablePrimArray s Word8  -- source array+          -> Int                       -- reading offset+          -> ST s ()+{-# INLINE copyChar' #-}+copyChar' !l !mba !j !ba !i = case l of+    1 -> do writePrimArray mba j =<< readPrimArray ba i+    2 -> do writePrimArray mba j =<< readPrimArray ba i+            writePrimArray mba (j+1) =<< readPrimArray ba (i+1)+    3 -> do writePrimArray mba j =<< readPrimArray ba i+            writePrimArray mba (j+1) =<< readPrimArray ba (i+1)+            writePrimArray mba (j+2) =<< readPrimArray ba (i+2)+    _ -> do writePrimArray mba j =<< readPrimArray ba i+            writePrimArray mba (j+1) =<< readPrimArray ba (i+1)+            writePrimArray mba (j+2) =<< readPrimArray ba (i+2)+            writePrimArray mba (j+3) =<< readPrimArray ba (i+3)++-- | @\xFFFD@, which will be encoded as @0xEF 0xBF 0xBD@ 3 bytes.+replacementChar :: Char+replacementChar = '\xFFFD'
+ Std/Data/Text/UTF8Rewind.hsc view
@@ -0,0 +1,126 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++{-|+Module      : Std.Data.Text.UTF8Rewind+Description : Errno provided by libuv+Copyright   : (c) Winterland, 2017-2018+License     : BSD+Maintainer  : drkoster@qq.com+Stability   : experimental+Portability : non-portable++INTERNAL MODULE, provides utf8rewind constants++-}++module Std.Data.Text.UTF8Rewind where++import Data.Bits+import Foreign.C.Types+import GHC.Generics++#include "utf8rewind.h"++-- | Locale for case mapping.+newtype Locale = Locale CSize deriving (Show, Eq, Ord, Generic)++#{enum Locale, Locale, localeDefault    = UTF8_LOCALE_DEFAULT }+#{enum Locale, Locale, localeLithuanian = UTF8_LOCALE_LITHUANIAN }+#{enum Locale, Locale, localeTurkishAndAzeriLatin = UTF8_LOCALE_TURKISH_AND_AZERI_LATIN }++-- | see 'NormalizeMode' in Std.Data.Text.Base+#{enum CSize, CSize, normalizeCompose       = UTF8_NORMALIZE_COMPOSE }+#{enum CSize, CSize, normalizeDecompose     = UTF8_NORMALIZE_DECOMPOSE }+#{enum CSize, CSize, normalizeCompatibility = UTF8_NORMALIZE_COMPATIBILITY }++{-|+These are the Unicode Normalization Forms:++@+Form                         | Description+---------------------------- | ---------------------------------------------+Normalization Form D (NFD)   | Canonical decomposition+Normalization Form C (NFC)   | Canonical decomposition, followed by canonical composition+Normalization Form KD (NFKD) | Compatibility decomposition+Normalization Form KC (NFKC) | Compatibility decomposition, followed by canonical composition+@ +-}+data NormalizeMode = NFC | NFKC | NFD | NFKD deriving (Show, Eq, Ord, Generic)++normalizeModeToFlag :: NormalizeMode -> CSize+normalizeModeToFlag NFC  = #{const UTF8_NORMALIZE_COMPOSE}+normalizeModeToFlag NFKC = #{const UTF8_NORMALIZE_COMPOSE} + #{const UTF8_NORMALIZE_COMPATIBILITY}+normalizeModeToFlag NFD  = #{const UTF8_NORMALIZE_DECOMPOSE}+normalizeModeToFlag NFKD = #{const UTF8_NORMALIZE_DECOMPOSE} + #{const UTF8_NORMALIZE_COMPATIBILITY}++data NormalizationResult = NormalizedYes | NormalizedMaybe | NormalizedNo deriving (Show, Eq, Ord, Generic)++toNormalizationResult :: Int -> NormalizationResult+toNormalizationResult #{const UTF8_NORMALIZATION_RESULT_YES} = NormalizedYes+toNormalizationResult #{const UTF8_NORMALIZATION_RESULT_MAYBE} = NormalizedMaybe+toNormalizationResult #{const UTF8_NORMALIZATION_RESULT_NO} = NormalizedNo+++-- | Unicode categories.+-- See 'Std.Data.Text.Base.isCategory', you can combine categories with bitwise or.+newtype Category = Category CSize deriving (Show, Eq, Ord, Bits, FiniteBits, Generic)++#{enum Category, Category, categoryLetterUppercase        = UTF8_CATEGORY_LETTER_UPPERCASE }+#{enum Category, Category, categoryLetterLowercase        = UTF8_CATEGORY_LETTER_LOWERCASE }+#{enum Category, Category, categoryLetterTitlecase        = UTF8_CATEGORY_LETTER_TITLECASE }+#{enum Category, Category, categoryLetterOther            = UTF8_CATEGORY_LETTER_OTHER }+#{enum Category, Category, categoryLetter                 = UTF8_CATEGORY_LETTER }+#{enum Category, Category, categoryCaseMapped             = UTF8_CATEGORY_CASE_MAPPED }++#{enum Category, Category, categoryMarkNonSpacing         = UTF8_CATEGORY_MARK_NON_SPACING }+#{enum Category, Category, categoryMarkSpacing            = UTF8_CATEGORY_MARK_SPACING }+#{enum Category, Category, categoryMarkEnclosing          = UTF8_CATEGORY_MARK_ENCLOSING }+#{enum Category, Category, categoryMark                   = UTF8_CATEGORY_MARK }++#{enum Category, Category, categoryNumberDecimal          = UTF8_CATEGORY_NUMBER_DECIMAL }+#{enum Category, Category, categoryNumberLetter           = UTF8_CATEGORY_NUMBER_LETTER }+#{enum Category, Category, categoryNumberOther            = UTF8_CATEGORY_NUMBER_OTHER }+#{enum Category, Category, categoryNumber                 = UTF8_CATEGORY_NUMBER }++#{enum Category, Category, categoryPunctuationConnector   = UTF8_CATEGORY_PUNCTUATION_CONNECTOR }+#{enum Category, Category, categoryPunctuationDash        = UTF8_CATEGORY_PUNCTUATION_DASH }+#{enum Category, Category, categoryPunctuationOpen        = UTF8_CATEGORY_PUNCTUATION_OPEN }+#{enum Category, Category, categoryPunctuationClose       = UTF8_CATEGORY_PUNCTUATION_CLOSE }+#{enum Category, Category, categoryPunctuationInitial     = UTF8_CATEGORY_PUNCTUATION_INITIAL }+#{enum Category, Category, categoryPunctuationFinal       = UTF8_CATEGORY_PUNCTUATION_FINAL }+#{enum Category, Category, categoryPunctuationOther       = UTF8_CATEGORY_PUNCTUATION_OTHER }+#{enum Category, Category, categoryPunctuation            = UTF8_CATEGORY_PUNCTUATION }++#{enum Category, Category, categorySymbolMath             = UTF8_CATEGORY_SYMBOL_MATH }+#{enum Category, Category, categorySymbolCurrency         = UTF8_CATEGORY_SYMBOL_CURRENCY }+#{enum Category, Category, categorySymbolModifier         = UTF8_CATEGORY_SYMBOL_MODIFIER }+#{enum Category, Category, categorySymbolOther            = UTF8_CATEGORY_SYMBOL_OTHER }+#{enum Category, Category, categorySymbol                 = UTF8_CATEGORY_SYMBOL }++#{enum Category, Category, categorySeparatorSpace         = UTF8_CATEGORY_SEPARATOR_SPACE }+#{enum Category, Category, categorySeparatorLine          = UTF8_CATEGORY_SEPARATOR_LINE }+#{enum Category, Category, categorySeparatorParagraph     = UTF8_CATEGORY_SEPARATOR_PARAGRAPH }+#{enum Category, Category, categorySeparator              = UTF8_CATEGORY_SEPARATOR }+#{enum Category, Category, categoryControl                = UTF8_CATEGORY_CONTROL }+#{enum Category, Category, categoryFormat                 = UTF8_CATEGORY_FORMAT }+#{enum Category, Category, categorySurrogate              = UTF8_CATEGORY_SURROGATE }+#{enum Category, Category, categoryPrivateUse             = UTF8_CATEGORY_PRIVATE_USE }+#{enum Category, Category, categoryUnassigned             = UTF8_CATEGORY_UNASSIGNED }+#{enum Category, Category, categoryCompatibility          = UTF8_CATEGORY_COMPATIBILITY }+#{enum Category, Category, categoryIgnoreGraphemeCluste   = UTF8_CATEGORY_IGNORE_GRAPHEME_CLUSTER }+#{enum Category, Category, categoryIscntrl                = UTF8_CATEGORY_ISCNTRL }++#{enum Category, Category, categoryIsprint                = UTF8_CATEGORY_ISPRINT }+#{enum Category, Category, categoryIsspace                = UTF8_CATEGORY_ISSPACE }+#{enum Category, Category, categoryIsblank                = UTF8_CATEGORY_ISBLANK }+#{enum Category, Category, categoryIsgraph                = UTF8_CATEGORY_ISGRAPH }+#{enum Category, Category, categoryIspunct                = UTF8_CATEGORY_ISPUNCT }+#{enum Category, Category, categoryIsalnum                = UTF8_CATEGORY_ISALNUM }+#{enum Category, Category, categoryIsalpha                = UTF8_CATEGORY_ISALPHA }+#{enum Category, Category, categoryIsupper                = UTF8_CATEGORY_ISUPPER }+#{enum Category, Category, categoryIslower                = UTF8_CATEGORY_ISLOWER }+#{enum Category, Category, categoryIsdigit                = UTF8_CATEGORY_ISDIGIT }+#{enum Category, Category, categoryIsxdigit               = UTF8_CATEGORY_ISXDIGIT }++foreign import ccall unsafe utf8envlocale :: IO Category
+ Std/Data/TextBuilder.hs view
@@ -0,0 +1,197 @@+{-# LANGUAGE CPP                        #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE FlexibleInstances          #-}++{-|+Module      : Std.Data.Builder.Numeric+Description : UTF8 compatible builders.+Copyright   : (c) Dong Han, 2017-2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++UTF8 compatible textual builders.++-}++module Std.Data.TextBuilder+  (+  -- * Textual Builder+    TextBuilder(..)+  , buildText+  -- * Basic UTF8 builders+  , stringUTF8, charUTF8, string7, char7, text+  -- * Numeric builders+  -- ** Integral type formatting+  , B.IFormat(..)+  , B.defaultIFormat+  , B.Padding(..)+  , int+  , intWith+  , integer+  -- ** Fixded size hexidecimal formatting+  , hex, heX+  -- ** IEEE float formating+  , B.FFormat(..)+  , double+  , doubleWith+  , float+  , floatWith+  , scientific+  , scientificWith+  ) where++import qualified Data.Scientific          as Sci+import           Data.String+import           Data.Bits+import qualified Std.Data.Builder.Base    as B+import qualified Std.Data.Builder.Numeric as B+import           Std.Data.Text.Base       (Text (..))++-- | Buidlers which guarantee UTF-8 encoding, thus can be used to build+-- text directly.+--+-- Notes on 'IsString' instance: It's recommended to use 'IsString' instance instead of 'stringUTF8'+-- or 'string7' since there's a rewrite rule to turn encoding loop into a memcpy, which is much faster.+--+-- Different from 'Builder ()', 'TextBuilder ()''s 'IsString' instance will gives desired UTF8 guarantees:+--+-- * "\NUL" will be written directly as @\x00@.+--+-- * @\xD800@ ~ @\xDFFF@ will be replaced by replacement char.+--+newtype TextBuilder a = TextBuilder { toBuilder :: B.Builder a }+    deriving (Functor, Applicative, Monad)++instance (a ~ ()) => IsString (TextBuilder a) where+    {-# INLINE fromString #-}+    fromString = stringUTF8++deriving instance Semigroup (TextBuilder ())+deriving instance Monoid (TextBuilder ())++buildText :: TextBuilder a -> Text+{-# INLINE buildText #-}+buildText = Text . B.buildBytes . toBuilder++--------------------------------------------------------------------------------++-- | Turn 'String' into 'TextBuilder' with UTF8 encoding+--+-- Illegal codepoints will be written as 'T.replacementChar's. This function will be rewritten into a memcpy if possible, (running a fast UTF-8 validation at runtime first).+stringUTF8 :: String -> TextBuilder ()+{-# INLINE stringUTF8 #-}+stringUTF8 = TextBuilder . B.stringUTF8++-- | Turn 'Char' into 'TextBuilder' with UTF8 encoding+--+-- Illegal codepoints will be written as 'T.replacementChar's.+charUTF8 :: Char -> TextBuilder ()+{-# INLINE charUTF8 #-}+charUTF8 = TextBuilder . B.charUTF8++-- | Turn 'String' into 'TextBuilder' with ASCII7 encoding+--+-- Codepoints beyond @'\x7F'@ will be chopped.+string7 :: String -> TextBuilder ()+{-# INLINE string7 #-}+string7 = TextBuilder . B.string7++-- | Turn 'Char' into 'TextBuilder' with ASCII7 encoding+--+-- Codepoints beyond @'\x7F'@ will be chopped.+char7 :: Char -> TextBuilder ()+{-# INLINE char7 #-}+char7 = TextBuilder . B.char7++-- | Write UTF8 encoded 'Text' using 'Builder'.+--+-- Note, if you're trying to write string literals builders,+-- please open 'OverloadedStrings' and use 'Builder's 'IsString' instance,+-- it will be rewritten into a memcpy.+text :: Text -> TextBuilder ()+{-# INLINE text #-}+text = TextBuilder . B.text++--------------------------------------------------------------------------------++-- | @int = intWith defaultIFormat@+int :: (Integral a, Bounded a) => a -> TextBuilder ()+{-# INLINE int #-}+int = TextBuilder . B.int++-- | Format a 'Bounded' 'Integral' type like @Int@ or @Word16@ into decimal ascii digits.+intWith :: (Integral a, Bounded a)+        => B.IFormat+        -> a+        -> TextBuilder ()+{-# INLINE intWith #-}+intWith fmt x = TextBuilder $ B.intWith fmt x++-- | Format a 'Integer' into decimal ascii digits.+integer :: Integer -> TextBuilder ()+{-# INLINE integer #-}+integer = TextBuilder . B.integer++-- | Format a 'FiniteBits' 'Integral' type into hex nibbles.+hex :: (FiniteBits a, Integral a) => a -> TextBuilder ()+{-# INLINE hex #-}+hex = TextBuilder . B.hex++-- | The UPPERCASED version of 'hex'.+heX :: (FiniteBits a, Integral a) => a -> TextBuilder ()+{-# INLINE heX #-}+heX = TextBuilder . B.heX++-- | Decimal encoding of an IEEE 'Float'.+--+-- Using standard decimal notation for arguments whose absolute value lies+-- between @0.1@ and @9,999,999@, and scientific notation otherwise.+float :: Float -> TextBuilder ()+{-# INLINE float #-}+float = TextBuilder . B.float++-- | Format single-precision float using drisu3 with dragon4 fallback.+floatWith :: B.FFormat+          -> Maybe Int  -- ^ Number of decimal places to render.+          -> Float+          -> TextBuilder ()+{-# INLINE floatWith #-}+floatWith fmt ds x = TextBuilder (B.floatWith fmt ds x)+++-- | Decimal encoding of an IEEE 'Double'.+--+-- Using standard decimal notation for arguments whose absolute value lies+-- between @0.1@ and @9,999,999@, and scientific notation otherwise.+double :: Double -> TextBuilder ()+{-# INLINE double #-}+double = TextBuilder . B.double++-- | Format double-precision float using drisu3 with dragon4 fallback.+doubleWith :: B.FFormat+           -> Maybe Int  -- ^ Number of decimal places to render.+           -> Double+           -> TextBuilder ()+{-# INLINE doubleWith #-}+doubleWith fmt ds x = TextBuilder (B.doubleWith fmt ds x)+++-- | A @Builder@ which renders a scientific number to full+-- precision, using standard decimal notation for arguments whose+-- absolute value lies between @0.1@ and @9,999,999@, and scientific+-- notation otherwise.+scientific :: Sci.Scientific -> TextBuilder ()+{-# INLINE scientific #-}+scientific = TextBuilder . B.scientific++-- | Like 'scientific' but provides rendering options.+scientificWith :: B.FFormat+               -> Maybe Int  -- ^ Number of decimal places to render.+               -> Sci.Scientific+               -> TextBuilder ()+{-# INLINE scientificWith #-}+scientificWith fmt ds x = TextBuilder (B.scientificWith fmt ds x)
+ Std/Data/Vector.hs view
@@ -0,0 +1,179 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE CApiFFI #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE UnliftedFFITypes #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE QuasiQuotes #-}++{-|+Module      : Std.Data.Vector+Description : Fast boxed and unboxed vector+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provide fast boxed and unboxed vector with unified interface.+The API is similar to bytestring and vector. If you find missing functions, please report!++Performance consideration:++  * Use 'PrimVector' for 'Prim' types, it stores content in packed memory, and it's+    strict on its elements (following strictness consideration are mainly for lifted+    'Vector' type), many functions DO NOT NEED the result vectors's type to be same+    with the source one, e.g. @map :: (Vec v a, Vec u b) => (a -> b) -> v a -> u b@.++  * There're some specialized function which only works on 'Bytes', which is enabled+    with rewrite rules, if you want to use specialized versions directly, import+    "Std.Data.Vector.Base" and "Std.Data.Vector.Extra" module. Doing so will also+    enable vector internals, which is useful for working on the underlying arrays.++  * The 'Functor' instance for 'Vector' are lazy in order to abid 'Functor' law.+    namely @fmap id vectorConatinBottom == vectorContainBottom@, if you need strict mapping+    for lifted 'Vector', use 'map'' ('PrimVector' will never contain bottom thus it's not+    a problem). THIS MAY COME AS A SURPRISE SO MAKE SURE YOU USE THE CORRECT 'map' s.++  * The 'Foldable' instance for 'Vector' is fine, use 'Prelude' functions such as+    'null', 'length', etc. should not incur performance overhead, though there're+    partial functions you should avoid, i.e. foldl1, foldr1, maximum, minimum. Use+    'foldl1Maybe'', 'foldr1Maybe'', 'maximumMaybe', 'minmumMaybe' instead.++  * The 'Traversable' instance have specialized implementations for 'ST' and 'IO',+    if you don't want to write thunks into result vector, use @return <$!>@ idiom.++  * When use stateful generating functions like 'mapAccumL', 'mapAccumR' ,etc. force+    both the accumulator and value with @acc `seq` v `seq` (acc, v)@ idiom to avoid+    thunks inside result vector.++  * The 'unpack', 'unpackR' and 'pack', 'packN', 'packR', 'packRN' are designed to+    work with @build/foldr@ streaming fusion in base, thus it's OK to expect idioms like++        > pack . List filter f . List.map . unpack++        to work in contant space. While++        > Vector.filter . Vector.map++        will create intermediate vectors on the fly, which have different time/space characteristic.++Since all functions works on more general types, inlining and specialization are the keys+to achieve high performance, e.g. the performance gap between running in GHCi and+compiled binary may be huge due to dictionary passing. If there're cases that GHC fail to+specialized these functions, it should be regarded as a bug either in this library or GHC.++-}++module Std.Data.Vector (+  -- * The Vec typeclass+    Vec+  -- * Boxed and unboxed vector type+  , Vector+  , PrimVector+  -- ** Word8 vector+  , Bytes, packASCII+  -- * Basic creating+  , empty, singleton, copy+  -- * Conversion between list+  , pack, packN, packR, packRN+  , unpack, unpackR+  -- * Basic interface+  , null+  , length+  , append+  , map, map', imap'+  , foldl', ifoldl', foldl1', foldl1Maybe'+  , foldr', ifoldr', foldr1', foldr1Maybe'+    -- ** Special folds+  , concat, concatMap+  , maximumMaybe, minimumMaybe+  , sum+  , count+  , product, product'+  , all, any+  -- * Building vector+  -- ** Accumulating maps+  , mapAccumL+  , mapAccumR+  -- ** Generating and unfolding vector+  , replicate+  , cycleN+  , unfoldr+  , unfoldrN+  -- * Searching by equality+  , elem, notElem, elemIndex+  -- * Slice manipulation+  , cons, snoc+  , uncons, unsnoc+  , headMaybe, tailMayEmpty+  , lastMaybe, initMayEmpty+  , inits, tails+  , take, drop, takeR, dropR+  , slice+  , splitAt+  , takeWhile, takeWhileR, dropWhile, dropWhileR, dropAround+  , break, span, breakR, spanR, breakOn+  , group, groupBy+  , stripPrefix, stripSuffix+  , split, splitWith, splitOn+  , isPrefixOf, isSuffixOf, isInfixOf+  , commonPrefix+  , words, lines, unwords, unlines+  , padLeft, padRight+  -- * Transform+  , reverse+  , intersperse+  , intercalate+  , intercalateElem+  , transpose+  -- * Zipping+  , zipWith', unzipWith'+  -- * Scans+  , scanl', scanl1'+  , scanr', scanr1'+  -- * Search+  -- ** element-wise search+  , find, findR+  , findIndices, elemIndices+  , filter, partition+  -- ** sub-vector search+  , indicesOverlapping+  , indices+  -- * Sort+  -- ** comparison search+  , mergeSort+  , mergeSortBy+  , mergeTileSize+  , insertSort+  , insertSortBy+  , Down(..)+  -- ** radix search+  , radixSort+  , Radix(..)+  , RadixDown(..)+  -- * QuasiQuoters+  , ascii+  , vecW8, vecW16, vecW32, vecW64, vecWord+  , vecI8, vecI16, vecI32, vecI64, vecInt+  -- * Misc+  , IPair(..)+  , VectorException(..)+  , castVector+ ) where++import           Prelude ()+import           Std.Data.Vector.Base+import           Std.Data.Vector.Extra+import           Std.Data.Vector.Search+import           Std.Data.Vector.Sort+import           Std.Data.Vector.QQ
+ Std/Data/Vector/Base.hs view
@@ -0,0 +1,1244 @@+{-# LANGUAGE BangPatterns           #-}+{-# LANGUAGE DeriveDataTypeable     #-}+{-# LANGUAGE FlexibleContexts       #-}+{-# LANGUAGE FlexibleInstances      #-}+{-# LANGUAGE MagicHash              #-}+{-# LANGUAGE MultiParamTypeClasses  #-}+{-# LANGUAGE PatternSynonyms        #-}+{-# LANGUAGE RankNTypes             #-}+{-# LANGUAGE ScopedTypeVariables    #-}+{-# LANGUAGE TypeFamilies           #-}+{-# LANGUAGE TypeFamilyDependencies #-}+{-# LANGUAGE UnboxedTuples          #-}+{-# LANGUAGE ViewPatterns           #-}+{-# LANGUAGE UnliftedFFITypes       #-}+{-# LANGUAGE QuantifiedConstraints  #-}++{-|+Module      : Std.Data.Vector.Base+Description : Fast boxed and unboxed vector+Copyright   : (c) Dong Han, 2017-2019+              (c) Tao He, 2018-2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provides unified vector interface. Conceptually a vector is simply a slice of an array, for example this is the definition of boxed vector:++@+data Vector a = Vector !(SmallArray a)   !Int    !Int+                     -- payload           offset  length+@++The 'Vec' class unified different type of vectors, and this module provide operation over 'Vec' instances, with all the internal structures. Be careful on modifying internal slices, otherwise segmentation fault await.++-}++module Std.Data.Vector.Base (+  -- * The Vec typeclass+    Vec(..)+  , pattern Vec+  , indexMaybe+  -- * Boxed and unboxed vector type+  , Vector(..)+  , PrimVector(..)+  -- ** Word8 vector+  , Bytes, packASCII+  , w2c, c2w+  -- * Basic creating+  , create, create', creating, creating', createN, createN2+  , empty, singleton, copy+  -- * Conversion between list+  , pack, packN, packR, packRN+  , unpack, unpackR+  -- * Basic interface+  , null+  , length+  , append+  , map, map', imap'+  , foldl', ifoldl', foldl1', foldl1Maybe'+  , foldr', ifoldr', foldr1', foldr1Maybe'+    -- ** Special folds+  , concat, concatMap+  , maximum, minimum+  , maximumMaybe, minimumMaybe+  , sum+  , count+  , product, product'+  , all, any+  -- * Building vector+  -- ** Accumulating maps+  , mapAccumL+  , mapAccumR+  -- ** Generating and unfolding vector+  , replicate+  , cycleN+  , unfoldr+  , unfoldrN+  -- * Searching by equality+  , elem, notElem, elemIndex+  -- * Misc+  , IPair(..)+  , defaultInitSize+  , chunkOverhead+  , defaultChunkSize+  , smallChunkSize+  , VectorException(..)+  , errorEmptyVector+  , errorOutRange+  , castVector+  -- * C FFI+  , c_strcmp+  , c_strlen+  , c_ascii_validate_addr+  , c_fnv_hash_addr+  , c_fnv_hash_ba+ ) where++import           Control.DeepSeq+import           Control.Exception+import           Control.Monad+import           Control.Monad.ST+import           Data.Bits+import           Data.Char                     (ord)+import           Data.Data+import qualified Data.Foldable                 as F+import           Data.Functor.Identity+import           Data.Hashable                 (Hashable(..), hashByteArrayWithSalt)+import           Data.Hashable.Lifted          (Hashable1(..), hashWithSalt1)+import qualified Data.List                     as List+import           Data.Maybe+import           Data.Monoid                   (Monoid (..))+import           Data.Word8                    (toLower)+import qualified Data.CaseInsensitive          as CI+import           Data.Primitive+import           Data.Primitive.PrimArray+import           Data.Primitive.SmallArray+import           Data.Primitive.Ptr+import           Data.Semigroup                (Semigroup ((<>)))+import           Data.String                   (IsString(..))+import qualified Data.Traversable              as T+import           Data.Typeable+import           Foreign.C+import           GHC.CString+import           GHC.Exts                      (build)+import           GHC.Stack+import           GHC.Prim+import           GHC.Ptr+import           GHC.Types+import           GHC.Word+import           Prelude                       hiding (concat, concatMap,+                                                elem, notElem, null, length, map,+                                                foldl, foldl1, foldr, foldr1,+                                                maximum, minimum, product, sum,+                                                all, any, replicate, traverse)+import           System.IO.Unsafe              (unsafeDupablePerformIO)++import           Std.Data.Array+import           Std.Data.PrimArray.BitTwiddle (c_memchr)+import           Std.Data.PrimArray.Cast++-- | Typeclass for box and unboxed vectors, which are created by slicing arrays.+--+class (Arr (MArray v) (IArray v) a) => Vec v a where+    -- | Vector's mutable array type+    type MArray v = (marr :: * -> * -> *) | marr -> v+    -- | Vector's immutable array type+    type IArray v = (iarr :: * -> *) | iarr -> v+    -- | Get underline array and slice range(offset and length).+    toArr :: v a -> (IArray v a, Int, Int)+    -- | Create a vector by slicing an array(with offset and length).+    fromArr :: IArray v a -> Int -> Int -> v a++-- | A pattern synonyms for matching the underline array, offset and length.+--+-- This is a bidirectional pattern synonyms, but very unsafe if not use properly.+-- Make sure your slice is within array's bounds!+pattern Vec :: Vec v a => IArray v a -> Int -> Int -> v a+pattern Vec arr s l <- (toArr -> (arr,s,l)) where+        Vec arr s l = fromArr arr s l++-- | /O(1)/ Index array element.+--+-- Return 'Nothing' if index is out of bounds.+--+indexMaybe :: (Vec v a, HasCallStack) => v a -> Int -> Maybe a+{-# INLINE indexMaybe #-}+indexMaybe (Vec arr s l) i | i < 0 || i >= l = Nothing+                           | otherwise       = arr `indexArrM` (s + i)++--------------------------------------------------------------------------------+-- | Boxed vector+--+data Vector a = Vector+    {-# UNPACK #-} !(SmallArray a)  -- ^ payload+    {-# UNPACK #-} !Int             -- ^ offset+    {-# UNPACK #-} !Int             -- ^ length+    deriving (Typeable, Data)++instance Vec Vector a where+    type MArray Vector = SmallMutableArray+    type IArray Vector = SmallArray+    {-# INLINE toArr #-}+    toArr (Vector arr s l) = (arr, s, l)+    {-# INLINE fromArr #-}+    fromArr = Vector++instance Eq a => Eq (Vector a) where+    {-# INLINABLE (==) #-}+    v1 == v2 = eqVector v1 v2++eqVector :: Eq a => Vector a -> Vector a -> Bool+{-# INLINE eqVector #-}+eqVector (Vector baA sA lA) (Vector baB sB lB)+    | baA `sameArr` baB =+        if sA == sB then lA == lB else lA == lB && go sA sB+    | otherwise = lA == lB && go sA sB+  where+    !endA = sA + lA+    go !i !j+        | i >= endA = True+        | otherwise =+            (indexSmallArray baA i == indexSmallArray baB j) && go (i+1) (j+1)++instance Ord a => Ord (Vector a) where+    {-# INLINABLE compare #-}+    compare = compareVector++compareVector :: Ord a => Vector a -> Vector a -> Ordering+{-# INLINE compareVector #-}+compareVector (Vector baA sA lA) (Vector baB sB lB)+    | baA `sameArr` baB = if sA == sB then lA `compare` lB else go sA sB+    | otherwise = go sA sB+  where+    !endA = sA + lA+    !endB = sB + lB+    go !i !j | i >= endA  = endA `compare` endB+             | j >= endB  = endA `compare` endB+             | otherwise = let o = indexSmallArray baA i `compare` indexSmallArray baB j+                           in case o of EQ -> go (i+1) (j+1)+                                        x  -> x++instance Semigroup (Vector a) where+    {-# INLINE (<>) #-}+    (<>)    = append++instance Monoid (Vector a) where+    {-# INLINE mempty #-}+    mempty  = empty+    {-# INLINE mappend #-}+    mappend = append+    {-# INLINE mconcat #-}+    mconcat = concat++instance NFData a => NFData (Vector a) where+    {-# INLINE rnf #-}+    rnf (Vector arr s l) = go s+      where+        !end = s+l+        go !i | i < end   = case indexArr' arr i of (# x #) -> x `seq` go (i+1)+              | otherwise = ()++instance (Show a) => Show (Vector a) where+    showsPrec p v = showsPrec p (unpack v)++instance (Read a) => Read (Vector a) where+    readsPrec p str = [ (pack x, y) | (x, y) <- readsPrec p str ]++instance Functor Vector where+    {-# INLINE fmap #-}+    fmap = map++instance F.Foldable Vector where+    {-# INLINE foldr' #-}+    foldr' = foldr'+    {-# INLINE foldr #-}+    foldr f acc = List.foldr f acc . unpack+    {-# INLINE foldl' #-}+    foldl' = foldl'+    {-# INLINE foldl #-}+    foldl f acc = List.foldr (flip f) acc . unpackR+    {-# INLINE toList #-}+    toList = unpack+    {-# INLINE null #-}+    null = null+    {-# INLINE length #-}+    length = length+    {-# INLINE elem #-}+    elem = elem+    {-# INLINE maximum #-}+    maximum = maximum+    {-# INLINE minimum #-}+    minimum = minimum+    {-# INLINE product #-}+    product = product+    {-# INLINE sum #-}+    sum = sum++instance T.Traversable Vector where+    traverse = traverse++instance Hashable a => Hashable (Vector a) where+    {-# INLINE hashWithSalt #-}+    hashWithSalt = hashWithSalt1++instance Hashable1 Vector where+    {-# INLINE liftHashWithSalt #-}+    liftHashWithSalt h salt (Vector arr s l) = hashWithSalt (go salt s) l+      where+        !end = s + l+        go !salt !i+            | i >= end  = salt+            | otherwise = go (h salt (indexArr arr i)) (i+1)++traverse :: (Vec v a, Vec u b, Applicative f) => (a -> f b) -> v a -> f (u b)+{-# INLINE [1] traverse #-}+{-# RULES "traverse/ST" traverse = traverseST #-}+{-# RULES "traverse/IO" traverse = traverseIO #-}+traverse f v = packN (length v) <$> T.traverse f (unpack v)++traverseST :: forall v u a b s. (Vec v a, Vec u b) => (a -> ST s b) -> v a -> ST s (u b)+{-# INLINE traverseST #-}+traverseST f (Vec arr s l)+    | l == 0    = return empty+    | otherwise = do+        marr <- newArr l+        go marr 0+        ba <- unsafeFreezeArr marr+        return $! fromArr ba 0 l+  where+    go :: MArray u s b -> Int -> ST s ()+    go !marr !i+        | i >= l = return ()+        | otherwise = do+            x <- indexArrM arr i+            writeArr marr i =<< f x+            go marr (i+1)++traverseIO :: forall v u a b. (Vec v a, Vec u b) => (a -> IO b) -> v a -> IO (u b)+{-# INLINE traverseIO #-}+traverseIO f (Vec arr s l)+    | l == 0    = return empty+    | otherwise = do+        marr <- newArr l+        go marr 0+        ba <- unsafeFreezeArr marr+        return $! fromArr ba 0 l+  where+    go :: MArray u RealWorld b -> Int -> IO ()+    go !marr !i+        | i >= l = return ()+        | otherwise = do+            x <- indexArrM arr i+            writeArr marr i =<< f x+            go marr (i+1)++--------------------------------------------------------------------------------+-- | Primitive vector+--+data PrimVector a = PrimVector+    {-# UNPACK #-} !(PrimArray a) -- payload+    {-# UNPACK #-} !Int         -- offset in elements of type a rather than in bytes+    {-# UNPACK #-} !Int         -- length in elements of type a rather than in bytes+  deriving Typeable++instance Prim a => Vec PrimVector a where+    type MArray PrimVector = MutablePrimArray+    type IArray PrimVector = PrimArray+    {-# INLINE toArr #-}+    toArr (PrimVector arr s l) = (arr, s, l)+    {-# INLINE fromArr #-}+    fromArr arr s l = PrimVector arr s l++instance (Prim a, Eq a) => Eq (PrimVector a) where+    {-# INLINE (==) #-}+    (==) = eqPrimVector++eqPrimVector :: forall a. Prim a => PrimVector a -> PrimVector a -> Bool+{-# INLINE eqPrimVector #-}+eqPrimVector (PrimVector (PrimArray baA#) (I# sA#) lA@(I# lA#))+             (PrimVector (PrimArray baB#) (I# sB#) lB@(I# lB#))+    = -- we use memcmp for all primitive vector, ghc emit code to test+      -- pointer equality so we don't have to do it manually here+      lA == lB &&+        0 == I# (compareByteArrays# baA# (sA# *# siz#) baB# (sB# *# siz#) n#)+  where+    siz@(I# siz#) = sizeOf (undefined :: a)+    (I# n#) = min (lA*siz) (lB*siz)++instance {-# OVERLAPPABLE #-} (Prim a, Ord a) => Ord (PrimVector a) where+    {-# INLINE compare #-}+    compare = comparePrimVector++instance {-# OVERLAPPING #-} Ord (PrimVector Word8) where+    {-# INLINE compare #-}+    compare = compareBytes++comparePrimVector :: (Prim a, Ord a) => PrimVector a -> PrimVector a -> Ordering+{-# INLINE comparePrimVector #-}+comparePrimVector (PrimVector baA sA lA) (PrimVector baB sB lB)+    | baA `sameArr` baB = if sA == sB then lA `compare` lB else go sA sB+    | otherwise = go sA sB+  where+    !endA = sA + lA+    !endB = sB + lB+    go !i !j | i >= endA  = endA `compare` endB+             | j >= endB  = endA `compare` endB+             | otherwise = let o = indexPrimArray baA i `compare` indexPrimArray baB j+                           in case o of EQ -> go (i+1) (j+1)+                                        x  -> x++compareBytes :: PrimVector Word8 -> PrimVector Word8 -> Ordering+{-# INLINE compareBytes #-}+compareBytes (PrimVector (PrimArray baA#) (I# sA#) lA@(I# lA#))+             (PrimVector (PrimArray baB#) (I# sB#) lB@(I# lB#)) =+    let (I# n#) = min lA lB+        r = I# (compareByteArrays# baA# sA# baB# sB# n#)+    in case r `compare` 0 of+        EQ  -> lA `compare` lB+        x  -> x++instance Prim a => Semigroup (PrimVector a) where+    {-# INLINE (<>) #-}+    (<>)    = append++instance Prim a => Monoid (PrimVector a) where+    {-# INLINE mempty #-}+    mempty  = empty+    {-# INLINE mappend #-}+    mappend = append+    {-# INLINE mconcat #-}+    mconcat = concat++instance NFData (PrimVector a) where+    {-# INLINE rnf #-}+    rnf PrimVector{} = ()++instance (Prim a, Show a) => Show (PrimVector a) where+    showsPrec p v = showsPrec p (unpack v)++instance (Prim a, Read a) => Read (PrimVector a) where+    readsPrec p str = [ (pack x, y) | (x, y) <- readsPrec p str ]++instance  {-# OVERLAPPABLE #-}  (Hashable a, Prim a) => Hashable (PrimVector a) where+    {-# INLINE hashWithSalt #-}+    -- we don't do a final hash with length to keep consistent with Bytes's instance+    hashWithSalt salt (PrimVector arr s l) = go salt s+      where+        !end = s + l+        go !salt !i+            | i >= end  = salt+            | otherwise = go (hashWithSalt salt (indexPrimArray arr i)) (i+1)++instance {-# OVERLAPPING #-} Hashable (PrimVector Word8) where+    {-# INLINE hashWithSalt #-}+    hashWithSalt salt (PrimVector (PrimArray ba#) s l) =+        unsafeDupablePerformIO (c_fnv_hash_ba ba# s l salt)++--------------------------------------------------------------------------------++-- | 'Bytes' is just primitive word8 vectors.+type Bytes = PrimVector Word8++instance (a ~ Word8) => IsString (PrimVector a) where+    {-# INLINE fromString #-}+    fromString = packASCII++instance CI.FoldCase Bytes where+    {-# INLINE foldCase #-}+    foldCase = map toLower++packASCII :: String -> Bytes+{-# INLINE CONLIKE [1] packASCII #-}+{-# RULES+    "packASCII/packStringAddr" forall addr . packASCII (unpackCString# addr) = packStringAddr addr+  #-}+packASCII = pack . fmap (fromIntegral . ord)++packStringAddr :: Addr# -> Bytes+{-# INLINABLE packStringAddr #-}+packStringAddr addr# = validateAndCopy addr#+  where+    len = fromIntegral . unsafeDupablePerformIO $ c_strlen addr#+    valid = unsafeDupablePerformIO $ c_ascii_validate_addr addr# len+    validateAndCopy addr#+        | valid == 0 = pack . fmap (fromIntegral . ord) $ unpackCString# addr#+        | otherwise = runST $ do+            marr <- newPrimArray len+            copyPtrToMutablePrimArray marr 0 (Ptr addr#) len+            arr <- unsafeFreezePrimArray marr+            return (PrimVector arr 0 len)++-- | Conversion between 'Word8' and 'Char'. Should compile to a no-op.+--+w2c :: Word8 -> Char+{-# INLINE w2c #-}+w2c (W8# w#) = C# (chr# (word2Int# w#))++-- | Unsafe conversion between 'Char' and 'Word8'. This is a no-op and+-- silently truncates to 8 bits Chars > '\255'. It is provided as+-- convenience for PrimVector construction.+c2w :: Char -> Word8+{-# INLINE c2w #-}+c2w (C# c#) = W8# (int2Word# (ord# c#))++--------------------------------------------------------------------------------+-- Basic creating++-- | Create a vector with size N.+--+create :: Vec v a+       => Int                                   -- ^ length in elements of type @a@+       -> (forall s. MArray v s a -> ST s ())   -- ^ initialization function+       -> v a+{-# INLINE create #-}+create n0 fill = runST (do+        let n = max 0 n0+        marr <- newArr n+        fill marr+        ba <- unsafeFreezeArr marr+        return $! fromArr ba 0 n)++-- | Create a vector with a initial size N array (which may not be the final array).+--+create' :: Vec v a+        => Int                                                      -- ^ length in elements of type @a@+        -> (forall s. MArray v s a -> ST s (IPair (MArray v s a)))  -- ^ initialization function+                                                                    --   return a result size and array+                                                                    --   the result must start from index 0+        -> v a+{-# INLINE create' #-}+create' n0 fill = runST (do+        let n = max 0 n0+        marr <- newArr n+        IPair n' marr' <- fill marr+        shrinkMutableArr marr' n'+        ba <- unsafeFreezeArr marr'+        return $! fromArr ba 0 n')++-- | Create a vector with a initial size N array, return both the vector and+-- the monadic result during creating.+--+-- The result is not demanded strictly while the returned vector will be in normal form.+-- It this is not desired, use @return $!@ idiom in your initialization function.+creating :: Vec v a+         => Int  -- length in elements of type @a@+         -> (forall s. MArray v s a -> ST s b)  -- ^ initialization function+         -> (b, v a)+{-# INLINE creating #-}+creating n0 fill = runST (do+        let n = max 0 n0+        marr <- newArr n+        b <- fill marr+        ba <- unsafeFreezeArr marr+        let !v = fromArr ba 0 n+        return (b, v))++-- | Create a vector with a initial size N array (which may not be the final array),+-- return both the vector and the monadic result during creating.+--+-- The result is not demanded strictly while the returned vector will be in normal form.+-- It this is not desired, use @return $!@ idiom in your initialization function.+creating' :: Vec v a+         => Int  -- length in elements of type @a@+         -> (forall s. MArray v s a -> ST s (b, (IPair (MArray v s a))))  -- ^ initialization function+         -> (b, v a)+{-# INLINE creating' #-}+creating' n0 fill = runST (do+        let n = max 0 n0+        marr <- newArr n+        (b, IPair n' marr') <- fill marr+        shrinkMutableArr marr' n'+        ba <- unsafeFreezeArr marr'+        let !v = fromArr ba 0 n'+        return (b, v))++-- | Create a vector up to a specific length.+--+-- If the initialization function return a length larger than initial size,+-- an 'IndexOutOfVectorRange' will be raised.+--+createN :: (Vec v a, HasCallStack)+        => Int                                  -- ^ length's upper bound+        -> (forall s. MArray v s a -> ST s Int) -- ^ initialization function which return the actual length+        -> v a+{-# INLINE createN #-}+createN n0 fill = runST (do+        let n = max 0 n0+        marr <- newArr n+        l' <- fill marr+        shrinkMutableArr marr l'+        ba <- unsafeFreezeArr marr+        if l' <= n+        then return $! fromArr ba 0 l'+        else errorOutRange l')++-- | Create two vector up to a specific length.+--+-- If the initialization function return lengths larger than initial sizes,+-- an 'IndexOutOfVectorRange' will be raised.+--+createN2 :: (Vec v a, Vec u b, HasCallStack)+         => Int+         -> Int+         -> (forall s. MArray v s a -> MArray u s b -> ST s (Int,Int))+         -> (v a, u b)+{-# INLINE createN2 #-}+createN2 n0 n1 fill = runST (do+        let n0' = max 0 n0+            n1' = max 0 n1+        mba0 <- newArr n0'+        mba1 <- newArr n1'+        (l0, l1) <- fill mba0 mba1+        shrinkMutableArr mba0 l0+        shrinkMutableArr mba1 l1+        ba0 <- unsafeFreezeArr mba0+        ba1 <- unsafeFreezeArr mba1+        if (l0 <= n0)+        then if (l1 <= n1)+            then let !v1 = fromArr ba0 0 l0+                     !v2 = fromArr ba1 0 l1+                 in return (v1, v2)+            else errorOutRange l1+        else errorOutRange l0)++-- | /O(1)/. The empty vector.+--+empty :: Vec v a => v a+{-# INLINE empty #-}+empty = create 0 (\_ -> return ())++-- | /O(1)/. Single element vector.+singleton :: Vec v a => a -> v a+{-# INLINE singleton #-}+singleton c = create 1 (\ marr -> writeArr marr 0 c)++-- | /O(n)/. Copy a vector from slice.+--+copy :: Vec v a => v a -> v a+{-# INLINE copy #-}+copy (Vec ba s l) = create l (\ marr -> copyArr marr 0 ba s l)++--------------------------------------------------------------------------------+-- Conversion between list+--+-- | /O(n)/ Convert a list into a vector+--+-- Alias for @'packN' 'defaultInitSize'@.+--+pack :: Vec v a => [a] -> v a+{-# INLINE pack #-}+pack = packN defaultInitSize+++-- | /O(n)/ Convert a list into a vector with an approximate size.+--+-- If the list's length is large than the size given, we simply double the buffer size+-- and continue building.+--+-- This function is a /good consumer/ in the sense of build/foldr fusion.+--+packN :: forall v a. Vec v a => Int -> [a] -> v a+{-# INLINE packN #-}+packN n0 = \ ws0 -> runST (do let n = max 4 n0+                              marr <- newArr n+                              (IPair i marr') <- foldM go (IPair 0 marr) ws0+                              shrinkMutableArr marr' i+                              ba <- unsafeFreezeArr marr'+                              return $! fromArr ba 0 i+                          )+  where+    -- It's critical that this function get specialized and unboxed+    -- Keep an eye on its core!+    go :: IPair (MArray v s a) -> a -> ST s (IPair (MArray v s a))+    go (IPair i marr) x = do+        n <- sizeofMutableArr marr+        if i < n+        then do writeArr marr i x+                return (IPair (i+1) marr)+        else do let !n' = n `shiftL` 1+                !marr' <- resizeMutableArr marr n'+                writeArr marr' i x+                return (IPair (i+1) marr')++-- | /O(n)/ Alias for @'packRN' 'defaultInitSize'@.+--+packR :: Vec v a => [a] -> v a+{-# INLINE packR #-}+packR = packRN defaultInitSize++-- | /O(n)/ 'packN' in reverse order.+--+-- This function is a /good consumer/ in the sense of build/foldr fusion.+--+packRN :: forall v a. Vec v a => Int -> [a] -> v a+{-# INLINE packRN #-}+packRN n0 = \ ws0 -> runST (do let n = max 4 n0+                               marr <- newArr n+                               (IPair i marr') <- foldM go (IPair (n-1) marr) ws0+                               ba <- unsafeFreezeArr marr'+                               let i' = i + 1+                                   n' = sizeofArr ba+                               return $! fromArr ba i' (n'-i')+                           )+  where+    go :: IPair (MArray v s a) -> a -> ST s (IPair (MArray v s a))+    go (IPair i marr) !x = do+        n <- sizeofMutableArr marr+        if i >= 0+        then do writeArr marr i x+                return (IPair (i-1) marr)+        else do let !n' = n `shiftL` 1  -- double the buffer+                !marr' <- newArr n'+                copyMutableArr marr' n marr 0 n+                writeArr marr' (n-1) x+                return (IPair (n-2) marr')++-- | /O(n)/ Convert vector to a list.+--+-- Unpacking is done lazily. i.e. we will retain reference to the array until all element are consumed.+--+-- This function is a /good producer/ in the sense of build/foldr fusion.+unpack :: Vec v a => v a -> [a]+{-# INLINE [1] unpack #-}+unpack (Vec ba s l) = go s+  where+    !end = s + l+    go !idx+        | idx >= end = []+        | otherwise = case indexArr' ba idx of (# x #) -> x : go (idx+1)++unpackFB :: Vec v a => v a -> (a -> r -> r) -> r -> r+{-# INLINE [0] unpackFB #-}+unpackFB (Vec ba s l) k z = go s+  where+    !end = s + l+    go !idx+        | idx >= end = z+        | otherwise = case indexArr' ba idx of (# x #) -> x `k` go (idx+1)++{-# RULES+"unpack" [~1] forall v . unpack v = build (\ k z -> unpackFB v k z)+"unpackFB" [1] forall v . unpackFB v (:) [] = unpack v+ #-}++-- | /O(n)/ Convert vector to a list in reverse order.+--+-- This function is a /good producer/ in the sense of build/foldr fusion.+unpackR :: Vec v a => v a -> [a]+{-# INLINE [1] unpackR #-}+unpackR (Vec ba s l) = go (s + l - 1)+  where+    go !idx+        | idx < s = []+        | otherwise =+            case indexArr' ba idx of (# x #) -> x : go (idx-1)++unpackRFB :: Vec v a => v a -> (a -> r -> r) -> r -> r+{-# INLINE [0] unpackRFB #-}+unpackRFB (Vec ba s l) k z = go (s + l - 1)+  where+    go !idx+        | idx < s = z+        | otherwise =+            case indexArr' ba idx of (# x #) -> x `k` go (idx-1)++{-# RULES+"unpackR" [~1] forall v . unpackR v = build (\ k z -> unpackRFB v k z)+"unpackRFB" [1] forall v . unpackRFB v (:) [] = unpackR v+ #-}++--------------------------------------------------------------------------------+-- Basic interface+--+-- |  /O(1)/ The length of a vector.+length :: Vec v a => v a -> Int+{-# INLINE length #-}+length (Vec _ _ l) = l++-- | /O(1)/ Test whether a vector is empty.+null :: Vec v a => v a -> Bool+{-# INLINE null #-}+null v = length v == 0++-- | /O(m+n)/+--+-- There's no need to guard empty vector because we guard them for you, so+-- appending empty vectors are no-ops.+append :: Vec v a => v a -> v a -> v a+{-# INLINE append #-}+append (Vec _ _ 0) b                    = b+append a                (Vec _ _ 0)     = a+append (Vec baA sA lA) (Vec baB sB lB) = create (lA+lB) $ \ marr -> do+    copyArr marr 0  baA sA lA+    copyArr marr lA baB sB lB++--------------------------------------------------------------------------------++-- | Mapping between vectors (possiblely with two different vector types).+--+-- NOTE, the result vector contain thunks in lifted 'Vector' case, use 'map''+-- if that's not desired.+--+-- For 'PrimVector', 'map' and 'map'' are same, since 'PrimVector's never+-- store thunks.+map :: forall u v a b. (Vec u a, Vec v b) => (a -> b) -> u a -> v b+{-# INLINE map #-}+map f (Vec arr s l) = create l (go 0)+  where+    go :: Int -> MArray v s b -> ST s ()+    go !i !marr | i >= l = return ()+                | otherwise = do+                    x <- indexArrM arr (i+s); writeArr marr i (f x);+                    go (i+1) marr++-- | Mapping between vectors (possiblely with two different vector types).+--+-- This is the strict version map. Note that the 'Functor' instance of lifted+-- 'Vector' is defined with 'map' to statisfy laws, which this strict version+-- breaks (@map' id arrayContainsBottom /= arrayContainsBottom @).+map' :: forall u v a b. (Vec u a, Vec v b) => (a -> b) -> u a -> v b+{-# INLINE map' #-}+map' f (Vec arr s l) = create l (go 0)+  where+    go :: Int -> MArray v s b -> ST s ()+    go !i !marr | i < l = do+                    x <- indexArrM arr (i+s)+                    let !v = f x in writeArr marr i v+                    go (i+1) marr+               | otherwise = return ()++-- | Strict mapping with index.+--+imap' :: forall u v a b. (Vec u a, Vec v b) => (Int -> a -> b) -> u a -> v b+{-# INLINE imap' #-}+imap' f (Vec arr s l) = create l (go 0)+  where+    go :: Int -> MArray v s b -> ST s ()+    go !i !marr | i < l = do+                    x <- indexArrM arr (i+s)+                    let !v = f i x in writeArr marr i v+                    go (i+1) marr+               | otherwise = return ()++--------------------------------------------------------------------------------+--+-- Strict folds+--++-- | Strict left to right fold.+foldl' :: Vec v a => (b -> a -> b) -> b -> v a -> b+{-# INLINE foldl' #-}+foldl' f z (Vec arr s l) = go z s+  where+    !end = s + l+    -- tail recursive; traverses array left to right+    go !acc !i | i < end  = case indexArr' arr i of+                                (# x #) -> go (f acc x) (i + 1)+               | otherwise = acc++-- | Strict left to right fold with index.+ifoldl' :: Vec v a => (b -> Int ->  a -> b) -> b -> v a -> b+{-# INLINE ifoldl' #-}+ifoldl' f z (Vec arr s l) = go z s+  where+    !end = s + l+    go !acc !i | i < end  = case indexArr' arr i of+                                (# x #) -> go (f acc i x) (i + 1)+               | otherwise = acc++-- | Strict left to right fold using first element as the initial value.+--+-- Throw 'EmptyVector' if vector is empty.+foldl1' :: forall v a. (Vec v a, HasCallStack) => (a -> a -> a) -> v a -> a+{-# INLINE foldl1' #-}+foldl1' f (Vec arr s l)+    | l <= 0    = errorEmptyVector+    | otherwise = case indexArr' arr s of+                    (# x0 #) -> foldl' f x0 (fromArr arr (s+1) (l-1) :: v a)++-- | Strict left to right fold using first element as the initial value.+--   return 'Nothing' when vector is empty.+foldl1Maybe' :: forall v a. Vec v a => (a -> a -> a) -> v a -> Maybe a+{-# INLINE foldl1Maybe' #-}+foldl1Maybe' f (Vec arr s l)+    | l <= 0    = Nothing+    | otherwise = case indexArr' arr s of+                    (# x0 #) -> let !r = foldl' f x0 (fromArr arr (s+1) (l-1) :: v a)+                                in Just r++-- | Strict right to left fold+foldr' :: Vec v a => (a -> b -> b) -> b -> v a -> b+{-# INLINE foldr' #-}+foldr' f z (Vec arr s l) = go z (s+l-1)+  where+    -- tail recursive; traverses array right to left+    go !acc !i | i >= s    = case indexArr' arr i of+                                (# x #) -> go (f x acc) (i - 1)+               | otherwise = acc++-- | Strict right to left fold with index+--+-- NOTE: the index is counting from 0, not backwards+ifoldr' :: Vec v a => (Int -> a -> b -> b) -> b -> v a -> b+{-# INLINE ifoldr' #-}+ifoldr' f z (Vec arr s l) = go z (s+l-1) 0+  where+    go !acc !i !k | i >= s    = case indexArr' arr i of+                                    (# x #) -> go (f k x acc) (i - 1) (k + 1)+                  | otherwise = acc++-- | Strict right to left fold using last element as the initial value.+--+-- Throw 'EmptyVector' if vector is empty.+foldr1' :: forall v a. (Vec v a, HasCallStack) => (a -> a -> a) -> v a -> a+{-# INLINE foldr1' #-}+foldr1' f (Vec arr s l)+    | l <= 0 = errorEmptyVector+    | otherwise = case indexArr' arr (s+l-1) of+                    (# x0 #) -> foldl' f x0 (fromArr arr s (l-1) :: v a)++-- | Strict right to left fold using last element as the initial value,+--   return 'Nothing' when vector is empty.+foldr1Maybe' :: forall v a. Vec v a => (a -> a -> a) -> v a -> Maybe a+{-# INLINE foldr1Maybe' #-}+foldr1Maybe' f (Vec arr s l)+    | l <= 0 = Nothing+    | otherwise = case indexArr' arr (s+l-1) of+                    (# x0 #) -> let !r = foldl' f x0 (fromArr arr s (l-1) :: v a)+                                in Just r++--------------------------------------------------------------------------------+--+-- Special folds+--+-- | /O(n)/ Concatenate a list of vector.+--+-- Note: 'concat' have to force the entire list to filter out empty vector and calculate+-- the length for allocation.+concat :: forall v a . Vec v a => [v a] -> v a+{-# INLINE concat #-}+concat [v] = v  -- shortcut common case in Parser+concat vs = case pre 0 0 vs of+    (1, _) -> let Just v = List.find (not . null) vs in v -- there must be a not null vector+    (_, l) -> create l (copy vs 0)+  where+    -- pre scan to decide if we really need to copy and calculate total length+    -- we don't accumulate another result list, since it's rare to got empty+    pre :: Int -> Int -> [v a] -> (Int, Int)+    pre !nacc !lacc [] = (nacc, lacc)+    pre !nacc !lacc (v@(Vec _ _ l):vs)+        | l <= 0    = pre nacc lacc vs+        | otherwise = pre (nacc+1) (l+lacc) vs++    copy :: [v a] -> Int -> MArray v s a -> ST s ()+    copy [] !_ !_                   = return ()+    copy (Vec ba s l:vs) !i !marr = do when (l /= 0) (copyArr marr i ba s l)+                                       copy vs (i+l) marr++-- | Map a function over a vector and concatenate the results+concatMap :: Vec v a => (a -> v a) -> v a -> v a+{-# INLINE concatMap #-}+concatMap f = concat . foldr' ((:) . f) []++-- | /O(n)/ 'maximum' returns the maximum value from a vector+--+-- It's defined with 'foldl1'', an 'EmptyVector' exception will be thrown+-- in the case of an empty vector.+maximum :: (Vec v a, Ord a, HasCallStack) => v a -> a+{-# INLINE maximum #-}+maximum = foldl1' max++-- | /O(n)/ 'maximum' returns the maximum value from a vector,+--   return 'Nothing' in the case of an empty vector.+maximumMaybe :: (Vec v a, Ord a, HasCallStack) => v a -> Maybe a+{-# INLINE maximumMaybe #-}+maximumMaybe = foldl1Maybe' max++-- | /O(n)/ 'minimum' returns the minimum value from a 'vector'+--+-- An 'EmptyVector' exception will be thrown in the case of an empty vector.+minimum :: (Vec v a, Ord a, HasCallStack) => v a -> a+{-# INLINE minimum #-}+minimum = foldl1' min++-- | /O(n)/ 'minimum' returns the minimum value from a vector,+--   return 'Nothing' in the case of an empty vector.+minimumMaybe :: (Vec v a, Ord a, HasCallStack) => v a -> Maybe a+{-# INLINE minimumMaybe #-}+minimumMaybe = foldl1Maybe' min++-- | /O(n)/ 'product' returns the product value from a vector+product :: (Vec v a, Num a) => v a -> a+{-# INLINE product #-}+product = foldl' (*) 1++-- | /O(n)/ 'product' returns the product value from a vector+--+-- This function will shortcut on zero. Note this behavior change the semantics+-- for lifted vector: @product [1,0,undefined] /= product' [1,0,undefined]@.+product' :: (Vec v a, Num a, Eq a) => v a -> a+{-# INLINE product' #-}+product' (Vec arr s l) = go 1 s+  where+    !end = s+l+    go !acc !i | acc == 0  = 0+               | i >= end  = acc+               | otherwise = case indexArr' arr i of+                                (# x #) -> go (acc*x) (i+1)++-- | /O(n)/ Applied to a predicate and a vector, 'any' determines+-- if any elements of the vector satisfy the predicate.+any :: Vec v a => (a -> Bool) -> v a -> Bool+{-# INLINE any #-}+any f (Vec arr s l)+    | l <= 0    = False+    | otherwise = case indexArr' arr s of+                    (# x0 #) -> go (f x0) (s+1)+  where+    !end = s+l+    go !acc !i | acc       = True+               | i >= end  = acc+               | otherwise = case indexArr' arr i of+                                (# x #) -> go (acc || f x) (i+1)++-- | /O(n)/ Applied to a predicate and a vector, 'all' determines+-- if all elements of the vector satisfy the predicate.+all :: Vec v a => (a -> Bool) -> v a -> Bool+{-# INLINE all #-}+all f (Vec arr s l)+    | l <= 0    = True+    | otherwise = case indexArr' arr s of+                    (# x0 #) -> go (f x0) (s+1)+  where+    !end = s+l+    go !acc !i | not acc   = False+               | i >= end  = acc+               | otherwise = case indexArr' arr i of+                                (# x #) -> go (acc && f x) (i+1)++-- | /O(n)/ 'sum' returns the sum value from a 'vector'+sum :: (Vec v a, Num a) => v a -> a+{-# INLINE sum #-}+sum = foldl' (+) 0++-- | /O(n)/ 'count' returns count of an element from a 'vector'+count :: (Vec v a, Eq a) => a -> v a -> Int+{-# INLINE count #-}+count w = foldl' (\ acc x -> if x == w then acc+1 else acc) 0++--------------------------------------------------------------------------------+-- Accumulating maps++-- | The 'mapAccumL' function behaves like a combination of 'map' and+-- 'foldl'; it applies a function to each element of a vector,+-- passing an accumulating parameter from left to right, and returning a+-- final value of this accumulator together with the new list.+--+-- Note, this function will only force the result tuple, not the elements inside,+-- to prevent creating thunks during 'mapAccumL', `seq` your accumulator and result+-- with the result tuple.+--+mapAccumL :: forall u v a b c. (Vec u b, Vec v c) => (a -> b -> (a, c)) -> a -> u b -> (a, v c)+{-# INLINE mapAccumL #-}+mapAccumL f z (Vec ba s l)+    | l <= 0    = (z, empty)+    | otherwise = creating l (go z s)+  where+    !end = s + l+    go :: a -> Int -> MArray v s c -> ST s a+    go acc !i !marr+        | i >= end = return acc+        | otherwise = do+            x <- indexArrM ba i+            let (acc', c) = acc `f` x+            writeArr marr (i-s) c+            go acc' (i+1) marr++-- | The 'mapAccumR' function behaves like a combination of 'map' and+-- 'foldr'; it applies a function to each element of a vector,+-- passing an accumulating parameter from right to left, and returning a+-- final value of this accumulator together with the new vector.+--+-- The same strictness property with 'mapAccumL' applys to 'mapAccumR' too.+--+mapAccumR :: forall u v a b c. (Vec u b, Vec v c) => (a -> b -> (a, c)) -> a -> u b -> (a, v c)+{-# INLINE mapAccumR #-}+mapAccumR f z (Vec ba s l)+    | l <= 0    = (z, empty)+    | otherwise = creating l (go z (s+l-1))+  where+    go :: a -> Int ->  MArray v s c -> ST s a+    go acc !i !marr+        | i < s     = return acc+        | otherwise = do+            x <- indexArrM ba i+            let (acc', c) = acc `f` x+            writeArr marr (i-s) c+            go acc' (i-1) marr++--------------------------------------------------------------------------------+--  Generating and unfolding vector.+--+-- | /O(n)/ 'replicate' @n x@ is a vector of length @n@ with @x@+-- the value of every element.+--+-- Note: 'replicate' will not force the element in boxed vector case.+replicate :: (Vec v a) => Int -> a -> v a+{-# INLINE replicate #-}+replicate n x | n <= 0    = empty+              | otherwise = create n (\ marr -> setArr marr 0 n x)++-- | /O(n*m)/ 'cycleN' a vector n times.+cycleN :: forall v a. Vec v a => Int -> v a -> v a+{-# INLINE cycleN #-}+cycleN n (Vec arr s l)+    | l == 0    = empty+    | otherwise = create end (go 0)+  where+    !end = n*l+    go :: Int -> MArray v s a -> ST s ()+    go !i !marr | i >= end  = return ()+                | otherwise = copyArr marr i arr s l >> go (i+l) marr++-- | /O(n)/, where /n/ is the length of the result.  The 'unfoldr'+-- function is analogous to the List \'unfoldr\'.  'unfoldr' builds a+-- vector from a seed value. The function takes the element and+-- returns 'Nothing' if it is done producing the vector or returns+-- 'Just' @(a,b)@, in which case, @a@ is the next byte in the string,+-- and @b@ is the seed value for further production.+--+-- Examples:+--+-- >    unfoldr (\x -> if x <= 5 then Just (x, x + 1) else Nothing) 0+-- > == pack [0, 1, 2, 3, 4, 5]+--+unfoldr :: Vec u b => (a -> Maybe (b, a)) -> a -> u b+{-# INLINE unfoldr #-}+unfoldr f = pack . List.unfoldr f++-- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a vector from a seed+-- value.  However, the length of the result is limited by the first+-- argument to 'unfoldrN'.  This function is more efficient than 'unfoldr'+-- when the maximum length of the result is known.+--+-- The following equation relates 'unfoldrN' and 'unfoldr':+--+-- > fst (unfoldrN n f s) == take n (unfoldr f s)+--+unfoldrN :: forall v a b. Vec v b => Int -> (a -> Maybe (b, a)) -> a -> (v b, Maybe a)+{-# INLINE unfoldrN #-}+unfoldrN n f+    | n < 0     = \ z -> (empty, Just z)+    | otherwise = \ z ->+        let ((r, len), Vec arr _ _) = creating n (go z 0)+        in (Vec arr 0 len, r)+  where+    go :: a -> Int -> MArray v s b -> ST s (Maybe a, Int)+    go !acc !i !marr+      | n == i    = return (Just acc, i)+      | otherwise = case f acc of+          Nothing        -> return (Nothing, i)+          Just (x, acc') -> do writeArr marr i x+                               go acc' (i+1) marr++--------------------------------------------------------------------------------+-- Searching by equality++-- | /O(n)/ 'elem' test if given element is in given vector.+elem :: (Vec v a, Eq a) => a -> v a -> Bool+{-# INLINE elem #-}+elem x = isJust . elemIndex x++-- | /O(n)/ 'not . elem'+notElem ::  (Vec v a, Eq a) => a -> v a -> Bool+{-# INLINE notElem #-}+notElem x = not . elem x++-- | /O(n)/ The 'elemIndex' function returns the index of the first+-- element in the given vector which is equal to the query+-- element, or 'Nothing' if there is no such element.+elemIndex :: (Vec v a, Eq a) => a -> v a -> Maybe Int+{-# INLINE [1] elemIndex #-}+{-# RULES "elemIndex/Bytes" elemIndex = elemIndexBytes #-}+elemIndex w (Vec arr s l) = go s+  where+    !end = s + l+    go !i+        | i >= end = Nothing+        | x == w   = let !i' = i - s in Just i'+        | otherwise = go (i+1)+        where (# x #) = indexArr' arr i++-- | /O(n)/ Special 'elemIndex' for 'Bytes' using @memchr(3)@+--+-- On most platforms @memchr(3)@ is a highly optimized byte searching+-- function, thus we make a special binding for it.+--+-- A rewrite rule @elemIndex = elemIndexBytes@ is also included.+elemIndexBytes :: Word8 -> Bytes -> Maybe Int+{-# INLINE elemIndexBytes #-}+elemIndexBytes w (PrimVector (PrimArray ba#) s l) =+    case fromIntegral (c_memchr ba# s w l) of+        -1 -> Nothing+        r  -> Just r++--------------------------------------------------------------------------------++-- | Index pair type to help GHC unpack in some loops, useful when write fast folds.+data IPair a = IPair {-# UNPACK #-}!Int a++-- | The chunk size used for I\/O. Currently set to @32k-chunkOverhead@+defaultChunkSize :: Int+{-# INLINE defaultChunkSize #-}+defaultChunkSize = 32 * 1024 - chunkOverhead++-- | The recommended chunk size. Currently set to @4k - chunkOverhead@.+smallChunkSize :: Int+{-# INLINE smallChunkSize #-}+smallChunkSize = 4 * 1024 - chunkOverhead++-- | The memory management overhead. Currently this is tuned for GHC only.+chunkOverhead :: Int+{-# INLINE chunkOverhead #-}+chunkOverhead = 2 * sizeOf (undefined :: Int)++-- | @defaultInitSize = 30@, used as initialize size when packing list of unknown size.+defaultInitSize :: Int+{-# INLINE defaultInitSize #-}+defaultInitSize = 30++data VectorException = IndexOutOfVectorRange {-# UNPACK #-} !Int CallStack+                     | EmptyVector CallStack+                    deriving (Show, Typeable)+instance Exception VectorException++errorEmptyVector :: HasCallStack => a+{-# NOINLINE errorEmptyVector #-}+errorEmptyVector = throw (EmptyVector callStack)++errorOutRange :: HasCallStack => Int -> a+{-# NOINLINE errorOutRange #-}+errorOutRange i = throw (IndexOutOfVectorRange i callStack)++-- | Cast between vectors+castVector :: (Vec v a, Cast a b) => v a -> v b+castVector = unsafeCoerce#++--------------------------------------------------------------------------------++foreign import ccall unsafe "string.h strcmp"+    c_strcmp :: Addr# -> Addr# -> IO CInt++foreign import ccall unsafe "string.h strlen"+    c_strlen :: Addr# -> IO CSize++foreign import ccall unsafe "text.h ascii_validate_addr"+    c_ascii_validate_addr :: Addr# -> Int -> IO Int++foreign import ccall unsafe "bytes.h hs_fnv_hash_addr"+    c_fnv_hash_addr :: Addr# -> Int -> Int -> IO Int++foreign import ccall unsafe "bytes.h hs_fnv_hash"+    c_fnv_hash_ba :: ByteArray# -> Int -> Int -> Int -> IO Int
+ Std/Data/Vector/Extra.hs view
@@ -0,0 +1,834 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UnboxedTuples #-}++{-|+Module      : Std.Data.Vector.Extra+Description : Fast vector slice manipulation+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++Various combinators works on 'Vec' class instances.++-}++module Std.Data.Vector.Extra (+  -- * Slice manipulation+    cons, snoc+  , uncons, unsnoc+  , headMaybe, tailMayEmpty+  , lastMaybe, initMayEmpty+  , inits, tails+  , take, drop, takeR, dropR+  , slice+  , splitAt+  , takeWhile, takeWhileR, dropWhile, dropWhileR, dropAround+  , break, span, breakR, spanR, breakOn+  , group, groupBy+  , stripPrefix, stripSuffix+  , split, splitWith, splitOn+  , isPrefixOf, isSuffixOf, isInfixOf+  , commonPrefix+  , words, lines, unwords, unlines+  , padLeft, padRight+  -- * Transform+  , reverse+  , intersperse+  , intercalate+  , intercalateElem+  , transpose+  -- * Zipping+  , zipWith', unzipWith'+  -- * Scans+  , scanl', scanl1'+  , scanr', scanr1'+  -- * Misc+  , rangeCut+  -- * Unsafe operations+  , head+  , tail+  , init+  , last+  , index+  , unsafeHead+  , unsafeTail+  , unsafeInit+  , unsafeLast+  , unsafeIndex+  , unsafeTake+  , unsafeDrop+  ) where++import           Control.Monad.ST+import           GHC.Stack+import           GHC.Word+import           Std.Data.Array+import           Std.Data.Vector.Base+import           Std.Data.Vector.Search+import           Prelude                       hiding (concat, concatMap,+                                                elem, notElem, null, length, map,+                                                foldl, foldl1, foldr, foldr1,+                                                maximum, minimum, product, sum,+                                                all, any, replicate, traverse,+                                                head, tail, init, last,+                                                take, drop, splitAt,+                                                takeWhile, dropWhile,+                                                break, span, reverse,+                                                words, lines, unwords, unlines)+import qualified Data.List                     as List+import           Data.Bits+import           Control.Exception             (assert)++--------------------------------------------------------------------------------+-- Slice+--+-- | /O(n)/ 'cons' is analogous to (:) for lists, but of different+-- complexity, as it requires making a copy.+cons :: Vec v a => a -> v a -> v a+{-# INLINE cons #-}+cons x (Vec arr s l) = create (l+1) $ \ marr ->+    writeArr marr 0 x >> copyArr marr 1 arr s l++-- | /O(n)/ Append a byte to the end of a vector+snoc :: Vec v a => v a -> a -> v a+{-# INLINE snoc #-}+snoc (Vec arr s l) x = create (l+1) $ \ marr ->+    copyArr marr 0 arr s l >> writeArr marr l x++-- | /O(1)/ Extract the head and tail of a vector, return 'Nothing'+-- if it is empty.+uncons :: Vec v a => v a -> Maybe (a, v a)+{-# INLINE uncons #-}+uncons (Vec arr s l)+    | l <= 0    = Nothing+    | otherwise = let !v = fromArr arr (s+1) (l-1)+                  in case indexArr' arr s of (# x #) -> Just (x ,v)++-- | /O(1)/ Extract the init and last of a vector, return 'Nothing'+-- if vector is empty.+unsnoc :: Vec v a => v a -> Maybe (v a, a)+{-# INLINE unsnoc #-}+unsnoc (Vec arr s l)+    | l <= 0    = Nothing+    | otherwise = let !v = fromArr arr s (l-1)+                  in case indexArr' arr (s+l-1) of (# x #) -> Just (v, x)++-- | /O(1)/ Extract the first element of a vector.+headMaybe :: Vec v a => v a -> Maybe a+{-# INLINE headMaybe #-}+headMaybe (Vec arr s l)+    | l <= 0    = Nothing+    | otherwise = indexArrM arr s++-- | /O(1)/ Extract the elements after the head of a vector.+--+-- NOTE: 'tailMayEmpty' return empty vector in the case of an empty vector.+tailMayEmpty :: Vec v a => v a -> v a+{-# INLINE tailMayEmpty #-}+tailMayEmpty (Vec arr s l)+    | l <= 0    = empty+    | otherwise = fromArr arr (s+1) (l-1)++-- | /O(1)/ Extract the last element of a vector.+lastMaybe :: Vec v a => v a -> Maybe a+{-# INLINE lastMaybe #-}+lastMaybe (Vec arr s l)+    | l <= 0    = Nothing+    | otherwise = indexArrM arr (s+l-1)++-- | /O(1)/ Extract the elements before of the last one.+--+-- NOTE: 'initMayEmpty' return empty vector in the case of an empty vector.+initMayEmpty :: Vec v a => v a -> v a+{-# INLINE initMayEmpty #-}+initMayEmpty (Vec arr s l)+    | l <= 0    = empty+    | otherwise = fromArr arr s (l-1)++-- | /O(n)/ Return all initial segments of the given vector, empty first.+inits :: Vec v a => v a -> [v a]+{-# INLINE inits #-}+inits (Vec arr s l) =  [Vec arr s n | n <- [0..l]]++-- | /O(n)/ Return all final segments of the given vector, whole vector first.+tails :: Vec v a => v a -> [v a]+{-# INLINE tails #-}+tails (Vec arr s l) = [Vec arr (s+n) (l-n) | n <- [0..l]]++-- | /O(1)/ 'take' @n@, applied to a vector @xs@, returns the prefix+-- of @xs@ of length @n@, or @xs@ itself if @n > 'length' xs@.+take :: Vec v a => Int -> v a -> v a+{-# INLINE take #-}+take n v@(Vec arr s l)+    | n <= 0    = empty+    | n >= l    = v+    | otherwise = fromArr arr s n++-- | /O(1)/ 'takeR' @n@, applied to a vector @xs@, returns the suffix+-- of @xs@ of length @n@, or @xs@ itself if @n > 'length' xs@.+takeR :: Vec v a => Int -> v a -> v a+{-# INLINE takeR #-}+takeR n v@(Vec arr s l)+    | n <= 0    = empty+    | n >= l    = v+    | otherwise = fromArr arr (s+l-n) n++-- | /O(1)/ 'drop' @n xs@ returns the suffix of @xs@ after the first @n@+-- elements, or @[]@ if @n > 'length' xs@.+drop :: Vec v a => Int -> v a -> v a+{-# INLINE drop #-}+drop n v@(Vec arr s l)+    | n <= 0    = v+    | n >= l    = empty+    | otherwise = fromArr arr (s+n) (l-n)++-- | /O(1)/ 'dropR' @n xs@ returns the prefix of @xs@ before the last @n@+-- elements, or @[]@ if @n > 'length' xs@.+dropR :: Vec v a => Int -> v a -> v a+{-# INLINE dropR #-}+dropR n v@(Vec arr s l)+    | n <= 0    = v+    | n >= l    = empty+    | otherwise = fromArr arr s (l-n)++-- | /O(1)/ Extract a sub-range vector with give start index and length.+--+-- This function is a total function just like 'take/drop', index/length+-- exceeds range will be ingored, e.g.+--+-- @+-- slice 1 3 "hello"   == "ell"+-- slice -1 -1 "hello" == ""+-- slice -2 2 "hello"  == ""+-- slice 2 10 "hello"  == "llo"+-- @+--+-- This holds for all x y: @slice x y vs == drop x . take (x+y) vs@+slice :: Vec v a => Int     -- ^ slice beginning index+                 -> Int     -- ^ slice length+                 -> v a -> v a+{-# INLINE slice #-}+slice x y = drop x . take (x+y)++-- | /O(1)/ 'splitAt' @n xs@ is equivalent to @('take' n xs, 'drop' n xs)@.+splitAt :: Vec v a => Int -> v a -> (v a, v a)+{-# INLINE splitAt #-}+splitAt z (Vec arr s l) = let !v1 = fromArr arr s z'+                              !v2 = fromArr arr (s+z') (l-z')+                          in (v1, v2)+  where z' = rangeCut z 0 l++-- | /O(n)/ Applied to a predicate @p@ and a vector @vs@,+-- returns the longest prefix (possibly empty) of @vs@ of elements that+-- satisfy @p@.+takeWhile :: Vec v a => (a -> Bool) -> v a -> v a+{-# INLINE takeWhile #-}+takeWhile f v@(Vec arr s l) =+    case findIndex (not . f) v of+        0  -> empty+        i  -> Vec arr s i++-- | /O(n)/ Applied to a predicate @p@ and a vector @vs@,+-- returns the longest suffix (possibly empty) of @vs@ of elements that+-- satisfy @p@.+takeWhileR :: Vec v a => (a -> Bool) -> v a -> v a+{-# INLINE takeWhileR #-}+takeWhileR f v@(Vec arr s l) =+    case findIndexR (not . f) v of+        -1 -> v+        i  -> Vec arr (s+i+1) (l-i-1)++-- | /O(n)/ Applied to a predicate @p@ and a vector @vs@,+-- returns the suffix (possibly empty) remaining after 'takeWhile' @p vs@.+dropWhile :: Vec v a => (a -> Bool) -> v a -> v a+{-# INLINE dropWhile #-}+dropWhile f v@(Vec arr s l) =+    case findIndex (not . f) v of+        i | i == l     -> empty+          | otherwise  -> Vec arr (s+i) (l-i)++-- | /O(n)/ Applied to a predicate @p@ and a vector @vs@,+-- returns the prefix (possibly empty) remaining before 'takeWhileR' @p vs@.+dropWhileR :: Vec v a => (a -> Bool) -> v a -> v a+{-# INLINE dropWhileR #-}+dropWhileR f v@(Vec arr s l) =+    case findIndexR (not . f) v of+        -1 -> empty+        i  -> Vec arr s (i+1)++-- | /O(n)/ @dropAround f = dropWhile f . dropWhileR f@+dropAround :: Vec v a => (a -> Bool) -> v a -> v a+{-# INLINE dropAround #-}+dropAround f = dropWhile f . dropWhileR f+++-- | /O(n)/ Split the vector into the longest prefix of elements that do not satisfy the predicate and the rest without copying.+break :: Vec v a => (a -> Bool) -> v a -> (v a, v a)+{-# INLINE break #-}+break f vs@(Vec arr s l) =+    let !n =  findIndex f vs+        !v1 = Vec arr s n+        !v2 = Vec arr (s+n) (l-n)+    in (v1, v2)++-- | /O(n)/ Split the vector into the longest prefix of elements that satisfy the predicate and the rest without copying.+span :: Vec v a => (a -> Bool) -> v a -> (v a, v a)+{-# INLINE span #-}+span f = break (not . f)++-- | 'breakR' behaves like 'break' but from the end of the vector.+--+-- @breakR p == spanR (not.p)@+breakR :: Vec v a => (a -> Bool) -> v a -> (v a, v a)+{-# INLINE breakR #-}+breakR f vs@(Vec arr s l) =+    let !n = findIndexR f vs+        !v1 = Vec arr s (n+1)+        !v2 = Vec arr (s+n+1) (l-1-n)+    in (v1, v2)++-- | 'spanR' behaves like 'span' but from the end of the vector.+spanR :: Vec v a => (a -> Bool) -> v a -> (v a, v a)+{-# INLINE spanR #-}+spanR f = breakR (not . f)++-- | Break a vector on a subvector, returning a pair of the part of the+-- vector prior to the match, and the rest of the vector, e.g.+--+-- > break "wor" "hello, world" = ("hello, ", "world")+--+breakOn :: (Vec v a, Eq a) => v a -> v a -> (v a, v a)+{-# INLINE breakOn #-}+breakOn needle = \ haystack@(Vec arr s l) ->+    case search haystack False of+        (i:_) -> let !v1 = Vec arr s i+                     !v2 = Vec arr (s+i) (l-i)+                 in (v1, v2)+        _     -> (haystack, empty)+  where search = indices needle+++group :: (Vec v a, Eq a) => v a -> [v a]+{-# INLINE group #-}+group = groupBy (==)++groupBy :: Vec v a =>  (a -> a -> Bool) -> v a -> [v a]+{-# INLINE groupBy #-}+groupBy f (Vec arr s l)+    | l == 0    = []+    | otherwise = Vec arr s n : groupBy f (Vec arr (s+n) (l-n))+  where+    n = case indexArr' arr s of+        (# x #) -> 1 + findIndex (not . f x) (Vec arr (s+1) (l-1))++-- | /O(n)/ The 'stripPrefix' function takes two vectors and returns 'Just'+-- the remainder of the second iff the first is its prefix, and otherwise+-- 'Nothing'.+--+stripPrefix :: (Vec v a, Eq (v a))+            => v a      -- ^ the prefix to be tested+            -> v a -> Maybe (v a)+{-# INLINE stripPrefix #-}+stripPrefix v1@(Vec _ _ l1) v2@(Vec arr s l2)+   | v1 `isPrefixOf` v2 = Just (Vec arr (s+l1) (l2-l1))+   | otherwise = Nothing++-- | The 'isPrefix' function returns 'True' if the first argument is a prefix of the second.+isPrefixOf :: (Vec v a, Eq (v a))+           => v a       -- ^ the prefix to be tested+           -> v a -> Bool+{-# INLINE isPrefixOf #-}+isPrefixOf (Vec arrA sA lA) (Vec arrB sB lB)+    | lA == 0 = True+    | lA > lB = False+    | otherwise = Vec arrA sA lA == Vec arrB sB lA++-- | /O(n)/ Find the longest non-empty common prefix of two strings+-- and return it, along with the suffixes of each string at which they+-- no longer match. e.g.+--+-- >>> commonPrefix "foobar" "fooquux"+-- ("foo","bar","quux")+--+-- >>> commonPrefix "veeble" "fetzer"+-- ("","veeble","fetzer")+commonPrefix :: (Vec v a, Eq a) => v a -> v a -> (v a, v a, v a)+{-# INLINE commonPrefix #-}+commonPrefix vA@(Vec arrA sA lA) vB@(Vec arrB sB lB) = go sA sB+  where+    !endA = sA + lA+    !endB = sB + lB+    go !i !j | i >= endA = let !vB' = fromArr arrB (sB+i-sA) (lB-i+sA) in (vA, empty, vB')+             | j >= endB = let !vA' = fromArr arrA (sA+j-sB) (lA-j+sB) in (vB, vA', empty)+             | indexArr arrA i == indexArr arrB j = go (i+1) (j+1)+             | otherwise =+                let !vB' = fromArr arrB (sB+i-sA) (lB-i+sA)+                    !vA' = fromArr arrA (sA+j-sB) (lA-j+sB)+                    !vC  = fromArr arrA sA (i-sA)+                in (vC, vA', vB')++-- | O(n) The 'stripSuffix' function takes two vectors and returns Just the remainder of the second iff the first is its suffix, and otherwise Nothing.+stripSuffix :: (Vec v a, Eq (v a)) => v a -> v a -> Maybe (v a)+{-# INLINE stripSuffix #-}+stripSuffix v1@(Vec _ _ l1) v2@(Vec arr s l2)+   | v1 `isSuffixOf` v2 = Just (Vec arr s (l2-l1))+   | otherwise = Nothing++-- | /O(n)/ The 'isSuffixOf' function takes two vectors and returns 'True'+-- if the first is a suffix of the second.+isSuffixOf :: (Vec v a, Eq (v a)) => v a -> v a -> Bool+{-# INLINE isSuffixOf #-}+isSuffixOf (Vec arrA sA lA) (Vec arrB sB lB)+    | lA == 0 = True+    | lA > lB = False+    | otherwise = Vec arrA sA lA == Vec arrB (sB+lB-lA) lA++-- | Check whether one vector is a subvector of another.+--+-- @needle `isInfixOf` haystack === null haystack || indices needle haystake /= []@.+isInfixOf :: (Vec v a, Eq a) => v a -> v a -> Bool+{-# INLINE isInfixOf #-}+isInfixOf needle = \ haystack -> null haystack || search haystack False /= []+  where search = indices needle++-- | /O(n)/ Break a vector into pieces separated by the delimiter element+-- consuming the delimiter. I.e.+--+-- > split '\n' "a\nb\nd\ne" == ["a","b","d","e"]+-- > split 'a'  "aXaXaXa"    == ["","X","X","X",""]+-- > split 'x'  "x"          == ["",""]+--+-- and+--+-- > intercalate [c] . split c == id+-- > split == splitWith . (==)+--+-- NOTE, this function behavior different with bytestring's. see+-- <https://github.com/haskell/bytestring/issues/56 #56>.+split :: (Vec v a, Eq a) => a -> v a -> [v a]+{-# INLINE split #-}+split x = splitWith (==x)++-- | /O(m+n)/ Break haystack into pieces separated by needle.+--+-- Note: An empty needle will essentially split haystack element+-- by element.+--+-- Examples:+--+-- >>> splitOn "\r\n" "a\r\nb\r\nd\r\ne"+-- ["a","b","d","e"]+--+-- >>> splitOn "aaa"  "aaaXaaaXaaaXaaa"+-- ["","X","X","X",""]+--+-- >>> splitOn "x"  "x"+-- ["",""]+--+-- and+--+-- > intercalate s . splitOn s         == id+-- > splitOn (singleton c)             == split (==c)+splitOn :: (Vec v a, Eq a) => v a -> v a -> [v a]+{-# INLINE splitOn #-}+splitOn needle = splitBySearch+  where+    splitBySearch haystack@(Vec arr s l) = go s (search haystack False)+      where+        !l' = length needle+        !end = s+l+        search = indices needle+        go !s' (i:is) = let !v = fromArr arr s' (i+s-s')+                               in v : go (i+l') is+        go !s' _      = let !v = fromArr arr s' (end-s') in [v]++-- | /O(n)/ Splits a vector into components delimited by+-- separators, where the predicate returns True for a separator element.+-- The resulting components do not contain the separators.  Two adjacent+-- separators result in an empty component in the output.  eg.+--+-- > splitWith (=='a') "aabbaca" == ["","","bb","c",""]+-- > splitWith (=='a') []        == [""]+--+-- NOTE, this function behavior different with bytestring's. see+-- <https://github.com/haskell/bytestring/issues/56 #56>.+splitWith :: Vec v a => (a -> Bool) -> v a -> [v a]+{-# INLINE splitWith #-}+splitWith f (Vec arr s l) = go s s+  where+    !end = s + l+    go !p !q | q >= end  = let !v = Vec arr p (q-p) in [v]+             | f x       = let !v = Vec arr p (q-p) in v:go (q+1) (q+1)+             | otherwise = go p (q+1)+        where (# x #) = indexArr' arr q++-- | /O(n)/ Breaks a 'Bytes' up into a list of words, delimited by ascii space.+words ::  Bytes -> [Bytes]+{-# INLINE words #-}+words (Vec arr s l) = go s s+  where+    !end = s + l+    go !s' !i | i >= end =+                    if s' == end+                    then []+                    else let !v = fromArr arr s' (end-s') in [v]+              | isASCIISpace (indexArr arr i) =+                    if s' == i+                    then go (i+1) (i+1)+                    else+                    let !v = fromArr arr s' (i-s') in v : go (i+1) (i+1)+              | otherwise = go s' (i+1)++-- | /O(n)/ Breaks a 'Bytes' up into a list of lines, delimited by ascii @\n@.+lines ::  Bytes -> [Bytes]+{-# INLINE lines #-}+lines (Vec arr s l) = go s s+  where+    !end = s + l+    go !p !q | q >= end              = if p == q+                                       then []+                                       else let !v = Vec arr p (q-p) in [v]+             | indexArr arr q == 10  = let !v = Vec arr p (q-p) in v:go (q+1) (q+1)+             | otherwise             = go p (q+1)++-- | /O(n)/ Joins words with ascii space.+unwords :: [Bytes] -> Bytes+{-# INLINE unwords #-}+unwords = intercalateElem 32++-- | /O(n)/ Joins lines with ascii @\n@.+unlines :: [Bytes] -> Bytes+{-# INLINE unlines #-}+unlines [] = empty+unlines vs = create (len vs 0) (copy 0 vs)+  where+    len []             !acc = acc+    len (Vec _ _ l:vs) !acc = len vs (acc+l+1)+    copy !i []               !marr = return ()+    copy !i (Vec arr s l:vs) !marr = do+        let !i' = i + l+        copyArr marr i arr s l+        writeArr marr i' 10+        copy (i'+1) vs marr++-- | Add padding to the left so that the whole vector's length is at least n.+padLeft :: Vec v a => Int -> a -> v a -> v a+{-# INLINE padLeft #-}+padLeft n x v@(Vec arr s l) | n <= l = v+                            | otherwise = create n (\ marr -> do+                                    setArr marr 0 (n-l) x+                                    copyArr marr (n-l) arr s l)++-- | Add padding to the right so that the whole vector's length is at least n.+padRight :: Vec v a => Int -> a -> v a -> v a+{-# INLINE padRight #-}+padRight n x v@(Vec arr s l) | n <= l = v+                             | otherwise = create n (\ marr -> do+                                    copyArr marr 0 arr s l+                                    setArr marr l (n-l) x)++--------------------------------------------------------------------------------+-- Transform++-- | /O(n)/ 'reverse' @vs@ efficiently returns the elements of @xs@ in reverse order.+--+reverse :: forall v a. (Vec v a) => v a -> v a+{-# INLINE reverse #-}+reverse (Vec arr s l) = create l (go s (l-1))+  where+    go :: Int -> Int -> MArray v s a -> ST s ()+    go !i !j !marr | j < 0 = return ()+                   | j >= 3 = do  -- a bit of loop unrolling here+                        indexArrM arr i >>= writeArr marr j+                        indexArrM arr (i+1) >>= writeArr marr (j-1)+                        indexArrM arr (i+2) >>= writeArr marr (j-2)+                        indexArrM arr (i+3) >>= writeArr marr (j-3)+                        go (i+4) (j-4) marr+                   | otherwise = do+                        indexArrM arr i >>= writeArr marr j+                        go (i+1) (j-1) marr++-- | /O(n)/ The 'intersperse' function takes an element and a+-- vector and \`intersperses\' that element between the elements of+-- the vector.  It is analogous to the intersperse function on+-- Lists.+--+intersperse :: forall v a. Vec v a => a -> v a -> v a+{-# INLINE intersperse #-}+intersperse x   (Vec _ _ 0)  = empty+intersperse x v@(Vec _ _ 1)  = v+intersperse x   (Vec arr s l) = create (2*l-1) (go s 0)+   where+    !end = s+l-1+    go :: Int         -- the reading index of orginal bytes+       -> Int         -- the writing index of new buf+       -> MArray v s a -- the new buf+       -> ST s ()+    go !i !j !marr+        | i >= end = writeArr marr j =<< indexArrM arr i+        | i <= end - 4 = do -- a bit of loop unrolling+            writeArr marr j =<< indexArrM arr i+            writeArr marr (j+1) x+            writeArr marr (j+2) =<< indexArrM arr (i+1)+            writeArr marr (j+3) x+            writeArr marr (j+4) =<< indexArrM arr (i+2)+            writeArr marr (j+5) x+            writeArr marr (j+6) =<< indexArrM arr (i+3)+            writeArr marr (j+7) x+            go (i+4) (j+8) marr+        | otherwise = do+            writeArr marr j =<< indexArrM arr i+            writeArr marr (j+1) x+            go (i+1) (j+2) marr++-- | /O(n)/ The 'intercalate' function takes a vector and a list of+-- vectors and concatenates the list after interspersing the first+-- argument between each element of the list.+--+-- Note: 'intercalate' will force the entire vector list.+--+intercalate :: Vec v a => v a -> [v a] -> v a+{-# INLINE intercalate #-}+intercalate s = concat . List.intersperse s++-- | /O(n)/ An efficient way to join vector with an element.+--+intercalateElem :: Vec v a => a -> [v a] -> v a+{-# INLINE intercalateElem #-}+intercalateElem _ [] = empty+intercalateElem _ [v] = v+intercalateElem w vs = create (len vs 0) (copy 0 vs)+  where+    len []             !acc = acc+    len [Vec _ _ l]    !acc = l + acc+    len (Vec _ _ l:vs) !acc = len vs (acc+l+1)+    copy !i []               !marr = return ()+    copy !i (Vec arr s l:[]) !marr = copyArr marr i arr s l+    copy !i (Vec arr s l:vs) !marr = do+        let !i' = i + l+        copyArr marr i arr s l+        writeArr marr i' w+        copy (i'+1) vs marr++-- | The 'transpose' function transposes the rows and columns of its+-- vector argument.+--+transpose :: Vec v a => [v a] -> [v a]+{-# INLINE transpose #-}+transpose vs =+    List.map (packN n) . List.transpose . List.map unpack $ vs+  where n = List.length vs++--------------------------------------------------------------------------------+--  Zipping++-- | 'zipWith'' zip two vector with a zipping function.+--+-- For example, @'zipWith' (+)@ is applied to two vector to produce+-- a vector of corresponding sums, the result will be evaluated strictly.+zipWith' :: (Vec v a, Vec u b, Vec w c)+         => (a -> b -> c) -> v a -> u b -> w c+{-# INLINE zipWith' #-}+zipWith' f (Vec arrA sA lA) (Vec arrB sB lB) = create len (go 0)+  where+    !len = min lA lB+    go !i !marr+        | i >= len = return ()+        | otherwise = case indexArr' arrA (i+sA) of+             (# a #) -> case indexArr' arrB (i+sB) of+                 (# b #) -> do let !c = f a b in writeArr marr i c+                               go (i+1) marr++-- | 'unzipWith'' disassemble a vector with a disassembling function,+--+-- The results inside tuple will be evaluated strictly.+unzipWith' :: (Vec v a, Vec u b, Vec w c)+           => (a -> (b, c)) -> v a -> (u b, w c)+{-# INLINE unzipWith' #-}+unzipWith' f (Vec arr s l) = createN2 l l (go 0)+  where+    go !i !marrB !marrC+        | i >= l = return (l,l)+        | otherwise = case indexArr' arr (i+s) of+            (# a #) -> do let (!b, !c) = f a+                          writeArr marrB i b+                          writeArr marrC i c+                          go (i+1) marrB marrC++--------------------------------------------------------------------------------+-- Scans++-- | 'scanl'' is similar to 'foldl', but returns a list of successive+-- reduced values from the left.+--+-- > scanl' f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]+--+-- Note that+--+-- > lastM (scanl' f z xs) == Just (foldl f z xs).+--+scanl' :: forall v u a b. (Vec v a, Vec u b) => (b -> a -> b) -> b -> v a -> u b+{-# INLINE scanl' #-}+scanl' f z (Vec arr s l) =+    create (l+1) (\ marr -> writeArr marr 0 z >> go z s 1 marr)+  where+    go :: b  -> Int -> Int -> MArray u s b -> ST s ()+    go !acc !i !j !marr+        | j > l = return ()+        | otherwise = do+            x <- indexArrM arr i+            let !acc' = acc `f` x+            writeArr marr j acc'+            go acc' (i+1) (j+1) marr++-- | 'scanl1\'' is a variant of 'scanl' that has no starting value argument.+--+-- > scanl1' f [x1, x2, ...] == [x1, x1 `f` x2, ...]+-- > scanl1' f [] == []+--+scanl1' :: forall v a. Vec v a => (a -> a -> a) -> v a -> v a+{-# INLINE scanl1' #-}+scanl1' f (Vec arr s l)+    | l <= 0    = empty+    | otherwise = case indexArr' arr s of+                    (# x0 #) -> scanl' f x0 (fromArr arr (s+1) (l-1) :: v a)++-- | scanr' is the right-to-left dual of scanl'.+--+scanr' :: forall v u a b. (Vec v a, Vec u b) => (a -> b -> b) -> b -> v a -> u b+{-# INLINE scanr' #-}+scanr' f z (Vec arr s l) =+    create (l+1) (\ marr -> writeArr marr l z >> go z (s+l-1) (l-1) marr)+  where+    go :: b -> Int -> Int -> MArray u s b -> ST s ()+    go !acc !i !j !marr+        | j < 0 = return ()+        | otherwise = do+            x <- indexArrM arr i+            let !acc' = x `f` acc+            writeArr marr j acc'+            go acc' (i-1) (j-1) marr++-- | 'scanr1'' is a variant of 'scanr' that has no starting value argument.+scanr1' :: forall v a. Vec v a => (a -> a -> a) -> v a -> v a+{-# INLINE scanr1' #-}+scanr1' f (Vec arr s l)+    | l <= 0    = empty+    | otherwise = case indexArr' arr (s+l-1) of+                    (# x0 #) -> scanr' f x0 (fromArr arr s (l-1) :: v a)++--------------------------------------------------------------------------------+-- Misc++-- | @x' = rangeCut x min max@ limit @x'@ 's range to @min@ ~ @max@.+rangeCut :: Int -> Int -> Int -> Int+{-# INLINE rangeCut #-}+rangeCut !r !min !max | r < min = min+                      | r > max = max+                      | otherwise = r++isASCIISpace :: Word8 -> Bool+{-# INLINE isASCIISpace #-}+isASCIISpace w = w == 32 || w - 0x9 <= 4 || w == 0xa0++--------------------------------------------------------------------------------++-- | /O(1)/ Extract the first element of a vector.+--+-- Throw 'EmptyVector' if vector is empty.+head :: (Vec v a, HasCallStack) => v a -> a+{-# INLINE head #-}+head (Vec arr s l)+    | l <= 0    = errorEmptyVector+    | otherwise = indexArr arr s++-- | /O(1)/ Extract the elements after the head of a vector.+--+-- Throw 'EmptyVector' if vector is empty.+tail :: (Vec v a, HasCallStack) => v a -> v a+{-# INLINE tail #-}+tail (Vec arr s l)+    | l <= 0    = errorEmptyVector+    | otherwise = fromArr arr (s+1) (l-1)++-- | /O(1)/ Extract the elements before of the last one.+--+-- Throw 'EmptyVector' if vector is empty.+init :: (Vec v a, HasCallStack) => v a -> v a+{-# INLINE init #-}+init (Vec arr s l)+    | l <= 0    = errorEmptyVector+    | otherwise = fromArr arr s (l-1)++-- | /O(1)/ Extract the last element of a vector.+--+-- Throw 'EmptyVector' if vector is empty.+last :: (Vec v a, HasCallStack) => v a -> a+{-# INLINE last #-}+last (Vec arr s l)+    | l <= 0    = errorEmptyVector+    | otherwise = indexArr arr (s+l-1)++-- | /O(1)/ Index array element.+--+-- Throw 'IndexOutOfVectorRange' if index outside of the vector.+index :: (Vec v a, HasCallStack) => v a -> Int -> a+{-# INLINE index #-}+index (Vec arr s l) i | i < 0 || i >= l = errorOutRange i+                      | otherwise       = arr `indexArr` (s + i)++-- | /O(1)/ Extract the first element of a vector.+--+-- Make sure vector is non-empty, otherwise segmentation fault await!+unsafeHead  :: Vec v a => v a -> a+{-# INLINE unsafeHead #-}+unsafeHead (Vec arr s l) = assert (l > 0) (indexArr arr s)++-- | /O(1)/ Extract the elements after the head of a vector.+--+-- Make sure vector is non-empty, otherwise segmentation fault await!+unsafeTail  :: Vec v a => v a -> v a+{-# INLINE unsafeTail #-}+unsafeTail (Vec arr s l) = assert (l > 0) (fromArr arr (s+1) (l-1))++-- | /O(1)/ Extract the elements before of the last one.+--+-- Make sure vector is non-empty, otherwise segmentation fault await!+unsafeInit  :: Vec v a => v a -> v a+{-# INLINE unsafeInit #-}+unsafeInit (Vec arr s l) = assert (l > 0) (fromArr arr s (l-1))++-- | /O(1)/ Extract the last element of a vector.+--+-- Make sure vector is non-empty, otherwise segmentation fault await!+unsafeLast  :: Vec v a => v a -> a+{-# INLINE unsafeLast #-}+unsafeLast (Vec arr s l) = assert (l > 0) (indexArr arr (s+l-1))++-- | /O(1)/ Index array element.+--+-- Make sure index is in bound, otherwise segmentation fault await!+unsafeIndex :: Vec v a => v a -> Int -> a+{-# INLINE unsafeIndex #-}+unsafeIndex (Vec arr s l) i = indexArr arr (s + i)++-- | /O(1)/ 'take' @n@, applied to a vector @xs@, returns the prefix+-- of @xs@ of length @n@.+--+-- Make sure n is smaller than vector's length, otherwise segmentation fault await!+unsafeTake :: Vec v a => Int -> v a -> v a+{-# INLINE unsafeTake #-}+unsafeTake n (Vec arr s l) = assert (0 <= n && n <= l) (fromArr arr s n)++-- | /O(1)/ 'drop' @n xs@ returns the suffix of @xs@ after the first @n@+-- elements.+--+-- Make sure n is smaller than vector's length, otherwise segmentation fault await!+unsafeDrop :: Vec v a => Int -> v a -> v a+{-# INLINE unsafeDrop #-}+unsafeDrop n (Vec arr s l) = assert (0 <= n && n <= l) (fromArr arr (s+n) (l-n))
+ Std/Data/Vector/QQ.hs view
@@ -0,0 +1,115 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE MagicHash #-}++{-|+Module      : Std.Data.Vector.QQ+Description : vectors literals using QuasiQuote+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provides functions for writing vector literals using 'QuasiQuote'.++-}++module Std.Data.Vector.QQ (+  -- * QuasiQuoters+    ascii+  , vecW8, vecW16, vecW32, vecW64, vecWord+  , vecI8, vecI16, vecI32, vecI64, vecInt+  ) where++import qualified Language.Haskell.TH.Quote     as QQ+import           Std.Data.PrimArray.QQ         as QQ+import           Std.Data.Vector.Base+import           GHC.Types (Int(..))++--------------------------------------------------------------------------------+-- Quoters++ascii :: QQ.QuasiQuoter+ascii = QQ.QuasiQuoter+    (asciiLiteral $ \ len addr -> [| PrimVector (QQ.word8ArrayFromAddr $(len) $(addr)) 0 (I# $(len)) |])+    (error "Cannot use ascii as a pattern")+    (error "Cannot use ascii as a type")+    (error "Cannot use ascii as a dec")++vecW8 :: QQ.QuasiQuoter+vecW8 = QQ.QuasiQuoter+    (QQ.word8Literal $ \ len addr -> [| PrimVector (QQ.word8ArrayFromAddr $(len) $(addr)) 0 (I# $(len)) |])+    (error "Cannot use vecW8 as a pattern")+    (error "Cannot use vecW8 as a type")+    (error "Cannot use vecW8 as a dec")++vecW16 :: QQ.QuasiQuoter+vecW16 = QQ.QuasiQuoter+    (QQ.word16Literal $ \ len addr -> [| PrimVector (QQ.word16ArrayFromAddr $(len) $(addr)) 0 (I# $(len)) |])+    (error "Cannot use vecW16 as a pattern")+    (error "Cannot use vecW16 as a type")+    (error "Cannot use vecW16 as a dec")++vecW32 :: QQ.QuasiQuoter+vecW32 = QQ.QuasiQuoter+    (QQ.word32Literal $ \ len addr -> [| PrimVector (QQ.word32ArrayFromAddr $(len) $(addr)) 0 (I# $(len)) |])+    (error "Cannot use vecW32 as a pattern")+    (error "Cannot use vecW32 as a type")+    (error "Cannot use vecW32 as a dec")++vecW64 :: QQ.QuasiQuoter+vecW64 = QQ.QuasiQuoter+    (QQ.word64Literal $ \ len addr -> [| PrimVector (QQ.word64ArrayFromAddr $(len) $(addr)) 0 (I# $(len)) |])+    (error "Cannot use vecW64 as a pattern")+    (error "Cannot use vecW64 as a type")+    (error "Cannot use vecW64 as a dec")++vecWord :: QQ.QuasiQuoter+vecWord = QQ.QuasiQuoter+    (QQ.wordLiteral $ \ len addr ->+        [| PrimVector (QQ.wordArrayFromAddr $(len) $(addr)) 0 (I# $(len)) |])+    (error "Cannot use vecWord as a pattern")+    (error "Cannot use vecWord as a type")+    (error "Cannot use vecWord as a dec")++vecI8 :: QQ.QuasiQuoter+vecI8 = QQ.QuasiQuoter+    (QQ.int8Literal $ \ len addr ->+        [| PrimVector (QQ.int8ArrayFromAddr $(len) $(addr)) 0 (I# $(len)) |])+    (error "Cannot use vecI8 as a pattern")+    (error "Cannot use vecI8 as a type")+    (error "Cannot use vecI8 as a dec")++vecI16 :: QQ.QuasiQuoter+vecI16 = QQ.QuasiQuoter+    (QQ.int16Literal $ \ len addr ->+        [| PrimVector (QQ.int16ArrayFromAddr $(len) $(addr)) 0 (I# $(len)) |])+    (error "Cannot use vecI16 as a pattern")+    (error "Cannot use vecI16 as a type")+    (error "Cannot use vecI16 as a dec")++vecI32 :: QQ.QuasiQuoter+vecI32 = QQ.QuasiQuoter+    (QQ.int32Literal $ \ len addr ->+        [| PrimVector (QQ.int32ArrayFromAddr $(len) $(addr)) 0 (I# $(len)) |])+    (error "Cannot use vecI32 as a pattern")+    (error "Cannot use vecI32 as a type")+    (error "Cannot use vecI32 as a dec")++vecI64 :: QQ.QuasiQuoter+vecI64 = QQ.QuasiQuoter+    (QQ.int64Literal $ \ len addr ->+        [| PrimVector (QQ.int64ArrayFromAddr $(len) $(addr)) 0 (I# $(len)) |])+    (error "Cannot use vecI64 as a pattern")+    (error "Cannot use vecI64 as a type")+    (error "Cannot use vecI64 as a dec")++vecInt :: QQ.QuasiQuoter+vecInt = QQ.QuasiQuoter+    (QQ.intLiteral $ \ len addr ->+        [| PrimVector (QQ.intArrayFromAddr $(len) $(addr)) 0 (I# $(len)) |])+    (error "Cannot use vecInt as a pattern")+    (error "Cannot use vecInt as a type")+    (error "Cannot use vecInt as a dec")+
+ Std/Data/Vector/Search.hs view
@@ -0,0 +1,463 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Std.Data.Vector.Search+Description : Searching vectors+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provides:++  * Element-wise searching within vectors++  * Fast sub-vector searching algorithm based on KMP string searching.++  * A hybrid sub-vector searching algorithm for 'Bytes'.++  * Rewrite rules to use 'Bytes' specialized version if possible.++-}++module Std.Data.Vector.Search (+  -- * Element-wise search+    findIndices, elemIndices+  , find, findR+  , findIndex, findIndexR+  , filter, partition+  -- * Sub-vector search+  , indicesOverlapping+  , indices+  -- * 'Bytes' specialized combinators+  , elemIndicesBytes, findByte, findByteR+  , indicesOverlappingBytes, indicesBytes+  -- * Helpers+  , kmpNextTable+  , sundayBloom+  , elemSundayBloom+  ) where++import           Control.Monad.ST+import           Data.Bits+import           GHC.Word+import           Prelude                       hiding (filter, partition)+import           Std.Data.Array+import           Std.Data.PrimArray.BitTwiddle (c_memchr, memchrReverse)+import           Std.Data.Vector.Base++--------------------------------------------------------------------------------+-- Searching by equality or predicate++-- | /O(n)/ The 'elemIndices' function extends 'elemIndex', by returning+-- the indices of all elements equal to the query element, in ascending order.+elemIndices :: (Vec v a, Eq a) => a -> v a -> [Int]+{-# INLINE [1] elemIndices #-}+{-# RULES "elemIndices/Bytes" elemIndices = elemIndicesBytes #-}+elemIndices w (Vec arr s l) = go s+  where+    !end = s + l+    go !i+        | i >= end  = []+        | x == w    = let !i' = i - s in i' : go (i+1)+        | otherwise = go (i+1)+        where (# x #) = indexArr' arr i++-- | The 'findIndex' function takes a predicate and a vector and+-- returns the index of the first element in the vector+-- satisfying the predicate.+findIndices :: Vec v a => (a -> Bool) -> v a -> [Int]+{-# INLINE [1] findIndices #-}+{-# RULES "findIndices/Bytes" forall w. findIndices (w `eqWord8`) = elemIndicesBytes w #-}+{-# RULES "findIndices/Bytes" forall w. findIndices (`eqWord8` w) = elemIndicesBytes w #-}+findIndices f (Vec arr s l) = go s+  where+    !end = s + l+    go !p | p >= end  = []+          | f x       = p : go (p+1)+          | otherwise = go (p+1)+        where (# x #) = indexArr' arr p++-- | /O(n)/ Special 'elemIndices' for 'Bytes' using @memchr(3)@+elemIndicesBytes :: Word8 -> Bytes -> [Int]+{-# INLINE elemIndicesBytes #-}+elemIndicesBytes w (PrimVector (PrimArray ba#) s l) = go s+  where+    !end = s + l+    go !i+        | i >= end = []+        | otherwise =+            case c_memchr ba# i w (end - i) of+                -1 -> []+                r  -> let !i' = (i+r) in i': go (i'+1)++-- | @findIndex f v = fst (find f v)@+findIndex :: Vec v a => (a -> Bool) -> v a -> Int+{-# INLINE findIndex #-}+findIndex f v = fst (find f v)++-- | @findIndexR f v = fst (findR f v)@+findIndexR :: Vec v a => (a -> Bool) -> v a -> Int+{-# INLINE findIndexR #-}+findIndexR f v = fst (findR f v)++-- | /O(n)/ find the first index and element matching the predicate in a vector+-- from left to right, if there isn't one, return (length of the vector, Nothing).+--+find :: Vec v a => (a -> Bool) -> v a -> (Int, Maybe a)+{-# INLINE [1] find #-}+{-# RULES "find/Bytes" forall w. find (w `eqWord8`) = findByte w #-}+{-# RULES "find/Bytes" forall w. find (`eqWord8` w) = findByte w #-}+find f (Vec arr s l) = go s+  where+    !end = s + l+    go !p | p >= end  = (l, Nothing)+          | f x       = let !i = p-s in (i, Just x)+          | otherwise = go (p+1)+        where (# x #) = indexArr' arr p++-- | /O(n)/ Special 'findByte' for 'Word8' using @memchr(3)@+findByte :: Word8 -> Bytes -> (Int, Maybe Word8)+{-# INLINE findByte #-}+findByte w (PrimVector (PrimArray ba#) s l) =+    case c_memchr ba# s w l of+        -1 -> (l, Nothing)+        r  -> (r, Just w)+++-- | /O(n)/ find the first index and element matching the predicate+-- in a vector from right to left, if there isn't one, return '(-1, Nothing)'.+findR :: Vec v a => (a -> Bool) -> v a -> (Int, Maybe a)+{-# INLINE [1] findR #-}+{-# RULES "findR/Bytes" forall w. findR (w `eqWord8`) = findByteR w #-}+{-# RULES "findR/Bytes" forall w. findR (`eqWord8` w) = findByteR w #-}+findR f (Vec arr s l) = go (s+l-1)+  where+    go !p | p < s     = (-1, Nothing)+          | f x       = let !i = p-s in (i, Just x)+          | otherwise = go (p-1)+        where (# x #) = indexArr' arr p++-- | /O(n)/ Special 'findR' for 'Bytes' with handle roll bit twiddling.+findByteR :: Word8 -> Bytes -> (Int, Maybe Word8)+{-# INLINE findByteR #-}+findByteR w (PrimVector ba s l) =+    case memchrReverse ba w (s+l-1) l of+        -1 -> (-1, Nothing)+        r  -> (r, Just w)++-- | /O(n)/ 'filter', applied to a predicate and a vector,+-- returns a vector containing those elements that satisfy the+-- predicate.+filter :: forall v a. Vec v a => (a -> Bool) -> v a -> v a+{-# INLINE filter #-}+filter f (Vec arr s l)+    | l == 0    = empty+    | otherwise = createN l (go f 0 s)+  where+    !end = s + l+    go :: (a -> Bool) -> Int -> Int -> MArray v s a -> ST s Int+    go f !i !p !marr+        | p >= end    = return i+        | f x         = writeArr marr i x >> go f (i+1) (p+1) marr+        | otherwise   = go f i (p+1) marr+        where (# x #) = indexArr' arr p++-- | /O(n)/ The 'partition' function takes a predicate, a vector, returns+-- a pair of vector with elements which do and do not satisfy the+-- predicate, respectively; i.e.,+--+-- > partition p vs == (filter p vs, filter (not . p) vs)+partition :: forall v a. Vec v a => (a -> Bool) -> v a -> (v a, v a)+{-# INLINE partition #-}+partition f (Vec arr s l)+    | l == 0    = (empty, empty)+    | otherwise = createN2 l l (go f 0 0 s)+  where+    !end = s + l+    go :: (a -> Bool) -> Int -> Int -> Int -> MArray v s a -> MArray v s a -> ST s (Int, Int)+    go f !i !j !p !mba0 !mba1+        | p >= end   = return (i, j)+        | f x        = writeArr mba0 i x >> go f (i+1) j (p+1) mba0 mba1+        | otherwise  = writeArr mba1 j x >> go f i (j+1) (p+1) mba0 mba1+        where (# x #) = indexArr' arr p++--------------------------------------------------------------------------------+-- Sub vector search++-- | /O(n+m)/ Find the offsets of all indices (possibly overlapping) of @needle@+-- within @haystack@ using KMP algorithm.+--+-- The KMP algorithm need pre-calculate a shift table in /O(m)/ time and space,+-- the worst case time complexity is /O(n+m)/. Partial apply this function to+-- reuse pre-calculated table between same needles.+--+-- Chunked input are support via partial match argument, if set we will return an+-- extra negative index in case of partial match at the end of input chunk, e.g.+--+-- > indicesOverlapping [ascii|ada|]  [ascii|adadad|] True == [0,2,-2]+--+-- Where @-2@ is the length of the partial match part @ad@ 's negation.+--+-- If an empty pattern is supplied, we will return every possible index of haystack,+-- e.g.+--+-- > indicesOverlapping "" "abc" = [0,1,2]+--+-- References:+--+--  * Knuth, Donald; Morris, James H.; Pratt, Vaughan: "Fast pattern matching in strings" (1977)+--  * <http://www-igm.univ-mlv.fr/~lecroq/string/node8.html#SECTION0080>+indicesOverlapping :: (Vec v a, Eq a)+        => v a -- ^ vector to search for (@needle@)+        -> v a -- ^ vector to search in (@haystack@)+        -> Bool -- ^ report partial match at the end of haystack+        -> [Int]+{-# INLINABLE[1] indicesOverlapping #-}+{-# RULES "indicesOverlapping/Bytes" indicesOverlapping = indicesOverlappingBytes #-}+indicesOverlapping needle@(Vec narr noff nlen) = search+  where+    next = kmpNextTable needle+    search haystack@(Vec harr hoff hlen) reportPartial+        | nlen <= 0 = [0..hlen-1]+        | nlen == 1 = case indexArr' narr 0 of+                       (# x #) -> elemIndices x haystack+        | otherwise = kmp 0 0+      where+        kmp !i !j | i >= hlen = if reportPartial && j /= 0 then [-j] else []+                  | narr `indexArr` (j+noff) == harr `indexArr` (i+hoff) =+                        let !j' = j+1+                        in if j' >= nlen+                        then let !i' = i-j+                            in case next `indexArr` j' of+                                -1 -> i' : kmp (i+1) 0+                                j'' -> i' : kmp (i+1) j''+                        else kmp (i+1) j'+                  | otherwise = case next `indexArr` j of+                                    -1 -> kmp (i+1) 0+                                    j' -> kmp i j'++-- | /O(n\/m)/ Find the offsets of all indices (possibly overlapping) of @needle@+-- within @haystack@ using KMP algorithm, combined with simplified sunday's+-- rule to obtain /O(n\/m)/ complexity in average use case.+--+-- The hybrid algorithm need pre-calculate a shift table in /O(m)/ time and space,+-- and a bad character bloom filter in /O(m)/ time and /O(1)/ space, the worst case+-- time complexity is /O(n+m)/.+--+-- References:+--+-- * Frantisek FranekChristopher G. JenningsWilliam F. Smyth A Simple Fast Hybrid Pattern-Matching Algorithm (2005)+-- * D. M. Sunday: A Very Fast Substring Search Algorithm. Communications of the ACM, 33, 8, 132-142 (1990)+-- * F. Lundh: The Fast Search Algorithm. <http://effbot.org/zone/stringlib.htm> (2006)+indicesOverlappingBytes :: Bytes -- ^ bytes to search for (@needle@)+                        -> Bytes -- ^ bytes to search in (@haystack@)+                        -> Bool -- ^ report partial match at the end of haystack+                        -> [Int]+{-# INLINABLE indicesOverlappingBytes #-}+indicesOverlappingBytes needle@(Vec narr noff nlen) | popCount bloom > 48 = search+                                                    | otherwise = search'+  where+    next = kmpNextTable needle+    bloom = sundayBloom needle+    search haystack@(Vec harr hoff hlen) reportPartial+        | nlen <= 0 = [0..hlen-1]+        | nlen == 1 = case indexArr' narr 0 of+                       (# x #) -> elemIndices x haystack+        | otherwise = kmp 0 0+      where+        kmp !i !j | i >= hlen = if reportPartial && j /= 0 then [-j] else []+                  | narr `indexArr` (j+noff) == harr `indexArr` (i+hoff) =+                        let !j' = j+1+                        in if j' >= nlen+                        then let !i' = i-j+                            in case next `indexArr` j' of+                                -1 -> i' : kmp (i+1) 0+                                j'' -> i' : kmp (i+1) j''+                        else kmp (i+1) j'+                  | otherwise = case next `indexArr` j of+                                    -1 -> kmp (i+1) 0+                                    j' -> kmp i j'+    search' haystack@(Vec harr hoff hlen) reportPartial+        | nlen <= 0 = [0..hlen-1]+        | nlen == 1 = elemIndices (indexArr narr 0) haystack+        | otherwise = sunday 0 0+      where+        kmp !i !j | i >= hlen = if reportPartial && j /= 0 then [-j] else []+                  | narr `indexArr` (j+noff) == harr `indexArr` (i+hoff) =+                        let !j' = j+1+                        in if j' >= nlen+                        then let !i' = i-j+                            in case next `indexArr` j' of+                                -1 -> i' : kmp (i+1) 0+                                j'' -> i' : kmp (i+1) j''+                        else kmp (i+1) j'+                  | otherwise = case next `indexArr` j of+                                    -1 -> kmp (i+1) 0+                                    j' -> kmp i j'+        !hlen' = hlen - nlen+        sunday !i !j | i >= hlen' = kmp i j+                     | narr `indexArr` (j+noff) == harr `indexArr` (i+hoff) =+                            let !j' = j+1+                            in if j' >= nlen+                            then let !i' = i-j+                                in case next `indexArr` j' of+                                    -1 -> i' : sunday (i+1) 0+                                    j'' -> i' : sunday (i+1) j''+                            else sunday (i+1) j'+                     | otherwise = let !k = i+nlen-j+                                       !afterNeedle = indexArr harr (k+hoff)+                                   in if elemSundayBloom bloom afterNeedle+                                      -- fallback to KMP+                                      then case next `indexArr` j of+                                               -1 -> sunday (i+1) 0+                                               j' -> sunday i j'+                                      -- sunday's shifting+                                      else sunday (k+1) 0++-- | /O(n+m)/ Find the offsets of all non-overlapping indices of @needle@+-- within @haystack@ using KMP algorithm.+--+-- If an empty pattern is supplied, we will return every possible index of haystack,+-- e.g.+--+-- > indicesOverlapping "" "abc" = [0,1,2]+indices :: (Vec v a, Eq a) => v a -> v a -> Bool -> [Int]+{-# INLINABLE[1] indices #-}+{-# RULES "indices/Bytes" indices = indicesBytes #-}+indices needle@(Vec narr noff nlen) = search+  where+    next = kmpNextTable needle+    search haystack@(Vec harr hoff hlen) reportPartial+        | nlen <= 0 = [0..hlen-1]+        | nlen == 1 = case indexArr' narr 0 of+                       (# x #) -> elemIndices x haystack+        | otherwise = kmp 0 0+      where+        kmp !i !j | i >= hlen = if reportPartial && j /= 0 then [-j] else []+                  | narr `indexArr` (j+noff) == harr `indexArr` (i+hoff) =+                        let !j' = j+1+                        in if j' >= nlen+                            then let !i' = i-j in i' : kmp (i+1) 0+                            else kmp (i+1) j'+                  | otherwise = case next `indexArr` j of+                                    -1 -> kmp (i+1) 0+                                    j' -> kmp i j'++-- | /O(n\/m)/ Find the offsets of all non-overlapping indices of @needle@+-- within @haystack@ using KMP algorithm, combined with simplified sunday's+-- rule to obtain /O(m\/n)/ complexity in average use case.+indicesBytes :: Bytes -- ^ bytes to search for (@needle@)+             -> Bytes -- ^ bytes to search in (@haystack@)+             -> Bool -- ^ report partial match at the end of haystack+             -> [Int]+{-# INLINABLE indicesBytes #-}+indicesBytes needle@(Vec narr noff nlen) | popCount bloom > 48 = search+                                         | otherwise = search'+  where+    next = kmpNextTable needle+    bloom = sundayBloom needle+    search haystack@(Vec harr hoff hlen) reportPartial+        | nlen <= 0 = [0..hlen-1]+        | nlen == 1 = case indexArr' narr 0 of+                       (# x #) -> elemIndices x haystack+        | otherwise = kmp 0 0+      where+        kmp !i !j | i >= hlen = if reportPartial && j /= 0 then [-j] else []+                  | narr `indexArr` (j+noff) == harr `indexArr` (i+hoff) =+                        let !j' = j+1+                        in if j' >= nlen+                            then let !i' = i-j in i' : kmp (i+1) 0+                            else kmp (i+1) j'+                  | otherwise = case next `indexArr` j of+                                    -1 -> kmp (i+1) 0+                                    j' -> kmp i j'+    search' haystack@(Vec harr hoff hlen) reportPartial+        | nlen <= 0 = [0..hlen-1]+        | nlen == 1 = elemIndices (indexArr narr 0) haystack+        | otherwise = sunday 0 0+      where+        kmp !i !j | i >= hlen = if reportPartial && j /= 0 then [-j] else []+                  | narr `indexArr` (j+noff) == harr `indexArr` (i+hoff) =+                        let !j' = j+1+                        in if j' >= nlen+                            then let !i' = i-j in i' : kmp (i+1) 0+                            else kmp (i+1) j'+                  | otherwise = case next `indexArr` j of+                                    -1 -> kmp (i+1) 0+                                    j' -> kmp i j'+        !hlen' = hlen - nlen+        sunday !i !j | i >= hlen' = kmp i j+                     | narr `indexArr` (j+noff) == harr `indexArr` (i+hoff) =+                            let !j' = j+1+                            in if j' >= nlen+                                then let !i' = i-j in i' : sunday (i+1) 0+                                else sunday (i+1) j'+                     | otherwise = let !k = i+nlen-j+                                       !afterNeedle = indexArr harr (k+hoff)+                                   in if elemSundayBloom bloom afterNeedle+                                      -- fallback to KMP+                                      then case next `indexArr` j of+                                               -1 -> sunday (i+1) 0+                                               j' -> sunday i j'+                                      -- sunday's shifting+                                      else sunday (k+1) 0++-- | /O(m)/ Calculate the KMP next shift table.+--+-- The shifting rules is: when a mismatch between @needle[j]@ and @haystack[i]@+-- is found, check if @next[j] == -1@, if so next search continue with @needle[0]@+-- and @haystack[i+1]@, otherwise continue with @needle[next[j]]@ and @haystack[i]@.+kmpNextTable :: (Vec v a, Eq a) => v a -> PrimArray Int+{-# INLINE kmpNextTable #-}+kmpNextTable (Vec arr s l) = runST (do+    ma <- newArr (l+1)+    writeArr ma 0 (-1)+    let dec !w !j+            | j < 0 || w == indexArr arr (s+j) = return $! j+1+            | otherwise = readArr ma j >>= dec w+        go !i !j+            | i > l    = unsafeFreezeArr ma+            | otherwise = do+                let !w = indexArr arr (s+i-1)+                j' <- dec w j+                if i < l && indexArr arr (s+j') == indexArr arr (s+i)+                    then readArr ma j' >>= writeArr ma i+                    else writeArr ma i j'+                go (i+1) j'+    go 1 (-1))++-- | /O(m)/ Calculate a simple bloom filter for simplified sunday's rule.+--+-- The shifting rules is: when a mismatch between @needle[j]@ and @haystack[i]@+-- is found, check if @elemSundayBloom bloom haystack[i+n-j]@, where n is the+-- length of needle, if not then next search can be safely continued with+-- @haystack[i+n-j+1]@ and @needle[0]@, otherwise next searh should continue with+-- @haystack[i]@ and @needle[0]@, or fallback to other shifting rules such as KMP.+--+-- The algorithm is very simple: for a given 'Word8' @w@, we set the bloom's bit+-- at @unsafeShiftL 0x01 (w .&. 0x3f)@, so there're three false positives per bit.+-- This's particularly suitable for search UTF-8 bytes since the significant bits+-- of a beginning byte is usually the same.+sundayBloom :: Bytes -> Word64+{-# INLINE sundayBloom #-}+sundayBloom (Vec arr s l) = go 0x00000000 s+  where+    !end = s+l+    go !b !i+        | i >= end  = b+        | otherwise =+            let !w = indexArr arr i+                !b' = b .|. (0x00000001 `unsafeShiftL` (fromIntegral w .&. 0x3f))+            in go b' (i+1)++-- | O(1) Test if a bloom filter contain a certain 'Word8'.+--+elemSundayBloom :: Word64 -> Word8 -> Bool+{-# INLINE elemSundayBloom #-}+elemSundayBloom b w = b .&. (0x01 `unsafeShiftL` (fromIntegral w .&. 0x3f)) /= 0
+ Std/Data/Vector/Sort.hs view
@@ -0,0 +1,444 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE CPP #-}++{-|+Module      : Std.Data.Vector.Sort+Description : Sorting vectors+Copyright   : (c) 2008-2011 Dan Doel, (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provide three stable sorting algorithms, which are:++  * 'mergeSort', a /O(log(n))/ general-purpose sorting algorithms for all different size vectors.++  * 'insertSort' a /O(n^2)/ sorting algorithms suitable for very small vectors.++  * 'radixSort' a /O(n)/ sorting algorithms based on 'Radix' instance, which is prefered on large vectors.++Sorting is always performed in ascending order. To reverse the order, either use @XXSortBy@ or use 'Down', 'RadixDown' newtypes. In general changing comparing functions can be done by creating auxiliary newtypes and 'Ord' instances (make sure you inline instance's method for performence!). Or 'Radix' instances in 'radixSort' case, for example:++@+data Foo = Foo { key :: Int16, ... }++instance Radix Foo where+    -- You should add INLINE pragmas to following methods+    bucketSize = bucketSize . key+    passes = passes . key+    radixLSB = radixLSB . key+    radix i = radix i . key+    radixMSB = radixMSB . key+@++-}++module Std.Data.Vector.Sort (+  -- * Sort+    mergeSort+  , mergeSortBy+  , mergeTileSize+  , insertSort+  , insertSortBy+  , Down(..)+  , radixSort+  , Radix(..)+  , RadixDown(..)+  ) where++import           Control.Monad.ST+import           Data.Bits+import           Data.Int+import           Data.Ord               (Down (..))+import           Data.Primitive         (sizeOf)+import           Data.Primitive.Types   (Prim (..))+import           Data.Word+import           Prelude                hiding (splitAt)+import           Std.Data.Array+import           Std.Data.Vector.Base+import           Std.Data.Vector.Extra+import           Std.Data.PrimArray.Cast++--------------------------------------------------------------------------------+-- Comparison Sort++-- | /O(n*log(n))/ Sort vector based on element's 'Ord' instance with classic+-- <https://en.wikipedia.org/wiki/Merge_sort mergesort> algorithm.+--+-- This is a stable sort, During sorting two O(n) worker arrays are needed, one of+-- them will be freezed into the result vector. The merge sort only begin at tile+-- size larger than 'mergeTileSize', each tile will be sorted with 'insertSort', then+-- iteratively merged into larger array, until all elements are sorted.+mergeSort :: forall v a. (Vec v a, Ord a) => v a -> v a+{-# INLINABLE mergeSort #-}+mergeSort = mergeSortBy compare++mergeSortBy :: forall v a. Vec v a => (a -> a -> Ordering) -> v a -> v a+{-# INLINE mergeSortBy #-}+mergeSortBy cmp v@(Vec _ _ l)+    | l <= mergeTileSize = insertSortBy cmp v+    | otherwise = runST (do+        -- create two worker array+        w1 <- newArr l+        w2 <- newArr l+        firstPass v 0 w1+        w <- mergePass w1 w2 mergeTileSize+        return $! fromArr w 0 l)+  where+    firstPass !v !i !marr+        | i >= l     = return ()+        | otherwise = do+            let (v',rest) = splitAt mergeTileSize v+            insertSortToMArr cmp v' i marr+            firstPass rest (i+mergeTileSize) marr++    mergePass !w1 !w2 !blockSiz+        | blockSiz >= l = unsafeFreezeArr w1+        | otherwise     = do+            mergeLoop w1 w2 blockSiz 0+            mergePass w2 w1 (blockSiz*2) -- swap worker array and continue merging++    mergeLoop !src !target !blockSiz !i+        | i >= l-blockSiz =                 -- remaining elements less than a block+            if i >= l+            then return ()+            else copyMutableArr target i src i (l-i)+        | otherwise = do+            let !mergeEnd = min (i+blockSiz+blockSiz) l+            mergeBlock src target (i+blockSiz) mergeEnd i (i+blockSiz) i+            mergeLoop src target blockSiz mergeEnd++    mergeBlock !src !target !leftEnd !rightEnd !i !j !k = do+        l <- readArr src i+        r <- readArr src j+        case r `cmp` l of+            LT -> do+                writeArr target k r+                let !j' = j + 1+                    !k' = k + 1+                if j' >= rightEnd+                then copyMutableArr target k' src i (leftEnd - i)+                else mergeBlock src target leftEnd rightEnd i j' k'+            _ -> do+                writeArr target k l+                let !i' = i + 1+                    !k' = k + 1+                if i' >= leftEnd+                then copyMutableArr target k' src j (rightEnd - j)+                else mergeBlock src target leftEnd rightEnd i' j k'++-- | The mergesort tile size, @mergeTileSize = 16@.+mergeTileSize :: Int+{-# INLINE mergeTileSize #-}+mergeTileSize = 16++-- | /O(n^2)/ Sort vector based on element's 'Ord' instance with simple+-- <https://en.wikipedia.org/wiki/Insertion_sort insertion-sort> algorithm.+--+-- This is a stable sort. O(n) extra space are needed,+-- which will be freezed into result vector.+insertSort :: (Vec v a, Ord a) => v a -> v a+{-# INLINE insertSort #-}+insertSort = insertSortBy compare++insertSortBy :: Vec v a => (a -> a -> Ordering) -> v a -> v a+{-# INLINE insertSortBy #-}+insertSortBy _ v@(Vec _ _ 0) = empty+insertSortBy _ v@(Vec arr s 1) = case indexArr' arr s of (# x #) -> singleton x+insertSortBy cmp v@(Vec arr s l) = create l (insertSortToMArr cmp v 0)++insertSortToMArr  :: Vec v a+                  => (a -> a -> Ordering)+                  -> v a            -- the original vector+                  -> Int            -- writing offset in the mutable array+                  -> MArray v s a   -- writing mutable array, must have enough space!+                  -> ST s ()+{-# INLINE insertSortToMArr #-}+insertSortToMArr cmp (Vec arr s l) moff marr = go s+  where+    !end = s + l+    !doff = moff-s+    go !i | i >= end  = return ()+          | otherwise = case indexArr' arr i of+               (# x #) -> do insert x (i+doff)+                             go (i+1)+    insert !temp !i+        | i <= moff = do+            writeArr marr moff temp+        | otherwise = do+            x <- readArr marr (i-1)+            case temp `cmp` x of+                LT -> do+                    writeArr marr i x+                    insert temp (i-1)+                _ -> writeArr marr i temp++--------------------------------------------------------------------------------+-- Radix Sort++-- | Types contain radixs, which can be inspected with 'radix' during different 'passes'.+--+-- The default instances share a same 'bucketSize' 256, which seems to be a good default.+class Radix a where+    -- | The size of an auxiliary array, i.e. the counting bucket+    bucketSize :: a -> Int+    -- | The number of passes necessary to sort an array of es,+    --   it equals to the key's byte number.+    passes :: a -> Int+    -- | The radix function used in the first pass, works on the least significant bit.+    radixLSB  :: a -> Int+    -- | The radix function parameterized by the current pass (0 < pass < passes e-1).+    radix  :: Int -> a -> Int+    -- | The radix function used in the last pass, works on the most significant bit.+    radixMSB  :: a -> Int++instance Radix Int8 where+    {-# INLINE bucketSize #-};+    bucketSize _ = 256+    {-# INLINE passes #-}+    passes _ = 1+    {-# INLINE radixLSB #-}+    radixLSB a =  255 .&. fromIntegral a `xor` 128+    {-# INLINE radix #-}+    radix _ a =  255 .&. fromIntegral a `xor` 128+    {-# INLINE radixMSB #-}+    radixMSB a =  255 .&. fromIntegral a `xor` 128++#define MULTI_BYTES_INT_RADIX(T) \+    {-# INLINE bucketSize #-}; \+    bucketSize _ = 256; \+    {-# INLINE passes #-}; \+    passes _ = sizeOf (undefined :: T); \+    {-# INLINE radixLSB #-}; \+    radixLSB a = fromIntegral (255 .&. a); \+    {-# INLINE radix #-}; \+    radix i a = fromIntegral (a `unsafeShiftR` (i `unsafeShiftL` 3)) .&. 255; \+    {-# INLINE radixMSB #-}; \+    radixMSB a = fromIntegral ((a `xor` minBound) `unsafeShiftR` ((passes a-1) `unsafeShiftL` 3)) .&. 255++instance Radix Int where MULTI_BYTES_INT_RADIX(Int)+instance Radix Int16 where MULTI_BYTES_INT_RADIX(Int16)+instance Radix Int32 where MULTI_BYTES_INT_RADIX(Int32)+instance Radix Int64 where MULTI_BYTES_INT_RADIX(Int64)++instance Radix Word8 where+    {-# INLINE bucketSize #-};+    bucketSize _ = 256+    {-# INLINE passes #-}+    passes _ = 1+    {-# INLINE radixLSB #-}+    radixLSB = fromIntegral+    {-# INLINE radix #-}+    radix _  = fromIntegral+    {-# INLINE radixMSB #-}+    radixMSB = fromIntegral++#define MULTI_BYTES_WORD_RADIX(T) \+    {-# INLINE bucketSize #-}; \+    bucketSize _ = 256; \+    {-# INLINE passes #-}; \+    passes _ = sizeOf (undefined :: T); \+    {-# INLINE radixLSB #-}; \+    radixLSB a = fromIntegral (255 .&. a); \+    {-# INLINE radix #-}; \+    radix i a = fromIntegral (a `unsafeShiftR` (i `unsafeShiftL` 3)) .&. 255; \+    {-# INLINE radixMSB #-}; \+    radixMSB a = fromIntegral (a `unsafeShiftR` ((passes a-1) `unsafeShiftL` 3)) .&. 255++instance Radix Word where MULTI_BYTES_INT_RADIX(Word)+instance Radix Word16 where MULTI_BYTES_INT_RADIX(Word16)+instance Radix Word32 where MULTI_BYTES_INT_RADIX(Word32)+instance Radix Word64 where MULTI_BYTES_INT_RADIX(Word64)++-- | Similar to 'Down' newtype for 'Ord', this newtype can inverse the order of a 'Radix'+-- instance when used in 'radixSort'.+newtype RadixDown a = RadixDown a deriving (Show, Eq, Prim)++instance Radix a => Radix (RadixDown a) where+    {-# INLINE bucketSize #-}+    bucketSize (RadixDown a) = bucketSize a+    {-# INLINE passes #-}+    passes (RadixDown a)  = passes a+    {-# INLINE radixLSB #-}+    radixLSB (RadixDown a) = bucketSize a - radixLSB a -1+    {-# INLINE radix #-}+    radix i (RadixDown a) = bucketSize a - radix i a -1+    {-# INLINE radixMSB #-}+    radixMSB (RadixDown a) = bucketSize a - radixMSB a -1++-- | /O(n)/ Sort vector based on element's 'Radix' instance with+-- <https://en.wikipedia.org/wiki/Radix_sort radix-sort>,+-- (Least significant digit radix sorts variation).+--+-- This is a stable sort, one or two extra O(n) worker array are need+-- depend on how many 'passes' shall be performed, and a 'bucketSize'+-- counting bucket are also needed. This sort algorithms performed extremly+-- well on small byte size types such as 'Int8' or 'Word8', while on larger+-- type, constant passes may render this algorithm not suitable for small+-- vectors (turning point around 2^(2*passes)).+radixSort :: forall v a. (Vec v a, Radix a) => v a -> v a+{-# INLINABLE radixSort #-}+radixSort v@(Vec _ _ 0) = empty+radixSort v@(Vec arr s 1) = case indexArr' arr s of (# x #) -> singleton x+radixSort (Vec arr s l) = runST (do+        bucket <- newArrWith buktSiz 0 :: ST s (MutablePrimArray s Int)+        w1 <- newArr l+        firstCountPass arr bucket s+        accumBucket bucket buktSiz 0 0+        firstMovePass arr s bucket w1+        w <- if passSiz == 1+            then unsafeFreezeArr w1+            else do+                w2 <- newArr l+                radixLoop w1 w2 bucket buktSiz 1+        return $! fromArr w 0 l)+  where+    passSiz = passes (undefined :: a)+    buktSiz = bucketSize (undefined :: a)+    !end = s + l++    {-# INLINABLE firstCountPass #-}+    firstCountPass !arr !bucket !i+        | i >= end  = return ()+        | otherwise = case indexArr' arr i of+            (# x #) -> do+                let !r = radixLSB x+                c <- readArr bucket r+                writeArr bucket r (c+1)+                firstCountPass arr bucket (i+1)++    {-# INLINABLE accumBucket #-}+    accumBucket !bucket !buktSiz !i !acc+        | i >= buktSiz = return ()+        | otherwise = do+            c <- readArr bucket i+            writeArr bucket i acc+            accumBucket bucket buktSiz (i+1) (acc+c)++    {-# INLINABLE firstMovePass #-}+    firstMovePass !arr !i !bucket !w+        | i >= end  = return ()+        | otherwise = case indexArr' arr i of+            (# x #) -> do+                let !r = radixLSB x+                c <- readArr bucket r+                writeArr bucket r (c+1)+                writeArr w c x+                firstMovePass arr (i+1) bucket w++    {-# INLINABLE radixLoop #-}+    radixLoop !w1 !w2 !bucket !buktSiz !pass+        | pass >= passSiz-1 = do+            setArr bucket 0 buktSiz 0   -- clear the counting bucket+            lastCountPass w1 bucket 0+            accumBucket bucket buktSiz 0 0+            lastMovePass w1 bucket w2 0+            unsafeFreezeArr w2+        | otherwise = do+            setArr bucket 0 buktSiz 0   -- clear the counting bucket+            countPass w1 bucket pass 0+            accumBucket bucket buktSiz 0 0+            movePass w1 bucket pass w2 0+            radixLoop w2 w1 bucket buktSiz (pass+1)++    {-# INLINABLE countPass #-}+    countPass !marr !bucket !pass !i+        | i >= l  = return ()+        | otherwise = do+                x <- readArr marr i+                let !r = radix pass x+                c <- readArr bucket r+                writeArr bucket r (c+1)+                countPass marr bucket pass (i+1)++    {-# INLINABLE movePass #-}+    movePass !src !bucket !pass !target !i+        | i >= l  = return ()+        | otherwise = do+                x <- readArr src i+                let !r = radix pass x+                c <- readArr bucket r+                writeArr bucket r (c+1)+                writeArr target c x+                movePass src bucket pass target (i+1)++    {-# INLINABLE lastCountPass #-}+    lastCountPass !marr !bucket !i+        | i >= l  = return ()+        | otherwise = do+                x <- readArr marr i+                let !r = radixMSB x+                c <- readArr bucket r+                writeArr bucket r (c+1)+                lastCountPass marr bucket (i+1)++    {-# INLINABLE lastMovePass #-}+    lastMovePass !src !bucket !target !i+        | i >= l  = return ()+        | otherwise = do+                x <- readArr src i+                let !r = radixMSB x+                c <- readArr bucket r+                writeArr bucket r (c+1)+                writeArr target c x+                lastMovePass src bucket target (i+1)++{- In fact IEEE float can be radix sorted like following:++newtype RadixDouble = RadixDouble Int64 deriving (Show, Eq, Prim)+instance Cast RadixDouble Double where cast (RadixDouble a) = cast a+instance Cast Double RadixDouble where cast a = RadixDouble (cast a)+instance Radix RadixDouble where+    {-# INLINE bucketSize #-}+    bucketSize (RadixDouble _) = 256+    {-# INLINE passes #-}+    passes (RadixDouble _)  = 8+    {-# INLINE radixLSB #-}+    radixLSB (RadixDouble a) | a > 0 = r+                             | otherwise = 255 - r+      where r = radixLSB a+    {-# INLINE radix #-}+    radix i (RadixDouble a) | a > 0 = r+                            | otherwise = 255 - r+      where r = radix i a+    {-# INLINE radixMSB #-}+    radixMSB (RadixDouble a) | r < 128  = r + 128+                             | otherwise = 255 - r+      where r = radixMSB (fromIntegral a :: Word64)++radixSortDouble :: PrimVector Double -> PrimVector Double+radixSortDouble v =  castVector (radixSort (castVector v :: PrimVector RadixDouble))++newtype RadixFloat = RadixFloat Int32 deriving (Show, Eq, Prim)+instance Cast RadixFloat Float where cast (RadixFloat a) = cast a+instance Cast Float RadixFloat where cast a = RadixFloat (cast a)+instance Radix RadixFloat where+    {-# INLINE bucketSize #-}+    bucketSize (RadixFloat _) = 256+    {-# INLINE passes #-}+    passes (RadixFloat _)  = 4+    {-# INLINE radixLSB #-}+    radixLSB (RadixFloat a) | a > 0 = r+                            | otherwise = 255 - r+      where r = radixLSB a+    {-# INLINE radix #-}+    radix i (RadixFloat a) | a > 0 = r+                           | otherwise = 255 - r+      where r = radix i a+    {-# INLINE radixMSB #-}+    radixMSB (RadixFloat a) | r < 128  = r + 128+                            | otherwise = 255 - r+      where r = radixMSB (fromIntegral a :: Word32)++radixSortFloat :: PrimVector Float -> PrimVector Float+radixSortFloat v =  castVector (radixSort (castVector v :: PrimVector RadixFloat))+-}
+ Std/Foreign/PrimArray.hs view
@@ -0,0 +1,295 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Std.Foreign.PrimArray+Description : Use PrimArray with FFI+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provide functions for using 'PrimArray' and 'PrimVector' with GHC FFI(Foreign function interface).+Since GHC runtime is garbaged collected, we have a quite complex story when passing primitive arrays to FFI.+We have two types of primitive array in GHC, with the objective to minimize overall memory management cost:++  * Small primitive arrays created with 'newPrimArray' are directly allocated on GHC heap, which can be moved+    by GHC garbage collector, we call these arrays @unpinned@. Allocating these array is cheap, we only need+    to check heap limit and bump heap pointer just like any other haskell heap objects. But we will pay GC cost+    , which is OK for small arrays.++  * Large primitive array and those created with 'newPinnedPrimArray' are allocated on GHC managed memory blocks,+    which is also traced by garbage collector, but will never moved before freed, thus are called @pinned@.+    Allocating these arrays are bit more expensive since it's more like how @malloc@ works, but we don't have to+    pay for GC cost.++Beside the @pinned/unpinned@ difference, we also have two types of FFI calls in GHC:++  * Safe FFI call annotated with @safe@ keyword. These calls are executed on separated OS thread, which can be+    running concurrently with GHC garbage collector, thus we want to make sure only pinned arrays are passed.+    The main use case for @safe@ FFIs are long running functions, for example, doing IO polling.+    Since these calls are running on separated OS thread, haskell thread on original OS thread will not be affected.++  * Unsafe FFI call annotated with @unsafe@ keyword. These calls are executed on the same OS thread which is+    running the haskell side FFI code, which will in turn stop GHC from doing a garbage collection. We can pass+    both 'pinned' and 'unpinned' arrays in this case. The use case for @unsafe@ FFIs are short/small functions,+    which can be treated like a fat primitive operations, such as @memcpy@, @memcmp@. Using @unsafe@ FFI with+    long running functions will effectively block GHC runtime thread from running any other haskell thread, which+    is dangerous. Even if you use threaded runtime and expect your haskell thread can be stolen by other OS thread,+    but this will not work since GHC garbage collector will refuse to run if one of the OS thread is blocked by+    FFI calls.++Base on above analysis, we have following FFI strategy table.++  +--------------+---------------+---------------++  | FFI  \ Array |    pinned     |   unpinned    |+  +--------------+---------------+---------------++  |   unsafe     | directly pass | directly pass |+  +--------------+---------------+---------------++  |     safe     | directly pass |  make a copy  |+  +--------------+---------------+---------------+++In this module, we separate safe and unsafe FFI handling due to the strategy difference: if the user can guarantee+the FFI are unsafe, we can save an extra copy and pinned allocation. Mistakenly using unsafe function with safe FFI+will result in segfault.++For convention you should always use `Ptr a` as the tagged pointer type, and `Addr` as the raw address type, use `addrToPtr/ptrToAddr` to cast between them if needed.++-}++module Std.Foreign.PrimArray+  ( -- ** Unsafe FFI+    withPrimArrayUnsafe+  , withMutablePrimArrayUnsafe+  , withMutableByteArrayUnsafe+  , withPrimVectorUnsafe+  , withPrimUnsafe+  , withPrimUnsafe'+    -- ** Safe FFI+  , withPrimArraySafe+  , withMutablePrimArraySafe+  , withMutableByteArraySafe+  , withPrimVectorSafe+  , withPrimSafe+  , withPrimSafe'+    -- ** Pointer helpers+  , BA#, MBA#+  , clearPtr+  , addrToPtr+  , ptrToAddr+  , castPtr+  -- ** re-export+  , module GHC.Prim+  , module Data.Primitive.Ptr+  ) where++import           Control.Monad.Primitive+import           Data.Primitive+import           Data.Primitive.ByteArray+import           Data.Primitive.PrimArray+import           Data.Primitive.Ptr+import           Data.Word+import           Foreign.C.Types+import           GHC.Prim+import           GHC.Ptr+import           Std.Data.Array+import           Std.Data.Vector.Base+import           Std.IO.Exception+import           Std.IO.Resource++-- | Type alias for 'ByteArray#'.+--+-- Since we can't newtype an unlifted type yet, type alias is the best we can get+-- to describe a 'ByteArray#' which we are going to pass across FFI. At C side you+-- should use a proper const pointer type.+--+-- Don't cast 'BA#' to 'Addr#' since the heap object offset is hard-coded in code generator:+-- <https://github.com/ghc/ghc/blob/master/compiler/codeGen/StgCmmForeign.hs#L520>+--+-- USE THIS TYPE WITH UNSAFE FFI CALL ONLY.+type BA# a = ByteArray#++-- | Type alias for 'MutableByteArray#' 'RealWorld'.+--+-- Since we can't newtype an unlifted type yet, type alias is the best we can get+-- to describe a 'MutableByteArray#' which we are going to pass across FFI. At C side you+-- should use a proper pointer type.+--+-- Don't cast 'MBA#' to 'Addr#' since the heap object offset is hard-coded in code generator:+-- <https://github.com/ghc/ghc/blob/master/compiler/codeGen/StgCmmForeign.hs#L520>+--+-- USE THIS TYPE WITH UNSAFE FFI CALL ONLY.+type MBA# a = MutableByteArray# RealWorld++-- | Pass primitive array to unsafe FFI as pointer.+--+-- Enable 'UnliftedFFITypes' extension in your haskell code, use proper pointer type and @CSize/CSsize@+-- to marshall @ByteArray#@ and @Int@ arguments on C side.+--+-- The second 'Int' arguement is the element size not the bytes size.+--+-- Don't cast 'ByteArray#' to 'Addr#' since the heap object offset is hard-coded in code generator:+-- <https://github.com/ghc/ghc/blob/master/compiler/codeGen/StgCmmForeign.hs#L520>+--+-- In haskell side we use type system to distinguish immutable / mutable arrays, but in C side we can't.+-- So it's users' responsibility to make sure the array content is not mutated (a const pointer type may help).+--+-- USE THIS FUNCTION WITH UNSAFE FFI CALL ONLY.+--+withPrimArrayUnsafe :: (Prim a) => PrimArray a -> (BA# a -> Int -> IO b) -> IO b+withPrimArrayUnsafe pa@(PrimArray ba#) f = f ba# (sizeofPrimArray pa)++-- | Pass mutable primitive array to unsafe FFI as pointer.+--+-- The mutable version of 'withPrimArrayUnsafe'.+--+-- USE THIS FUNCTION WITH UNSAFE FFI CALL ONLY.+--+withMutablePrimArrayUnsafe :: (Prim a) => MutablePrimArray RealWorld a+                           -> (MBA# a -> Int -> IO b) -> IO b+withMutablePrimArrayUnsafe mpa@(MutablePrimArray mba#) f =+    getSizeofMutablePrimArray mpa >>= f mba#++withMutableByteArrayUnsafe :: Int      -- ^ In bytes+                           -> (MBA# Word8 -> IO b) -> IO b+withMutableByteArrayUnsafe len f = do+    (MutableByteArray mba#) <- newByteArray len+    f mba#++-- | Pass 'PrimVector' to unsafe FFI as pointer+--+-- The 'PrimVector' version of 'withPrimArrayUnsafe'.+--+-- The second 'Int' arguement is the first element offset, the third 'Int' argument is the+-- element length.+--+-- USE THIS FUNCTION WITH UNSAFE FFI CALL ONLY.+--+withPrimVectorUnsafe :: (Prim a)+                     => PrimVector a -> (BA# a -> Int -> Int -> IO b) -> IO b+withPrimVectorUnsafe (PrimVector arr s l) f = withPrimArrayUnsafe arr $ \ ba# _ -> f ba# s l+++-- | Create an one element primitive array and use it as a pointer to the primitive element.+--+-- Return the element and the computation result.+--+-- USE THIS FUNCTION WITH UNSAFE FFI CALL ONLY.+--+withPrimUnsafe :: (Prim a)+               => a -> (MBA# a -> IO b) -> IO (a, b)+withPrimUnsafe v f = do+    mpa@(MutablePrimArray mba#) <- newPrimArray 1    -- All heap objects are WORD aligned+    writePrimArray mpa 0 v+    !b <- f mba#                                      -- so no need to do extra alignment+    !a <- readPrimArray mpa 0+    return (a, b)++withPrimUnsafe' :: (Prim a)+               => (MBA# a -> IO b) -> IO (a, b)+withPrimUnsafe' f = do+    mpa@(MutablePrimArray mba#) <- newPrimArray 1    -- All heap objects are WORD aligned+    !b <- f mba#                                      -- so no need to do extra alignment+    !a <- readPrimArray mpa 0+    return (a, b)++--------------------------------------------------------------------------------++-- | Pass primitive array to safe FFI as pointer.+--+-- Use proper pointer type and @CSize/CSsize@ to marshall @Ptr a@ and @Int@ arguments on C side.+-- The memory pointed by 'Ptr a' will not moved.+--+-- The second 'Int' arguement is the element size not the bytes size.+--+-- Don't pass a forever loop to this function, see <https://ghc.haskell.org/trac/ghc/ticket/14346 #14346>.+withPrimArraySafe :: (Prim a) => PrimArray a -> (Ptr a -> Int -> IO b) -> IO b+withPrimArraySafe arr f+    | isPrimArrayPinned arr = do+        let siz = sizeofPrimArray arr+        withPrimArrayContents arr $ \ ptr -> f ptr siz+    | otherwise = do+        let siz = sizeofPrimArray arr+        buf <- newPinnedPrimArray siz+        copyPrimArray buf 0 arr 0 siz+        withMutablePrimArrayContents buf $ \ ptr -> f ptr siz+++-- | Pass mutable primitive array to unsafe FFI as pointer.+--+-- The mutable version of 'withPrimArraySafe'.+--+-- Don't pass a forever loop to this function, see <https://ghc.haskell.org/trac/ghc/ticket/14346 #14346>.+withMutablePrimArraySafe :: (Prim a) => MutablePrimArray RealWorld a -> (Ptr a -> Int -> IO b) -> IO b+withMutablePrimArraySafe marr f+    | isMutablePrimArrayPinned marr = do+        siz <- getSizeofMutablePrimArray marr+        withMutablePrimArrayContents marr $ \ ptr -> f ptr siz+    | otherwise = do+        siz <- getSizeofMutablePrimArray marr+        buf <- newPinnedPrimArray siz+        copyMutablePrimArray buf 0 marr 0 siz+        withMutablePrimArrayContents buf $ \ ptr -> f ptr siz++withMutableByteArraySafe :: Int -> (Ptr Word8 -> IO b) -> IO b+withMutableByteArraySafe siz f = do+    buf <- newPinnedPrimArray siz+    withMutablePrimArrayContents buf f++-- | Pass 'PrimVector' to unsafe FFI as pointer+--+-- The 'PrimVector' version of 'withPrimArraySafe'. The 'Ptr' is already pointed+-- to the first element, thus no offset is provided.+--+-- Don't pass a forever loop to this function, see <https://ghc.haskell.org/trac/ghc/ticket/14346 #14346>.+withPrimVectorSafe :: forall a b. (Prim a) => PrimVector a -> (Ptr a -> Int -> IO b) -> IO b+withPrimVectorSafe v@(PrimVector arr s l) f+    | isPrimArrayPinned arr =+        withPrimArrayContents arr $ \ ptr ->+            let ptr' = ptr `plusPtr` (s * siz) in f ptr' l+    | otherwise = do+        buf <- newPinnedPrimArray l+        copyPrimArray buf 0 arr s l+        withMutablePrimArrayContents buf $ \ ptr -> f ptr l+  where+    siz = sizeOf (undefined :: a)++-- | Create an one element primitive array and use it as a pointer to the primitive element.+--+-- Don't pass a forever loop to this function, see <https://ghc.haskell.org/trac/ghc/ticket/14346 #14346>.+withPrimSafe :: forall a b. Prim a => a -> (Ptr a -> IO b) -> IO (a, b)+withPrimSafe v f = do+    buf <- newAlignedPinnedPrimArray 1+    writePrimArray buf 0 v+    !b <- withMutablePrimArrayContents buf $ \ ptr -> f ptr+    !a <- readPrimArray buf 0+    return (a, b)++withPrimSafe' :: forall a b. Prim a => (Ptr a -> IO b) -> IO (a, b)+withPrimSafe' f = do+    buf <- newAlignedPinnedPrimArray 1+    !b <- withMutablePrimArrayContents buf $ \ ptr -> f ptr+    !a <- readPrimArray buf 0+    return (a, b)++--------------------------------------------------------------------------------++foreign import ccall unsafe "string.h" memset :: Ptr a -> CInt -> CSize -> IO ()++-- | Zero a structure.+--+-- There's no 'Storable' or 'Prim' constraint on 'a' type, thus the length+-- should be given in bytes.+--+clearPtr :: Ptr a -> Int -> IO ()+clearPtr dest nbytes = memset dest 0 (fromIntegral nbytes)++-- | Cast between raw address and tagged pointer.+addrToPtr :: Addr -> Ptr a+addrToPtr (Addr addr#) = Ptr addr#++-- | Cast between tagged pointer and raw address.+ptrToAddr :: Ptr a -> Addr+ptrToAddr (Ptr addr#) = Addr addr#
+ Std/IO/Buffered.hs view
@@ -0,0 +1,331 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE ImplicitParams #-}++{-|+Module      : Std.IO.Buffered+Description : Buffered IO interface+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provide buffered IO interface.++-}++module Std.IO.Buffered+  ( -- * Input & Output device+    Input(..), Output(..)+    -- * Buffered Input+  , BufferedInput+  , newBufferedInput+  , readBuffer+  , unReadBuffer+  , readParser+  , readExactly+  , readToMagic, readToMagic'+  , readLine, readLine'+    -- * Buffered Output+  , BufferedOutput+  , newBufferedOutput+  , writeBuffer+  , writeBuilder+  , flushBuffer+    -- * Exceptions+  , ShortReadException(..)+  ) where++import           Control.Concurrent.MVar+import           Control.Concurrent.STM.TVar+import           Control.Monad+import           Control.Monad.Primitive     (ioToPrim, primToIO)+import           Control.Monad.ST+import           Data.IORef+import           Data.Primitive.PrimArray+import           Data.Typeable+import           Data.Word+import           Foreign.Ptr+import           Std.Data.Array+import qualified Std.Data.Builder.Base       as B+import qualified Std.Data.Parser             as P+import qualified Std.Data.Vector             as V+import qualified Std.Data.Vector.Base        as V+import           Std.Data.PrimIORef+import           Std.Foreign.PrimArray+import           Std.IO.Exception++-- | Input device+--+-- Laws: 'readInput' should return 0 on EOF.+--+-- Note: 'readInput' is considered not thread-safe, e.g. A 'Input' device+-- can only be used with a single 'BufferedInput', If multiple 'BufferedInput' s+-- are opened on a same 'Input' device, the behaviour will be undefined.+--+class Input i where+    readInput :: HasCallStack => i -> Ptr Word8 -> Int -> IO Int++-- | Output device+--+-- Laws: 'writeOutput' should not return until all data are written (may not+-- necessarily flushed to hardware, that should be done in device specific way).++-- Note: 'writeOutput' is considered not thread-safe, e.g. A 'Output' device+-- can only be used with a single 'BufferedOutput', If multiple 'BufferedOutput' s+-- are opened on a same 'Input' device, the behaviour will be undefined.+--+class Output o where+    writeOutput :: HasCallStack => o -> Ptr Word8 -> Int -> IO ()++-- | Input device with buffer, NOT THREAD SAFE!+data BufferedInput i = BufferedInput+    { bufInput    :: i+    , bufPushBack :: {-# UNPACK #-} !(IORef V.Bytes)+    , inputBuffer :: {-# UNPACK #-} !(IORef (MutablePrimArray RealWorld Word8))+    }++-- | Output device with buffer, NOT THREAD SAFE!+data BufferedOutput o = BufferedOutput+    { bufOutput     :: o+    , bufIndex      :: {-# UNPACK #-} !Counter+    , outputBuffer  :: {-# UNPACK #-} !(MutablePrimArray RealWorld Word8)+    }+++newBufferedInput :: input+                 -> Int     -- ^ Input buffer size+                 -> IO (BufferedInput input)+newBufferedInput i bufSiz = do+    pb <- newIORef V.empty+    buf <- newPinnedPrimArray bufSiz+    inputBuffer <- newIORef buf+    return (BufferedInput i pb inputBuffer)++newBufferedOutput :: output+                  -> Int    -- ^ Output buffer size+                  -> IO (BufferedOutput output)+newBufferedOutput o bufSiz = do+    index <- newPrimIORef 0+    buf <- newPinnedPrimArray bufSiz+    return (BufferedOutput o index buf)++-- | Request bytes from 'BufferedInput'.+--+-- The buffering logic is quite simple:+--+-- If we have pushed back bytes, directly return it, otherwise we read using buffer size.+-- If we read N bytes, and N is larger than half of the buffer size, then we freeze buffer and return,+-- otherwise we copy buffer into result and reuse buffer afterward.+--+readBuffer :: (HasCallStack, Input i) => BufferedInput i -> IO V.Bytes+readBuffer BufferedInput{..} = do+    pb <- readIORef bufPushBack+    if V.null pb+    then do+        rbuf <- readIORef inputBuffer+        bufSiz <- getSizeofMutablePrimArray rbuf+        l <- readInput bufInput (mutablePrimArrayContents rbuf) bufSiz+        if l < bufSiz `quot` 2                -- read less than half size+        then do+            mba <- newPrimArray l              -- copy result into new array+            copyMutablePrimArray mba 0 rbuf 0 l+            ba <- unsafeFreezePrimArray mba+            return $! V.fromArr ba 0 l+        else do                                -- freeze buf into result+            when (bufSiz /= 0) $ do+                buf' <- newPinnedPrimArray bufSiz+                writeIORef inputBuffer buf'+            ba <- unsafeFreezePrimArray rbuf+            return $! V.fromArr ba 0 l+    else do+        writeIORef bufPushBack V.empty+        return pb++-- | Read exactly N bytes+--+-- If EOF reached before N bytes read, a 'ShortReadException' will be thrown+--+readExactly :: (HasCallStack, Input i) => Int -> BufferedInput i -> IO V.Bytes+readExactly n h = V.concat `fmap` (go h n)+  where+    go h n = do+        chunk <- readBuffer h+        let l = V.length chunk+        if l > n+        then do+            let (lastChunk, rest) = V.splitAt n chunk+            unReadBuffer rest h+            return [lastChunk]+        else if l == n+            then return [chunk]+            else if l == 0+                then+                    throwIO (ShortReadException+                        (IOEInfo "" "unexpected EOF reached" callStack))+                else do+                    chunks <- go h (n - l)+                    return (chunk : chunks)++data ShortReadException = ShortReadException IOEInfo deriving (Show, Typeable)++instance Exception ShortReadException where+    toException = ioExceptionToException+    fromException = ioExceptionFromException+++-- | Push bytes back into buffer+--+unReadBuffer :: (HasCallStack, Input i) => V.Bytes -> BufferedInput i -> IO ()+unReadBuffer pb' BufferedInput{..} = do+    modifyIORef' bufPushBack $ \ pb -> pb' `V.append` pb++-- | Result returned by 'readParser'.+data ReadResult a+    = ReadSuccess  a        -- ^ read and parse successfully+    | ReadFailure String    -- ^ parse failed+    | ReadEOF               -- ^ EOF reached+  deriving Show++-- | Read buffer and parse with 'Parser'.+--+readParser :: (HasCallStack, Input i) => P.Parser a -> BufferedInput i -> IO (ReadResult a)+readParser p i = do+    bs <- readBuffer i+    if V.null bs+    then return ReadEOF+    else do+        (rest, r) <- P.parseChunks (readBuffer i) p bs+        unless (V.null rest) $ unReadBuffer rest i+        case r of+            Left err -> return (ReadFailure err)+            Right a  -> return (ReadSuccess a)++-- | Read until reach a magic bytes+--+-- If EOF is reached before meet a magic byte, partial bytes are returned.+readToMagic :: (HasCallStack, Input i) => Word8 -> BufferedInput i -> IO V.Bytes+readToMagic magic h = V.concat `fmap` (go h magic)+  where+    go h magic = do+        chunk <- readBuffer h+        if V.null chunk+        then return []+        else case V.elemIndex magic chunk of+            Just i -> do+                let (lastChunk, rest) = V.splitAt (i+1) chunk+                unReadBuffer rest h+                return [lastChunk]+            Nothing -> do+                chunks <- go h magic+                return (chunk : chunks)++-- | Read until reach a magic bytes+--+-- If EOF is reached before meet a magic byte, a 'ShortReadException' will be thrown.+readToMagic' :: (HasCallStack, Input i) => Word8 -> BufferedInput i -> IO V.Bytes+readToMagic' magic h = V.concat `fmap` (go h magic)+  where+    go h magic = do+        chunk <- readBuffer h+        if V.null chunk+        then throwIO (ShortReadException+            (IOEInfo "" "unexpected EOF reached" callStack))+        else case V.elemIndex magic chunk of+            Just i -> do+                let (lastChunk, rest) = V.splitAt (i+1) chunk+                unReadBuffer rest h+                return [lastChunk]+            Nothing -> do+                chunks <- go h magic+                return (chunk : chunks)++-- | Read to a linefeed ('\n' or '\r\n'), return 'Bytes' before it.+--+-- If EOF is reached before meet a magic byte, partial line is returned.+readLine :: (HasCallStack, Input i) => BufferedInput i -> IO V.Bytes+readLine i = do+    bs@(V.PrimVector arr s l) <- readToMagic 10 i+    return $ case bs `V.indexMaybe` (l-2) of+        Nothing -> V.PrimVector arr s (l-1)+        Just r | r == 13   -> V.PrimVector arr s (l-2)+               | otherwise -> V.PrimVector arr s (l-1)++-- | Read to a linefeed ('\n' or '\r\n'), return 'Bytes' before it.+--+-- If EOF reached before meet a magic byte, a 'ShortReadException' will be thrown.+readLine' :: (HasCallStack, Input i) => BufferedInput i -> IO V.Bytes+readLine' i = do+    bs@(V.PrimVector arr s l) <- readToMagic' 10 i+    return $ case bs `V.indexMaybe` (l-2) of+        Nothing -> V.PrimVector arr s (l-1)+        Just r | r == 13   -> V.PrimVector arr s (l-2)+               | otherwise -> V.PrimVector arr s (l-1)++--------------------------------------------------------------------------------++-- | Write 'V.Bytes' into buffered handle.+--+-- Copy 'V.Bytes' to buffer if it can hold, otherwise+-- write both buffer(if not empty) and 'V.Bytes'.+--+writeBuffer :: (Output o) => BufferedOutput o -> V.Bytes -> IO ()+writeBuffer o@BufferedOutput{..} v@(V.PrimVector ba s l) = do+    i <- readPrimIORef bufIndex+    bufSiz <- getSizeofMutablePrimArray outputBuffer+    if i + l <= bufSiz+    then do+        -- current buffer can hold it+        copyPrimArray outputBuffer i ba s l   -- copy to buffer+        writePrimIORef bufIndex (i+l)              -- update index+    else do+        if (i > 0)+        then do+            -- flush the buffer+            withMutablePrimArrayContents outputBuffer $ \ ptr -> writeOutput bufOutput ptr i+            writePrimIORef bufIndex 0++            writeBuffer o v -- try write to buffer again+        else+            withPrimVectorSafe v (writeOutput bufOutput)+++-- | Write 'V.Bytes' into buffered handle.+--+-- Copy 'V.Bytes' to buffer if it can hold, otherwise+-- write both buffer(if not empty) and 'V.Bytes'.+--+writeBuilder :: (Output o) => BufferedOutput o -> B.Builder a -> IO ()+writeBuilder BufferedOutput{..} (B.Builder b) = do+    i <- readPrimIORef bufIndex+    originBufSiz <- getSizeofMutablePrimArray outputBuffer+    _ <- primToIO (b (B.OneShotAction action) (lastStep originBufSiz) (B.Buffer outputBuffer i))+    return ()+  where+    action :: V.Bytes -> ST RealWorld ()+    action bytes = ioToPrim (withPrimVectorSafe bytes (writeOutput bufOutput))++    lastStep :: Int -> a -> B.BuildStep RealWorld+    lastStep originBufSiz _ (B.Buffer buf offset)+        | sameMutablePrimArray buf outputBuffer = ioToPrim $ do+            writePrimIORef bufIndex offset   -- record new buffer index+            return []+        | offset >= originBufSiz = ioToPrim $ do+            withMutablePrimArrayContents buf $ \ ptr -> writeOutput bufOutput ptr offset+            writePrimIORef bufIndex 0+            return [] -- to match 'BuildStep' return type+        | otherwise = ioToPrim $ do+            copyMutablePrimArray outputBuffer 0 buf 0 offset+            writePrimIORef bufIndex offset+            return [] -- to match 'BuildStep' return type++-- | Flush the buffer(if not empty).+--+flushBuffer :: Output f => BufferedOutput f -> IO ()+flushBuffer BufferedOutput{..} = do+    i <- readPrimIORef bufIndex+    withMutablePrimArrayContents outputBuffer $ \ ptr -> writeOutput bufOutput ptr i+    writePrimIORef bufIndex 0
+ Std/IO/Exception.hs view
@@ -0,0 +1,275 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Std.IO.Exception+Description : Extensible IO exceptions+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module implemented extensible io exception following approach described in /An Extensible Dynamically-Typed+Hierarchy of Exceptions/ by Simon Marlow. The implementation in this module has simplified to meet common need.+User who want to catch certain type of exceptions can directly use exception types this module provide,+which are modeled after @IOErrorType@ from "GHC.IO.Exception".+++Functions from this package will throw exceptions from this module only instead of the old 'IOError' on IO exceptions.+Exceptions from this module contain 'IOEInfo' which is pretty detailed, but this also require user of this module+do some extra work to keep error message's quality(provide CallStack, device informations, etc.).+New defined IO exceptions are encouraged to include a 'IOEInfo', since it helps a lot when debugging.++Example for library author defining new io exception:++@+  data MyNetworkException = MyNetworkException IOEInfo ... deriving (Show, Typeable)+  instance Exception MyNetworkException where+        toException = ioExceptionToException+        fromException = ioExceptionFromException+@++If you're dealing with OS's errno directly, you should convert the errno to libuv's errno in C side with+'uv_translate_sys_error' from @hs_uv.h@, then use 'throwUVIfMinus/throwUVError' from this module.++-}++module Std.IO.Exception+  ( -- * The 'SomeIOException' type+    SomeIOException(..)+  , ioExceptionToException+  , ioExceptionFromException+    -- * Builtin io exception types+  , IOEInfo(..)+  , AlreadyExists(..)+  , NoSuchThing(..)+  , ResourceBusy(..)+  , ResourceExhausted(..)+  , EOF(..)+  , IllegalOperation(..)+  , PermissionDenied(..)+  , UnsatisfiedConstraints(..)+  , SystemError(..)+  , ProtocolError(..)+  , OtherError(..)+  , InvalidArgument(..)+  , InappropriateType(..)+  , HardwareFault(..)+  , UnsupportedOperation(..)+  , TimeExpired(..)+  , ResourceVanished(..)+  , Interrupted(..)+    -- * Throw io exceptions+  , throwOOMIfNull+  , throwUVIfMinus+  , throwUVIfMinus_+  , throwECLOSED+  , throwECLOSEDSTM+  , throwUVError+    -- * Re-exports+  , module Control.Exception+  , HasCallStack+  , callStack+  ) where++import Control.Exception hiding (IOException)+import Control.Monad+import Control.Concurrent.STM+import Data.Typeable+import Foreign.Ptr+import Foreign.C.Types+import GHC.Stack+import Std.IO.UV.Errno++-- | The root type of all io exceptions, you can catch all io exception by catching this root type.+--+data SomeIOException = forall e . Exception e => SomeIOException e+    deriving Typeable++instance Show SomeIOException where+    show (SomeIOException e) = show e++instance Exception SomeIOException++ioExceptionToException :: Exception e => e -> SomeException+ioExceptionToException = toException . SomeIOException++ioExceptionFromException :: Exception e => SomeException -> Maybe e+ioExceptionFromException x = do+    SomeIOException a <- fromException x+    cast a++#define IOE(e) data e = e IOEInfo deriving (Show, Typeable);  \+               instance Exception e where                     \+                   { toException = ioExceptionToException     \+                   ; fromException = ioExceptionFromException \+                   }+IOE(AlreadyExists)+IOE(NoSuchThing)+IOE(ResourceBusy)+IOE(ResourceExhausted)+IOE(EOF)+IOE(IllegalOperation)+IOE(PermissionDenied)+IOE(UnsatisfiedConstraints)+IOE(SystemError)+IOE(ProtocolError)+IOE(OtherError)+IOE(InvalidArgument)+IOE(InappropriateType)+IOE(HardwareFault)+IOE(UnsupportedOperation)+IOE(TimeExpired)+IOE(ResourceVanished)+IOE(Interrupted)++--------------------------------------------------------------------------------++-- | Throw 'ResourceExhausted' if allocation return a 'nullPtr'.+--+throwOOMIfNull :: HasCallStack+               => IO (Ptr a)    -- ^ the allocation action+               -> IO (Ptr a)+throwOOMIfNull f = do+    addr <- f+    if addr == nullPtr+        then throwIO (ResourceExhausted (IOEInfo "OOM" "out of memory when doing allocation" callStack))+        else return addr++-- | Throw appropriate IO exception if return value < 0 (libuv's convention).+--+throwUVIfMinus :: (HasCallStack, Integral a)+               => IO a    -- ^ the IO action+               -> IO a+throwUVIfMinus f = do+    errno <- f+    let errno' = fromIntegral errno+    if errno' < 0+        then do+            name <- uvErrName errno'+            desc <- uvStdError errno'+            throwUVError errno' (IOEInfo name desc callStack)+        else return errno++-- | Throw appropriate IO exception if return value < 0, otherwise ignore the result.+--+throwUVIfMinus_ :: (HasCallStack, Integral a)+                => IO a    -- ^ the IO action+                -> IO ()+throwUVIfMinus_ f = do+    errno <- f+    let errno' = fromIntegral errno+    when (errno' < 0) $ do+        name <- uvErrName errno'+        desc <- uvStdError errno'+        throwUVError errno' (IOEInfo name desc callStack)++-- | Throw 'E.ResourceVanished' with name 'ECLOSED' and description 'resource is closed'.+--+throwECLOSED :: HasCallStack => IO a+throwECLOSED = throwIO (ResourceVanished+    (IOEInfo "ECLOSED" "resource is closed" callStack))++throwECLOSEDSTM :: HasCallStack => STM a+throwECLOSEDSTM = throwSTM (ResourceVanished+    (IOEInfo "ECLOSED" "resource is closed" callStack))++--------------------------------------------------------------------------------++-- | IO exceptions informations.+--+data IOEInfo = IOEInfo+    { ioeName        :: String      -- ^ the errno name, e.g. EADDRINUSE, etc. empty if no errno.+    , ioeDescription :: String      -- ^ description for this io error, can be errno description, or some custom description if no errno.+    , ioeCallStack   :: CallStack   -- ^ lightweight partial call-stack+    }++instance Show IOEInfo where+    show (IOEInfo errno desc cstack) =+         "{name:" ++ errno +++         ", description:" ++ desc +++         ", callstack:" ++ prettyCallStack cstack ++ "}"++throwUVError :: CInt -> IOEInfo -> IO a+throwUVError e info = case e of+    UV_EOF             -> throwIO (EOF                     info)+    UV_E2BIG           -> throwIO (ResourceExhausted       info)+    UV_EACCES          -> throwIO (PermissionDenied        info)+    UV_EADDRINUSE      -> throwIO (ResourceBusy            info)+    UV_EADDRNOTAVAIL   -> throwIO (UnsupportedOperation    info)+    UV_EAFNOSUPPORT    -> throwIO (UnsupportedOperation    info)+    UV_EAGAIN          -> throwIO (ResourceExhausted       info)+    UV_EAI_ADDRFAMILY  -> throwIO (UnsupportedOperation    info)+    UV_EAI_AGAIN       -> throwIO (ResourceExhausted       info)+    UV_EAI_BADFLAGS    -> throwIO (UnsupportedOperation    info)+    UV_EAI_BADHINTS    -> throwIO (UnsupportedOperation    info)+    UV_EAI_CANCELED    -> throwIO (ResourceVanished        info)+    UV_EAI_FAIL        -> throwIO (OtherError              info)+    UV_EAI_FAMILY      -> throwIO (UnsupportedOperation    info)+    UV_EAI_MEMORY      -> throwIO (ResourceExhausted       info)+    UV_EAI_NODATA      -> throwIO (NoSuchThing             info)+    UV_EAI_NONAME      -> throwIO (NoSuchThing             info)+    UV_EAI_OVERFLOW    -> throwIO (InvalidArgument         info)+    UV_EAI_PROTOCOL    -> throwIO (ProtocolError           info)+    UV_EAI_SERVICE     -> throwIO (UnsupportedOperation    info)+    UV_EAI_SOCKTYPE    -> throwIO (UnsupportedOperation    info)+    UV_EALREADY        -> throwIO (AlreadyExists           info)+    UV_EBADF           -> throwIO (InvalidArgument         info)+    UV_EBUSY           -> throwIO (ResourceBusy            info)+    UV_ECANCELED       -> throwIO (ResourceVanished        info)+    UV_ECHARSET        -> throwIO (OtherError              info)+    UV_ECONNABORTED    -> throwIO (ResourceVanished        info)+    UV_ECONNREFUSED    -> throwIO (NoSuchThing             info)+    UV_ECONNRESET      -> throwIO (ResourceVanished        info)+    UV_EDESTADDRREQ    -> throwIO (InvalidArgument         info)+    UV_EEXIST          -> throwIO (AlreadyExists           info)+    UV_EFAULT          -> throwIO (OtherError              info)+    UV_EFBIG           -> throwIO (PermissionDenied        info)+    UV_EHOSTUNREACH    -> throwIO (NoSuchThing             info)+    UV_EINTR           -> throwIO (Interrupted             info)+    UV_EINVAL          -> throwIO (InvalidArgument         info)+    UV_EIO             -> throwIO (HardwareFault           info)+    UV_EISCONN         -> throwIO (AlreadyExists           info)+    UV_EISDIR          -> throwIO (InappropriateType       info)+    UV_ELOOP           -> throwIO (InvalidArgument         info)+    UV_EMFILE          -> throwIO (ResourceExhausted       info)+    UV_EMSGSIZE        -> throwIO (ResourceExhausted       info)+    UV_ENAMETOOLONG    -> throwIO (InvalidArgument         info)+    UV_ENETDOWN        -> throwIO (ResourceVanished        info)+    UV_ENETUNREACH     -> throwIO (NoSuchThing             info)+    UV_ENFILE          -> throwIO (ResourceExhausted       info)+    UV_ENOBUFS         -> throwIO (ResourceExhausted       info)+    UV_ENODEV          -> throwIO (UnsupportedOperation    info)+    UV_ENOENT          -> throwIO (NoSuchThing             info)+    UV_ENOMEM          -> throwIO (ResourceExhausted       info)+    UV_ENOPROTOOPT     -> throwIO (UnsupportedOperation    info)+    UV_ENOSPC          -> throwIO (ResourceExhausted       info)+    UV_ENOSYS          -> throwIO (UnsupportedOperation    info)+    UV_ENOTCONN        -> throwIO (InvalidArgument         info)+    UV_ENOTDIR         -> throwIO (InappropriateType       info)+    UV_ENOTEMPTY       -> throwIO (UnsatisfiedConstraints  info)+    UV_ENOTSOCK        -> throwIO (InvalidArgument         info)+    UV_ENOTSUP         -> throwIO (UnsupportedOperation    info)+    UV_EPERM           -> throwIO (PermissionDenied        info)+    UV_EPIPE           -> throwIO (ResourceVanished        info)+    UV_EPROTO          -> throwIO (ProtocolError           info)+    UV_EPROTONOSUPPORT -> throwIO (ProtocolError           info)+    UV_EPROTOTYPE      -> throwIO (ProtocolError           info)+    UV_ERANGE          -> throwIO (UnsupportedOperation    info)+    UV_EROFS           -> throwIO (PermissionDenied        info)+    UV_ESHUTDOWN       -> throwIO (IllegalOperation        info)+    UV_ESPIPE          -> throwIO (UnsupportedOperation    info)+    UV_ESRCH           -> throwIO (NoSuchThing             info)+    UV_ETIMEDOUT       -> throwIO (TimeExpired             info)+    UV_ETXTBSY         -> throwIO (ResourceBusy            info)+    UV_EXDEV           -> throwIO (UnsupportedOperation    info)+    UV_UNKNOWN         -> throwIO (OtherError              info)+    UV_ENXIO           -> throwIO (NoSuchThing             info)+    UV_EMLINK          -> throwIO (ResourceExhausted       info)+    _                  -> throwIO (OtherError              info)
+ Std/IO/FileSystem.hs view
@@ -0,0 +1,468 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MultiWayIf   #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Std.IO.FileSystem+Description : Filesystem IO+Copyright   : (c) Dong Han, 2017~2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provide IO operations related to filesystem, operations are implemented using unsafe FFIs, which should be prefered when the operations' estimated time is short(<1ms), which is much common on modern SSDs.++-}++module Std.IO.FileSystem+  ( -- * regular file devices+    UVFile+  , UVFileReader, newUVFileReader, peekUVFileReader+  , UVFileWriter, newUVFileWriter, peekUVFileWriter+  , initUVFile+    -- * opening constant+  , UVFileMode(DEFAULT_MODE, S_IRWXU, S_IRUSR, S_IWUSR+      , S_IXUSR, S_IRWXG, S_IRGRP, S_IWGRP, S_IXGRP, S_IRWXO, S_IROTH+      )+  , UVFileFlag(O_APPEND, O_CREAT, O_DIRECT, O_DSYNC, O_EXCL+      , O_EXLOCK, O_NOATIME, O_NOFOLLOW, O_RDONLY, O_RDWR, O_SYMLINK+      , O_SYNC, O_TRUNC, O_WRONLY, O_RANDOM, O_SHORT_LIVED, O_SEQUENTIAL, O_TEMPORARY+      )+  -- * filesystem operations+  , mkdir+  , unlink+  , mkdtemp+  , rmdir+  , DirEntType(..)+  , scandir+  , UVStat(..), UVTimeSpec(..)+  , stat, lstat, fstat+  , rename+  , fsync, fdatasync+  , ftruncate+  , UVCopyFileFlag(COPYFILE_DEFAULT, COPYFILE_EXCL, COPYFILE_FICLONE)+  , copyfile+  , UVAccessMode(F_OK, R_OK, W_OK, X_OK)+  , AccessResult(..)+  , access+  , chmod, fchmod+  , utime, futime+  , UVSymlinkFlag(SYMLINK_DEFAULT, SYMLINK_DIR, SYMLINK_JUNCTION)+  , link, symlink+  , readlink, realpath+  ) where++import           Control.Concurrent.STM.TVar+import           Control.Concurrent.MVar+import           Control.Monad+import           Control.Monad.STM+import           Data.Word+import           Data.Int+import           Std.Data.CBytes                 as CBytes+import           Foreign.Ptr+import           Foreign.Storable               (peekElemOff)+import           Foreign.Marshal.Alloc          (allocaBytes)+import           Std.Foreign.PrimArray          (withPrimSafe', withPrimUnsafe')+import           Std.IO.Buffered+import           Std.IO.Exception+import           Std.IO.Resource+import           Std.IO.UV.Errno+import           Std.IO.UV.FFI+import           Std.IO.UV.Manager++--------------------------------------------------------------------------------+-- File++-- | 'UVFile' wrap a @uv_file_t@ and a referencing counter.+--+-- libuv implements read and write method with both implict and explict offset capable.+-- (negative offset result in @read/write@ system call otherwise @pread/pwrite@), we provide+-- implict offset interface with 'UVFile', which is NOT thread safe.+--+-- An offset bundled 'UVFileReader', 'UVFileWriter' is also provided, which can be used+-- concurrently. The offset is protected with 'MVar' and increasing automatically.+data UVFile = UVFile+    { uvfFD      :: {-# UNPACK #-} !UVFD+    , uvfCounter :: {-# UNPACK #-} !(TVar Int)+    }++instance Show UVFile where+    show (UVFile fd _) = "Std.IO.FileSystem: UVFile" ++ show fd++instance Input UVFile where+    -- readInput :: HasCallStack => UVFile -> Ptr Word8 -> Int -> IO Int+    -- use -1 offset to use fd's default offset+    readInput f buf bufSiz = readUVFile f buf bufSiz (-1)++readUVFile :: HasCallStack => UVFile -> Ptr Word8 -> Int -> Int64 -> IO Int+readUVFile (UVFile fd counter) buf bufSiz off =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (throwUVIfMinus $ hs_uv_fs_read fd buf bufSiz off)++instance Output UVFile where+    -- use -1 offset to use fd's default offset+    writeOutput f buf bufSiz = writeUVFile f buf bufSiz (-1)++writeUVFile :: HasCallStack => UVFile -> Ptr Word8 -> Int -> Int64 -> IO ()+writeUVFile (UVFile fd counter) buf bufSiz off =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (if off == -1 then go buf bufSiz+                           else go' buf bufSiz off)+  where+    go !buf !bufSiz = do+        written <- throwUVIfMinus+            (hs_uv_fs_write fd buf bufSiz (-1))+        when (written < bufSiz)+            (go (buf `plusPtr` written) (bufSiz-written))++    go' !buf !bufSiz !off = do+        written <- throwUVIfMinus+            (hs_uv_fs_write fd buf bufSiz off)+        when (written < bufSiz) $+            go' (buf `plusPtr` written)+                (bufSiz-written)+                (off+fromIntegral written)++-- | An 'UVFile' bundled with a 'MVar' protected reading offset.+data UVFileReader = UVFileReader {-# UNPACK #-} !UVFile+                                 {-# UNPACK #-} !(MVar Int64)++-- |  Create a reader from an 'UVFile'.+--+-- Note this will not increase 'UVFile''s referencing counter.+newUVFileReader :: UVFile       -- ^ the file we're reading+                -> Int64        -- ^ initial reading offset+                -> IO UVFileReader+newUVFileReader uvf off = UVFileReader uvf <$> newMVar off++-- | Change reader's offset.+peekUVFileReader :: UVFileReader+                 -> Int64       -- ^ the new offset+                 -> IO Int64    -- ^ the old offset+peekUVFileReader (UVFileReader _ offsetLock) = swapMVar offsetLock++instance Input UVFileReader where+    readInput (UVFileReader file offsetLock) buf bufSiz =+        modifyMVar offsetLock $ \ off -> do+            !l <- readUVFile file buf bufSiz off+            let !off' = off + fromIntegral l+            return (off', l)++-- | An 'UVFile' bundled with a 'MVar' protected writing offset.+data UVFileWriter = UVFileWriter {-# UNPACK #-} !UVFile+                                 {-# UNPACK #-} !(MVar Int64)++-- | Create a writer from an 'UVFile'.+--+-- Note this will not increase 'UVFile''s referencing counter.+newUVFileWriter :: UVFile       -- ^ the file we're writing+                -> Int64        -- ^ initial writing offset+                -> IO UVFileWriter+newUVFileWriter uvf off = UVFileWriter uvf <$> newMVar off++-- | Change writer's offset.+peekUVFileWriter :: UVFileWriter+                 -> Int64       -- ^ the new offset+                 -> IO Int64    -- ^ the old offset+peekUVFileWriter (UVFileWriter _ offsetLock) = swapMVar offsetLock++instance Output UVFileWriter where+    writeOutput (UVFileWriter file offsetLock) buf bufSiz =+        modifyMVar_ offsetLock $ \ off -> do+            writeUVFile file buf bufSiz off+            let !off' = off + fromIntegral bufSiz+            return off'++--------------------------------------------------------------------------------++-- | init a file 'Resource', which open a file when used.+--+-- Resource closing will wait for the referencing counter goes+-- down to zero (no reading or writing is in process), which can+-- be a problem if you are using multiple readers or writers in multiple threads.+-- In that case you have to stop all reading or writing thread if you don't want to+-- block the resource thread.+--+-- Note, on some versions of OSX, repeatly open and close same file 'Resource' may+-- result in shared memory object error, use 'O_CREAT' to avoid that.+initUVFile :: HasCallStack+           => CBytes+           -> UVFileFlag        -- ^ Opening flags, e.g. 'O_CREAT' @.|.@ 'O_RDWR'+           -> UVFileMode      -- ^ Sets the file mode (permission and sticky bits),+                              -- but only if the file was created, see 'DEFAULT_MODE'.+           -> Resource UVFile+initUVFile path flags mode =+    initResource+        (do fd <- withCBytes path $ \ p ->+                throwUVIfMinus $ hs_uv_fs_open p flags mode+            counter <- newTVarIO 0+            return (UVFile fd counter))+        (\ (UVFile fd counter) -> join . atomically $ do+            s <- readTVar counter+            case s `compare` 0 of+                GT -> retry -- don't close until no one is using it+                EQ -> do swapTVar counter (-1)+                         return (void $ hs_uv_fs_close fd)+                LT -> return (return ()))++--------------------------------------------------------------------------------++-- | Equivalent to <http://linux.die.net/man/2/mkdir mkdir(2)>.+--+-- Note mode is currently not implemented on Windows.+mkdir :: HasCallStack => CBytes -> UVFileMode -> IO ()+mkdir path mode = throwUVIfMinus_ . withCBytes path $ \ p ->+     hs_uv_fs_mkdir p mode++-- | Equivalent to <http://linux.die.net/man/2/unlink unlink(2)>.+unlink :: HasCallStack => CBytes -> IO ()+unlink path = throwUVIfMinus_ (withCBytes path hs_uv_fs_unlink)+++-- | Equivalent to <mkdtemp http://linux.die.net/man/3/mkdtemp>+--+-- Creates a temporary directory in the most secure manner possible.+-- There are no race conditions in the directory’s creation.+-- The directory is readable, writable, and searchable only by the creating user ID.+-- The user of mkdtemp() is responsible for deleting the temporary directory and+-- its contents when done with it.+--+-- Note: the argument is the prefix of the temporary directory,+-- so no need to add XXXXXX ending.+--+mkdtemp :: HasCallStack => CBytes -> IO CBytes+mkdtemp path = do+    let size = CBytes.length path+    withCBytes path $ \ p ->+        CBytes.create (size+7) $ \ p' -> do  -- we append "XXXXXX\NUL" in C+            throwUVIfMinus_ (hs_uv_fs_mkdtemp p size p')+            return (size+6)++-- | Equivalent to <http://linux.die.net/man/2/rmdir rmdir(2)>.+rmdir :: HasCallStack => CBytes -> IO ()+rmdir path = throwUVIfMinus_ (withCBytes path hs_uv_fs_rmdir)++-- | Equivalent to <http://linux.die.net/man/3/scandir scandir(3)>.+--+-- Note Unlike scandir(3), this function does not return the “.” and “..” entries.+--+-- Note On Linux, getting the type of an entry is only supported by some file systems (btrfs, ext2, ext3 and ext4 at the time of this writing), check the <http://linux.die.net/man/2/getdents getdents(2)> man page.+scandir :: HasCallStack => CBytes -> IO [(CBytes, DirEntType)]+scandir path = do+    uvm <- getUVManager+    bracket+        (withCBytes path $ \ p ->+            withPrimUnsafe' $ \ dents ->+                throwUVIfMinus (hs_uv_fs_scandir p dents))+        (\ (dents, n) -> hs_uv_fs_scandir_cleanup dents n)+        (\ (dents, n) -> forM [0..n-1] $ \ i -> do+            dent <- peekElemOff dents i+            (path, typ) <- peekUVDirEnt dent+            let !typ' = fromUVDirEntType typ+            !path' <- fromCString path+            return (path', typ'))++--------------------------------------------------------------------------------++-- | Equivalent to <http://linux.die.net/man/2/stat stat(2)>+stat :: HasCallStack => CBytes -> IO UVStat+stat path = do+    withCBytes path $ \ p ->+         allocaBytes uvStatSize $ \ stat -> do+            throwUVIfMinus_ (hs_uv_fs_stat p stat)+            peekUVStat stat++-- | Equivalent to <http://linux.die.net/man/2/lstat lstat(2)>+lstat :: HasCallStack => CBytes -> IO UVStat+lstat path = do+    withCBytes path $ \ p ->+         allocaBytes uvStatSize $ \ stat -> do+            throwUVIfMinus_ (hs_uv_fs_lstat p stat)+            peekUVStat stat++-- | Equivalent to <http://linux.die.net/man/2/fstat fstat(2)>+fstat :: HasCallStack => UVFile -> IO UVStat+fstat (UVFile fd counter) =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (allocaBytes uvStatSize $ \ stat -> do+                throwUVIfMinus_ (hs_uv_fs_fstat fd stat)+                peekUVStat stat)++--------------------------------------------------------------------------------++-- | Equivalent to <http://linux.die.net/man/2/rename rename(2)>.+--+-- Note On Windows if this function fails with UV_EBUSY, UV_EPERM or UV_EACCES, it will retry to rename the file up to four times with 250ms wait between attempts before giving up. If both path and new_path are existing directories this function will work only if target directory is empty.+rename :: HasCallStack => CBytes -> CBytes -> IO ()+rename path path' = throwUVIfMinus_ . withCBytes path $ \ p ->+    withCBytes path' (hs_uv_fs_rename p)++-- | Equivalent to <http://linux.die.net/man/2/fsync fsync(2)>.+fsync :: HasCallStack => UVFile -> IO ()+fsync (UVFile fd counter) =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (throwUVIfMinus_ (hs_uv_fs_fsync fd))++-- | Equivalent to <http://linux.die.net/man/2/fdatasync fdatasync(2)>.+fdatasync :: HasCallStack => UVFile -> IO ()+fdatasync (UVFile fd counter) =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (throwUVIfMinus_ (hs_uv_fs_fdatasync fd))++-- | Equivalent to <http://linux.die.net/man/2/ftruncate ftruncate(2)>.+ftruncate :: HasCallStack => UVFile -> Int64 -> IO ()+ftruncate (UVFile fd counter) off =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (throwUVIfMinus_ (hs_uv_fs_ftruncate fd off))++-- | Copies a file from path to new_path.+--+-- Warning: If the destination path is created, but an error occurs while copying the data, then the destination path is removed. There is a brief window of time between closing and removing the file where another process could access the file.+copyfile :: HasCallStack => CBytes -> CBytes -> UVCopyFileFlag -> IO ()+copyfile path path' flag = throwUVIfMinus_ . withCBytes path $ \ p ->+    withCBytes path' $ \ p' -> hs_uv_fs_copyfile p p' flag++-- | Equivalent to <http://linux.die.net/man/2/access access(2)> on Unix.+-- Windows uses GetFileAttributesW().+access :: HasCallStack => CBytes -> UVAccessMode -> IO AccessResult+access path mode = do+     r <- withCBytes path $ \ p -> fromIntegral <$> hs_uv_fs_access p mode+     if | r == 0           -> return AccessOK+        | r == UV_ENOENT   -> return NoExistence+        | r == UV_EACCES   -> return NoPermission+        | otherwise        -> do+            name <- uvErrName r+            desc <- uvStdError r+            throwUVError r (IOEInfo name desc callStack)++-- | Equivalent to <http://linux.die.net/man/2/chmod chmod(2)>.+chmod :: HasCallStack => CBytes -> UVFileMode -> IO ()+chmod path mode = throwUVIfMinus_ . withCBytes path $ \ p -> hs_uv_fs_chmod p mode++-- | Equivalent to <http://linux.die.net/man/2/fchmod fchmod(2)>.+fchmod :: HasCallStack => UVFile -> UVFileMode -> IO ()+fchmod (UVFile fd counter) mode =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (throwUVIfMinus_ (hs_uv_fs_fchmod fd mode))++-- | Equivalent to <http://linux.die.net/man/2/utime utime(2)>.+--+-- libuv choose 'Double' type due to cross platform concerns, we only provide micro-second precision:+--+--   * second     = v+--   * nanosecond = (v * 1000000) % 1000000 * 1000;+--+-- second and nanosecond are fields in 'UVTimeSpec' respectively.+--+-- Note libuv prior to v1.23.1 have issues which may result in nanosecond not set, 'futime' doesn't have+-- that issue.+utime :: HasCallStack+      => CBytes+      -> Double     -- ^ atime, i.e. access time+      -> Double     -- ^ mtime, i.e. modify time+      -> IO ()+utime path atime mtime = throwUVIfMinus_ . withCBytes path $ \ p -> hs_uv_fs_utime p atime mtime++-- | Equivalent to <http://linux.die.net/man/2/futime futime(2)>.+--+-- Same precision notes with 'utime'.+futime :: HasCallStack => UVFile -> Double -> Double -> IO ()+futime (UVFile fd counter) atime mtime =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (throwUVIfMinus_ (hs_uv_fs_futime fd atime mtime))++-- | Equivalent to <http://linux.die.net/man/2/link link(2)>.+link :: HasCallStack => CBytes -> CBytes -> IO ()+link path path' = throwUVIfMinus_ . withCBytes path $ \ p ->+    withCBytes path' $ hs_uv_fs_link p++-- | Equivalent to <http://linux.die.net/man/2/symlink symlink(2)>.+--+-- | Note On Windows the flags parameter can be specified to control how the symlink will be created.+--+--   * 'SYMLINK_DIR': indicates that path points to a directory.+--   * 'SYMLINK_JUNCTION': request that the symlink is created using junction points.+--+-- On other platforms these flags are ignored.+symlink :: HasCallStack => CBytes -> CBytes -> UVSymlinkFlag -> IO ()+symlink path path' flag = throwUVIfMinus_ . withCBytes path $ \ p ->+    withCBytes path' $ \ p' -> hs_uv_fs_symlink p p' flag++-- | Equivalent to <http://linux.die.net/man/2/readlink readlink(2)>.+readlink :: HasCallStack => CBytes -> IO CBytes+readlink path = do+    uvm <- getUVManager+    bracket+        (withCBytes path $ \ p ->+            withPrimUnsafe' $ \ p' ->+                throwUVIfMinus (hs_uv_fs_readlink p p'))+        (\ (path, _) -> hs_uv_fs_readlink_cleanup path)+        (\ (path, _) -> do+            !path' <- fromCString path+            return path')+++-- | Equivalent to <http://linux.die.net/man/3/realpath realpath(3)> on Unix. Windows uses <https://msdn.microsoft.com/en-us/library/windows/desktop/aa364962(v=vs.85).aspx GetFinalPathNameByHandle>.+--+-- Warning This function has certain platform-specific caveats that were discovered when used in Node.+--+--  * macOS and other BSDs: this function will fail with UV_ELOOP if more than 32 symlinks are found while+--    resolving the given path. This limit is hardcoded and cannot be sidestepped.+--+--  * Windows: while this function works in the common case, there are a number of corner cases where it doesn’t:+--+--      * Paths in ramdisk volumes created by tools which sidestep the Volume Manager (such as ImDisk) cannot be resolved.+--      * Inconsistent casing when using drive letters.+--      * Resolved path bypasses subst’d drives.+--+-- While this function can still be used, it’s not recommended if scenarios such as the above need to be supported.+-- The background story and some more details on these issues can be checked <https://github.com/nodejs/node/issues/7726 here>.+--+-- Note This function is not implemented on Windows XP and Windows Server 2003. On these systems, UV_ENOSYS is returned.+realpath :: HasCallStack => CBytes -> IO CBytes+realpath path = do+    uvm <- getUVManager+    bracket+        (withCBytes path $ \ p ->+            withPrimUnsafe' $ \ p' ->+                throwUVIfMinus (hs_uv_fs_realpath p p'))+        (\ (path, _) -> hs_uv_fs_readlink_cleanup path)+        (\ (path, _) -> do+            !path' <- fromCString path+            return path')
+ Std/IO/FileSystemT.hs view
@@ -0,0 +1,522 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Std.IO.FileSystemT+Description : Filesystem IO using threadpool+Copyright   : (c) Dong Han, 2017~2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provide IO operations related to filesystem, operations are implemented using libuv's threadpool to achieve non-block behavior (non-block here meaning won't block other haskell threads), which should be prefered when the operations' estimated time is long enough(>1ms) or running with a non-threaded haskell runtime, such as accessing network filesystem or scan a very large directory. Otherwise you may block RTS's capability thus all the other haskell threads live on it.++The threadpool version operations have overheads similar to safe FFI, but provide same adventages:++  * The libuv's threadpool have a limit on concurrent threads number (4 by default), which can reduce disk contention.+  * The threadpool version works with non-threaded runtime, which doesn't have safe FFI available.+  * The threadpool version won't relinquish current HEC (Haskell Execution Context) a.k.a. capability.++-}++module Std.IO.FileSystemT+  ( -- * regular file devices+    UVFile+  , UVFileReader, newUVFileReader, peekUVFileReader+  , UVFileWriter, newUVFileWriter, peekUVFileWriter+  , initUVFile+    -- * opening constant+  , UVFileMode(DEFAULT_MODE, S_IRWXU, S_IRUSR, S_IWUSR+      , S_IXUSR, S_IRWXG, S_IRGRP, S_IWGRP, S_IXGRP, S_IRWXO, S_IROTH+      )+  , UVFileFlag(O_APPEND, O_CREAT, O_DIRECT, O_DSYNC, O_EXCL+      , O_EXLOCK, O_NOATIME, O_NOFOLLOW, O_RDONLY, O_RDWR, O_SYMLINK+      , O_SYNC, O_TRUNC, O_WRONLY, O_RANDOM, O_SHORT_LIVED, O_SEQUENTIAL, O_TEMPORARY+      )+  -- * filesystem operations+  , mkdir+  , unlink+  , mkdtemp+  , rmdir+  , DirEntType(..)+  , scandir+  , UVStat(..), UVTimeSpec(..)+  , stat, lstat, fstat+  , rename+  , fsync, fdatasync+  , ftruncate+  , UVCopyFileFlag(COPYFILE_DEFAULT, COPYFILE_EXCL, COPYFILE_FICLONE)+  , copyfile+  , UVAccessMode(F_OK, R_OK, W_OK, X_OK)+  , AccessResult(..)+  , access+  , chmod, fchmod+  , utime, futime+  , UVSymlinkFlag(SYMLINK_DEFAULT, SYMLINK_DIR, SYMLINK_JUNCTION)+  , link, symlink+  , readlink, realpath+  ) where++import           Control.Concurrent.STM.TVar+import           Control.Concurrent.MVar+import           Control.Monad+import           Control.Monad.STM+import           Data.Word+import           Data.Int+import           Std.Data.CBytes                 as CBytes+import           Foreign.Ptr+import           Foreign.Storable               (peekElemOff)+import           Foreign.Marshal.Alloc          (allocaBytes)+import           Std.Foreign.PrimArray          (withPrimSafe', withPrimUnsafe')+import           Std.IO.Buffered+import           Std.IO.Exception+import           Std.IO.Resource+import           Std.IO.UV.Errno+import           Std.IO.UV.FFI+import           Std.IO.UV.Manager++--------------------------------------------------------------------------------+-- File++-- | 'UVFile' wrap a @uv_file_t@ and a referencing counter+--+-- Note this is a differet data type from "Std.IO.FileSystem" 's one, the 'Input'+-- and 'Output' instance use thread pool version functions.+--+-- libuv implements read and write method with both implict and explict offset capability.+-- (negative offset result in @read/write@ system call otherwise @pread/pwrite@), we provide+-- implict offset interface with 'UVFile', which is NOT thread safe.+--+-- An offset bundled 'UVFileReader', 'UVFileWriter' is also provided, which can be used+-- concurrently. The offset is protected with 'MVar' and increasing automatically.+data UVFile = UVFile+    { uvfFD      :: {-# UNPACK #-} !UVFD+    , uvfCounter :: {-# UNPACK #-} !(TVar Int)+    }++instance Show UVFile where+    show (UVFile fd _) = "Std.IO.FileSystemT: UVFile" ++ show fd++instance Input UVFile where+    readInput f buf bufSiz = readUVFile f buf bufSiz (-1)++readUVFile :: HasCallStack => UVFile -> Ptr Word8 -> Int -> Int64 -> IO Int+readUVFile (UVFile fd counter) buf bufSiz off =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (do uvm <- getUVManager+                 withUVRequest uvm+                    (hs_uv_fs_read_threaded fd buf bufSiz off))++instance Output UVFile where+    writeOutput f buf bufSiz = writeUVFile f buf bufSiz (-1)++writeUVFile :: HasCallStack => UVFile -> Ptr Word8 -> Int -> Int64 -> IO ()+writeUVFile (UVFile fd counter) buf bufSiz off =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (if off == -1 then go buf bufSiz+                           else go' buf bufSiz off)+  where+    -- use -1 offset to use fd's default offset+    go buf bufSiz = do+        uvm <- getUVManager+        written <- withUVRequest uvm+            (hs_uv_fs_write_threaded fd buf bufSiz (-1))+        when (written < bufSiz)+            (go (buf `plusPtr` written) (bufSiz-written))++    go' buf bufSiz !off = do+        uvm <- getUVManager+        written <- withUVRequest uvm+            (hs_uv_fs_write_threaded fd buf bufSiz off)+        when (written < bufSiz) $+            go' (buf `plusPtr` written)+                (bufSiz-written)+                (off+fromIntegral written)++data UVFileReader = UVFileReader {-# UNPACK #-} !UVFile+                                 {-# UNPACK #-} !(MVar Int64)++-- |  Create a reader from an 'UVFile'.+--+-- Note this will not increase 'UVFile''s referencing counter.+newUVFileReader :: UVFile       -- ^ the file we're reading+                -> Int64        -- ^ initial reading offset+                -> IO UVFileReader+newUVFileReader uvf off = UVFileReader uvf <$> newMVar off++-- | Change reader's offset.+peekUVFileReader :: UVFileReader+                 -> Int64       -- ^ the new offset+                 -> IO Int64    -- ^ the old offset+peekUVFileReader (UVFileReader _ offsetLock) = swapMVar offsetLock++instance Input UVFileReader where+    readInput (UVFileReader file offsetLock) buf bufSiz =+        modifyMVar offsetLock $ \ off -> do+            !l <- readUVFile file buf bufSiz off+            let !off' = off + fromIntegral l+            return (off', l)+++data UVFileWriter = UVFileWriter {-# UNPACK #-} !UVFile+                                 {-# UNPACK #-} !(MVar Int64)++-- | Create a writer from an 'UVFile'.+--+-- Note this will not increase 'UVFile''s referencing counter.+newUVFileWriter :: UVFile       -- ^ the file we're writing+                -> Int64        -- ^ initial writing offset+                -> IO UVFileWriter+newUVFileWriter uvf off = UVFileWriter uvf <$> newMVar off++-- | Change writer's offset.+peekUVFileWriter :: UVFileWriter+                 -> Int64       -- ^ the new offset+                 -> IO Int64    -- ^ the old offset+peekUVFileWriter (UVFileWriter _ offsetLock) = swapMVar offsetLock++instance Output UVFileWriter where+    writeOutput (UVFileWriter file offsetLock) buf bufSiz =+        modifyMVar_ offsetLock $ \ off -> do+            writeUVFile file buf bufSiz off+            let !off' = off + fromIntegral bufSiz+            return off'++--------------------------------------------------------------------------------++-- | init a file 'Resource', which open a file when used.+--+-- Resource closing will wait for the referencing counter goes+-- down to zero (no reading or writing is in process), which can+-- be a problem if you are using multiple readers or writers in multiple threads.+-- In that case you have to stop all reading or writing thread if you don't want to+-- block the resource thread.+initUVFile :: HasCallStack+           => CBytes+           -> UVFileFlag        -- ^ Opening flags, e.g. 'O_CREAT' @.|.@ 'O_RDWR'+           -> UVFileMode        -- ^ Sets the file mode (permission and sticky bits),+                                -- but only if the file was created, see 'DEFAULT_MODE'.+           -> Resource UVFile+initUVFile path flags mode =+    initResource+        (do uvm <- getUVManager+            fd <- withCBytes path $ \ p ->+                withUVRequest uvm (hs_uv_fs_open_threaded p flags mode)+            counter <- newTVarIO 0+            return (UVFile (fromIntegral fd) counter))+        (\ (UVFile fd counter) -> join . atomically $ do+            s <- readTVar counter+            case s `compare` 0 of+                GT -> retry -- don't close until no one is using it+                EQ -> do swapTVar counter (-1)+                         -- there's no need to wait for closing finish+                         -- so just put the closing into the thread pool+                         return (do+                            uvm <- getUVManager+                            void . withUVRequest uvm $+                                hs_uv_fs_close_threaded fd)+                LT -> return (return ()))++--------------------------------------------------------------------------------++-- | Equivalent to <http://linux.die.net/man/2/mkdir mkdir(2)>.+--+-- Note mode is currently not implemented on Windows.+mkdir :: HasCallStack => CBytes -> UVFileMode -> IO ()+mkdir path mode = do+    uvm <- getUVManager+    withCBytes path $ \ p ->+        withUVRequest_ uvm (hs_uv_fs_mkdir_threaded p mode)++-- | Equivalent to <http://linux.die.net/man/2/unlink unlink(2)>.+unlink :: HasCallStack => CBytes -> IO ()+unlink path = do+    uvm <- getUVManager+    withCBytes path $ \ p ->+        withUVRequest_ uvm (hs_uv_fs_unlink_threaded p)++-- | Equivalent to <mkdtemp http://linux.die.net/man/3/mkdtemp>+--+-- Creates a temporary directory in the most secure manner possible.+-- There are no race conditions in the directory’s creation.+-- The directory is readable, writable, and searchable only by the creating user ID.+-- The user of mkdtemp() is responsible for deleting the temporary directory and+-- its contents when done with it.+--+-- Note: the argument is the prefix of the temporary directory,+-- so no need to add XXXXXX ending.+mkdtemp :: HasCallStack => CBytes -> IO CBytes+mkdtemp path = do+    let size = CBytes.length path+    withCBytes path $ \ p ->+        CBytes.create (size+7) $ \ p' -> do  -- we append "XXXXXX\NUL" in C+            uvm <- getUVManager+            withUVRequest_ uvm (hs_uv_fs_mkdtemp_threaded p size p')+            return (size+6)++-- | Equivalent to <http://linux.die.net/man/2/rmdir rmdir(2)>.+rmdir :: HasCallStack => CBytes -> IO ()+rmdir path = do+    uvm <- getUVManager+    withCBytes path (void . withUVRequest uvm . hs_uv_fs_rmdir_threaded)++--------------------------------------------------------------------------------++-- | Equivalent to <http://linux.die.net/man/3/scandir scandir(3)>.+--+-- Note Unlike scandir(3), this function does not return the “.” and “..” entries.+--+-- Note On Linux, getting the type of an entry is only supported by some file systems (btrfs, ext2, ext3 and ext4 at the time of this writing), check the <http://linux.die.net/man/2/getdents getdents(2)> man page.+scandir :: HasCallStack => CBytes -> IO [(CBytes, DirEntType)]+scandir path = do+    uvm <- getUVManager+    bracket+        (withCBytes path $ \ p ->+            withPrimSafe' $ \ dents ->+                withUVRequestEx uvm+                    (hs_uv_fs_scandir_threaded p dents)+                    (hs_uv_fs_scandir_extra_cleanup dents))+        (\ (dents, n) -> hs_uv_fs_scandir_cleanup dents n)+        (\ (dents, n) -> forM [0..n-1] $ \ i -> do+            dent <- peekElemOff dents i+            (path, typ) <- peekUVDirEnt dent+            let !typ' = fromUVDirEntType typ+            !path' <- fromCString path+            return (path', typ'))++--------------------------------------------------------------------------------++-- | Equivalent to <http://linux.die.net/man/2/stat stat(2)>+stat :: HasCallStack => CBytes -> IO UVStat+stat path = do+    withCBytes path $ \ p ->+         allocaBytes uvStatSize $ \ stat -> do+            uvm <- getUVManager+            withUVRequest_ uvm (hs_uv_fs_stat_threaded p stat)+            peekUVStat stat++-- | Equivalent to <http://linux.die.net/man/2/lstat lstat(2)>+lstat :: HasCallStack => CBytes -> IO UVStat+lstat path = do+    withCBytes path $ \ p ->+         allocaBytes uvStatSize $ \ stat -> do+            uvm <- getUVManager+            withUVRequest_ uvm (hs_uv_fs_lstat_threaded p stat)+            peekUVStat stat++-- | Equivalent to <http://linux.die.net/man/2/fstat fstat(2)>+fstat :: HasCallStack => UVFile -> IO UVStat+fstat (UVFile fd counter) = do+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (allocaBytes uvStatSize $ \ stat -> do+                uvm <- getUVManager+                withUVRequest_ uvm (hs_uv_fs_fstat_threaded fd stat)+                peekUVStat stat)++--------------------------------------------------------------------------------++-- | Equivalent to <http://linux.die.net/man/2/rename rename(2)>.+--+-- Note On Windows if this function fails with UV_EBUSY, UV_EPERM or UV_EACCES, it will retry to rename the file up to four times with 250ms wait between attempts before giving up. If both path and new_path are existing directories this function will work only if target directory is empty.+rename :: HasCallStack => CBytes -> CBytes -> IO ()+rename path path' = do+    uvm <- getUVManager+    withCBytes path $ \ p ->+        withCBytes path' $ \ p' ->+            withUVRequest_ uvm (hs_uv_fs_rename_threaded p p')++-- | Equivalent to <http://linux.die.net/man/2/fsync fsync(2)>.+fsync :: HasCallStack => UVFile -> IO ()+fsync (UVFile fd counter) =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (do uvm <- getUVManager+                 withUVRequest_ uvm (hs_uv_fs_fsync_threaded fd))++-- | Equivalent to <http://linux.die.net/man/2/fdatasync fdatasync(2)>.+fdatasync :: HasCallStack => UVFile -> IO ()+fdatasync (UVFile fd counter) =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (do uvm <- getUVManager+                 withUVRequest_ uvm (hs_uv_fs_fdatasync_threaded fd))++-- | Equivalent to <http://linux.die.net/man/2/ftruncate ftruncate(2)>.+ftruncate :: HasCallStack => UVFile -> Int64 -> IO ()+ftruncate (UVFile fd counter) off =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (do uvm <- getUVManager+                 withUVRequest_ uvm (hs_uv_fs_ftruncate_threaded fd off))++-- | Copies a file from path to new_path.+--+-- Warning: If the destination path is created, but an error occurs while copying the data, then the destination path is removed. There is a brief window of time between closing and removing the file where another process could access the file.+copyfile :: HasCallStack => CBytes -> CBytes -> UVCopyFileFlag -> IO ()+copyfile path path' flag = do+    uvm <- getUVManager+    withCBytes path $ \ p ->+        withCBytes path' $ \ p' ->+            withUVRequest_ uvm (hs_uv_fs_copyfile_threaded p p' flag)++-- | Equivalent to <http://linux.die.net/man/2/access access(2)> on Unix.+-- Windows uses GetFileAttributesW().+access :: HasCallStack => CBytes -> UVAccessMode -> IO AccessResult+access path mode = do+    uvm <- getUVManager+    withCBytes path $ \ p ->+        withUVRequest' uvm (hs_uv_fs_access_threaded p mode) (handleResult . fromIntegral)+  where+    handleResult r+        | r == 0           = return AccessOK+        | r == UV_ENOENT   = return NoExistence+        | r == UV_EACCES   = return NoPermission+        | otherwise        = do+            name <- uvErrName r+            desc <- uvStdError r+            throwUVError r (IOEInfo name desc callStack)++-- | Equivalent to <http://linux.die.net/man/2/chmod chmod(2)>.+chmod :: HasCallStack => CBytes -> UVFileMode -> IO ()+chmod path mode = do+    uvm <- getUVManager+    withCBytes path $ \ p ->+        withUVRequest_ uvm (hs_uv_fs_chmod_threaded p mode)++-- | Equivalent to <http://linux.die.net/man/2/fchmod fchmod(2)>.+fchmod :: HasCallStack => UVFile -> UVFileMode -> IO ()+fchmod (UVFile fd counter) mode =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (do uvm <- getUVManager+                 withUVRequest_ uvm (hs_uv_fs_fchmod_threaded fd mode))++-- | Equivalent to <http://linux.die.net/man/2/utime utime(2)>.+--+-- libuv choose 'Double' type due to cross platform concerns, we only provide micro-second precision:+--+--   * second     = v+--   * nanosecond = (v * 1000000) % 1000000 * 1000;+--+-- second and nanosecond are fields in 'UVTimeSpec' respectively.+--+-- Note libuv prior to v1.23.1 have issues which may result in nanosecond not set, 'futime' doesn't have+utime :: HasCallStack+      => CBytes+      -> Double     -- ^ atime, i.e. access time+      -> Double     -- ^ mtime, i.e. modify time+      -> IO ()+utime path atime mtime = do+    uvm <- getUVManager+    withCBytes path $ \ p ->+        withUVRequest_ uvm (hs_uv_fs_utime_threaded p atime mtime)++-- | Equivalent to <http://linux.die.net/man/2/futime futime(2)>.+--+-- Same precision notes with 'utime'.+futime :: HasCallStack => UVFile -> Double -> Double -> IO ()+futime (UVFile fd counter) atime mtime =+    bracket_ (atomically $ do+                s <- readTVar counter+                if s >= 0 then modifyTVar' counter (+1)+                          else throwECLOSEDSTM)+             (atomically $ modifyTVar' counter (subtract 1))+             (do uvm <- getUVManager+                 withUVRequest_ uvm (hs_uv_fs_futime_threaded fd atime mtime))++-- | Equivalent to <http://linux.die.net/man/2/link link(2)>.+link :: HasCallStack => CBytes -> CBytes -> IO ()+link path path' = do+    uvm <- getUVManager+    withCBytes path $ \ p ->+        withCBytes path' $ \ p' ->+            withUVRequest_ uvm (hs_uv_fs_link_threaded p p')++-- | Equivalent to <http://linux.die.net/man/2/symlink symlink(2)>.+--+-- | Note On Windows the flags parameter can be specified to control how the symlink will be created.+--+--   * 'SYMLINK_DIR': indicates that path points to a directory.+--   * 'SYMLINK_JUNCTION': request that the symlink is created using junction points.+--+-- On other platforms these flags are ignored.+symlink :: HasCallStack => CBytes -> CBytes -> UVSymlinkFlag -> IO ()+symlink path path' flag = do+    uvm <- getUVManager+    withCBytes path $ \ p ->+        withCBytes path' $ \ p' ->+            withUVRequest_ uvm (hs_uv_fs_symlink_threaded p p' flag)++-- | Equivalent to <http://linux.die.net/man/2/readlink readlink(2)>.+readlink :: HasCallStack => CBytes -> IO CBytes+readlink path = do+    uvm <- getUVManager+    bracket+        (withCBytes path $ \ p ->+            withPrimSafe' $ \ p' ->+                withUVRequestEx uvm+                    (hs_uv_fs_readlink_threaded p p')+                    (\ _ -> hs_uv_fs_readlink_extra_cleanup p'))+        (\ (path, _) -> hs_uv_fs_readlink_cleanup path)+        (\ (path, _) -> do+            !path' <- fromCString path+            return path')++-- | Equivalent to <http://linux.die.net/man/3/realpath realpath(3)> on Unix. Windows uses <https://msdn.microsoft.com/en-us/library/windows/desktop/aa364962(v=vs.85).aspx GetFinalPathNameByHandle>.+--+-- Warning This function has certain platform-specific caveats that were discovered when used in Node.+--+--  * macOS and other BSDs: this function will fail with UV_ELOOP if more than 32 symlinks are found while+--    resolving the given path. This limit is hardcoded and cannot be sidestepped.+--+--  * Windows: while this function works in the common case, there are a number of corner cases where it doesn’t:+--+--      * Paths in ramdisk volumes created by tools which sidestep the Volume Manager (such as ImDisk) cannot be resolved.+--      * Inconsistent casing when using drive letters.+--      * Resolved path bypasses subst’d drives.+--+-- While this function can still be used, it’s not recommended if scenarios such as the above need to be supported.+-- The background story and some more details on these issues can be checked <https://github.com/nodejs/node/issues/7726 here>.+--+-- Note This function is not implemented on Windows XP and Windows Server 2003. On these systems, UV_ENOSYS is returned.+realpath :: HasCallStack => CBytes -> IO CBytes+realpath path = do+    uvm <- getUVManager+    bracket+        (withCBytes path $ \ p ->+            withPrimSafe' $ \ p' ->+                withUVRequestEx uvm+                    (hs_uv_fs_realpath_threaded p p')+                    (\ _ -> hs_uv_fs_readlink_extra_cleanup p'))+        (\ (path, _) -> hs_uv_fs_readlink_cleanup path)+        (\ (path, _) -> do+            !path' <- fromCString path+            return path')
+ Std/IO/Logger.hs view
@@ -0,0 +1,202 @@+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE BangPatterns #-}++{-|+Module      : Std.IO.Logger+Description : High performance logger+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++Simple, high performance logger. The design choice of this logger is biased towards simplicity instead of generlization:++    * All log functions lives in 'IO'.+    * A logger connected to stderr, 'setStdLogger' are always available.+    * Each logging thread are responsible for building log 'Builder's into a small 'V.Bytes' with line buffer+      instead of leaving all 'Builder's to the flushing thread so that:+        * We won't keep garbage for too long simply because they're referenced by log's 'Builder'.+        * Each logging thread only need perform a CAS to prepend log 'V.Bytes' into a list, which reduces contention.+        * Each log is atomic, Logging order is preserved under concurrent settings.++Flushing is automatic and throttled for 'debug', 'info', 'warn' to boost performance, while a 'fatal' log always flush logger's buffer, This also lead to a problem that if main thread exits too early logs may missed, to add a flushing when program exits, use 'withLogger' like:++@+import Std.IO.Logger++main :: IO ()+main = withStdLogger $ do+    ....+@+-}++module Std.IO.Logger+  ( -- * A simple Logger type+    Logger+  , LoggerConfig(..)+  , newLogger+  , loggerFlush+  , setStdLogger+  , getStdLogger+  , withStdLogger+    -- * logging functions+  , debug+  , info+  , warn+  , fatal+  , otherLevel+    -- * logging functions with specific logger+  , debugWith+  , infoWith+  , warnWith+  , fatalWith+  , otherLevelWith+  ) where++import Control.Monad+import Std.Data.Vector.Base as V+import Std.IO.LowResTimer+import Std.IO.StdStream+import Std.IO.Buffered+import System.IO.Unsafe (unsafePerformIO)+import GHC.Stack+import Data.Word8 (_space, _lf, _bracketleft, _bracketright)+import Data.IORef+import Control.Concurrent.MVar+import qualified Std.Data.Builder.Base as B+import qualified Std.Data.Builder.Numeric as B+import qualified Data.Time as Time+import Std.IO.Exception++data Logger = Logger+    { loggerFlush           :: IO ()                -- ^ flush logger's buffer to output device+    , loggerThrottledFlush  :: IO ()+    , loggerBytesList       :: {-# UNPACK #-} !(IORef [V.Bytes])+    , loggerConfig          :: {-# UNPACK #-} !LoggerConfig+    }++-- | Logger configuration.+data LoggerConfig = LoggerConfig+    { loggerBufferSize       :: {-# UNPACK #-} !Int -- ^ Buffer size used when creating logger's 'BufferedOutput'+    , loggerMinFlushInterval :: {-# UNPACK #-} !Int -- ^ Minimal flush interval, see Notes on 'debug'+    , loggerTsCache          :: IO (B.Builder ())   -- ^ A IO action return a formatted date/time string+    , loggerLineBufSize      :: {-# UNPACK #-} !Int -- ^ Buffer size to build each log/line+    , loggerShowDebug        :: Bool                -- ^ Set to 'False' to filter debug logs+    , loggerShowTS           :: Bool                -- ^ Set to 'False' to disable auto data/time string prepending+    }++-- | A default logger config with+--+--   * debug ON+--   * data/time@%Y-%m-%dT%H:%M:%S%Z@ ON+--   * 0.1s minimal flush interval+--   * line buffer size 128 bytes+--   * 'BufferedOutput' buffer size equals to 'V.defaultChunkSize'.+defaultLoggerConfig :: LoggerConfig+{-# NOINLINE defaultLoggerConfig #-}+defaultLoggerConfig = unsafePerformIO $ do+    tsCache <- throttle 1 $ do+        t <- Time.getCurrentTime+        return . B.string8 $+            Time.formatTime Time.defaultTimeLocale "%Y-%m-%dT%H:%M:%S%Z" t+    return $ LoggerConfig V.defaultChunkSize 10 tsCache 128 True True++flushLog :: Output o => MVar (BufferedOutput o) -> IORef [V.Bytes] -> IO ()+flushLog oLock bList =+    withMVar oLock $ \ o -> do+        bss <- atomicModifyIORef' bList (\ bss -> ([], bss))+        forM_ (reverse bss) (writeBuffer o)+        flushBuffer o++-- | Make a new logger+newLogger :: Output o+          => LoggerConfig+          -> o+          -> IO Logger+newLogger config o = do+    bList <- newIORef []+    oLock <- newMVar =<< newBufferedOutput o (loggerBufferSize config)+    let flush = flushLog oLock bList+    throttledFlush <- throttleTrailing_ (loggerMinFlushInterval config) flush+    return $ Logger flush throttledFlush bList config++globalLogger :: IORef Logger+{-# NOINLINE globalLogger #-}+globalLogger = unsafePerformIO $+    newIORef =<< newLogger defaultLoggerConfig stderr++-- | Change stderr logger.+setStdLogger :: Logger -> IO ()+setStdLogger !logger = atomicWriteIORef globalLogger logger++getStdLogger :: IO Logger+getStdLogger = readIORef globalLogger++-- | Manually flush stderr logger.+flushDefaultLogger :: IO ()+flushDefaultLogger = getStdLogger >>= loggerFlush++pushLog :: IORef [V.Bytes] -> Int -> B.Builder () -> IO ()+pushLog blist bfsiz b = do+    let !bs = B.buildBytesWith bfsiz b+    atomicModifyIORef' blist (\ bss -> (bs:bss, ()))++-- | Flush stderr logger when program exits.+withStdLogger :: IO () -> IO ()+withStdLogger = (`finally` flushDefaultLogger)++--------------------------------------------------------------------------------++debug :: B.Builder () -> IO ()+debug = otherLevel "DEBUG" False++info :: B.Builder () -> IO ()+info = otherLevel "INFO" False++warn :: B.Builder () -> IO ()+warn = otherLevel "WARN" False++fatal :: B.Builder () -> IO ()+fatal = otherLevel "FATAL" True++otherLevel :: B.Builder ()      -- ^ log level+           -> Bool              -- ^ flush immediately?+           -> B.Builder ()      -- ^ log content+           -> IO ()+otherLevel level flushNow b =+    getStdLogger >>= \ logger -> otherLevelWith logger level flushNow b++--------------------------------------------------------------------------------++debugWith :: Logger -> B.Builder () -> IO ()+debugWith logger = otherLevelWith logger "DEBUG" False++infoWith :: Logger -> B.Builder () -> IO ()+infoWith logger = otherLevelWith logger "INFO" False+warnWith :: Logger -> B.Builder () -> IO ()++warnWith logger = otherLevelWith logger "WARN" False+fatalWith :: Logger -> B.Builder () -> IO ()++fatalWith logger = otherLevelWith logger "FATAL" False++otherLevelWith :: Logger+               -> B.Builder ()      -- ^ log level+               -> Bool              -- ^ flush immediately?+               -> B.Builder ()      -- ^ log content+               -> IO ()+otherLevelWith logger level flushNow b = case logger of+    (Logger flush throttledFlush blist (LoggerConfig _ _ tscache lbsiz showdebug showts)) -> do+        ts <- if showts then tscache else return ""+        when showdebug $ do+            pushLog blist lbsiz $ do+                B.encodePrim _bracketleft+                level+                B.encodePrim _bracketright+                B.encodePrim _space+                when showts $ ts >> B.encodePrim _space+                b+                B.encodePrim _lf+            if flushNow then flush else throttledFlush
+ Std/IO/LowResTimer.hs view
@@ -0,0 +1,351 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Std.IO.LowResTimer+Description : Low resolution (0.1s) timing wheel+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provide low resolution (0.1s) timers using a timing wheel of size 128 per capability,+each timer thread will automatically started or stopped based on demannd. register or cancel a timeout is O(1),+and each step only need scan n/128 items given timers are registered in an even fashion.++This timer is particularly suitable for high concurrent approximated IO timeout scheduling.+You should not rely on it to provide timing information since it's very inaccurate.++Reference:++    * <https://github.com/netty/netty/blob/4.1/common/src/main/java/io/netty/util/HashedWheelTimer.java>+    * <http://www.cse.wustl.edu/~cdgill/courses/cs6874/TimingWheels.ppt>+-}+++module Std.IO.LowResTimer+  ( -- * low resolution timers+    registerLowResTimer+  , registerLowResTimer_+  , registerLowResTimerOn+  , LowResTimer+  , queryLowResTimer+  , cancelLowResTimer+  , cancelLowResTimer_+  , timeoutLowRes+  , throttle+  , throttle_+  , throttleTrailing_+    -- * low resolution timer manager+  , LowResTimerManager+  , getLowResTimerManager+  , isLowResTimerManagerRunning+  , lowResTimerManagerCapabilitiesChanged+  ) where++import           Std.Data.Array+#ifndef mingw32_HOST_OS+import           GHC.Event+#endif+import           Control.Concurrent+import           Control.Concurrent.MVar+import           Control.Exception+import           Control.Monad+import           Data.IORef+import           Std.Data.PrimIORef+import           Data.Word+import           GHC.Conc+import           System.IO.Unsafe++--+queueSize :: Int+queueSize = 128++-- | A simple timing wheel+--+data TimerList = TimerItem {-# UNPACK #-} !Counter (IO ()) TimerList | TimerNil++data LowResTimerManager = LowResTimerManager+    { lrTimerQueue :: Array (IORef TimerList)+    , lrIndexLock :: MVar Int+    , lrRegisterCount :: Counter+    , lrRunningLock :: MVar Bool+    }++newLowResTimerManager :: IO LowResTimerManager+newLowResTimerManager = do+    indexLock <- newMVar 0+    regCounter <- newCounter 0+    runningLock <- newMVar False+    queue <- newArr queueSize+    forM [0..queueSize-1] $ \ i -> do+        writeArr queue i =<< newIORef TimerNil+    iqueue <- unsafeFreezeArr queue+    return (LowResTimerManager iqueue indexLock regCounter runningLock)++lowResTimerManager :: IORef (Array LowResTimerManager)+{-# NOINLINE lowResTimerManager #-}+lowResTimerManager = unsafePerformIO $ do+    numCaps <- getNumCapabilities+    lrtmArray <- newArr numCaps+    forM [0..numCaps-1] $ \ i -> do+        writeArr lrtmArray i =<< newLowResTimerManager+    ilrtmArray <- unsafeFreezeArr lrtmArray+    newIORef ilrtmArray++-- | Create new low resolution timer manager on capability change.+--+-- Since low resolution timer manager is not hooked into RTS, you're responsible to call this function+-- after you call 'setNumCapabilities' to match timer manager array size with new capability number.+--+-- This is not a must though, when we fetch timer manager we always take a modulo.+--+lowResTimerManagerCapabilitiesChanged :: IO ()+lowResTimerManagerCapabilitiesChanged = do+    lrtmArray <- readIORef lowResTimerManager+    let oldSize = sizeofArr lrtmArray+    numCaps <- getNumCapabilities+    when (numCaps /= oldSize) $ do+        lrtmArray' <- newArr numCaps+        if numCaps < oldSize+        then do+            forM [0..numCaps-1] $ \ i -> do+                writeArr lrtmArray' i =<< indexArrM lrtmArray i+        else do+            forM [0..oldSize-1] $ \ i -> do+                writeArr lrtmArray' i =<< indexArrM lrtmArray i+            forM [oldSize..numCaps-1] $ \ i -> do+                writeArr lrtmArray' i =<< newLowResTimerManager++        ilrtmArray' <- unsafeFreezeArr lrtmArray'+        atomicModifyIORef' lowResTimerManager $ \ _ -> (ilrtmArray', ())++-- | Get a 'LowResTimerManager' for current thread.+--+getLowResTimerManager :: IO LowResTimerManager+getLowResTimerManager = do+    (cap, _) <- threadCapability =<< myThreadId+    lrtmArray <- readIORef lowResTimerManager+    indexArrM lrtmArray (cap `rem` sizeofArr lrtmArray)++-- | Check if a timer manager's wheel is turning+--+-- This is mostly for testing purpose.+--+isLowResTimerManagerRunning :: LowResTimerManager -> IO Bool+isLowResTimerManagerRunning (LowResTimerManager _ _ _ runningLock) = readMVar runningLock++-- | Register a new timer on current capability's timer manager, start the timing wheel if it's not turning.+--+-- If the action could block, you may want to run it in another thread. Example to kill a thread after 10s:+--+-- @+--   registerLowResTimer 100 (forkIO $ killThread tid)+-- @+--+registerLowResTimer :: Int          -- ^ timeout in unit of 0.1s+                    -> IO ()        -- ^ the action you want to perform, it should not block+                    -> IO LowResTimer+registerLowResTimer t action = do+    lrtm <- getLowResTimerManager+    registerLowResTimerOn lrtm t action++-- | 'void' ('registerLowResTimer' t action)+registerLowResTimer_ :: Int          -- ^ timeout in unit of 0.1s+                     -> IO ()        -- ^ the action you want to perform, it should not block+                     -> IO ()+registerLowResTimer_ t action = void (registerLowResTimer t action)++-- | Same as 'registerLowResTimer', but allow you choose timer manager.+--+registerLowResTimerOn :: LowResTimerManager   -- ^ a low resolution timer manager+                      -> Int          -- ^ timeout in unit of 0.1s+                      -> IO ()        -- ^ the action you want to perform, it should not block+                      -> IO LowResTimer+registerLowResTimerOn lrtm@(LowResTimerManager queue indexLock regCounter _) t action = do++    let (round, tick) = (max 0 t) `quotRem` queueSize+    i <- readMVar indexLock+    tlistRef <- indexArrM queue ((i + tick) `rem` queueSize)+    roundCounter <- newCounter round+    mask_ $ do+        atomicModifyIORef' tlistRef $ \ tlist ->+            let newList = TimerItem roundCounter action tlist+            in (newList, ())+        atomicAddCounter_ regCounter 1++    ensureLowResTimerManager lrtm++    return (LowResTimer roundCounter)  -- cancel is simple, just set the round number to -1.+                                       -- next scan will eventually release it++-- | Timer registered by 'registerLowResTimer' or 'registerLowResTimerOn'.+--+newtype LowResTimer = LowResTimer Counter++-- | Query how many seconds remain before timer firing.+--+-- A return value <= 0 indictate the timer is firing or fired.+--+queryLowResTimer :: LowResTimer -> IO Int+queryLowResTimer (LowResTimer c) = readPrimIORef c++-- | Cancel a timer, return the remaining ticks.+--+-- This function have no effect after the timer is fired.+--+cancelLowResTimer :: LowResTimer -> IO Int+cancelLowResTimer (LowResTimer c) = atomicOrCounter c (-1)++-- | @void . cancelLowResTimer@+--+cancelLowResTimer_ :: LowResTimer -> IO ()+cancelLowResTimer_ = void . cancelLowResTimer++-- | similar to 'System.Timeout.timeout', this function put a limit on time which an IO can consume.+--+-- Note timeoutLowRes is also implemented with 'Exception' underhood, which can have some surprising+-- effects on some devices, e.g. use 'timeoutLowRes' with reading or writing on 'UVStream's will close+-- the 'UVStream' once a reading or writing is not able to be done in time.+timeoutLowRes :: Int    -- ^ timeout in unit of 0.1s+              -> IO a+              -> IO (Maybe a)+timeoutLowRes timeo io = do+    mid <- myThreadId+    catch+        (do timer <- registerLowResTimer timeo (timeoutAThread mid)+            r <- io+            cancelLowResTimer timer+            return (Just r))+        ( \ (e :: TimeOutException) -> return Nothing )+  where+    timeoutAThread id = void . forkIO $ throwTo id TimeOutException++data TimeOutException = TimeOutException deriving Show+instance Exception TimeOutException++--------------------------------------------------------------------------------+-- | Check if low resolution timer manager loop is running, start loop if not.+--+ensureLowResTimerManager :: LowResTimerManager -> IO ()+ensureLowResTimerManager lrtm@(LowResTimerManager _ _ _ runningLock) = do+    modifyMVar_ runningLock $ \ running -> do+        unless running $ do+            tid <- forkIO (startLowResTimerManager lrtm)+            labelThread tid "stdio: low resolution time manager"    -- make sure we can see it in GHC event log+        return True++-- | Start low resolution timer loop, the loop is automatically stopped if there's no more new registrations.+--+startLowResTimerManager :: LowResTimerManager ->IO ()+startLowResTimerManager lrtm@(LowResTimerManager _ _ regCounter runningLock)  = do+    modifyMVar_ runningLock $ \ _ -> do     -- we shouldn't receive async exception here+        c <- readPrimIORef regCounter          -- unless something terribly wrong happened, e.g., stackoverflow+        if c > 0+        then do+            forkIO (fireLowResTimerQueue lrtm)  -- we offload the scanning to another thread to minimize+                                                -- the time we holding runningLock+            case () of+                _+#ifndef mingw32_HOST_OS+                    | rtsSupportsBoundThreads -> do+                        htm <- getSystemTimerManager+                        void $ registerTimeout htm 100000 (startLowResTimerManager lrtm)+#endif+                    | otherwise -> void . forkIO $ do   -- we have to fork another thread since we're holding runningLock,+                        threadDelay 100000              -- this may affect accuracy, but on windows there're no other choices.+                        startLowResTimerManager lrtm+            return True+        else do+            return False -- if we haven't got any registered timeout, we stop the time manager+                         -- doing this can stop us from getting the way of idle GC+                         -- since we're still inside runningLock, we won't miss new registration.++-- | Scan the timeout queue in current tick index, and move tick index forward by one.+--+fireLowResTimerQueue :: LowResTimerManager -> IO ()+fireLowResTimerQueue lrtm@(LowResTimerManager queue indexLock regCounter runningLock) = do+    (tList, tListRef) <- modifyMVar indexLock $ \ index -> do                 -- get the index lock+        tListRef <- indexArrM queue index+        tList <- atomicModifyIORef' tListRef $ \ tList -> (TimerNil, tList)   -- swap current index list with an empty one+        let !index' = (index+1) `rem` queueSize                               -- move index forward by 1+        return (index', (tList, tListRef))                                    -- release the lock++    go tList tListRef regCounter+  where+    go (TimerItem roundCounter action nextList) tListRef regCounter = do+        r <- atomicSubCounter roundCounter 1+        case r `compare` 0 of+            LT -> do                                     -- if round number is less than 0, then it's a cancelled timer+                atomicSubCounter_ regCounter 1+                go nextList tListRef regCounter+            EQ -> do                                     -- if round number is equal to 0, fire it+                atomicSubCounter_ regCounter 1+                catch action ( \ (_ :: SomeException) -> return () )  -- well, we really don't want timers break our loop+                go nextList tListRef regCounter+            GT -> do                                     -- if round number is larger than 0, put it back for another round+                atomicModifyIORef' tListRef $ \ tlist -> (TimerItem roundCounter action tlist, ())+                go nextList tListRef regCounter+    go TimerNil _ _ = return ()++--------------------------------------------------------------------------------++-- | Cache result of an IO action for give time t.+--+-- This combinator is useful when you want to share IO result within a period, the action will be called+-- on demand, and the result will be cached for t milliseconds.+--+-- One common way to get a shared periodical updated value is to start a seperate thread and do calculation+-- periodically, but doing that will stop system from being idle, which stop idle GC from running,+-- and in turn disable deadlock detection, which is too bad. This function solves that.+throttle :: Int         -- ^ cache time in unit of 0.1s+         -> IO a        -- ^ the original IO action+         -> IO (IO a)   -- ^ throttled IO action+throttle t action = do+    resultCounter <- newCounter 0+    resultRef <- newIORef =<< action+    return $ do+        c <- atomicOrCounter resultCounter (-1) -- 0x11111111 or 0x1111111111111111 depend machine word size+        if c == 0+        then do+            registerLowResTimer_ t (void $ atomicAndCounter resultCounter 0)+            !r <- action+            atomicWriteIORef resultRef r+            return r+        else readIORef resultRef++-- | Debounce IO action without caching result.+--+-- The IO action will run at leading edge. i.e. once run, during following (t/10)s throttled action will+-- no-ops.+--+-- Note the action will run in the calling thread.+throttle_ :: Int            -- ^ cache time in unit of 0.1s+          -> IO ()          -- ^ the original IO action+          -> IO (IO ())     -- ^ throttled IO action+throttle_ t action = do+    resultCounter <- newCounter 0+    return $ do+        c <- atomicOrCounter resultCounter (-1) -- 0x11111111 or 0x1111111111111111 depend machine word size+        when (c == 0) $ do+            registerLowResTimer_ t (void $ atomicAndCounter resultCounter 0)+            void action++-- | Similar to 'throttle_' but run action in trailing edge+--+-- The IO action will run at trailing edge. i.e. no matter how many times throttled action+-- are called, original action will run only once after (t/10)s.+--+-- Note the action will be run in a new created thread.+throttleTrailing_ :: Int+                  -> IO ()        -- ^ the original IO action+                  -> IO (IO ())   -- ^ throttled IO action+throttleTrailing_ t action = do+    resultCounter <- newCounter 0+    return $ do+        c <- atomicOrCounter resultCounter (-1) -- 0x11111111 or 0x1111111111111111 depend machine word size+        when (c == 0) . registerLowResTimer_ t . void . forkIO $ do+            atomicAndCounter_ resultCounter 0+            action
+ Std/IO/Resource.hs view
@@ -0,0 +1,285 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE RankNTypes #-}++{-|+Module      : Std.IO.Resource+Description : The Resource monad+Copyright   : (c) Dong Han, 2017+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module also implements Gabriel Gonzalez'd idea on 'Resource' applicative:+<http://www.haskellforall.com/2013/06/the-resource-applicative.html>. The 'Applicative' and 'Monad' instance is+especially useful when you want safely combine multiple resources.++A high performance resource pool based on STM is also provided.++-}++module Std.IO.Resource (+    -- * Resource management+    Resource(..)+  , initResource+  , initResource_+  , withResource+  , withResource'+    -- * Resource pool+  , Pool+  , PoolState(..)+  , initPool+  , statPool+  , initInPool+) where++import           Control.Concurrent.STM+import           Control.Concurrent.STM.TVar+import           Control.Monad+import qualified Control.Monad.Catch as MonadCatch+import           Control.Monad.IO.Class+import           Std.Data.PrimIORef+import           Std.IO.LowResTimer+import           Std.IO.Exception++--------------------------------------------------------------------------------++-- | A 'Resource' is an 'IO' action which acquires some resource of type a and+-- also returns a finalizer of type IO () that releases the resource.+--+-- The only safe way to use a 'Resource' is 'withResource' \/ 'withResource\'',+-- You should not use the `acquire` field directly, unless you want to implement your own+-- resource management. In the later case, you should always use 'mask_' since+-- some resource initializations may assume async exceptions are masked.+--+-- 'MonadIO' instance is provided so that you can lift 'IO' computation inside+-- 'Resource', this is convenient for propagating 'Resource' around since many+-- 'IO' computations carry finalizers.+--+-- A convention in stdio is that functions returning a 'Resource' should be+-- named in @initXXX@ format, users are strongly recommended to follow this convention.+--+-- There're two additional guarantees we made in stdio:+--+--   * All resources in stdio can track its own liveness, throw 'ResourceVanished'+--     exception using 'throwECLOSED' or 'throwECLOSEDSTM' when used after resource+--     is closed.+--+--   * All resources' clean up action in stdio is idempotent.+--+-- Library authors providing 'initXXX' are also encouraged to provide these guarantees.+--+newtype Resource a = Resource { acquire :: HasCallStack => IO (a, IO ()) }++-- | Create 'Resource' from create and release action.+--+-- Note, 'resource' doesn't open resource itself, resource is created when you use+-- 'with' \/ 'with''.+--+initResource :: IO a -> (a -> IO ()) -> Resource a+{-# INLINE initResource #-}+initResource create release = Resource $ do+    r <- create+    return $ (r, release r)++-- | Create 'Resource' from create and release action.+--+-- This function is useful when you want to add some initialization and clean up action+-- inside 'Resource' monad.+--+initResource_ :: IO () -> IO () -> Resource ()+{-# INLINE initResource_ #-}+initResource_ create release = Resource $ do+    r <- create+    return $ (r, release)++instance Functor Resource where+    {-# INLINE fmap #-}+    fmap f resource = Resource $ do+        (a, release) <- acquire resource+        return (f a, release)++instance Applicative Resource where+    {-# INLINE pure #-}+    pure a = Resource (pure (a, pure ()))+    {-# INLINE (<*>) #-}+    resource1 <*> resource2 = Resource $ do+        (f, release1) <- acquire resource1+        (x, release2) <- acquire resource2 `onException` release1+        return (f x, release2 >> release1)++instance Monad Resource where+    {-# INLINE return #-}+    return = pure+    {-# INLINE (>>=) #-}+    m >>= f = Resource $ do+        (m', release1) <- acquire m+        (x , release2) <- acquire (f m') `onException` release1+        return (x, release2 >> release1)++instance MonadIO Resource where+    {-# INLINE liftIO #-}+    liftIO f = Resource $ fmap (\ a -> (a, dummyRelease)) f+        where dummyRelease = return ()++-- | Create a new resource and run some computation, resource is guarantee to+-- be closed.+--+-- Be care don't leak the resource through computation return value, because+-- after the computation finishes, the resource is closed already.+--+withResource :: (MonadCatch.MonadMask m, MonadIO m, HasCallStack)+             => Resource a -> (a -> m b) -> m b+{-# INLINABLE withResource #-}+withResource resource k = MonadCatch.bracket+    (liftIO (acquire resource))+    (\(_, release) -> liftIO release)+    (\(a, _) -> k a)++-- | Create a new resource and run some computation, resource is guarantee to+-- be closed.+--+-- The difference from 'with' is that the computation will receive an extra+-- close action, which can be used to close the resource early before the whole+-- computation finished, the close action can be called multiple times,+-- only the first call will clean up the resource.+--+withResource' :: (MonadCatch.MonadMask m, MonadIO m, HasCallStack)+              => Resource a -> (a -> m () -> m b) -> m b+{-# INLINABLE withResource' #-}+withResource' resource k = do+    c <- liftIO (newCounter 0)+    MonadCatch.bracket+        (liftIO $ do+            (a, release) <- (acquire resource)+            let release' = do+                    c' <- atomicOrCounter c 1+                    when (c' == 0) release+            return (a, release'))+        (\(_, release) -> liftIO release)+        (\(a, release) -> k a (liftIO release))++--------------------------------------------------------------------------------++-- | A single resource pool entry.+data Entry a = Entry+    (a, IO ())             -- the resource and clean up action+    {-# UNPACK #-} !Int    -- the life remaining++data PoolState = PoolClosed | PoolScanning | PoolEmpty deriving (Eq, Show)++-- | A high performance resource pool based on STM.+--+-- We choose to not divide pool into strips due to the difficults in resource balancing. If there+-- is a high contention on resource (see 'statPool'), just increase the maximum number of resources+-- can be opened.+--+data Pool a = Pool+    { poolResource :: Resource a+    , poolLimit :: Int+    , poolIdleTime :: Int+    , poolEntries :: TVar [Entry a]+    , poolInUse :: TVar Int+    , poolState :: TVar PoolState+    }++-- | Initialize a resource pool with given 'Resource'+--+-- Like other initXXX functions, this function won't open a resource pool until you use 'withResource'.+-- And this resource pool follow the same resource management pattern like other resources.+--+initPool :: Resource a+         -> Int     -- ^ maximum number of resources can be opened+         -> Int     -- ^ amount of time after which an unused resource can be released (in seconds).+         -> Resource (Pool a)+initPool res limit itime = initResource createPool closePool+  where+    createPool = do+        entries <- newTVarIO []+        inuse <- newTVarIO 0+        state <- newTVarIO PoolEmpty+        return (Pool res limit itime entries inuse state)++    closePool (Pool _ _ _ entries _ state) = join . atomically $ do+        c <- readTVar state+        if c == PoolClosed+        then return (return ())+        else do+            writeTVar state PoolClosed+            return (do+                es <- readTVarIO entries+                forM_ es $ \ (Entry (_, close) _) ->+                    MonadCatch.handleAll (\ _ -> return ()) close)++-- | Get a resource pool's 'PoolState'+--+-- This function is useful when debug, under load lots of 'PoolEmpty' may indicate+-- contention on resources, i.e. the limit on maximum number of resources can be opened+-- should be adjusted to a higher number. On the otherhand, lots of 'PoolScanning'+-- may indicate there're too much free resources.+--+statPool :: Pool a -> IO PoolState+statPool pool = readTVarIO (poolState pool)++-- | Obtain the pooled resource inside a given resource pool.+--+-- You shouldn't use 'withResource' with this resource after you closed the pool,+-- an 'ResourceVanished' with @EPOOLCLOSED@ name will be thrown.+--+initInPool :: Pool a -> Resource a+initInPool (Pool res limit itime entries inuse state) = fst <$> initResource takeFromPool returnToPool+  where+    takeFromPool = join . atomically $ do+        c <- readTVar state+        if c == PoolClosed+        then throwECLOSEDSTM+        else do+            es <- readTVar entries+            case es of+                ((Entry a _):es') -> do+                    writeTVar entries es'+                    return (return a)+                _ -> do+                    i <- readTVar inuse+                    when (i == limit) retry+                    modifyTVar' inuse (+1)+                    return (acquire res `onException`+                         atomically (modifyTVar' inuse (subtract 1)))++    returnToPool a = join . atomically $ do+        c <- readTVar state+        case c of+            PoolClosed -> return (snd a)+            PoolEmpty -> do+                modifyTVar' entries (Entry a itime:)+                writeTVar state PoolScanning+                return (void $ registerLowResTimer 10 (scanPool entries inuse state))+            _ -> do+                modifyTVar' entries (Entry a itime:)+                return (return ())++    scanPool entries inuse state = do+         join . atomically $ do+            c <- readTVar state+            if c == PoolClosed+            then return (return ())+            else do+                es <- readTVar entries+                if (null es)+                then do+                    writeTVar state PoolEmpty+                    return (return ())+                else do+                    let (deadNum, dead, living) = age es 0 [] []+                    writeTVar entries living+                    modifyTVar' inuse (subtract deadNum)+                    return (do+                        forM_ dead $ \ (_, close) ->+                            MonadCatch.handleAll (\ _ -> return ()) close+                        void $ registerLowResTimer 10 (scanPool entries inuse state))++    age ((Entry a life):es) !deadNum dead living+        | life > 1  = age es deadNum     dead     (Entry a (life-1):living)+        | otherwise = age es (deadNum+1) (a:dead) living+    age _ !deadNum dead living = (deadNum, dead, living)
+ Std/IO/SockAddr.hsc view
@@ -0,0 +1,453 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE PatternSynonyms    #-}++{-|+Module      : Std.IO.SockAddr+Description : TCP/UDP socket address API+Copyright   : (c) Winterland, 2018+License     : BSD+Maintainer  : drkoster@qq.com+Stability   : experimental+Portability : non-portable++This module provides necessary types and constant for low level socket operation.++-}++module Std.IO.SockAddr+  ( -- * name to address+    SockAddr(..)+  , sockAddrFamily+  , peekSockAddr+  , withSockAddr+   -- ** IPv4 address+  , InetAddr+  , inetAny+  , inetBroadcast+  , inetNone+  , inetLoopback+  , inetUnspecificGroup+  , inetAllHostsGroup+  , inetMaxLocalGroup+  , inetAddrToTuple+  , tupleToInetAddr+   -- ** IPv6 address+  , Inet6Addr+  , inet6Any+  , inet6Loopback+  , inet6AddrToTuple+  , tupleToInet6Addr+  , FlowInfo+  , ScopeID+  -- * port numbber+  , PortNumber +  , aNY_PORT+  , htons+  , ntohs+  , ntohl+  , htonl+  -- * family, type, protocol+  , SocketFamily(..)+  , pattern AF_UNSPEC+  , pattern AF_INET+  , pattern AF_INET6+  , SocketType(..)+  , pattern SOCK_DGRAM+  , pattern SOCK_STREAM+  , pattern SOCK_SEQPACKET+  , pattern SOCK_RAW+  , pattern SOCK_RDM+  , SocketProtocol(..)+  , pattern IPPROTO_TCP+  , pattern IPPROTO_UDP+  ) where++import           Control.Monad.IO.Class+import           Control.Monad.Primitive+import           Data.Bits+import qualified Data.List                as List+import           Data.Primitive.PrimArray+import           Data.Ratio+import           Data.Typeable+import           Foreign+import           Foreign.C+import           GHC.ForeignPtr        (mallocPlainForeignPtrAlignedBytes)+import           GHC.Stack+import           Numeric               (showHex)+import           Std.Data.CBytes+import qualified Std.Data.Vector       as V+import           Std.Foreign.PrimArray+import           Std.IO.Exception+import           Std.IO.Resource+import           Std.IO.UV.Errno+import           System.IO.Unsafe      (unsafeDupablePerformIO)++#include "hs_uv.h" ++#if __GLASGOW_HASKELL__ < 800+#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)+#endif++#if defined(i386_HOST_ARCH) && defined(mingw32_HOST_OS)+#let CALLCONV = "stdcall"+#else+#let CALLCONV = "ccall"+#endif++--------------------------------------------------------------------------------++#if defined(_WIN32)+type CSaFamily = (#type unsigned short)+#elif defined(darwin_HOST_OS)+type CSaFamily = (#type u_char)+#else+type CSaFamily = (#type sa_family_t)+#endif++-- | IPv4 or IPv6 socket address, i.e. the `sockaddr_in` or `sockaddr_in6` struct.+-- +data SockAddr +    = SockAddrInet+        {-# UNPACK #-} !PortNumber  -- sin_port  (network byte order)+        {-# UNPACK #-} !InetAddr    -- sin_addr  (ditto)+    | SockAddrInet6+        {-# UNPACK #-} !PortNumber  -- sin6_port (network byte order)+        {-# UNPACK #-} !FlowInfo    -- sin6_flowinfo (ditto)+        {-# UNPACK #-} !Inet6Addr   -- sin6_addr (ditto)+        {-# UNPACK #-} !ScopeID     -- sin6_scope_id (ditto)+  deriving (Show, Eq, Ord)++sockAddrFamily :: SockAddr -> SocketFamily+sockAddrFamily (SockAddrInet _ _) = AF_INET+sockAddrFamily (SockAddrInet6 _ _ _ _) = AF_INET6++type FlowInfo = Word32+type ScopeID = Word32++--------------------------------------------------------------------------------++-- | Independent of endianness. For example @127.0.0.1@ is stored as @(127, 0, 0, 1)@.+--+-- For direct manipulation prefer 'inetAddrToTuple' and 'tupleToInetAddr'.+--+newtype InetAddr = InetAddr Word32 deriving (Eq, Ord)+instance Show InetAddr where+    showsPrec _ ia = +        let (a,b,c,d) = inetAddrToTuple ia+        in ("InetAddr " ++) . shows a . ('.':)+                            . shows b . ('.':)+                            . shows c . ('.':)+                            . shows d++-- | @0.0.0.0@+inetAny             :: InetAddr+inetAny              = InetAddr 0++-- | @255.255.255.255@+inetBroadcast       :: InetAddr+inetBroadcast        = tupleToInetAddr (255,255,255,255)++-- | @255.255.255.255@+inetNone            :: InetAddr+inetNone             = tupleToInetAddr (255,255,255,255)++-- | @127.0.0.1@+inetLoopback        :: InetAddr+inetLoopback         = tupleToInetAddr (127,  0,  0,  1)++-- | @224.0.0.0@+inetUnspecificGroup :: InetAddr+inetUnspecificGroup  = tupleToInetAddr (224,  0,  0,  0)++-- | @224.0.0.1@+inetAllHostsGroup   :: InetAddr+inetAllHostsGroup    = tupleToInetAddr (224,  0,  0,  1)++-- | @224.0.0.255@+inetMaxLocalGroup   :: InetAddr+inetMaxLocalGroup    = tupleToInetAddr (224,  0,  0,255)++instance Storable InetAddr where+    sizeOf _ = sizeOf (undefined :: Word32)+    alignment _ = alignment (undefined :: Word32) +    peek p = (InetAddr . ntohl) `fmap` peekByteOff p 0+    poke p (InetAddr ia) = pokeByteOff p 0 (htonl ia)++-- | Converts 'HostAddress' to representation-independent IPv4 quadruple.+-- For example for @127.0.0.1@ the function will return @(127, 0, 0, 1)@+-- regardless of host endianness.+inetAddrToTuple :: InetAddr -> (Word8, Word8, Word8, Word8)+inetAddrToTuple (InetAddr ia) =+    let byte i = fromIntegral (ia `shiftR` i) :: Word8+    in (byte 24, byte 16, byte 8, byte 0)++-- | Converts IPv4 quadruple to 'HostAddress'.+tupleToInetAddr :: (Word8, Word8, Word8, Word8) -> InetAddr+tupleToInetAddr (b3, b2, b1, b0) =+    let x `sl` i = fromIntegral x `shiftL` i :: Word32+    in InetAddr $ (b3 `sl` 24) .|. (b2 `sl` 16) .|. (b1 `sl` 8) .|. (b0 `sl` 0)++--------------------------------------------------------------------------------++-- | Independent of endianness. For example @::1@ is stored as @(0, 0, 0, 1)@.+--+-- For direct manipulation prefer 'inet6AddrToTuple' and 'tupleToInet6Addr'.+--+data Inet6Addr = Inet6Addr {-# UNPACK #-}!Word32+                           {-# UNPACK #-}!Word32+                           {-# UNPACK #-}!Word32+                           {-# UNPACK #-}!Word32 deriving (Eq, Ord)++instance Show Inet6Addr where+    showsPrec _ i6a = +        let (a,b,c,d,e,f,g,h) = inet6AddrToTuple i6a+        in ("Inet6Addr " ++) . showHex a . (':':)+                             . showHex b . (':':)+                             . showHex c . (':':)+                             . showHex d . (':':)+                             . showHex e . (':':)+                             . showHex f . (':':)+                             . showHex g . (':':)+                             . showHex h++-- | @::@+inet6Any      :: Inet6Addr+inet6Any       = Inet6Addr 0 0 0 0++-- | @::1@+inet6Loopback :: Inet6Addr+inet6Loopback  = Inet6Addr 0 0 0 1++inet6AddrToTuple :: Inet6Addr -> (Word16, Word16, Word16, Word16,+                                        Word16, Word16, Word16, Word16)+inet6AddrToTuple (Inet6Addr w3 w2 w1 w0) =+    let high, low :: Word32 -> Word16+        high w = fromIntegral (w `shiftR` 16)+        low w = fromIntegral w+    in (high w3, low w3, high w2, low w2, high w1, low w1, high w0, low w0)++tupleToInet6Addr :: (Word16, Word16, Word16, Word16,+                        Word16, Word16, Word16, Word16) -> Inet6Addr+tupleToInet6Addr (w7, w6, w5, w4, w3, w2, w1, w0) =+    let add :: Word16 -> Word16 -> Word32+        high `add` low = (fromIntegral high `shiftL` 16) .|. (fromIntegral low)+    in  Inet6Addr (w7 `add` w6) (w5 `add` w4) (w3 `add` w2) (w1 `add` w0)++instance Storable Inet6Addr where+    sizeOf _    = #size struct in6_addr+    alignment _ = #alignment struct in6_addr++    peek p = do+        a <- peek32 p 0+        b <- peek32 p 1+        c <- peek32 p 2+        d <- peek32 p 3+        return $ Inet6Addr a b c d++    poke p (Inet6Addr a b c d) = do+        poke32 p 0 a+        poke32 p 1 b+        poke32 p 2 c+        poke32 p 3 d++--------------------------------------------------------------------------------++peekSockAddr :: HasCallStack => Ptr SockAddr -> IO SockAddr+peekSockAddr p = do+    family <- (#peek struct sockaddr, sa_family) p+    case family :: CSaFamily of+        (#const AF_INET) -> do+            addr <- (#peek struct sockaddr_in, sin_addr) p+            port <- (#peek struct sockaddr_in, sin_port) p+            return (SockAddrInet (PortNum port) addr)+        (#const AF_INET6) -> do+            port <- (#peek struct sockaddr_in6, sin6_port) p+            flow <- (#peek struct sockaddr_in6, sin6_flowinfo) p+            addr <- (#peek struct sockaddr_in6, sin6_addr) p+            scope <- (#peek struct sockaddr_in6, sin6_scope_id) p+            return (SockAddrInet6 (PortNum port) flow addr scope)++        _ -> do let errno = UV_EAI_ADDRFAMILY+                name <- uvErrName errno+                desc <- uvStdError errno+                throwUVError errno (IOEInfo name desc callStack)++pokeSockAddr :: HasCallStack => Ptr SockAddr -> SockAddr -> IO ()+pokeSockAddr p (SockAddrInet (PortNum port) addr) =  do+#if defined(darwin_HOST_OS)+    clearPtr p (#const sizeof(struct sockaddr_in))+#endif+#if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)+    (#poke struct sockaddr_in, sin_len) p ((#const sizeof(struct sockaddr_in)) :: Word8)+#endif+    (#poke struct sockaddr_in, sin_family) p ((#const AF_INET) :: CSaFamily)+    (#poke struct sockaddr_in, sin_port) p port+    (#poke struct sockaddr_in, sin_addr) p addr+pokeSockAddr p (SockAddrInet6 (PortNum port) flow addr scope) =  do+#if defined(darwin_HOST_OS)+    clearPtr p (#const sizeof(struct sockaddr_in6))+#endif+#if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)+    (#poke struct sockaddr_in6, sin6_len) p ((#const sizeof(struct sockaddr_in6)) :: Word8)+#endif+    (#poke struct sockaddr_in6, sin6_family) p ((#const AF_INET6) :: CSaFamily)+    (#poke struct sockaddr_in6, sin6_port) p port+    (#poke struct sockaddr_in6, sin6_flowinfo) p flow+    (#poke struct sockaddr_in6, sin6_addr) p (addr)+    (#poke struct sockaddr_in6, sin6_scope_id) p scope++withSockAddr :: SockAddr -> (Ptr SockAddr -> IO a) -> IO a+withSockAddr sa@(SockAddrInet _ _) f = do+    allocaBytesAligned+        (#size struct sockaddr_in)+        (#alignment struct sockaddr_in) $ \ p -> pokeSockAddr p sa >> f p+withSockAddr sa@(SockAddrInet6 _ _ _ _) f = do+    allocaBytesAligned +        (#size struct sockaddr_in6) +        (#alignment struct sockaddr_in6) $ \ p -> pokeSockAddr p sa >> f p++-- The peek32 and poke32 functions work around the fact that the RFCs+-- don't require 32-bit-wide address fields to be present.  We can+-- only portably rely on an 8-bit field, s6_addr.++s6_addr_offset :: Int+s6_addr_offset = (#offset struct in6_addr, s6_addr)++peek32 :: Ptr a -> Int -> IO Word32+peek32 p i0 = do+    let i' = i0 * 4+        peekByte n = peekByteOff p (s6_addr_offset + i' + n) :: IO Word8+        a `sl` i = fromIntegral a `shiftL` i+    a0 <- peekByte 0+    a1 <- peekByte 1+    a2 <- peekByte 2+    a3 <- peekByte 3+    return ((a0 `sl` 24) .|. (a1 `sl` 16) .|. (a2 `sl` 8) .|. (a3 `sl` 0))++poke32 :: Ptr a -> Int -> Word32 -> IO ()+poke32 p i0 a = do+    let i' = i0 * 4+        pokeByte n = pokeByteOff p (s6_addr_offset + i' + n)+        x `sr` i = fromIntegral (x `shiftR` i) :: Word8+    pokeByte 0 (a `sr` 24)+    pokeByte 1 (a `sr` 16)+    pokeByte 2 (a `sr`  8)+    pokeByte 3 (a `sr`  0)++--------------------------------------------------------------------------------++-- Port Numbers++-- | Use the @Num@ instance (i.e. use a literal or 'fromIntegral') to create a+-- @PortNumber@ value with the correct network-byte-ordering.+--+-- >>> 1 :: PortNumber+-- 1+-- >>> read "1" :: PortNumber+-- 1+newtype PortNumber = PortNum Word16 deriving (Eq, Ord, Typeable)+-- newtyped to prevent accidental use of sane-looking+-- port numbers that haven't actually been converted to+-- network-byte-order first.++aNY_PORT :: PortNumber+aNY_PORT = 0++instance Show PortNumber where+  showsPrec p pn = showsPrec p (portNumberToInt pn)++instance Read PortNumber where+  readsPrec n = map (\(x,y) -> (intToPortNumber x, y)) . readsPrec n++intToPortNumber :: Int -> PortNumber+intToPortNumber v = PortNum (htons (fromIntegral v))++portNumberToInt :: PortNumber -> Int+portNumberToInt (PortNum po) = fromIntegral (ntohs po)++foreign import #{CALLCONV} unsafe "ntohs" ntohs :: Word16 -> Word16+foreign import #{CALLCONV} unsafe "htons" htons :: Word16 -> Word16+foreign import #{CALLCONV} unsafe "ntohl" ntohl :: Word32 -> Word32+foreign import #{CALLCONV} unsafe "htonl" htonl :: Word32 -> Word32++instance Enum PortNumber where+    toEnum   = intToPortNumber+    fromEnum = portNumberToInt++instance Num PortNumber where+   fromInteger i = intToPortNumber (fromInteger i)+    -- for completeness.+   (+) x y   = intToPortNumber (portNumberToInt x + portNumberToInt y)+   (-) x y   = intToPortNumber (portNumberToInt x - portNumberToInt y)+   negate x  = intToPortNumber (-portNumberToInt x)+   (*) x y   = intToPortNumber (portNumberToInt x * portNumberToInt y)+   abs n     = intToPortNumber (abs (portNumberToInt n))+   signum n  = intToPortNumber (signum (portNumberToInt n))++instance Real PortNumber where+    toRational x = toInteger x % 1++instance Integral PortNumber where+    quotRem a b = let (c,d) = quotRem (portNumberToInt a) (portNumberToInt b) in+                  (intToPortNumber c, intToPortNumber d)+    toInteger a = toInteger (portNumberToInt a)++instance Storable PortNumber where+   sizeOf    _ = sizeOf    (undefined :: Word16)+   alignment _ = alignment (undefined :: Word16)+   poke p (PortNum po) = poke (castPtr p) po+   peek p = PortNum `fmap` peek (castPtr p)+    +--------------------------------------------------------------------------------++newtype SocketFamily = SocketFamily CInt deriving (Show, Read, Eq, Ord, Typeable)+newtype SocketType = SocketType CInt deriving (Show, Read, Eq, Ord, Typeable)+newtype SocketProtocol = SocketProtocol CInt deriving (Show, Read, Eq, Ord, Typeable)++instance Storable SocketFamily where                      +    sizeOf _ = sizeOf (undefined :: CInt)       +    alignment _ = alignment (undefined :: CInt) +    peek ptr = SocketFamily `fmap` peek (castPtr ptr)             +    poke ptr (SocketFamily v) = poke (castPtr ptr) v++instance Storable SocketType where                      +    sizeOf _ = sizeOf (undefined :: CInt)       +    alignment _ = alignment (undefined :: CInt) +    peek ptr = SocketType `fmap` peek (castPtr ptr)             +    poke ptr (SocketType v) = poke (castPtr ptr) v++instance Storable SocketProtocol where                      +    sizeOf _ = sizeOf (undefined :: CInt)       +    alignment _ = alignment (undefined :: CInt) +    peek ptr = SocketProtocol `fmap` peek (castPtr ptr)             +    poke ptr (SocketProtocol v) = poke (castPtr ptr) v++-- | unspecified+pattern AF_UNSPEC :: SocketFamily+pattern AF_UNSPEC = SocketFamily (#const AF_UNSPEC)+-- | internetwork: UDP, TCP, etc+pattern AF_INET :: SocketFamily+pattern AF_INET = SocketFamily (#const AF_INET)+-- | Internet Protocol version 6+pattern AF_INET6 :: SocketFamily+pattern AF_INET6 = SocketFamily (#const AF_INET6)++pattern SOCK_STREAM :: SocketType+pattern SOCK_STREAM = SocketType (#const SOCK_STREAM)+pattern SOCK_DGRAM :: SocketType+pattern SOCK_DGRAM = SocketType (#const SOCK_DGRAM) +pattern SOCK_RAW :: SocketType+pattern SOCK_RAW = SocketType (#const SOCK_RAW) +pattern SOCK_RDM :: SocketType+pattern SOCK_RDM = SocketType (#const SOCK_RDM) +pattern SOCK_SEQPACKET :: SocketType+pattern SOCK_SEQPACKET = SocketType (#const SOCK_SEQPACKET) ++pattern IPPROTO_DEF :: SocketProtocol+pattern IPPROTO_DEF = SocketProtocol 0+pattern IPPROTO_IP :: SocketProtocol+pattern IPPROTO_IP = SocketProtocol (#const IPPROTO_IP)+pattern IPPROTO_TCP :: SocketProtocol+pattern IPPROTO_TCP = SocketProtocol (#const IPPROTO_TCP)+pattern IPPROTO_UDP :: SocketProtocol+pattern IPPROTO_UDP = SocketProtocol (#const IPPROTO_UDP)
+ Std/IO/StdStream.hs view
@@ -0,0 +1,167 @@+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE BangPatterns #-}+++{-|+Module      : Std.IO.StdStream+Description : TTY devices+Copyright   : (c) Dong Han, 2018~2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provides stdin\/stderr\/stdout reading and writings. Usually you don't have to use 'stderr' or 'stderrBuf' directly, 'Std.IO.Logger' provides more logging utilities through @stderr@. While 'stdinBuf' and 'stdoutBuf' is useful when you write interactive programs, 'Std.IO.Buffered' module provide many reading and writing operations. Example:++@+import Std.IO.LowResTimer+import Std.IO.Buffered+import Std.IO.StdStream++main = do+    -- read by '\n'+    b1 <- readLineStd+    -- read whatever user input in 3s, otherwise get Nothing+    b2 <- timeoutLowRes 30 $ readBuffered stdinBuf+    ...+    putStd "hello world!"++@++-}+module Std.IO.StdStream+  ( -- * Standard input & output streams+    StdStream+  , isStdStreamTTY+  , stdin, stdout, stderr+  , stdinBuf, stdoutBuf+    -- * utils+  , printStd+  , readLineStd+  , putStd+  , putLineStd+  ) where++import Std.Data.Builder as B+import Std.Data.Vector as V+import Std.IO.UV.FFI+import Std.IO.UV.Manager+import Control.Monad+import Control.Concurrent.STM.TVar+import Control.Concurrent.MVar+import Std.IO.Exception+import Std.IO.UV.Errno+import System.IO.Unsafe+import Std.IO.Resource+import Std.IO.Buffered+import Std.Data.Vector.Base (defaultChunkSize)+import Foreign.Ptr++-- | Standard input and output streams+--+-- We support both regular file and TTY based streams, when initialized+-- 'uv_guess_handle' is called to decide which type of devices are connected+-- to standard streams.+--+-- 'StdStream' is different from other 'UVStream' in that exception during reading & writing+-- won't close 'StdStream'.++data StdStream+    = StdTTY {-# UNPACK #-}!(Ptr UVHandle) {-# UNPACK #-}!UVSlot UVManager -- similar to UVStream+    | StdFile {-# UNPACK #-}!UVFD                                          -- similar to UVFile++isStdStreamTTY :: StdStream -> Bool+isStdStreamTTY (StdTTY _ _ _) = True+isStdStreamTTY _              = False++instance Input StdStream where+    {-# INLINE readInput #-}+    readInput uvs@(StdTTY handle slot uvm) buf len = mask_ $ do+        m <- getBlockMVar uvm slot+        withUVManager_ uvm $ do+            throwUVIfMinus_ (hs_uv_read_start handle)+            pokeBufferTable uvm slot buf len+            tryTakeMVar m+        r <- takeMVar m+        if  | r > 0  -> return r+            -- r == 0 should be impossible, since we guard this situation in c side+            | r == fromIntegral UV_EOF -> return 0+            | r < 0 ->  throwUVIfMinus (return r)+    readInput (StdFile fd) buf len =+        throwUVIfMinus $ hs_uv_fs_read fd buf len (-1)++instance Output StdStream where+    {-# INLINE writeOutput #-}+    writeOutput (StdTTY handle _ uvm) buf len = mask_ $ do+        (slot, m) <- withUVManager_ uvm $ do+            slot <- getUVSlot uvm (hs_uv_write handle buf len)+            m <- getBlockMVar uvm slot+            tryTakeMVar m+            return (slot, m)+        throwUVIfMinus_  (takeMVar m)+    writeOutput (StdFile fd) buf len = go buf len+      where+        go !buf !bufSiz = do+            written <- throwUVIfMinus+                (hs_uv_fs_write fd buf bufSiz (-1))+            when (written < bufSiz)+                (go (buf `plusPtr` written) (bufSiz-written))++stdin :: StdStream+{-# NOINLINE stdin #-}+stdin = unsafePerformIO (makeStdStream 0)++stdout :: StdStream+{-# NOINLINE stdout #-}+stdout = unsafePerformIO (makeStdStream 1)++stderr :: StdStream+{-# NOINLINE stderr #-}+stderr = unsafePerformIO (makeStdStream 2)++stdinBuf :: BufferedInput StdStream+{-# NOINLINE stdinBuf #-}+stdinBuf = unsafePerformIO (newBufferedInput stdin defaultChunkSize)++stdoutBuf :: BufferedOutput StdStream+{-# NOINLINE stdoutBuf #-}+stdoutBuf = unsafePerformIO (newBufferedOutput stdout defaultChunkSize)++makeStdStream :: UVFD -> IO StdStream+makeStdStream fd = do+    typ <- uv_guess_handle fd+    if typ == UV_TTY+    then do+        uvm <- getUVManager+        withUVManager uvm $ \ loop -> do+            handle <- hs_uv_handle_alloc loop+            slot <- getUVSlot uvm (peekUVHandleData handle)+            tryTakeMVar =<< getBlockMVar uvm slot   -- clear the parking spot+            throwUVIfMinus_ (uv_tty_init loop handle (fromIntegral fd))+                `onException` hs_uv_handle_free handle+            return (StdTTY handle slot uvm)+    else return (StdFile fd)++--------------------------------------------------------------------------------++-- | print a 'Show' to stdout+printStd :: Show a => a -> IO ()+printStd s = do+    writeBuffer stdoutBuf (B.buildBytes . B.stringUTF8 . show $ s)+    flushBuffer stdoutBuf++-- | print a 'Builder' and flush to stdout.+putStd :: Builder a -> IO ()+putStd b = do+    writeBuffer stdoutBuf (B.buildBytes b)+    flushBuffer stdoutBuf++-- | print a 'Builder' and flush to stdout stdout, with a linefeed.+putLineStd :: Builder a -> IO ()+putLineStd b = do+    writeBuffer stdoutBuf (B.buildBytes $ b >> B.char8 '\n')+    flushBuffer stdoutBuf++-- | read a line from stdin+readLineStd :: IO V.Bytes+readLineStd = readLine stdinBuf
+ Std/IO/TCP.hs view
@@ -0,0 +1,162 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ExistentialQuantification #-}++{-|+Module      : Std.IO.TCP+Description : TCP servers and clients+Copyright   : (c) Dong Han, 2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provides an API for creating TCP servers and clients.++-}++module Std.IO.TCP (+  -- * TCP Client+    ClientConfig(..)+  , defaultClientConfig+  , initClient+  -- * TCP Server+  , ServerConfig(..)+  , defaultServerConfig+  , startServer+  , module Std.IO.SockAddr+  ) where++import           Control.Concurrent+import           Control.Concurrent.MVar+import           Control.Monad+import           Control.Monad.IO.Class+import           Data.Int+import           Data.Primitive.PrimArray+import           Foreign.C.Types+import           Foreign.Ptr+import           GHC.Ptr+import           Std.Foreign.PrimArray+import           Std.Data.Array+import           Std.IO.Buffered+import           Std.IO.Exception+import           Std.IO.SockAddr+import           Std.IO.Resource+import           Std.IO.UV.FFI+import           Std.IO.UV.Manager+import           Std.Data.Vector++initTCPStream :: HasCallStack => UVManager -> Resource UVStream+initTCPStream = initUVStream (\ loop handle ->+    throwUVIfMinus_ (uv_tcp_init loop handle))++initTCPExStream :: HasCallStack => CUInt -> UVManager -> Resource UVStream+initTCPExStream family = initUVStream (\ loop handle ->+    throwUVIfMinus_ (uv_tcp_init_ex loop handle family))++--------------------------------------------------------------------------------++-- | A TCP client configuration+--+data ClientConfig = ClientConfig+    { clientLocalAddr :: Maybe SockAddr+    , clientTargetAddr :: SockAddr+    , clientNoDelay :: Bool+    }++defaultClientConfig :: ClientConfig+defaultClientConfig = ClientConfig Nothing (SockAddrInet 8888 inetLoopback) True++initClient :: HasCallStack => ClientConfig -> Resource UVStream+initClient ClientConfig{..} = do+    uvm <- liftIO getUVManager+    client <- initTCPStream uvm+    let handle = uvsHandle client+    liftIO . withSockAddr clientTargetAddr $ \ targetPtr -> do+        forM_ clientLocalAddr $ \ clientLocalAddr' ->+            withSockAddr clientLocalAddr' $ \ localPtr ->+                -- bind is safe without withUVManager+                throwUVIfMinus_ (uv_tcp_bind handle localPtr 0)+        -- nodelay is safe without withUVManager+        when clientNoDelay $ throwUVIfMinus_ (uv_tcp_nodelay handle 1)+        withUVRequest uvm $ \ _ -> hs_uv_tcp_connect handle targetPtr+    return client++--------------------------------------------------------------------------------++-- | A TCP server configuration+--+data ServerConfig = ServerConfig+    { serverAddr       :: SockAddr+    , serverBackLog    :: Int+    , serverWorker     :: UVStream -> IO ()+    , serverWorkerNoDelay :: Bool+    }++-- | A default hello world server on localhost:8888+--+-- Test it with @main = startServer defaultServerConfig@, now try @nc -v 127.0.0.1 8888@+--+defaultServerConfig :: ServerConfig+defaultServerConfig = ServerConfig+    (SockAddrInet 8888 inetAny)+    128+    (\ uvs -> writeOutput uvs (Ptr "hello world"#) 11)+    True++-- | Start a server+--+-- Fork new worker thread upon a new connection.+--+startServer :: ServerConfig -> IO ()+startServer ServerConfig{..} = do+    serverManager <- getUVManager+    withResource (initTCPStream serverManager) $ \ (UVStream serverHandle serverSlot _ _) ->+        bracket+            (throwOOMIfNull $ hs_uv_accept_check_alloc serverHandle)+            (hs_uv_accept_check_close) $ \ check -> do+                throwUVIfMinus_ $ hs_uv_accept_check_init check+                withSockAddr serverAddr $ \ addrPtr -> do+                    m <- getBlockMVar serverManager serverSlot+                    acceptBuf <- newPinnedPrimArray ACCEPT_BUFFER_SIZE+                    let acceptBufPtr = (coerce (mutablePrimArrayContents acceptBuf :: Ptr UVFD))++                    withUVManager_ serverManager $ do+                        pokeBufferTable serverManager serverSlot acceptBufPtr 0+                        throwUVIfMinus_ (uv_tcp_bind serverHandle addrPtr 0)+                        throwUVIfMinus_ (hs_uv_listen serverHandle (fromIntegral serverBackLog))++                    forever $ do+                        takeMVar m++                        -- we lock uv manager here in case of next uv_run overwrite current accept buffer+                        acceptBufCopy <- withUVManager_ serverManager $ do+                            tryTakeMVar m+                            accepted <- peekBufferTable serverManager serverSlot+                            acceptBuf' <- newPrimArray accepted+                            copyMutablePrimArray acceptBuf' 0 acceptBuf 0 accepted+                            pokeBufferTable serverManager serverSlot acceptBufPtr 0+                            unsafeFreezePrimArray acceptBuf'++                        let accepted = sizeofPrimArray acceptBufCopy++                        forM_ [0..accepted-1] $ \ i -> do+                            let fd = indexPrimArray acceptBufCopy i+                            if fd < 0+                            -- minus fd indicate a server error and we should close server+                            then throwUVIfMinus_ (return fd)+                            -- It's important to use the worker thread's mananger instead of server's one!+                            else void . forkBa $ do+                                uvm <- getUVManager+                                withResource (initUVStream (\ loop handle -> do+                                    throwUVIfMinus_ (uv_tcp_init loop handle)+                                    throwUVIfMinus_ (hs_uv_tcp_open handle fd)) uvm) $ \ client -> do+                                    when serverWorkerNoDelay . throwUVIfMinus_ $+                                        -- safe without withUVManager+                                        uv_tcp_nodelay (uvsHandle client) 1+                                    serverWorker client++                        when (accepted == ACCEPT_BUFFER_SIZE) $+                            withUVManager_ serverManager (hs_uv_listen_resume serverHandle)
+ Std/IO/UV/Errno.hsc view
@@ -0,0 +1,256 @@+{-# LANGUAGE PatternSynonyms #-}+{-|+Module      : Std.IO.UVErrno+Description : Errno provided by libuv+Copyright   : (c) Winterland, 2017-2018+License     : BSD+Maintainer  : drkoster@qq.com+Stability   : experimental+Portability : non-portable++INTERNAL MODULE, provides all libuv errno.++-}++module Std.IO.UV.Errno where++import Foreign.C.Types+import Foreign.C.String++#include "hs_uv.h"++uvStdError :: CInt -> IO String+uvStdError errno = peekCString =<< uv_strerror errno++foreign import ccall unsafe uv_strerror :: CInt -> IO CString++uvErrName :: CInt -> IO String+uvErrName errno = peekCString =<< uv_err_name errno++foreign import ccall unsafe uv_err_name :: CInt -> IO CString++-- | argument list too long+pattern UV_E2BIG           :: CInt+pattern UV_E2BIG           = #{const UV_E2BIG          }+-- | permission denied+pattern UV_EACCES          :: CInt+pattern UV_EACCES          = #{const UV_EACCES         }+-- | address already in use+pattern UV_EADDRINUSE      :: CInt+pattern UV_EADDRINUSE      = #{const UV_EADDRINUSE     }+-- | address not available+pattern UV_EADDRNOTAVAIL   :: CInt+pattern UV_EADDRNOTAVAIL   = #{const UV_EADDRNOTAVAIL  }+-- | address family not supported+pattern UV_EAFNOSUPPORT    :: CInt+pattern UV_EAFNOSUPPORT    = #{const UV_EAFNOSUPPORT   }+-- | resource temporarily unavailable+pattern UV_EAGAIN          :: CInt+pattern UV_EAGAIN          = #{const UV_EAGAIN         }+-- | address family not supported+pattern UV_EAI_ADDRFAMILY  :: CInt+pattern UV_EAI_ADDRFAMILY  = #{const UV_EAI_ADDRFAMILY }+-- | temporary failure+pattern UV_EAI_AGAIN       :: CInt+pattern UV_EAI_AGAIN       = #{const UV_EAI_AGAIN      }+-- | bad ai_flags value+pattern UV_EAI_BADFLAGS    :: CInt+pattern UV_EAI_BADFLAGS    = #{const UV_EAI_BADFLAGS   }+-- | invalid value for hints+pattern UV_EAI_BADHINTS    :: CInt+pattern UV_EAI_BADHINTS    = #{const UV_EAI_BADHINTS   }+-- | request canceled+pattern UV_EAI_CANCELED    :: CInt+pattern UV_EAI_CANCELED    = #{const UV_EAI_CANCELED   }+-- | permanent failure+pattern UV_EAI_FAIL        :: CInt+pattern UV_EAI_FAIL        = #{const UV_EAI_FAIL       }+-- | ai_family not supported+pattern UV_EAI_FAMILY      :: CInt+pattern UV_EAI_FAMILY      = #{const UV_EAI_FAMILY     }+-- | out of memory+pattern UV_EAI_MEMORY      :: CInt+pattern UV_EAI_MEMORY      = #{const UV_EAI_MEMORY     }+-- | no address+pattern UV_EAI_NODATA      :: CInt+pattern UV_EAI_NODATA      = #{const UV_EAI_NODATA     }+-- | unknown node or service+pattern UV_EAI_NONAME      :: CInt+pattern UV_EAI_NONAME      = #{const UV_EAI_NONAME     }+-- | argument buffer overflow+pattern UV_EAI_OVERFLOW    :: CInt+pattern UV_EAI_OVERFLOW    = #{const UV_EAI_OVERFLOW   }+-- | resolved protocol is unknown+pattern UV_EAI_PROTOCOL    :: CInt+pattern UV_EAI_PROTOCOL    = #{const UV_EAI_PROTOCOL   }+-- | service not available for socket type+pattern UV_EAI_SERVICE     :: CInt+pattern UV_EAI_SERVICE     = #{const UV_EAI_SERVICE    }+-- | socket type not supported+pattern UV_EAI_SOCKTYPE    :: CInt+pattern UV_EAI_SOCKTYPE    = #{const UV_EAI_SOCKTYPE   }+-- | connection already in progress+pattern UV_EALREADY        :: CInt+pattern UV_EALREADY        = #{const UV_EALREADY       }+-- | bad file descriptor+pattern UV_EBADF           :: CInt+pattern UV_EBADF           = #{const UV_EBADF          }+-- | resource busy or locked+pattern UV_EBUSY           :: CInt+pattern UV_EBUSY           = #{const UV_EBUSY          }+-- | operation canceled+pattern UV_ECANCELED       :: CInt+pattern UV_ECANCELED       = #{const UV_ECANCELED      }+-- | invalid Unicode character+pattern UV_ECHARSET        :: CInt+pattern UV_ECHARSET        = #{const UV_ECHARSET       }+-- | software caused connection abort+pattern UV_ECONNABORTED    :: CInt+pattern UV_ECONNABORTED    = #{const UV_ECONNABORTED   }+-- | connection refused+pattern UV_ECONNREFUSED    :: CInt+pattern UV_ECONNREFUSED    = #{const UV_ECONNREFUSED   }+-- | connection reset by peer+pattern UV_ECONNRESET      :: CInt+pattern UV_ECONNRESET      = #{const UV_ECONNRESET     }+-- | destination address required+pattern UV_EDESTADDRREQ    :: CInt+pattern UV_EDESTADDRREQ    = #{const UV_EDESTADDRREQ   }+-- | file already exists+pattern UV_EEXIST          :: CInt+pattern UV_EEXIST          = #{const UV_EEXIST         }+-- | bad address in system call argument+pattern UV_EFAULT          :: CInt+pattern UV_EFAULT          = #{const UV_EFAULT         }+-- | file too large+pattern UV_EFBIG           :: CInt+pattern UV_EFBIG           = #{const UV_EFBIG          }+-- | host is unreachable+pattern UV_EHOSTUNREACH    :: CInt+pattern UV_EHOSTUNREACH    = #{const UV_EHOSTUNREACH   }+-- | interrupted system call+pattern UV_EINTR           :: CInt+pattern UV_EINTR           = #{const UV_EINTR          }+-- | invalid argument+pattern UV_EINVAL          :: CInt+pattern UV_EINVAL          = #{const UV_EINVAL         }+-- | i/o error+pattern UV_EIO             :: CInt+pattern UV_EIO             = #{const UV_EIO            }+-- | socket is already connected+pattern UV_EISCONN         :: CInt+pattern UV_EISCONN         = #{const UV_EISCONN        }+-- | illegal operation on a directory+pattern UV_EISDIR          :: CInt+pattern UV_EISDIR          = #{const UV_EISDIR         }+-- | too many symbolic links encountered+pattern UV_ELOOP           :: CInt+pattern UV_ELOOP           = #{const UV_ELOOP          }+-- | too many open files+pattern UV_EMFILE          :: CInt+pattern UV_EMFILE          = #{const UV_EMFILE         }+-- | message too long+pattern UV_EMSGSIZE        :: CInt+pattern UV_EMSGSIZE        = #{const UV_EMSGSIZE       }+-- | name too long+pattern UV_ENAMETOOLONG    :: CInt+pattern UV_ENAMETOOLONG    = #{const UV_ENAMETOOLONG   }+-- | network is down+pattern UV_ENETDOWN        :: CInt+pattern UV_ENETDOWN        = #{const UV_ENETDOWN       }+-- | network is unreachable+pattern UV_ENETUNREACH     :: CInt+pattern UV_ENETUNREACH     = #{const UV_ENETUNREACH    }+-- | file table overflow+pattern UV_ENFILE          :: CInt+pattern UV_ENFILE          = #{const UV_ENFILE         }+-- | no buffer space available+pattern UV_ENOBUFS         :: CInt+pattern UV_ENOBUFS         = #{const UV_ENOBUFS        }+-- | no such device+pattern UV_ENODEV          :: CInt+pattern UV_ENODEV          = #{const UV_ENODEV         }+-- | no such file or directory+pattern UV_ENOENT          :: CInt+pattern UV_ENOENT          = #{const UV_ENOENT         }+-- | not enough memory+pattern UV_ENOMEM          :: CInt+pattern UV_ENOMEM          = #{const UV_ENOMEM         }+-- | machine is not on the network+pattern UV_ENONET          :: CInt+pattern UV_ENONET          = #{const UV_ENONET         }+-- | protocol not available+pattern UV_ENOPROTOOPT     :: CInt+pattern UV_ENOPROTOOPT     = #{const UV_ENOPROTOOPT    }+-- | no space left on device+pattern UV_ENOSPC          :: CInt+pattern UV_ENOSPC          = #{const UV_ENOSPC         }+-- | function not implemented+pattern UV_ENOSYS          :: CInt+pattern UV_ENOSYS          = #{const UV_ENOSYS         }+-- | socket is not connected+pattern UV_ENOTCONN        :: CInt+pattern UV_ENOTCONN        = #{const UV_ENOTCONN       }+-- | not a directory+pattern UV_ENOTDIR         :: CInt+pattern UV_ENOTDIR         = #{const UV_ENOTDIR        }+-- | directory not empty+pattern UV_ENOTEMPTY       :: CInt+pattern UV_ENOTEMPTY       = #{const UV_ENOTEMPTY      }+-- | socket operation on non-socket+pattern UV_ENOTSOCK        :: CInt+pattern UV_ENOTSOCK        = #{const UV_ENOTSOCK       }+-- | operation not supported on socket+pattern UV_ENOTSUP         :: CInt+pattern UV_ENOTSUP         = #{const UV_ENOTSUP        }+-- | operation not permitted+pattern UV_EPERM           :: CInt+pattern UV_EPERM           = #{const UV_EPERM          }+-- | broken pipe+pattern UV_EPIPE           :: CInt+pattern UV_EPIPE           = #{const UV_EPIPE          }+-- | protocol error+pattern UV_EPROTO          :: CInt+pattern UV_EPROTO          = #{const UV_EPROTO         }+-- | protocol not supported+pattern UV_EPROTONOSUPPORT :: CInt+pattern UV_EPROTONOSUPPORT = #{const UV_EPROTONOSUPPORT}+-- | protocol wrong type for socket+pattern UV_EPROTOTYPE      :: CInt+pattern UV_EPROTOTYPE      = #{const UV_EPROTOTYPE     }+-- | result too large+pattern UV_ERANGE          :: CInt+pattern UV_ERANGE          = #{const UV_ERANGE         }+-- | read-only file system+pattern UV_EROFS           :: CInt+pattern UV_EROFS           = #{const UV_EROFS          }+-- | cannot send after transport endpoint shutdown+pattern UV_ESHUTDOWN       :: CInt+pattern UV_ESHUTDOWN       = #{const UV_ESHUTDOWN      }+-- | invalid seek+pattern UV_ESPIPE          :: CInt+pattern UV_ESPIPE          = #{const UV_ESPIPE         }+-- | no such process+pattern UV_ESRCH           :: CInt+pattern UV_ESRCH           = #{const UV_ESRCH          }+-- | connection timed out+pattern UV_ETIMEDOUT       :: CInt+pattern UV_ETIMEDOUT       = #{const UV_ETIMEDOUT      }+-- | text file is busy+pattern UV_ETXTBSY         :: CInt+pattern UV_ETXTBSY         = #{const UV_ETXTBSY        }+-- | cross-device link not permitted+pattern UV_EXDEV           :: CInt+pattern UV_EXDEV           = #{const UV_EXDEV          }+-- | unknown error+pattern UV_UNKNOWN         :: CInt+pattern UV_UNKNOWN         = #{const UV_UNKNOWN        }+-- | end of file+pattern UV_EOF             :: CInt+pattern UV_EOF             = #{const UV_EOF            }+-- | no such device or address+pattern UV_ENXIO           :: CInt+pattern UV_ENXIO           = #{const UV_ENXIO          }+-- | too many links+pattern UV_EMLINK          :: CInt+pattern UV_EMLINK          = #{const UV_EMLINK         }
+ Std/IO/UV/FFI.hsc view
@@ -0,0 +1,650 @@+{-# LANGUAGE CPP                        #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MagicHash                  #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE PatternSynonyms            #-}+{-# LANGUAGE UnliftedFFITypes           #-}++{-|+Module      : Std.IO.UV+Description : libuv operations+Copyright   : (c) Winterland, 2017-2018+License     : BSD+Maintainer  : drkoster@qq.com+Stability   : experimental+Portability : non-portable++INTERNAL MODULE, provides all libuv side operations.++-}++module Std.IO.UV.FFI where++import           Data.Bits+import           Data.Int+import           Data.Word+import           Foreign.C.String+import           Foreign.C.Types+import           Foreign.Ptr+import           Foreign.Storable+import           GHC.Prim+import           Std.Foreign.PrimArray+import           Std.IO.Exception+import           Std.IO.SockAddr    (SockAddr, SocketFamily (..))+import           System.Posix.Types (CSsize (..))+import           GHC.Generics++#include "hs_uv.h"+#if HAVE_UNISTD_H+#include <unistd.h>+#endif++--------------------------------------------------------------------------------+-- libuv version+foreign import ccall unsafe uv_version :: IO CUInt+foreign import ccall unsafe uv_version_string :: IO CString++--------------------------------------------------------------------------------+-- Type alias+type UVSlot = Int+-- | UVSlotUnSafe wrap a slot which may not have a 'MVar' in blocking table, +--   i.e. the blocking table need to be resized.+newtype UVSlotUnSafe = UVSlotUnSafe { unsafeGetSlot :: UVSlot }+type UVFD = Int32++--------------------------------------------------------------------------------+-- CONSTANT++pattern ACCEPT_BUFFER_SIZE :: Int+pattern ACCEPT_BUFFER_SIZE = #const ACCEPT_BUFFER_SIZE+pattern SO_REUSEPORT_LOAD_BALANCE :: Int+pattern SO_REUSEPORT_LOAD_BALANCE = #const SO_REUSEPORT_LOAD_BALANCE+pattern INIT_LOOP_SIZE :: Int+pattern INIT_LOOP_SIZE = #const INIT_LOOP_SIZE++--------------------------------------------------------------------------------+-- loop+data UVLoop+data UVLoopData++peekUVEventQueue :: Ptr UVLoopData -> IO (Int, Ptr Int)+peekUVEventQueue p = (,)+    <$> (#{peek hs_loop_data, event_counter          } p)+    <*> (#{peek hs_loop_data, event_queue            } p)++clearUVEventCounter :: Ptr UVLoopData -> IO ()+clearUVEventCounter p = do+    #{poke hs_loop_data, event_counter          } p $ (0 :: Int)++peekUVBufferTable :: Ptr UVLoopData -> IO (Ptr (Ptr Word8), Ptr CSsize)+peekUVBufferTable p = (,)+    <$> (#{peek hs_loop_data, buffer_table          } p)+    <*> (#{peek hs_loop_data, buffer_size_table     } p)++newtype UVRunMode = UVRunMode CInt +    deriving (Eq, Ord, Read, Show, FiniteBits, Bits, Storable)++pattern UV_RUN_DEFAULT :: UVRunMode+pattern UV_RUN_DEFAULT = UVRunMode #{const UV_RUN_DEFAULT}+pattern UV_RUN_ONCE :: UVRunMode+pattern UV_RUN_ONCE    = UVRunMode #{const UV_RUN_ONCE}+pattern UV_RUN_NOWAIT :: UVRunMode+pattern UV_RUN_NOWAIT  = UVRunMode #{const UV_RUN_NOWAIT}++-- | Peek loop data pointer from uv loop  pointer.+peekUVLoopData :: Ptr UVLoop -> IO (Ptr UVLoopData)+peekUVLoopData p = #{peek uv_loop_t, data} p++foreign import ccall unsafe hs_uv_loop_init      :: Int -> IO (Ptr UVLoop)+foreign import ccall unsafe hs_uv_loop_close     :: Ptr UVLoop -> IO ()++-- | uv_run with usafe FFI.+foreign import ccall unsafe "hs_uv_run" uv_run    :: Ptr UVLoop -> UVRunMode -> IO CInt++-- | uv_run with safe FFI.+foreign import ccall safe "hs_uv_run" uv_run_safe :: Ptr UVLoop -> UVRunMode -> IO CInt++foreign import ccall unsafe uv_loop_alive :: Ptr UVLoop -> IO CInt++--------------------------------------------------------------------------------+-- thread safe wake up++foreign import ccall unsafe hs_uv_wake_up_timer :: Ptr UVLoopData -> IO CInt+foreign import ccall unsafe hs_uv_wake_up_async :: Ptr UVLoopData -> IO CInt++--------------------------------------------------------------------------------+-- handle+data UVHandle++peekUVHandleData :: Ptr UVHandle -> IO UVSlotUnSafe+peekUVHandleData p =  UVSlotUnSafe <$> (#{peek uv_handle_t, data} p :: IO Int)++foreign import ccall unsafe hs_uv_fileno :: Ptr UVHandle -> IO UVFD+foreign import ccall unsafe hs_uv_handle_alloc :: Ptr UVLoop -> IO (Ptr UVHandle)+foreign import ccall unsafe hs_uv_handle_free  :: Ptr UVHandle -> IO ()+foreign import ccall unsafe hs_uv_handle_close :: Ptr UVHandle -> IO ()++--------------------------------------------------------------------------------+-- request++foreign import ccall unsafe hs_uv_cancel :: Ptr UVLoop -> UVSlot -> IO ()++--------------------------------------------------------------------------------+-- stream++foreign import ccall unsafe hs_uv_listen  :: Ptr UVHandle -> CInt -> IO CInt+foreign import ccall unsafe hs_uv_listen_resume :: Ptr UVHandle -> IO ()++foreign import ccall unsafe hs_uv_read_start :: Ptr UVHandle -> IO CInt+foreign import ccall unsafe hs_uv_write :: Ptr UVHandle -> Ptr Word8 -> Int -> IO UVSlotUnSafe++foreign import ccall unsafe hs_uv_accept_check_alloc :: Ptr UVHandle -> IO (Ptr UVHandle)+foreign import ccall unsafe hs_uv_accept_check_init :: Ptr UVHandle -> IO CInt+foreign import ccall unsafe hs_uv_accept_check_close :: Ptr UVHandle -> IO ()++--------------------------------------------------------------------------------+-- tcp+foreign import ccall unsafe hs_uv_tcp_open :: Ptr UVHandle -> UVFD -> IO CInt+foreign import ccall unsafe uv_tcp_init :: Ptr UVLoop -> Ptr UVHandle -> IO CInt+foreign import ccall unsafe uv_tcp_init_ex :: Ptr UVLoop -> Ptr UVHandle -> CUInt -> IO CInt+foreign import ccall unsafe uv_tcp_nodelay :: Ptr UVHandle -> CInt -> IO CInt+foreign import ccall unsafe uv_tcp_keepalive :: Ptr UVHandle -> CInt -> CUInt -> IO CInt++uV_TCP_IPV6ONLY :: CUInt+uV_TCP_IPV6ONLY = #{const UV_TCP_IPV6ONLY}+foreign import ccall unsafe uv_tcp_bind :: Ptr UVHandle -> Ptr SockAddr -> CUInt -> IO CInt+foreign import ccall unsafe hs_uv_tcp_connect :: Ptr UVHandle -> Ptr SockAddr -> IO UVSlotUnSafe+foreign import ccall unsafe hs_set_socket_reuse :: Ptr UVHandle -> IO CInt++--------------------------------------------------------------------------------+-- pipe+foreign import ccall unsafe uv_pipe_init :: Ptr UVLoop -> Ptr UVHandle -> CInt -> IO CInt++--------------------------------------------------------------------------------+-- tty+newtype UVTTYMode = UVTTYMode CInt+    deriving (Eq, Ord, Read, Show, FiniteBits, Bits, Storable)++pattern UV_TTY_MODE_NORMAL :: UVTTYMode+pattern UV_TTY_MODE_NORMAL = UVTTYMode #{const UV_TTY_MODE_NORMAL}+pattern UV_TTY_MODE_RAW :: UVTTYMode+pattern UV_TTY_MODE_RAW = UVTTYMode #{const UV_TTY_MODE_RAW}+pattern UV_TTY_MODE_IO :: UVTTYMode+pattern UV_TTY_MODE_IO = UVTTYMode #{const UV_TTY_MODE_IO}++foreign import ccall unsafe uv_tty_init :: Ptr UVLoop -> Ptr UVHandle -> CInt -> IO CInt++--------------------------------------------------------------------------------+-- fs++newtype UVFileMode = UVFileMode CInt+    deriving (Eq, Ord, Read, Show, FiniteBits, Bits, Storable)++-- | 00700 user (file owner) has read, write and execute permission+pattern S_IRWXU :: UVFileMode+pattern S_IRWXU = UVFileMode #{const S_IRWXU}++-- | 00400 user has read permission+pattern S_IRUSR :: UVFileMode+pattern S_IRUSR = UVFileMode #{const S_IRUSR}++-- | 00200 user has write permission+pattern S_IWUSR :: UVFileMode+pattern S_IWUSR = UVFileMode #{const S_IWUSR}++-- | 00100 user has execute permission+pattern S_IXUSR :: UVFileMode+pattern S_IXUSR = UVFileMode #{const S_IXUSR}++-- | 00070 group has read, write and execute permission+pattern S_IRWXG :: UVFileMode+pattern S_IRWXG = UVFileMode #{const S_IRWXG}++-- | 00040 group has read permission+pattern S_IRGRP :: UVFileMode+pattern S_IRGRP = UVFileMode #{const S_IRGRP}++-- | 00020 group has write permission+pattern S_IWGRP :: UVFileMode+pattern S_IWGRP = UVFileMode #{const S_IWGRP}++-- | 00010 group has execute permission+pattern S_IXGRP :: UVFileMode+pattern S_IXGRP = UVFileMode #{const S_IXGRP}++-- | 00007 others have read, write and execute permission+pattern S_IRWXO :: UVFileMode+pattern S_IRWXO = UVFileMode #{const S_IRWXO}++-- | 00004 others have read permission+pattern S_IROTH :: UVFileMode+pattern S_IROTH = UVFileMode #{const S_IROTH}++-- | 00002 others have write permission+pattern S_IWOTH :: UVFileMode+pattern S_IWOTH = UVFileMode #{const S_IWOTH}++-- | 00001 others have execute permission+pattern S_IXOTH :: UVFileMode+pattern S_IXOTH = UVFileMode #{const S_IXOTH}++-- | Default mode for open, 0o666(readable and writable).+pattern DEFAULT_MODE :: UVFileMode+pattern DEFAULT_MODE = UVFileMode 0o666++-- non-threaded functions+foreign import ccall unsafe hs_uv_fs_open    :: CString -> UVFileFlag -> UVFileMode -> IO UVFD+foreign import ccall unsafe hs_uv_fs_close   :: UVFD -> IO Int+foreign import ccall unsafe hs_uv_fs_read    :: UVFD -> Ptr Word8 -> Int -> Int64 -> IO Int+foreign import ccall unsafe hs_uv_fs_write   :: UVFD -> Ptr Word8 -> Int -> Int64 -> IO Int+foreign import ccall unsafe hs_uv_fs_unlink  :: CString -> IO Int+foreign import ccall unsafe hs_uv_fs_mkdir   :: CString -> UVFileMode -> IO Int+foreign import ccall unsafe hs_uv_fs_rmdir   :: CString -> IO Int+foreign import ccall unsafe hs_uv_fs_mkdtemp :: CString -> Int -> CString -> IO Int++-- threaded functions+foreign import ccall unsafe hs_uv_fs_open_threaded +    :: CString -> UVFileFlag -> UVFileMode -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_close_threaded +    :: UVFD -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_read_threaded  +    :: UVFD -> Ptr Word8 -> Int -> Int64 -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_write_threaded +    :: UVFD -> Ptr Word8 -> Int -> Int64 -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_unlink_threaded+    :: CString -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_mkdir_threaded +    :: CString -> UVFileMode -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_rmdir_threaded +    :: CString -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_mkdtemp_threaded +    :: CString -> Int -> CString -> Ptr UVLoop -> IO UVSlotUnSafe++newtype UVFileFlag = UVFileFlag CInt+    deriving (Eq, Ord, Read, Show, FiniteBits, Bits, Storable)++-- | The file is opened in append mode. Before each write, the file offset is positioned at the end of the file.+pattern O_APPEND :: UVFileFlag+pattern O_APPEND = UVFileFlag #{const UV_FS_O_APPEND}++-- | The file is created if it does not already exist.+pattern O_CREAT :: UVFileFlag+pattern O_CREAT = UVFileFlag #{const UV_FS_O_CREAT}++-- | File IO is done directly to and from user-space buffers, which must be aligned. Buffer size and address should be a multiple of the physical sector size of the block device, (DO NOT USE WITH stdio's @BufferedIO@)+pattern O_DIRECT :: UVFileFlag+pattern O_DIRECT = UVFileFlag #{const UV_FS_O_DIRECT}++-- | If the path is not a directory, fail the open. (Not useful on regular file)+--+-- Note 'o_DIRECTORY' is not supported on Windows.+pattern O_DIRECTORY :: UVFileFlag+pattern O_DIRECTORY = UVFileFlag #{const UV_FS_O_DIRECTORY}++-- |The file is opened for synchronous IO. Write operations will complete once all data and a minimum of metadata are flushed to disk.+--+-- Note 'o_DSYNC' is supported on Windows via @FILE_FLAG_WRITE_THROUGH@.+pattern O_DSYNC :: UVFileFlag+pattern O_DSYNC = UVFileFlag #{const UV_FS_O_DSYNC}++-- | If the 'o_CREAT' flag is set and the file already exists, fail the open.+--+-- Note In general, the behavior of 'o_EXCL' is undefined if it is used without 'o_CREAT'. There is one exception: on +-- Linux 2.6 and later, 'o_EXCL' can be used without 'o_CREAT' if pathname refers to a block device. If the block +-- device is in use by the system (e.g., mounted), the open will fail with the error @EBUSY@.+pattern O_EXCL :: UVFileFlag+pattern O_EXCL = UVFileFlag #{const UV_FS_O_EXCL}++-- | Atomically obtain an exclusive lock.+--+-- Note UV_FS_O_EXLOCK is only supported on macOS and Windows.+-- (libuv: Changed in version 1.17.0: support is added for Windows.)+pattern O_EXLOCK :: UVFileFlag+pattern O_EXLOCK = UVFileFlag #{const UV_FS_O_EXLOCK}++-- | Do not update the file access time when the file is read.+-- +-- Note 'o_NOATIME' is not supported on Windows.+pattern O_NOATIME :: UVFileFlag+pattern O_NOATIME = UVFileFlag #{const UV_FS_O_NOATIME}++-- | If the path identifies a terminal device, opening the path will not cause that terminal to become the controlling terminal for the process (if the process does not already have one). (Not sure if this flag is useful)+--+-- Note 'o_NOCTTY' is not supported on Windows.+pattern O_NOCTTY :: UVFileFlag+pattern O_NOCTTY = UVFileFlag #{const UV_FS_O_NOCTTY}++-- | If the path is a symbolic link, fail the open.+--+-- Note 'o_NOFOLLOW' is not supported on Windows.+pattern O_NOFOLLOW :: UVFileFlag+pattern O_NOFOLLOW = UVFileFlag #{const UV_FS_O_NOFOLLOW}++-- | Open the file in nonblocking mode if possible. (Definitely not useful with stdio)+--+-- Note 'o_NONBLOCK' is not supported on Windows. (Not useful on regular file anyway)+pattern O_NONBLOCK :: UVFileFlag+pattern O_NONBLOCK = UVFileFlag #{const UV_FS_O_NONBLOCK}++-- | Access is intended to be random. The system can use this as a hint to optimize file caching.+-- +-- Note 'o_RANDOM' is only supported on Windows via @FILE_FLAG_RANDOM_ACCESS@.+pattern O_RANDOM :: UVFileFlag+pattern O_RANDOM = UVFileFlag #{const UV_FS_O_RANDOM}++-- | Open the file for read-only access.+pattern O_RDONLY :: UVFileFlag+pattern O_RDONLY = UVFileFlag #{const UV_FS_O_RDONLY}++-- | Open the file for read-write access.+pattern O_RDWR :: UVFileFlag+pattern O_RDWR = UVFileFlag #{const UV_FS_O_RDWR}+++-- | Access is intended to be sequential from beginning to end. The system can use this as a hint to optimize file caching.+-- +-- Note 'o_SEQUENTIAL' is only supported on Windows via @FILE_FLAG_SEQUENTIAL_SCAN@.+pattern O_SEQUENTIAL :: UVFileFlag+pattern O_SEQUENTIAL = UVFileFlag #{const UV_FS_O_SEQUENTIAL}++-- | The file is temporary and should not be flushed to disk if possible.+--+-- Note 'o_SHORT_LIVED' is only supported on Windows via @FILE_ATTRIBUTE_TEMPORARY@.+pattern O_SHORT_LIVED :: UVFileFlag+pattern O_SHORT_LIVED = UVFileFlag #{const UV_FS_O_SHORT_LIVED}++-- | Open the symbolic link itself rather than the resource it points to.+pattern O_SYMLINK :: UVFileFlag+pattern O_SYMLINK = UVFileFlag #{const UV_FS_O_SYMLINK}++-- | The file is opened for synchronous IO. Write operations will complete once all data and all metadata are flushed to disk.+--+-- Note 'o_SYNC' is supported on Windows via @FILE_FLAG_WRITE_THROUGH@.+pattern O_SYNC :: UVFileFlag+pattern O_SYNC = UVFileFlag #{const UV_FS_O_SYNC}++-- | The file is temporary and should not be flushed to disk if possible.+--+-- Note 'o_TEMPORARY' is only supported on Windows via @FILE_ATTRIBUTE_TEMPORARY@.+pattern O_TEMPORARY :: UVFileFlag+pattern O_TEMPORARY = UVFileFlag #{const UV_FS_O_TEMPORARY}++-- | If the file exists and is a regular file, and the file is opened successfully for write access, its length shall be truncated to zero.+pattern O_TRUNC :: UVFileFlag+pattern O_TRUNC = UVFileFlag #{const UV_FS_O_TRUNC}++-- | Open the file for write-only access.+pattern O_WRONLY :: UVFileFlag+pattern O_WRONLY = UVFileFlag #{const UV_FS_O_WRONLY}++#if defined(_WIN32)+newtype UVDirEntType = UVDirEntType CInt+#else+newtype UVDirEntType = UVDirEntType CChar+#endif+    deriving (Eq, Ord, Read, Show, FiniteBits, Bits, Storable)++data DirEntType+    = DirEntUnknown+    | DirEntFile+    | DirEntDir+    | DirEntLink+    | DirEntFIFO+    | DirEntSocket+    | DirEntChar+    | DirEntBlock+  deriving (Read, Show, Eq, Ord, Generic)++fromUVDirEntType :: UVDirEntType -> DirEntType+fromUVDirEntType t+    | t == uV__DT_FILE   = DirEntFile+    | t == uV__DT_DIR    = DirEntDir+    | t == uV__DT_LINK   = DirEntLink+    | t == uV__DT_FIFO   = DirEntFIFO+    | t == uV__DT_SOCKET = DirEntSocket+    | t == uV__DT_CHAR   = DirEntChar+    | t == uV__DT_BLOCK  = DirEntBlock+    | otherwise          = DirEntUnknown++#{enum UVDirEntType, UVDirEntType,+    uV__DT_FILE    = UV__DT_FILE,+    uV__DT_DIR     = UV__DT_DIR,+    uV__DT_LINK    = UV__DT_LINK,+    uV__DT_FIFO    = UV__DT_FIFO,+    uV__DT_SOCKET  = UV__DT_SOCKET,+    uV__DT_CHAR    = UV__DT_CHAR,+    uV__DT_BLOCK   = UV__DT_BLOCK}++data UVDirEnt++peekUVDirEnt :: Ptr UVDirEnt -> IO (CString, UVDirEntType)+#ifdef HAVE_DIRENT_TYPES+peekUVDirEnt p = (,) (#{ptr hs_uv__dirent_t, d_name } p) <$> (#{peek hs_uv__dirent_t, d_type } p)+#else+peekUVDirEnt p = return ((#{ptr hs_uv__dirent_t,  d_name } p), #{const DT_UNKNOWN})+#endif++foreign import ccall unsafe hs_uv_fs_scandir_cleanup+    :: Ptr (Ptr UVDirEnt) -> Int -> IO ()+foreign import ccall unsafe hs_uv_fs_scandir+    :: CString -> MBA## (Ptr UVDirEnt) -> IO Int+foreign import ccall unsafe hs_uv_fs_scandir_extra_cleanup +    :: Ptr (Ptr (Ptr UVDirEnt)) -> Int -> IO ()+foreign import ccall unsafe hs_uv_fs_scandir_threaded+    :: CString -> Ptr (Ptr (Ptr UVDirEnt)) -> Ptr UVLoop -> IO UVSlotUnSafe++data UVTimeSpec = UVTimeSpec +    { uvtSecond     :: {-# UNPACK #-} !CLong+    , uvtNanoSecond :: {-# UNPACK #-} !CLong+    } deriving (Show, Read, Eq, Ord, Generic)++instance Storable UVTimeSpec where+    sizeOf _  = #{size uv_timespec_t}+    alignment _ = #{alignment uv_timespec_t}+    peek p = UVTimeSpec <$> (#{peek uv_timespec_t, tv_sec } p)+                        <*> (#{peek uv_timespec_t, tv_nsec } p)+    poke p (UVTimeSpec sec nsec) = do+        (#{poke uv_timespec_t, tv_sec  } p sec)+        (#{poke uv_timespec_t, tv_nsec } p nsec)++data UVStat = UVStat+    { stDev      :: {-# UNPACK #-} !Word64+    , stMode     :: {-# UNPACK #-} !Word64+    , stNlink    :: {-# UNPACK #-} !Word64+    , stUid      :: {-# UNPACK #-} !Word64+    , stGid      :: {-# UNPACK #-} !Word64+    , stRdev     :: {-# UNPACK #-} !Word64+    , stIno      :: {-# UNPACK #-} !Word64+    , stSize     :: {-# UNPACK #-} !Word64+    , stBlksize  :: {-# UNPACK #-} !Word64+    , stBlocks   :: {-# UNPACK #-} !Word64+    , stFlags    :: {-# UNPACK #-} !Word64+    , stGen      :: {-# UNPACK #-} !Word64+    , stAtim     :: {-# UNPACK #-} !UVTimeSpec+    , stMtim     :: {-# UNPACK #-} !UVTimeSpec+    , stCtim     :: {-# UNPACK #-} !UVTimeSpec+    , stBirthtim :: {-# UNPACK #-} !UVTimeSpec+    } deriving (Show, Read, Eq, Ord, Generic)++uvStatSize :: Int+uvStatSize = #{size uv_stat_t}++peekUVStat :: Ptr UVStat -> IO UVStat+peekUVStat p = UVStat+    <$> (#{peek uv_stat_t, st_dev          } p)+    <*> (#{peek uv_stat_t, st_mode         } p)+    <*> (#{peek uv_stat_t, st_nlink        } p)+    <*> (#{peek uv_stat_t, st_uid          } p)+    <*> (#{peek uv_stat_t, st_gid          } p)+    <*> (#{peek uv_stat_t, st_rdev         } p)+    <*> (#{peek uv_stat_t, st_ino          } p)+    <*> (#{peek uv_stat_t, st_size         } p)+    <*> (#{peek uv_stat_t, st_blksize      } p)+    <*> (#{peek uv_stat_t, st_blocks       } p)+    <*> (#{peek uv_stat_t, st_flags        } p)+    <*> (#{peek uv_stat_t, st_gen          } p)+    <*> (#{peek uv_stat_t, st_atim         } p)+    <*> (#{peek uv_stat_t, st_mtim         } p)+    <*> (#{peek uv_stat_t, st_ctim         } p)+    <*> (#{peek uv_stat_t, st_birthtim     } p)++foreign import ccall unsafe hs_uv_fs_stat :: CString -> Ptr UVStat -> IO Int+foreign import ccall unsafe hs_uv_fs_fstat :: UVFD -> Ptr UVStat -> IO Int+foreign import ccall unsafe hs_uv_fs_lstat :: CString -> Ptr UVStat -> IO Int+foreign import ccall unsafe hs_uv_fs_rename :: CString -> CString -> IO Int+foreign import ccall unsafe hs_uv_fs_fsync :: UVFD -> IO Int+foreign import ccall unsafe hs_uv_fs_fdatasync :: UVFD -> IO Int+foreign import ccall unsafe hs_uv_fs_ftruncate :: UVFD -> Int64 -> IO Int++foreign import ccall unsafe hs_uv_fs_stat_threaded+    :: CString -> Ptr UVStat -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_fstat_threaded+    :: UVFD -> Ptr UVStat -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_lstat_threaded+    :: CString -> Ptr UVStat -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_rename_threaded+    :: CString -> CString -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_fsync_threaded+    :: UVFD -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_fdatasync_threaded+    :: UVFD -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_ftruncate_threaded +    :: UVFD -> Int64 -> Ptr UVLoop -> IO UVSlotUnSafe++-- | Flags control copying.+-- +--   * 'COPYFILE_EXCL': If present, uv_fs_copyfile() will fail with UV_EEXIST if the destination path already exists. The default behavior is to overwrite the destination if it exists.+--   * 'COPYFILE_FICLONE': If present, uv_fs_copyfile() will attempt to create a copy-on-write reflink. If the underlying platform does not support copy-on-write, then a fallback copy mechanism is used.+-- +newtype UVCopyFileFlag = UVCopyFileFlag CInt+    deriving (Eq, Ord, Read, Show, FiniteBits, Bits, Storable)++pattern COPYFILE_DEFAULT :: UVCopyFileFlag+pattern COPYFILE_DEFAULT = UVCopyFileFlag 0++pattern COPYFILE_EXCL :: UVCopyFileFlag+pattern COPYFILE_EXCL = UVCopyFileFlag #{const UV_FS_COPYFILE_EXCL}++pattern COPYFILE_FICLONE :: UVCopyFileFlag+#ifdef UV_FS_COPYFILE_FICLONE+pattern COPYFILE_FICLONE = UVCopyFileFlag #{const UV_FS_COPYFILE_FICLONE}+#else+pattern COPYFILE_FICLONE = UVCopyFileFlag 0   -- fallback to normal copy.+#endif++foreign import ccall unsafe hs_uv_fs_copyfile :: CString -> CString -> UVCopyFileFlag -> IO Int+foreign import ccall unsafe hs_uv_fs_copyfile_threaded+    :: CString -> CString -> UVCopyFileFlag -> Ptr UVLoop -> IO UVSlotUnSafe++newtype UVAccessMode = UVAccessMode CInt+    deriving (Eq, Ord, Read, Show, FiniteBits, Bits, Storable)++pattern F_OK :: UVAccessMode+pattern F_OK = UVAccessMode #{const F_OK}+pattern R_OK :: UVAccessMode+pattern R_OK = UVAccessMode #{const R_OK}+pattern W_OK :: UVAccessMode+pattern W_OK = UVAccessMode #{const W_OK}+pattern X_OK :: UVAccessMode+pattern X_OK = UVAccessMode #{const X_OK}++data AccessResult = NoExistence | NoPermission | AccessOK deriving (Show, Eq, Ord)++foreign import ccall unsafe hs_uv_fs_access :: CString -> UVAccessMode -> IO Int+foreign import ccall unsafe hs_uv_fs_access_threaded+    :: CString -> UVAccessMode -> Ptr UVLoop -> IO UVSlotUnSafe++foreign import ccall unsafe hs_uv_fs_chmod :: CString -> UVFileMode -> IO Int+foreign import ccall unsafe hs_uv_fs_chmod_threaded+    :: CString -> UVFileMode -> Ptr UVLoop -> IO UVSlotUnSafe++foreign import ccall unsafe hs_uv_fs_fchmod :: UVFD -> UVFileMode -> IO Int+foreign import ccall unsafe hs_uv_fs_fchmod_threaded+    :: UVFD -> UVFileMode -> Ptr UVLoop -> IO UVSlotUnSafe++foreign import ccall unsafe hs_uv_fs_utime :: CString -> Double -> Double -> IO Int+foreign import ccall unsafe hs_uv_fs_utime_threaded+    :: CString -> Double -> Double -> Ptr UVLoop -> IO UVSlotUnSafe++foreign import ccall unsafe hs_uv_fs_futime :: UVFD -> Double -> Double -> IO Int+foreign import ccall unsafe hs_uv_fs_futime_threaded+    :: UVFD -> Double -> Double -> Ptr UVLoop -> IO UVSlotUnSafe++newtype UVSymlinkFlag = UVSymlinkFlag CInt+    deriving (Eq, Ord, Read, Show, FiniteBits, Bits, Storable)++pattern SYMLINK_DEFAULT :: UVSymlinkFlag+pattern SYMLINK_DEFAULT = UVSymlinkFlag 0++pattern SYMLINK_DIR :: UVSymlinkFlag+pattern SYMLINK_DIR = UVSymlinkFlag #{const UV_FS_SYMLINK_DIR}++pattern SYMLINK_JUNCTION :: UVSymlinkFlag+pattern SYMLINK_JUNCTION = UVSymlinkFlag #{const UV_FS_SYMLINK_JUNCTION}++foreign import ccall unsafe hs_uv_fs_link :: CString -> CString -> IO Int+foreign import ccall unsafe hs_uv_fs_link_threaded+    :: CString -> CString -> Ptr UVLoop -> IO UVSlotUnSafe++foreign import ccall unsafe hs_uv_fs_symlink :: CString -> CString -> UVSymlinkFlag -> IO Int+foreign import ccall unsafe hs_uv_fs_symlink_threaded+    :: CString -> CString -> UVSymlinkFlag -> Ptr UVLoop -> IO UVSlotUnSafe++-- readlink and realpath share the same cleanup and callback+foreign import ccall unsafe hs_uv_fs_readlink_cleanup+    :: CString -> IO ()+foreign import ccall unsafe hs_uv_fs_readlink+    :: CString -> MBA## CString -> IO Int+foreign import ccall unsafe hs_uv_fs_realpath+    :: CString -> MBA## CString -> IO Int+foreign import ccall unsafe hs_uv_fs_readlink_extra_cleanup +    :: Ptr CString -> IO ()+foreign import ccall unsafe hs_uv_fs_readlink_threaded+    :: CString -> Ptr CString -> Ptr UVLoop -> IO UVSlotUnSafe+foreign import ccall unsafe hs_uv_fs_realpath_threaded+    :: CString -> Ptr CString -> Ptr UVLoop -> IO UVSlotUnSafe++--------------------------------------------------------------------------------+-- misc++newtype UVHandleType = UVHandleType CInt deriving (Eq, Ord, Read, Show, Storable)++pattern UV_UNKNOWN_HANDLE :: UVHandleType+pattern UV_UNKNOWN_HANDLE = UVHandleType #{const UV_UNKNOWN_HANDLE}+pattern UV_ASYNC :: UVHandleType+pattern UV_ASYNC = UVHandleType #{const UV_ASYNC}+pattern UV_CHECK :: UVHandleType+pattern UV_CHECK = UVHandleType #{const UV_CHECK}+pattern UV_FS_EVENT :: UVHandleType+pattern UV_FS_EVENT = UVHandleType #{const UV_FS_EVENT}+pattern UV_FS_POLL :: UVHandleType+pattern UV_FS_POLL = UVHandleType #{const UV_FS_POLL}+pattern UV_HANDLE :: UVHandleType+pattern UV_HANDLE = UVHandleType #{const UV_HANDLE}+pattern UV_IDLE :: UVHandleType+pattern UV_IDLE = UVHandleType #{const UV_IDLE}+pattern UV_NAMED_PIPE :: UVHandleType+pattern UV_NAMED_PIPE = UVHandleType #{const UV_NAMED_PIPE}+pattern UV_POLL :: UVHandleType+pattern UV_POLL = UVHandleType #{const UV_POLL}+pattern UV_PREPARE :: UVHandleType+pattern UV_PREPARE = UVHandleType #{const UV_PREPARE}+pattern UV_PROCESS :: UVHandleType+pattern UV_PROCESS = UVHandleType #{const UV_PROCESS}+pattern UV_STREAM :: UVHandleType+pattern UV_STREAM = UVHandleType #{const UV_STREAM}+pattern UV_TCP :: UVHandleType+pattern UV_TCP = UVHandleType #{const UV_TCP}+pattern UV_TIMER :: UVHandleType+pattern UV_TIMER = UVHandleType #{const UV_TIMER}+pattern UV_TTY :: UVHandleType+pattern UV_TTY = UVHandleType #{const UV_TTY}+pattern UV_UDP :: UVHandleType+pattern UV_UDP = UVHandleType #{const UV_UDP}+pattern UV_SIGNAL :: UVHandleType+pattern UV_SIGNAL = UVHandleType #{const UV_SIGNAL}+pattern UV_FILE :: UVHandleType+pattern UV_FILE = UVHandleType #{const UV_FILE}++foreign import ccall unsafe uv_guess_handle :: UVFD -> IO UVHandleType
+ Std/IO/UV/Manager.hs view
@@ -0,0 +1,454 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE MultiWayIf #-}++{-|+Module      : Std.IO.UV.Manager+Description : IO manager based on libuv+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provide IO manager which bridge libuv's async interface with ghc's light weight thread.++The main procedures for doing event IO is:++  * Allocate a slot number using 'allocSlot'.+  * Prepare you IO buffer and write them to uv loop with 'pokeBufferTable'(both read and write).+  * Block your thread with a 'MVar', using 'getBlockMVar' to get it.+  * Read the result with 'getResult', for read it's the read bytes number, for write it will be zero.+    Use 'E.throwIfError' to guard error situations.+  * Return the slot back uv manager with 'freeSlot'.++Usually slots are cache in the IO device so that you don't have to allocate new one before each IO operation.+Check "System.IO.Socket.TCP" as an example.++-}++module Std.IO.UV.Manager+  ( UVManager+  , getUVManager+  , getBlockMVar+  , peekBufferTable+  , pokeBufferTable+  , withUVManager+  , withUVManager_+  , getUVSlot+  -- * request based async function helper+  , withUVRequest+  , withUVRequest_+  , withUVRequest'+  , withUVRequestEx+  -- * uv_stream abstraction+  , initUVStream+  , UVStream(..)+  -- * concurrent helpers+  , forkBa+  ) where++import           Control.Concurrent+import           Control.Concurrent.MVar+import           Control.Monad+import           Control.Monad.IO.Class+import           Data.IORef+import           Data.Bits (shiftL)+import           Data.Primitive.PrimArray+import           Data.Word+import           Foreign.C+import           Foreign.Ptr+import           Foreign.Storable+import           GHC.Conc.Sync            (labelThread)+import           Std.Data.Array+import           Std.Data.PrimIORef+import           Std.IO.Buffered+import           Std.IO.Exception+import           Std.IO.UV.Errno+import           Std.IO.Resource+import           Std.IO.UV.FFI+import           System.IO.Unsafe++#define IDLE_LIMIT 20++--------------------------------------------------------------------------------++data UVManager = UVManager+    { uvmBlockTable :: {-# UNPACK #-} !(IORef (UnliftedArray (MVar Int))) -- a array to store threads blocked on async IO.++    , uvmLoop       :: {-# UNPACK #-} !(Ptr UVLoop)        -- the uv loop refrerence++    , uvmLoopData   :: {-# UNPACK #-} !(Ptr UVLoopData)    -- cached pointer to uv_loop_t's data field++    , uvmRunning    :: {-# UNPACK #-} !(MVar Bool)     -- only uv manager thread will modify this value.+                                                        -- 'True' druing uv_run and 'False' otherwise.+                                                        --+                                                        -- unlike epoll/ONESHOT, uv loop are NOT thread safe,+                                                        -- we have to wake up the loop before mutating uv_loop's+                                                        -- state.+    , uvmCap        ::  {-# UNPACK #-} !Int                -- the capability uv manager run on.+    }++instance Show UVManager where+    show uvm = "UVManager on capability " ++ show (uvmCap uvm)++instance Eq UVManager where+    uvm == uvm' =+        uvmCap uvm == uvmCap uvm'++uvManagerArray :: IORef (Array UVManager)+{-# NOINLINE uvManagerArray #-}+uvManagerArray = unsafePerformIO $ do+    numCaps <- getNumCapabilities+    uvmArray <- newArr numCaps+    s <- newQSemN 0+    forM_ [0..numCaps-1] $ \ i -> do+        -- fork uv manager thread+        forkOn i . withResource (initUVManager INIT_LOOP_SIZE i) $ \ m -> do+            myThreadId >>= (`labelThread` ("uv manager on " ++ show i))+            writeArr uvmArray i m+            signalQSemN s 1+            startUVManager m+    waitQSemN s numCaps+    iuvmArray <- unsafeFreezeArr uvmArray+    newIORef iuvmArray++-- | Get 'UVManager' runing on the same capability.+--+getUVManager :: IO UVManager+{-# INLINABLE getUVManager #-}+getUVManager = do+    (cap, _) <- threadCapability =<< myThreadId+    uvmArray <- readIORef uvManagerArray+    indexArrM uvmArray (cap `rem` sizeofArr uvmArray)++-- | Get 'MVar' from blocking table with given slot.+--+getBlockMVar :: UVManager -> UVSlot -> IO (MVar Int)+{-# INLINABLE getBlockMVar #-}+getBlockMVar uvm slot = do+    blockTable <- readIORef (uvmBlockTable uvm)+    indexArrM blockTable slot++-- | Poke a prepared buffer and size into loop data under given slot.+--+-- NOTE, this action is not protected with 'withUVManager_ for effcient reason, you should merge this action+-- with other uv action and put them together inside a 'withUVManager_ or 'withUVManager\''. for example:+--+-- @+--    ...+--    withUVManager_ uvm $ do+--        pokeBufferTable uvm slot buf len+--        uvReadStart handle+--    ...+-- @+--+pokeBufferTable :: UVManager -> UVSlot -> Ptr Word8 -> Int -> IO ()+{-# INLINABLE pokeBufferTable #-}+pokeBufferTable uvm slot buf bufSiz = do+    (bufTable, bufSizTable) <- peekUVBufferTable (uvmLoopData uvm)+    pokeElemOff bufTable slot buf+    pokeElemOff bufSizTable slot (fromIntegral bufSiz)++peekBufferTable :: UVManager -> UVSlot -> IO Int+{-# INLINABLE peekBufferTable #-}+peekBufferTable uvm slot = do+    (bufTable, bufSizTable) <- peekUVBufferTable (uvmLoopData uvm)+    fromIntegral <$> peekElemOff bufSizTable slot++initUVManager :: HasCallStack => Int -> Int -> Resource UVManager+initUVManager siz cap = do+    loop  <- initUVLoop (fromIntegral siz)+    liftIO $ do+        mblockTable <- newArr siz+        forM_ [0..siz-1] $ \ i -> writeArr mblockTable i =<< newEmptyMVar+        blockTable <- unsafeFreezeArr mblockTable+        blockTableRef <- newIORef blockTable+        loopData <- peekUVLoopData loop+        running <- newMVar False+        return (UVManager blockTableRef loop loopData running cap)+  where+    initUVLoop :: HasCallStack => Int -> Resource (Ptr UVLoop)+    initUVLoop siz = initResource+        (throwOOMIfNull $ hs_uv_loop_init siz+        ) hs_uv_loop_close++-- | Lock an uv mananger, so that we can safely mutate its uv_loop's state.+--+-- libuv is not thread safe, use this function to perform any action which will mutate uv_loop's state.+--+withUVManager :: HasCallStack => UVManager -> (Ptr UVLoop -> IO a) -> IO a+withUVManager (UVManager _ loop loopData running _) f = go+  where+    go = do+        r <- withMVar running $ \ running ->+            if running+            then do+                -- if uv_run is running, it will stop+                -- if uv_run is not running, next running won't block+                throwUVIfMinus_ (hs_uv_wake_up_async loopData)+                return Nothing+            else do+                r <- f loop+                return (Just r)+        case r of+            Just r' -> return r'+            _       -> yield >> go -- we yield here, because uv_run is probably not finished yet++-- | Lock an uv mananger, so that we can safely mutate its uv_loop's state.+--+-- Some action did not request uv_loop pointer explicitly, but will mutate uv_loop underhood, for example:+-- @uv_read_start@. These actions have to be protected by locking the uv_loop.+--+-- In fact most of the libuv's functions are not thread safe, so watch out!+--+withUVManager_ :: HasCallStack => UVManager -> IO a -> IO a+withUVManager_ uvm f = withUVManager uvm (\ _ -> f)++-- | Start the uv loop+--+startUVManager :: HasCallStack => UVManager -> IO ()+startUVManager uvm@(UVManager _ _ _ running _) = loop -- use a closure capture uvm in case of stack memory leaking+  where+    loop = do+        e <- withMVar running $ \ _ -> step uvm False   -- we borrow mio's non-blocking/blocking poll strategy here+        if e > 0                                        -- first we do a non-blocking poll, if we got events+        then yield >> loop                              -- we yield here, to let other threads do actual work+        else do                                         -- otherwise we still yield once+            yield                                       -- in case other threads can still progress+            e <- withMVar running $ \ _ -> step uvm False   -- now we do another non-blocking poll to make sure+            if e > 0 then yield >> loop             -- if we got events somehow, we yield and go back+            else do                                 -- if there's still no events, we directly jump to safe blocking poll+                _ <- swapMVar running True          -- after swap this lock, other thread can wake up us+                e <- step uvm True                  -- by send async handler, and it's thread safe+                _ <- swapMVar running False++                yield                               -- we yield here, to let other threads do actual work+                loop++    -- call uv_run, return the event number+    step :: UVManager -> Bool -> IO Int+    step (UVManager blockTableRef loop loopData _ _) block = do+            blockTable <- readIORef blockTableRef+            clearUVEventCounter loopData        -- clean event counter++            if block+            then if rtsSupportsBoundThreads+                then throwUVIfMinus_ $ uv_run_safe loop UV_RUN_ONCE+                else do+                    -- use a 1ms timeout blocking poll on non-threaded rts+                    throwUVIfMinus_ (hs_uv_wake_up_timer loopData)+                    throwUVIfMinus_ (uv_run loop UV_RUN_ONCE)+            else throwUVIfMinus_ (uv_run loop UV_RUN_NOWAIT)++            (c, q) <- peekUVEventQueue loopData+            forM_ [0..c-1] $ \ i -> do+                slot <- peekElemOff q i+                lock <- indexArrM blockTable slot+                -- It's important to read the buffer size table inside running lock and+                -- unlock ghc thread with the result, where 'tryPutMVar' will mutate waiting+                -- thread's stack to ensure it will receive the result after get resumed.+                --+                -- After step finished, other threads are free to take the same slot,+                -- thus can overwrite the buffer size table, i.e. the previous result.+                --+                r <- peekBufferTable uvm slot+                tryPutMVar lock r+            return c++-- | Run a libuv FFI to get a 'UVSlotUnSafe' (which may exceed block table size),+-- resize the block table in that case, so that the returned slot always has an+-- accompanying 'MVar' in block table.+--+-- Always use this function to turn an 'UVSlotUnsafe' into 'UVSlot', so that the block+-- table size synchronize with libuv side's slot table.+getUVSlot :: HasCallStack => UVManager -> IO UVSlotUnSafe -> IO UVSlot+{-# INLINE getUVSlot #-}+getUVSlot (UVManager blockTableRef _ _ _ _) f = do+    slot <- throwUVIfMinus (unsafeGetSlot <$> f)+    blockTable <- readIORef blockTableRef+    let oldSiz = sizeofArr blockTable+    when (slot == oldSiz) $ do+        let newSiz = oldSiz `shiftL` 2+        blockTable' <- newArr newSiz+        copyArr blockTable' 0 blockTable 0 oldSiz+        forM_ [oldSiz..newSiz-1] $ \ i ->+            writeArr blockTable' i =<< newEmptyMVar+        !iBlockTable' <- unsafeFreezeArr blockTable'+        writeIORef blockTableRef iBlockTable'+    return slot++--------------------------------------------------------------------------------++-- | Cancel uv async function (actions which can be cancelled with 'uv_cancel') with+-- best effort, if the action is already performed, run an extra clean up action.+cancelUVReq :: UVManager -> UVSlot -> (Int -> IO ()) -> IO ()+cancelUVReq uvm slot extra_cleanup = withUVManager uvm $ \ loop -> do+    m <- getBlockMVar uvm slot+    r <- tryTakeMVar m+    case r of+        Just r' -> extra_cleanup r'             -- It's too late+        _ -> do+            pokeBufferTable uvm slot nullPtr 0  -- doing this let libuv side knows that+                                                -- we won't keep buffer alive in callbacks+            hs_uv_cancel loop slot              -- then we cancel the io with best efforts++-- | Exception safe uv request helper+--+-- This helper will run a libuv's async function, which will return a+-- libuv side's slot, then we will accommodate a 'MVar' in block table and+-- wait on that 'MVar', until the async function finished or an exception+-- is received, in later case we will call 'cancelUVReq' to cancel the on-going+-- async function with best efforts,+withUVRequest :: HasCallStack+              => UVManager -> (Ptr UVLoop -> IO UVSlotUnSafe) -> IO Int+withUVRequest uvm f = do+    (slot, m) <- withUVManager uvm $ \ loop -> mask_ $ do+        slot <- getUVSlot uvm (f loop)+        m <- getBlockMVar uvm slot+        tryTakeMVar m+        return (slot, m)+    throwUVIfMinus $+        takeMVar m `onException` cancelUVReq uvm slot no_extra_cleanup+  where no_extra_cleanup = const $ return ()++-- | Same with 'withUVRequest' but disgard the result.+withUVRequest_ :: HasCallStack+               => UVManager -> (Ptr UVLoop -> IO UVSlotUnSafe) -> IO ()+withUVRequest_ uvm f = void (withUVRequest uvm f)++-- | Same with 'withUVRequest' but apply an convert function to result.+--+-- The convert function have all access to the returned value including+-- negative ones, it's convert funtions's responsiblity to throw an exception+-- if appropriate.+withUVRequest' :: HasCallStack+               => UVManager+               -> (Ptr UVLoop -> IO UVSlotUnSafe)+               -> (Int -> IO b)     -- ^ convert function+               -> IO b+withUVRequest' uvm f g = do+    (slot, m) <- withUVManager uvm $ \ loop -> mask_ $ do+        slot <- getUVSlot uvm (f loop)+        m <- getBlockMVar uvm slot+        tryTakeMVar m+        return (slot, m)+    (g =<< takeMVar m) `onException` cancelUVReq uvm slot no_extra_cleanup+  where no_extra_cleanup = const $ return ()++-- | Same with 'withUVRequest', but will also run an extra cleanup function+-- if async exception hit this thread but the async action is already successfully performed,+-- e.g. release result memory.+withUVRequestEx :: HasCallStack+                => UVManager -> (Ptr UVLoop -> IO UVSlotUnSafe) -> (Int -> IO ()) -> IO Int+withUVRequestEx uvm f extra_cleanup = do+    (slot, m) <- withUVManager uvm $ \ loop -> mask_ $ do+        slot <- getUVSlot uvm (f loop)+        m <- getBlockMVar uvm slot+        tryTakeMVar m+        return (slot, m)+    throwUVIfMinus $+        takeMVar m `onException` cancelUVReq uvm slot extra_cleanup++--------------------------------------------------------------------------------++-- | Fork a new GHC thread with active load-balancing.+--+-- Using libuv based IO solution has a disadvantage that file handlers are bound to certain+-- uv_loop, thus certain uv mananger/capability. Worker threads that migrate to other capability+-- will lead contention since various APIs here is protected by manager's lock, this makes GHC's+-- work-stealing strategy unsuitable for certain workload, such as a webserver.+-- we solve this problem with simple round-robin load-balancing: forkBa will automatically+-- distribute new threads to all capabilities in round-robin manner. Thus its name forkBa(lance).+forkBa :: IO () -> IO ThreadId+forkBa io = do+    i <- atomicAddCounter counter 1+    forkOn i io+  where+    counter :: Counter+    {-# NOINLINE counter #-}+    counter = unsafePerformIO $ newCounter 0++--------------------------------------------------------------------------------+-- UVStream++-- | A haskell data type wrap an @uv_stream_t@ inside+--+-- 'UVStream' DO NOT provide thread safety! Use 'UVStream' concurrently in multiple+-- threads will lead to undefined behavior.+data UVStream = UVStream+    { uvsHandle :: {-# UNPACK #-} !(Ptr UVHandle)+    , uvsSlot    :: {-# UNPACK #-} !UVSlot+    , uvsManager :: UVManager+    , uvsClosed  :: {-# UNPACK #-} !(IORef Bool)+    }++instance Show UVStream where+    show (UVStream handle slot uvm _) =+        "UVStream{uvsHandle = " ++ show handle +++                ",uvsSlot = " ++ show slot +++                ",uvsManager =" ++ show uvm ++ "}"++-- | Safely lock an uv manager and perform uv_handle initialization.+--+-- Initialization an UV stream usually take two step:+--+--   * allocate an uv_stream struct with proper size+--   * lock a particular uv_loop from a uv manager, and perform custom initialization, such as @uv_tcp_init@.+--+-- And this is what 'initUVStream' do, all you need to do is to provide the manager you want to hook the handle+-- onto(usually the one on the same capability, i.e. the one obtained by 'getUVManager'),+-- and provide a custom initialization function.+--+initUVStream :: HasCallStack+             => (Ptr UVLoop -> Ptr UVHandle -> IO ())+             -> UVManager+             -> Resource UVStream+initUVStream init uvm = initResource+    (withUVManager uvm $ \ loop -> do+        handle <- hs_uv_handle_alloc loop+        slot <- getUVSlot uvm (peekUVHandleData handle)+        tryTakeMVar =<< getBlockMVar uvm slot   -- clear the parking spot+        init loop handle `onException` hs_uv_handle_free handle+        closed <- newIORef False+        return (UVStream handle slot uvm closed))+    closeUVStream++closeUVStream :: UVStream -> IO ()+closeUVStream (UVStream handle _ uvm closed) = withUVManager_ uvm $ do+    c <- readIORef closed+    unless c $ writeIORef closed True >> hs_uv_handle_close handle++instance Input UVStream where+    -- readInput :: HasCallStack => UVStream -> Ptr Word8 ->  Int -> IO Int+    readInput uvs@(UVStream handle slot uvm closed) buf len = mask_ $ do+        c <- readIORef closed+        when c throwECLOSED+        m <- getBlockMVar uvm slot+        withUVManager_ uvm $ do+            throwUVIfMinus_ (hs_uv_read_start handle)+            pokeBufferTable uvm slot buf len+            tryTakeMVar m+        -- We really can't do much when async exception hit a stream IO+        -- There's no way to cancel, all we can do is to close the stream+        r <- takeMVar m `onException` closeUVStream uvs+        if  | r > 0  -> return r+            -- r == 0 should be impossible, since we guard this situation in c side+            | r == fromIntegral UV_EOF -> return 0+            | r < 0 ->  throwUVIfMinus (return r)+++instance Output UVStream where+    -- writeOutput :: HasCallStack => UVStream -> Ptr Word8 -> Int -> IO ()+    writeOutput uvs@(UVStream handle _ uvm closed) buf len = mask_ $ do+        c <- readIORef closed+        when c throwECLOSED+        (slot, m) <- withUVManager_ uvm $ do+            slot <- getUVSlot uvm (hs_uv_write handle buf len)+            m <- getBlockMVar uvm slot+            tryTakeMVar m+            return (slot, m)+        -- cancel uv_write_t will also close the stream+        throwUVIfMinus_  (takeMVar m `onException` closeUVStream uvs)++--------------------------------------------------------------------------------
+ cbits/bytes.c view
@@ -0,0 +1,58 @@+/*+Copyright Johan Tibell 2011, Dong Han 2019+All rights reserved.+Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:+    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.+    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.+    * Neither the name of Johan Tibell nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+*/++#include <bytes.h>++HsInt hs_memchr(uint8_t *a, HsInt aoff, uint8_t b, HsInt n) {+    a += aoff;+    uint8_t *p = memchr(a, b, (size_t)n);+    if (p == NULL) return -1;+    else return (p - a);+}+++/* FNV-1 hash+ *+ * The FNV-1 hash description: http://isthe.com/chongo/tech/comp/fnv/+ * The FNV-1 hash is public domain: http://isthe.com/chongo/tech/comp/fnv/#public_domain+ *+ * The original version from hashable use long type which doesn't match 'Int' in haskell and+ * cause problems on window, here we use HsInt.+ */+HsInt hs_fnv_hash_addr(const unsigned char* str, HsInt len, HsInt salt) {++    HsWord hash = salt;+    while (len--) {+      hash = (hash * 16777619) ^ *str++;+    }++    return hash;+}++HsInt hs_fnv_hash(const unsigned char* str, HsInt offset, HsInt len, HsInt salt) {+    return hs_fnv_hash_addr(str + offset, len, salt);+}
+ cbits/dtoa.c view
@@ -0,0 +1,367 @@+/*+ * Copyright Winterland1989+ * Copyright author of MathGeoLib (https://github.com/juj)+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     http://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License. http://www.apache.org/licenses/LICENSE-2.0+ */++/*+ * Extracted from MathGeoLib, modified by Winterland1989.+ *+ * MatGeoLib grisu3.c comment:+ *+ *     This file is part of an implementation of the "grisu3" double to string+ *     conversion algorithm described in the research paper+ *+ *     "Printing Floating-Point Numbers Quickly And Accurately with Integers"+ *     by Florian Loitsch, available at+ *     http://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf+ */++#include <dtoa.h>+#include <stdint.h> // uint64_t etc.+#include <assert.h> // assert+#include <math.h> // ceil++#ifdef _MSC_VER+#pragma warning(disable : 4204) // nonstandard extension used : non-constant aggregate initializer+#endif++#define D64_SIGN         0x8000000000000000ULL+#define D64_EXP_MASK     0x7FF0000000000000ULL+#define D64_FRACT_MASK   0x000FFFFFFFFFFFFFULL+#define D64_IMPLICIT_ONE 0x0010000000000000ULL+#define D64_EXP_POS      52+#define D64_EXP_BIAS     1075+#define D32_SIGN         0x80000000U+#define D32_EXP_MASK     0x7F800000U+#define D32_FRACT_MASK   0x007FFFFFU+#define D32_IMPLICIT_ONE 0x00800000U+#define D32_EXP_POS      23+#define D32_EXP_BIAS     150+#define DIYFP_FRACT_SIZE 64+#define D_1_LOG2_10      0.30102999566398114 // 1 / lg(10)+#define MIN_TARGET_EXP   -60+#define MASK32           0xFFFFFFFFULL++#define CAST_U64(d) (*(uint64_t*)&d)+#define CAST_U32(d) (*(uint32_t*)&d)+#define MIN(x,y) ((x) <= (y) ? (x) : (y))+#define MAX(x,y) ((x) >= (y) ? (x) : (y))++#define MIN_CACHED_EXP -348+#define CACHED_EXP_STEP 8++typedef struct diy_fp+{+    uint64_t f;+    int e;+} diy_fp;++typedef struct power+{+    uint64_t fract;+    int16_t b_exp, d_exp;+} power;++static const power pow_cache[] =+{+    { 0xfa8fd5a0081c0288ULL, -1220, -348 },+    { 0xbaaee17fa23ebf76ULL, -1193, -340 },+    { 0x8b16fb203055ac76ULL, -1166, -332 },+    { 0xcf42894a5dce35eaULL, -1140, -324 },+    { 0x9a6bb0aa55653b2dULL, -1113, -316 },+    { 0xe61acf033d1a45dfULL, -1087, -308 },+    { 0xab70fe17c79ac6caULL, -1060, -300 },+    { 0xff77b1fcbebcdc4fULL, -1034, -292 },+    { 0xbe5691ef416bd60cULL, -1007, -284 },+    { 0x8dd01fad907ffc3cULL,  -980, -276 },+    { 0xd3515c2831559a83ULL,  -954, -268 },+    { 0x9d71ac8fada6c9b5ULL,  -927, -260 },+    { 0xea9c227723ee8bcbULL,  -901, -252 },+    { 0xaecc49914078536dULL,  -874, -244 },+    { 0x823c12795db6ce57ULL,  -847, -236 },+    { 0xc21094364dfb5637ULL,  -821, -228 },+    { 0x9096ea6f3848984fULL,  -794, -220 },+    { 0xd77485cb25823ac7ULL,  -768, -212 },+    { 0xa086cfcd97bf97f4ULL,  -741, -204 },+    { 0xef340a98172aace5ULL,  -715, -196 },+    { 0xb23867fb2a35b28eULL,  -688, -188 },+    { 0x84c8d4dfd2c63f3bULL,  -661, -180 },+    { 0xc5dd44271ad3cdbaULL,  -635, -172 },+    { 0x936b9fcebb25c996ULL,  -608, -164 },+    { 0xdbac6c247d62a584ULL,  -582, -156 },+    { 0xa3ab66580d5fdaf6ULL,  -555, -148 },+    { 0xf3e2f893dec3f126ULL,  -529, -140 },+    { 0xb5b5ada8aaff80b8ULL,  -502, -132 },+    { 0x87625f056c7c4a8bULL,  -475, -124 },+    { 0xc9bcff6034c13053ULL,  -449, -116 },+    { 0x964e858c91ba2655ULL,  -422, -108 },+    { 0xdff9772470297ebdULL,  -396, -100 },+    { 0xa6dfbd9fb8e5b88fULL,  -369,  -92 },+    { 0xf8a95fcf88747d94ULL,  -343,  -84 },+    { 0xb94470938fa89bcfULL,  -316,  -76 },+    { 0x8a08f0f8bf0f156bULL,  -289,  -68 },+    { 0xcdb02555653131b6ULL,  -263,  -60 },+    { 0x993fe2c6d07b7facULL,  -236,  -52 },+    { 0xe45c10c42a2b3b06ULL,  -210,  -44 },+    { 0xaa242499697392d3ULL,  -183,  -36 },+    { 0xfd87b5f28300ca0eULL,  -157,  -28 },+    { 0xbce5086492111aebULL,  -130,  -20 },+    { 0x8cbccc096f5088ccULL,  -103,  -12 },+    { 0xd1b71758e219652cULL,   -77,   -4 },+    { 0x9c40000000000000ULL,   -50,    4 },+    { 0xe8d4a51000000000ULL,   -24,   12 },+    { 0xad78ebc5ac620000ULL,     3,   20 },+    { 0x813f3978f8940984ULL,    30,   28 },+    { 0xc097ce7bc90715b3ULL,    56,   36 },+    { 0x8f7e32ce7bea5c70ULL,    83,   44 },+    { 0xd5d238a4abe98068ULL,   109,   52 },+    { 0x9f4f2726179a2245ULL,   136,   60 },+    { 0xed63a231d4c4fb27ULL,   162,   68 },+    { 0xb0de65388cc8ada8ULL,   189,   76 },+    { 0x83c7088e1aab65dbULL,   216,   84 },+    { 0xc45d1df942711d9aULL,   242,   92 },+    { 0x924d692ca61be758ULL,   269,  100 },+    { 0xda01ee641a708deaULL,   295,  108 },+    { 0xa26da3999aef774aULL,   322,  116 },+    { 0xf209787bb47d6b85ULL,   348,  124 },+    { 0xb454e4a179dd1877ULL,   375,  132 },+    { 0x865b86925b9bc5c2ULL,   402,  140 },+    { 0xc83553c5c8965d3dULL,   428,  148 },+    { 0x952ab45cfa97a0b3ULL,   455,  156 },+    { 0xde469fbd99a05fe3ULL,   481,  164 },+    { 0xa59bc234db398c25ULL,   508,  172 },+    { 0xf6c69a72a3989f5cULL,   534,  180 },+    { 0xb7dcbf5354e9beceULL,   561,  188 },+    { 0x88fcf317f22241e2ULL,   588,  196 },+    { 0xcc20ce9bd35c78a5ULL,   614,  204 },+    { 0x98165af37b2153dfULL,   641,  212 },+    { 0xe2a0b5dc971f303aULL,   667,  220 },+    { 0xa8d9d1535ce3b396ULL,   694,  228 },+    { 0xfb9b7cd9a4a7443cULL,   720,  236 },+    { 0xbb764c4ca7a44410ULL,   747,  244 },+    { 0x8bab8eefb6409c1aULL,   774,  252 },+    { 0xd01fef10a657842cULL,   800,  260 },+    { 0x9b10a4e5e9913129ULL,   827,  268 },+    { 0xe7109bfba19c0c9dULL,   853,  276 },+    { 0xac2820d9623bf429ULL,   880,  284 },+    { 0x80444b5e7aa7cf85ULL,   907,  292 },+    { 0xbf21e44003acdd2dULL,   933,  300 },+    { 0x8e679c2f5e44ff8fULL,   960,  308 },+    { 0xd433179d9c8cb841ULL,   986,  316 },+    { 0x9e19db92b4e31ba9ULL,  1013,  324 },+    { 0xeb96bf6ebadf77d9ULL,  1039,  332 },+    { 0xaf87023b9bf0ee6bULL,  1066,  340 }+};++static int cached_pow(int exp, diy_fp *p)+{+    int k = (int)ceil((exp+DIYFP_FRACT_SIZE-1) * D_1_LOG2_10);+    int i = (k-MIN_CACHED_EXP-1) / CACHED_EXP_STEP + 1;+    p->f = pow_cache[i].fract;+    p->e = pow_cache[i].b_exp;+    return pow_cache[i].d_exp;+}++static diy_fp minus(diy_fp x, diy_fp y)+{+    diy_fp d; d.f = x.f - y.f; d.e = x.e;+    assert(x.e == y.e && x.f >= y.f);+    return d;+}++static diy_fp multiply(diy_fp x, diy_fp y)+{+    uint64_t a, b, c, d, ac, bc, ad, bd, tmp;+    diy_fp r;+    a = x.f >> 32; b = x.f & MASK32;+    c = y.f >> 32; d = y.f & MASK32;+    ac = a*c; bc = b*c;+    ad = a*d; bd = b*d;+    tmp = (bd >> 32) + (ad & MASK32) + (bc & MASK32);+    tmp += 1U << 31; // round+    r.f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);+    r.e = x.e + y.e + 64;+    return r;+}++static diy_fp normalize_diy_fp(diy_fp n)+{+    assert(n.f != 0);+    while(!(n.f & 0xFFC0000000000000ULL)) { n.f <<= 10; n.e -= 10; }+    while(!(n.f & D64_SIGN)) { n.f <<= 1; --n.e; }+    return n;+}++static diy_fp double2diy_fp(double d)+{+    diy_fp fp;+    uint64_t u64 = CAST_U64(d);+    if (!(u64 & D64_EXP_MASK)) {+        fp.f = u64 & D64_FRACT_MASK;+        fp.e = 1 - D64_EXP_BIAS;+    }+    else {+        fp.f = (u64 & D64_FRACT_MASK) + D64_IMPLICIT_ONE; +        fp.e = (int)((u64 & D64_EXP_MASK) >> D64_EXP_POS) - D64_EXP_BIAS; +    }+    return fp;+}++static diy_fp float2diy_fp(float d)+{+    diy_fp fp;+    uint32_t u32 = CAST_U32(d);+    if (!(u32 & D32_EXP_MASK)) {+        fp.f = (uint64_t)u32 & D32_FRACT_MASK; +        fp.e = 1 - D32_EXP_BIAS; +    }+    else {+        fp.f = (uint64_t)((u32 & D32_FRACT_MASK) + D32_IMPLICIT_ONE); +        fp.e = (int)((u32 & D32_EXP_MASK) >> D32_EXP_POS) - D32_EXP_BIAS; +    }+    return fp;+}++// pow10_cache[i] = 10^(i-1)+static const unsigned int pow10_cache[] = { 0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };++static int largest_pow10(uint32_t n, int n_bits, uint32_t *power)+{+    int guess = ((n_bits + 1) * 1233 >> 12) + 1/*skip first entry*/;+    if (n < pow10_cache[guess]) --guess; // We don't have any guarantees that 2^n_bits <= n.+    *power = pow10_cache[guess];+    return guess;+}++static int round_weed(char *buffer, int len, uint64_t wp_W, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t ulp)+{+    uint64_t wp_Wup = wp_W - ulp;+    uint64_t wp_Wdown = wp_W + ulp;+    while(rest < wp_Wup && delta - rest >= ten_kappa+            && (rest + ten_kappa < wp_Wup || wp_Wup - rest >= rest + ten_kappa - wp_Wup))+    {+        --buffer[len-1];+        rest += ten_kappa;+    }+    if (rest < wp_Wdown && delta - rest >= ten_kappa+            && (rest + ten_kappa < wp_Wdown || wp_Wdown - rest > rest + ten_kappa - wp_Wdown))+        return 0;++    return 2*ulp <= rest && rest <= delta - 4*ulp;+}++static int digit_gen(diy_fp low, diy_fp w, diy_fp high, char *buffer, HsInt *length, int *kappa)+{+    uint64_t unit = 1;+    diy_fp too_low = { low.f - unit, low.e };+    diy_fp too_high = { high.f + unit, high.e };+    diy_fp unsafe_interval = minus(too_high, too_low);+    diy_fp one = { 1ULL << -w.e, w.e };+    uint32_t p1 = (uint32_t)(too_high.f >> -one.e);+    uint64_t p2 = too_high.f & (one.f - 1);+    uint32_t div;+    *kappa = largest_pow10(p1, DIYFP_FRACT_SIZE + one.e, &div);+    *length = 0;++    while(*kappa > 0)+    {+        uint64_t rest;+        int digit = p1 / div;+        buffer[*length] = (char)(digit);+        ++*length;+        p1 %= div;+        --*kappa;+        rest = ((uint64_t)p1 << -one.e) + p2;+        if (rest < unsafe_interval.f) return round_weed(buffer, *length, minus(too_high, w).f, unsafe_interval.f, rest, (uint64_t)div << -one.e, unit);+        div /= 10;+    }++    for(;;)+    {+        int digit;+        p2 *= 10;+        unit *= 10;+        unsafe_interval.f *= 10;+        // Integer division by one.+        digit = (int)(p2 >> -one.e);+        buffer[*length] = (char)(digit);+        ++*length;+        p2 &= one.f - 1;  // Modulo by one.+        --*kappa;+        if (p2 < unsafe_interval.f) return round_weed(buffer, *length, minus(too_high, w).f * unit, unsafe_interval.f, p2, one.f, unit);+    }+}++HsInt grisu3(double v, char *buffer, HsInt *length, HsInt *d_exp)+{+    int mk, kappa, success;+    diy_fp dfp = double2diy_fp(v);+    diy_fp w = normalize_diy_fp(dfp);++    // normalize boundaries+    diy_fp t = { (dfp.f << 1) + 1, dfp.e - 1 };+    diy_fp b_plus = normalize_diy_fp(t);+    diy_fp b_minus;+    diy_fp c_mk; // Cached power of ten: 10^-k+    uint64_t u64 = CAST_U64(v);+    assert(v > 0 && v <= 1.7976931348623157e308); // Grisu only handles strictly positive finite numbers.+    if (!(u64 & D64_FRACT_MASK) && (u64 & D64_EXP_MASK) != 0) { +        b_minus.f = (dfp.f << 2) - 1; b_minus.e =  dfp.e - 2;+    } // lower boundary is closer?+    else { b_minus.f = (dfp.f << 1) - 1; b_minus.e = dfp.e - 1; }+    b_minus.f = b_minus.f << (b_minus.e - b_plus.e);+    b_minus.e = b_plus.e;++    mk = cached_pow(MIN_TARGET_EXP - DIYFP_FRACT_SIZE - w.e, &c_mk);++    w = multiply(w, c_mk);+    b_minus = multiply(b_minus, c_mk);+    b_plus  = multiply(b_plus,  c_mk);++    success = digit_gen(b_minus, w, b_plus, buffer, length, &kappa);+    *d_exp = kappa - mk;+    return (HsInt)success;+}++HsInt grisu3_sp(float v, char *buffer, HsInt *length, HsInt *d_exp)+{+    int mk, kappa, success;+    diy_fp dfp = float2diy_fp(v);+    diy_fp w = normalize_diy_fp(dfp);++    // normalize boundaries+    diy_fp t = { (dfp.f << 1) + 1, dfp.e - 1 };+    diy_fp b_plus = normalize_diy_fp(t);+    diy_fp b_minus;+    diy_fp c_mk; // Cached power of ten: 10^-k+    uint64_t u32 = CAST_U32(v);+    assert(v > 0 && v <= 3.4028235e38); // Grisu only handles strictly positive finite numbers.+    if (!(u32 & D32_FRACT_MASK) && (u32 & D32_EXP_MASK) != 0) {+        b_minus.f = (dfp.f << 2) - 1; b_minus.e =  dfp.e - 2;+    } // lower boundary is closer?+    else { b_minus.f = (dfp.f << 1) - 1; b_minus.e = dfp.e - 1; }+    b_minus.f = b_minus.f << (b_minus.e - b_plus.e);+    b_minus.e = b_plus.e;++    mk = cached_pow(MIN_TARGET_EXP - DIYFP_FRACT_SIZE - w.e, &c_mk);++    w = multiply(w, c_mk);+    b_minus = multiply(b_minus, c_mk);+    b_plus  = multiply(b_plus,  c_mk);++    success = digit_gen(b_minus, w, b_plus, buffer, length, &kappa);+    *d_exp = kappa - mk;+    return (HsInt)success;+}
+ cbits/hs_uv_base.c view
@@ -0,0 +1,295 @@+/*+ * Copyright (c) 2017-2018 Dong Han+ *+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the names of the authors or the names of any contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */++#include <hs_uv.h>+#include <stdio.h>++////////////////////////////////////////////////////////////////////////////////+// loop+//+// initialize a loop with its data to give slot size. return NULL on fail.+uv_loop_t* hs_uv_loop_init(HsInt siz){+    int r; +    HsInt i;++    uv_loop_t* loop = malloc(sizeof(uv_loop_t));+    r = uv_loop_init(loop);++    if (r < 0) { +        free(loop);+        return NULL;+    }++    hs_loop_data* loop_data = malloc(sizeof(hs_loop_data));+        +    HsInt* event_queue = malloc(siz*sizeof(HsInt));+    char** buffer_table = malloc(siz*sizeof(char*));+    HsInt* buffer_size_table = malloc(siz*sizeof(HsInt));+    HsInt* slot_table = malloc(siz*sizeof(HsInt));+    HsInt* free_slot_queue = malloc(siz*sizeof(HsInt));+    hs_uv_struct** uv_struct_table = malloc(sizeof(void*));+    hs_uv_struct* uv_struct_table_block = malloc(siz*sizeof(hs_uv_struct));++    uv_async_t* async = malloc(sizeof(uv_async_t));+    uv_timer_t* timer = malloc(sizeof(uv_timer_t));++    if (loop_data == NULL || event_queue == NULL || buffer_table == NULL ||+            buffer_size_table == NULL || slot_table == NULL || free_slot_queue == NULL ||+                uv_struct_table == NULL || uv_struct_table_block == NULL ||+                    async == NULL || timer == NULL ||+                        uv_timer_init(loop, timer) < 0 ||+                            uv_async_init(loop, async, NULL) < 0){+        free(event_queue);+        free(loop_data);+        free(buffer_table);+        free(buffer_size_table);+        free(slot_table);+        free(free_slot_queue);+        free(uv_struct_table);+        free(uv_struct_table_block);++        free(async);+        free(timer);++        uv_loop_close(loop);+        free(loop);+        free(loop_data);+        return NULL;    // before return NULL, free all structs+    } else {+        // initialize slot table+        for (i = 0; i < siz; i++) {+            slot_table[i] = i+1;+        }+        loop_data->event_queue          = event_queue;+        loop_data->buffer_table         = buffer_table;+        loop_data->buffer_size_table    = buffer_size_table;+        loop_data->slot_table           = slot_table;+        loop_data->free_slot            = 0;+        loop_data->free_slot_queue      = free_slot_queue;+        loop_data->free_slot_counter    = 0;+        loop_data->uv_struct_table      = uv_struct_table;+        uv_struct_table[0]              = uv_struct_table_block;+        loop_data->resize               = 0;+        loop_data->size                 = siz;+        loop_data->async                = async;+        loop_data->timer                = timer;+        loop->data = loop_data;+        return loop;+    }+}++// resize a loop's data to given slot size, return NULL on fail.+hs_loop_data* hs_uv_loop_resize(hs_loop_data* loop_data, HsInt siz){+    HsInt i;+    loop_data->resize += 1;+    HsInt* event_queue_new       = realloc(loop_data->event_queue, (siz*sizeof(HsInt)));+    char** buffer_table_new       = realloc(loop_data->buffer_table, (siz*sizeof(char*)));+    HsInt* buffer_size_table_new = realloc(loop_data->buffer_size_table, (siz*sizeof(HsInt)));+    HsInt* slot_table_new = realloc(loop_data->slot_table, (siz*sizeof(HsInt)));+    HsInt* free_slot_queue_new = realloc(loop_data->free_slot_queue, (siz*sizeof(HsInt)));+    hs_uv_struct** uv_struct_table_new = realloc(loop_data->uv_struct_table, (loop_data->resize+1)*sizeof(void*));+    hs_uv_struct* uv_struct_table_block = malloc((loop_data->size)*sizeof(hs_uv_struct));++    if (event_queue_new == NULL || buffer_table_new == NULL ||+            buffer_size_table_new == NULL || slot_table_new == NULL || free_slot_queue_new == NULL ||+                uv_struct_table_new == NULL || uv_struct_table_block == NULL){+        // release new memory+        if (event_queue_new != loop_data->event_queue) free(event_queue_new);+        if (buffer_table_new != loop_data->buffer_table) free(buffer_table_new);+        if (buffer_size_table_new != loop_data->buffer_size_table) free(buffer_size_table_new);+        if (slot_table_new != loop_data->slot_table) free(slot_table_new);+        if (free_slot_queue_new != loop_data->free_slot_queue) free(free_slot_queue_new);+        if (uv_struct_table_new != loop_data->uv_struct_table) free(uv_struct_table_new);+        free(uv_struct_table_block);+        return NULL;+    } else {+        for (i = loop_data->size; i < siz; i++) {+            slot_table_new[i] = i+1;+        }+        loop_data->event_queue        = event_queue_new;+        loop_data->buffer_table       = buffer_table_new;+        loop_data->buffer_size_table  = buffer_size_table_new;+        loop_data->slot_table         = slot_table_new;+        loop_data->free_slot          = loop_data->size;+        loop_data->free_slot_queue    = free_slot_queue_new;+        loop_data->uv_struct_table    = uv_struct_table_new;+        uv_struct_table_new[loop_data->resize] = uv_struct_table_block;+        loop_data->size               = siz;+        return loop_data;+    }+}++// allocate free slot, resize loop data if neccessary +// return -1 on resize failure, slot otherwise.+HsInt alloc_slot(hs_loop_data* loop_data){+    HsInt r = loop_data->free_slot;+    loop_data->free_slot = loop_data->slot_table[r];+    // the slot exceed range, we should resize+    if (r == loop_data->size-1 &&+        hs_uv_loop_resize(loop_data, (loop_data->size) << 1) == NULL) {+        return -1;+    }+    return r;+}++void free_slot(hs_loop_data* loop_data, HsInt slot){+    loop_data->free_slot_queue[loop_data->free_slot_counter] = slot;+    loop_data->free_slot_counter++;+}++int hs_uv_run(uv_loop_t* loop, uv_run_mode mode){+    hs_loop_data* loop_data = loop->data;+    HsInt* q = loop_data->free_slot_queue;+    HsInt i = loop_data->free_slot_counter;+    HsInt slot;+    // do the real slot release, see notes on slot allocation in hs_uv.h+    for (i--; i >= 0; i--){+        slot = q[i];+        loop_data->slot_table[slot] = loop_data->free_slot;+        loop_data->free_slot = slot;+    }+    loop_data->free_slot_counter = 0;+    return uv_run(loop, mode);+}++hs_uv_struct* fetch_uv_struct(hs_loop_data* loop_data, HsInt slot){+    int bits = 0;+    HsInt slot2 = slot >> INIT_LOOP_SIZE_BIT;+    // __builtin_clz may be a good idea+    while (slot2 > 0){ bits += 1; slot2 = slot2 >> 1; }+    if (bits == 0)+        return loop_data->uv_struct_table[bits] + slot;+    else+        return loop_data->uv_struct_table[bits] + +            slot - (1<<(INIT_LOOP_SIZE_BIT+bits-1));+}++void hs_uv_walk_close_cb(uv_handle_t* handle, void* arg){+    if (uv_is_closing(handle) == 0) uv_close(handle, hs_uv_handle_free);+}++// This function close all the handles live on that loop and the loop itself,+// then release all the memory.+//+// https://stackoverflow.com/questions/25615340/closing-libuv-handles-correctly+//+void hs_uv_loop_close(uv_loop_t* loop){+    uv_stop(loop);+    uv_walk(loop, hs_uv_walk_close_cb, NULL);+    uv_run(loop, UV_RUN_NOWAIT);+    while(uv_loop_close(loop) == UV_EBUSY);++    hs_loop_data* loop_data = loop->data;+    free(loop);+    free(loop_data->event_queue);+    free(loop_data->buffer_table);+    free(loop_data->buffer_size_table);+    free(loop_data->slot_table);+    free(loop_data->uv_struct_table);++    free(loop_data->async);+    free(loop_data->timer);++    free(loop_data);+    free(loop);+}++////////////////////////////////////////////////////////////////////////////////+// thread-safe wake up++void uv_timer_wake_cb(uv_timer_t* timer){ uv_timer_stop(timer); }++int hs_uv_wake_up_timer(hs_loop_data* loop_data){+    return uv_timer_start(loop_data->timer, uv_timer_wake_cb, 1, 1);+}+int hs_uv_wake_up_async(hs_loop_data* loop_data){+    return uv_async_send(loop_data->async);+}++////////////////////////////////////////////////////////////////////////////////+// handle+//+// Get handle's OS file+int32_t hs_uv_fileno(uv_handle_t* handle){+    uv_os_fd_t fd;+    int r;+    r = uv_fileno(handle, &fd);+    if (r < 0) { return (int32_t)r; } else { return (int32_t)fd; }+}++// Initialize a uv_handle_t, with data field set to an unique slot+uv_handle_t* hs_uv_handle_alloc(uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return NULL;+    uv_handle_t* handle = +        (uv_handle_t*)fetch_uv_struct(loop_data, slot);+    handle->loop = loop;+    handle->data = (void*)slot;+    return handle;+}++// Free uv_handle_t only, used when handle initialization failed.+void hs_uv_handle_free(uv_handle_t* handle){+    uv_loop_t* loop = handle->loop;+    free_slot(loop->data, (HsInt)handle->data);+}++// Close and free uv_handle_t+void hs_uv_handle_close(uv_handle_t* handle){+    uv_close(handle, hs_uv_handle_free);+}++////////////////////////////////////////////////////////////////////////////////+// request++// Cancel an ongoing uv request, so that the slot can be freed ASAP.+void hs_uv_cancel(uv_loop_t* loop, HsInt slot){+    hs_loop_data* loop_data = loop->data;+    uv_req_t* req = +        (uv_req_t*)fetch_uv_struct(loop_data, slot);+    switch (req->type) {+        case UV_CONNECT:+            hs_uv_handle_close((uv_handle_t*)((uv_connect_t*)req)->handle);+            break;+        case UV_WRITE:+            hs_uv_handle_close((uv_handle_t*)((uv_write_t*)req)->handle);+            break;+        case UV_SHUTDOWN:+            hs_uv_handle_close((uv_handle_t*)((uv_shutdown_t*)req)->handle);+            break;+        case UV_UDP_SEND:+            hs_uv_handle_close((uv_handle_t*)((uv_udp_send_t*)req)->handle);+            break;+        default:+            // we do it in best effort basis+            uv_cancel(req);+    }+}
+ cbits/hs_uv_file.c view
@@ -0,0 +1,739 @@+/*+ * Copyright (c) 2017-2018 Dong Han+ *+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the names of the authors or the names of any contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */++#include <hs_uv.h>++////////////////////////////////////////////////////////////////////////////////+// fs, none thread pool version+//+// we wrappered non-threaded pool version functions, so that we can move the allocation+// of uv_fs_t to stack, most of the functions can be optimized in this way.+// in none thread pool version, req->result is directly returned.++int32_t hs_uv_fs_open(const char* path, int flags, int mode){+    uv_fs_t req;+    uv_fs_open(NULL, &req, path, flags, mode, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (int32_t)req.result;+}++HsInt hs_uv_fs_close(int32_t file){+    uv_fs_t req;+    uv_fs_close(NULL, &req, (uv_file)file, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_read(int32_t file, char* buffer, HsInt buffer_size, int64_t offset){+    uv_fs_t req;+    uv_buf_t buf = { .base = buffer, .len = (size_t)buffer_size };+    uv_fs_read(NULL, &req, (uv_file)file, &buf, 1, offset, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_write(int32_t file, char* buffer, HsInt buffer_size, int64_t offset){+    uv_fs_t req;+    uv_buf_t buf = { .base = buffer, .len = (size_t)buffer_size };+    uv_fs_write(NULL, &req, (uv_file)file, &buf, 1, offset, NULL);+    return (HsInt)req.result;+}++HsInt hs_uv_fs_unlink(const char* path){+    uv_fs_t req;+    uv_fs_unlink(NULL, &req, path, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_mkdir(const char* path, int mode){+    uv_fs_t req;+    uv_fs_mkdir(NULL, &req, path, mode, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_mkdtemp(const char* tpl, HsInt tpl_size, char* temp_path){+    uv_fs_t req;+    strcpy(temp_path, tpl);+    strcpy(temp_path + tpl_size, "XXXXXX");+    uv_fs_mkdtemp(NULL, &req, temp_path, NULL);+    strcpy(temp_path, req.path);    // save the temp path+    uv_fs_req_cleanup(&req);        // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_rmdir(const char* path){+    uv_fs_t req;+    uv_fs_rmdir(NULL, &req, path, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++void hs_uv_fs_scandir_cleanup(uv_dirent_t** dents, HsInt n){+    int i;+    for (i=0; i<n; i++){+        uv__fs_scandir_free(dents[i]);+    }+    uv__fs_scandir_free(dents);+}++HsInt hs_uv_fs_scandir(const char* path, uv_dirent_t*** dents){+    uv_fs_t req;+    uv_fs_scandir(NULL, &req, path, 0, NULL);+    *dents = req.ptr;+#if defined(_WIN32)+    uv__free(req.file.pathw);      //  we clean up dents later+#endif+    return (HsInt)req.result;+}++HsInt hs_uv_fs_stat(const char* path, uv_stat_t* stat){+    uv_fs_t req;+    uv_fs_stat(NULL, &req, path, NULL);+    memcpy(stat, &req.statbuf, sizeof(uv_stat_t));+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_fstat(int32_t file, uv_stat_t* stat){+    uv_fs_t req;+    uv_fs_fstat(NULL, &req, file, NULL);+    memcpy(stat, &req.statbuf, sizeof(uv_stat_t));+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_lstat(const char* path, uv_stat_t* stat){+    uv_fs_t req;+    uv_fs_lstat(NULL, &req, path, NULL);+    memcpy(stat, &req.statbuf, sizeof(uv_stat_t));+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_rename(const char* path, const char* path2){+    uv_fs_t req;+    uv_fs_rename(NULL, &req, path, path2, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_fsync(int32_t file){+    uv_fs_t req;+    uv_fs_fsync(NULL, &req, file, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_fdatasync(int32_t file){+    uv_fs_t req;+    uv_fs_fdatasync(NULL, &req, file, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_ftruncate(int32_t file, int64_t off){+    uv_fs_t req;+    uv_fs_ftruncate(NULL, &req, file, off, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_copyfile(const char* path, const char* path2, int flag){+    uv_fs_t req;+    uv_fs_copyfile(NULL, &req, path, path2, flag, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_access(const char* path, int mode){+    uv_fs_t req;+    uv_fs_access(NULL, &req, path, mode, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_chmod(const char* path, int mode){+    uv_fs_t req;+    uv_fs_chmod(NULL, &req, path, mode, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_fchmod(int32_t file, int mode){+    uv_fs_t req;+    uv_fs_fchmod(NULL, &req, file, mode, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_utime(const char* path, double atime, double mtime){+    uv_fs_t req;+    uv_fs_utime(NULL, &req, path, atime, mtime, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_futime(int32_t file, double atime, double mtime){+    uv_fs_t req;+    uv_fs_futime(NULL, &req, file, atime, mtime, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_link(const char* path, const char* path2){+    uv_fs_t req;+    uv_fs_link(NULL, &req, path, path2, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++HsInt hs_uv_fs_symlink(const char* path, const char* path2, int flag){+    uv_fs_t req;+    uv_fs_symlink(NULL, &req, path, path2, flag, NULL);+    uv_fs_req_cleanup(&req);    // maybe not neccessary+    return (HsInt)req.result;+}++void hs_uv_fs_readlink_cleanup(char* path){+    if (path != NULL) uv__free(path);+}++HsInt hs_uv_fs_readlink(const char* path, char** result_path){+    uv_fs_t req;+    uv_fs_readlink(NULL, &req, path, NULL);+    *result_path = req.ptr;+#if defined(_WIN32)+    uv__free(req.file.pathw);      //  we clean up result_path later+#endif+    return (HsInt)req.result;+}++HsInt hs_uv_fs_realpath(const char* path, char** result_path){+    uv_fs_t req;+    uv_fs_realpath(NULL, &req, path, NULL);+    *result_path = req.ptr;+#if defined(_WIN32)+    uv__free(req.file.pathw);      //  we clean up result_path later+#endif+    return (HsInt)req.result;+}++////////////////////////////////////////////////////////////////////////////////+// fs, thread pool version+//+void hs_uv_fs_callback(uv_fs_t* req){+    uv_loop_t* loop = req->loop;+    hs_loop_data* loop_data = loop->data;+    HsInt slot = (HsInt)req->data; +    // push the slot to event queue+    loop_data->buffer_size_table[slot] = (HsInt)req->result;+    loop_data->event_queue[loop_data->event_counter] = slot;+    loop_data->event_counter += 1;+    uv_fs_req_cleanup(req);+    free_slot(loop_data, slot);  // free the uv_req_t+}++HsInt hs_uv_fs_open_threaded(const char* path, int flags, int mode, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;++    int r = uv_fs_open(loop, req, path, flags, mode, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_close_threaded(int32_t file, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_close(loop, req, (uv_file)file, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_read_threaded(int32_t file, char* buffer, HsInt buffer_size, int64_t offset, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    uv_buf_t buf = { .base = buffer, .len = (size_t)buffer_size };+    int r = uv_fs_read(loop, req, (uv_file)file, &buf, 1, offset, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_write_threaded(int32_t file, char* buffer, HsInt buffer_size, int64_t offset, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    uv_buf_t buf = { .base = buffer, .len = (size_t)buffer_size };+    int r = uv_fs_write(loop, req, (uv_file)file, &buf, 1, offset, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_unlink_threaded(const char* path, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_unlink(loop, req, path, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_mkdir_threaded(const char* path, int mode, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_mkdir(loop, req, path, mode, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++void hs_uv_fs_mkdtemp_callback(uv_fs_t* req){+    uv_loop_t* loop = req->loop;+    hs_loop_data* loop_data = loop->data;+    HsInt slot = (HsInt)req->data; +    char* path = loop_data->buffer_table[slot];+    if (path != NULL) {+        // push the slot to event queue+        loop_data->buffer_size_table[slot] = (HsInt)req->result;+        loop_data->event_queue[loop_data->event_counter] = slot;+        loop_data->event_counter += 1;+        strcpy(path, req->path);  // save the temp path+    }+    uv_fs_req_cleanup(req);+    free_slot(loop_data, slot);  // free the uv_req_t+}++HsInt hs_uv_fs_mkdtemp_threaded(const char* tpl, HsInt tpl_size, char* temp_path, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    strcpy(temp_path, tpl);+    strcpy(temp_path + tpl_size, "XXXXXX");+    loop_data->buffer_table[slot] = temp_path;+    int r = uv_fs_mkdtemp(loop, req, temp_path, hs_uv_fs_mkdtemp_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_rmdir_threaded(const char* path, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_rmdir(loop, req, path, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++void hs_uv_fs_scandir_callback(uv_fs_t* req){+    uv_loop_t* loop = req->loop;+    hs_loop_data* loop_data = loop->data;+    HsInt slot = (HsInt)req->data; +    uv_dirent_t*** dents = (uv_dirent_t***)loop_data->buffer_table[slot];+    if (dents != NULL) {+        *dents = req->ptr;+        // save the dent struct array pointer+        // push the slot to event queue+        loop_data->buffer_size_table[slot] = (HsInt)req->result;+        loop_data->event_queue[loop_data->event_counter] = slot;+        loop_data->event_counter += 1;+    }+    //  we can't cleanup request here, because doing that will+    //  destory our dents array, which we haven't copied in Haskell yet. +    //  so we manually break down uv_fs_req_cleanup here:+    //  we free path buffer first, then clean up dents later using+    //  hs_uv_fs_scandir_cleanup, or hs_uv_fs_scandir_extra_cleanup +    //  in case of async exception.+#if defined(_WIN32)+    if (req->file.pathw != NULL)+        uv__free(req->file.pathw);  +#else+    if (req->path != NULL)+        uv__free((void*) req->path);+#endif+    free_slot(loop_data, slot);  // free the uv_req_t+}++void hs_uv_fs_scandir_extra_cleanup(uv_dirent_t*** dents_p, HsInt n){+    int i;+    uv_dirent_t** dents = *dents_p;+    if (dents != NULL) {+        for (i=0; i<n; i++){+            uv__fs_scandir_free(dents[i]);+        }+        uv__fs_scandir_free(dents);+    }+}++HsInt hs_uv_fs_scandir_threaded(const char* path, uv_dirent_t*** dents, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    loop_data->buffer_table[slot] = (char*)dents;+    int r = uv_fs_scandir(loop, req, path, 0, hs_uv_fs_scandir_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++void hs_uv_fs_stat_callback(uv_fs_t* req){+    uv_loop_t* loop = req->loop;+    hs_loop_data* loop_data = loop->data;+    HsInt slot = (HsInt)req->data; +    uv_stat_t* stat = (uv_stat_t*)loop_data->buffer_table[slot];+    if (stat != NULL) {+        // push the slot to event queue+        loop_data->buffer_size_table[slot] = (HsInt)req->result;+        loop_data->event_queue[loop_data->event_counter] = slot;+        loop_data->event_counter += 1;+        memcpy(stat, &req->statbuf, sizeof(uv_stat_t));  // save the temp path+    }+    uv_fs_req_cleanup(req);+    free_slot(loop_data, slot);  // free the uv_req_t+}++HsInt hs_uv_fs_stat_threaded(const char* path, uv_stat_t* stat, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    loop_data->buffer_table[slot] = (char*)stat;+    int r = uv_fs_stat(loop, req, path, hs_uv_fs_stat_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_fstat_threaded(int32_t file, uv_stat_t* stat, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    loop_data->buffer_table[slot] = (char*)stat;+    int r = uv_fs_fstat(loop, req, file, hs_uv_fs_stat_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_lstat_threaded(const char* path, uv_stat_t* stat, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    loop_data->buffer_table[slot] = (char*)stat;+    int r = uv_fs_lstat(loop, req, path, hs_uv_fs_stat_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_rename_threaded(const char* path, const char* path2, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_rename(loop, req, path, path2, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_fsync_threaded(int32_t file, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_fsync(loop, req, file, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_fdatasync_threaded(int32_t file, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_fdatasync(loop, req, file, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_ftruncate_threaded(int32_t file, int64_t off, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_ftruncate(loop, req, file, off, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_copyfile_threaded(const char* path, const char* path2, int flag, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_copyfile(loop, req, path, path2, flag, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_access_threaded(const char* path, int mode, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_access(loop, req, path, mode, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_chmod_threaded(const char* path, int mode, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_chmod(loop, req, path, mode, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_fchmod_threaded(int32_t file, int mode, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_fchmod(loop, req, file, mode, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_utime_threaded(const char* path, double atime, double mtime, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_utime(loop, req, path, atime, mtime, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_futime_threaded(int32_t file, double atime, double mtime, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_futime(loop, req, file, atime, mtime, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_link_threaded(const char* path, const char* path2, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_link(loop, req, path, path2, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++HsInt hs_uv_fs_symlink_threaded(const char* path, const char* path2, int flag, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_fs_symlink(loop, req, path, path2, flag, hs_uv_fs_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++void hs_uv_fs_readlink_callback(uv_fs_t* req){+    uv_loop_t* loop = req->loop;+    hs_loop_data* loop_data = loop->data;+    HsInt slot = (HsInt)req->data; +    char** path = (char**)loop_data->buffer_table[slot];+    if (path != NULL) {+        *path = req->ptr;  // save the result path+        // push the slot to event queue+        loop_data->buffer_size_table[slot] = (HsInt)req->result;+        loop_data->event_queue[loop_data->event_counter] = slot;+        loop_data->event_counter += 1;+    }+    //  for the same reason with 'scandir', we can't cleanup request here+#if defined(_WIN32)+    if (req->file.pathw != NULL)+        uv__free(req->file.pathw);  +#else+    if (req->path != NULL)+        uv__free((void*) req->path);+#endif+    free_slot(loop_data, slot);  // free the uv_req_t+}++void hs_uv_fs_readlink_extra_cleanup(char** path){+    if (*path != NULL) uv__free(*path);+}++HsInt hs_uv_fs_readlink_threaded(const char* path, char** result_path, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    loop_data->buffer_table[slot] = (char*)result_path;+    int r = uv_fs_readlink(loop, req, path, hs_uv_fs_readlink_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}++// share cleanup and callback with readlink+HsInt hs_uv_fs_realpath_threaded(const char* path, char** result_path, uv_loop_t* loop){+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_fs_t* req = +        (uv_fs_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    loop_data->buffer_table[slot] = (char*)result_path;+    int r = uv_fs_realpath(loop, req, path, hs_uv_fs_readlink_callback);+    if (r < 0) {+        free_slot(loop_data, slot);+        return (HsInt)r;+    } else return slot;+}
+ cbits/hs_uv_stream.c view
@@ -0,0 +1,356 @@+/*+ * Copyright (c) 2017-2018 Dong Han+ *+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the names of the authors or the names of any contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */++#include <hs_uv.h>++////////////////////////////////////////////////////////////////////////////////+//+// stream+//+// We reuse buffer_size_table as the result table, i.e. after haskell threads+// are unblocked, they should peek result(length, errcode..) from buffer_size_table++// This callback simply copy buffer from buffer table and buffer size table+void hs_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf){+    HsInt slot = (HsInt)handle->data;+    hs_loop_data* loop_data = handle->loop->data;+    buf->base = loop_data->buffer_table[slot];      // fetch buffer_table from buffer_table table+    buf->len = loop_data->buffer_size_table[slot];  // we ignore suggested_size completely+}++// We only do single read per uv_run with uv_read_stop+void hs_read_cb (uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf){+    HsInt slot = (HsInt)stream->data;+    hs_loop_data* loop_data = stream->loop->data;+    if (nread != 0) {+        loop_data->buffer_size_table[slot] = nread;+        loop_data->event_queue[loop_data->event_counter] = slot; // push the slot to event queue+        loop_data->event_counter += 1;+        uv_read_stop(stream);+    }+}++int hs_uv_read_start(uv_stream_t* stream){+    return uv_read_start(stream, hs_alloc_cb, hs_read_cb);+}++void hs_write_cb(uv_write_t* req, int status){+    HsInt slot = (HsInt)req->data;+    uv_loop_t* loop = req->handle->loop;+    hs_loop_data* loop_data = loop->data;+    loop_data->buffer_size_table[slot] = (HsInt)status;      // 0 in case of success, < 0 otherwise.+    loop_data->event_queue[loop_data->event_counter] = slot;   // push the slot to event queue+    loop_data->event_counter += 1;+    free_slot(loop_data, slot);  // free the uv_req_t+}++HsInt hs_uv_write(uv_stream_t* handle, char* buf, HsInt buf_siz){+    uv_loop_t* loop = handle->loop;+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_write_t* req = +        (uv_write_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;++    // on windows this struct is captured by WSASend+    // on unix this struct is copied by libuv's uv_write+    // so it's safe to allocate it on stack+    uv_buf_t buf_t = { .base = buf, .len = (size_t)buf_siz };+    +    int r = uv_write(req, handle, &buf_t, 1, hs_write_cb); // we never use writev: we do our own+                                                           // user-space buffering in haskell.+    if (r < 0) {+        free_slot(loop_data, slot);  // free the uv_req_t, the callback won't fired+        return (HsInt)r;+    } else return slot;+}++////////////////////////////////////////////////////////////////////////////////+//+// tcp++/* on windows uv_tcp_open doesn't work propery for sockets that are not+ * connected or accepted by libuv because the lack of some state initialization,+ * so we do it by manually set those flags+ *+ * referenes:   https://github.com/libuv/libuv/issues/397+ *              https://github.com/libuv/libuv/pull/1150+ */+#if defined(_WIN32)+void hs_uv_connection_init(uv_stream_t* handle){+  handle->flags |= UV_HANDLE_CONNECTION;+  handle->stream.conn.write_reqs_pending = 0;+  (&handle->read_req)->type = UV_READ;                                                        \+  (&handle->read_req)->u.io.overlapped.Internal = 0;  /* SET_REQ_SUCCESS() */ +  handle->read_req.event_handle = NULL;+  handle->read_req.wait_handle = INVALID_HANDLE_VALUE;+  handle->read_req.data = handle;+  handle->stream.conn.shutdown_req = NULL;+}++int hs_uv_tcp_open(uv_tcp_t* handle, int32_t sock) {+  int r = uv_tcp_open(handle, (uv_os_sock_t)sock);+  if (r == 0) {+    hs_uv_connection_init((uv_stream_t*)handle);+    handle->flags |= UV_HANDLE_BOUND | UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;+  }+  return r;+}+#else+int hs_uv_tcp_open(uv_tcp_t* handle, int32_t sock) {+  return uv_tcp_open(handle, (uv_os_sock_t)sock);+}+#endif++void hs_connect_cb(uv_connect_t* req, int status){+    HsInt slot = (HsInt)req->data;+    uv_loop_t* loop = req->handle->loop;+    hs_loop_data* loop_data = loop->data;  // uv_connect_t has handle field+    loop_data->buffer_size_table[slot] = status;             // 0 in case of success, < 0 otherwise.+    loop_data->event_queue[loop_data->event_counter] = slot; // push the slot to event queue+    loop_data->event_counter += 1;+    free_slot(loop_data, slot);  // free the uv_req_t+}++HsInt hs_uv_tcp_connect(uv_tcp_t* handle, const struct sockaddr* addr){+    uv_loop_t* loop = handle->loop;+    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_connect_t* req = +        (uv_connect_t*)fetch_uv_struct(loop_data, slot);+    req->data = (void*)slot;+    int r = uv_tcp_connect(req, handle, addr, hs_connect_cb);+    if (r < 0) {+        free_slot(loop_data, slot);  // free the uv_req_t, the callback won't fired+        return r;+    } else return slot;+}++// When libuv listen's callback is called, client is actually already accepted, +// so our customized accept function just return the fd directly, Following code+// doesn't support IPC for now.+//+// TODO research on accepting fds sent by IPC pipes.+//+#if defined(_WIN32)+int32_t hs_uv_tcp_accept(uv_tcp_t* server) {+  int32_t fd = -1;++  uv_tcp_accept_t* req = server->tcp.serv.pending_accepts;++  if (!req) {+    /* No valid connections found, so we error out. */+    return WSAEWOULDBLOCK;+  }++  if (req->accept_socket == INVALID_SOCKET) {+    return WSAENOTCONN;+  }++  fd = (int32_t)req->accept_socket;++  /* Prepare the req to pick up a new connection */++  server->tcp.serv.pending_accepts = req->next_pending;+  req->next_pending = NULL;+  req->accept_socket = INVALID_SOCKET;++  if (!(server->flags & UV__HANDLE_CLOSING)) {+    /* Check if we're in a middle of changing the number of pending accepts. */+    if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) {+      uv_tcp_queue_accept(server, req);+    } else {+      /* We better be switching to a single pending accept. */+      assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT);+      server->tcp.serv.processed_accepts++;+      if (server->tcp.serv.processed_accepts >= uv_simultaneous_server_accepts) {+        server->tcp.serv.processed_accepts = 0;+        /*+         * All previously queued accept requests are now processed.+         * We now switch to queueing just a single accept.+         */+        uv_tcp_queue_accept(server, &server->tcp.serv.accept_reqs[0]);+        server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING;+        server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;+      }+    }+  }+  return fd;+}+int32_t hs_uv_pipe_accept(uv_pipe_t* server) {+    int32_t fd = -1;++    uv_loop_t* loop = server->loop;+    uv_pipe_accept_t* req;+    req = server->pipe.serv.pending_accepts;+    if (!req) {+      /* No valid connections found, so we error out. */+      return WSAEWOULDBLOCK;+    }++    fd = (int32_t)req->pipeHandle;++    /* Prepare the req to pick up a new connection */+    server->pipe.serv.pending_accepts = req->next_pending;+    req->next_pending = NULL;+    req->pipeHandle = INVALID_HANDLE_VALUE;+    if (!(server->flags & UV__HANDLE_CLOSING)) {+        uv_pipe_queue_accept(loop, server, req, FALSE);+    }+    return fd;+}+int32_t hs_uv_accept(uv_stream_t* server) {+    int32_t fd;+    switch (server->type) {+        case UV_TCP:+            fd = hs_uv_tcp_accept((uv_tcp_t*)server);+            break;+        case UV_NAMED_PIPE:+            fd = hs_uv_pipe_accept((uv_pipe_t*)server);+            break;+        default:+            assert(0);+    }+    return fd;+}+#else+int32_t hs_uv_accept(uv_stream_t* server) {+    int32_t fd = (int32_t)server->accepted_fd;+    server->accepted_fd = -1;+    return fd;+}+#endif++void hs_listen_cb(uv_stream_t* server, int status){+    HsInt slot = (HsInt)server->data;+    hs_loop_data* loop_data = server->loop->data;++    // fetch accept buffer from buffer_table table+    int32_t* accept_buf = (int32_t*)loop_data->buffer_table[slot];     +    HsInt accepted_number = loop_data->buffer_size_table[slot];++    if (status == 0) {+        if (accepted_number < ACCEPT_BUFFER_SIZE - 1) {+            accept_buf[accepted_number] = hs_uv_accept(server);       +            loop_data->buffer_size_table[slot] = accepted_number + 1;+        } else {+#if defined(_WIN32)+            // we have no way to deal with this situation on windows, since +            // we can't stop accepting after request has been inserted+            // but this should not happen on windows anyway,+            // since on windows simultaneous_accepts is small, e.g. pending accept+            // requests' number is small.+            // It must takes many uv_run without copying accept buffer on haskell side+            // which is very unlikely to happen.+            closesocket(hs_uv_accept(server)); +#else+            // on unix, we can stop accepting using uv__io_stop, this is+            // important because libuv will loop accepting until EAGAIN/EWOULDBLOCK,+            // If we return to accept thread too slow in haskell side, the +            // accept buffer may not be able to hold all the clients queued in backlog.+            // And this is very likely to happen under high load. Thus we+            // must stop accepting when the buffer is full.+            //+            // Limit this number may also be good for stop a non-block uv_run from+            // running too long, which will affect haskell's GC.+            //+            // do last accept without clearing server->accepted_fd+            // libuv will take this as a no accepting, thus call uv__io_stop for us.+            accept_buf[accepted_number] = hs_uv_accept(server);       +            // set back accepted_fd so that libuv break from accept loop+            // upon next resuming, we clear this accepted_fd with -1 and call uv__io_start+            server->accepted_fd = accept_buf[accepted_number];+            loop_data->buffer_size_table[slot] = accepted_number + 1;+#endif+        }+    } else {+        accept_buf[accepted_number] = (int32_t)status;+        loop_data->buffer_size_table[slot] = accepted_number + 1;+    }++}++int hs_uv_listen(uv_stream_t* stream, int backlog){+    return uv_listen(stream, backlog, hs_listen_cb);+}++// on windows we don't need to do anything, since we didn't and can't stopped. +void hs_uv_listen_resume(uv_stream_t* server){+#if !defined(_WIN32)+    server->accepted_fd = -1;+    uv__io_start(server->loop, &server->io_watcher, POLLIN);+#endif+}++// Check if the socket's accept buffer is still filled, if so, unlock the accept thread+//+void hs_accept_check_cb(uv_check_t* check){+    uv_stream_t* server=(uv_stream_t*)check->data;+    HsInt slot = (HsInt)server->data;+    hs_loop_data* loop_data = server->loop->data;++    if (loop_data->buffer_size_table[slot] > 0){+        loop_data->event_queue[loop_data->event_counter] = slot; // push the slot to event queue+        loop_data->event_counter += 1;+    }+}++// It's hard to arrange accepting notification without check handler, we can't+// do it in listen's callback, since it'll be called multiple times during uv_run.+uv_check_t* hs_uv_accept_check_alloc(uv_stream_t* server){+    uv_check_t* check = malloc(sizeof(uv_check_t));+    if (check == NULL) return NULL;+    check->data = (void*)server;    // we link server to check's data field+    return check;+}++int hs_uv_accept_check_init(uv_check_t* check){+    uv_stream_t* server = check->data;+    int r = uv_check_init(server->loop, check);+    if (r < 0) return r;+    return uv_check_start(check, hs_accept_check_cb);+}++void hs_uv_accept_check_close(uv_check_t* check){+    uv_close((uv_handle_t*)check, (uv_close_cb)free);+}++int hs_set_socket_reuse(uv_stream_t* server) {+#if (SO_REUSEPORT_LOAD_BALANCE == 1)+    int yes = 1;+    if (setsockopt(server->io_watcher.fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))+        return uv_translate_sys_error(errno);+    return 0;+#else+    return 0;+#endif+}
+ cbits/text.c view
@@ -0,0 +1,290 @@+#include <text.h>+#include <stdint.h>+#include <utf8rewind.h>+#include <codepoint.h>++#ifdef __SSE2__+#include <simdasciicheck.h>+#include <simdutf8check.h>+#endif++HsInt ascii_validate(const char* p, HsInt off, HsInt len){+    const char* q = p + off;+#ifdef __AVX2__+    return (HsInt)validate_ascii_fast_avx(q, (size_t)len);+#else+#ifdef __SSE2__+    return (HsInt)validate_ascii_fast(q, (size_t)len);+#else+    return (HsInt)ascii_u64(q, (size_t)len);+#endif+#endif+}+// for some reason unknown, on windows we have to supply a seperated version of ascii_validate+// otherwise we got segfault if we import the same FFI with different type (Addr# vs ByteArray#)+HsInt ascii_validate_addr(const char* p, HsInt len){+#ifdef __AVX2__+    return (HsInt)validate_ascii_fast_avx(p, (size_t)len);+#else+#ifdef __SSE2__+    return (HsInt)validate_ascii_fast(p, (size_t)len);+#else+    return (HsInt)ascii_u64(p, (size_t)len);+#endif+#endif+}++HsInt utf8_validate(const char* p, HsInt off, HsInt len){+    const char* q = p + off;+#ifdef __AVX2__+    return (HsInt)validate_utf8_fast_avx(q, (size_t)len);+#else+#ifdef __SSE2__+    return (HsInt)validate_utf8_fast(q, (size_t)len);+#else+    return utf8_validate_slow(q, (size_t)len);+#endif+#endif+}+// for some reason unknown, on windows we have to supply a seperated version of utf8_validate+// otherwise we got segfault if we import the same FFI with different type (Addr# vs ByteArray#)+HsInt utf8_validate_addr(const char* p, HsInt len){+#ifdef __AVX2__+    return (HsInt)validate_utf8_fast_avx(p, (size_t)len);+#else+#ifdef __SSE2__+    return (HsInt)validate_utf8_fast(p, (size_t)len);+#else+    return utf8_validate_slow(p, (size_t)len);+#endif+#endif+}++////////////////////////////////////////////////////////////////////////////////++static inline int ascii_u64(const uint8_t *data, size_t len)+{+    uint8_t orall = 0;++    if (len >= 16) {++        uint64_t or1 = 0, or2 = 0;+        const uint8_t *data2 = data+8;++        do {+            or1 |= *(const uint64_t *)data;+            or2 |= *(const uint64_t *)data2;+            data += 16;+            data2 += 16;+            len -= 16;+        } while (len >= 16);++        /*+         * Idea from Benny Halevy <bhalevy@scylladb.com>+         * - 7-th bit set   ==> orall = !(non-zero) - 1 = 0 - 1 = 0xFF+         * - 7-th bit clear ==> orall = !0 - 1          = 1 - 1 = 0x00+         */+        orall = !((or1 | or2) & 0x8080808080808080ULL) - 1;+    }++    while (len--)+        orall |= *data++;++    return orall < 0x80;+}++////////////////////////////////////////////////////////////////////////////////++#define UTF8_ACCEPT 0+#define UTF8_REJECT 1++static const uint8_t utf8d[] = {+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 00..1f+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20..3f+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 40..5f+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 60..7f+    1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,+    1,   1,   1,   1,   1,   9,   9,   9,   9,   9,   9,+    9,   9,   9,   9,   9,   9,   9,   9,   9,   9, // 80..9f+    7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7,+    7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7,+    7,   7,   7,   7,   7,   7,   7,   7,   7,   7, // a0..bf+    8,   8,   2,   2,   2,   2,   2,   2,   2,   2,   2,+    2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,+    2,   2,   2,   2,   2,   2,   2,   2,   2,   2, // c0..df+    0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3,+    0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef+    0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,+    0x8, 0x8, 0x8, 0x8, 0x8 // f0..ff+};++static const uint8_t utf8d_transition[] = {+    0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4,+    0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0+    1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,+    1,   1,   1,   1,   1,   1,   0,   1,   1,   1,   1,+    1,   0,   1,   0,   1,   1,   1,   1,   1,   1, // s1..s2+    1,   2,   1,   1,   1,   1,   1,   2,   1,   2,   1,+    1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,+    1,   2,   1,   1,   1,   1,   1,   1,   1,   1, // s3..s4+    1,   2,   1,   1,   1,   1,   1,   1,   1,   2,   1,+    1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,+    1,   3,   1,   3,   1,   1,   1,   1,   1,   1, // s5..s6+    1,   3,   1,   1,   1,   1,   1,   3,   1,   3,   1,+    1,   1,   1,   1,   1,   1,   3,   1,   1,   1,   1,+    1,   1,   1,   1,   1,   1,   1,   1,   1,   1, // s7..s8+};++static uint32_t inline updatestate(uint32_t *state, uint32_t byte) {+    uint32_t type = utf8d[byte];+    *state = utf8d_transition[16 * *state + type];+    return *state;+}++HsInt utf8_validate_slow(const char* c, size_t len){+    const unsigned char *cu = (const unsigned char *)c;+    uint32_t state = 0;+    for (size_t i = 0; i < len; i++) {+        uint32_t byteval = (uint32_t)cu[i];+        if (updatestate(&state, byteval) == UTF8_REJECT)+            return 0;+    }+    return 1;+}++HsInt utf8_isnormalized(const char* p, HsInt off, HsInt len, size_t flag){+    size_t offset;+    return (HsInt)utf8isnormalized(p+off, len, flag, &offset);+}++HsInt utf8_normalize(const char* p, HsInt off, HsInt len, char* q, HsInt len2, size_t flag){+    size_t converted_size;+    int32_t errors;+    if ((converted_size = utf8normalize(p+off, len, q, len2, flag, &errors)) == 0 ||+        errors != UTF8_ERR_NONE)+    {+        return -1;+    } else {+        return converted_size;+    }+}++HsInt utf8_normalize_length(const char* p, HsInt off, HsInt len, size_t flag){+    size_t converted_size;+    int32_t errors;+    if ((converted_size = utf8normalize(p+off, len, NULL, 0, flag, &errors)) == 0 ||+        errors != UTF8_ERR_NONE)+    {+        return -1;+    } else {+        return converted_size;+    }+}++HsInt utf8_casefold(const char* p, HsInt off, HsInt len, char* q, HsInt len2, size_t locale){+    size_t converted_size;+    int32_t errors;+    if ((converted_size = utf8casefold(p+off, len, q, len2, locale, &errors)) == 0 ||+        errors != UTF8_ERR_NONE)+    {+        return -1;+    } else {+        return converted_size;+    }+}++HsInt utf8_casefold_length(const char* p, HsInt off, HsInt len, size_t locale){+    size_t converted_size;+    int32_t errors;+    if ((converted_size = utf8casefold(p+off, len, NULL, 0, locale, &errors)) == 0 ||+        errors != UTF8_ERR_NONE)+    {+        return -1;+    } else {+        return converted_size;+    }+}++HsInt utf8_tolower(const char* p, HsInt off, HsInt len, char* q, HsInt len2, size_t locale){+    size_t converted_size;+    int32_t errors;+    if ((converted_size = utf8tolower(p+off, len, q, len2, locale, &errors)) == 0 ||+        errors != UTF8_ERR_NONE)+    {+        return -1;+    } else {+        return converted_size;+    }+}++HsInt utf8_tolower_length(const char* p, HsInt off, HsInt len, size_t locale){+    size_t converted_size;+    int32_t errors;+    if ((converted_size = utf8tolower(p+off, len, NULL, 0, locale, &errors)) == 0 ||+        errors != UTF8_ERR_NONE)+    {+        return -1;+    } else {+        return converted_size;+    }+}++HsInt utf8_toupper(const char* p, HsInt off, HsInt len, char* q, HsInt len2, size_t locale){+    size_t converted_size;+    int32_t errors;+    if ((converted_size = utf8toupper(p+off, len, q, len2, locale, &errors)) == 0 ||+        errors != UTF8_ERR_NONE)+    {+        return -1;+    } else {+        return converted_size;+    }+}++HsInt utf8_toupper_length(const char* p, HsInt off, HsInt len, size_t locale){+    size_t converted_size;+    int32_t errors;+    if ((converted_size = utf8toupper(p+off, len, NULL, 0, locale, &errors)) == 0 ||+        errors != UTF8_ERR_NONE)+    {+        return -1;+    } else {+        return converted_size;+    }+}++HsInt utf8_totitle(const char* p, HsInt off, HsInt len, char* q, HsInt len2, size_t locale){+    size_t converted_size;+    int32_t errors;+    if ((converted_size = utf8totitle(p+off, len, q, len2, locale, &errors)) == 0 ||+        errors != UTF8_ERR_NONE)+    {+        return -1;+    } else {+        return converted_size;+    }+}++HsInt utf8_totitle_length(const char* p, HsInt off, HsInt len, size_t locale){+    size_t converted_size;+    int32_t errors;+    if ((converted_size = utf8totitle(p+off, len, NULL, 0, locale, &errors)) == 0 ||+        errors != UTF8_ERR_NONE)+    {+        return -1;+    } else {+        return converted_size;+    }+}++HsInt utf8_iscategory(const char* p, HsInt off, HsInt len, size_t flags){+    return (HsInt)utf8iscategory(p+off, len, flags);+}
+ include/bytes.h view
@@ -0,0 +1,37 @@+/*+ * Copyright (c) 2017-2018 Dong Han+ *+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the names of the authors or the names of any contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */++#include <stdint.h>+#include <string.h>+#include <Rts.h>++HsInt hs_memchr(uint8_t *a, HsInt aoff, uint8_t b, HsInt n);+HsInt hs_fnv_hash_addr(const unsigned char* str, HsInt len, HsInt salt);+HsInt hs_fnv_hash(const unsigned char* str, HsInt offset, HsInt len, HsInt salt);
+ include/dtoa.h view
@@ -0,0 +1,34 @@+/*+ * Copyright (c) 2017-2019 Dong Han+ *+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the names of the authors or the names of any contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */++#include <Rts.h>++HsInt grisu3(double v, char *buffer, HsInt *length, HsInt *d_exp);+HsInt grisu3_sp(float v, char *buffer, HsInt *length, HsInt *d_exp);
+ include/hs_uv.h view
@@ -0,0 +1,629 @@+/*+ * Copyright (c) 2017-2018 Dong Han+ *+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the names of the authors or the names of any contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */++#include <uv.h>+#include <assert.h>+#include <HsFFI.h>  // for HsInt+#include <stdlib.h> // for malloc, free, etc.+#include <string.h> // for fs path++#if !defined(_WIN32)++#if defined(__sun)+# include <sys/port.h>+# include <port.h>+#endif /* __sun */++#if defined(_AIX)+# define reqevents events+# define rtnevents revents+# include <sys/poll.h>+#else+# include <poll.h>+#endif /* _AIX */++#include <dirent.h>++#endif /* _WIN32 */++////////////////////////////////////////////////////////////////////////////////+// CONSTANT+#define ACCEPT_BUFFER_SIZE 1024+#define INIT_LOOP_SIZE 128+#define INIT_LOOP_SIZE_BIT 7++#if defined(__linux__) && defined(SO_REUSEPORT)+#define SO_REUSEPORT_LOAD_BALANCE 1+#else+#define SO_REUSEPORT_LOAD_BALANCE 0+#endif++// this function will be a noop when SO_REUSEPORT_LOAD_BALANCE == 0+int hs_set_socket_reuse(uv_stream_t* server);++////////////////////////////////////////////////////////////////////////////////+// error handling+int uv_translate_sys_error(int sys_errno);++////////////////////////////////////////////////////////////////////////////////+// loop+//+// the memory pool item struct, we use the largest possible value,+// except uv_getnameinfo_t, which is too large than average :(+//+// following size data is from libuv v1.12, in bytes+//                         win  unix+// uv_timer_t        : 160  152+// uv_prepare_t      : 120  120+// uv_check_t        : 120  120+// uv_idle_t         : 120  120+// uv_async_t        : 224  128+// uv_poll_t         : 416  160+// uv_signal_t       : 264  152+// uv_process_t      : 264  136+// uv_tcp_t          : 320  248+// uv_pipe_t         : 576  264+// uv_tty_t          : 344  312+// uv_udp_t          : 424  216+// uv_fs_event_t     : 272  136+// uv_fs_poll_t      : 104  104+// uv_req_t          : 112  64+// uv_getaddrinfo_t  : 216  160+// uv_getnameinfo_t  : 1368 1320  !too large+// uv_shutdown_t     : 128  80+// uv_write_t        : 176  192+// uv_connect_t      : 128  96+// uv_udp_send_t     : 128  320+// uv_fs_t           : 456  440+// uv_work_t         : 176  128+typedef union {+    uv_timer_t          timer_t      ;+    uv_prepare_t        prepare_t    ;+    uv_check_t          check_t      ;+    uv_idle_t           idle_t       ;+    uv_async_t          async_t      ;+    uv_poll_t           poll_t       ;+    uv_signal_t         signal_t     ;+    uv_process_t        process_t    ;+    uv_tcp_t            tcp_t        ;+    uv_pipe_t           pipe_t       ;+    uv_tty_t            tty_t        ;+    uv_udp_t            udp_t        ;+    uv_fs_event_t       fs_event_t   ;+    uv_fs_poll_t        fs_poll_t    ;+    uv_req_t            req_t        ;+    uv_getaddrinfo_t    getaddrinfo_t;+//   uv_getnameinfo_t    getnameinfo_t; !too large+    uv_shutdown_t       shutdown_t   ;+    uv_write_t          write_t      ;+    uv_connect_t        connect_t    ;+    uv_udp_send_t       udp_send_t   ;+    uv_fs_t             fs_t         ;+    uv_work_t           work_t       ;+} hs_uv_struct;++typedef struct {+    // following two fields record events during uv_run, inside callback which+    // wants to record a event, push the handler's slot into the queue+    HsInt   event_counter;+    HsInt*  event_queue;+    // following two fields provide buffers allocated in haskell to uv_alloc_cb,+    // the buffer_size_table are also used to record operation's result+    char**  buffer_table;+    HsInt*  buffer_size_table;+    // following fields are used to implemented a stable slot allocator+    // see note below+    HsInt*  slot_table;+    HsInt   free_slot;+    HsInt*  free_slot_queue;+    HsInt   free_slot_counter;+    // uv_struct_table field is a memory pool for uv_handle_t / uv_req_t struct,+    // see note below+    hs_uv_struct**  uv_struct_table;+    HsInt   size;+    size_t  resize;+    // following fields are handlers used to wake up event loop under threaded and+    // non-threaded RTS respectively.+    uv_async_t* async;+    uv_timer_t* timer;+} hs_loop_data;+// Note: the slot allocator+//+// we used to do slot allocation in haskell, but doing it in C allow us to free slot+// in the right place, e.g. uv_close_cb. The allocator use the same algorithm with+// ghc's stable pointer table. When initialized, it's looked like:+//+//  slot_table->[0][1][2][3]...[INIT_LOOP_SIZE-1]+//               |  |  |  |+//              =1 =2 =3 =4 ...+//  free_slot = 0+//+// Every time we allocate a slot, we return current free_slot, and set the free_slot to+// slot_table[free_slot], so after 3 allocation, it's looked like+//+//  slot_table->[0][1][2][3]...[INIT_LOOP_SIZE-1]+//               |  |  |  |+//              =1 =2 =3 =4 ...+//  free_slot = 3+//+// When we free slot x, we set slot_table[x] to current free_slot, and free_slot+// to x. Now let's say we return slot 1, it will be looked like+//+//  slot_table->[0][1][2][3]...[INIT_LOOP_SIZE-1]+//               |  |  |  |+//              =1 =3 =3 =4 ...+//  free_slot = 1+//+// Next time allocation will give 1 back to us, and free_slot will continue point to 3.+//+// But in practice, we never directly return a free slot back to slot_table, because+// the haskell thread allocating slot may be paused by RTS before its takeMVar parking its+// TSO since parking itself need an allocation. Now if uv_run fired its callback and +// free the slot, next registration will got the same slot, and mess up with previous+// haskell thread. In order to solve this race condition, we free a slot in two steps:+//+// 1. free_slot will first push slot to free_slot_queue, and increase free_slot_counter.+// 2. before uv_run we loop through this queue and put these free slots back to slot_table.+//+// With this scheme, slots will be held one scheduler loop longer, thus ensure the haskell+// thread can successfully wait on its 'MVar', and in turn make sure it will be resumed.+//+////////////////////////////////////////////////////////////////////////////////+//+// Note: uv_handle_t/uv_req_t memory pool+//+// The reasons to use a memory pool for uv structs are:+//+// 1. A malloc/free per request is inefficient.+// 2. It's diffcult to manange if we use haskell heap(pinned).+// 3. uv structs are small mostly.+//+// The memory pool is grow on demand, when initialized, it's looked like:+//+// uv_struct_table [0]+//                  |+//                  V+//      struct_block[INIT_LOOP_SIZE]+//+// After several loop data resize, it will be looked like:+//+// uv_struct_table [0]                [1]                [2] ...+//                  |                  |                  |+//                  V                  |                  |+//      struct_block[INIT_LOOP_SIZE]   V                  |+//                        struct_block[INIT_LOOP_SIZE]    V+//                                            struct_block[INIT_LOOP_SIZE*2]+//                                                                            .+//                                                                            .+//                                                                            .+// That is, we keep the total number of items sync with loop->data->size, while+// not touching previously allocated blocks, so that the structs are never moved.+//+// Check fetch_uv_struct below to see how do we get struct's address by slot.++uv_loop_t* hs_uv_loop_init(HsInt siz);+void hs_uv_loop_close(uv_loop_t* loop);+HsInt alloc_slot(hs_loop_data* loop_data);+void free_slot(hs_loop_data* loop_data, HsInt slot);+hs_uv_struct* fetch_uv_struct(hs_loop_data* loop_data, HsInt slot);+int hs_uv_run(uv_loop_t* loop, uv_run_mode mode);++////////////////////////////////////////////////////////////////////////////////+// wake up+int hs_uv_wake_up_timer(hs_loop_data* loop_data);+int hs_uv_wake_up_async(hs_loop_data* loop_data);++////////////////////////////////////////////////////////////////////////////////+// handle+uv_handle_t* hs_uv_handle_alloc(uv_loop_t* loop);+void hs_uv_handle_free(uv_handle_t* handle);+void hs_uv_handle_close(uv_handle_t* handle);++////////////////////////////////////////////////////////////////////////////////+// request+void hs_uv_cancel(uv_loop_t* loop, HsInt slot);++////////////////////////////////////////////////////////////////////////////////+// stream+int hs_uv_listen(uv_stream_t* stream, int backlog);+void hs_uv_listen_resume(uv_stream_t* server);+int hs_uv_read_start(uv_stream_t* handle);+HsInt hs_uv_write(uv_stream_t* handle, char* buf, HsInt buf_size);+uv_check_t* hs_uv_accept_check_alloc(uv_stream_t* server);+int hs_uv_accept_check_init(uv_check_t* check);+void hs_uv_accept_check_close(uv_check_t* check);++////////////////////////////////////////////////////////////////////////////////+// tcp+int hs_uv_tcp_open(uv_tcp_t* handle, int sock);+HsInt hs_uv_tcp_connect(uv_tcp_t* handle, const struct sockaddr* addr);++#if defined(_WIN32)+#define UV_HANDLE_READING                       0x00000100+#define UV_HANDLE_BOUND                         0x00000200+#define UV_HANDLE_LISTENING                     0x00000800+#define UV_HANDLE_CONNECTION                    0x00001000+#define UV_HANDLE_READABLE                      0x00008000+#define UV_HANDLE_WRITABLE                      0x00010000+enum {+  UV__SIGNAL_ONE_SHOT = 0x80000,  /* On signal reception remove sighandler */+  UV__HANDLE_INTERNAL = 0x8000,+  UV__HANDLE_ACTIVE   = 0x4000,+  UV__HANDLE_REF      = 0x2000,+  UV__HANDLE_CLOSING  = 0 /* no-op on unix */+};+#define UV_HANDLE_TCP_SINGLE_ACCEPT             0x08000000+#define UV_HANDLE_TCP_ACCEPT_STATE_CHANGING     0x10000000+extern unsigned int uv_simultaneous_server_accepts;+extern void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req);+#else+void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events);+#endif++////////////////////////////////////////////////////////////////////////////////+// fs++// we define file open flag here for compatibility on libuv < v1.16+// see https://github.com/libuv/libuv/commit/4b666bd2d82a51f1c809b2703a91679789c1ec01#diff-a5e63f9b16ca783355e2d83941c3eafb++#if defined(_WIN32)++/* fs open() flags supported on this platform: */+#ifndef UV_FS_O_APPEND+#define UV_FS_O_APPEND       _O_APPEND+#endif+#ifndef UV_FS_O_CREAT+#define UV_FS_O_CREAT        _O_CREAT+#endif+#ifndef UV_FS_O_EXCL+#define UV_FS_O_EXCL         _O_EXCL+#endif+#ifndef UV_FS_O_RANDOM+#define UV_FS_O_RANDOM       _O_RANDOM+#endif+#ifndef UV_FS_O_RDONLY+#define UV_FS_O_RDONLY       _O_RDONLY+#endif+#ifndef UV_FS_O_RDWR+#define UV_FS_O_RDWR         _O_RDWR+#endif+#ifndef UV_FS_O_SEQUENTIAL+#define UV_FS_O_SEQUENTIAL   _O_SEQUENTIAL+#endif+#ifndef UV_FS_O_SHORT_LIVED+#define UV_FS_O_SHORT_LIVED  _O_SHORT_LIVED+#endif+#ifndef UV_FS_O_TEMPORARY+#define UV_FS_O_TEMPORARY    _O_TEMPORARY+#endif+#ifndef UV_FS_O_TRUNC+#define UV_FS_O_TRUNC        _O_TRUNC+#endif+#ifndef UV_FS_O_WRONLY+#define UV_FS_O_WRONLY       _O_WRONLY+#endif++/* fs open() flags supported on other platforms (or mapped on this platform): */+#ifndef UV_FS_O_DIRECT+#define UV_FS_O_DIRECT       0x2000000 /* FILE_FLAG_NO_BUFFERING */+#endif+#ifndef UV_FS_O_DIRECTORY+#define UV_FS_O_DIRECTORY    0+#endif+#ifndef UV_FS_O_DSYNC+#define UV_FS_O_DSYNC        0x4000000 /* FILE_FLAG_WRITE_THROUGH */+#endif+#ifndef UV_FS_O_EXLOCK+#define UV_FS_O_EXLOCK       0+#endif+#ifndef UV_FS_O_NOATIME+#define UV_FS_O_NOATIME      0+#endif+#ifndef UV_FS_O_NOCTTY+#define UV_FS_O_NOCTTY       0+#endif+#ifndef UV_FS_O_NOFOLLOW+#define UV_FS_O_NOFOLLOW     0+#endif+#ifndef UV_FS_O_NONBLOCK+#define UV_FS_O_NONBLOCK     0+#endif+#ifndef UV_FS_O_SYMLINK+#define UV_FS_O_SYMLINK      0+#endif+#ifndef UV_FS_O_SYNC+#define UV_FS_O_SYNC         0x8000000 /* FILE_FLAG_WRITE_THROUGH */+#endif++#else /* _WIN32 */++#ifndef UV_FS_O_APPEND+#if defined(O_APPEND)+# define UV_FS_O_APPEND       O_APPEND+#else+# define UV_FS_O_APPEND       0+#endif+#endif+#ifndef UV_FS_O_CREAT+#if defined(O_CREAT)+# define UV_FS_O_CREAT        O_CREAT+#else+# define UV_FS_O_CREAT        0+#endif+#endif+#ifndef UV_FS_O_DIRECT+#if defined(O_DIRECT)+# define UV_FS_O_DIRECT       O_DIRECT+#else+# define UV_FS_O_DIRECT       0+#endif+#endif+#ifndef UV_FS_O_DIRECTORY+#if defined(O_DIRECTORY)+# define UV_FS_O_DIRECTORY    O_DIRECTORY+#else+# define UV_FS_O_DIRECTORY    0+#endif+#endif+#ifndef UV_FS_O_DSYNC+#if defined(O_DSYNC)+# define UV_FS_O_DSYNC        O_DSYNC+#else+# define UV_FS_O_DSYNC        0+#endif+#endif+#ifndef UV_FS_O_EXCL+#if defined(O_EXCL)+# define UV_FS_O_EXCL         O_EXCL+#else+# define UV_FS_O_EXCL         0+#endif+#endif+#ifndef UV_FS_O_EXLOCK+#if defined(O_EXLOCK)+# define UV_FS_O_EXLOCK       O_EXLOCK+#else+# define UV_FS_O_EXLOCK       0+#endif+#endif+#ifndef UV_FS_O_NOATIME+#if defined(O_NOATIME)+# define UV_FS_O_NOATIME      O_NOATIME+#else+# define UV_FS_O_NOATIME      0+#endif+#endif+#ifndef UV_FS_O_NOCTTY+#if defined(O_NOCTTY)+# define UV_FS_O_NOCTTY       O_NOCTTY+#else+# define UV_FS_O_NOCTTY       0+#endif+#endif+#ifndef UV_FS_O_NOFOLLOW+#if defined(O_NOFOLLOW)+# define UV_FS_O_NOFOLLOW     O_NOFOLLOW+#else+# define UV_FS_O_NOFOLLOW     0+#endif+#endif+#ifndef UV_FS_O_NONBLOCK+#if defined(O_NONBLOCK)+# define UV_FS_O_NONBLOCK     O_NONBLOCK+#else+# define UV_FS_O_NONBLOCK     0+#endif+#endif+#ifndef UV_FS_O_RDONLY+#if defined(O_RDONLY)+# define UV_FS_O_RDONLY       O_RDONLY+#else+# define UV_FS_O_RDONLY       0+#endif+#endif+#ifndef UV_FS_O_RDWR+#if defined(O_RDWR)+# define UV_FS_O_RDWR         O_RDWR+#else+# define UV_FS_O_RDWR         0+#endif+#endif+#ifndef UV_FS_O_SYMLINK+#if defined(O_SYMLINK)+# define UV_FS_O_SYMLINK      O_SYMLINK+#else+# define UV_FS_O_SYMLINK      0+#endif+#endif+#ifndef UV_FS_O_SYNC+#if defined(O_SYNC)+# define UV_FS_O_SYNC         O_SYNC+#else+# define UV_FS_O_SYNC         0+#endif+#endif+#ifndef UV_FS_O_TRUNC+#if defined(O_TRUNC)+# define UV_FS_O_TRUNC        O_TRUNC+#else+# define UV_FS_O_TRUNC        0+#endif+#endif+#ifndef UV_FS_O_WRONLY+#if defined(O_WRONLY)+# define UV_FS_O_WRONLY       O_WRONLY+#else+# define UV_FS_O_WRONLY       0+#endif+#endif++/* fs open() flags supported on other platforms: */+#ifndef UV_FS_O_RANDOM+#define UV_FS_O_RANDOM        0+#endif+#ifndef UV_FS_O_SHORT_LIVED+#define UV_FS_O_SHORT_LIVED   0+#endif+#ifndef UV_FS_O_SEQUENTIAL+#define UV_FS_O_SEQUENTIAL    0+#endif+#ifndef UV_FS_O_TEMPORARY+#define UV_FS_O_TEMPORARY     0+#endif++#endif /* _WIN32 */++typedef uv__dirent_t hs_uv__dirent_t;++#if defined(_WIN32)++#define HAVE_DIRENT_TYPES+#define UV__DT_DIR     UV_DIRENT_DIR+#define UV__DT_FILE    UV_DIRENT_FILE+#define UV__DT_LINK    UV_DIRENT_LINK+#define UV__DT_FIFO    UV_DIRENT_FIFO+#define UV__DT_SOCKET  UV_DIRENT_SOCKET+#define UV__DT_CHAR    UV_DIRENT_CHAR+#define UV__DT_BLOCK   UV_DIRENT_BLOCK++#else /* _WIN32 */++#if defined(DT_UNKNOWN)+# define HAVE_DIRENT_TYPES+# if defined(DT_REG)+#  define UV__DT_FILE DT_REG+# else+#  define UV__DT_FILE -1+# endif+# if defined(DT_DIR)+#  define UV__DT_DIR DT_DIR+# else+#  define UV__DT_DIR -2+# endif+# if defined(DT_LNK)+#  define UV__DT_LINK DT_LNK+# else+#  define UV__DT_LINK -3+# endif+# if defined(DT_FIFO)+#  define UV__DT_FIFO DT_FIFO+# else+#  define UV__DT_FIFO -4+# endif+# if defined(DT_SOCK)+#  define UV__DT_SOCKET DT_SOCK+# else+#  define UV__DT_SOCKET -5+# endif+# if defined(DT_CHR)+#  define UV__DT_CHAR DT_CHR+# else+#  define UV__DT_CHAR -6+# endif+# if defined(DT_BLK)+#  define UV__DT_BLOCK DT_BLK+# else+#  define UV__DT_BLOCK -7+# endif+#endif /* DT_UNKNOWN */++#endif /* _WIN32 */+++#if defined(_WIN32)+void uv__free(void* p);+# define uv__fs_scandir_free uv__free+#else /* _WIN32 */+# define uv__fs_scandir_free free+#endif /* _WIN32 */++void hs_uv_fs_scandir_cleanup(uv_dirent_t** dents, HsInt n);+void hs_uv_fs_scandir_extra_cleanup(uv_dirent_t*** dents_p, HsInt n);+void hs_uv_fs_readlink_extra_cleanup(char** path);+void hs_uv_fs_readlink_cleanup(char* path);++////////////////////////////////////////////////////////////////////////////////+// fs, none thread pool version+int32_t hs_uv_fs_open(const char* path, int flags, int mode);+HsInt hs_uv_fs_close(int32_t file);+HsInt hs_uv_fs_read(int32_t file, char* buffer, HsInt buffer_size, int64_t offset);+HsInt hs_uv_fs_write(int32_t file, char* buffer, HsInt buffer_size, int64_t offset);+HsInt hs_uv_fs_unlink(const char* path);+HsInt hs_uv_fs_mkdir(const char* path, int mode);+HsInt hs_uv_fs_mkdtemp(const char* tpl, HsInt tpl_size, char* temp_path);+HsInt hs_uv_fs_rmdir(const char* path);+HsInt hs_uv_fs_scandir(const char* path, uv_dirent_t*** dents);+HsInt hs_uv_fs_stat(const char* path, uv_stat_t* stat);+HsInt hs_uv_fs_fstat(int32_t file, uv_stat_t* stat);+HsInt hs_uv_fs_lstat(const char* path, uv_stat_t* stat);+HsInt hs_uv_fs_rename(const char* path, const char* path2);+HsInt hs_uv_fs_fsync(int32_t file);+HsInt hs_uv_fs_fdatasync(int32_t file);+HsInt hs_uv_fs_ftruncate(int32_t file, int64_t off);+HsInt hs_uv_fs_copyfile(const char* path, const char* path2, int flag);+HsInt hs_uv_fs_access(const char* path, int mode);+HsInt hs_uv_fs_chmod(const char* path, int mode);+HsInt hs_uv_fs_fchmod(int32_t file, int mode);+HsInt hs_uv_fs_utime(const char* path, double atime, double mtime);+HsInt hs_uv_fs_futime(int32_t file, double atime, double mtime);+HsInt hs_uv_fs_link(const char* path, const char* path2);+HsInt hs_uv_fs_symlink(const char* path, const char* path2, int flag);+HsInt hs_uv_fs_readlink(const char* path, char** result_path);+HsInt hs_uv_fs_realpath(const char* path, char** result_path);+++////////////////////////////////////////////////////////////////////////////////+// fs, thread pool version+HsInt hs_uv_fs_open_threaded(const char* path, int flags, int mode, uv_loop_t* loop);+HsInt hs_uv_fs_close_threaded(int32_t file, uv_loop_t* loop);+HsInt hs_uv_fs_read_threaded(int32_t file, char* buffer, HsInt buffer_size, int64_t offset, uv_loop_t* loop);+HsInt hs_uv_fs_write_threaded(int32_t file, char* buffer, HsInt buffer_size, int64_t offset, uv_loop_t* loop);+HsInt hs_uv_fs_unlink_threaded(const char* path, uv_loop_t* loop);+HsInt hs_uv_fs_mkdir_threaded(const char* path, int mode, uv_loop_t* loop);+HsInt hs_uv_fs_mkdtemp_threaded(const char* tpl, HsInt tpl_size, char* temp_path, uv_loop_t* loop);+HsInt hs_uv_fs_rmdir_threaded(const char* path, uv_loop_t* loop);+HsInt hs_uv_fs_scandir_threaded(const char* path, uv_dirent_t*** dents, uv_loop_t* loop);+HsInt hs_uv_fs_stat_threaded(const char* path, uv_stat_t* stat, uv_loop_t* loop);+HsInt hs_uv_fs_fstat_threaded(int32_t file, uv_stat_t* stat, uv_loop_t* loop);+HsInt hs_uv_fs_lstat_threaded(const char* path, uv_stat_t* stat, uv_loop_t* loop);+HsInt hs_uv_fs_rename_threaded(const char* path, const char* path2, uv_loop_t* loop);+HsInt hs_uv_fs_fsync_threaded(int32_t file, uv_loop_t* loop);+HsInt hs_uv_fs_fdatasync_threaded(int32_t file, uv_loop_t* loop);+HsInt hs_uv_fs_ftruncate_threaded(int32_t file, int64_t off, uv_loop_t* loop);+HsInt hs_uv_fs_copyfile_threaded(const char* path, const char* path2, int flag, uv_loop_t* loop);+HsInt hs_uv_fs_access_threaded(const char* path, int mode, uv_loop_t* loop);+HsInt hs_uv_fs_chmod_threaded(const char* path, int mode, uv_loop_t* loop);+HsInt hs_uv_fs_fchmod_threaded(int32_t file, int mode, uv_loop_t* loop);+HsInt hs_uv_fs_utime_threaded(const char* path, double atime, double mtime, uv_loop_t* loop);+HsInt hs_uv_fs_futime_threaded(int32_t file, double atime, double mtime, uv_loop_t* loop);+HsInt hs_uv_fs_link_threaded(const char* path, const char* path2, uv_loop_t* loop);+HsInt hs_uv_fs_symlink_threaded(const char* path, const char* path2, int flag, uv_loop_t* loop);+HsInt hs_uv_fs_readlink_threaded(const char* path, char** result_path, uv_loop_t* loop);+HsInt hs_uv_fs_realpath_threaded(const char* path, char** result_path, uv_loop_t* loop);
+ include/text.h view
@@ -0,0 +1,55 @@+/*+ * Copyright (c) 2017-2018 Dong Han+ *+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the names of the authors or the names of any contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */++#include <Rts.h>++HsInt ascii_validate(const char* p, HsInt off, HsInt len);+HsInt ascii_validate_addr(const char* p, HsInt len);+HsInt utf8_validate(const char* p, HsInt off, HsInt len);+HsInt utf8_validate_addr(const char* p, HsInt len);++HsInt utf8_isnormalized(const char* p, HsInt off, HsInt len, size_t flag);+HsInt utf8_normalize(const char* p, HsInt off, HsInt len, char* q, HsInt len2, size_t flag);+HsInt utf8_normalize_length(const char* p, HsInt off, HsInt len, size_t flag);+++HsInt utf8_casefold(const char* p, HsInt off, HsInt len, char* q, HsInt len2, size_t locale);+HsInt utf8_casefold_length(const char* p, HsInt off, HsInt len, size_t locale);++HsInt utf8_tolower(const char* p, HsInt off, HsInt len, char* q, HsInt len2, size_t locale);+HsInt utf8_tolower_length(const char* p, HsInt off, HsInt len, size_t locale);++HsInt utf8_toupper(const char* p, HsInt off, HsInt len, char* q, HsInt len2, size_t locale);+HsInt utf8_toupper_length(const char* p, HsInt off, HsInt len, size_t locale);++HsInt utf8_totitle(const char* p, HsInt off, HsInt len, char* q, HsInt len2, size_t locale);+HsInt utf8_totitle_length(const char* p, HsInt off, HsInt len, size_t locale);++HsInt utf8_iscategory(const char* p, HsInt off, HsInt len, size_t flags);
+ stdio.cabal view
@@ -0,0 +1,350 @@+name:                stdio+version:             0.1.0.0+synopsis:            A simple and high performance IO toolkit for Haskell+description:         This package provides a simple and high performance IO toolkit for Haskell, including+                     packed vectors, unicode texts, socket, file system, timers and more!+license:             BSD3+license-file:        LICENSE+author:              Dong Han, Tao He+maintainer:          winterland1989@gmail.com+copyright:           (c) Dong Han, 2017-2018+                     (c) Tao He, 2017-2019+category:            Data+build-type:          Simple+cabal-version:       >=1.10+homepage:            https://github.com/haskell-stdio/stdio+bug-reports:         https://github.com/haskell-stdio/stdio/issues++extra-source-files:  ChangeLog.md+                     README.md+                     LICENSE++                     include/bytes.h+                     include/dtoa.h+                     include/hs_uv.h+                     include/text.h+                     cbits/bytes.c+                     cbits/dtoa.c+                     cbits/hs_uv_base.c+                     cbits/hs_uv_stream.c+                     cbits/hs_uv_file.c+                     cbits/text.c++                     -- libuv C sources (for Windows)+                     third_party/libuv/include/uv.h+                     third_party/libuv/include/uv/win.h+                     third_party/libuv/include/uv/tree.h+                     third_party/libuv/include/uv/errno.h+                     third_party/libuv/include/uv/threadpool.h+                     third_party/libuv/include/uv/version.h+                     third_party/libuv/include/uv/stdint-msvc2008.h++                     third_party/libuv/src/fs-poll.c +                     third_party/libuv/src/heap-inl.h +                     third_party/libuv/src/idna.c +                     third_party/libuv/src/idna.h+                     third_party/libuv/src/inet.c +                     third_party/libuv/src/queue.h +                     third_party/libuv/src/strscpy.c +                     third_party/libuv/src/strscpy.h +                     third_party/libuv/src/threadpool.c +                     third_party/libuv/src/timer.c +                     third_party/libuv/src/uv-common.c +                     third_party/libuv/src/uv-common.h +                     third_party/libuv/src/uv-data-getter-setters.c +                     third_party/libuv/src/version.c++                     third_party/libuv/src/win/async.c +                     third_party/libuv/src/win/atomicops-inl.h +                     third_party/libuv/src/win/core.c +                     third_party/libuv/src/win/detect-wakeup.c +                     third_party/libuv/src/win/dl.c +                     third_party/libuv/src/win/error.c +                     third_party/libuv/src/win/fs.c +                     third_party/libuv/src/win/fs-event.c +                     third_party/libuv/src/win/getaddrinfo.c +                     third_party/libuv/src/win/getnameinfo.c +                     third_party/libuv/src/win/handle.c +                     third_party/libuv/src/win/handle-inl.h +                     third_party/libuv/src/win/internal.h +                     third_party/libuv/src/win/loop-watcher.c +                     third_party/libuv/src/win/pipe.c +                     third_party/libuv/src/win/poll.c +                     third_party/libuv/src/win/process.c +                     third_party/libuv/src/win/process-stdio.c +                     third_party/libuv/src/win/req-inl.h +                     third_party/libuv/src/win/signal.c +                     third_party/libuv/src/win/snprintf.c +                     third_party/libuv/src/win/stream.c +                     third_party/libuv/src/win/stream-inl.h +                     third_party/libuv/src/win/tcp.c +                     third_party/libuv/src/win/thread.c +                     third_party/libuv/src/win/tty.c +                     third_party/libuv/src/win/udp.c +                     third_party/libuv/src/win/util.c +                     third_party/libuv/src/win/winapi.c +                     third_party/libuv/src/win/winapi.h +                     third_party/libuv/src/win/winsock.c +                     third_party/libuv/src/win/winsock.h++                     -- utf8rewind C sources+                     third_party/utf8rewind/include/utf8rewind/utf8rewind.h+                     third_party/utf8rewind/source/unicodedatabase.c+                     third_party/utf8rewind/source/unicodedatabase.h+                     third_party/utf8rewind/source/internal/base.h+                     third_party/utf8rewind/source/internal/casemapping.c+                     third_party/utf8rewind/source/internal/casemapping.h+                     third_party/utf8rewind/source/internal/codepoint.c+                     third_party/utf8rewind/source/internal/codepoint.h+                     third_party/utf8rewind/source/internal/composition.c+                     third_party/utf8rewind/source/internal/composition.h+                     third_party/utf8rewind/source/internal/database.c+                     third_party/utf8rewind/source/internal/database.h+                     third_party/utf8rewind/source/internal/decomposition.c+                     third_party/utf8rewind/source/internal/decomposition.h+                     third_party/utf8rewind/source/internal/seeking.c+                     third_party/utf8rewind/source/internal/seeking.h+                     third_party/utf8rewind/source/internal/streaming.c+                     third_party/utf8rewind/source/internal/streaming.h+                     third_party/utf8rewind/source/utf8rewind.c++                     -- simd utf8 code+                     third_party/fastvalidate-utf-8/include/simdasciicheck.h+                     third_party/fastvalidate-utf-8/include/simdutf8check.h++source-repository head+  type:     git+  location: git://github.com/haskell-stdio/stdio.git+++flag integer-simple+  description:+    Use the [simple integer library](http://hackage.haskell.org/package/integer-simple)+    instead of [integer-gmp](http://hackage.haskell.org/package/integer-gmp)+  default: False+  manual: False++library+    exposed-modules:        Std.Data.Vector+                            Std.Data.Vector.Base+                            Std.Data.Vector.Extra+                            Std.Data.Vector.Search+                            Std.Data.Vector.Sort+                            Std.Data.Vector.QQ+                            Std.Data.PrimArray.Cast+                            Std.Data.PrimArray.QQ+                            Std.Data.PrimArray.BitTwiddle+                            Std.Data.PrimArray.UnalignedAccess+                            Std.Data.Array+                            Std.Data.Array.Checked+                            Std.Data.CBytes++                            Std.Data.Text+                            Std.Data.Text.Base+                            Std.Data.Text.Extra+                            Std.Data.Text.Search+                            Std.Data.Text.UTF8Codec+                            Std.Data.Text.UTF8Rewind+                            Std.Data.TextBuilder++                            Std.Data.Builder+                            Std.Data.Builder.Base+                            Std.Data.Builder.Numeric+                            Std.Data.Builder.Numeric.DigitTable++                            Std.Data.Parser+                            Std.Data.Parser.Base+                            Std.Data.Parser.Numeric++                            Std.Data.PrimIORef+                            Std.Data.PrimSTRef+                            Std.Data.PrimSTRef.Base++                            -- Std.Data.LEON++                            Std.Foreign.PrimArray++                            Std.IO.Resource+                            Std.IO.LowResTimer+                            Std.IO.Logger+                            Std.IO.Exception +                            Std.IO.Buffered+                            Std.IO.FileSystem+                            Std.IO.FileSystemT+                            Std.IO.TCP+                            Std.IO.SockAddr+                            Std.IO.StdStream++                            Std.IO.UV.Errno+                            Std.IO.UV.FFI+                            Std.IO.UV.Manager++    -- other-modules:         ++    -- other-extensions:    ++    build-depends:          base >=4.12 && <5.0+                        ,   ghc-prim  >= 0.4+                        ,   primitive >= 0.6.4+                        ,   deepseq+                        ,   template-haskell +                        ,   exceptions >= 0.10+                        ,   transformers+                        ,   word8+                        ,   scientific+                        ,   hashable+                        ,   case-insensitive+                        ,   stm+                        ,   time++  if flag(integer-simple)+    cpp-options: -DINTEGER_SIMPLE+    build-depends: integer-simple >= 0.1 && < 0.5+  else+    cpp-options: -DINTEGER_GMP+    build-depends: integer-gmp >= 0.2 && < 1.1++    include-dirs:       include+                        third_party/utf8rewind/include/utf8rewind+                        third_party/utf8rewind/source/internal+                        third_party/utf8rewind/source+                        third_party/fastvalidate-utf-8/include+    includes:           bytes.h+                        dtoa.h+                        hs_uv.h+                        text.h+                        utf8rewind.h+                        simdasciicheck.h+                        simdutf8check.h+    install-includes:   bytes.h+                        dtoa.h+                        hs_uv.h+                        text.h+                        utf8rewind.h+                        simdasciicheck.h+                        simdutf8check.h+    cc-options:         -march=native+    c-sources:          cbits/bytes.c+                        cbits/dtoa.c+                        cbits/text.c+                        cbits/hs_uv_base.c+                        cbits/hs_uv_stream.c+                        cbits/hs_uv_file.c+                        third_party/utf8rewind/source/unicodedatabase.c+                        third_party/utf8rewind/source/internal/casemapping.c+                        third_party/utf8rewind/source/internal/codepoint.c+                        third_party/utf8rewind/source/internal/composition.c+                        third_party/utf8rewind/source/internal/database.c+                        third_party/utf8rewind/source/internal/decomposition.c+                        third_party/utf8rewind/source/internal/seeking.c+                        third_party/utf8rewind/source/internal/streaming.c+                        third_party/utf8rewind/source/utf8rewind.c++    if os(windows)+      c-sources:+        -- Note: The c-sources list is taken from libuv's Makefile.mingw, needs to be+        -- updated when we bump up libuv's version.+        -- header files are ignored here, otherwise will confuse linker +        third_party/libuv/src/fs-poll.c +        -- third_party/libuv/src/heap-inl.h +        third_party/libuv/src/idna.c +        third_party/libuv/src/inet.c +        -- third_party/libuv/src/queue.h +        third_party/libuv/src/strscpy.c +        -- third_party/libuv/src/strscpy.h +        third_party/libuv/src/threadpool.c +        third_party/libuv/src/timer.c +        third_party/libuv/src/uv-data-getter-setters.c +        third_party/libuv/src/uv-common.c +        -- third_party/libuv/src/uv-common.h +        third_party/libuv/src/version.c++        third_party/libuv/src/win/async.c +        -- third_party/libuv/src/win/atomicops-inl.h +        third_party/libuv/src/win/core.c +        third_party/libuv/src/win/detect-wakeup.c +        third_party/libuv/src/win/dl.c +        third_party/libuv/src/win/error.c +        third_party/libuv/src/win/fs-event.c +        third_party/libuv/src/win/fs.c +        third_party/libuv/src/win/getaddrinfo.c +        third_party/libuv/src/win/getnameinfo.c +        third_party/libuv/src/win/handle.c +        -- third_party/libuv/src/win/handle-inl.h +        -- third_party/libuv/src/win/internal.h +        third_party/libuv/src/win/loop-watcher.c +        third_party/libuv/src/win/pipe.c +        third_party/libuv/src/win/poll.c +        third_party/libuv/src/win/process-stdio.c +        third_party/libuv/src/win/process.c +        -- third_party/libuv/src/win/req-inl.h +        third_party/libuv/src/win/signal.c +        third_party/libuv/src/win/stream.c +        -- third_party/libuv/src/win/stream-inl.h +        third_party/libuv/src/win/tcp.c +        third_party/libuv/src/win/thread.c +        third_party/libuv/src/win/tty.c +        third_party/libuv/src/win/udp.c +        third_party/libuv/src/win/util.c +        third_party/libuv/src/win/winapi.c +        -- third_party/libuv/src/win/winapi.h +        third_party/libuv/src/win/winsock.c +        -- third_party/libuv/src/win/winsock.h++      cc-options:        -Wall -Wextra -Wno-unused-parameter -Wstrict-prototypes -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600 -march=native+      cpp-options:       -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600+      include-dirs:      third_party/libuv/include+                         third_party/libuv/src+      -- The C runtime dependencies are imposed by libuv.+      extra-libraries:   psapi, Iphlpapi, userenv, Ws2_32+    else+      extra-libraries:   uv++    -- hs-source-dirs:+    default-language:    Haskell2010+    build-tools:         hsc2hs, hspec-discover+    -- ghc-options:         -Wall++test-suite test+    type: exitcode-stdio-1.0+    main-is: Spec.hs+    hs-source-dirs: test+    build-depends:  stdio+                  , base+                  , hspec >= 2.5.4+                  , hashable+                  , HUnit+                  , QuickCheck >= 2.10+                  , quickcheck-instances+                  , word8+                  , scientific+                  , primitive++    other-modules:+        Std.Data.Builder.NumericSpec+        Std.Data.CBytesSpec+        Std.Data.Parser.BaseSpec+        Std.Data.Parser.NumericSpec+        Std.Data.PrimArray.UnalignedAccessSpec+        Std.Data.Text.BaseSpec+        Std.Data.Text.ExtraSpec+        Std.Data.Text.SearchSpec+        Std.Data.Vector.BaseSpec+        Std.Data.Vector.ExtraSpec+        Std.Data.Vector.SearchSpec+        Std.Data.Vector.SortSpec+        Std.IO.FileSystemSpec+        Std.IO.FileSystemTSpec+        Std.IO.LowResTimerSpec+        Std.IO.ResourceSpec+++  if flag(integer-simple)+    cpp-options: -DINTEGER_SIMPLE+    build-depends: integer-simple >= 0.1 && < 0.5+  else+    cpp-options: -DINTEGER_GMP+    build-depends: integer-gmp >= 0.2 && < 1.1++    ghc-options:         -threaded+    default-language:    Haskell2010 
+ test/Spec.hs view
@@ -0,0 +1,2 @@+-- file test/Spec.hs+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ test/Std/Data/Builder/NumericSpec.hs view
@@ -0,0 +1,230 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.Data.Builder.NumericSpec where++import qualified Data.List                as List+import           Data.Word+import           Data.Int+import           GHC.Float+import           Text.Printf                 (printf)+import qualified Std.Data.Builder.Numeric as B+import qualified Std.Data.Builder.Base    as B+import qualified Std.Data.Text as T+import qualified Std.Data.Vector as V+import qualified Data.Scientific as Sci+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.QuickCheck.Instances.Scientific+import           Test.Hspec+import           Test.Hspec.QuickCheck++spec :: Spec+spec = describe "builder numeric" . modifyMaxSuccess (*50) . modifyMaxSize (*50) $ do+    describe "int roundtrip" $ do+        prop "int roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.int @Word i)+        prop "int roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.int @Int i)+        prop "int roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.int @Word64 i)+        prop "int roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.int @Int64 i)+        prop "int roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.int @Word32 i)+        prop "int roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.int @Int32 i)+        prop "int roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.int @Word16 i)+        prop "int roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.int @Int16 i)+        prop "int roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.int @Word8 i)+        prop "int roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.int @Int8 i)++    describe "int roundtrip" $ do+        let f = B.defaultIFormat{B.width = 100, B.padding = B.ZeroPadding}+        prop "int roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.intWith @Word f i)+        prop "int roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.intWith @Int f i)+        prop "padding length" $ \ i ->+            100 === (V.length . B.buildBytes $ B.intWith @Word f i)+        prop "padding length" $ \ i ->+            100 === (V.length . B.buildBytes $ B.intWith @Int f i)++        let f = B.defaultIFormat{B.width = 10, B.padding = B.ZeroPadding}+        prop "padding roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.intWith @Word f i)+        prop "padding roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.intWith @Int f i)++        let f = B.defaultIFormat{B.width = 10, B.padding = B.LeftSpacePadding}+        prop "padding roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.intWith @Word f i)+        prop "padding roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.intWith @Int f i)++        let f = B.defaultIFormat{B.width = 10, B.padding = B.RightSpacePadding}+        prop "padding roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.intWith @Word f i)+        prop "padding roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.intWith @Int f i)++    describe "integer roundtrip" $ do+        prop "integer roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.integer i)++    describe "scientific roundtrip" $ do+        prop "scientific roundtrip" $ \ c e ->+            Sci.scientific c e ===+                (read . T.unpack . T.validate . B.buildBytes . B.scientific $ Sci.scientific c e)+        prop "scientificWith roundtrip" $ \ c e ->+            Sci.scientific c e ===+                (read . T.unpack . T.validate . B.buildBytes . B.scientificWith B.Exponent Nothing $+                    Sci.scientific c e)+        {- B.Exponent doesn't roundtrip, i.e. B.scientificWith B.Exponent (Just 0) 101 ===> 1e2+        prop "scientificWith roundtrip" $ \ c e ->+            Sci.scientific c e ===+                (read . T.unpack . T.validate . B.buildBytes . B.scientificWith B.Exponent (Just (abs e)) $+                    Sci.scientific c e)+        -}+        prop "scientificWith roundtrip" $ \ c e ->+            Sci.scientific c e ===+                (read . T.unpack . T.validate . B.buildBytes . B.scientificWith B.Generic Nothing $+                    Sci.scientific c e)+        prop "scientificWith roundtrip" $ \ c e ->+            Sci.scientific c e ===+                (read . T.unpack . T.validate . B.buildBytes . B.scientificWith B.Generic (Just (abs e)) $+                    Sci.scientific c e)+        prop "scientificWith roundtrip" $ \ c e ->+            Sci.scientific c e ===+                (read . T.unpack . T.validate . B.buildBytes . B.scientificWith B.Fixed Nothing $+                    Sci.scientific c e)+        prop "scientificWith roundtrip" $ \ c e ->+            Sci.scientific c e ===+                (read . T.unpack . T.validate . B.buildBytes . B.scientificWith B.Fixed (Just (abs e)) $+                    Sci.scientific c e)++    describe "hex roundtrip" $ do++        let read' s = read $ "0x" ++ s++        prop "hex roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.hex @Word i)+        prop "hex roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.hex @Int i)+        prop "hex roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.hex @Word64 i)+        prop "hex roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.hex @Int64 i)+        prop "hex roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.hex @Word32 i)+        prop "hex roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.hex @Int32 i)+        prop "hex roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.hex @Word16 i)+        prop "hex roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.hex @Int16 i)+        prop "hex roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.hex @Word8 i)+        prop "hex roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.hex @Int8 i)++    describe "heX roundtrip" $ do++        let read' s = read $ "0x" ++ s++        prop "heX roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.heX @Word i)+        prop "heX roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.heX @Int i)+        prop "heX roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.heX @Word64 i)+        prop "heX roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.heX @Int64 i)+        prop "heX roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.heX @Word32 i)+        prop "heX roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.heX @Int32 i)+        prop "heX roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.heX @Word16 i)+        prop "heX roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.heX @Int16 i)+        prop "heX roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.heX @Word8 i)+        prop "heX roundtrip" $ \ i ->+            i === (read' . T.unpack . T.validate . B.buildBytes $ B.heX @Int8 i)++    describe "int === show" $ do+        prop "int === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes $ B.int @Word i)+        prop "int === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes $ B.int @Int i)+        prop "int === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes $ B.int @Word64 i)+        prop "int === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes $ B.int @Int64 i)+        prop "int === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes $ B.int @Word32 i)+        prop "int === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes $ B.int @Int32 i)+        prop "int === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes $ B.int @Word16 i)+        prop "int === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes $ B.int @Int16 i)+        prop "int === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes $ B.int @Word8 i)+        prop "int === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes $ B.int @Int8 i)++    describe "intWith === printf" $ do+        prop "int === printf" $ \ i ->+            printf "%d" i ===+                (T.unpack . T.validate . B.buildBytes $ B.intWith @Int B.defaultIFormat i)+        prop "int === printf" $ \ i (Positive w) ->+            printf ("%" ++ show w ++ "d") i ===+                (T.unpack . T.validate . B.buildBytes $ B.intWith @Int B.defaultIFormat+                    {B.padding = B.LeftSpacePadding, B.width = w} i)+        prop "int === printf" $ \ i (Positive w) ->+            printf ("%0" ++ show w ++ "d") i ===+                (T.unpack . T.validate . B.buildBytes $ B.intWith @Int B.defaultIFormat+                    {B.padding = B.ZeroPadding, B.width = w} i)+        prop "int === printf" $ \ i (Positive w) ->+            printf ("%-" ++ show w ++ "d") i ===+                (T.unpack . T.validate . B.buildBytes $ B.intWith @Int B.defaultIFormat+                    {B.padding = B.RightSpacePadding, B.width = w} i)++        prop "int === printf" $ \ i ->+            printf "%08x" i ===+                (T.unpack . T.validate . B.buildBytes $ B.hex @Int32 i)++    describe "float, double === show" $ do+        prop "float === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes  $ B.float i)+        prop "double === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes  $ B.double i)+        prop "scientific === show" $ \ i ->+            show i === (T.unpack . T.validate . B.buildBytes  $ B.scientific i)++    describe "floatWith, doubleWith === formatRealFloat" $ do+        prop "floatWith === formatRealFloat" $ \ i l ->+            formatRealFloat FFGeneric l i ===+                (T.unpack . T.validate . B.buildBytes  $ B.floatWith B.Generic l i)+        prop "doubleWith === formatRealFloat" $ \ i l ->+            formatRealFloat FFGeneric l i ===+                (T.unpack . T.validate . B.buildBytes  $ B.doubleWith  B.Generic l i)+        prop "floatWith === formatRealFloat" $ \ i l ->+            formatRealFloat FFFixed  l  i ===+                (T.unpack . T.validate . B.buildBytes  $ B.floatWith B.Fixed  l i)+        prop "doubleWith === formatRealFloat" $ \ i l ->+            formatRealFloat FFFixed  l  i ===+                (T.unpack . T.validate . B.buildBytes  $ B.doubleWith  B.Fixed  l i)+        prop "floatWith === formatRealFloat" $ \ i l ->+            formatRealFloat FFExponent l i ===+                (T.unpack . T.validate . B.buildBytes  $ B.floatWith B.Exponent l i)+        prop "doubleWith === formatRealFloat" $ \ i l ->+            formatRealFloat FFExponent l i ===+                (T.unpack . T.validate . B.buildBytes  $ B.doubleWith B.Exponent l i)
+ test/Std/Data/CBytesSpec.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.Data.CBytesSpec where++import qualified Data.List                as List+import           Data.Word+import           Data.Hashable            (hashWithSalt, hash)+import qualified Std.Data.CBytes          as CB+import qualified Std.Data.Vector.Base     as V+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++spec :: Spec+spec = describe "CBytes-base" $ do+    describe "CBytes Eq Ord property" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "CBytes eq === List.eq" $ \ xs ys ->+            (CB.pack xs == CB.pack ys) === (xs == ys)++        prop "CBytes compare === List.compare" $ \ xs ys ->+            let xs' = List.filter (/= '\NUL') xs+                ys' = List.filter (/= '\NUL') ys+            in (CB.pack xs' `compare` CB.pack ys') === (xs' `compare` ys')++    describe "CBytes Hashable instance property" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "CBytes a's hash should be equal to Bytes's hash" $ \ (ASCIIString xs) ->+            let ys = List.filter (/= '\NUL') xs+            in hash (CB.pack ys) === hash (V.packASCII ys)+        prop "CBytes a's hash should be equal to literal's hash" $+            hash ("hello world!" :: CB.CBytes) === hash (CB.fromBytes "hello world!")++    describe "CBytes IsString instance property" $ do+        prop "ASCII string" $+            "hello world" === CB.fromText "hello world"+        prop "UTF8 string" $+            "你好世界" === CB.fromText "你好世界"++    describe "CBytes length == List.length" $ do+        prop "CBytes length === List.length" $ \ (ASCIIString xs) ->+            let ys = List.filter (/= '\NUL') xs+            in (CB.length $ CB.pack ys)  ===  List.length ys++    describe "CBytes append == List.(++)" $ do+        prop "CBytes eq === List.eq" $ \ xs ys ->+            (CB.pack xs `CB.append` CB.pack ys) === CB.pack (xs ++ ys)
+ test/Std/Data/Parser/BaseSpec.hs view
@@ -0,0 +1,123 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.Data.Parser.BaseSpec where++import qualified Data.List                as L+import           Data.Word+import           Data.Int+import           GHC.Float+import           Text.Printf                 (printf)+import           Data.Word8                  (toLower, toUpper)+import qualified Std.Data.Parser.Base    as P+import qualified Std.Data.Text as T+import qualified Std.Data.Vector.Base as V+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck+++parse' :: P.Parser a -> [Word8] -> Maybe a+parse' p str = case P.parse p (V.pack str) of+    Left msg -> Nothing+    Right a  -> Just a++parse'' :: P.Parser a -> [Word8] -> Maybe (V.Bytes, a)+parse'' p str = case P.parse' p (V.pack str) of+    (rest, Right a)  -> Just (rest, a)+    _                -> Nothing++spec :: Spec+spec = describe "parsers" . modifyMaxSuccess (*10) . modifyMaxSize (*10)  $ do+        prop "satisfy" $ \ w s ->+            parse' (P.satisfy (<=w)) (w:s) === Just w++        prop "satisfyWith" $ \ w s (Fun _ f) ->+            parse' (P.satisfyWith f (== f w)) (w:s) === Just (f w :: Int)++        prop "word8" $ \ w w' s ->+            parse' (P.word8 w) (w':s) ===+                (if w == w' then Just () else Nothing)++        prop "skipWhile" $ \ s (Fun _ f) ->+            parse'' (P.skipWhile f) s === Just (V.pack (L.dropWhile f s), ())++        prop "takeWhile" $ \ s (Fun _ f) ->+            parse'' (P.takeWhile f) s === Just (V.pack (L.dropWhile f s), V.pack (L.takeWhile f s))++        prop "takeTill" $ \ s (Fun _ f) ->+            let (s1, s2) = L.break f s+            in parse'' (P.takeTill f) s === Just (V.pack s2, V.pack s1)++        prop "takeWhile1" $ \ s (Fun _ f) ->+            parse'' (P.takeWhile1 f) s ===+                case s of+                    (w:_) | f w  -> Just (V.pack (L.dropWhile f s), V.pack (L.takeWhile f s))+                    _            -> Nothing++        prop "take" $ \ s n ->+            parse'' (P.take n) s ===+                if L.length s >= n+                    then Just (V.pack (L.drop n s), V.pack (L.take n s))+                    else Nothing++        prop "skip" $ \ s n ->+            parse'' (P.skip n) s ===+                if L.length s >= n+                    then Just (V.pack (L.drop n s), ())+                    else Nothing++        prop "anyWord8" $ \ s ->+            parse' ((,) <$> P.anyWord8 <*> P.takeWhile (const True)) s ===+                case s of [] -> Nothing+                          (w:s') -> Just (w, V.pack s')+++        prop "peek" $ \ s ->+            parse' ((,) <$> P.peek <*> P.takeWhile (const True)) s ===+                case s of [] -> Nothing+                          (w:_) -> Just (w, V.pack s)++        prop "peekMaybe" $ \ s ->+            parse' ((,) <$> P.peekMaybe <*> P.takeWhile (const True)) s ===+                case s of [] -> Just (Nothing, V.pack s)+                          (w:_) -> Just (Just w, V.pack s)++        prop "bytes" $ \ s t ->+            parse' (P.bytes . V.pack $ t) s ===+                if L.take (L.length t) s == t then Just () else Nothing++        prop "bytes" $ \ s t ->+            parse'' (P.bytes . V.pack $ t) (t ++ s) === Just (V.pack s, ())++        prop "bytes" $ \ s t u ->+            parse'' (P.bytes (V.pack s) >> P.bytes (V.pack t)) (s ++ t ++ u) === Just (V.pack u, ())++        prop "bytesCI" $ \ s t ->+            parse'' (P.bytesCI . V.pack $ t) (t ++ s) === Just (V.pack s, ())++        prop "bytesCI" $ \ s t ->+            parse'' (P.bytesCI . V.pack $ t) (L.map toLower t ++ s) === Just (V.pack s, ())++        prop "endOfInput" $ \ s ->+            parse' P.endOfInput s ===+                case s of [] -> Just True+                          _  -> Just False++        prop "scan" $ \ s l ->+            let go l  _ | l <= 0    = Nothing+                        | otherwise = Just (l-1)+            in parse' (P.scan l go) s === Just (V.pack $ L.take l s)++        prop "endOfLine" $ \ s ->+            let r = fromIntegral (fromEnum '\r')+                n =  fromIntegral (fromEnum '\n')+            in parse'' (P.skipWhile (\w -> w `L.notElem` [r, n]) >> P.endOfLine) s ===+                    case break (\w -> w `L.elem` [r, n]) s of+                        (_, bs) -> case bs of+                            (b:bs') | b == n -> Just (V.pack bs', ())+                            (b:c:bs') | b == r && c == n -> Just (V.pack bs', ())+                            _ -> Nothing+
+ test/Std/Data/Parser/NumericSpec.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.Data.Parser.NumericSpec where++import qualified Data.List                as L+import           Data.Word+import           Data.Int+import           GHC.Float+import           Text.Printf                 (printf)+import           Data.Word8                  (toLower, toUpper)+import qualified Std.Data.Parser.Numeric    as P+import qualified Std.Data.Parser.Base    as P+import qualified Std.Data.Builder.Numeric    as B+import qualified Std.Data.Builder.Base    as B+import qualified Std.Data.Text as T+import qualified Std.Data.Vector.Base as V+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++spec :: Spec+spec = describe "numeric parsers roundtrip" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "positive hex roundtrip" $ \ i ->+            P.parse P.hex (B.buildBytes (B.hex i)) === Right (i :: Int)+        prop "positive hex roundtrip" $ \ i ->+            P.parse P.hex (B.buildBytes (B.hex i)) === Right (i :: Int64)+        prop "positive hex roundtrip" $ \ i ->+            P.parse P.hex (B.buildBytes (B.hex i)) === Right (i :: Int32)+        prop "positive hex roundtrip" $ \ i ->+            P.parse P.hex (B.buildBytes (B.hex i)) === Right (i :: Int16)+        prop "positive hex roundtrip" $ \ i ->+            P.parse P.hex (B.buildBytes (B.hex i)) === Right (i :: Int8)+        prop "positive hex roundtrip" $ \ i ->+            P.parse P.hex (B.buildBytes (B.hex i)) === Right (i :: Word)+        prop "positive hex roundtrip" $ \ i ->+            P.parse P.hex (B.buildBytes (B.hex i)) === Right (i :: Word64)+        prop "positive hex roundtrip" $ \ i ->+            P.parse P.hex (B.buildBytes (B.hex i)) === Right (i :: Word32)+        prop "positive hex roundtrip" $ \ i ->+            P.parse P.hex (B.buildBytes (B.hex i)) === Right (i :: Word16)+        prop "positive hex roundtrip" $ \ i ->+            P.parse P.hex (B.buildBytes (B.hex i)) === Right (i :: Word8)+++        prop "positive int roundtrip" $ \ (Positive i) ->+            P.parse P.uint (B.buildBytes (B.int i)) === Right (i :: Int)+        prop "positive int roundtrip" $ \ (Positive i) ->+            P.parse P.uint (B.buildBytes (B.int i)) === Right (i :: Int64)+        prop "positive int roundtrip" $ \ (Positive i) ->+            P.parse P.uint (B.buildBytes (B.int i)) === Right (i :: Int32)+        prop "positive int roundtrip" $ \ (Positive i) ->+            P.parse P.uint (B.buildBytes (B.int i)) === Right (i :: Int16)+        prop "positive int roundtrip" $ \ (Positive i) ->+            P.parse P.uint (B.buildBytes (B.int i)) === Right (i :: Int8)+        prop "positive int roundtrip" $ \ (Positive i) ->+            P.parse P.uint (B.buildBytes (B.int i)) === Right (i :: Word)+        prop "positive int roundtrip" $ \ (Positive i) ->+            P.parse P.uint (B.buildBytes (B.int i)) === Right (i :: Word64)+        prop "positive int roundtrip" $ \ (Positive i) ->+            P.parse P.uint (B.buildBytes (B.int i)) === Right (i :: Word32)+        prop "positive int roundtrip" $ \ (Positive i) ->+            P.parse P.uint (B.buildBytes (B.int i)) === Right (i :: Word16)+        prop "positive int roundtrip" $ \ (Positive i) ->+            P.parse P.uint (B.buildBytes (B.int i)) === Right (i :: Word8)+++        prop "positive int roundtrip" $ \ i ->+            P.parse P.int (B.buildBytes (B.int i)) === Right (i :: Int)+        prop "positive int roundtrip" $ \ i ->+            P.parse P.int (B.buildBytes (B.int i)) === Right (i :: Int64)+        prop "positive int roundtrip" $ \ i ->+            P.parse P.int (B.buildBytes (B.int i)) === Right (i :: Int32)+        prop "positive int roundtrip" $ \ i ->+            P.parse P.int (B.buildBytes (B.int i)) === Right (i :: Int16)+        prop "positive int roundtrip" $ \ i ->+            P.parse P.int (B.buildBytes (B.int i)) === Right (i :: Int8)+        prop "positive int roundtrip" $ \ i ->+            P.parse P.int (B.buildBytes (B.int i)) === Right (i :: Word)+        prop "positive int roundtrip" $ \ i ->+            P.parse P.int (B.buildBytes (B.int i)) === Right (i :: Word64)+        prop "positive int roundtrip" $ \ i ->+            P.parse P.int (B.buildBytes (B.int i)) === Right (i :: Word32)+        prop "positive int roundtrip" $ \ i ->+            P.parse P.int (B.buildBytes (B.int i)) === Right (i :: Word16)+        prop "positive int roundtrip" $ \ i ->+            P.parse P.int (B.buildBytes (B.int i)) === Right (i :: Word8)+++        prop "float roundtrip" $ \ i ->+            P.parse P.float (B.buildBytes (B.float i)) === Right (i :: Float)+        prop "double roundtrip" $ \ i ->+            P.parse P.double (B.buildBytes (B.double i)) === Right (i :: Double)
+ test/Std/Data/PrimArray/UnalignedAccessSpec.hs view
@@ -0,0 +1,294 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.Data.PrimArray.UnalignedAccessSpec where++import qualified Data.List                as L+import           Data.Int+import           GHC.Float+import           Data.Word+import           Std.Data.PrimArray.UnalignedAccess+import           Control.Monad.Primitive+import           Data.Primitive.ByteArray+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++spec :: Spec+spec = describe "unaligned acess" . modifyMaxSuccess (*10) . modifyMaxSize (*10)  $ do+        prop "roundtrip Word8" $ \ (w::Word8) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# w)+            w' <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let w'' = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip Word16" $ \ (w::Word16) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# w)+            w' <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let w'' = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip Word32" $ \ (w::Word32) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# w)+            w' <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let w'' = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip Word64" $ \ (w::Word64) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# w)+            w' <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let w'' = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip Word" $ \ (w::Word) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# w)+            w' <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let w'' = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip LE Word16" $ \ (w::Word16) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (LE w))+            (LE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (LE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip LE Word32" $ \ (w::Word32) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (LE w))+            (LE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (LE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip LE Word64" $ \ (w::Word64) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (LE w))+            (LE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (LE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip LE Word" $ \ (w::Word) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (LE w))+            (LE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (LE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip BE Word16" $ \ (w::Word16) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (BE w))+            (BE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (BE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip BE Word32" $ \ (w::Word32) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (BE w))+            (BE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (BE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip BE Word64" $ \ (w::Word64) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (BE w))+            (BE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (BE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip BE Word" $ \ (w::Word) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (BE w))+            (BE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (BE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++--------------------------------------------------------------------------------++        prop "roundtrip Int16" $ \ (w::Int16) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# w)+            w' <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let w'' = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip LE Int16" $ \ (w::Int16) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (LE w))+            (LE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (LE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip BE Int16" $ \ (w::Int16) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (BE w))+            (BE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (BE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip Int32" $ \ (w::Int32) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# w)+            w' <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let w'' = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip LE Int32" $ \ (w::Int32) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (LE w))+            (LE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (LE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip BE Int32" $ \ (w::Int32) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (BE w))+            (BE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (BE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip Int64" $ \ (w::Int64) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# w)+            w' <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let w'' = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip LE Int64" $ \ (w::Int64) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (LE w))+            (LE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (LE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip BE Int64" $ \ (w::Int64) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (BE w))+            (BE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (BE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip Int" $ \ (w::Int) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# w)+            w' <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let w'' = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip LE Int" $ \ (w::Int) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (LE w))+            (LE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (LE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip BE Int" $ \ (w::Int) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (BE w))+            (BE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (BE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip Float" $ \ (w::Float) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# w)+            w' <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let w'' = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip LE Float" $ \ (w::Float) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (LE w))+            (LE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (LE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip BE Float" $ \ (w::Float) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (BE w))+            (BE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (BE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip Double" $ \ (w::Double) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# w)+            w' <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let w'' = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip LE Double" $ \ (w::Double) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (LE w))+            (LE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (LE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip BE Double" $ \ (w::Double) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (BE w))+            (BE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (BE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip Char" $ \ (w::Char) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# w)+            w' <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let w'' = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip LE Char" $ \ (w::Char) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (LE w))+            (LE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (LE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')++        prop "roundtrip BE Char" $ \ (w::Char) -> ioProperty $ do+            mba@(MutableByteArray mba#) <- newByteArray 128+            primitive_ (writeWord8ArrayAs mba# 7# (BE w))+            (BE w') <- primitive (readWord8ArrayAs mba# 7#)+            (ByteArray ba#) <- unsafeFreezeByteArray mba+            let (BE w'') = indexWord8ArrayAs ba# 7#+            return $ (w === w') .&&. (w === w'')
+ test/Std/Data/Text/BaseSpec.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.Data.Text.BaseSpec where++import qualified Data.List                as List+import           Data.Word+import qualified Std.Data.Text.Base       as T+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++spec :: Spec+spec = describe "text-base" $ do+    describe "text Eq Ord property" $ do+        prop "text eq === List.eq" $ \ xs ys ->+            (T.pack xs == T.pack ys) === (xs == ys)++        prop "text compare === List.compare" $ \ xs ys ->+            (T.pack xs `compare` T.pack ys) === (xs `compare` ys)++    describe "text unpack(R) . pack(R)(N) == id/reverse" . modifyMaxSuccess (*50) . modifyMaxSize (*50) $ do+        prop "unpack . pack === id" $ \ xs  ->+            (T.unpack (T.pack xs))  === xs++        prop "unpackR . pack === reverse" $ \ xs  ->+            (T.unpackR (T.pack xs))  ===  reverse xs++        prop "unpack . packR === reverse" $ \ xs  ->+            (T.unpack (T.packR xs))  ===  reverse xs++        prop "unpackR . packR === id" $ \ xs  ->+            (T.unpackR (T.packR xs))  === xs++    describe "text pack == packN" . modifyMaxSuccess (*50) . modifyMaxSize (*50) $ do+        prop "pack === packN XX" $ \ xs d ->+            (T.pack xs) === (T.packN d xs)++        prop "packR === packRN XX" $ \ xs d ->+            (T.packR xs) === (T.packRN d xs)++    describe "Text IsString instance property" $ do+        prop "ASCII string" $+            "hello world" === T.pack "hello world"+        prop "UTF8 string" $+            "你好世界" === T.pack "你好世界"+        prop "NUL codepoint" $+            "你好\NUL世界" === T.pack "你好\NUL世界"+        prop "surrogate codepoint" $+            "你好\xFFFD世界" === T.pack "你好\xD800世界"++    describe "text length == List.length" $ do+        prop "text length === List.length" $ \ xs ->+            (T.length $ T.pack xs)  ===  List.length xs++    describe "text append == List.(++)" $ do+        prop "text eq === List.eq" $ \ xs ys ->+            (T.unpack $ T.pack xs `T.append` T.pack ys) === (xs ++ ys)++    describe "text map' == List.map" $ do+        prop "text map' === List.map" $ \ xs (Fun _ f) ->+            (T.map' f (T.pack xs)) === (T.pack $ List.map f xs)++    describe "text imap' (const f) == List.map f" $ do+        prop "text imap' (const f) == List.map f" $ \ xs (Fun _ f) ->+            (T.imap' (const f) $ T.pack xs) === (T.pack $ List.map f xs)++    describe "text imap' const == List.zipWith const [0..]" $ do+        prop "text imap' const == List.zipWith const [0..]" $ \ xs ->+            (T.imap' (\ i _ -> toEnum i) $ T.pack xs) === (T.pack . List.map toEnum $ List.zipWith const [0..] xs)++    describe "text foldl' == List.foldl'" $ do+        prop "text foldl' === List.foldl'" $ \ xs f x ->+            (T.foldl' (applyFun2 f :: Char -> Char -> Char) x (T.pack xs))  ===+                (List.foldl' (applyFun2 f) x $ xs)++    describe "text foldr' == List.foldr'" $ do+        prop "text foldr' === List.foldr" $ \ xs f x ->+            (T.foldr' (applyFun2 f :: Char -> Char -> Char) x (T.pack xs))  ===+                (List.foldr (applyFun2 f) x $ xs)++    describe "text concat == List.concat" $ do+        prop "text concat === List.concat" $ \ xss ->+            (T.concat $ List.map (T.pack . getUnicodeString) xss)  ===+                (T.pack . List.concat $ List.map getUnicodeString xss)++    describe "text concatMap == List.concatMap" $ do+        prop "text concatMap === List.concatMap" $ \ xs (Fun _ f) ->+            (T.concatMap (T.pack . f) . T.pack . getUnicodeString) xs  ===+                (T.pack . List.concatMap f $ getUnicodeString xs)++    describe "text all == List.all" $ do+        prop "text all === List.all" $ \ xs (Fun _ f) ->+            (T.all f $ T.pack xs)  === (List.all f $ xs)++    describe "text any == List.any" $ do+        prop "text any === List.any" $ \ xs (Fun _ f) ->+            (T.any f $ T.pack xs)  === (List.any f $ xs)++    describe "text count x == List.length . List.filter (==x)" $ do+        prop "text count === List.length . List.filter (==x)" $ \ xs x ->+            (T.count x $ T.pack xs)  === (List.length . List.filter (==x) $ xs)++    describe "text replicate == List.replicate" $ do+        prop "text replicate = List.replicate" $ \ n x ->+            (T.replicate n x) == (T.pack (List.replicate n $ x))+
+ test/Std/Data/Text/ExtraSpec.hs view
@@ -0,0 +1,210 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.Data.Text.ExtraSpec where++import qualified Data.List                as List+import           Data.Word+import qualified Std.Data.Text.Base        as T+import qualified Std.Data.Text.Extra       as T+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++spec :: Spec+spec = describe "text-extra" $ do++    describe "T.cons" $ do+        prop "T.cons == List.(:)" $ \ xs x ->+            (T.cons x $ T.pack xs)  === (T.pack . (:) x $ xs)++    describe "T.snoc" $ do+        prop "T.snoc == List.++" $ \ xs x ->+            ((`T.snoc` x) $ T.pack xs)  === (T.pack . (++ [x]) $ xs)++    describe "Text.headMaybe" $ do+        prop "T.headMaybe === Just . list.head" $ \ (NonEmpty xs) ->+            (T.headMaybe $ T.pack xs)  === (Just . List.head $ xs)++    describe "T.initMayEmpty" $ do+        prop "T.initMayEmpty === List.init" $ \ (NonEmpty xs) ->+            (T.initMayEmpty $ T.pack xs)  === (T.pack . List.init $ xs)++    describe "T.lastMaybe" $ do+        prop "T.lastMaybe === Just . list.last" $ \ (NonEmpty xs) ->+            (T.lastMaybe $ T.pack xs)  === (Just . List.last $ xs)++    describe "T.tailMayEmpty" $ do+        prop "T.tailMayEmpty === List.tail" $ \ (NonEmpty xs) ->+            (T.tailMayEmpty $ T.pack xs)  === (T.pack . List.tail $ xs)++    describe "T.take" $ do+        prop "T.take == List.take" $ \ xs x ->+            (T.take x $ T.pack xs)  === (T.pack . List.take x $ xs)++    describe "T.takeR" $ do+        prop "T.takeR x == List.reverse . List.take x . List.reverse" $ \ xs x ->+            (T.takeR x $ T.pack xs)  ===+                (T.pack . List.reverse . List.take x . List.reverse $ xs)++    describe "T.drop" $ do+        prop "T.drop == List.drop" $ \ xs x ->+            (T.drop x $ T.pack xs)  === (T.pack . List.drop x $ xs)++    describe "T.dropR" $ do+        prop "T.dropR x == List.reverse . List.drop x . List.reverse" $ \ xs x ->+            (T.dropR x $ T.pack xs)  ===+                (T.pack . List.reverse . List.drop x . List.reverse $ xs)++    describe "T.slice x y" $ do+        prop "T.slice x y === drop x . take (x+y)" $ \ x y xs ->+            (T.slice x y $ T.pack xs)  === (T.pack . drop x . take (x+y) $ xs)++    describe "T.splitAt" $ do+        prop "T.splitAt == List.splitAt" $ \ xs x ->+            (T.splitAt x $ T.pack xs)  ===+                (let (a,b) = List.splitAt x $ xs in (T.pack a, T.pack b))++    describe "T.takeWhile" $ do+        prop "T.takeWhile == List.takeWhile" $ \ xs (Fun _ x) ->+            (T.takeWhile x $ T.pack xs)  ===+                (T.pack . List.takeWhile x $ xs)++    describe "T.takeWhileR" $ do+        prop "T.takeWhileR == reverse . List.takeWhile . reverse" $ \ xs (Fun _ x) ->+            (T.takeWhileR x $ T.pack xs)  ===+                (T.pack . List.reverse . List.takeWhile x $ List.reverse xs)++    describe "T.dropWhile" $ do+        prop "T.dropWhile == List.dropWhile" $ \ xs (Fun _ x) ->+            (T.dropWhile x $ T.pack xs)  === (T.pack . List.dropWhile x $ xs)++    describe "T.dropWhileR" $ do+        prop "T.dropWhileR == reverse . List.dropWhile . reverse" $ \ xs (Fun _ x) ->+            (T.dropWhileR x $ T.pack xs)  ===+                (T.pack . List.reverse . List.dropWhile x $ List.reverse xs)++    describe "T.break" $ do+        prop "T.break == List.break" $ \ xs (Fun _ x) ->+            (T.break x $ T.pack xs)  ===+                (let (a,b) = List.break x xs in (T.pack a, T.pack b))++    describe "T.breakOn" $ do+        prop "T.breakOn rules" $ \ xs ys ->+            (let (a, b) = T.breakOn (T.pack xs) $ T.pack ys+             in (a `T.append` b, T.pack xs `T.isPrefixOf` b || T.null b) === (T.pack ys, True))++    describe "T.span" $ do+        prop "T.span == List.span" $ \ xs (Fun _ x) ->+            (T.span x $ T.pack xs)  ===+                (let (a,b) = List.span x $ xs in (T.pack a, T.pack b))++    describe "T.breakR" $ do+        prop "T.breakR == List.break in reverse driection" $ \ xs (Fun _ x) ->+            (T.breakR x $ T.pack xs)  ===+                (let (b,a) = List.break x . List.reverse $ xs+                 in (T.reverse $ T.pack a, T.reverse $ T.pack b))++    describe "T.spanR" $ do+        prop "T.spanR == List.span in reverse driection" $ \ xs (Fun _ x) ->+            (T.spanR x $ T.pack xs)  ===+                (let (b,a) = List.span x . List.reverse $ xs+                 in (T.reverse $ T.pack a, T.reverse $ T.pack b))++    describe "T.group" $ do+        prop "T.group == List.group" $ \ xs ->+            (T.group $ T.pack xs)  === (T.pack <$> List.group xs)++    describe "T.groupBy" $ do+        prop "T.groupBy == List.groupBy" $ \ xs x ->+            (T.groupBy (applyFun2 x) $ T.pack xs)  ===+                (T.pack <$> List.groupBy (applyFun2 x) xs)++    describe "T.stripPrefix" $ do+        prop "T.stripPrefix a (a+b) = b " $ \ xs ys ->+            (T.stripPrefix (T.pack xs) . T.pack $ xs++ys) ===+                (Just $ T.pack ys)++    describe "T.stripSuffix" $ do+        prop "T.stripSuffix b (a+b) = a " $ \ xs ys ->+            (T.stripSuffix (T.pack xs) . T.pack $ ys++xs) ===+                (Just $ T.pack ys)++    describe "T.isInfixOf" $ do+        prop "T.isInfixOf b (a+b+c) = True" $ \ xs ys zs ->+            (T.isInfixOf (T.pack xs) . T.pack $ ys++xs++zs) === True++    describe "T.commonPrefix" $ do+        prop "let (c,a,b) = T.commonPrefix x y in (a,b) = (stripPrefix c x,stripPrefix c y)" $ \ xs ys ->+            let (c,a,b) = T.commonPrefix (T.pack xs) $ T.pack ys+                Just xs' = T.stripPrefix c $ T.pack xs+                Just ys' = T.stripPrefix c $ T.pack ys+            in (a,b) === (xs', ys')++    describe "T.intercalate" $ do+        prop "T.intercalate [x] . split x == id" $ \ xs x ->+            (T.intercalate (T.singleton x) . T.split x $ T.pack xs) === T.pack xs++    describe "T.intercalate" $ do+        prop "T.intercalate x . splitOn x == id" $ \ xs x ->+            (T.intercalate (T.pack x) . T.splitOn (T.pack x) $ T.pack xs) ===+                T.pack xs++    describe "T.words" $ do+        prop "T.words === List.words" $ \ xs ->+            (T.words $ T.pack xs)  === (T.pack <$> List.words xs)++    describe "T.lines" $ do+        prop "T.lines === List.lines" $ \ xs ->+            (T.lines $ T.pack xs)  === (T.pack <$> List.lines xs)++    describe "T.unwords" $ do+        prop "T.unwords === List.unwords" $ \ xs ->+            (T.unwords $ List.map T.pack xs)  === (T.pack $ List.unwords xs)++    describe "T.unlines" $ do+        prop "T.unlines === List.unlines" $ \ xs ->+            (T.unlines $ List.map T.pack xs)  === (T.pack $ List.unlines xs)++    describe "T.padLeft" $ do+        prop "T.padLeft n x xs = if l >= n then xs else replicate (n-l) x ++ xs" $ \ xs n x ->+            (T.padLeft n x $ T.pack xs) ===+                (let l = List.length xs+                 in if l >= n then T.pack xs+                              else T.pack $ (List.replicate (n-l) x ++ xs))++    describe "T.padRight" $ do+        prop "T.padRight n x xs = if l >= n then xs else xs ++ List.replicate (n-l) x" $ \ xs n x ->+            (T.padRight n x $ T.pack xs) ===+                (let l = List.length xs+                 in if l >= n then T.pack xs+                              else T.pack $ xs ++ (List.replicate (n-l) x))++    describe "T.reverse" $ do+        prop "reverse . pack === packR XX" $ \ xs ->+            (T.reverse $ T.pack xs) === (T.packR xs)++        prop "unpack reverse === List.reverse" $ \ xs ->+            (T.unpack . T.reverse $ T.pack xs) === (List.reverse xs)++    describe "T.intersperse" $ do+        prop "T.intersperse === List.intersperse" $ \ xs x ->+            (T.intersperse x $ T.pack xs)  ===+                (T.pack . List.intersperse x $ xs)++    describe "T.intercalate" $ do+        prop "T.intercalate === List.intercalate" $ \ xs ys ->+            (T.intercalate (T.pack ys) $ List.map T.pack xs)  ===+                (T.pack . List.intercalate ys $ xs)++    describe "T.intercalateElem" $ do+        prop "T.intercalateElem x === List.intercalate [x]" $ \ xs x ->+            (T.intercalateElem x $ List.map T.pack xs)  ===+                (T.pack . List.intercalate [x] $ xs)++    describe "T.transpose" $ do+        prop "T.transpose === List.transpose" $ \ xss ->+            (T.transpose $ List.map T.pack xss)  === (List.map T.pack $ List.transpose xss)+
+ test/Std/Data/Text/SearchSpec.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.Data.Text.SearchSpec where++import qualified Data.List                as List+import           Data.Word+import qualified Std.Data.Text.Base        as T+import qualified Std.Data.Text.Extra        as T+import qualified Std.Data.Text.Search      as T+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++spec :: Spec+spec = describe "text-search" $ do++    describe "T.elem == List.elem" $ do+        prop "T.elem = List.elem" $ \ y x ->+            (T.elem y $ T.pack x) === (List.elem y $ x)++    describe "snd . T.find == List.find" $ do+        prop "snd .T.find = List.find" $ \ (Fun _ y) x ->+            (case T.find y . T.pack $ x of (_, _, c) -> c)  === (List.find y $ x)++    describe "T.find" $ do+        prop "T.find = maybe List.length List.findIndexOrEnd" $ \ (Fun _ y) x ->+            (case T.find y . T.pack $ x of (i,_,_) -> i) ===+                (maybe (List.length x) id $ List.findIndex y x)++    describe "T.findR" $ do+        prop "T.find = findR . reverse" $ \ (Fun _ y) x ->+            (case T.find y . T.pack $ x of (i,_,_) -> i) ===+                (case T.findR y . T.reverse $ T.pack x of (i,_,_) -> i)++    describe "T.filter == List.filter" $ do+        prop "T.filter = List.filter" $ \ (Fun _ y) x ->+            (T.filter y . T.pack $ x) === (T.pack $ List.filter y $ x)++    describe "T.partition == List.partition" $ do+        prop "T.partition = List.partition" $ \ (Fun _ y) x ->+            (T.partition y . T.pack $ x) ===+                (let (a,b) = List.partition y $ x in (T.pack a, T.pack b))+
+ test/Std/Data/Vector/BaseSpec.hs view
@@ -0,0 +1,285 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.Data.Vector.BaseSpec where++import qualified Data.List                as List+import           Data.Word+import           Data.Hashable            (hashWithSalt, hash)+import qualified Std.Data.Vector.Base     as V+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++spec :: Spec+spec = describe "vector-base" $ do+    describe "vector Eq Ord property" $ do+        prop "vector eq === List.eq" $ \ xs ys ->+            (V.pack @V.Vector @Integer xs == V.pack ys) === (xs == ys)+        prop "vector eq === List.eq" $ \ xs ys ->+            (V.pack @V.PrimVector @Int xs == V.pack ys) === (xs == ys)+        prop "vector eq === List.eq" $ \ xs ys ->+            (V.pack @V.PrimVector @Word8 xs == V.pack ys) === (xs == ys)++        prop "vector compare === List.compare" $ \ xs ys ->+            (V.pack @V.Vector @Integer xs `compare` V.pack ys) === (xs `compare` ys)+        prop "vector compare === List.compare" $ \ xs ys ->+            (V.pack @V.PrimVector @Int xs `compare` V.pack ys) === (xs `compare` ys)+        prop "vector compare === List.compare" $ \ xs ys ->+            (V.pack @V.PrimVector @Word8 xs `compare` V.pack ys) === (xs `compare` ys)++    describe "vector unpack(R) . pack(R)(N) == id" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "unpack . pack === id" $ \ xs ->+            (V.unpack @V.Vector @Integer) (V.pack xs)  === xs+        prop "unpack . pack === id" $ \ xs ->+            (V.unpack @V.PrimVector @Int) (V.pack xs)  === xs+        prop "unpack . pack === id" $ \ xs ->+            (V.unpack @V.PrimVector @Word8) (V.pack xs)  === xs++        prop "unpackR . packR === id" $ \ xs ->+            (V.unpackR @V.Vector @Integer) (V.packR xs)  === xs+        prop "unpackR . packR === id" $ \ xs ->+            (V.unpackR @V.PrimVector @Int) (V.packR xs)  === xs+        prop "unpackR . packR === id" $ \ xs ->+            (V.unpackR @V.PrimVector @Word8) (V.packR xs)  === xs++    describe "vector pack == packN" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "pack === packN XX" $ \ xs d ->+            (V.pack @V.Vector @Integer xs) === (V.packN d xs)+        prop "pack === packN XX" $ \ xs d ->+            (V.pack @V.PrimVector @Int xs) === (V.packN d xs)+        prop "pack === packN XX" $ \ xs d ->+            (V.pack @V.PrimVector @Word8 xs) === (V.packN d xs)++        prop "packR === packRN XX" $ \ xs d ->+            (V.packR @V.Vector @Integer xs) === (V.packRN d xs)+        prop "packR === packRN XX" $ \ xs d ->+            (V.packR @V.PrimVector @Int xs) === (V.packRN d xs)+        prop "packR === packRN XX" $ \ xs d ->+            (V.packR @V.PrimVector @Word8 xs) === (V.packRN d xs)++    describe "Bytes Hashable instance property" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do++        prop "Vector Word8's hash should be equal to hashWithSalt (Bytes's one) (Bytes's length)" $ \ xs ->+            hash (V.pack @V.Vector @Word8 xs) === hashWithSalt (hash (V.pack @V.PrimVector @Word8 xs)) (List.length xs)+        prop "Vector a's hash should be equal to [a]'s hash" $ \ xs ->+            hash (V.pack @V.Vector @Word8 xs) === hash xs+        prop "Vector a's hash should be equal to [a]'s hash" $ \ xs ->+            hash (V.pack @V.Vector @Int xs) === hash xs+        prop "Vector a's hash should be equal to [a]'s hash" $ \ xs ->+            hash (V.pack @V.Vector @Integer xs) === hash xs+++    describe "Bytes IsString instance property" $ do+        prop "ASCII string" $+            "hello world" === V.pack @V.PrimVector (List.map V.c2w "hello world")+        prop "UTF8 string" $+            "你好世界" === V.pack @V.PrimVector (List.map V.c2w "你好世界")++    describe "vector length == List.length" $ do+        prop "vector length === List.length" $ \ xs ->+            (V.length $ V.pack @V.Vector @Integer xs)  ===  List.length xs+        prop "vector length === List.length" $ \ xs ->+            (V.length $ V.pack @V.PrimVector @Int xs)  ===  List.length xs+        prop "vector length === List.length" $ \ xs ->+            (V.length $ V.pack @V.PrimVector @Word8 xs)  ===  List.length xs++    describe "vector append == List.(++)" $ do+        prop "vector eq === List.eq" $ \ xs ys ->+            (V.unpack $ V.pack @V.Vector @Integer xs `V.append` V.pack ys) === (xs ++ ys)+        prop "vector eq === List.eq" $ \ xs ys ->+            (V.unpack $ V.pack @V.PrimVector @Int xs `V.append` V.pack ys) === (xs ++ ys)+        prop "vector eq === List.eq" $ \ xs ys ->+            (V.unpack $ V.pack @V.PrimVector @Word8 xs `V.append` V.pack ys) === (xs ++ ys)++    describe "vector map/map' == List.map" $ do+        prop "vector map === List.map" $ \ xs (Fun _ f) ->+            (V.map @V.Vector @V.Vector (f :: Integer -> Integer) $ V.pack @V.Vector @Integer xs) ===+                (V.pack $ List.map f xs)+        prop "vector map' === List.map" $ \ xs (Fun _ f) ->+            (V.map' @V.Vector @V.Vector (f :: Integer -> Integer) $ V.pack @V.Vector @Integer xs) ===+                (V.pack $ List.map f xs)+        prop "vector map === List.map" $ \ xs (Fun _ f)  ->+            (V.map @V.PrimVector @V.PrimVector (f :: Int -> Word8) $ V.pack @V.PrimVector @Int xs) ===+                (V.pack $ List.map f xs)+        prop "vector map === List.map" $ \ xs (Fun _ f) ->+            (V.map @V.PrimVector @V.PrimVector (f :: Word8 -> Int) $ V.pack @V.PrimVector @Word8 xs) ===+                (V.pack $ List.map f xs)+        prop "vector map === List.map" $ \ xs (Fun _ f) ->+            (V.map @V.PrimVector @V.Vector (f :: Word8 -> Integer) $ V.pack @V.PrimVector @Word8 xs) ===+                (V.pack $ List.map f xs)+        prop "vector map === List.map" $ \ xs (Fun _ f) ->+            (V.map @V.Vector @V.PrimVector (f :: Integer -> Word8) $ V.pack @V.Vector @Integer xs) ===+                (V.pack $ List.map f xs)++    describe "vector imap' (const f) == List.map f" $ do+        prop "vector imap' (const f) == List.map f" $ \ xs (Fun _ f) ->+            (V.imap' @V.Vector @V.PrimVector (const (f :: Integer -> Word8)) $ V.pack @V.Vector @Integer xs) ===+                (V.pack $ List.map f xs)++    describe "vector imap' const == List.zipWith const [0..]" $ do+        prop "vector imap' const == List.zipWith const [0..]" $ \ xs ->+            (V.imap' @V.Vector @V.PrimVector const $ V.pack @V.Vector @Integer xs) ===+                (V.pack $ List.zipWith const [0..] xs)++    describe "vector foldl' == List.foldl'" $ do+        prop "vector foldl' === List.foldl'" $ \ xs f x ->+            (V.foldl' (applyFun2 f :: Integer -> Integer -> Integer) x . V.pack @V.Vector @Integer $ xs)  ===+                (List.foldl' (applyFun2 f) x $ xs)+        prop "vector foldl' x === List.foldl' x" $ \ xs f x ->+            (V.foldl' (applyFun2 f :: Int -> Int -> Int) x . V.pack @V.PrimVector @Int $ xs)  ===+                (List.foldl' (applyFun2 f) x $ xs)+        prop "vector foldl' x === List.foldl' x" $ \ xs f x ->+            (V.foldl' (applyFun2 f :: Int -> Word8 -> Int) x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (List.foldl' (applyFun2 f) x $ xs)++    describe "vector foldr' == List.foldr'" $ do+        prop "vector foldr' === List.foldr" $ \ xs f x ->+            (V.foldr' (applyFun2 f :: Integer -> Integer -> Integer) x . V.pack @V.Vector @Integer $ xs)  ===+                (List.foldr (applyFun2 f) x $ xs)+        prop "vector foldr' x === List.foldr' x" $ \ xs f x ->+            (V.foldr' (applyFun2 f :: Int -> Int -> Int) x . V.pack @V.PrimVector @Int $ xs)  ===+                (List.foldr (applyFun2 f) x $ xs)+        prop "vector foldr' x === List.foldr' x" $ \ xs f x ->+            (V.foldr' (applyFun2 f :: Word8 -> Int -> Int) x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (List.foldr (applyFun2 f) x $ xs)++    describe "vector concat == List.concat" $ do+        prop "vector concat === List.concat" $ \ xss ->+            (V.concat . List.map (V.pack @V.Vector @Integer) $ xss)  === (V.pack . List.concat $ xss)+        prop "vector concat === List.concat" $ \ xss ->+            (V.concat . List.map (V.pack @V.PrimVector @Int) $ xss) === (V.pack . List.concat $ xss)+        prop "vector concat === List.concat" $ \ xss ->+            (V.concat . List.map (V.pack @V.PrimVector @Word8) $ xss) === (V.pack . List.concat $ xss)++    describe "vector concatMap == List.concatMap" $ do+        prop "vector concatMap === List.concatMap" $ \ xss (Fun _ f) ->+            (V.concatMap (V.pack @V.Vector @Integer . f) . V.pack $ xss)  === (V.pack . List.concatMap f $ xss)+        prop "vector concatMap === List.concatMap" $ \ xss (Fun _ f) ->+            (V.concatMap (V.pack @V.PrimVector @Int . f) . V.pack $ xss) === (V.pack . List.concatMap f $ xss)+        prop "vector concatMap === List.concatMap" $ \ xss (Fun _ f) ->+            (V.concatMap (V.pack @V.PrimVector @Word8 . f) . V.pack $ xss) === (V.pack . List.concatMap f $ xss)++    describe "vector all == List.all" $ do+        prop "vector all === List.all" $ \ xs (Fun _ f) ->+            (V.all f . V.pack @V.Vector @Integer $ xs)  === (List.all f $ xs)+        prop "vector all === List.all" $ \ xs (Fun _ f) ->+            (V.all f . V.pack @V.PrimVector @Int $ xs)  === (List.all f $ xs)+        prop "vector all === List.all" $ \ xs (Fun _ f) ->+            (V.all f . V.pack @V.PrimVector @Word8 $ xs)  === (List.all f $ xs)++    describe "vector any == List.any" $ do+        prop "vector any === List.any" $ \ xs (Fun _ f) ->+            (V.any f . V.pack @V.Vector @Integer $ xs)  === (List.any f $ xs)+        prop "vector any === List.any" $ \ xs (Fun _ f) ->+            (V.any f . V.pack @V.PrimVector @Int $ xs)  === (List.any f $ xs)+        prop "vector any === List.any" $ \ xs (Fun _ f) ->+            (V.any f . V.pack @V.PrimVector @Word8 $ xs)  === (List.any f $ xs)++    describe "vector sum == Prelude.sum" $ do+        prop "vector sum === List.sum" $ \ xs ->+            (V.sum . V.pack @V.Vector @Integer $ xs)  === (sum $ xs)+        prop "vector sum === List.sum" $ \ xs ->+            (V.sum . V.pack @V.PrimVector @Int $ xs)  === (sum $ xs)+        prop "vector sum === List.sum" $ \ xs ->+            (V.sum . V.pack @V.PrimVector @Word8 $ xs)  === (sum $ xs)++    describe "vector product == Prelude.product" $ do+        prop "vector product === List.product" $ \ xs ->+            (V.product . V.pack @V.Vector @Integer $ xs)  === (product $ xs)+        prop "vector product === List.product" $ \ xs ->+            (V.product . V.pack @V.PrimVector @Int $ xs)  === (product $ xs)+        prop "vector product === List.product" $ \ xs ->+            (V.product . V.pack @V.PrimVector @Word8 $ xs)  === (product $ xs)++    describe "vector product' == Prelude.product" $ do+        prop "vector product' === List.product" $ \ xs ->+            (V.product' . V.pack @V.Vector @Integer $ xs)  === (product $ xs)+        prop "vector product === List.product" $ \ xs ->+            (V.product' . V.pack @V.PrimVector @Int $ xs)  === (product $ xs)+        prop "vector product === List.product" $ \ xs ->+            (V.product' . V.pack @V.PrimVector @Word8 $ xs)  === (product $ xs)++    describe "vector maximumMaybe == Just . List.maximum" $ do+        prop "vector maximumMaybe === Just . List.maximum" $ \ (NonEmpty xs) ->+            (V.maximumMaybe . V.pack @V.Vector @Integer $ xs)  === (Just . List.maximum $ xs)+        prop "vector maximumMaybe === Just . List.maximum" $ \ (NonEmpty xs) ->+            (V.maximumMaybe . V.pack @V.PrimVector @Int $ xs)  === (Just . List.maximum $ xs)+        prop "vector maximumMaybe === Just . List.maximum" $ \ (NonEmpty xs) ->+            (V.maximumMaybe . V.pack @V.PrimVector @Word8 $ xs)  === (Just . List.maximum $ xs)++    describe "vector minimumMaybe == Just . List.minimum" $ do+        prop "vector minimumMaybe === Just . List.minimum" $ \ (NonEmpty xs) ->+            (V.minimumMaybe . V.pack @V.Vector @Integer $ xs)  === (Just . List.minimum $ xs)+        prop "vector minimumMaybe === Just . List.minimum" $ \ (NonEmpty xs) ->+            (V.minimumMaybe . V.pack @V.PrimVector @Int $ xs)  === (Just . List.minimum $ xs)+        prop "vector minimumMaybe === Just . List.minimum" $ \ (NonEmpty xs) ->+            (V.minimumMaybe . V.pack @V.PrimVector @Word8 $ xs)  === (Just . List.minimum $ xs)++    describe "vector count x == List.length . List.filter (==x)" $ do+        prop "vector count === List.length . List.filter (==x)" $ \ xs x ->+            (V.count x . V.pack @V.Vector @Integer $ xs)  === (List.length . List.filter (==x) $ xs)+        prop "vector count === List.length . List.filter (==x)" $ \ xs x ->+            (V.count x . V.pack @V.PrimVector @Int $ xs)  === (List.length . List.filter (==x) $ xs)+        prop "vector count === List.length . List.filter (==x)" $ \ xs x ->+            (V.count x . V.pack @V.PrimVector @Word8 $ xs)  === (List.length . List.filter (==x) $ xs)++    describe "vector mapAccumL == List.mapAccumL" $ do+        prop "vector mapAccumL === Just . List.mapAccumL" $ \ xs x f ->+            (V.unpack @V.Vector <$> (V.mapAccumL (applyFun2 f) x . V.pack @V.Vector @Integer $ xs))+                === (List.mapAccumL (applyFun2 f) x xs :: (Integer, [Integer]))+        prop "vector mapAccumL === Just . List.mapAccumL" $ \ xs x f ->+            (V.unpack @V.PrimVector <$> (V.mapAccumL (applyFun2 f) x . V.pack @V.PrimVector @Int $ xs))+                === (List.mapAccumL (applyFun2 f) x xs :: (Int, [Int]))+        prop "vector mapAccumL === Just . List.mapAccumL" $ \ xs x f ->+            (V.unpack @V.PrimVector <$> (V.mapAccumL (applyFun2 f) x . V.pack @V.PrimVector @Word8 $ xs))+                === (List.mapAccumL (applyFun2 f) x xs :: (Word8, [Word8]))++    describe "vector mapAccumR == List.mapAccumR" $ do+        prop "vector mapAccumR === Just . List.mapAccumR" $ \ xs x f ->+            (V.unpack @V.Vector <$> (V.mapAccumR (applyFun2 f) x . V.pack @V.Vector @Integer $ xs))+                === (List.mapAccumR (applyFun2 f) x xs :: (Integer, [Integer]))+        prop "vector mapAccumR === Just . List.mapAccumR" $ \ xs x f ->+            (V.unpack @V.PrimVector <$> (V.mapAccumR (applyFun2 f) x . V.pack @V.PrimVector @Int $ xs))+                === (List.mapAccumR (applyFun2 f) x xs :: (Int, [Int]))+        prop "vector mapAccumR === Just . List.mapAccumR" $ \ xs x f ->+            (V.unpack @V.PrimVector <$> (V.mapAccumR (applyFun2 f) x . V.pack @V.PrimVector @Word8 $ xs))+                === (List.mapAccumR (applyFun2 f) x xs :: (Word8, [Word8]))++    describe "vector replicate == List.replicate" $ do+        prop "vector replicate = List.replicate" $ \ n x ->+            (V.unpack . V.replicate @V.Vector @Integer n $ x)  === (List.replicate n $ x)+        prop "vector replicate = List.replicate" $ \ n x ->+            (V.unpack . V.replicate @V.PrimVector @Int n $ x)  === (List.replicate n $ x)+        prop "vector replicate = List.replicate" $ \ n x ->+            (V.unpack . V.replicate @V.PrimVector @Word8 n $ x)  === (List.replicate n $ x)++    describe "vector unfoldrN n == List.take n . List.unfoldr" $ do+        prop "vector unfoldrN n == List.take n . List.unfoldr" $ \ (Fun _ f) (x :: Integer) n ->+            (V.unpack . fst . V.unfoldrN @V.Vector @Integer @Integer n f $ x)+                === (List.take n . List.unfoldr f $ x)+        prop "vector unfoldrN n == List.take n . List.unfoldr" $ \ (Fun _ f) (x :: Int) n ->+            (V.unpack . fst . V.unfoldrN @V.PrimVector @Int @Int n f $ x)+                === (List.take n . List.unfoldr f $ x)+        prop "vector unfoldrN n == List.take n . List.unfoldr" $ \ (Fun _ f) (x :: Word8) n ->+            (V.unpack . fst . V.unfoldrN @V.PrimVector @Word8 @Word8 n f $ x)+                === (List.take n . List.unfoldr f $ x)++    describe "vector elem == List.elem" $ do+        prop "vector elem = List.elem" $ \ y x ->+            (V.elem y . V.pack @V.Vector @Integer $ x)  === (List.elem y $ x)+        prop "vector elem = List.elem" $ \ y x ->+            (V.elem y . V.pack @V.PrimVector @Int $ x)  === (List.elem y $ x)+        prop "vector elem = List.elem" $ \ y x ->+            (V.elem y . V.pack @V.PrimVector @Word8 $ x)  === (List.elem y $ x)++    describe "vector elemIndex == List.elemIndex" $ do+        prop "vector elemIndex = List.elemIndex" $ \ y x ->+            (V.elemIndex y . V.pack @V.Vector @Integer $ x)  === (List.elemIndex y $ x)+        prop "vector elemIndex = List.elemIndex" $ \ y x ->+            (V.elemIndex y . V.pack @V.PrimVector @Int $ x)  === (List.elemIndex y $ x)+        prop "vector elemIndex = List.elemIndex" $ \ y x ->+            (V.elemIndex y . V.pack @V.PrimVector @Word8 $ x)  === (List.elemIndex y $ x)
+ test/Std/Data/Vector/ExtraSpec.hs view
@@ -0,0 +1,532 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.Data.Vector.ExtraSpec where++import qualified Data.List                as List+import           Data.Word+import qualified Std.Data.Vector          as V+import qualified Std.Data.Vector.Base     as V+import qualified Std.Data.Vector.Extra    as V+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++spec :: Spec+spec =  describe "vector-extras" $ do+    describe "vector cons == List.(:)" $ do+        prop "vector cons == List.(:)" $ \ xs x ->+            (V.cons x . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . (:) x $ xs)+        prop "vector cons == List.(:)" $ \ xs x ->+            (V.cons x . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . (:) x $ xs)+        prop "vector cons == List.(:)" $ \ xs x ->+            (V.cons x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . (:) x $ xs)++    describe "vector snoc == List.++" $ do+        prop "vector snoc == List.++" $ \ xs x ->+            ((`V.snoc` x) . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . (++ [x]) $ xs)+        prop "vector snoc == List.++" $ \ xs x ->+            ((`V.snoc` x) . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . (++ [x]) $ xs)+        prop "vector snoc == List.++" $ \ xs x ->+            ((`V.snoc` x) . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . (++ [x]) $ xs)++    describe "vector headMaybe == Just. List.head" $ do+        prop "vector headMaybe === Just . list.head" $ \ (NonEmpty xs) ->+            (V.headMaybe . V.pack @V.Vector @Integer $ xs)  ===+                (Just . List.head $ xs)+        prop "vector headMaybe === Just . List.head" $ \ (NonEmpty xs) ->+            (V.headMaybe . V.pack @V.PrimVector @Int $ xs)  ===+                (Just . List.head $ xs)+        prop "vector headMaybe === Just . List.head" $ \ (NonEmpty xs) ->+            (V.headMaybe . V.pack @V.PrimVector @Word8 $ xs)  ===+                (Just . List.head $ xs)++    describe "vector initMayEmpty == List.init" $ do+        prop "vector initMayEmpty === List.init" $ \ (NonEmpty xs) ->+            (V.initMayEmpty . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.init $ xs)+        prop "vector initMayEmpty === List.init" $ \ (NonEmpty xs) ->+            (V.initMayEmpty . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.init $ xs)+        prop "vector initMayEmpty === List.init" $ \ (NonEmpty xs) ->+            (V.initMayEmpty . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.init $ xs)++    describe "vector lastMaybe == Just. List.last" $ do+        prop "vector lastMaybe === Just . list.last" $ \ (NonEmpty xs) ->+            (V.lastMaybe . V.pack @V.Vector @Integer $ xs)  ===+                (Just . List.last $ xs)+        prop "vector lastMaybe === Just . List.last" $ \ (NonEmpty xs) ->+            (V.lastMaybe . V.pack @V.PrimVector @Int $ xs)  ===+                (Just . List.last $ xs)+        prop "vector lastMaybe === Just . List.last" $ \ (NonEmpty xs) ->+            (V.lastMaybe . V.pack @V.PrimVector @Word8 $ xs)  ===+                (Just . List.last $ xs)++    describe "vector tailMayEmpty == List.tail" $ do+        prop "vector tailMayEmpty === List.tail" $ \ (NonEmpty xs) ->+            (V.tailMayEmpty . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.tail $ xs)+        prop "vector tailMayEmpty === List.tail" $ \ (NonEmpty xs) ->+            (V.tailMayEmpty . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.tail $ xs)+        prop "vector tailMayEmpty === List.tail" $ \ (NonEmpty xs) ->+            (V.tailMayEmpty . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.tail $ xs)++    describe "vector take == List.take" $ do+        prop "vector take == List.take" $ \ xs x ->+            (V.take x . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.take x $ xs)+        prop "vector take == List.take" $ \ xs x ->+            (V.take x . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.take x $ xs)+        prop "vector take == List.take" $ \ xs x ->+            (V.take x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.take x $ xs)++    describe "vector takeR x == List.reverse . List.take x . List.reverse" $ do+        prop "vector takeR x == List.reverse . List.take x . List.reverse" $ \ xs x ->+            (V.takeR x . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.reverse . List.take x . List.reverse $ xs)+        prop "vector takeR x == List.reverse . List.take x . List.reverse" $ \ xs x ->+            (V.takeR x . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.reverse . List.take x . List.reverse $ xs)+        prop "vector takeR x == List.reverse . List.take x . List.reverse" $ \ xs x ->+            (V.takeR x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.reverse . List.take x . List.reverse $ xs)++    describe "vector drop == List.drop" $ do+        prop "vector drop == List.drop" $ \ xs x ->+            (V.drop x . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.drop x $ xs)+        prop "vector drop == List.drop" $ \ xs x ->+            (V.drop x . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.drop x $ xs)+        prop "vector drop == List.drop" $ \ xs x ->+            (V.drop x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.drop x $ xs)++    describe "vector dropR x == List.reverse . List.drop x . List.reverse" $ do+        prop "vector dropR x == List.reverse . List.drop x . List.reverse" $ \ xs x ->+            (V.dropR x . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.reverse . List.drop x . List.reverse $ xs)+        prop "vector dropR x == List.reverse . List.drop x . List.reverse" $ \ xs x ->+            (V.dropR x . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.reverse . List.drop x . List.reverse $ xs)+        prop "vector dropR x == List.reverse . List.drop x . List.reverse" $ \ xs x ->+            (V.dropR x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.reverse . List.drop x . List.reverse $ xs)++    describe "vector slice x y == drop x . take (x+y)" $ do+        prop "vector slice x y === drop x . take (x+y)" $ \ x y xs ->+            (V.slice x y  . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . drop x . take (x+y) $ xs)+        prop "vector slice x y xs === drop x . take (x+y) x" $ \ x y xs ->+            (V.slice x y  . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . drop x . take (x+y) $ xs)+        prop "vector slice x y xs === drop x . take (x+y) x" $ \ x y xs ->+            (V.slice x y  . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . drop x . take (x+y) $ xs)++    describe "vector splitAt == List.splitAt" $ do+        prop "vector splitAt == List.splitAt" $ \ xs x ->+            (V.splitAt x . V.pack @V.Vector @Integer $ xs)  ===+                (let (a,b) = List.splitAt x $ xs in (V.pack a, V.pack b))+        prop "vector splitAt == List.splitAt" $ \ xs x ->+            (V.splitAt x . V.pack @V.PrimVector @Int $ xs)  ===+                (let (a,b) = List.splitAt x $ xs in (V.pack a, V.pack b))+        prop "vector splitAt == List.splitAt" $ \ xs x ->+            (V.splitAt x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (let (a,b) = List.splitAt x $ xs in (V.pack a, V.pack b))++    describe "vector takeWhile == List.takeWhile" $ do+        prop "vector takeWhile == List.takeWhile" $ \ xs (Fun _ x) ->+            (V.takeWhile x . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.takeWhile x $ xs)+        prop "vector takeWhile == List.takeWhile" $ \ xs (Fun _ x) ->+            (V.takeWhile x . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.takeWhile x $ xs)+        prop "vector takeWhile == List.takeWhile" $ \ xs (Fun _ x) ->+            (V.takeWhile x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.takeWhile x $ xs)++    describe "vector takeWhileR == reverse . List.takeWhile . reverse" $ do+        prop "vector takeWhileR == reverse . List.takeWhile . reverse" $ \ xs (Fun _ x) ->+            (V.takeWhileR x . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.reverse . List.takeWhile x $ List.reverse xs)+        prop "vector takeWhileR == reverse . List.takeWhile . reverse" $ \ xs (Fun _ x) ->+            (V.takeWhileR x . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.reverse . List.takeWhile x $ List.reverse xs)+        prop "vector takeWhileR == reverse . List.takeWhile . reverse" $ \ xs (Fun _ x) ->+            (V.takeWhileR x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.reverse . List.takeWhile x $ List.reverse xs)++    describe "vector dropWhile == List.dropWhile" $ do+        prop "vector dropWhile == List.dropWhile" $ \ xs (Fun _ x) ->+            (V.dropWhile x . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.dropWhile x $ xs)+        prop "vector dropWhile == List.dropWhile" $ \ xs (Fun _ x) ->+            (V.dropWhile x . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.dropWhile x $ xs)+        prop "vector dropWhile == List.dropWhile" $ \ xs (Fun _ x) ->+            (V.dropWhile x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.dropWhile x $ xs)++    describe "vector dropWhileR == reverse . List.dropWhile . reverse" $ do+        prop "vector dropWhileR == reverse . List.dropWhile . reverse" $ \ xs (Fun _ x) ->+            (V.dropWhileR x . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.reverse . List.dropWhile x $ List.reverse xs)+        prop "vector dropWhileR == reverse . List.dropWhile . reverse" $ \ xs (Fun _ x) ->+            (V.dropWhileR x . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.reverse . List.dropWhile x $ List.reverse xs)+        prop "vector dropWhileR == reverse . List.dropWhile . reverse" $ \ xs (Fun _ x) ->+            (V.dropWhileR x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.reverse . List.dropWhile x $ List.reverse xs)++    describe "vector break == List.break" $ do+        prop "vector break == List.break" $ \ xs (Fun _ x) ->+            (V.break x . V.pack @V.Vector @Integer $ xs)  ===+                (let (a,b) = List.break x $ xs in (V.pack a, V.pack b))+        prop "vector break == List.break" $ \ xs (Fun _ x) ->+            (V.break x . V.pack @V.PrimVector @Int $ xs)  ===+                (let (a,b) = List.break x $ xs in (V.pack a, V.pack b))+        prop "vector break == List.break" $ \ xs (Fun _ x) ->+            (V.break x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (let (a,b) = List.break x $ xs in (V.pack a, V.pack b))++    describe "vector breakOn rules" $ do+        prop "vector breakOn rules" $ \ xs ys ->+            (let (a, b) = V.breakOn (V.pack xs) . V.pack @V.Vector @Integer $ ys+             in (a `V.append` b, V.pack xs `V.isPrefixOf` b || V.null b) === (V.pack ys, True))+        prop "vector breakOn rules" $ \ xs ys ->+            (let (a, b) = V.breakOn (V.pack xs) . V.pack @V.PrimVector @Int $ ys+             in (a `V.append` b, V.pack xs `V.isPrefixOf` b || V.null b) === (V.pack ys, True))+        prop "vector breakOn rules" $ \ xs ys ->+            (let (a, b) = V.breakOn (V.pack xs) . V.pack @V.PrimVector @Word8 $ ys+             in (a `V.append` b, V.pack xs `V.isPrefixOf` b || V.null b) === (V.pack ys, True))++    describe "vector span == List.span" $ do+        prop "vector span == List.span" $ \ xs (Fun _ x) ->+            (V.span x . V.pack @V.Vector @Integer $ xs)  ===+                (let (a,b) = List.span x $ xs in (V.pack a, V.pack b))+        prop "vector span == List.span" $ \ xs (Fun _ x) ->+            (V.span x . V.pack @V.PrimVector @Int $ xs)  ===+                (let (a,b) = List.span x $ xs in (V.pack a, V.pack b))+        prop "vector span == List.span" $ \ xs (Fun _ x) ->+            (V.span x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (let (a,b) = List.span x $ xs in (V.pack a, V.pack b))++    describe "vector breakR == List.break in reverse driection" $ do+        prop "vector breakR == List.break in reverse driection" $ \ xs (Fun _ x) ->+            (V.breakR x . V.pack @V.Vector @Integer $ xs)  ===+                (let (b,a) = List.break x . List.reverse $ xs+                 in (V.reverse $ V.pack a, V.reverse $ V.pack b))+        prop "vector breakR == List.break in reverse driection" $ \ xs (Fun _ x) ->+            (V.breakR x . V.pack @V.PrimVector @Int $ xs)  ===+                (let (b,a) = List.break x . List.reverse $ xs+                 in (V.reverse $ V.pack a, V.reverse $ V.pack b))+        prop "vector breakR == List.break in reverse driection" $ \ xs (Fun _ x) ->+            (V.breakR x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (let (b,a) = List.break x . List.reverse $ xs+                 in (V.reverse $ V.pack a, V.reverse $ V.pack b))++    describe "vector spanR == List.span in reverse driection" $ do+        prop "vector spanR == List.span in reverse driection" $ \ xs (Fun _ x) ->+            (V.spanR x . V.pack @V.Vector @Integer $ xs)  ===+                (let (b,a) = List.span x . List.reverse $ xs+                 in (V.reverse $ V.pack a, V.reverse $ V.pack b))+        prop "vector spanR == List.span in reverse driection" $ \ xs (Fun _ x) ->+            (V.spanR x . V.pack @V.PrimVector @Int $ xs)  ===+                (let (b,a) = List.span x . List.reverse $ xs+                 in (V.reverse $ V.pack a, V.reverse $ V.pack b))+        prop "vector spanR == List.span in reverse driection" $ \ xs (Fun _ x) ->+            (V.spanR x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (let (b,a) = List.span x . List.reverse $ xs+                 in (V.reverse $ V.pack a, V.reverse $ V.pack b))++    describe "vector group == List.group" $ do+        prop "vector group == List.group" $ \ xs ->+            (V.group . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack <$> List.group xs)+        prop "vector group == List.group" $ \ xs ->+            (V.group . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack <$> List.group xs)+        prop "vector group == List.group" $ \ xs ->+            (V.group . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack <$> List.group xs)++    describe "vector groupBy == List.groupBy" $ do+        prop "vector groupBy == List.groupBy" $ \ xs x ->+            (V.groupBy (applyFun2 x) . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack <$> List.groupBy (applyFun2 x) xs)+        prop "vector groupBy == List.groupBy" $ \ xs x ->+            (V.groupBy (applyFun2 x) . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack <$> List.groupBy (applyFun2 x) xs)+        prop "vector groupBy == List.groupBy" $ \ xs x ->+            (V.groupBy (applyFun2 x) . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack <$> List.groupBy (applyFun2 x) xs)++    describe "vector stripPrefix a (a+b) = b " $ do+        prop "vector stripPrefix == List.stripPrefix" $ \ xs ys ->+            (V.stripPrefix (V.pack xs) . V.pack @V.Vector @Integer $ xs++ys) ===+                (Just $ V.pack ys)+        prop "vector stripPrefix == List.stripPrefix" $ \ xs ys ->+            (V.stripPrefix (V.pack xs) . V.pack @V.PrimVector @Int $ xs++ys) ===+                (Just $ V.pack ys)+        prop "vector stripPrefix == List.stripPrefix" $ \ xs ys ->+            (V.stripPrefix (V.pack xs) . V.pack @V.PrimVector @Word8 $ xs++ys) ===+                (Just $ V.pack ys)++    describe "vector stripSuffix b (a+b) = a " $ do+        prop "vector stripSuffix == List.stripSuffix" $ \ xs ys ->+            (V.stripSuffix (V.pack xs) . V.pack @V.Vector @Integer $ ys++xs) ===+                (Just $ V.pack ys)+        prop "vector stripSuffix == List.stripSuffix" $ \ xs ys ->+            (V.stripSuffix (V.pack xs) . V.pack @V.PrimVector @Int $ ys++xs) ===+                (Just $ V.pack ys)+        prop "vector stripSuffix == List.stripSuffix" $ \ xs ys ->+            (V.stripSuffix (V.pack xs) . V.pack @V.PrimVector @Word8 $ ys++xs) ===+                (Just $ V.pack ys)++    describe "vector isInfixOf b (a+b+c) = True " $ do+        prop "vector isInfixOf == List.isInfixOf" $ \ xs ys zs ->+            (V.isInfixOf (V.pack xs) . V.pack @V.Vector @Integer $ ys++xs++zs) === True+        prop "vector isInfixOf == List.isInfixOf" $ \ xs ys zs ->+            (V.isInfixOf (V.pack xs) . V.pack @V.PrimVector @Int $ ys++xs++zs) === True+        prop "vector isInfixOf == List.isInfixOf" $ \ xs ys zs ->+            (V.isInfixOf (V.pack xs) . V.pack @V.PrimVector @Word8 $ ys++xs++zs) === True++    describe "let (c,a,b) = vector commonPrefix x y in (a,b) = (stripPrefix c x,stripPrefix c y) " $ do+        prop "vector commonPrefix rules" $ \ xs ys ->+            let (c,a,b) = V.commonPrefix (V.pack xs) . V.pack @V.Vector @Integer $ ys+                Just xs' = V.stripPrefix c $ V.pack xs+                Just ys' = V.stripPrefix c $ V.pack ys+            in (a,b) === (xs', ys')+        prop "vector commonPrefix rules" $ \ xs ys ->+            let (c,a,b) = V.commonPrefix (V.pack xs) . V.pack @V.PrimVector @Int $ ys+                Just xs' = V.stripPrefix c $ V.pack xs+                Just ys' = V.stripPrefix c $ V.pack ys+            in (a,b) === (xs', ys')+        prop "vector commonPrefix rules" $ \ xs ys ->+            let (c,a,b) = V.commonPrefix (V.pack xs) . V.pack @V.PrimVector @Word8 $ ys+                Just xs' = V.stripPrefix c $ V.pack xs+                Just ys' = V.stripPrefix c $ V.pack ys+            in (a,b) === (xs', ys')++    describe "vector intercalate [x] . split x == id" $ do+        prop "vector intercalate [x] . split x == id" $ \ xs x ->+            (V.intercalate (V.singleton x) . V.split x . V.pack @V.Vector @Integer $ xs) ===+                V.pack xs+        prop "vector intercalate [x] . split x == id" $ \ xs x ->+            (V.intercalate (V.singleton x) . V.split x . V.pack @V.PrimVector @Int $ xs) ===+                V.pack xs+        prop "vector intercalate [x] . split x == id" $ \ xs x ->+            (V.intercalate (V.singleton x) . V.split x . V.pack @V.PrimVector @Word8 $ xs) ===+                V.pack xs++    describe "vector intercalate x . splitOn x == id" $ do+        prop "vector intercalate x . splitOn x == id" $ \ xs x ->+            (V.intercalate (V.pack x) . V.splitOn (V.pack x) . V.pack @V.Vector @Integer $ xs) ===+                V.pack xs+        prop "vector intercalate x . splitOn x == id" $ \ xs x ->+            (V.intercalate (V.pack x) . V.splitOn (V.pack x) . V.pack @V.PrimVector @Int $ xs) ===+                V.pack xs+        prop "vector intercalate x . splitOn x == id" $ \ xs x ->+            (V.intercalate (V.pack x) . V.splitOn (V.pack x) . V.pack @V.PrimVector @Word8 $ xs) ===+                V.pack xs++    describe "vector reverse . pack == packR" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "reverse . pack === packR XX" $ \ xs ->+            (V.reverse $ V.pack @V.Vector @Integer xs) === (V.packR xs)+        prop "reverse . pack === packR XX" $ \ xs ->+            (V.reverse $ V.pack @V.PrimVector @Int xs) === (V.packR xs)+        prop "reverse . pack === packR XX" $ \ xs ->+            (V.reverse $ V.pack @V.PrimVector @Word8 xs) === (V.packR xs)+++    describe "vector words == List.words" $ do+        prop "vector words === List.words" $ \ xs ->+            (V.words . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.map V.c2w <$> (List.words . List.map V.w2c $ xs))++    describe "vector lines == List.lines" $ do+        prop "vector lines === List.lines" $ \ xs ->+            (V.lines . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.map V.c2w <$> (List.lines . List.map V.w2c $ xs))++    describe "vector unwords == List.unwords" $ do+        prop "vector unwords === List.unwords" $ \ xs ->+            (V.unwords $ V.pack @V.PrimVector @Word8 <$> xs)  ===+                (V.pack (List.map V.c2w . List.unwords $ List.map V.w2c <$> xs))++    describe "vector unlines == List.unlines" $ do+        prop "vector unlines === List.unlines" $ \ xs ->+            (V.unlines $ V.pack @V.PrimVector @Word8 <$> xs)  ===+                (V.pack (List.map V.c2w . List.unlines $ List.map V.w2c <$> xs))++    describe "vector padLeft n x xs = if l >= n then xs else replicate (n-l) x ++ xs" $ do+        prop "vector padLeft n x xs = if l >= n then xs else replicate (n-l) x ++ xs" $ \ xs n x ->+            (V.padLeft n x . V.pack @V.Vector @Integer $ xs) ===+                (let l = List.length xs+                 in if l >= n then V.pack xs+                              else V.pack $ (List.replicate (n-l) x ++ xs))+        prop "vector padLeft n x xs = if l >= n then xs else replicate (n-l) x ++ xs" $ \ xs n x ->+            (V.padLeft n x . V.pack @V.PrimVector @Int $ xs) ===+                (let l = List.length xs+                 in if l >= n then V.pack xs+                              else V.pack $ (List.replicate (n-l) x ++ xs))+        prop "vector padLeft n x xs = if l >= n then xs else replicate (n-l) x ++ xs" $ \ xs n x ->+            (V.padLeft n x . V.pack @V.PrimVector @Word8 $ xs) ===+                (let l = List.length xs+                 in if l >= n then V.pack xs+                              else V.pack $ (List.replicate (n-l) x ++ xs))++    describe "vector padRight n x xs = if l >= n then xs else xs ++ List.replicate (n-l) x" $ do+        prop "vector padRight n x xs = if l >= n then xs else xs ++ List.replicate (n-l) x" $ \ xs n x ->+            (V.padRight n x . V.pack @V.Vector @Integer $ xs) ===+                (let l = List.length xs+                 in if l >= n then V.pack xs+                              else V.pack $ xs ++ (List.replicate (n-l) x))+        prop "vector padRight n x xs = if l >= n then xs else xs ++ List.replicate (n-l) x" $ \ xs n x ->+            (V.padRight n x . V.pack @V.PrimVector @Int $ xs) ===+                (let l = List.length xs+                 in if l >= n then V.pack xs+                              else V.pack $ xs ++ (List.replicate (n-l) x))+        prop "vector padRight n x xs = if l >= n then xs else xs ++ List.replicate (n-l) x" $ \ xs n x ->+            (V.padRight n x . V.pack @V.PrimVector @Word8 $ xs) ===+                (let l = List.length xs+                 in if l >= n then V.pack xs+                              else V.pack $ xs ++ (List.replicate (n-l) x))++    describe "vector reverse == List.reverse" $ do+        prop "vector reverse === List.reverse" $ \ xs ->+            (V.reverse . V.pack @V.Vector @Integer $ xs)  === (V.pack . List.reverse $ xs)+        prop "vector reverse === List.reverse" $ \ xs ->+            (V.reverse . V.pack @V.PrimVector @Int $ xs)  === (V.pack . List.reverse $ xs)+        prop "vector reverse === List.reverse" $ \ xs ->+            (V.reverse . V.pack @V.PrimVector @Word8 $ xs)  === (V.pack . List.reverse $ xs)++    describe "vector intersperse == List.intersperse" $ do+        prop "vector intersperse === List.intersperse" $ \ xs x ->+            (V.intersperse x . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.intersperse x $ xs)+        prop "vector intersperse x === List.intersperse x" $ \ xs x ->+            (V.intersperse x . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.intersperse x $ xs)+        prop "vector intersperse x === List.intersperse x" $ \ xs x ->+            (V.intersperse x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.intersperse x $ xs)++    describe "vector intercalate == List.intercalate" $ do+        prop "vector intercalate === List.intercalate" $ \ xs ys ->+            (V.intercalate (V.pack ys) . List.map (V.pack @V.Vector @Integer) $ xs)  ===+                (V.pack . List.intercalate ys $ xs)+        prop "vector intercalate ys === List.intercalate x" $ \ xs ys ->+            (V.intercalate (V.pack ys) . List.map (V.pack @V.PrimVector @Int) $ xs)  ===+                (V.pack . List.intercalate ys $ xs)+        prop "vector intercalate ys === List.intercalate x" $ \ xs ys ->+            (V.intercalate (V.pack ys) . List.map (V.pack @V.PrimVector @Word8) $ xs)  ===+                (V.pack . List.intercalate ys $ xs)++    describe "vector intercalateElem x == List.intercalate [x]" $ do+        prop "vector intercalateElem x === List.intercalate [x]" $ \ xs x ->+            (V.intercalateElem x . List.map (V.pack @V.Vector @Integer) $ xs)  ===+                (V.pack . List.intercalate [x] $ xs)+        prop "vector intercalateElem ys === List.intercalate x" $ \ xs x ->+            (V.intercalateElem x . List.map (V.pack @V.PrimVector @Int) $ xs)  ===+                (V.pack . List.intercalate [x] $ xs)+        prop "vector intercalateElem ys === List.intercalate x" $ \ xs x ->+            (V.intercalateElem x . List.map (V.pack @V.PrimVector @Word8) $ xs)  ===+                (V.pack . List.intercalate [x] $ xs)++    describe "vector transpose == List.transpose" $ do+        prop "vector transpose == List.transpose" $ \ xs ->+            (V.transpose $ V.pack @V.Vector @Integer <$> xs)  ===+                (V.pack <$> List.transpose xs)+        prop "vector transpose == List.transpose" $ \ xs ->+            (V.transpose $ V.pack @V.PrimVector @Int <$> xs)  ===+                (V.pack <$> List.transpose xs)+        prop "vector transpose == List.transpose" $ \ xs ->+            (V.transpose $ V.pack @V.PrimVector @Word8 <$> xs)  ===+                (V.pack <$> List.transpose xs)++    describe "vector zipWith' == List.zipWith" $ do+        prop "vector zipWith' == List.zipWith" $ \ xs ys x ->+            let pack' = V.pack @V.Vector @Integer+            in (V.zipWith' (applyFun2 x) (pack' xs) (pack' ys))  ===+                (pack' $ List.zipWith (applyFun2 x) xs ys)+        prop "vector zipWith == List.zipWith" $ \ xs ys x ->+            let pack' = V.pack @V.PrimVector @Int+            in (V.zipWith' (applyFun2 x) (pack' xs) (pack' ys))  ===+                (pack' $ List.zipWith (applyFun2 x) xs ys)+        prop "vector zipWith' == List.zipWith" $ \ xs ys x ->+            let pack' = V.pack @V.PrimVector @Word8+            in (V.zipWith' (applyFun2 x) (pack' xs) (pack' ys))  ===+                (pack' $ List.zipWith (applyFun2 x) xs ys)++    describe "vector unzipWith' f == List.unzip . List.map f" $ do+        prop "vector zipWith' == List.unzip . List.map f" $ \ zs (Fun _ x) ->+            let pack' = V.pack @V.Vector @Integer+            in (V.unzipWith' x (pack' zs))  ===+                (let (a,b) = List.unzip (List.map x zs) in (pack' a, pack' b))+        prop "vector zipWith == List.unzip . List.map f" $ \ zs (Fun _ x) ->+            let pack' = V.pack @V.PrimVector @Int+            in (V.unzipWith' x (pack' zs))  ===+                (let (a,b) = List.unzip (List.map x zs) in (pack' a, pack' b))+        prop "vector zipWith' == List.unzip . List.map f" $ \ zs (Fun _ x) ->+            let pack' = V.pack @V.PrimVector @Word8+            in (V.unzipWith' x (pack' zs))  ===+                (let (a,b) = List.unzip (List.map x zs) in (pack' a, pack' b))++    describe "vector scanl' == List.scanl" $ do+        prop "vector scanl' === List.scanl" $ \ xs f x ->+            (V.scanl' @V.Vector @V.Vector (applyFun2 f :: Integer -> Integer -> Integer) x . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.scanl (applyFun2 f) x $ xs)+        prop "vector scanl' x === List.scanl x" $ \ xs f x ->+            (V.scanl' @V.PrimVector @V.PrimVector (applyFun2 f :: Int -> Int -> Int) x . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.scanl (applyFun2 f) x $ xs)+        prop "vector scanl' x === List.scanl x" $ \ xs f x ->+            (V.scanl' @V.PrimVector @V.Vector (applyFun2 f :: Int -> Word8 -> Int) x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.scanl (applyFun2 f) x $ xs)++    describe "vector scanl1' == List.scanl1" $ do+        prop "vector scanl1' === List.scanl1" $ \ xs f ->+            (V.scanl1' (applyFun2 f :: Integer -> Integer -> Integer) . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.scanl1 (applyFun2 f) $ xs)+        prop "vector scanl1' x === List.scanl1 x" $ \ xs f ->+            (V.scanl1' (applyFun2 f :: Int -> Int -> Int) . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.scanl1 (applyFun2 f) $ xs)+        prop "vector scanl1' x === List.scanl1 x" $ \ xs f ->+            (V.scanl1' (applyFun2 f :: Word8 -> Word8 -> Word8) . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.scanl1 (applyFun2 f) $ xs)++    describe "vector scanr' == List.scanr" $ do+        prop "vector scanr' === List.scanr" $ \ xs f x ->+            (V.scanr' @V.Vector @V.Vector (applyFun2 f :: Integer -> Integer -> Integer) x . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.scanr (applyFun2 f) x $ xs)+        prop "vector scanr' x === List.scanr x" $ \ xs f x ->+            (V.scanr' @V.PrimVector @V.PrimVector (applyFun2 f :: Int -> Int -> Int) x . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.scanr (applyFun2 f) x $ xs)+        prop "vector scanr' x === List.scanr x" $ \ xs f x ->+            (V.scanr' @V.PrimVector @V.Vector (applyFun2 f :: Word8 -> Int -> Int) x . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.scanr (applyFun2 f) x $ xs)++    describe "vector scanr1' == List.scanr1" $ do+        prop "vector scanr1' === List.scanr1" $ \ xs f ->+            (V.scanr1' (applyFun2 f :: Integer -> Integer -> Integer) . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack . List.scanr1 (applyFun2 f) $ xs)+        prop "vector scanr1' x === List.scanr1 x" $ \ xs f ->+            (V.scanr1' (applyFun2 f :: Int -> Int -> Int) . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack . List.scanr1 (applyFun2 f) $ xs)+        prop "vector scanr1' x === List.scanr1 x" $ \ xs f ->+            (V.scanr1' (applyFun2 f :: Word8 -> Word8 -> Word8) . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack . List.scanr1 (applyFun2 f) $ xs)
+ test/Std/Data/Vector/SearchSpec.hs view
@@ -0,0 +1,194 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.Data.Vector.SearchSpec where++import qualified Data.List                as List+import           Data.Word+import qualified Std.Data.Vector          as V+import qualified Std.Data.Vector.Search   as V+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++spec :: Spec+spec = describe "vector-search" $ do+    describe "snd . vector find == List.find" $ do+        prop "snd .vector find = List.find" $ \ (Fun _ y) x ->+            (snd . V.find y . V.pack @V.Vector @Integer $ x)  === (List.find y $ x)+        prop "snd . vector find = List.find" $ \ (Fun _ y) x ->+            (snd . V.find y . V.pack @V.PrimVector @Int $ x)  === (List.find y $ x)+        prop "snd . vector find = List.find" $ \ (Fun _ y) x ->+            (snd . V.find y . V.pack @V.PrimVector @Word8 $ x)  === (List.find y $ x)++    describe "vector findIndex == maybe List.length List.findIndex" $ do+        prop "vector findIndex = maybe List.length List.findIndex" $ \ (Fun _ y) x ->+            (V.findIndex y . V.pack @V.Vector @Integer $ x)  ===+                (maybe (List.length x) id $ List.findIndex y x)+        prop "vector findIndex = maybe List.length List.findIndex" $ \ (Fun _ y) x ->+            (V.findIndex y . V.pack @V.PrimVector @Int $ x)  ===+                (maybe (List.length x) id $ List.findIndex y x)+        prop "vector findIndex = maybe List.length List.findIndex" $ \ (Fun _ y) x ->+            (V.findIndex y . V.pack @V.PrimVector @Word8 $ x)  ===+                (maybe (List.length x) id $ List.findIndex y x)++    describe "vector findIndex ==  length - findIndexR . reverse - 1" $ do+        prop "vector findIndex = length - findIndexR . reverse - 1" $ \ (Fun _ y) x ->+            (V.findIndex y . V.pack @V.Vector @Integer $ x)  ===+                (List.length x - 1 - (V.findIndexR y . V.reverse . V.pack @V.Vector @Integer $ x))+        prop "vector findIndex = length - findIndexR . reverse - 1" $ \ (Fun _ y) x ->+            (V.findIndex y . V.pack @V.PrimVector @Int $ x)  ===+                (List.length x - 1 - (V.findIndexR y . V.reverse . V.pack @V.PrimVector @Int $ x))+        prop "vector findIndex = length - findIndexR . reverse - 1" $ \ (Fun _ y) x ->+            (V.findIndex y . V.pack @V.PrimVector @Word8 $ x)  ===+                (List.length x - 1 - (V.findIndexR y . V.reverse . V.pack @V.PrimVector @Word8 $ x))++    describe "vector elemIndices == List.elemIndices" $ do+        prop "vector elemIndices = List.elemIndices" $ \ y x ->+            (V.elemIndices y . V.pack @V.Vector @Integer $ x)  === (List.elemIndices y $ x)+        prop "vector elemIndices = List.elemIndices" $ \ y x ->+            (V.elemIndices y . V.pack @V.PrimVector @Int $ x)  === (List.elemIndices y $ x)+        prop "vector elemIndices = List.elemIndices" $ \ y x ->+            (V.elemIndices y . V.pack @V.PrimVector @Word8 $ x)  === (List.elemIndices y $ x)++    describe "vector filter == List.filter" $ do+        prop "vector filter = List.filter" $ \ (Fun _ y) x ->+            (V.filter y . V.pack @V.Vector @Integer $ x)  === (V.pack . List.filter y $ x)+        prop "vector filter = List.filter" $ \ (Fun _ y) x ->+            (V.filter y . V.pack @V.PrimVector @Int $ x)  === (V.pack . List.filter y $ x)+        prop "vector filter = List.filter" $ \ (Fun _ y) x ->+            (V.filter y . V.pack @V.PrimVector @Word8 $ x)  === (V.pack . List.filter y $ x)++    describe "vector partition == List.partition" $ do+        prop "vector partition = List.partition" $ \ (Fun _ y) x ->+            (V.partition y . V.pack @V.Vector @Integer $ x)  ===+                (let (a,b) = List.partition y $ x in (V.pack a, V.pack b))+        prop "vector partition = List.partition" $ \ (Fun _ y) x ->+            (V.partition y . V.pack @V.PrimVector @Int $ x)  ===+                (let (a,b) = List.partition y $ x in (V.pack a, V.pack b))+        prop "vector partition = List.partition" $ \ (Fun _ y) x ->+            (V.partition y . V.pack @V.PrimVector @Word8 $ x)  ===+                (let (a,b) = List.partition y $ x in (V.pack a, V.pack b))++    describe "vector indices property" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "subvector at indices should be equal to needle" $ \ needle haystack ->+            (let is = V.indices (V.pack needle) (V.pack @V.Vector @Integer $ haystack) False+             in all (\i -> List.take (List.length needle) (List.drop i haystack) == needle) is+            ) === True+        prop "subvector at indices should be equal to needle" $ \ needle haystack ->+            (let is = V.indices (V.pack needle) (V.pack @V.PrimVector @Int $ haystack) False+             in all (\i -> List.take (List.length needle) (List.drop i haystack) == needle) is+            ) === True+        prop "subvector at indices should be equal to needle" $ \ needle haystack ->+            (let is = V.indices (V.pack needle) (V.pack @V.PrimVector @Word8 $ haystack) False+             in all (\i -> List.take (List.length needle) (List.drop i haystack) == needle) is+            ) === True++    describe "vector indices property" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "indices should not overlapped" $ \ needle haystack ->+            (let is = V.indices (V.pack needle) (V.pack @V.Vector @Integer $ haystack) False+                 is' = drop 1 is+                 isDiff = List.zipWith (-) is' is+             in all (>= List.length needle)  isDiff+            ) === True+        prop "indices should not overlapped" $ \ needle haystack ->+            (let is = V.indices (V.pack needle) (V.pack @V.PrimVector @Int $ haystack) False+                 is' = drop 1 is+                 isDiff = List.zipWith (-) is' is+             in all (>= List.length needle)  isDiff+            ) === True+        prop "indices should not overlapped" $ \ needle haystack ->+            (let is = V.indices (V.pack needle) (V.pack @V.PrimVector @Word8 $ haystack) False+                 is' = drop 1 is+                 isDiff = List.zipWith (-) is' is+             in all (>= List.length needle)  isDiff+            ) === True++    describe "vector indices property (partial match)" $ do+        prop "subvector at indices should be equal to needle" $ \ needle haystack ->+            (let is = V.indices (V.pack needle) (V.pack @V.Vector @Integer $ haystack) True+             in all (\i ->+                    if (i > 0)+                    then List.take (List.length needle) (List.drop i haystack) == needle+                    else (List.drop (List.length haystack + i) haystack) ==+                            (List.take (0-i) needle)+                ) is+            ) === True+        prop "subvector at indices should be equal to needle" $ \ needle haystack ->+            (let is = V.indices (V.pack needle) (V.pack @V.PrimVector @Int $ haystack) True+             in all (\i ->+                    if (i > 0)+                    then List.take (List.length needle) (List.drop i haystack) == needle+                    else (List.drop (List.length haystack + i) haystack) ==+                            (List.take (0-i) needle)+                ) is+            ) === True+        prop "subvector at indices should be equal to needle" $ \ needle haystack ->+            (let is = V.indices (V.pack needle) (V.pack @V.PrimVector @Word8 $ haystack) True+             in all (\i ->+                    if (i > 0)+                    then List.take (List.length needle) (List.drop i haystack) == needle+                    else (List.drop (List.length haystack + i) haystack) ==+                            (List.take (0-i) needle)+                ) is+            ) === True++    describe "vector overlapping indices property" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "subvector at indices should be equal to needle" $ \ needle haystack ->+            (let is = V.indicesOverlapping (V.pack needle) (V.pack @V.Vector @Integer $ haystack) False+             in all (\i -> List.take (List.length needle) (List.drop i haystack) == needle) is+            ) === True+        prop "subvector not at indicesOverlapping should be not equal to needle" $ \ needle haystack  ->+            (let is = V.indicesOverlapping (V.pack needle) (V.pack @V.Vector @Integer $ haystack) False+                 is' = filter (`notElem` is) [0..List.length haystack-1]+             in all (\i -> List.take (List.length needle) (List.drop i haystack) /= needle) is'+            ) === True+        prop "subvector at indicesOverlapping should be equal to needle" $ \ needle haystack ->+            (let is = V.indicesOverlapping (V.pack needle) (V.pack @V.PrimVector @Int $ haystack) False+             in all (\i -> List.take (List.length needle) (List.drop i haystack) == needle) is+            ) === True+        prop "subvector not at indicesOverlapping should be not equal to needle" $ \ needle haystack  ->+            (let is = V.indicesOverlapping (V.pack needle) (V.pack @V.PrimVector @Int $ haystack) False+                 is' = filter (`notElem` is) [0..List.length haystack-1]+             in all (\i -> List.take (List.length needle) (List.drop i haystack) /= needle) is'+            ) === True+        prop "subvector at indicesOverlapping should be equal to needle" $ \ needle haystack ->+            (let is = V.indicesOverlapping (V.pack needle) (V.pack @V.PrimVector @Word8 $ haystack) False+             in all (\i -> List.take (List.length needle) (List.drop i haystack) == needle) is+            ) === True+        prop "subvector not at indicesOverlapping should be not equal to needle" $ \ needle haystack  ->+            (let is = V.indicesOverlapping (V.pack needle) (V.pack @V.PrimVector @Word8 $ haystack) False+                 is' = filter (`notElem` is) [0..List.length haystack-1]+             in all (\i -> List.take (List.length needle) (List.drop i haystack) /= needle) is'+            ) === True++    describe "vector indicesOverlapping property (partial match)" $ do+        prop "subvector at indicesOverlapping should be equal to needle" $ \ needle haystack ->+            (let is = V.indicesOverlapping (V.pack needle) (V.pack @V.Vector @Integer $ haystack) True+             in all (\i ->+                    if (i > 0)+                    then List.take (List.length needle) (List.drop i haystack) == needle+                    else (List.drop (List.length haystack + i) haystack) ==+                            (List.take (0-i) needle)+                ) is+            ) === True+        prop "subvector at indicesOverlapping should be equal to needle" $ \ needle haystack ->+            (let is = V.indicesOverlapping (V.pack needle) (V.pack @V.PrimVector @Int $ haystack) True+             in all (\i ->+                    if (i > 0)+                    then List.take (List.length needle) (List.drop i haystack) == needle+                    else (List.drop (List.length haystack + i) haystack) ==+                            (List.take (0-i) needle)+                ) is+            ) === True+        prop "subvector at indicesOverlapping should be equal to needle" $ \ needle haystack ->+            (let is = V.indicesOverlapping (V.pack needle) (V.pack @V.PrimVector @Word8 $ haystack) True+             in all (\i ->+                    if (i > 0)+                    then List.take (List.length needle) (List.drop i haystack) == needle+                    else (List.drop (List.length haystack + i) haystack) ==+                            (List.take (0-i) needle)+                ) is+            ) === True
+ test/Std/Data/Vector/SortSpec.hs view
@@ -0,0 +1,138 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.Data.Vector.SortSpec where++import qualified Data.List                as List+import           Data.Word+import           Data.Int+import qualified Std.Data.Vector          as V+import qualified Std.Data.Vector.Sort     as V+import           Std.Data.Vector.Sort     (Radix(..))+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++data StableTest = StableTest { key :: Int, payload :: Integer } deriving (Eq, Show)+instance Ord StableTest where+    StableTest x1 y1 `compare` StableTest x2 y2 = x1 `compare` x2++instance V.Radix StableTest where+    bucketSize = bucketSize . key+    passes = passes . key+    radixLSB = radixLSB . key+    radix i = radix i . key+    radixMSB = radixMSB . key++spec :: Spec+spec = describe "vector-sort" $ do+    describe "vector insertSort == List.sort" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "vector insertSort == List.sort" $ \ xs ->+            (V.insertSort . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector insertSort == List.sort" $ \ xs ->+            (V.insertSort . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector insertSort == List.sort" $ \ xs ->+            (V.insertSort . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack $ List.sort xs)++    describe "vector insertSort should be stable" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "vector insertSort should be stable" $ \ xs ys ->+            (V.insertSort . V.pack @V.Vector $ List.zipWith StableTest xs ys)  ===+                (V.pack $ List.sort $ List.zipWith StableTest xs ys)++    describe "vector mergeSort == List.sort" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "vector mergeSort == List.sort" $ \ xs ->+            (V.mergeSort . V.pack @V.Vector @Integer $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector mergeSort == List.sort" $ \ xs ->+            (V.mergeSort . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector mergeSort == List.sort" $ \ xs ->+            (V.mergeSort . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack $ List.sort xs)++    describe "vector mergeSort should be stable" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "vector mergeSort should be stable" $ \ xs ys ->+            (V.mergeSort . V.pack @V.Vector $ List.zipWith StableTest xs ys)  ===+                (V.pack $ List.sort $ List.zipWith StableTest xs ys)++    describe "vector radixSort == List.sort" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "vector radixSort == List.sort" $ \ xs ->+            (V.radixSort . V.pack @V.Vector @Int $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector radixSort == List.sort" $ \ xs ->+            (V.radixSort . V.pack @V.PrimVector @Int $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector radixSort == List.sort" $ \ xs ->+            (V.radixSort . V.pack @V.PrimVector @Int64 $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector radixSort == List.sort" $ \ xs ->+            (V.radixSort . V.pack @V.PrimVector @Int32 $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector radixSort == List.sort" $ \ xs ->+            (V.radixSort . V.pack @V.PrimVector @Int16 $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector radixSort == List.sort" $ \ xs ->+            (V.radixSort . V.pack @V.PrimVector @Int8 $ xs)  ===+                (V.pack $ List.sort xs)++        prop "vector radixSort == List.sort" $ \ xs ->+            (V.radixSort . V.pack @V.PrimVector @Word $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector radixSort == List.sort" $ \ xs ->+            (V.radixSort . V.pack @V.PrimVector @Word64 $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector radixSort == List.sort" $ \ xs ->+            (V.radixSort . V.pack @V.PrimVector @Word32 $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector radixSort == List.sort" $ \ xs ->+            (V.radixSort . V.pack @V.PrimVector @Word16 $ xs)  ===+                (V.pack $ List.sort xs)+        prop "vector radixSort == List.sort" $ \ xs ->+            (V.radixSort . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.pack $ List.sort xs)++    describe "vector radixSort should be reversed by RadixDown" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "vector radixSort should be reversed by RadixDown" $ \ xs ->+            (V.castVector . V.radixSort . V.pack @V.Vector @Int $ xs)  ===+                (V.reverse . V.radixSort . V.pack $ map V.RadixDown xs)+        prop "vector radixSort should be reversed by RadixDown" $ \ xs ->+            (V.castVector . V.radixSort . V.pack @V.PrimVector @Int $ xs)  ===+                (V.reverse . V.radixSort . V.pack $ map V.RadixDown xs)+        prop "vector radixSort should be reversed by RadixDown" $ \ xs ->+            (V.castVector . V.radixSort . V.pack @V.PrimVector @Int64 $ xs)  ===+                (V.reverse . V.radixSort . V.pack $ map V.RadixDown xs)+        prop "vector radixSort should be reversed by RadixDown" $ \ xs ->+            (V.castVector . V.radixSort . V.pack @V.PrimVector @Int32 $ xs)  ===+                (V.reverse . V.radixSort . V.pack $ map V.RadixDown xs)+        prop "vector radixSort should be reversed by RadixDown" $ \ xs ->+            (V.castVector . V.radixSort . V.pack @V.PrimVector @Int16 $ xs)  ===+                (V.reverse . V.radixSort . V.pack $ map V.RadixDown xs)+        prop "vector radixSort should be reversed by RadixDown" $ \ xs ->+            (V.castVector . V.radixSort . V.pack @V.PrimVector @Int8 $ xs)  ===+                (V.reverse . V.radixSort . V.pack $ map V.RadixDown xs)++        prop "vector radixSort should be reversed by RadixDown" $ \ xs ->+            (V.castVector . V.radixSort . V.pack @V.PrimVector @Word $ xs)  ===+                (V.reverse . V.radixSort . V.pack $ map V.RadixDown xs)+        prop "vector radixSort should be reversed by RadixDown" $ \ xs ->+            (V.castVector . V.radixSort . V.pack @V.PrimVector @Word64 $ xs)  ===+                (V.reverse . V.radixSort . V.pack $ map V.RadixDown xs)+        prop "vector radixSort should be reversed by RadixDown" $ \ xs ->+            (V.castVector . V.radixSort . V.pack @V.PrimVector @Word32 $ xs)  ===+                (V.reverse . V.radixSort . V.pack $ map V.RadixDown xs)+        prop "vector radixSort should be reversed by RadixDown" $ \ xs ->+            (V.castVector . V.radixSort . V.pack @V.PrimVector @Word16 $ xs)  ===+                (V.reverse . V.radixSort . V.pack $ map V.RadixDown xs)+        prop "vector radixSort should be reversed by RadixDown" $ \ xs ->+            (V.castVector . V.radixSort . V.pack @V.PrimVector @Word8 $ xs)  ===+                (V.reverse . V.radixSort . V.pack $ map V.RadixDown xs)++    describe "vector radixSort should be stable" . modifyMaxSuccess (*10) . modifyMaxSize (*10) $ do+        prop "vector radixSort should be stable" $ \ xs ys ->+            (V.radixSort . V.pack @V.Vector $ List.zipWith StableTest xs ys)  ===+                (V.pack $ List.sort $ List.zipWith StableTest xs ys)
+ test/Std/IO/FileSystemSpec.hs view
@@ -0,0 +1,146 @@+{-# LANGUAGE OverloadedStrings #-}++module Std.IO.FileSystemSpec where++import           Control.Concurrent.MVar (readMVar)+import           Control.Monad+import           Data.Bits+import           Std.Data.Vector         as V+import           Std.Data.Vector.Base    as V+import           Data.List               as List+import           Foreign.Marshal.Array+import           Foreign.Ptr+import           Std.IO.Buffered+import           Std.IO.Exception+import           Std.IO.FileSystem+import           Std.IO.Resource+import           Std.IO.UV.Manager+import           Test.Hspec+import           Test.HUnit++spec :: Spec+spec = describe "filesystem operations" $ do++        let content = "Hello world!"+            content2 = V.cycleN 1024 "quick fox jumps over the lazy dog, 世界你好!\n"+            size = V.length content+            size2 = V.length content2++        tempdir <- runIO $ mkdtemp "stdio-filesystem-unit"++        it "create a temp dir" $ do++            dirs <- scandir "./"+            List.lookup tempdir dirs @?= Just DirEntDir+++        let flags = O_RDWR .|. O_CREAT+            mode = DEFAULT_MODE+            filename = tempdir <> "/test-file"++        it "Opens and writes a file" $ do+            withResource (initUVFile filename flags mode) $ \ file -> do+                o <- newBufferedOutput file 4096+                writeBuffer o content+                flushBuffer o++            withResource (initUVFile filename flags mode) $ \ file -> do+                i <- newBufferedInput file 4096+                written <- readExactly size i+                written @=? content++                fr <- newUVFileReader file 0+                i <- newBufferedInput fr 4096+                written <- readExactly size i+                written @=? content++            unlink filename++        it "Opens and writes a file II" $ do+            withResource (initUVFile filename flags mode) $ \ file -> do+                o <- newBufferedOutput file 4096+                writeBuffer o content2+                flushBuffer o++            withResource (initUVFile filename flags mode) $ \ file -> do+                i <- newBufferedInput file 4096+                written <- readExactly size2 i+                written @=? content2++            withResource (initUVFile filename flags mode) $ \ file -> do+                i <- newBufferedInput file 4096+                firstLine <- readLine i+                firstLine  @=? fst (V.break (== V.c2w '\n') content2)++                fr <- newUVFileReader file 0+                i <- newBufferedInput fr 4096+                replicateM_ 1024 $ do+                    firstLine <- readLine i+                    firstLine  @=? fst (V.break (== V.c2w '\n') content2)+            unlink filename++        let dirname  = tempdir <> "/test-dir"++        it "create and remove dir" $ do+            mkdir dirname mode+            dirs <- scandir tempdir+            print dirs+            List.lookup "test-dir" dirs @?= Just DirEntDir+            rmdir dirname++        let linkname  = tempdir <> "/test-link"+            symlinkname  = tempdir <> "/test-symlink"+            symlinkname2  = tempdir <> "/test-symlink2"++        it "link stat should be equal to target file" $ do++            withResource (initUVFile filename flags mode) $ \ file -> return ()++            s0 <- stat filename++            link filename linkname+            symlink "test-link" symlinkname SYMLINK_DEFAULT++            absfp <- realpath filename+            symlink absfp symlinkname2 SYMLINK_DEFAULT  -- the second way to create a proper symlink++            s1 <- stat linkname+            s2 <- stat symlinkname+            s2' <- stat symlinkname2++            s0 @?= s1 {stNlink = 1} -- update hard link number+            s0 @?= s2 {stNlink = 1}+            s0 @?= s2' {stNlink = 1}++            withResource (initUVFile filename flags mode) $ \ file -> do+                s4 <- fstat file+                s0 @?= s4 {stNlink = 1}++            unlink filename+            unlink linkname+            unlink symlinkname+            unlink symlinkname2++        it "utime result in stat change" $ do+            withResource (initUVFile filename flags mode) $ \ file -> return ()+            utime filename 1000.2000 3000.4000+            s <- stat filename+            print s+            uvtSecond (stAtim s) @?= 1000+            uvtNanoSecond (stAtim s) @?= 200000000+            uvtSecond (stMtim s) @?= 3000+            uvtNanoSecond (stMtim s) @?= 400000000+            unlink filename++        it "futime result in fstat change" $ do+            withResource (initUVFile filename flags mode) $ \ file -> do+                futime file 5000.6000 7000.8000+                s <- fstat file+                print s+                uvtSecond (stAtim s) @?= 5000+                uvtNanoSecond (stAtim s) @?= 600000000+                uvtSecond (stMtim s) @?= 7000+                uvtNanoSecond (stMtim s) @?= 800000000+            unlink filename++        it "remove test temp dir" $ rmdir tempdir
+ test/Std/IO/FileSystemTSpec.hs view
@@ -0,0 +1,146 @@+{-# LANGUAGE OverloadedStrings #-}++module Std.IO.FileSystemTSpec where++import           Control.Concurrent.MVar (readMVar)+import           Control.Monad+import           Data.Bits+import           Std.Data.Vector         as V+import           Std.Data.Vector.Base    as V+import           Data.List               as List+import           Foreign.Marshal.Array+import           Foreign.Ptr+import           Std.IO.Buffered+import           Std.IO.Exception+import           Std.IO.FileSystemT+import           Std.IO.Resource+import           Std.IO.UV.Manager+import           Test.Hspec+import           Test.HUnit++spec :: Spec+spec = describe "filesystem (threadpool version) operations" $ do++        let content = "Hello world!"+            content2 = V.cycleN 1024 "quick fox jumps over the lazy dog, 世界你好!\n"+            size = V.length content+            size2 = V.length content2++        tempdir <- runIO $ mkdtemp "stdio-filesystem-unit"++        it "create a temp dir" $ do++            dirs <- scandir "./"+            List.lookup tempdir dirs @?= Just DirEntDir+++        let flags = O_RDWR .|. O_CREAT+            mode = DEFAULT_MODE+            filename = tempdir <> "/test-file"++        it "Opens and writes a file" $ do+            withResource (initUVFile filename flags mode) $ \ file -> do+                o <- newBufferedOutput file 4096+                writeBuffer o content+                flushBuffer o++            withResource (initUVFile filename flags mode) $ \ file -> do+                i <- newBufferedInput file 4096+                written <- readExactly size i+                written @=? content++                fr <- newUVFileReader file 0+                i <- newBufferedInput fr 4096+                written <- readExactly size i+                written @=? content++            unlink filename++        it "Opens and writes a file II" $ do+            withResource (initUVFile filename flags mode) $ \ file -> do+                o <- newBufferedOutput file 4096+                writeBuffer o content2+                flushBuffer o++            withResource (initUVFile filename flags mode) $ \ file -> do+                i <- newBufferedInput file 4096+                written <- readExactly size2 i+                written @=? content2++            withResource (initUVFile filename flags mode) $ \ file -> do+                i <- newBufferedInput file 4096+                firstLine <- readLine i+                firstLine  @=? fst (V.break (== V.c2w '\n') content2)++                fr <- newUVFileReader file 0+                i <- newBufferedInput fr 4096+                replicateM_ 1024 $ do+                    firstLine <- readLine i+                    firstLine  @=? fst (V.break (== V.c2w '\n') content2)+            unlink filename++        let dirname  = tempdir <> "/test-dir"++        it "create and remove dir" $ do+            mkdir dirname mode+            dirs <- scandir tempdir+            print dirs+            List.lookup "test-dir" dirs @?= Just DirEntDir+            rmdir dirname++        let linkname  = tempdir <> "/test-link"+            symlinkname  = tempdir <> "/test-symlink"+            symlinkname2  = tempdir <> "/test-symlink2"++        it "link stat should be equal to target file" $ do++            withResource (initUVFile filename flags mode) $ \ file -> return ()++            s0 <- stat filename++            link filename linkname+            symlink "test-link" symlinkname SYMLINK_DEFAULT++            absfp <- realpath filename+            symlink absfp symlinkname2 SYMLINK_DEFAULT  -- the second way to create a proper symlink++            s1 <- stat linkname+            s2 <- stat symlinkname+            s2' <- stat symlinkname2++            s0 @?= s1 {stNlink = 1} -- update hard link number+            s0 @?= s2 {stNlink = 1}+            s0 @?= s2' {stNlink = 1}++            withResource (initUVFile filename flags mode) $ \ file -> do+                s4 <- fstat file+                s0 @?= s4 {stNlink = 1}++            unlink filename+            unlink linkname+            unlink symlinkname+            unlink symlinkname2++        it "utime result in stat change" $ do+            withResource (initUVFile filename flags mode) $ \ file -> return ()+            utime filename 1000.2000 3000.4000+            s <- stat filename+            print s+            uvtSecond (stAtim s) @?= 1000+            uvtNanoSecond (stAtim s) @?= 200000000+            uvtSecond (stMtim s) @?= 3000+            uvtNanoSecond (stMtim s) @?= 400000000+            unlink filename++        it "futime result in fstat change" $ do+            withResource (initUVFile filename flags mode) $ \ file -> do+                futime file 5000.6000 7000.8000+                s <- fstat file+                print s+                uvtSecond (stAtim s) @?= 5000+                uvtNanoSecond (stAtim s) @?= 600000000+                uvtSecond (stMtim s) @?= 7000+                uvtNanoSecond (stMtim s) @?= 800000000+            unlink filename++        it "remove test temp dir" $ rmdir tempdir
+ test/Std/IO/LowResTimerSpec.hs view
@@ -0,0 +1,52 @@+module Std.IO.LowResTimerSpec where++import           Control.Concurrent+import           Control.Monad+import           Control.Monad.IO.Class+import           Std.Data.PrimIORef+import           Std.IO.LowResTimer+import           Test.Hspec+import           Test.HUnit++spec :: Spec+spec = describe "low resolution timers" $ do+    it "timers registration should not be missed" $ do+        c <- newCounter 0+        replicateM_ 10000 $ do+            forM_ [1..10] $ \ i -> do+                registerLowResTimer i (atomicAddCounter_ c 1)++        threadDelay 1000+        lrtm <- getLowResTimerManager+        running <- isLowResTimerManagerRunning lrtm+        assertEqual "timer manager should start" True running++        threadDelay 1200000 -- make sure all timers are fired+        c' <- readPrimIORef c+        assertEqual "timers registration counter" 100000 c'++        threadDelay 100000  -- another 0.1s++        lrtm <- getLowResTimerManager+        running <- isLowResTimerManagerRunning lrtm+        assertEqual "timer manager should stopped" False running++    it "throttle" $ do+        c <- newCounter 0+        throttledAdd <- throttle 10 (atomicAddCounter_ c 1)+        forkIO . replicateM_ 100 $ do+            throttledAdd+            threadDelay 50000+        threadDelay 10000000  -- wait 10s here+        c' <- readPrimIORef c+        assertBool "throttled add" (6  <= c' && c' <= 7)++    it "throttleTrailing" $ do+        c <- newCounter 0+        throttledAdd <- throttleTrailing_ 10 (atomicAddCounter_ c 1)+        forkIO . replicateM_ 100 $ do+            throttledAdd+            threadDelay 50000+        threadDelay 10000000  -- wait 10s here+        c' <- readPrimIORef c+        assertBool "throttled add" (5  <= c' && c' <= 6)
+ test/Std/IO/ResourceSpec.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Std.IO.ResourceSpec where++import           Control.Concurrent+import           Control.Exception+import           Control.Monad+import           Std.Data.PrimIORef+import           Data.Typeable+import           Std.IO.Resource          as R+import           Test.Hspec+import           Test.HUnit++data WorkerException = WorkerException deriving (Typeable, Show)++instance Exception WorkerException++spec :: Spec+spec = describe "resource tests" $ do+    it "resource pool" $ do+        resCounter <- newCounter 0+        workerCounter <- newCounter 0+        let res = initResource (atomicAddCounter_ resCounter 1)+                               (\ _ -> atomicSubCounter_ resCounter 1)+            resPool = initPool res 100 1+        R.withResource resPool $ \ pool -> do+            let res = initInPool pool+            replicateM_ 300 . forkIO. R.withResource res $ \ _ -> do+                atomicAddCounter_ workerCounter 1+                r <- readPrimIORef resCounter+                threadDelay 1000000+                assertEqual "pool should limit max usage" True (r <= 100)++            threadDelay 4000000 -- first 100 worker quickly get resources+                                -- then hold for 1s, rest 100 worker have to wait, and so on+                                -- so here we wait for 4s to make sure every worker got a resource+                                -- we used to use replicateConcurrently_ from async, but it's+                                -- not really neccessary++            w <- readPrimIORef workerCounter+            assertEqual "worker should be able to get resource" 300 w++            r <- readPrimIORef resCounter+            assertEqual "pool should keep returned resources alive" 100 r++            s <- statPool pool+            assertEqual "pool should be scanning returned resources" PoolScanning s++            threadDelay 1200000  -- another 1.2s++            r <- readPrimIORef resCounter+            assertEqual "pool should reap unused resources" 0 r++            threadDelay 1200000  -- another 1.2s++            s <- statPool pool+            assertEqual "pool should stop scanning returned resources" PoolEmpty s++            -- Let's test again++            writePrimIORef workerCounter 0++            replicateM_ 300 . forkIO. R.withResource res $ \ _ -> do+                atomicAddCounter_ workerCounter 1+                r <- readPrimIORef resCounter+                threadDelay 1000000+                assertEqual "pool should limit max usage" True (r <= 100)++            threadDelay 4000000++            w <- readPrimIORef workerCounter+            assertEqual "worker should be able to get resource" 300 w++            r <- readPrimIORef resCounter+            assertEqual "pool should keep returned resources alive" 100 r++            s <- statPool pool+            assertEqual "pool should be scanning returned resources" PoolScanning s++            threadDelay 1200000  -- another 1.2s++            r <- readPrimIORef resCounter+            assertEqual "pool should reap unused resources" 0 r++            threadDelay 1200000  -- another 1.2s++            s <- statPool pool+            assertEqual "pool should stop scanning returned resources" PoolEmpty s++    it "resource pool under exceptions" $ do+        resCounter <- newCounter 0+        let res = initResource (atomicAddCounter' resCounter 1)+                               (\ _ -> atomicSubCounter_ resCounter 1)+            resPool = initPool res 100 1+        R.withResource resPool $ \ pool -> do+            let res = initInPool pool+            handle (\ (e :: WorkerException) -> return ()) .+                    replicateM_ 300 . forkIO. R.withResource res $ \ i -> do+                        r <- readPrimIORef resCounter+                        threadDelay 1000000+                        when (even i) (throwIO WorkerException)+                        assertEqual "pool should limit max usage" True (r <= 100)++            threadDelay 4000000++            r <- readPrimIORef resCounter+            assertEqual "pool should keep returned resources alive" 100 r++            s <- statPool pool+            assertEqual "pool should be scanning returned resources" PoolScanning s++            threadDelay 1200000  -- another 1.2s++            r <- readPrimIORef resCounter+            assertEqual "pool should reap unused resources" 0 r++            threadDelay 1200000  -- another 1.2s++            s <- statPool pool+            assertEqual "pool should stop scanning returned resources" PoolEmpty s
+ third_party/fastvalidate-utf-8/include/simdasciicheck.h view
@@ -0,0 +1,55 @@+#ifndef SIMDASCIICHECK_H+#define SIMDASCIICHECK_H++#include <emmintrin.h> // SSE2+#include <stdbool.h>   // c99 bool+#include <stddef.h>    // size_t++// The function returns true (1) if all chars passed in src are+// 7-bit values (0x00..0x7F). Otherwise, it returns false (0).+static bool validate_ascii_fast(const char *src, size_t len) {+  size_t i = 0;+  __m128i has_error = _mm_setzero_si128();+  if (len >= 16) {+    for (; i <= len - 16; i += 16) {+      __m128i current_bytes = _mm_loadu_si128((const __m128i *)(src + i));+      has_error = _mm_or_si128(has_error, current_bytes);+    }+  }+  int error_mask = _mm_movemask_epi8(has_error);++  char tail_has_error = 0;+  for (; i < len; i++) {+    tail_has_error |= src[i];+  }+  error_mask |= (tail_has_error & 0x80);++  return !error_mask;+}++#ifdef __AVX2__+#include <x86intrin.h>+// The function returns true (1) if all chars passed in src are+// 7-bit values (0x00..0x7F). Otherwise, it returns false (0).+static bool validate_ascii_fast_avx(const char *src, size_t len) {+  size_t i = 0;+  __m256i has_error = _mm256_setzero_si256();+  if (len >= 32) {+    for (; i <= len - 32; i += 32) {+      __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(src + i));+      has_error = _mm256_or_si256(has_error, current_bytes);+    }+  }+  int error_mask = _mm256_movemask_epi8(has_error);++  char tail_has_error = 0;+  for (; i < len; i++) {+    tail_has_error |= src[i];+  }+  error_mask |= (tail_has_error & 0x80);++  return !error_mask;+}+#endif++#endif
+ third_party/fastvalidate-utf-8/include/simdutf8check.h view
@@ -0,0 +1,458 @@++#ifndef SIMDUTF8CHECK_H+#define SIMDUTF8CHECK_H+#include <stdbool.h>+#include <stddef.h>+#include <stdint.h>+#include <string.h>+#include <x86intrin.h>+/*+ * legal utf-8 byte sequence+ * http://www.unicode.org/versions/Unicode6.0.0/ch03.pdf - page 94+ *+ *  Code Points        1st       2s       3s       4s+ * U+0000..U+007F     00..7F+ * U+0080..U+07FF     C2..DF   80..BF+ * U+0800..U+0FFF     E0       A0..BF   80..BF+ * U+1000..U+CFFF     E1..EC   80..BF   80..BF+ * U+D000..U+D7FF     ED       80..9F   80..BF+ * U+E000..U+FFFF     EE..EF   80..BF   80..BF+ * U+10000..U+3FFFF   F0       90..BF   80..BF   80..BF+ * U+40000..U+FFFFF   F1..F3   80..BF   80..BF   80..BF+ * U+100000..U+10FFFF F4       80..8F   80..BF   80..BF+ *+ */++// all byte values must be no larger than 0xF4+static inline void checkSmallerThan0xF4(__m128i current_bytes,+                                        __m128i *has_error) {+  // unsigned, saturates to 0 below max+  *has_error = _mm_or_si128(*has_error,+                            _mm_subs_epu8(current_bytes, _mm_set1_epi8(0xF4)));+}++static inline __m128i continuationLengths(__m128i high_nibbles) {+  return _mm_shuffle_epi8(+      _mm_setr_epi8(1, 1, 1, 1, 1, 1, 1, 1, // 0xxx (ASCII)+                    0, 0, 0, 0,             // 10xx (continuation)+                    2, 2,                   // 110x+                    3,                      // 1110+                    4), // 1111, next should be 0 (not checked here)+      high_nibbles);+}++static inline __m128i carryContinuations(__m128i initial_lengths,+                                         __m128i previous_carries) {++  __m128i right1 =+      _mm_subs_epu8(_mm_alignr_epi8(initial_lengths, previous_carries, 16 - 1),+                    _mm_set1_epi8(1));+  __m128i sum = _mm_add_epi8(initial_lengths, right1);++  __m128i right2 = _mm_subs_epu8(_mm_alignr_epi8(sum, previous_carries, 16 - 2),+                                 _mm_set1_epi8(2));+  return _mm_add_epi8(sum, right2);+}++static inline void checkContinuations(__m128i initial_lengths, __m128i carries,+                                      __m128i *has_error) {++  // overlap || underlap+  // carry > length && length > 0 || !(carry > length) && !(length > 0)+  // (carries > length) == (lengths > 0)+  __m128i overunder =+      _mm_cmpeq_epi8(_mm_cmpgt_epi8(carries, initial_lengths),+                     _mm_cmpgt_epi8(initial_lengths, _mm_setzero_si128()));++  *has_error = _mm_or_si128(*has_error, overunder);+}++// when 0xED is found, next byte must be no larger than 0x9F+// when 0xF4 is found, next byte must be no larger than 0x8F+// next byte must be continuation, ie sign bit is set, so signed < is ok+static inline void checkFirstContinuationMax(__m128i current_bytes,+                                             __m128i off1_current_bytes,+                                             __m128i *has_error) {+  __m128i maskED = _mm_cmpeq_epi8(off1_current_bytes, _mm_set1_epi8(0xED));+  __m128i maskF4 = _mm_cmpeq_epi8(off1_current_bytes, _mm_set1_epi8(0xF4));++  __m128i badfollowED =+      _mm_and_si128(_mm_cmpgt_epi8(current_bytes, _mm_set1_epi8(0x9F)), maskED);+  __m128i badfollowF4 =+      _mm_and_si128(_mm_cmpgt_epi8(current_bytes, _mm_set1_epi8(0x8F)), maskF4);++  *has_error = _mm_or_si128(*has_error, _mm_or_si128(badfollowED, badfollowF4));+}++// map off1_hibits => error condition+// hibits     off1    cur+// C       => < C2 && true+// E       => < E1 && < A0+// F       => < F1 && < 90+// else      false && false+static inline void checkOverlong(__m128i current_bytes,+                                 __m128i off1_current_bytes, __m128i hibits,+                                 __m128i previous_hibits, __m128i *has_error) {+  __m128i off1_hibits = _mm_alignr_epi8(hibits, previous_hibits, 16 - 1);+  __m128i initial_mins = _mm_shuffle_epi8(+      _mm_setr_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128, -128,+                    -128, -128, // 10xx => false+                    0xC2, -128, // 110x+                    0xE1,       // 1110+                    0xF1),+      off1_hibits);++  __m128i initial_under = _mm_cmpgt_epi8(initial_mins, off1_current_bytes);++  __m128i second_mins = _mm_shuffle_epi8(+      _mm_setr_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128, -128,+                    -128, -128, // 10xx => false+                    127, 127,   // 110x => true+                    0xA0,       // 1110+                    0x90),+      off1_hibits);+  __m128i second_under = _mm_cmpgt_epi8(second_mins, current_bytes);+  *has_error =+      _mm_or_si128(*has_error, _mm_and_si128(initial_under, second_under));+}++struct processed_utf_bytes {+  __m128i rawbytes;+  __m128i high_nibbles;+  __m128i carried_continuations;+};++static inline void count_nibbles(__m128i bytes,+                                 struct processed_utf_bytes *answer) {+  answer->rawbytes = bytes;+  answer->high_nibbles =+      _mm_and_si128(_mm_srli_epi16(bytes, 4), _mm_set1_epi8(0x0F));+}++// check whether the current bytes are valid UTF-8+// at the end of the function, previous gets updated+static struct processed_utf_bytes+checkUTF8Bytes(__m128i current_bytes, struct processed_utf_bytes *previous,+               __m128i *has_error) {+  struct processed_utf_bytes pb;+  count_nibbles(current_bytes, &pb);++  checkSmallerThan0xF4(current_bytes, has_error);++  __m128i initial_lengths = continuationLengths(pb.high_nibbles);++  pb.carried_continuations =+      carryContinuations(initial_lengths, previous->carried_continuations);++  checkContinuations(initial_lengths, pb.carried_continuations, has_error);++  __m128i off1_current_bytes =+      _mm_alignr_epi8(pb.rawbytes, previous->rawbytes, 16 - 1);+  checkFirstContinuationMax(current_bytes, off1_current_bytes, has_error);++  checkOverlong(current_bytes, off1_current_bytes, pb.high_nibbles,+                previous->high_nibbles, has_error);+  return pb;+}++static bool validate_utf8_fast(const char *src, size_t len) {+  size_t i = 0;+  __m128i has_error = _mm_setzero_si128();+  struct processed_utf_bytes previous = {.rawbytes = _mm_setzero_si128(),+                                         .high_nibbles = _mm_setzero_si128(),+                                         .carried_continuations =+                                             _mm_setzero_si128()};+  if (len >= 16) {+    for (; i <= len - 16; i += 16) {+      __m128i current_bytes = _mm_loadu_si128((const __m128i *)(src + i));+      previous = checkUTF8Bytes(current_bytes, &previous, &has_error);+    }+  }++  // last part+  if (i < len) {+    char buffer[16];+    memset(buffer, 0, 16);+    memcpy(buffer, src + i, len - i);+    __m128i current_bytes = _mm_loadu_si128((const __m128i *)(buffer));+    previous = checkUTF8Bytes(current_bytes, &previous, &has_error);+  } else {+    has_error =+        _mm_or_si128(_mm_cmpgt_epi8(previous.carried_continuations,+                                    _mm_setr_epi8(9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+                                                  9, 9, 9, 9, 9, 1)),+                     has_error);+  }++  return _mm_testz_si128(has_error, has_error);+}++#ifdef __AVX2__++/*****************************/+static inline __m256i push_last_byte_of_a_to_b(__m256i a, __m256i b) {+  return _mm256_alignr_epi8(b, _mm256_permute2x128_si256(a, b, 0x21), 15);+}++static inline __m256i push_last_2bytes_of_a_to_b(__m256i a, __m256i b) {+  return _mm256_alignr_epi8(b, _mm256_permute2x128_si256(a, b, 0x21), 14);+}++// all byte values must be no larger than 0xF4+static inline void avxcheckSmallerThan0xF4(__m256i current_bytes,+                                           __m256i *has_error) {+  // unsigned, saturates to 0 below max+  *has_error = _mm256_or_si256(+      *has_error, _mm256_subs_epu8(current_bytes, _mm256_set1_epi8(0xF4)));+}++static inline __m256i avxcontinuationLengths(__m256i high_nibbles) {+  return _mm256_shuffle_epi8(+      _mm256_setr_epi8(1, 1, 1, 1, 1, 1, 1, 1, // 0xxx (ASCII)+                       0, 0, 0, 0,             // 10xx (continuation)+                       2, 2,                   // 110x+                       3,                      // 1110+                       4, // 1111, next should be 0 (not checked here)+                       1, 1, 1, 1, 1, 1, 1, 1, // 0xxx (ASCII)+                       0, 0, 0, 0,             // 10xx (continuation)+                       2, 2,                   // 110x+                       3,                      // 1110+                       4 // 1111, next should be 0 (not checked here)+                       ),+      high_nibbles);+}++static inline __m256i avxcarryContinuations(__m256i initial_lengths,+                                            __m256i previous_carries) {++  __m256i right1 = _mm256_subs_epu8(+      push_last_byte_of_a_to_b(previous_carries, initial_lengths),+      _mm256_set1_epi8(1));+  __m256i sum = _mm256_add_epi8(initial_lengths, right1);++  __m256i right2 = _mm256_subs_epu8(+      push_last_2bytes_of_a_to_b(previous_carries, sum), _mm256_set1_epi8(2));+  return _mm256_add_epi8(sum, right2);+}++static inline void avxcheckContinuations(__m256i initial_lengths,+                                         __m256i carries, __m256i *has_error) {++  // overlap || underlap+  // carry > length && length > 0 || !(carry > length) && !(length > 0)+  // (carries > length) == (lengths > 0)+  __m256i overunder = _mm256_cmpeq_epi8(+      _mm256_cmpgt_epi8(carries, initial_lengths),+      _mm256_cmpgt_epi8(initial_lengths, _mm256_setzero_si256()));++  *has_error = _mm256_or_si256(*has_error, overunder);+}++// when 0xED is found, next byte must be no larger than 0x9F+// when 0xF4 is found, next byte must be no larger than 0x8F+// next byte must be continuation, ie sign bit is set, so signed < is ok+static inline void avxcheckFirstContinuationMax(__m256i current_bytes,+                                                __m256i off1_current_bytes,+                                                __m256i *has_error) {+  __m256i maskED =+      _mm256_cmpeq_epi8(off1_current_bytes, _mm256_set1_epi8(0xED));+  __m256i maskF4 =+      _mm256_cmpeq_epi8(off1_current_bytes, _mm256_set1_epi8(0xF4));++  __m256i badfollowED = _mm256_and_si256(+      _mm256_cmpgt_epi8(current_bytes, _mm256_set1_epi8(0x9F)), maskED);+  __m256i badfollowF4 = _mm256_and_si256(+      _mm256_cmpgt_epi8(current_bytes, _mm256_set1_epi8(0x8F)), maskF4);++  *has_error =+      _mm256_or_si256(*has_error, _mm256_or_si256(badfollowED, badfollowF4));+}++// map off1_hibits => error condition+// hibits     off1    cur+// C       => < C2 && true+// E       => < E1 && < A0+// F       => < F1 && < 90+// else      false && false+static inline void avxcheckOverlong(__m256i current_bytes,+                                    __m256i off1_current_bytes, __m256i hibits,+                                    __m256i previous_hibits,+                                    __m256i *has_error) {+  __m256i off1_hibits = push_last_byte_of_a_to_b(previous_hibits, hibits);+  __m256i initial_mins = _mm256_shuffle_epi8(+      _mm256_setr_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128,+                       -128, -128, -128, // 10xx => false+                       0xC2, -128,       // 110x+                       0xE1,             // 1110+                       0xF1, -128, -128, -128, -128, -128, -128, -128, -128,+                       -128, -128, -128, -128, // 10xx => false+                       0xC2, -128,             // 110x+                       0xE1,                   // 1110+                       0xF1),+      off1_hibits);++  __m256i initial_under = _mm256_cmpgt_epi8(initial_mins, off1_current_bytes);++  __m256i second_mins = _mm256_shuffle_epi8(+      _mm256_setr_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128,+                       -128, -128, -128, // 10xx => false+                       127, 127,         // 110x => true+                       0xA0,             // 1110+                       0x90, -128, -128, -128, -128, -128, -128, -128, -128,+                       -128, -128, -128, -128, // 10xx => false+                       127, 127,               // 110x => true+                       0xA0,                   // 1110+                       0x90),+      off1_hibits);+  __m256i second_under = _mm256_cmpgt_epi8(second_mins, current_bytes);+  *has_error = _mm256_or_si256(*has_error,+                               _mm256_and_si256(initial_under, second_under));+}++struct avx_processed_utf_bytes {+  __m256i rawbytes;+  __m256i high_nibbles;+  __m256i carried_continuations;+};++static inline void avx_count_nibbles(__m256i bytes,+                                     struct avx_processed_utf_bytes *answer) {+  answer->rawbytes = bytes;+  answer->high_nibbles =+      _mm256_and_si256(_mm256_srli_epi16(bytes, 4), _mm256_set1_epi8(0x0F));+}++// check whether the current bytes are valid UTF-8+// at the end of the function, previous gets updated+static struct avx_processed_utf_bytes+avxcheckUTF8Bytes(__m256i current_bytes,+                  struct avx_processed_utf_bytes *previous,+                  __m256i *has_error) {+  struct avx_processed_utf_bytes pb;+  avx_count_nibbles(current_bytes, &pb);++  avxcheckSmallerThan0xF4(current_bytes, has_error);++  __m256i initial_lengths = avxcontinuationLengths(pb.high_nibbles);++  pb.carried_continuations =+      avxcarryContinuations(initial_lengths, previous->carried_continuations);++  avxcheckContinuations(initial_lengths, pb.carried_continuations, has_error);++  __m256i off1_current_bytes =+      push_last_byte_of_a_to_b(previous->rawbytes, pb.rawbytes);+  avxcheckFirstContinuationMax(current_bytes, off1_current_bytes, has_error);++  avxcheckOverlong(current_bytes, off1_current_bytes, pb.high_nibbles,+                   previous->high_nibbles, has_error);+  return pb;+}++// check whether the current bytes are valid UTF-8+// at the end of the function, previous gets updated+static struct avx_processed_utf_bytes+avxcheckUTF8Bytes_asciipath(__m256i current_bytes,+                            struct avx_processed_utf_bytes *previous,+                            __m256i *has_error) {+  if (_mm256_testz_si256(current_bytes,+                         _mm256_set1_epi8(0x80))) { // fast ascii path+    *has_error = _mm256_or_si256(+        _mm256_cmpgt_epi8(previous->carried_continuations,+                          _mm256_setr_epi8(9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+                                           9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+                                           9, 9, 9, 9, 9, 9, 9, 1)),+        *has_error);+    return *previous;+  }++  struct avx_processed_utf_bytes pb;+  avx_count_nibbles(current_bytes, &pb);++  avxcheckSmallerThan0xF4(current_bytes, has_error);++  __m256i initial_lengths = avxcontinuationLengths(pb.high_nibbles);++  pb.carried_continuations =+      avxcarryContinuations(initial_lengths, previous->carried_continuations);++  avxcheckContinuations(initial_lengths, pb.carried_continuations, has_error);++  __m256i off1_current_bytes =+      push_last_byte_of_a_to_b(previous->rawbytes, pb.rawbytes);+  avxcheckFirstContinuationMax(current_bytes, off1_current_bytes, has_error);++  avxcheckOverlong(current_bytes, off1_current_bytes, pb.high_nibbles,+                   previous->high_nibbles, has_error);+  return pb;+}++static bool validate_utf8_fast_avx_asciipath(const char *src, size_t len) {+  size_t i = 0;+  __m256i has_error = _mm256_setzero_si256();+  struct avx_processed_utf_bytes previous = {+      .rawbytes = _mm256_setzero_si256(),+      .high_nibbles = _mm256_setzero_si256(),+      .carried_continuations = _mm256_setzero_si256()};+  if (len >= 32) {+    for (; i <= len - 32; i += 32) {+      __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(src + i));+      previous =+          avxcheckUTF8Bytes_asciipath(current_bytes, &previous, &has_error);+    }+  }++  // last part+  if (i < len) {+    char buffer[32];+    memset(buffer, 0, 32);+    memcpy(buffer, src + i, len - i);+    __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(buffer));+    previous = avxcheckUTF8Bytes(current_bytes, &previous, &has_error);+  } else {+    has_error = _mm256_or_si256(+        _mm256_cmpgt_epi8(previous.carried_continuations,+                          _mm256_setr_epi8(9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+                                           9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+                                           9, 9, 9, 9, 9, 9, 9, 1)),+        has_error);+  }++  return _mm256_testz_si256(has_error, has_error);+}++static bool validate_utf8_fast_avx(const char *src, size_t len) {+  size_t i = 0;+  __m256i has_error = _mm256_setzero_si256();+  struct avx_processed_utf_bytes previous = {+      .rawbytes = _mm256_setzero_si256(),+      .high_nibbles = _mm256_setzero_si256(),+      .carried_continuations = _mm256_setzero_si256()};+  if (len >= 32) {+    for (; i <= len - 32; i += 32) {+      __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(src + i));+      previous = avxcheckUTF8Bytes(current_bytes, &previous, &has_error);+    }+  }++  // last part+  if (i < len) {+    char buffer[32];+    memset(buffer, 0, 32);+    memcpy(buffer, src + i, len - i);+    __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(buffer));+    previous = avxcheckUTF8Bytes(current_bytes, &previous, &has_error);+  } else {+    has_error = _mm256_or_si256(+        _mm256_cmpgt_epi8(previous.carried_continuations,+                          _mm256_setr_epi8(9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+                                           9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,+                                           9, 9, 9, 9, 9, 9, 9, 1)),+        has_error);+  }++  return _mm256_testz_si256(has_error, has_error);+}++#endif // __AVX2__+#endif
+ third_party/libuv/include/uv.h view
@@ -0,0 +1,1664 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++/* See https://github.com/libuv/libuv#documentation for documentation. */++#ifndef UV_H+#define UV_H+#ifdef __cplusplus+extern "C" {+#endif++#ifdef _WIN32+  /* Windows - set up dll import/export decorators. */+# if defined(BUILDING_UV_SHARED)+    /* Building shared library. */+#   define UV_EXTERN __declspec(dllexport)+# elif defined(USING_UV_SHARED)+    /* Using shared library. */+#   define UV_EXTERN __declspec(dllimport)+# else+    /* Building static library. */+#   define UV_EXTERN /* nothing */+# endif+#elif __GNUC__ >= 4+# define UV_EXTERN __attribute__((visibility("default")))+#else+# define UV_EXTERN /* nothing */+#endif++#include "uv/errno.h"+#include "uv/version.h"+#include <stddef.h>+#include <stdio.h>++#if defined(_MSC_VER) && _MSC_VER < 1600+# include "uv/stdint-msvc2008.h"+#else+# include <stdint.h>+#endif++#if defined(_WIN32)+# include "uv/win.h"+#else+# include "uv/unix.h"+#endif++/* Expand this list if necessary. */+#define UV_ERRNO_MAP(XX)                                                      \+  XX(E2BIG, "argument list too long")                                         \+  XX(EACCES, "permission denied")                                             \+  XX(EADDRINUSE, "address already in use")                                    \+  XX(EADDRNOTAVAIL, "address not available")                                  \+  XX(EAFNOSUPPORT, "address family not supported")                            \+  XX(EAGAIN, "resource temporarily unavailable")                              \+  XX(EAI_ADDRFAMILY, "address family not supported")                          \+  XX(EAI_AGAIN, "temporary failure")                                          \+  XX(EAI_BADFLAGS, "bad ai_flags value")                                      \+  XX(EAI_BADHINTS, "invalid value for hints")                                 \+  XX(EAI_CANCELED, "request canceled")                                        \+  XX(EAI_FAIL, "permanent failure")                                           \+  XX(EAI_FAMILY, "ai_family not supported")                                   \+  XX(EAI_MEMORY, "out of memory")                                             \+  XX(EAI_NODATA, "no address")                                                \+  XX(EAI_NONAME, "unknown node or service")                                   \+  XX(EAI_OVERFLOW, "argument buffer overflow")                                \+  XX(EAI_PROTOCOL, "resolved protocol is unknown")                            \+  XX(EAI_SERVICE, "service not available for socket type")                    \+  XX(EAI_SOCKTYPE, "socket type not supported")                               \+  XX(EALREADY, "connection already in progress")                              \+  XX(EBADF, "bad file descriptor")                                            \+  XX(EBUSY, "resource busy or locked")                                        \+  XX(ECANCELED, "operation canceled")                                         \+  XX(ECHARSET, "invalid Unicode character")                                   \+  XX(ECONNABORTED, "software caused connection abort")                        \+  XX(ECONNREFUSED, "connection refused")                                      \+  XX(ECONNRESET, "connection reset by peer")                                  \+  XX(EDESTADDRREQ, "destination address required")                            \+  XX(EEXIST, "file already exists")                                           \+  XX(EFAULT, "bad address in system call argument")                           \+  XX(EFBIG, "file too large")                                                 \+  XX(EHOSTUNREACH, "host is unreachable")                                     \+  XX(EINTR, "interrupted system call")                                        \+  XX(EINVAL, "invalid argument")                                              \+  XX(EIO, "i/o error")                                                        \+  XX(EISCONN, "socket is already connected")                                  \+  XX(EISDIR, "illegal operation on a directory")                              \+  XX(ELOOP, "too many symbolic links encountered")                            \+  XX(EMFILE, "too many open files")                                           \+  XX(EMSGSIZE, "message too long")                                            \+  XX(ENAMETOOLONG, "name too long")                                           \+  XX(ENETDOWN, "network is down")                                             \+  XX(ENETUNREACH, "network is unreachable")                                   \+  XX(ENFILE, "file table overflow")                                           \+  XX(ENOBUFS, "no buffer space available")                                    \+  XX(ENODEV, "no such device")                                                \+  XX(ENOENT, "no such file or directory")                                     \+  XX(ENOMEM, "not enough memory")                                             \+  XX(ENONET, "machine is not on the network")                                 \+  XX(ENOPROTOOPT, "protocol not available")                                   \+  XX(ENOSPC, "no space left on device")                                       \+  XX(ENOSYS, "function not implemented")                                      \+  XX(ENOTCONN, "socket is not connected")                                     \+  XX(ENOTDIR, "not a directory")                                              \+  XX(ENOTEMPTY, "directory not empty")                                        \+  XX(ENOTSOCK, "socket operation on non-socket")                              \+  XX(ENOTSUP, "operation not supported on socket")                            \+  XX(EPERM, "operation not permitted")                                        \+  XX(EPIPE, "broken pipe")                                                    \+  XX(EPROTO, "protocol error")                                                \+  XX(EPROTONOSUPPORT, "protocol not supported")                               \+  XX(EPROTOTYPE, "protocol wrong type for socket")                            \+  XX(ERANGE, "result too large")                                              \+  XX(EROFS, "read-only file system")                                          \+  XX(ESHUTDOWN, "cannot send after transport endpoint shutdown")              \+  XX(ESPIPE, "invalid seek")                                                  \+  XX(ESRCH, "no such process")                                                \+  XX(ETIMEDOUT, "connection timed out")                                       \+  XX(ETXTBSY, "text file is busy")                                            \+  XX(EXDEV, "cross-device link not permitted")                                \+  XX(UNKNOWN, "unknown error")                                                \+  XX(EOF, "end of file")                                                      \+  XX(ENXIO, "no such device or address")                                      \+  XX(EMLINK, "too many links")                                                \+  XX(EHOSTDOWN, "host is down")                                               \+  XX(EREMOTEIO, "remote I/O error")                                           \+  XX(ENOTTY, "inappropriate ioctl for device")                                \+  XX(EFTYPE, "inappropriate file type or format")                             \++#define UV_HANDLE_TYPE_MAP(XX)                                                \+  XX(ASYNC, async)                                                            \+  XX(CHECK, check)                                                            \+  XX(FS_EVENT, fs_event)                                                      \+  XX(FS_POLL, fs_poll)                                                        \+  XX(HANDLE, handle)                                                          \+  XX(IDLE, idle)                                                              \+  XX(NAMED_PIPE, pipe)                                                        \+  XX(POLL, poll)                                                              \+  XX(PREPARE, prepare)                                                        \+  XX(PROCESS, process)                                                        \+  XX(STREAM, stream)                                                          \+  XX(TCP, tcp)                                                                \+  XX(TIMER, timer)                                                            \+  XX(TTY, tty)                                                                \+  XX(UDP, udp)                                                                \+  XX(SIGNAL, signal)                                                          \++#define UV_REQ_TYPE_MAP(XX)                                                   \+  XX(REQ, req)                                                                \+  XX(CONNECT, connect)                                                        \+  XX(WRITE, write)                                                            \+  XX(SHUTDOWN, shutdown)                                                      \+  XX(UDP_SEND, udp_send)                                                      \+  XX(FS, fs)                                                                  \+  XX(WORK, work)                                                              \+  XX(GETADDRINFO, getaddrinfo)                                                \+  XX(GETNAMEINFO, getnameinfo)                                                \++typedef enum {+#define XX(code, _) UV_ ## code = UV__ ## code,+  UV_ERRNO_MAP(XX)+#undef XX+  UV_ERRNO_MAX = UV__EOF - 1+} uv_errno_t;++typedef enum {+  UV_UNKNOWN_HANDLE = 0,+#define XX(uc, lc) UV_##uc,+  UV_HANDLE_TYPE_MAP(XX)+#undef XX+  UV_FILE,+  UV_HANDLE_TYPE_MAX+} uv_handle_type;++typedef enum {+  UV_UNKNOWN_REQ = 0,+#define XX(uc, lc) UV_##uc,+  UV_REQ_TYPE_MAP(XX)+#undef XX+  UV_REQ_TYPE_PRIVATE+  UV_REQ_TYPE_MAX+} uv_req_type;+++/* Handle types. */+typedef struct uv_loop_s uv_loop_t;+typedef struct uv_handle_s uv_handle_t;+typedef struct uv_stream_s uv_stream_t;+typedef struct uv_tcp_s uv_tcp_t;+typedef struct uv_udp_s uv_udp_t;+typedef struct uv_pipe_s uv_pipe_t;+typedef struct uv_tty_s uv_tty_t;+typedef struct uv_poll_s uv_poll_t;+typedef struct uv_timer_s uv_timer_t;+typedef struct uv_prepare_s uv_prepare_t;+typedef struct uv_check_s uv_check_t;+typedef struct uv_idle_s uv_idle_t;+typedef struct uv_async_s uv_async_t;+typedef struct uv_process_s uv_process_t;+typedef struct uv_fs_event_s uv_fs_event_t;+typedef struct uv_fs_poll_s uv_fs_poll_t;+typedef struct uv_signal_s uv_signal_t;++/* Request types. */+typedef struct uv_req_s uv_req_t;+typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;+typedef struct uv_getnameinfo_s uv_getnameinfo_t;+typedef struct uv_shutdown_s uv_shutdown_t;+typedef struct uv_write_s uv_write_t;+typedef struct uv_connect_s uv_connect_t;+typedef struct uv_udp_send_s uv_udp_send_t;+typedef struct uv_fs_s uv_fs_t;+typedef struct uv_work_s uv_work_t;++/* None of the above. */+typedef struct uv_cpu_info_s uv_cpu_info_t;+typedef struct uv_interface_address_s uv_interface_address_t;+typedef struct uv_dirent_s uv_dirent_t;+typedef struct uv_passwd_s uv_passwd_t;+typedef struct uv_utsname_s uv_utsname_t;++typedef enum {+  UV_LOOP_BLOCK_SIGNAL+} uv_loop_option;++typedef enum {+  UV_RUN_DEFAULT = 0,+  UV_RUN_ONCE,+  UV_RUN_NOWAIT+} uv_run_mode;+++UV_EXTERN unsigned int uv_version(void);+UV_EXTERN const char* uv_version_string(void);++typedef void* (*uv_malloc_func)(size_t size);+typedef void* (*uv_realloc_func)(void* ptr, size_t size);+typedef void* (*uv_calloc_func)(size_t count, size_t size);+typedef void (*uv_free_func)(void* ptr);++UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func,+                                   uv_realloc_func realloc_func,+                                   uv_calloc_func calloc_func,+                                   uv_free_func free_func);++UV_EXTERN uv_loop_t* uv_default_loop(void);+UV_EXTERN int uv_loop_init(uv_loop_t* loop);+UV_EXTERN int uv_loop_close(uv_loop_t* loop);+/*+ * NOTE:+ *  This function is DEPRECATED (to be removed after 0.12), users should+ *  allocate the loop manually and use uv_loop_init instead.+ */+UV_EXTERN uv_loop_t* uv_loop_new(void);+/*+ * NOTE:+ *  This function is DEPRECATED (to be removed after 0.12). Users should use+ *  uv_loop_close and free the memory manually instead.+ */+UV_EXTERN void uv_loop_delete(uv_loop_t*);+UV_EXTERN size_t uv_loop_size(void);+UV_EXTERN int uv_loop_alive(const uv_loop_t* loop);+UV_EXTERN int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...);+UV_EXTERN int uv_loop_fork(uv_loop_t* loop);++UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode);+UV_EXTERN void uv_stop(uv_loop_t*);++UV_EXTERN void uv_ref(uv_handle_t*);+UV_EXTERN void uv_unref(uv_handle_t*);+UV_EXTERN int uv_has_ref(const uv_handle_t*);++UV_EXTERN void uv_update_time(uv_loop_t*);+UV_EXTERN uint64_t uv_now(const uv_loop_t*);++UV_EXTERN int uv_backend_fd(const uv_loop_t*);+UV_EXTERN int uv_backend_timeout(const uv_loop_t*);++typedef void (*uv_alloc_cb)(uv_handle_t* handle,+                            size_t suggested_size,+                            uv_buf_t* buf);+typedef void (*uv_read_cb)(uv_stream_t* stream,+                           ssize_t nread,+                           const uv_buf_t* buf);+typedef void (*uv_write_cb)(uv_write_t* req, int status);+typedef void (*uv_connect_cb)(uv_connect_t* req, int status);+typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status);+typedef void (*uv_connection_cb)(uv_stream_t* server, int status);+typedef void (*uv_close_cb)(uv_handle_t* handle);+typedef void (*uv_poll_cb)(uv_poll_t* handle, int status, int events);+typedef void (*uv_timer_cb)(uv_timer_t* handle);+typedef void (*uv_async_cb)(uv_async_t* handle);+typedef void (*uv_prepare_cb)(uv_prepare_t* handle);+typedef void (*uv_check_cb)(uv_check_t* handle);+typedef void (*uv_idle_cb)(uv_idle_t* handle);+typedef void (*uv_exit_cb)(uv_process_t*, int64_t exit_status, int term_signal);+typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg);+typedef void (*uv_fs_cb)(uv_fs_t* req);+typedef void (*uv_work_cb)(uv_work_t* req);+typedef void (*uv_after_work_cb)(uv_work_t* req, int status);+typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req,+                                  int status,+                                  struct addrinfo* res);+typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req,+                                  int status,+                                  const char* hostname,+                                  const char* service);++typedef struct {+  long tv_sec;+  long tv_nsec;+} uv_timespec_t;+++typedef struct {+  uint64_t st_dev;+  uint64_t st_mode;+  uint64_t st_nlink;+  uint64_t st_uid;+  uint64_t st_gid;+  uint64_t st_rdev;+  uint64_t st_ino;+  uint64_t st_size;+  uint64_t st_blksize;+  uint64_t st_blocks;+  uint64_t st_flags;+  uint64_t st_gen;+  uv_timespec_t st_atim;+  uv_timespec_t st_mtim;+  uv_timespec_t st_ctim;+  uv_timespec_t st_birthtim;+} uv_stat_t;+++typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle,+                               const char* filename,+                               int events,+                               int status);++typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle,+                              int status,+                              const uv_stat_t* prev,+                              const uv_stat_t* curr);++typedef void (*uv_signal_cb)(uv_signal_t* handle, int signum);+++typedef enum {+  UV_LEAVE_GROUP = 0,+  UV_JOIN_GROUP+} uv_membership;+++UV_EXTERN int uv_translate_sys_error(int sys_errno);++UV_EXTERN const char* uv_strerror(int err);+UV_EXTERN char* uv_strerror_r(int err, char* buf, size_t buflen);++UV_EXTERN const char* uv_err_name(int err);+UV_EXTERN char* uv_err_name_r(int err, char* buf, size_t buflen);+++#define UV_REQ_FIELDS                                                         \+  /* public */                                                                \+  void* data;                                                                 \+  /* read-only */                                                             \+  uv_req_type type;                                                           \+  /* private */                                                               \+  void* reserved[6];                                                          \+  UV_REQ_PRIVATE_FIELDS                                                       \++/* Abstract base class of all requests. */+struct uv_req_s {+  UV_REQ_FIELDS+};+++/* Platform-specific request types. */+UV_PRIVATE_REQ_TYPES+++UV_EXTERN int uv_shutdown(uv_shutdown_t* req,+                          uv_stream_t* handle,+                          uv_shutdown_cb cb);++struct uv_shutdown_s {+  UV_REQ_FIELDS+  uv_stream_t* handle;+  uv_shutdown_cb cb;+  UV_SHUTDOWN_PRIVATE_FIELDS+};+++#define UV_HANDLE_FIELDS                                                      \+  /* public */                                                                \+  void* data;                                                                 \+  /* read-only */                                                             \+  uv_loop_t* loop;                                                            \+  uv_handle_type type;                                                        \+  /* private */                                                               \+  uv_close_cb close_cb;                                                       \+  void* handle_queue[2];                                                      \+  union {                                                                     \+    int fd;                                                                   \+    void* reserved[4];                                                        \+  } u;                                                                        \+  UV_HANDLE_PRIVATE_FIELDS                                                    \++/* The abstract base class of all handles. */+struct uv_handle_s {+  UV_HANDLE_FIELDS+};++UV_EXTERN size_t uv_handle_size(uv_handle_type type);+UV_EXTERN uv_handle_type uv_handle_get_type(const uv_handle_t* handle);+UV_EXTERN const char* uv_handle_type_name(uv_handle_type type);+UV_EXTERN void* uv_handle_get_data(const uv_handle_t* handle);+UV_EXTERN uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle);+UV_EXTERN void uv_handle_set_data(uv_handle_t* handle, void* data);++UV_EXTERN size_t uv_req_size(uv_req_type type);+UV_EXTERN void* uv_req_get_data(const uv_req_t* req);+UV_EXTERN void uv_req_set_data(uv_req_t* req, void* data);+UV_EXTERN uv_req_type uv_req_get_type(const uv_req_t* req);+UV_EXTERN const char* uv_req_type_name(uv_req_type type);++UV_EXTERN int uv_is_active(const uv_handle_t* handle);++UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg);++/* Helpers for ad hoc debugging, no API/ABI stability guaranteed. */+UV_EXTERN void uv_print_all_handles(uv_loop_t* loop, FILE* stream);+UV_EXTERN void uv_print_active_handles(uv_loop_t* loop, FILE* stream);++UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb);++UV_EXTERN int uv_send_buffer_size(uv_handle_t* handle, int* value);+UV_EXTERN int uv_recv_buffer_size(uv_handle_t* handle, int* value);++UV_EXTERN int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd);++UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len);+++#define UV_STREAM_FIELDS                                                      \+  /* number of bytes queued for writing */                                    \+  size_t write_queue_size;                                                    \+  uv_alloc_cb alloc_cb;                                                       \+  uv_read_cb read_cb;                                                         \+  /* private */                                                               \+  UV_STREAM_PRIVATE_FIELDS++/*+ * uv_stream_t is a subclass of uv_handle_t.+ *+ * uv_stream is an abstract class.+ *+ * uv_stream_t is the parent class of uv_tcp_t, uv_pipe_t and uv_tty_t.+ */+struct uv_stream_s {+  UV_HANDLE_FIELDS+  UV_STREAM_FIELDS+};++UV_EXTERN size_t uv_stream_get_write_queue_size(const uv_stream_t* stream);++UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);+UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client);++UV_EXTERN int uv_read_start(uv_stream_t*,+                            uv_alloc_cb alloc_cb,+                            uv_read_cb read_cb);+UV_EXTERN int uv_read_stop(uv_stream_t*);++UV_EXTERN int uv_write(uv_write_t* req,+                       uv_stream_t* handle,+                       const uv_buf_t bufs[],+                       unsigned int nbufs,+                       uv_write_cb cb);+UV_EXTERN int uv_write2(uv_write_t* req,+                        uv_stream_t* handle,+                        const uv_buf_t bufs[],+                        unsigned int nbufs,+                        uv_stream_t* send_handle,+                        uv_write_cb cb);+UV_EXTERN int uv_try_write(uv_stream_t* handle,+                           const uv_buf_t bufs[],+                           unsigned int nbufs);++/* uv_write_t is a subclass of uv_req_t. */+struct uv_write_s {+  UV_REQ_FIELDS+  uv_write_cb cb;+  uv_stream_t* send_handle; /* TODO: make private and unix-only in v2.x. */+  uv_stream_t* handle;+  UV_WRITE_PRIVATE_FIELDS+};+++UV_EXTERN int uv_is_readable(const uv_stream_t* handle);+UV_EXTERN int uv_is_writable(const uv_stream_t* handle);++UV_EXTERN int uv_stream_set_blocking(uv_stream_t* handle, int blocking);++UV_EXTERN int uv_is_closing(const uv_handle_t* handle);+++/*+ * uv_tcp_t is a subclass of uv_stream_t.+ *+ * Represents a TCP stream or TCP server.+ */+struct uv_tcp_s {+  UV_HANDLE_FIELDS+  UV_STREAM_FIELDS+  UV_TCP_PRIVATE_FIELDS+};++UV_EXTERN int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle);+UV_EXTERN int uv_tcp_init_ex(uv_loop_t*, uv_tcp_t* handle, unsigned int flags);+UV_EXTERN int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock);+UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable);+UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle,+                               int enable,+                               unsigned int delay);+UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);++enum uv_tcp_flags {+  /* Used with uv_tcp_bind, when an IPv6 address is used. */+  UV_TCP_IPV6ONLY = 1+};++UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle,+                          const struct sockaddr* addr,+                          unsigned int flags);+UV_EXTERN int uv_tcp_getsockname(const uv_tcp_t* handle,+                                 struct sockaddr* name,+                                 int* namelen);+UV_EXTERN int uv_tcp_getpeername(const uv_tcp_t* handle,+                                 struct sockaddr* name,+                                 int* namelen);+UV_EXTERN int uv_tcp_connect(uv_connect_t* req,+                             uv_tcp_t* handle,+                             const struct sockaddr* addr,+                             uv_connect_cb cb);++/* uv_connect_t is a subclass of uv_req_t. */+struct uv_connect_s {+  UV_REQ_FIELDS+  uv_connect_cb cb;+  uv_stream_t* handle;+  UV_CONNECT_PRIVATE_FIELDS+};+++/*+ * UDP support.+ */++enum uv_udp_flags {+  /* Disables dual stack mode. */+  UV_UDP_IPV6ONLY = 1,+  /*+   * Indicates message was truncated because read buffer was too small. The+   * remainder was discarded by the OS. Used in uv_udp_recv_cb.+   */+  UV_UDP_PARTIAL = 2,+  /*+   * Indicates if SO_REUSEADDR will be set when binding the handle.+   * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other+   * Unix platforms, it sets the SO_REUSEADDR flag.  What that means is that+   * multiple threads or processes can bind to the same address without error+   * (provided they all set the flag) but only the last one to bind will receive+   * any traffic, in effect "stealing" the port from the previous listener.+   */+  UV_UDP_REUSEADDR = 4+};++typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);+typedef void (*uv_udp_recv_cb)(uv_udp_t* handle,+                               ssize_t nread,+                               const uv_buf_t* buf,+                               const struct sockaddr* addr,+                               unsigned flags);++/* uv_udp_t is a subclass of uv_handle_t. */+struct uv_udp_s {+  UV_HANDLE_FIELDS+  /* read-only */+  /*+   * Number of bytes queued for sending. This field strictly shows how much+   * information is currently queued.+   */+  size_t send_queue_size;+  /*+   * Number of send requests currently in the queue awaiting to be processed.+   */+  size_t send_queue_count;+  UV_UDP_PRIVATE_FIELDS+};++/* uv_udp_send_t is a subclass of uv_req_t. */+struct uv_udp_send_s {+  UV_REQ_FIELDS+  uv_udp_t* handle;+  uv_udp_send_cb cb;+  UV_UDP_SEND_PRIVATE_FIELDS+};++UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle);+UV_EXTERN int uv_udp_init_ex(uv_loop_t*, uv_udp_t* handle, unsigned int flags);+UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock);+UV_EXTERN int uv_udp_bind(uv_udp_t* handle,+                          const struct sockaddr* addr,+                          unsigned int flags);++UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle,+                                 struct sockaddr* name,+                                 int* namelen);+UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle,+                                    const char* multicast_addr,+                                    const char* interface_addr,+                                    uv_membership membership);+UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t* handle, int on);+UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl);+UV_EXTERN int uv_udp_set_multicast_interface(uv_udp_t* handle,+                                             const char* interface_addr);+UV_EXTERN int uv_udp_set_broadcast(uv_udp_t* handle, int on);+UV_EXTERN int uv_udp_set_ttl(uv_udp_t* handle, int ttl);+UV_EXTERN int uv_udp_send(uv_udp_send_t* req,+                          uv_udp_t* handle,+                          const uv_buf_t bufs[],+                          unsigned int nbufs,+                          const struct sockaddr* addr,+                          uv_udp_send_cb send_cb);+UV_EXTERN int uv_udp_try_send(uv_udp_t* handle,+                              const uv_buf_t bufs[],+                              unsigned int nbufs,+                              const struct sockaddr* addr);+UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,+                                uv_alloc_cb alloc_cb,+                                uv_udp_recv_cb recv_cb);+UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle);+UV_EXTERN size_t uv_udp_get_send_queue_size(const uv_udp_t* handle);+UV_EXTERN size_t uv_udp_get_send_queue_count(const uv_udp_t* handle);+++/*+ * uv_tty_t is a subclass of uv_stream_t.+ *+ * Representing a stream for the console.+ */+struct uv_tty_s {+  UV_HANDLE_FIELDS+  UV_STREAM_FIELDS+  UV_TTY_PRIVATE_FIELDS+};++typedef enum {+  /* Initial/normal terminal mode */+  UV_TTY_MODE_NORMAL,+  /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */+  UV_TTY_MODE_RAW,+  /* Binary-safe I/O mode for IPC (Unix-only) */+  UV_TTY_MODE_IO+} uv_tty_mode_t;++UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable);+UV_EXTERN int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode);+UV_EXTERN int uv_tty_reset_mode(void);+UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height);++#ifdef __cplusplus+extern "C++" {++inline int uv_tty_set_mode(uv_tty_t* handle, int mode) {+  return uv_tty_set_mode(handle, static_cast<uv_tty_mode_t>(mode));+}++}+#endif++UV_EXTERN uv_handle_type uv_guess_handle(uv_file file);++/*+ * uv_pipe_t is a subclass of uv_stream_t.+ *+ * Representing a pipe stream or pipe server. On Windows this is a Named+ * Pipe. On Unix this is a Unix domain socket.+ */+struct uv_pipe_s {+  UV_HANDLE_FIELDS+  UV_STREAM_FIELDS+  int ipc; /* non-zero if this pipe is used for passing handles */+  UV_PIPE_PRIVATE_FIELDS+};++UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc);+UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file);+UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name);+UV_EXTERN void uv_pipe_connect(uv_connect_t* req,+                               uv_pipe_t* handle,+                               const char* name,+                               uv_connect_cb cb);+UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle,+                                  char* buffer,+                                  size_t* size);+UV_EXTERN int uv_pipe_getpeername(const uv_pipe_t* handle,+                                  char* buffer,+                                  size_t* size);+UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count);+UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle);+UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle);+UV_EXTERN int uv_pipe_chmod(uv_pipe_t* handle, int flags);+++struct uv_poll_s {+  UV_HANDLE_FIELDS+  uv_poll_cb poll_cb;+  UV_POLL_PRIVATE_FIELDS+};++enum uv_poll_event {+  UV_READABLE = 1,+  UV_WRITABLE = 2,+  UV_DISCONNECT = 4,+  UV_PRIORITIZED = 8+};++UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd);+UV_EXTERN int uv_poll_init_socket(uv_loop_t* loop,+                                  uv_poll_t* handle,+                                  uv_os_sock_t socket);+UV_EXTERN int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb);+UV_EXTERN int uv_poll_stop(uv_poll_t* handle);+++struct uv_prepare_s {+  UV_HANDLE_FIELDS+  UV_PREPARE_PRIVATE_FIELDS+};++UV_EXTERN int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare);+UV_EXTERN int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb);+UV_EXTERN int uv_prepare_stop(uv_prepare_t* prepare);+++struct uv_check_s {+  UV_HANDLE_FIELDS+  UV_CHECK_PRIVATE_FIELDS+};++UV_EXTERN int uv_check_init(uv_loop_t*, uv_check_t* check);+UV_EXTERN int uv_check_start(uv_check_t* check, uv_check_cb cb);+UV_EXTERN int uv_check_stop(uv_check_t* check);+++struct uv_idle_s {+  UV_HANDLE_FIELDS+  UV_IDLE_PRIVATE_FIELDS+};++UV_EXTERN int uv_idle_init(uv_loop_t*, uv_idle_t* idle);+UV_EXTERN int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb);+UV_EXTERN int uv_idle_stop(uv_idle_t* idle);+++struct uv_async_s {+  UV_HANDLE_FIELDS+  UV_ASYNC_PRIVATE_FIELDS+};++UV_EXTERN int uv_async_init(uv_loop_t*,+                            uv_async_t* async,+                            uv_async_cb async_cb);+UV_EXTERN int uv_async_send(uv_async_t* async);+++/*+ * uv_timer_t is a subclass of uv_handle_t.+ *+ * Used to get woken up at a specified time in the future.+ */+struct uv_timer_s {+  UV_HANDLE_FIELDS+  UV_TIMER_PRIVATE_FIELDS+};++UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* handle);+UV_EXTERN int uv_timer_start(uv_timer_t* handle,+                             uv_timer_cb cb,+                             uint64_t timeout,+                             uint64_t repeat);+UV_EXTERN int uv_timer_stop(uv_timer_t* handle);+UV_EXTERN int uv_timer_again(uv_timer_t* handle);+UV_EXTERN void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat);+UV_EXTERN uint64_t uv_timer_get_repeat(const uv_timer_t* handle);+++/*+ * uv_getaddrinfo_t is a subclass of uv_req_t.+ *+ * Request object for uv_getaddrinfo.+ */+struct uv_getaddrinfo_s {+  UV_REQ_FIELDS+  /* read-only */+  uv_loop_t* loop;+  /* struct addrinfo* addrinfo is marked as private, but it really isn't. */+  UV_GETADDRINFO_PRIVATE_FIELDS+};+++UV_EXTERN int uv_getaddrinfo(uv_loop_t* loop,+                             uv_getaddrinfo_t* req,+                             uv_getaddrinfo_cb getaddrinfo_cb,+                             const char* node,+                             const char* service,+                             const struct addrinfo* hints);+UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai);+++/*+* uv_getnameinfo_t is a subclass of uv_req_t.+*+* Request object for uv_getnameinfo.+*/+struct uv_getnameinfo_s {+  UV_REQ_FIELDS+  /* read-only */+  uv_loop_t* loop;+  /* host and service are marked as private, but they really aren't. */+  UV_GETNAMEINFO_PRIVATE_FIELDS+};++UV_EXTERN int uv_getnameinfo(uv_loop_t* loop,+                             uv_getnameinfo_t* req,+                             uv_getnameinfo_cb getnameinfo_cb,+                             const struct sockaddr* addr,+                             int flags);+++/* uv_spawn() options. */+typedef enum {+  UV_IGNORE         = 0x00,+  UV_CREATE_PIPE    = 0x01,+  UV_INHERIT_FD     = 0x02,+  UV_INHERIT_STREAM = 0x04,++  /*+   * When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE+   * determine the direction of flow, from the child process' perspective. Both+   * flags may be specified to create a duplex data stream.+   */+  UV_READABLE_PIPE  = 0x10,+  UV_WRITABLE_PIPE  = 0x20,++  /*+   * Open the child pipe handle in overlapped mode on Windows.+   * On Unix it is silently ignored.+   */+  UV_OVERLAPPED_PIPE = 0x40+} uv_stdio_flags;++typedef struct uv_stdio_container_s {+  uv_stdio_flags flags;++  union {+    uv_stream_t* stream;+    int fd;+  } data;+} uv_stdio_container_t;++typedef struct uv_process_options_s {+  uv_exit_cb exit_cb; /* Called after the process exits. */+  const char* file;   /* Path to program to execute. */+  /*+   * Command line arguments. args[0] should be the path to the program. On+   * Windows this uses CreateProcess which concatenates the arguments into a+   * string this can cause some strange errors. See the note at+   * windows_verbatim_arguments.+   */+  char** args;+  /*+   * This will be set as the environ variable in the subprocess. If this is+   * NULL then the parents environ will be used.+   */+  char** env;+  /*+   * If non-null this represents a directory the subprocess should execute+   * in. Stands for current working directory.+   */+  const char* cwd;+  /*+   * Various flags that control how uv_spawn() behaves. See the definition of+   * `enum uv_process_flags` below.+   */+  unsigned int flags;+  /*+   * The `stdio` field points to an array of uv_stdio_container_t structs that+   * describe the file descriptors that will be made available to the child+   * process. The convention is that stdio[0] points to stdin, fd 1 is used for+   * stdout, and fd 2 is stderr.+   *+   * Note that on windows file descriptors greater than 2 are available to the+   * child process only if the child processes uses the MSVCRT runtime.+   */+  int stdio_count;+  uv_stdio_container_t* stdio;+  /*+   * Libuv can change the child process' user/group id. This happens only when+   * the appropriate bits are set in the flags fields. This is not supported on+   * windows; uv_spawn() will fail and set the error to UV_ENOTSUP.+   */+  uv_uid_t uid;+  uv_gid_t gid;+} uv_process_options_t;++/*+ * These are the flags that can be used for the uv_process_options.flags field.+ */+enum uv_process_flags {+  /*+   * Set the child process' user id. The user id is supplied in the `uid` field+   * of the options struct. This does not work on windows; setting this flag+   * will cause uv_spawn() to fail.+   */+  UV_PROCESS_SETUID = (1 << 0),+  /*+   * Set the child process' group id. The user id is supplied in the `gid`+   * field of the options struct. This does not work on windows; setting this+   * flag will cause uv_spawn() to fail.+   */+  UV_PROCESS_SETGID = (1 << 1),+  /*+   * Do not wrap any arguments in quotes, or perform any other escaping, when+   * converting the argument list into a command line string. This option is+   * only meaningful on Windows systems. On Unix it is silently ignored.+   */+  UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2),+  /*+   * Spawn the child process in a detached state - this will make it a process+   * group leader, and will effectively enable the child to keep running after+   * the parent exits.  Note that the child process will still keep the+   * parent's event loop alive unless the parent process calls uv_unref() on+   * the child's process handle.+   */+  UV_PROCESS_DETACHED = (1 << 3),+  /*+   * Hide the subprocess window that would normally be created. This option is+   * only meaningful on Windows systems. On Unix it is silently ignored.+   */+  UV_PROCESS_WINDOWS_HIDE = (1 << 4),+  /*+   * Hide the subprocess console window that would normally be created. This+   * option is only meaningful on Windows systems. On Unix it is silently+   * ignored.+   */+  UV_PROCESS_WINDOWS_HIDE_CONSOLE = (1 << 5),+  /*+   * Hide the subprocess GUI window that would normally be created. This+   * option is only meaningful on Windows systems. On Unix it is silently+   * ignored.+   */+  UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6)+};++/*+ * uv_process_t is a subclass of uv_handle_t.+ */+struct uv_process_s {+  UV_HANDLE_FIELDS+  uv_exit_cb exit_cb;+  int pid;+  UV_PROCESS_PRIVATE_FIELDS+};++UV_EXTERN int uv_spawn(uv_loop_t* loop,+                       uv_process_t* handle,+                       const uv_process_options_t* options);+UV_EXTERN int uv_process_kill(uv_process_t*, int signum);+UV_EXTERN int uv_kill(int pid, int signum);+UV_EXTERN uv_pid_t uv_process_get_pid(const uv_process_t*);+++/*+ * uv_work_t is a subclass of uv_req_t.+ */+struct uv_work_s {+  UV_REQ_FIELDS+  uv_loop_t* loop;+  uv_work_cb work_cb;+  uv_after_work_cb after_work_cb;+  UV_WORK_PRIVATE_FIELDS+};++UV_EXTERN int uv_queue_work(uv_loop_t* loop,+                            uv_work_t* req,+                            uv_work_cb work_cb,+                            uv_after_work_cb after_work_cb);++UV_EXTERN int uv_cancel(uv_req_t* req);+++struct uv_cpu_times_s {+  uint64_t user;+  uint64_t nice;+  uint64_t sys;+  uint64_t idle;+  uint64_t irq;+};++struct uv_cpu_info_s {+  char* model;+  int speed;+  struct uv_cpu_times_s cpu_times;+};++struct uv_interface_address_s {+  char* name;+  char phys_addr[6];+  int is_internal;+  union {+    struct sockaddr_in address4;+    struct sockaddr_in6 address6;+  } address;+  union {+    struct sockaddr_in netmask4;+    struct sockaddr_in6 netmask6;+  } netmask;+};++struct uv_passwd_s {+  char* username;+  long uid;+  long gid;+  char* shell;+  char* homedir;+};++struct uv_utsname_s {+  char sysname[256];+  char release[256];+  char version[256];+  char machine[256];+  /* This struct does not contain the nodename and domainname fields present in+     the utsname type. domainname is a GNU extension. Both fields are referred+     to as meaningless in the docs. */+};++typedef enum {+  UV_DIRENT_UNKNOWN,+  UV_DIRENT_FILE,+  UV_DIRENT_DIR,+  UV_DIRENT_LINK,+  UV_DIRENT_FIFO,+  UV_DIRENT_SOCKET,+  UV_DIRENT_CHAR,+  UV_DIRENT_BLOCK+} uv_dirent_type_t;++struct uv_dirent_s {+  const char* name;+  uv_dirent_type_t type;+};++UV_EXTERN char** uv_setup_args(int argc, char** argv);+UV_EXTERN int uv_get_process_title(char* buffer, size_t size);+UV_EXTERN int uv_set_process_title(const char* title);+UV_EXTERN int uv_resident_set_memory(size_t* rss);+UV_EXTERN int uv_uptime(double* uptime);+UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd);+UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_fd);++typedef struct {+  long tv_sec;+  long tv_usec;+} uv_timeval_t;++typedef struct {+   uv_timeval_t ru_utime; /* user CPU time used */+   uv_timeval_t ru_stime; /* system CPU time used */+   uint64_t ru_maxrss;    /* maximum resident set size */+   uint64_t ru_ixrss;     /* integral shared memory size */+   uint64_t ru_idrss;     /* integral unshared data size */+   uint64_t ru_isrss;     /* integral unshared stack size */+   uint64_t ru_minflt;    /* page reclaims (soft page faults) */+   uint64_t ru_majflt;    /* page faults (hard page faults) */+   uint64_t ru_nswap;     /* swaps */+   uint64_t ru_inblock;   /* block input operations */+   uint64_t ru_oublock;   /* block output operations */+   uint64_t ru_msgsnd;    /* IPC messages sent */+   uint64_t ru_msgrcv;    /* IPC messages received */+   uint64_t ru_nsignals;  /* signals received */+   uint64_t ru_nvcsw;     /* voluntary context switches */+   uint64_t ru_nivcsw;    /* involuntary context switches */+} uv_rusage_t;++UV_EXTERN int uv_getrusage(uv_rusage_t* rusage);++UV_EXTERN int uv_os_homedir(char* buffer, size_t* size);+UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size);+UV_EXTERN int uv_os_get_passwd(uv_passwd_t* pwd);+UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd);+UV_EXTERN uv_pid_t uv_os_getpid(void);+UV_EXTERN uv_pid_t uv_os_getppid(void);++#define UV_PRIORITY_LOW 19+#define UV_PRIORITY_BELOW_NORMAL 10+#define UV_PRIORITY_NORMAL 0+#define UV_PRIORITY_ABOVE_NORMAL -7+#define UV_PRIORITY_HIGH -14+#define UV_PRIORITY_HIGHEST -20++UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority);+UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);++UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);+UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);++UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,+                                     int* count);+UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses,+                                           int count);++UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size);+UV_EXTERN int uv_os_setenv(const char* name, const char* value);+UV_EXTERN int uv_os_unsetenv(const char* name);++#ifdef MAXHOSTNAMELEN+# define UV_MAXHOSTNAMESIZE (MAXHOSTNAMELEN + 1)+#else+  /*+    Fallback for the maximum hostname size, including the null terminator. The+    Windows gethostname() documentation states that 256 bytes will always be+    large enough to hold the null-terminated hostname.+  */+# define UV_MAXHOSTNAMESIZE 256+#endif++UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);++UV_EXTERN int uv_os_uname(uv_utsname_t* buffer);+++typedef enum {+  UV_FS_UNKNOWN = -1,+  UV_FS_CUSTOM,+  UV_FS_OPEN,+  UV_FS_CLOSE,+  UV_FS_READ,+  UV_FS_WRITE,+  UV_FS_SENDFILE,+  UV_FS_STAT,+  UV_FS_LSTAT,+  UV_FS_FSTAT,+  UV_FS_FTRUNCATE,+  UV_FS_UTIME,+  UV_FS_FUTIME,+  UV_FS_ACCESS,+  UV_FS_CHMOD,+  UV_FS_FCHMOD,+  UV_FS_FSYNC,+  UV_FS_FDATASYNC,+  UV_FS_UNLINK,+  UV_FS_RMDIR,+  UV_FS_MKDIR,+  UV_FS_MKDTEMP,+  UV_FS_RENAME,+  UV_FS_SCANDIR,+  UV_FS_LINK,+  UV_FS_SYMLINK,+  UV_FS_READLINK,+  UV_FS_CHOWN,+  UV_FS_FCHOWN,+  UV_FS_REALPATH,+  UV_FS_COPYFILE,+  UV_FS_LCHOWN+} uv_fs_type;++/* uv_fs_t is a subclass of uv_req_t. */+struct uv_fs_s {+  UV_REQ_FIELDS+  uv_fs_type fs_type;+  uv_loop_t* loop;+  uv_fs_cb cb;+  ssize_t result;+  void* ptr;+  const char* path;+  uv_stat_t statbuf;  /* Stores the result of uv_fs_stat() and uv_fs_fstat(). */+  UV_FS_PRIVATE_FIELDS+};++UV_EXTERN uv_fs_type uv_fs_get_type(const uv_fs_t*);+UV_EXTERN ssize_t uv_fs_get_result(const uv_fs_t*);+UV_EXTERN void* uv_fs_get_ptr(const uv_fs_t*);+UV_EXTERN const char* uv_fs_get_path(const uv_fs_t*);+UV_EXTERN uv_stat_t* uv_fs_get_statbuf(uv_fs_t*);++UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req);+UV_EXTERN int uv_fs_close(uv_loop_t* loop,+                          uv_fs_t* req,+                          uv_file file,+                          uv_fs_cb cb);+UV_EXTERN int uv_fs_open(uv_loop_t* loop,+                         uv_fs_t* req,+                         const char* path,+                         int flags,+                         int mode,+                         uv_fs_cb cb);+UV_EXTERN int uv_fs_read(uv_loop_t* loop,+                         uv_fs_t* req,+                         uv_file file,+                         const uv_buf_t bufs[],+                         unsigned int nbufs,+                         int64_t offset,+                         uv_fs_cb cb);+UV_EXTERN int uv_fs_unlink(uv_loop_t* loop,+                           uv_fs_t* req,+                           const char* path,+                           uv_fs_cb cb);+UV_EXTERN int uv_fs_write(uv_loop_t* loop,+                          uv_fs_t* req,+                          uv_file file,+                          const uv_buf_t bufs[],+                          unsigned int nbufs,+                          int64_t offset,+                          uv_fs_cb cb);+/*+ * This flag can be used with uv_fs_copyfile() to return an error if the+ * destination already exists.+ */+#define UV_FS_COPYFILE_EXCL   0x0001++/*+ * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.+ * If copy-on-write is not supported, a fallback copy mechanism is used.+ */+#define UV_FS_COPYFILE_FICLONE 0x0002++/*+ * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.+ * If copy-on-write is not supported, an error is returned.+ */+#define UV_FS_COPYFILE_FICLONE_FORCE 0x0004++UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop,+                             uv_fs_t* req,+                             const char* path,+                             const char* new_path,+                             int flags,+                             uv_fs_cb cb);+UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop,+                          uv_fs_t* req,+                          const char* path,+                          int mode,+                          uv_fs_cb cb);+UV_EXTERN int uv_fs_mkdtemp(uv_loop_t* loop,+                            uv_fs_t* req,+                            const char* tpl,+                            uv_fs_cb cb);+UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop,+                          uv_fs_t* req,+                          const char* path,+                          uv_fs_cb cb);+UV_EXTERN int uv_fs_scandir(uv_loop_t* loop,+                            uv_fs_t* req,+                            const char* path,+                            int flags,+                            uv_fs_cb cb);+UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req,+                                 uv_dirent_t* ent);+UV_EXTERN int uv_fs_stat(uv_loop_t* loop,+                         uv_fs_t* req,+                         const char* path,+                         uv_fs_cb cb);+UV_EXTERN int uv_fs_fstat(uv_loop_t* loop,+                          uv_fs_t* req,+                          uv_file file,+                          uv_fs_cb cb);+UV_EXTERN int uv_fs_rename(uv_loop_t* loop,+                           uv_fs_t* req,+                           const char* path,+                           const char* new_path,+                           uv_fs_cb cb);+UV_EXTERN int uv_fs_fsync(uv_loop_t* loop,+                          uv_fs_t* req,+                          uv_file file,+                          uv_fs_cb cb);+UV_EXTERN int uv_fs_fdatasync(uv_loop_t* loop,+                              uv_fs_t* req,+                              uv_file file,+                              uv_fs_cb cb);+UV_EXTERN int uv_fs_ftruncate(uv_loop_t* loop,+                              uv_fs_t* req,+                              uv_file file,+                              int64_t offset,+                              uv_fs_cb cb);+UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop,+                             uv_fs_t* req,+                             uv_file out_fd,+                             uv_file in_fd,+                             int64_t in_offset,+                             size_t length,+                             uv_fs_cb cb);+UV_EXTERN int uv_fs_access(uv_loop_t* loop,+                           uv_fs_t* req,+                           const char* path,+                           int mode,+                           uv_fs_cb cb);+UV_EXTERN int uv_fs_chmod(uv_loop_t* loop,+                          uv_fs_t* req,+                          const char* path,+                          int mode,+                          uv_fs_cb cb);+UV_EXTERN int uv_fs_utime(uv_loop_t* loop,+                          uv_fs_t* req,+                          const char* path,+                          double atime,+                          double mtime,+                          uv_fs_cb cb);+UV_EXTERN int uv_fs_futime(uv_loop_t* loop,+                           uv_fs_t* req,+                           uv_file file,+                           double atime,+                           double mtime,+                           uv_fs_cb cb);+UV_EXTERN int uv_fs_lstat(uv_loop_t* loop,+                          uv_fs_t* req,+                          const char* path,+                          uv_fs_cb cb);+UV_EXTERN int uv_fs_link(uv_loop_t* loop,+                         uv_fs_t* req,+                         const char* path,+                         const char* new_path,+                         uv_fs_cb cb);++/*+ * This flag can be used with uv_fs_symlink() on Windows to specify whether+ * path argument points to a directory.+ */+#define UV_FS_SYMLINK_DIR          0x0001++/*+ * This flag can be used with uv_fs_symlink() on Windows to specify whether+ * the symlink is to be created using junction points.+ */+#define UV_FS_SYMLINK_JUNCTION     0x0002++UV_EXTERN int uv_fs_symlink(uv_loop_t* loop,+                            uv_fs_t* req,+                            const char* path,+                            const char* new_path,+                            int flags,+                            uv_fs_cb cb);+UV_EXTERN int uv_fs_readlink(uv_loop_t* loop,+                             uv_fs_t* req,+                             const char* path,+                             uv_fs_cb cb);+UV_EXTERN int uv_fs_realpath(uv_loop_t* loop,+                             uv_fs_t* req,+                             const char* path,+                             uv_fs_cb cb);+UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop,+                           uv_fs_t* req,+                           uv_file file,+                           int mode,+                           uv_fs_cb cb);+UV_EXTERN int uv_fs_chown(uv_loop_t* loop,+                          uv_fs_t* req,+                          const char* path,+                          uv_uid_t uid,+                          uv_gid_t gid,+                          uv_fs_cb cb);+UV_EXTERN int uv_fs_fchown(uv_loop_t* loop,+                           uv_fs_t* req,+                           uv_file file,+                           uv_uid_t uid,+                           uv_gid_t gid,+                           uv_fs_cb cb);+UV_EXTERN int uv_fs_lchown(uv_loop_t* loop,+                           uv_fs_t* req,+                           const char* path,+                           uv_uid_t uid,+                           uv_gid_t gid,+                           uv_fs_cb cb);+++enum uv_fs_event {+  UV_RENAME = 1,+  UV_CHANGE = 2+};+++struct uv_fs_event_s {+  UV_HANDLE_FIELDS+  /* private */+  char* path;+  UV_FS_EVENT_PRIVATE_FIELDS+};+++/*+ * uv_fs_stat() based polling file watcher.+ */+struct uv_fs_poll_s {+  UV_HANDLE_FIELDS+  /* Private, don't touch. */+  void* poll_ctx;+};++UV_EXTERN int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle);+UV_EXTERN int uv_fs_poll_start(uv_fs_poll_t* handle,+                               uv_fs_poll_cb poll_cb,+                               const char* path,+                               unsigned int interval);+UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle);+UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle,+                                 char* buffer,+                                 size_t* size);+++struct uv_signal_s {+  UV_HANDLE_FIELDS+  uv_signal_cb signal_cb;+  int signum;+  UV_SIGNAL_PRIVATE_FIELDS+};++UV_EXTERN int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle);+UV_EXTERN int uv_signal_start(uv_signal_t* handle,+                              uv_signal_cb signal_cb,+                              int signum);+UV_EXTERN int uv_signal_start_oneshot(uv_signal_t* handle,+                                      uv_signal_cb signal_cb,+                                      int signum);+UV_EXTERN int uv_signal_stop(uv_signal_t* handle);++UV_EXTERN void uv_loadavg(double avg[3]);+++/*+ * Flags to be passed to uv_fs_event_start().+ */+enum uv_fs_event_flags {+  /*+   * By default, if the fs event watcher is given a directory name, we will+   * watch for all events in that directory. This flags overrides this behavior+   * and makes fs_event report only changes to the directory entry itself. This+   * flag does not affect individual files watched.+   * This flag is currently not implemented yet on any backend.+   */+  UV_FS_EVENT_WATCH_ENTRY = 1,++  /*+   * By default uv_fs_event will try to use a kernel interface such as inotify+   * or kqueue to detect events. This may not work on remote filesystems such+   * as NFS mounts. This flag makes fs_event fall back to calling stat() on a+   * regular interval.+   * This flag is currently not implemented yet on any backend.+   */+  UV_FS_EVENT_STAT = 2,++  /*+   * By default, event watcher, when watching directory, is not registering+   * (is ignoring) changes in it's subdirectories.+   * This flag will override this behaviour on platforms that support it.+   */+  UV_FS_EVENT_RECURSIVE = 4+};+++UV_EXTERN int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle);+UV_EXTERN int uv_fs_event_start(uv_fs_event_t* handle,+                                uv_fs_event_cb cb,+                                const char* path,+                                unsigned int flags);+UV_EXTERN int uv_fs_event_stop(uv_fs_event_t* handle);+UV_EXTERN int uv_fs_event_getpath(uv_fs_event_t* handle,+                                  char* buffer,+                                  size_t* size);++UV_EXTERN int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr);+UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr);++UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size);+UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size);++UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);+UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);++#if defined(IF_NAMESIZE)+# define UV_IF_NAMESIZE (IF_NAMESIZE + 1)+#elif defined(IFNAMSIZ)+# define UV_IF_NAMESIZE (IFNAMSIZ + 1)+#else+# define UV_IF_NAMESIZE (16 + 1)+#endif++UV_EXTERN int uv_if_indextoname(unsigned int ifindex,+                                char* buffer,+                                size_t* size);+UV_EXTERN int uv_if_indextoiid(unsigned int ifindex,+                               char* buffer,+                               size_t* size);++UV_EXTERN int uv_exepath(char* buffer, size_t* size);++UV_EXTERN int uv_cwd(char* buffer, size_t* size);++UV_EXTERN int uv_chdir(const char* dir);++UV_EXTERN uint64_t uv_get_free_memory(void);+UV_EXTERN uint64_t uv_get_total_memory(void);++UV_EXTERN uint64_t uv_hrtime(void);++UV_EXTERN void uv_disable_stdio_inheritance(void);++UV_EXTERN int uv_dlopen(const char* filename, uv_lib_t* lib);+UV_EXTERN void uv_dlclose(uv_lib_t* lib);+UV_EXTERN int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr);+UV_EXTERN const char* uv_dlerror(const uv_lib_t* lib);++UV_EXTERN int uv_mutex_init(uv_mutex_t* handle);+UV_EXTERN int uv_mutex_init_recursive(uv_mutex_t* handle);+UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle);+UV_EXTERN void uv_mutex_lock(uv_mutex_t* handle);+UV_EXTERN int uv_mutex_trylock(uv_mutex_t* handle);+UV_EXTERN void uv_mutex_unlock(uv_mutex_t* handle);++UV_EXTERN int uv_rwlock_init(uv_rwlock_t* rwlock);+UV_EXTERN void uv_rwlock_destroy(uv_rwlock_t* rwlock);+UV_EXTERN void uv_rwlock_rdlock(uv_rwlock_t* rwlock);+UV_EXTERN int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock);+UV_EXTERN void uv_rwlock_rdunlock(uv_rwlock_t* rwlock);+UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t* rwlock);+UV_EXTERN int uv_rwlock_trywrlock(uv_rwlock_t* rwlock);+UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t* rwlock);++UV_EXTERN int uv_sem_init(uv_sem_t* sem, unsigned int value);+UV_EXTERN void uv_sem_destroy(uv_sem_t* sem);+UV_EXTERN void uv_sem_post(uv_sem_t* sem);+UV_EXTERN void uv_sem_wait(uv_sem_t* sem);+UV_EXTERN int uv_sem_trywait(uv_sem_t* sem);++UV_EXTERN int uv_cond_init(uv_cond_t* cond);+UV_EXTERN void uv_cond_destroy(uv_cond_t* cond);+UV_EXTERN void uv_cond_signal(uv_cond_t* cond);+UV_EXTERN void uv_cond_broadcast(uv_cond_t* cond);++UV_EXTERN int uv_barrier_init(uv_barrier_t* barrier, unsigned int count);+UV_EXTERN void uv_barrier_destroy(uv_barrier_t* barrier);+UV_EXTERN int uv_barrier_wait(uv_barrier_t* barrier);++UV_EXTERN void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex);+UV_EXTERN int uv_cond_timedwait(uv_cond_t* cond,+                                uv_mutex_t* mutex,+                                uint64_t timeout);++UV_EXTERN void uv_once(uv_once_t* guard, void (*callback)(void));++UV_EXTERN int uv_key_create(uv_key_t* key);+UV_EXTERN void uv_key_delete(uv_key_t* key);+UV_EXTERN void* uv_key_get(uv_key_t* key);+UV_EXTERN void uv_key_set(uv_key_t* key, void* value);++typedef void (*uv_thread_cb)(void* arg);++UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg);++typedef enum {+  UV_THREAD_NO_FLAGS = 0x00,+  UV_THREAD_HAS_STACK_SIZE = 0x01+} uv_thread_create_flags;++struct uv_thread_options_s {+  unsigned int flags;+  size_t stack_size;+  /* More fields may be added at any time. */+};++typedef struct uv_thread_options_s uv_thread_options_t;++UV_EXTERN int uv_thread_create_ex(uv_thread_t* tid,+                                  const uv_thread_options_t* params,+                                  uv_thread_cb entry,+                                  void* arg);+UV_EXTERN uv_thread_t uv_thread_self(void);+UV_EXTERN int uv_thread_join(uv_thread_t *tid);+UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2);++/* The presence of these unions force similar struct layout. */+#define XX(_, name) uv_ ## name ## _t name;+union uv_any_handle {+  UV_HANDLE_TYPE_MAP(XX)+};++union uv_any_req {+  UV_REQ_TYPE_MAP(XX)+};+#undef XX+++struct uv_loop_s {+  /* User data - use this for whatever. */+  void* data;+  /* Loop reference counting. */+  unsigned int active_handles;+  void* handle_queue[2];+  union {+    void* unused[2];+    unsigned int count;+  } active_reqs;+  /* Internal flag to signal loop stop. */+  unsigned int stop_flag;+  UV_LOOP_PRIVATE_FIELDS+};++UV_EXTERN void* uv_loop_get_data(const uv_loop_t*);+UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data);++/* Don't export the private CPP symbols. */+#undef UV_HANDLE_TYPE_PRIVATE+#undef UV_REQ_TYPE_PRIVATE+#undef UV_REQ_PRIVATE_FIELDS+#undef UV_STREAM_PRIVATE_FIELDS+#undef UV_TCP_PRIVATE_FIELDS+#undef UV_PREPARE_PRIVATE_FIELDS+#undef UV_CHECK_PRIVATE_FIELDS+#undef UV_IDLE_PRIVATE_FIELDS+#undef UV_ASYNC_PRIVATE_FIELDS+#undef UV_TIMER_PRIVATE_FIELDS+#undef UV_GETADDRINFO_PRIVATE_FIELDS+#undef UV_GETNAMEINFO_PRIVATE_FIELDS+#undef UV_FS_REQ_PRIVATE_FIELDS+#undef UV_WORK_PRIVATE_FIELDS+#undef UV_FS_EVENT_PRIVATE_FIELDS+#undef UV_SIGNAL_PRIVATE_FIELDS+#undef UV_LOOP_PRIVATE_FIELDS+#undef UV_LOOP_PRIVATE_PLATFORM_FIELDS+#undef UV__ERR++#ifdef __cplusplus+}+#endif+#endif /* UV_H */
+ third_party/libuv/include/uv/errno.h view
@@ -0,0 +1,443 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#ifndef UV_ERRNO_H_+#define UV_ERRNO_H_++#include <errno.h>+#if EDOM > 0+# define UV__ERR(x) (-(x))+#else+# define UV__ERR(x) (x)+#endif++#define UV__EOF     (-4095)+#define UV__UNKNOWN (-4094)++#define UV__EAI_ADDRFAMILY  (-3000)+#define UV__EAI_AGAIN       (-3001)+#define UV__EAI_BADFLAGS    (-3002)+#define UV__EAI_CANCELED    (-3003)+#define UV__EAI_FAIL        (-3004)+#define UV__EAI_FAMILY      (-3005)+#define UV__EAI_MEMORY      (-3006)+#define UV__EAI_NODATA      (-3007)+#define UV__EAI_NONAME      (-3008)+#define UV__EAI_OVERFLOW    (-3009)+#define UV__EAI_SERVICE     (-3010)+#define UV__EAI_SOCKTYPE    (-3011)+#define UV__EAI_BADHINTS    (-3013)+#define UV__EAI_PROTOCOL    (-3014)++/* Only map to the system errno on non-Windows platforms. It's apparently+ * a fairly common practice for Windows programmers to redefine errno codes.+ */+#if defined(E2BIG) && !defined(_WIN32)+# define UV__E2BIG UV__ERR(E2BIG)+#else+# define UV__E2BIG (-4093)+#endif++#if defined(EACCES) && !defined(_WIN32)+# define UV__EACCES UV__ERR(EACCES)+#else+# define UV__EACCES (-4092)+#endif++#if defined(EADDRINUSE) && !defined(_WIN32)+# define UV__EADDRINUSE UV__ERR(EADDRINUSE)+#else+# define UV__EADDRINUSE (-4091)+#endif++#if defined(EADDRNOTAVAIL) && !defined(_WIN32)+# define UV__EADDRNOTAVAIL UV__ERR(EADDRNOTAVAIL)+#else+# define UV__EADDRNOTAVAIL (-4090)+#endif++#if defined(EAFNOSUPPORT) && !defined(_WIN32)+# define UV__EAFNOSUPPORT UV__ERR(EAFNOSUPPORT)+#else+# define UV__EAFNOSUPPORT (-4089)+#endif++#if defined(EAGAIN) && !defined(_WIN32)+# define UV__EAGAIN UV__ERR(EAGAIN)+#else+# define UV__EAGAIN (-4088)+#endif++#if defined(EALREADY) && !defined(_WIN32)+# define UV__EALREADY UV__ERR(EALREADY)+#else+# define UV__EALREADY (-4084)+#endif++#if defined(EBADF) && !defined(_WIN32)+# define UV__EBADF UV__ERR(EBADF)+#else+# define UV__EBADF (-4083)+#endif++#if defined(EBUSY) && !defined(_WIN32)+# define UV__EBUSY UV__ERR(EBUSY)+#else+# define UV__EBUSY (-4082)+#endif++#if defined(ECANCELED) && !defined(_WIN32)+# define UV__ECANCELED UV__ERR(ECANCELED)+#else+# define UV__ECANCELED (-4081)+#endif++#if defined(ECHARSET) && !defined(_WIN32)+# define UV__ECHARSET UV__ERR(ECHARSET)+#else+# define UV__ECHARSET (-4080)+#endif++#if defined(ECONNABORTED) && !defined(_WIN32)+# define UV__ECONNABORTED UV__ERR(ECONNABORTED)+#else+# define UV__ECONNABORTED (-4079)+#endif++#if defined(ECONNREFUSED) && !defined(_WIN32)+# define UV__ECONNREFUSED UV__ERR(ECONNREFUSED)+#else+# define UV__ECONNREFUSED (-4078)+#endif++#if defined(ECONNRESET) && !defined(_WIN32)+# define UV__ECONNRESET UV__ERR(ECONNRESET)+#else+# define UV__ECONNRESET (-4077)+#endif++#if defined(EDESTADDRREQ) && !defined(_WIN32)+# define UV__EDESTADDRREQ UV__ERR(EDESTADDRREQ)+#else+# define UV__EDESTADDRREQ (-4076)+#endif++#if defined(EEXIST) && !defined(_WIN32)+# define UV__EEXIST UV__ERR(EEXIST)+#else+# define UV__EEXIST (-4075)+#endif++#if defined(EFAULT) && !defined(_WIN32)+# define UV__EFAULT UV__ERR(EFAULT)+#else+# define UV__EFAULT (-4074)+#endif++#if defined(EHOSTUNREACH) && !defined(_WIN32)+# define UV__EHOSTUNREACH UV__ERR(EHOSTUNREACH)+#else+# define UV__EHOSTUNREACH (-4073)+#endif++#if defined(EINTR) && !defined(_WIN32)+# define UV__EINTR UV__ERR(EINTR)+#else+# define UV__EINTR (-4072)+#endif++#if defined(EINVAL) && !defined(_WIN32)+# define UV__EINVAL UV__ERR(EINVAL)+#else+# define UV__EINVAL (-4071)+#endif++#if defined(EIO) && !defined(_WIN32)+# define UV__EIO UV__ERR(EIO)+#else+# define UV__EIO (-4070)+#endif++#if defined(EISCONN) && !defined(_WIN32)+# define UV__EISCONN UV__ERR(EISCONN)+#else+# define UV__EISCONN (-4069)+#endif++#if defined(EISDIR) && !defined(_WIN32)+# define UV__EISDIR UV__ERR(EISDIR)+#else+# define UV__EISDIR (-4068)+#endif++#if defined(ELOOP) && !defined(_WIN32)+# define UV__ELOOP UV__ERR(ELOOP)+#else+# define UV__ELOOP (-4067)+#endif++#if defined(EMFILE) && !defined(_WIN32)+# define UV__EMFILE UV__ERR(EMFILE)+#else+# define UV__EMFILE (-4066)+#endif++#if defined(EMSGSIZE) && !defined(_WIN32)+# define UV__EMSGSIZE UV__ERR(EMSGSIZE)+#else+# define UV__EMSGSIZE (-4065)+#endif++#if defined(ENAMETOOLONG) && !defined(_WIN32)+# define UV__ENAMETOOLONG UV__ERR(ENAMETOOLONG)+#else+# define UV__ENAMETOOLONG (-4064)+#endif++#if defined(ENETDOWN) && !defined(_WIN32)+# define UV__ENETDOWN UV__ERR(ENETDOWN)+#else+# define UV__ENETDOWN (-4063)+#endif++#if defined(ENETUNREACH) && !defined(_WIN32)+# define UV__ENETUNREACH UV__ERR(ENETUNREACH)+#else+# define UV__ENETUNREACH (-4062)+#endif++#if defined(ENFILE) && !defined(_WIN32)+# define UV__ENFILE UV__ERR(ENFILE)+#else+# define UV__ENFILE (-4061)+#endif++#if defined(ENOBUFS) && !defined(_WIN32)+# define UV__ENOBUFS UV__ERR(ENOBUFS)+#else+# define UV__ENOBUFS (-4060)+#endif++#if defined(ENODEV) && !defined(_WIN32)+# define UV__ENODEV UV__ERR(ENODEV)+#else+# define UV__ENODEV (-4059)+#endif++#if defined(ENOENT) && !defined(_WIN32)+# define UV__ENOENT UV__ERR(ENOENT)+#else+# define UV__ENOENT (-4058)+#endif++#if defined(ENOMEM) && !defined(_WIN32)+# define UV__ENOMEM UV__ERR(ENOMEM)+#else+# define UV__ENOMEM (-4057)+#endif++#if defined(ENONET) && !defined(_WIN32)+# define UV__ENONET UV__ERR(ENONET)+#else+# define UV__ENONET (-4056)+#endif++#if defined(ENOSPC) && !defined(_WIN32)+# define UV__ENOSPC UV__ERR(ENOSPC)+#else+# define UV__ENOSPC (-4055)+#endif++#if defined(ENOSYS) && !defined(_WIN32)+# define UV__ENOSYS UV__ERR(ENOSYS)+#else+# define UV__ENOSYS (-4054)+#endif++#if defined(ENOTCONN) && !defined(_WIN32)+# define UV__ENOTCONN UV__ERR(ENOTCONN)+#else+# define UV__ENOTCONN (-4053)+#endif++#if defined(ENOTDIR) && !defined(_WIN32)+# define UV__ENOTDIR UV__ERR(ENOTDIR)+#else+# define UV__ENOTDIR (-4052)+#endif++#if defined(ENOTEMPTY) && !defined(_WIN32)+# define UV__ENOTEMPTY UV__ERR(ENOTEMPTY)+#else+# define UV__ENOTEMPTY (-4051)+#endif++#if defined(ENOTSOCK) && !defined(_WIN32)+# define UV__ENOTSOCK UV__ERR(ENOTSOCK)+#else+# define UV__ENOTSOCK (-4050)+#endif++#if defined(ENOTSUP) && !defined(_WIN32)+# define UV__ENOTSUP UV__ERR(ENOTSUP)+#else+# define UV__ENOTSUP (-4049)+#endif++#if defined(EPERM) && !defined(_WIN32)+# define UV__EPERM UV__ERR(EPERM)+#else+# define UV__EPERM (-4048)+#endif++#if defined(EPIPE) && !defined(_WIN32)+# define UV__EPIPE UV__ERR(EPIPE)+#else+# define UV__EPIPE (-4047)+#endif++#if defined(EPROTO) && !defined(_WIN32)+# define UV__EPROTO UV__ERR(EPROTO)+#else+# define UV__EPROTO UV__ERR(4046)+#endif++#if defined(EPROTONOSUPPORT) && !defined(_WIN32)+# define UV__EPROTONOSUPPORT UV__ERR(EPROTONOSUPPORT)+#else+# define UV__EPROTONOSUPPORT (-4045)+#endif++#if defined(EPROTOTYPE) && !defined(_WIN32)+# define UV__EPROTOTYPE UV__ERR(EPROTOTYPE)+#else+# define UV__EPROTOTYPE (-4044)+#endif++#if defined(EROFS) && !defined(_WIN32)+# define UV__EROFS UV__ERR(EROFS)+#else+# define UV__EROFS (-4043)+#endif++#if defined(ESHUTDOWN) && !defined(_WIN32)+# define UV__ESHUTDOWN UV__ERR(ESHUTDOWN)+#else+# define UV__ESHUTDOWN (-4042)+#endif++#if defined(ESPIPE) && !defined(_WIN32)+# define UV__ESPIPE UV__ERR(ESPIPE)+#else+# define UV__ESPIPE (-4041)+#endif++#if defined(ESRCH) && !defined(_WIN32)+# define UV__ESRCH UV__ERR(ESRCH)+#else+# define UV__ESRCH (-4040)+#endif++#if defined(ETIMEDOUT) && !defined(_WIN32)+# define UV__ETIMEDOUT UV__ERR(ETIMEDOUT)+#else+# define UV__ETIMEDOUT (-4039)+#endif++#if defined(ETXTBSY) && !defined(_WIN32)+# define UV__ETXTBSY UV__ERR(ETXTBSY)+#else+# define UV__ETXTBSY (-4038)+#endif++#if defined(EXDEV) && !defined(_WIN32)+# define UV__EXDEV UV__ERR(EXDEV)+#else+# define UV__EXDEV (-4037)+#endif++#if defined(EFBIG) && !defined(_WIN32)+# define UV__EFBIG UV__ERR(EFBIG)+#else+# define UV__EFBIG (-4036)+#endif++#if defined(ENOPROTOOPT) && !defined(_WIN32)+# define UV__ENOPROTOOPT UV__ERR(ENOPROTOOPT)+#else+# define UV__ENOPROTOOPT (-4035)+#endif++#if defined(ERANGE) && !defined(_WIN32)+# define UV__ERANGE UV__ERR(ERANGE)+#else+# define UV__ERANGE (-4034)+#endif++#if defined(ENXIO) && !defined(_WIN32)+# define UV__ENXIO UV__ERR(ENXIO)+#else+# define UV__ENXIO (-4033)+#endif++#if defined(EMLINK) && !defined(_WIN32)+# define UV__EMLINK UV__ERR(EMLINK)+#else+# define UV__EMLINK (-4032)+#endif++/* EHOSTDOWN is not visible on BSD-like systems when _POSIX_C_SOURCE is+ * defined. Fortunately, its value is always 64 so it's possible albeit+ * icky to hard-code it.+ */+#if defined(EHOSTDOWN) && !defined(_WIN32)+# define UV__EHOSTDOWN UV__ERR(EHOSTDOWN)+#elif defined(__APPLE__) || \+      defined(__DragonFly__) || \+      defined(__FreeBSD__) || \+      defined(__FreeBSD_kernel__) || \+      defined(__NetBSD__) || \+      defined(__OpenBSD__)+# define UV__EHOSTDOWN (-64)+#else+# define UV__EHOSTDOWN (-4031)+#endif++#if defined(EREMOTEIO) && !defined(_WIN32)+# define UV__EREMOTEIO UV__ERR(EREMOTEIO)+#else+# define UV__EREMOTEIO (-4030)+#endif++#if defined(ENOTTY) && !defined(_WIN32)+# define UV__ENOTTY UV__ERR(ENOTTY)+#else+# define UV__ENOTTY (-4029)+#endif++#if defined(EFTYPE) && !defined(_WIN32)+# define UV__EFTYPE UV__ERR(EFTYPE)+#else+# define UV__EFTYPE (-4028)+#endif+++#endif /* UV_ERRNO_H_ */
+ third_party/libuv/include/uv/stdint-msvc2008.h view
@@ -0,0 +1,247 @@+// ISO C9x  compliant stdint.h for Microsoft Visual Studio+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +//  Copyright (c) 2006-2008 Alexander Chemeris+// +// Redistribution and use in source and binary forms, with or without+// modification, are permitted provided that the following conditions are met:+// +//   1. Redistributions of source code must retain the above copyright notice,+//      this list of conditions and the following disclaimer.+// +//   2. Redistributions in binary form must reproduce the above copyright+//      notice, this list of conditions and the following disclaimer in the+//      documentation and/or other materials provided with the distribution.+// +//   3. The name of the author may be used to endorse or promote products+//      derived from this software without specific prior written permission.+// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+// +///////////////////////////////////////////////////////////////////////////////++#ifndef _MSC_VER // [+#error "Use this header only with Microsoft Visual C++ compilers!"+#endif // _MSC_VER ]++#ifndef _MSC_STDINT_H_ // [+#define _MSC_STDINT_H_++#if _MSC_VER > 1000+#pragma once+#endif++#include <limits.h>++// For Visual Studio 6 in C++ mode and for many Visual Studio versions when+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'+// or compiler give many errors like this:+//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed+#ifdef __cplusplus+extern "C" {+#endif+#  include <wchar.h>+#ifdef __cplusplus+}+#endif++// Define _W64 macros to mark types changing their size, like intptr_t.+#ifndef _W64+#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300+#     define _W64 __w64+#  else+#     define _W64+#  endif+#endif+++// 7.18.1 Integer types++// 7.18.1.1 Exact-width integer types++// Visual Studio 6 and Embedded Visual C++ 4 doesn't+// realize that, e.g. char has the same size as __int8+// so we give up on __intX for them.+#if (_MSC_VER < 1300)+   typedef signed char       int8_t;+   typedef signed short      int16_t;+   typedef signed int        int32_t;+   typedef unsigned char     uint8_t;+   typedef unsigned short    uint16_t;+   typedef unsigned int      uint32_t;+#else+   typedef signed __int8     int8_t;+   typedef signed __int16    int16_t;+   typedef signed __int32    int32_t;+   typedef unsigned __int8   uint8_t;+   typedef unsigned __int16  uint16_t;+   typedef unsigned __int32  uint32_t;+#endif+typedef signed __int64       int64_t;+typedef unsigned __int64     uint64_t;+++// 7.18.1.2 Minimum-width integer types+typedef int8_t    int_least8_t;+typedef int16_t   int_least16_t;+typedef int32_t   int_least32_t;+typedef int64_t   int_least64_t;+typedef uint8_t   uint_least8_t;+typedef uint16_t  uint_least16_t;+typedef uint32_t  uint_least32_t;+typedef uint64_t  uint_least64_t;++// 7.18.1.3 Fastest minimum-width integer types+typedef int8_t    int_fast8_t;+typedef int16_t   int_fast16_t;+typedef int32_t   int_fast32_t;+typedef int64_t   int_fast64_t;+typedef uint8_t   uint_fast8_t;+typedef uint16_t  uint_fast16_t;+typedef uint32_t  uint_fast32_t;+typedef uint64_t  uint_fast64_t;++// 7.18.1.4 Integer types capable of holding object pointers+#ifdef _WIN64 // [+   typedef signed __int64    intptr_t;+   typedef unsigned __int64  uintptr_t;+#else // _WIN64 ][+   typedef _W64 signed int   intptr_t;+   typedef _W64 unsigned int uintptr_t;+#endif // _WIN64 ]++// 7.18.1.5 Greatest-width integer types+typedef int64_t   intmax_t;+typedef uint64_t  uintmax_t;+++// 7.18.2 Limits of specified-width integer types++#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259++// 7.18.2.1 Limits of exact-width integer types+#define INT8_MIN     ((int8_t)_I8_MIN)+#define INT8_MAX     _I8_MAX+#define INT16_MIN    ((int16_t)_I16_MIN)+#define INT16_MAX    _I16_MAX+#define INT32_MIN    ((int32_t)_I32_MIN)+#define INT32_MAX    _I32_MAX+#define INT64_MIN    ((int64_t)_I64_MIN)+#define INT64_MAX    _I64_MAX+#define UINT8_MAX    _UI8_MAX+#define UINT16_MAX   _UI16_MAX+#define UINT32_MAX   _UI32_MAX+#define UINT64_MAX   _UI64_MAX++// 7.18.2.2 Limits of minimum-width integer types+#define INT_LEAST8_MIN    INT8_MIN+#define INT_LEAST8_MAX    INT8_MAX+#define INT_LEAST16_MIN   INT16_MIN+#define INT_LEAST16_MAX   INT16_MAX+#define INT_LEAST32_MIN   INT32_MIN+#define INT_LEAST32_MAX   INT32_MAX+#define INT_LEAST64_MIN   INT64_MIN+#define INT_LEAST64_MAX   INT64_MAX+#define UINT_LEAST8_MAX   UINT8_MAX+#define UINT_LEAST16_MAX  UINT16_MAX+#define UINT_LEAST32_MAX  UINT32_MAX+#define UINT_LEAST64_MAX  UINT64_MAX++// 7.18.2.3 Limits of fastest minimum-width integer types+#define INT_FAST8_MIN    INT8_MIN+#define INT_FAST8_MAX    INT8_MAX+#define INT_FAST16_MIN   INT16_MIN+#define INT_FAST16_MAX   INT16_MAX+#define INT_FAST32_MIN   INT32_MIN+#define INT_FAST32_MAX   INT32_MAX+#define INT_FAST64_MIN   INT64_MIN+#define INT_FAST64_MAX   INT64_MAX+#define UINT_FAST8_MAX   UINT8_MAX+#define UINT_FAST16_MAX  UINT16_MAX+#define UINT_FAST32_MAX  UINT32_MAX+#define UINT_FAST64_MAX  UINT64_MAX++// 7.18.2.4 Limits of integer types capable of holding object pointers+#ifdef _WIN64 // [+#  define INTPTR_MIN   INT64_MIN+#  define INTPTR_MAX   INT64_MAX+#  define UINTPTR_MAX  UINT64_MAX+#else // _WIN64 ][+#  define INTPTR_MIN   INT32_MIN+#  define INTPTR_MAX   INT32_MAX+#  define UINTPTR_MAX  UINT32_MAX+#endif // _WIN64 ]++// 7.18.2.5 Limits of greatest-width integer types+#define INTMAX_MIN   INT64_MIN+#define INTMAX_MAX   INT64_MAX+#define UINTMAX_MAX  UINT64_MAX++// 7.18.3 Limits of other integer types++#ifdef _WIN64 // [+#  define PTRDIFF_MIN  _I64_MIN+#  define PTRDIFF_MAX  _I64_MAX+#else  // _WIN64 ][+#  define PTRDIFF_MIN  _I32_MIN+#  define PTRDIFF_MAX  _I32_MAX+#endif  // _WIN64 ]++#define SIG_ATOMIC_MIN  INT_MIN+#define SIG_ATOMIC_MAX  INT_MAX++#ifndef SIZE_MAX // [+#  ifdef _WIN64 // [+#     define SIZE_MAX  _UI64_MAX+#  else // _WIN64 ][+#     define SIZE_MAX  _UI32_MAX+#  endif // _WIN64 ]+#endif // SIZE_MAX ]++// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>+#ifndef WCHAR_MIN // [+#  define WCHAR_MIN  0+#endif  // WCHAR_MIN ]+#ifndef WCHAR_MAX // [+#  define WCHAR_MAX  _UI16_MAX+#endif  // WCHAR_MAX ]++#define WINT_MIN  0+#define WINT_MAX  _UI16_MAX++#endif // __STDC_LIMIT_MACROS ]+++// 7.18.4 Limits of other integer types++#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260++// 7.18.4.1 Macros for minimum-width integer constants++#define INT8_C(val)  val##i8+#define INT16_C(val) val##i16+#define INT32_C(val) val##i32+#define INT64_C(val) val##i64++#define UINT8_C(val)  val##ui8+#define UINT16_C(val) val##ui16+#define UINT32_C(val) val##ui32+#define UINT64_C(val) val##ui64++// 7.18.4.2 Macros for greatest-width integer constants+#define INTMAX_C   INT64_C+#define UINTMAX_C  UINT64_C++#endif // __STDC_CONSTANT_MACROS ]+++#endif // _MSC_STDINT_H_ ]
+ third_party/libuv/include/uv/threadpool.h view
@@ -0,0 +1,37 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++/*+ * This file is private to libuv. It provides common functionality to both+ * Windows and Unix backends.+ */++#ifndef UV_THREADPOOL_H_+#define UV_THREADPOOL_H_++struct uv__work {+  void (*work)(struct uv__work *w);+  void (*done)(struct uv__work *w, int status);+  struct uv_loop_s* loop;+  void* wq[2];+};++#endif /* UV_THREADPOOL_H_ */
+ third_party/libuv/include/uv/tree.h view
@@ -0,0 +1,768 @@+/*-+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef  UV_TREE_H_+#define  UV_TREE_H_++#ifndef UV__UNUSED+# if __GNUC__+#  define UV__UNUSED __attribute__((unused))+# else+#  define UV__UNUSED+# endif+#endif++/*+ * This file defines data structures for different types of trees:+ * splay trees and red-black trees.+ *+ * A splay tree is a self-organizing data structure.  Every operation+ * on the tree causes a splay to happen.  The splay moves the requested+ * node to the root of the tree and partly rebalances it.+ *+ * This has the benefit that request locality causes faster lookups as+ * the requested nodes move to the top of the tree.  On the other hand,+ * every lookup causes memory writes.+ *+ * The Balance Theorem bounds the total access time for m operations+ * and n inserts on an initially empty tree as O((m + n)lg n).  The+ * amortized cost for a sequence of m accesses to a splay tree is O(lg n);+ *+ * A red-black tree is a binary search tree with the node color as an+ * extra attribute.  It fulfills a set of conditions:+ *  - every search path from the root to a leaf consists of the+ *    same number of black nodes,+ *  - each red node (except for the root) has a black parent,+ *  - each leaf node is black.+ *+ * Every operation on a red-black tree is bounded as O(lg n).+ * The maximum height of a red-black tree is 2lg (n+1).+ */++#define SPLAY_HEAD(name, type)                                                \+struct name {                                                                 \+  struct type *sph_root; /* root of the tree */                               \+}++#define SPLAY_INITIALIZER(root)                                               \+  { NULL }++#define SPLAY_INIT(root) do {                                                 \+  (root)->sph_root = NULL;                                                    \+} while (/*CONSTCOND*/ 0)++#define SPLAY_ENTRY(type)                                                     \+struct {                                                                      \+  struct type *spe_left;          /* left element */                          \+  struct type *spe_right;         /* right element */                         \+}++#define SPLAY_LEFT(elm, field)    (elm)->field.spe_left+#define SPLAY_RIGHT(elm, field)   (elm)->field.spe_right+#define SPLAY_ROOT(head)          (head)->sph_root+#define SPLAY_EMPTY(head)         (SPLAY_ROOT(head) == NULL)++/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */+#define SPLAY_ROTATE_RIGHT(head, tmp, field) do {                             \+  SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field);              \+  SPLAY_RIGHT(tmp, field) = (head)->sph_root;                                 \+  (head)->sph_root = tmp;                                                     \+} while (/*CONSTCOND*/ 0)++#define SPLAY_ROTATE_LEFT(head, tmp, field) do {                              \+  SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field);              \+  SPLAY_LEFT(tmp, field) = (head)->sph_root;                                  \+  (head)->sph_root = tmp;                                                     \+} while (/*CONSTCOND*/ 0)++#define SPLAY_LINKLEFT(head, tmp, field) do {                                 \+  SPLAY_LEFT(tmp, field) = (head)->sph_root;                                  \+  tmp = (head)->sph_root;                                                     \+  (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);                     \+} while (/*CONSTCOND*/ 0)++#define SPLAY_LINKRIGHT(head, tmp, field) do {                                \+  SPLAY_RIGHT(tmp, field) = (head)->sph_root;                                 \+  tmp = (head)->sph_root;                                                     \+  (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);                    \+} while (/*CONSTCOND*/ 0)++#define SPLAY_ASSEMBLE(head, node, left, right, field) do {                   \+  SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field);             \+  SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);            \+  SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field);             \+  SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field);             \+} while (/*CONSTCOND*/ 0)++/* Generates prototypes and inline functions */++#define SPLAY_PROTOTYPE(name, type, field, cmp)                               \+void name##_SPLAY(struct name *, struct type *);                              \+void name##_SPLAY_MINMAX(struct name *, int);                                 \+struct type *name##_SPLAY_INSERT(struct name *, struct type *);               \+struct type *name##_SPLAY_REMOVE(struct name *, struct type *);               \+                                                                              \+/* Finds the node with the same key as elm */                                 \+static __inline struct type *                                                 \+name##_SPLAY_FIND(struct name *head, struct type *elm)                        \+{                                                                             \+  if (SPLAY_EMPTY(head))                                                      \+    return(NULL);                                                             \+  name##_SPLAY(head, elm);                                                    \+  if ((cmp)(elm, (head)->sph_root) == 0)                                      \+    return (head->sph_root);                                                  \+  return (NULL);                                                              \+}                                                                             \+                                                                              \+static __inline struct type *                                                 \+name##_SPLAY_NEXT(struct name *head, struct type *elm)                        \+{                                                                             \+  name##_SPLAY(head, elm);                                                    \+  if (SPLAY_RIGHT(elm, field) != NULL) {                                      \+    elm = SPLAY_RIGHT(elm, field);                                            \+    while (SPLAY_LEFT(elm, field) != NULL) {                                  \+      elm = SPLAY_LEFT(elm, field);                                           \+    }                                                                         \+  } else                                                                      \+    elm = NULL;                                                               \+  return (elm);                                                               \+}                                                                             \+                                                                              \+static __inline struct type *                                                 \+name##_SPLAY_MIN_MAX(struct name *head, int val)                              \+{                                                                             \+  name##_SPLAY_MINMAX(head, val);                                             \+  return (SPLAY_ROOT(head));                                                  \+}++/* Main splay operation.+ * Moves node close to the key of elm to top+ */+#define SPLAY_GENERATE(name, type, field, cmp)                                \+struct type *                                                                 \+name##_SPLAY_INSERT(struct name *head, struct type *elm)                      \+{                                                                             \+    if (SPLAY_EMPTY(head)) {                                                  \+      SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL;                \+    } else {                                                                  \+      int __comp;                                                             \+      name##_SPLAY(head, elm);                                                \+      __comp = (cmp)(elm, (head)->sph_root);                                  \+      if(__comp < 0) {                                                        \+        SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);         \+        SPLAY_RIGHT(elm, field) = (head)->sph_root;                           \+        SPLAY_LEFT((head)->sph_root, field) = NULL;                           \+      } else if (__comp > 0) {                                                \+        SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);       \+        SPLAY_LEFT(elm, field) = (head)->sph_root;                            \+        SPLAY_RIGHT((head)->sph_root, field) = NULL;                          \+      } else                                                                  \+        return ((head)->sph_root);                                            \+    }                                                                         \+    (head)->sph_root = (elm);                                                 \+    return (NULL);                                                            \+}                                                                             \+                                                                              \+struct type *                                                                 \+name##_SPLAY_REMOVE(struct name *head, struct type *elm)                      \+{                                                                             \+  struct type *__tmp;                                                         \+  if (SPLAY_EMPTY(head))                                                      \+    return (NULL);                                                            \+  name##_SPLAY(head, elm);                                                    \+  if ((cmp)(elm, (head)->sph_root) == 0) {                                    \+    if (SPLAY_LEFT((head)->sph_root, field) == NULL) {                        \+      (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);                \+    } else {                                                                  \+      __tmp = SPLAY_RIGHT((head)->sph_root, field);                           \+      (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);                 \+      name##_SPLAY(head, elm);                                                \+      SPLAY_RIGHT((head)->sph_root, field) = __tmp;                           \+    }                                                                         \+    return (elm);                                                             \+  }                                                                           \+  return (NULL);                                                              \+}                                                                             \+                                                                              \+void                                                                          \+name##_SPLAY(struct name *head, struct type *elm)                             \+{                                                                             \+  struct type __node, *__left, *__right, *__tmp;                              \+  int __comp;                                                                 \+                                                                              \+  SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;            \+  __left = __right = &__node;                                                 \+                                                                              \+  while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) {                      \+    if (__comp < 0) {                                                         \+      __tmp = SPLAY_LEFT((head)->sph_root, field);                            \+      if (__tmp == NULL)                                                      \+        break;                                                                \+      if ((cmp)(elm, __tmp) < 0){                                             \+        SPLAY_ROTATE_RIGHT(head, __tmp, field);                               \+        if (SPLAY_LEFT((head)->sph_root, field) == NULL)                      \+          break;                                                              \+      }                                                                       \+      SPLAY_LINKLEFT(head, __right, field);                                   \+    } else if (__comp > 0) {                                                  \+      __tmp = SPLAY_RIGHT((head)->sph_root, field);                           \+      if (__tmp == NULL)                                                      \+        break;                                                                \+      if ((cmp)(elm, __tmp) > 0){                                             \+        SPLAY_ROTATE_LEFT(head, __tmp, field);                                \+        if (SPLAY_RIGHT((head)->sph_root, field) == NULL)                     \+          break;                                                              \+      }                                                                       \+      SPLAY_LINKRIGHT(head, __left, field);                                   \+    }                                                                         \+  }                                                                           \+  SPLAY_ASSEMBLE(head, &__node, __left, __right, field);                      \+}                                                                             \+                                                                              \+/* Splay with either the minimum or the maximum element                       \+ * Used to find minimum or maximum element in tree.                           \+ */                                                                           \+void name##_SPLAY_MINMAX(struct name *head, int __comp)                       \+{                                                                             \+  struct type __node, *__left, *__right, *__tmp;                              \+                                                                              \+  SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;            \+  __left = __right = &__node;                                                 \+                                                                              \+  while (1) {                                                                 \+    if (__comp < 0) {                                                         \+      __tmp = SPLAY_LEFT((head)->sph_root, field);                            \+      if (__tmp == NULL)                                                      \+        break;                                                                \+      if (__comp < 0){                                                        \+        SPLAY_ROTATE_RIGHT(head, __tmp, field);                               \+        if (SPLAY_LEFT((head)->sph_root, field) == NULL)                      \+          break;                                                              \+      }                                                                       \+      SPLAY_LINKLEFT(head, __right, field);                                   \+    } else if (__comp > 0) {                                                  \+      __tmp = SPLAY_RIGHT((head)->sph_root, field);                           \+      if (__tmp == NULL)                                                      \+        break;                                                                \+      if (__comp > 0) {                                                       \+        SPLAY_ROTATE_LEFT(head, __tmp, field);                                \+        if (SPLAY_RIGHT((head)->sph_root, field) == NULL)                     \+          break;                                                              \+      }                                                                       \+      SPLAY_LINKRIGHT(head, __left, field);                                   \+    }                                                                         \+  }                                                                           \+  SPLAY_ASSEMBLE(head, &__node, __left, __right, field);                      \+}++#define SPLAY_NEGINF  -1+#define SPLAY_INF     1++#define SPLAY_INSERT(name, x, y)  name##_SPLAY_INSERT(x, y)+#define SPLAY_REMOVE(name, x, y)  name##_SPLAY_REMOVE(x, y)+#define SPLAY_FIND(name, x, y)    name##_SPLAY_FIND(x, y)+#define SPLAY_NEXT(name, x, y)    name##_SPLAY_NEXT(x, y)+#define SPLAY_MIN(name, x)        (SPLAY_EMPTY(x) ? NULL                      \+                                  : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))+#define SPLAY_MAX(name, x)        (SPLAY_EMPTY(x) ? NULL                      \+                                  : name##_SPLAY_MIN_MAX(x, SPLAY_INF))++#define SPLAY_FOREACH(x, name, head)                                          \+  for ((x) = SPLAY_MIN(name, head);                                           \+       (x) != NULL;                                                           \+       (x) = SPLAY_NEXT(name, head, x))++/* Macros that define a red-black tree */+#define RB_HEAD(name, type)                                                   \+struct name {                                                                 \+  struct type *rbh_root; /* root of the tree */                               \+}++#define RB_INITIALIZER(root)                                                  \+  { NULL }++#define RB_INIT(root) do {                                                    \+  (root)->rbh_root = NULL;                                                    \+} while (/*CONSTCOND*/ 0)++#define RB_BLACK  0+#define RB_RED    1+#define RB_ENTRY(type)                                                        \+struct {                                                                      \+  struct type *rbe_left;        /* left element */                            \+  struct type *rbe_right;       /* right element */                           \+  struct type *rbe_parent;      /* parent element */                          \+  int rbe_color;                /* node color */                              \+}++#define RB_LEFT(elm, field)     (elm)->field.rbe_left+#define RB_RIGHT(elm, field)    (elm)->field.rbe_right+#define RB_PARENT(elm, field)   (elm)->field.rbe_parent+#define RB_COLOR(elm, field)    (elm)->field.rbe_color+#define RB_ROOT(head)           (head)->rbh_root+#define RB_EMPTY(head)          (RB_ROOT(head) == NULL)++#define RB_SET(elm, parent, field) do {                                       \+  RB_PARENT(elm, field) = parent;                                             \+  RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL;                          \+  RB_COLOR(elm, field) = RB_RED;                                              \+} while (/*CONSTCOND*/ 0)++#define RB_SET_BLACKRED(black, red, field) do {                               \+  RB_COLOR(black, field) = RB_BLACK;                                          \+  RB_COLOR(red, field) = RB_RED;                                              \+} while (/*CONSTCOND*/ 0)++#ifndef RB_AUGMENT+#define RB_AUGMENT(x)  do {} while (0)+#endif++#define RB_ROTATE_LEFT(head, elm, tmp, field) do {                            \+  (tmp) = RB_RIGHT(elm, field);                                               \+  if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) {                 \+    RB_PARENT(RB_LEFT(tmp, field), field) = (elm);                            \+  }                                                                           \+  RB_AUGMENT(elm);                                                            \+  if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) {              \+    if ((elm) == RB_LEFT(RB_PARENT(elm, field), field))                       \+      RB_LEFT(RB_PARENT(elm, field), field) = (tmp);                          \+    else                                                                      \+      RB_RIGHT(RB_PARENT(elm, field), field) = (tmp);                         \+  } else                                                                      \+    (head)->rbh_root = (tmp);                                                 \+  RB_LEFT(tmp, field) = (elm);                                                \+  RB_PARENT(elm, field) = (tmp);                                              \+  RB_AUGMENT(tmp);                                                            \+  if ((RB_PARENT(tmp, field)))                                                \+    RB_AUGMENT(RB_PARENT(tmp, field));                                        \+} while (/*CONSTCOND*/ 0)++#define RB_ROTATE_RIGHT(head, elm, tmp, field) do {                           \+  (tmp) = RB_LEFT(elm, field);                                                \+  if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) {                 \+    RB_PARENT(RB_RIGHT(tmp, field), field) = (elm);                           \+  }                                                                           \+  RB_AUGMENT(elm);                                                            \+  if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) {              \+    if ((elm) == RB_LEFT(RB_PARENT(elm, field), field))                       \+      RB_LEFT(RB_PARENT(elm, field), field) = (tmp);                          \+    else                                                                      \+      RB_RIGHT(RB_PARENT(elm, field), field) = (tmp);                         \+  } else                                                                      \+    (head)->rbh_root = (tmp);                                                 \+  RB_RIGHT(tmp, field) = (elm);                                               \+  RB_PARENT(elm, field) = (tmp);                                              \+  RB_AUGMENT(tmp);                                                            \+  if ((RB_PARENT(tmp, field)))                                                \+    RB_AUGMENT(RB_PARENT(tmp, field));                                        \+} while (/*CONSTCOND*/ 0)++/* Generates prototypes and inline functions */+#define  RB_PROTOTYPE(name, type, field, cmp)                                 \+  RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)+#define  RB_PROTOTYPE_STATIC(name, type, field, cmp)                          \+  RB_PROTOTYPE_INTERNAL(name, type, field, cmp, UV__UNUSED static)+#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr)                   \+attr void name##_RB_INSERT_COLOR(struct name *, struct type *);               \+attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\+attr struct type *name##_RB_REMOVE(struct name *, struct type *);             \+attr struct type *name##_RB_INSERT(struct name *, struct type *);             \+attr struct type *name##_RB_FIND(struct name *, struct type *);               \+attr struct type *name##_RB_NFIND(struct name *, struct type *);              \+attr struct type *name##_RB_NEXT(struct type *);                              \+attr struct type *name##_RB_PREV(struct type *);                              \+attr struct type *name##_RB_MINMAX(struct name *, int);                       \+                                                                              \++/* Main rb operation.+ * Moves node close to the key of elm to top+ */+#define  RB_GENERATE(name, type, field, cmp)                                  \+  RB_GENERATE_INTERNAL(name, type, field, cmp,)+#define  RB_GENERATE_STATIC(name, type, field, cmp)                           \+  RB_GENERATE_INTERNAL(name, type, field, cmp, UV__UNUSED static)+#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr)                    \+attr void                                                                     \+name##_RB_INSERT_COLOR(struct name *head, struct type *elm)                   \+{                                                                             \+  struct type *parent, *gparent, *tmp;                                        \+  while ((parent = RB_PARENT(elm, field)) != NULL &&                          \+      RB_COLOR(parent, field) == RB_RED) {                                    \+    gparent = RB_PARENT(parent, field);                                       \+    if (parent == RB_LEFT(gparent, field)) {                                  \+      tmp = RB_RIGHT(gparent, field);                                         \+      if (tmp && RB_COLOR(tmp, field) == RB_RED) {                            \+        RB_COLOR(tmp, field) = RB_BLACK;                                      \+        RB_SET_BLACKRED(parent, gparent, field);                              \+        elm = gparent;                                                        \+        continue;                                                             \+      }                                                                       \+      if (RB_RIGHT(parent, field) == elm) {                                   \+        RB_ROTATE_LEFT(head, parent, tmp, field);                             \+        tmp = parent;                                                         \+        parent = elm;                                                         \+        elm = tmp;                                                            \+      }                                                                       \+      RB_SET_BLACKRED(parent, gparent, field);                                \+      RB_ROTATE_RIGHT(head, gparent, tmp, field);                             \+    } else {                                                                  \+      tmp = RB_LEFT(gparent, field);                                          \+      if (tmp && RB_COLOR(tmp, field) == RB_RED) {                            \+        RB_COLOR(tmp, field) = RB_BLACK;                                      \+        RB_SET_BLACKRED(parent, gparent, field);                              \+        elm = gparent;                                                        \+        continue;                                                             \+      }                                                                       \+      if (RB_LEFT(parent, field) == elm) {                                    \+        RB_ROTATE_RIGHT(head, parent, tmp, field);                            \+        tmp = parent;                                                         \+        parent = elm;                                                         \+        elm = tmp;                                                            \+      }                                                                       \+      RB_SET_BLACKRED(parent, gparent, field);                                \+      RB_ROTATE_LEFT(head, gparent, tmp, field);                              \+    }                                                                         \+  }                                                                           \+  RB_COLOR(head->rbh_root, field) = RB_BLACK;                                 \+}                                                                             \+                                                                              \+attr void                                                                     \+name##_RB_REMOVE_COLOR(struct name *head, struct type *parent,                \+    struct type *elm)                                                         \+{                                                                             \+  struct type *tmp;                                                           \+  while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) &&                 \+      elm != RB_ROOT(head)) {                                                 \+    if (RB_LEFT(parent, field) == elm) {                                      \+      tmp = RB_RIGHT(parent, field);                                          \+      if (RB_COLOR(tmp, field) == RB_RED) {                                   \+        RB_SET_BLACKRED(tmp, parent, field);                                  \+        RB_ROTATE_LEFT(head, parent, tmp, field);                             \+        tmp = RB_RIGHT(parent, field);                                        \+      }                                                                       \+      if ((RB_LEFT(tmp, field) == NULL ||                                     \+          RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&                \+          (RB_RIGHT(tmp, field) == NULL ||                                    \+          RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {               \+        RB_COLOR(tmp, field) = RB_RED;                                        \+        elm = parent;                                                         \+        parent = RB_PARENT(elm, field);                                       \+      } else {                                                                \+        if (RB_RIGHT(tmp, field) == NULL ||                                   \+            RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {              \+          struct type *oleft;                                                 \+          if ((oleft = RB_LEFT(tmp, field))                                   \+              != NULL)                                                        \+            RB_COLOR(oleft, field) = RB_BLACK;                                \+          RB_COLOR(tmp, field) = RB_RED;                                      \+          RB_ROTATE_RIGHT(head, tmp, oleft, field);                           \+          tmp = RB_RIGHT(parent, field);                                      \+        }                                                                     \+        RB_COLOR(tmp, field) = RB_COLOR(parent, field);                       \+        RB_COLOR(parent, field) = RB_BLACK;                                   \+        if (RB_RIGHT(tmp, field))                                             \+          RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;                   \+        RB_ROTATE_LEFT(head, parent, tmp, field);                             \+        elm = RB_ROOT(head);                                                  \+        break;                                                                \+      }                                                                       \+    } else {                                                                  \+      tmp = RB_LEFT(parent, field);                                           \+      if (RB_COLOR(tmp, field) == RB_RED) {                                   \+        RB_SET_BLACKRED(tmp, parent, field);                                  \+        RB_ROTATE_RIGHT(head, parent, tmp, field);                            \+        tmp = RB_LEFT(parent, field);                                         \+      }                                                                       \+      if ((RB_LEFT(tmp, field) == NULL ||                                     \+          RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&                \+          (RB_RIGHT(tmp, field) == NULL ||                                    \+          RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {               \+        RB_COLOR(tmp, field) = RB_RED;                                        \+        elm = parent;                                                         \+        parent = RB_PARENT(elm, field);                                       \+      } else {                                                                \+        if (RB_LEFT(tmp, field) == NULL ||                                    \+            RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {               \+          struct type *oright;                                                \+          if ((oright = RB_RIGHT(tmp, field))                                 \+              != NULL)                                                        \+            RB_COLOR(oright, field) = RB_BLACK;                               \+          RB_COLOR(tmp, field) = RB_RED;                                      \+          RB_ROTATE_LEFT(head, tmp, oright, field);                           \+          tmp = RB_LEFT(parent, field);                                       \+        }                                                                     \+        RB_COLOR(tmp, field) = RB_COLOR(parent, field);                       \+        RB_COLOR(parent, field) = RB_BLACK;                                   \+        if (RB_LEFT(tmp, field))                                              \+          RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;                    \+        RB_ROTATE_RIGHT(head, parent, tmp, field);                            \+        elm = RB_ROOT(head);                                                  \+        break;                                                                \+      }                                                                       \+    }                                                                         \+  }                                                                           \+  if (elm)                                                                    \+    RB_COLOR(elm, field) = RB_BLACK;                                          \+}                                                                             \+                                                                              \+attr struct type *                                                            \+name##_RB_REMOVE(struct name *head, struct type *elm)                         \+{                                                                             \+  struct type *child, *parent, *old = elm;                                    \+  int color;                                                                  \+  if (RB_LEFT(elm, field) == NULL)                                            \+    child = RB_RIGHT(elm, field);                                             \+  else if (RB_RIGHT(elm, field) == NULL)                                      \+    child = RB_LEFT(elm, field);                                              \+  else {                                                                      \+    struct type *left;                                                        \+    elm = RB_RIGHT(elm, field);                                               \+    while ((left = RB_LEFT(elm, field)) != NULL)                              \+      elm = left;                                                             \+    child = RB_RIGHT(elm, field);                                             \+    parent = RB_PARENT(elm, field);                                           \+    color = RB_COLOR(elm, field);                                             \+    if (child)                                                                \+      RB_PARENT(child, field) = parent;                                       \+    if (parent) {                                                             \+      if (RB_LEFT(parent, field) == elm)                                      \+        RB_LEFT(parent, field) = child;                                       \+      else                                                                    \+        RB_RIGHT(parent, field) = child;                                      \+      RB_AUGMENT(parent);                                                     \+    } else                                                                    \+      RB_ROOT(head) = child;                                                  \+    if (RB_PARENT(elm, field) == old)                                         \+      parent = elm;                                                           \+    (elm)->field = (old)->field;                                              \+    if (RB_PARENT(old, field)) {                                              \+      if (RB_LEFT(RB_PARENT(old, field), field) == old)                       \+        RB_LEFT(RB_PARENT(old, field), field) = elm;                          \+      else                                                                    \+        RB_RIGHT(RB_PARENT(old, field), field) = elm;                         \+      RB_AUGMENT(RB_PARENT(old, field));                                      \+    } else                                                                    \+      RB_ROOT(head) = elm;                                                    \+    RB_PARENT(RB_LEFT(old, field), field) = elm;                              \+    if (RB_RIGHT(old, field))                                                 \+      RB_PARENT(RB_RIGHT(old, field), field) = elm;                           \+    if (parent) {                                                             \+      left = parent;                                                          \+      do {                                                                    \+        RB_AUGMENT(left);                                                     \+      } while ((left = RB_PARENT(left, field)) != NULL);                      \+    }                                                                         \+    goto color;                                                               \+  }                                                                           \+  parent = RB_PARENT(elm, field);                                             \+  color = RB_COLOR(elm, field);                                               \+  if (child)                                                                  \+    RB_PARENT(child, field) = parent;                                         \+  if (parent) {                                                               \+    if (RB_LEFT(parent, field) == elm)                                        \+      RB_LEFT(parent, field) = child;                                         \+    else                                                                      \+      RB_RIGHT(parent, field) = child;                                        \+    RB_AUGMENT(parent);                                                       \+  } else                                                                      \+    RB_ROOT(head) = child;                                                    \+color:                                                                        \+  if (color == RB_BLACK)                                                      \+    name##_RB_REMOVE_COLOR(head, parent, child);                              \+  return (old);                                                               \+}                                                                             \+                                                                              \+/* Inserts a node into the RB tree */                                         \+attr struct type *                                                            \+name##_RB_INSERT(struct name *head, struct type *elm)                         \+{                                                                             \+  struct type *tmp;                                                           \+  struct type *parent = NULL;                                                 \+  int comp = 0;                                                               \+  tmp = RB_ROOT(head);                                                        \+  while (tmp) {                                                               \+    parent = tmp;                                                             \+    comp = (cmp)(elm, parent);                                                \+    if (comp < 0)                                                             \+      tmp = RB_LEFT(tmp, field);                                              \+    else if (comp > 0)                                                        \+      tmp = RB_RIGHT(tmp, field);                                             \+    else                                                                      \+      return (tmp);                                                           \+  }                                                                           \+  RB_SET(elm, parent, field);                                                 \+  if (parent != NULL) {                                                       \+    if (comp < 0)                                                             \+      RB_LEFT(parent, field) = elm;                                           \+    else                                                                      \+      RB_RIGHT(parent, field) = elm;                                          \+    RB_AUGMENT(parent);                                                       \+  } else                                                                      \+    RB_ROOT(head) = elm;                                                      \+  name##_RB_INSERT_COLOR(head, elm);                                          \+  return (NULL);                                                              \+}                                                                             \+                                                                              \+/* Finds the node with the same key as elm */                                 \+attr struct type *                                                            \+name##_RB_FIND(struct name *head, struct type *elm)                           \+{                                                                             \+  struct type *tmp = RB_ROOT(head);                                           \+  int comp;                                                                   \+  while (tmp) {                                                               \+    comp = cmp(elm, tmp);                                                     \+    if (comp < 0)                                                             \+      tmp = RB_LEFT(tmp, field);                                              \+    else if (comp > 0)                                                        \+      tmp = RB_RIGHT(tmp, field);                                             \+    else                                                                      \+      return (tmp);                                                           \+  }                                                                           \+  return (NULL);                                                              \+}                                                                             \+                                                                              \+/* Finds the first node greater than or equal to the search key */            \+attr struct type *                                                            \+name##_RB_NFIND(struct name *head, struct type *elm)                          \+{                                                                             \+  struct type *tmp = RB_ROOT(head);                                           \+  struct type *res = NULL;                                                    \+  int comp;                                                                   \+  while (tmp) {                                                               \+    comp = cmp(elm, tmp);                                                     \+    if (comp < 0) {                                                           \+      res = tmp;                                                              \+      tmp = RB_LEFT(tmp, field);                                              \+    }                                                                         \+    else if (comp > 0)                                                        \+      tmp = RB_RIGHT(tmp, field);                                             \+    else                                                                      \+      return (tmp);                                                           \+  }                                                                           \+  return (res);                                                               \+}                                                                             \+                                                                              \+/* ARGSUSED */                                                                \+attr struct type *                                                            \+name##_RB_NEXT(struct type *elm)                                              \+{                                                                             \+  if (RB_RIGHT(elm, field)) {                                                 \+    elm = RB_RIGHT(elm, field);                                               \+    while (RB_LEFT(elm, field))                                               \+      elm = RB_LEFT(elm, field);                                              \+  } else {                                                                    \+    if (RB_PARENT(elm, field) &&                                              \+        (elm == RB_LEFT(RB_PARENT(elm, field), field)))                       \+      elm = RB_PARENT(elm, field);                                            \+    else {                                                                    \+      while (RB_PARENT(elm, field) &&                                         \+          (elm == RB_RIGHT(RB_PARENT(elm, field), field)))                    \+        elm = RB_PARENT(elm, field);                                          \+      elm = RB_PARENT(elm, field);                                            \+    }                                                                         \+  }                                                                           \+  return (elm);                                                               \+}                                                                             \+                                                                              \+/* ARGSUSED */                                                                \+attr struct type *                                                            \+name##_RB_PREV(struct type *elm)                                              \+{                                                                             \+  if (RB_LEFT(elm, field)) {                                                  \+    elm = RB_LEFT(elm, field);                                                \+    while (RB_RIGHT(elm, field))                                              \+      elm = RB_RIGHT(elm, field);                                             \+  } else {                                                                    \+    if (RB_PARENT(elm, field) &&                                              \+        (elm == RB_RIGHT(RB_PARENT(elm, field), field)))                      \+      elm = RB_PARENT(elm, field);                                            \+    else {                                                                    \+      while (RB_PARENT(elm, field) &&                                         \+          (elm == RB_LEFT(RB_PARENT(elm, field), field)))                     \+        elm = RB_PARENT(elm, field);                                          \+      elm = RB_PARENT(elm, field);                                            \+    }                                                                         \+  }                                                                           \+  return (elm);                                                               \+}                                                                             \+                                                                              \+attr struct type *                                                            \+name##_RB_MINMAX(struct name *head, int val)                                  \+{                                                                             \+  struct type *tmp = RB_ROOT(head);                                           \+  struct type *parent = NULL;                                                 \+  while (tmp) {                                                               \+    parent = tmp;                                                             \+    if (val < 0)                                                              \+      tmp = RB_LEFT(tmp, field);                                              \+    else                                                                      \+      tmp = RB_RIGHT(tmp, field);                                             \+  }                                                                           \+  return (parent);                                                            \+}++#define RB_NEGINF   -1+#define RB_INF      1++#define RB_INSERT(name, x, y)   name##_RB_INSERT(x, y)+#define RB_REMOVE(name, x, y)   name##_RB_REMOVE(x, y)+#define RB_FIND(name, x, y)     name##_RB_FIND(x, y)+#define RB_NFIND(name, x, y)    name##_RB_NFIND(x, y)+#define RB_NEXT(name, x, y)     name##_RB_NEXT(y)+#define RB_PREV(name, x, y)     name##_RB_PREV(y)+#define RB_MIN(name, x)         name##_RB_MINMAX(x, RB_NEGINF)+#define RB_MAX(name, x)         name##_RB_MINMAX(x, RB_INF)++#define RB_FOREACH(x, name, head)                                             \+  for ((x) = RB_MIN(name, head);                                              \+       (x) != NULL;                                                           \+       (x) = name##_RB_NEXT(x))++#define RB_FOREACH_FROM(x, name, y)                                           \+  for ((x) = (y);                                                             \+      ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL);                \+       (x) = (y))++#define RB_FOREACH_SAFE(x, name, head, y)                                     \+  for ((x) = RB_MIN(name, head);                                              \+      ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL);                \+       (x) = (y))++#define RB_FOREACH_REVERSE(x, name, head)                                     \+  for ((x) = RB_MAX(name, head);                                              \+       (x) != NULL;                                                           \+       (x) = name##_RB_PREV(x))++#define RB_FOREACH_REVERSE_FROM(x, name, y)                                   \+  for ((x) = (y);                                                             \+      ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL);                \+       (x) = (y))++#define RB_FOREACH_REVERSE_SAFE(x, name, head, y)                             \+  for ((x) = RB_MAX(name, head);                                              \+      ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL);                \+       (x) = (y))++#endif  /* UV_TREE_H_ */
+ third_party/libuv/include/uv/version.h view
@@ -0,0 +1,43 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#ifndef UV_VERSION_H+#define UV_VERSION_H++ /*+ * Versions with the same major number are ABI stable. API is allowed to+ * evolve between minor releases, but only in a backwards compatible way.+ * Make sure you update the -soname directives in configure.ac+ * and uv.gyp whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but+ * not UV_VERSION_PATCH.)+ */++#define UV_VERSION_MAJOR 1+#define UV_VERSION_MINOR 26+#define UV_VERSION_PATCH 0+#define UV_VERSION_IS_RELEASE 1+#define UV_VERSION_SUFFIX ""++#define UV_VERSION_HEX  ((UV_VERSION_MAJOR << 16) | \+                         (UV_VERSION_MINOR <<  8) | \+                         (UV_VERSION_PATCH))++#endif /* UV_VERSION_H */
+ third_party/libuv/include/uv/win.h view
@@ -0,0 +1,685 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#ifndef _WIN32_WINNT+# define _WIN32_WINNT   0x0600+#endif++#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)+typedef intptr_t ssize_t;+# define SSIZE_MAX INTPTR_MAX+# define _SSIZE_T_+# define _SSIZE_T_DEFINED+#endif++#include <winsock2.h>++#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)+typedef struct pollfd {+  SOCKET fd;+  short  events;+  short  revents;+} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;+#endif++#ifndef LOCALE_INVARIANT+# define LOCALE_INVARIANT 0x007f+#endif++#include <mswsock.h>+#include <ws2tcpip.h>+#include <windows.h>++#include <process.h>+#include <signal.h>+#include <fcntl.h>+#include <sys/stat.h>++#if defined(_MSC_VER) && _MSC_VER < 1600+# include "uv/stdint-msvc2008.h"+#else+# include <stdint.h>+#endif++#include "uv/tree.h"+#include "uv/threadpool.h"++#define MAX_PIPENAME_LEN 256++#ifndef S_IFLNK+# define S_IFLNK 0xA000+#endif++/* Additional signals supported by uv_signal and or uv_kill. The CRT defines+ * the following signals already:+ *+ *   #define SIGINT           2+ *   #define SIGILL           4+ *   #define SIGABRT_COMPAT   6+ *   #define SIGFPE           8+ *   #define SIGSEGV         11+ *   #define SIGTERM         15+ *   #define SIGBREAK        21+ *   #define SIGABRT         22+ *+ * The additional signals have values that are common on other Unix+ * variants (Linux and Darwin)+ */+#define SIGHUP                1+#define SIGKILL               9+#define SIGWINCH             28++/* Redefine NSIG to take SIGWINCH into consideration */+#if defined(NSIG) && NSIG <= SIGWINCH+# undef NSIG+#endif+#ifndef NSIG+# define NSIG SIGWINCH + 1+#endif++/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many unix-like+ * platforms. However MinGW doesn't define it, so we do. */+#ifndef SIGABRT_COMPAT+# define SIGABRT_COMPAT       6+#endif++/*+ * Guids and typedefs for winsock extension functions+ * Mingw32 doesn't have these :-(+ */+#ifndef WSAID_ACCEPTEX+# define WSAID_ACCEPTEX                                                       \+         {0xb5367df1, 0xcbac, 0x11cf,                                         \+         {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}++# define WSAID_CONNECTEX                                                      \+         {0x25a207b9, 0xddf3, 0x4660,                                         \+         {0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}}++# define WSAID_GETACCEPTEXSOCKADDRS                                           \+         {0xb5367df2, 0xcbac, 0x11cf,                                         \+         {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}++# define WSAID_DISCONNECTEX                                                   \+         {0x7fda2e11, 0x8630, 0x436f,                                         \+         {0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}}++# define WSAID_TRANSMITFILE                                                   \+         {0xb5367df0, 0xcbac, 0x11cf,                                         \+         {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}++  typedef BOOL (PASCAL *LPFN_ACCEPTEX)+                      (SOCKET sListenSocket,+                       SOCKET sAcceptSocket,+                       PVOID lpOutputBuffer,+                       DWORD dwReceiveDataLength,+                       DWORD dwLocalAddressLength,+                       DWORD dwRemoteAddressLength,+                       LPDWORD lpdwBytesReceived,+                       LPOVERLAPPED lpOverlapped);++  typedef BOOL (PASCAL *LPFN_CONNECTEX)+                      (SOCKET s,+                       const struct sockaddr* name,+                       int namelen,+                       PVOID lpSendBuffer,+                       DWORD dwSendDataLength,+                       LPDWORD lpdwBytesSent,+                       LPOVERLAPPED lpOverlapped);++  typedef void (PASCAL *LPFN_GETACCEPTEXSOCKADDRS)+                      (PVOID lpOutputBuffer,+                       DWORD dwReceiveDataLength,+                       DWORD dwLocalAddressLength,+                       DWORD dwRemoteAddressLength,+                       LPSOCKADDR* LocalSockaddr,+                       LPINT LocalSockaddrLength,+                       LPSOCKADDR* RemoteSockaddr,+                       LPINT RemoteSockaddrLength);++  typedef BOOL (PASCAL *LPFN_DISCONNECTEX)+                      (SOCKET hSocket,+                       LPOVERLAPPED lpOverlapped,+                       DWORD dwFlags,+                       DWORD reserved);++  typedef BOOL (PASCAL *LPFN_TRANSMITFILE)+                      (SOCKET hSocket,+                       HANDLE hFile,+                       DWORD nNumberOfBytesToWrite,+                       DWORD nNumberOfBytesPerSend,+                       LPOVERLAPPED lpOverlapped,+                       LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,+                       DWORD dwFlags);++  typedef PVOID RTL_SRWLOCK;+  typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;+#endif++typedef int (WSAAPI* LPFN_WSARECV)+            (SOCKET socket,+             LPWSABUF buffers,+             DWORD buffer_count,+             LPDWORD bytes,+             LPDWORD flags,+             LPWSAOVERLAPPED overlapped,+             LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);++typedef int (WSAAPI* LPFN_WSARECVFROM)+            (SOCKET socket,+             LPWSABUF buffers,+             DWORD buffer_count,+             LPDWORD bytes,+             LPDWORD flags,+             struct sockaddr* addr,+             LPINT addr_len,+             LPWSAOVERLAPPED overlapped,+             LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);++#ifndef _NTDEF_+  typedef LONG NTSTATUS;+  typedef NTSTATUS *PNTSTATUS;+#endif++#ifndef RTL_CONDITION_VARIABLE_INIT+  typedef PVOID CONDITION_VARIABLE, *PCONDITION_VARIABLE;+#endif++typedef struct _AFD_POLL_HANDLE_INFO {+  HANDLE Handle;+  ULONG Events;+  NTSTATUS Status;+} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO;++typedef struct _AFD_POLL_INFO {+  LARGE_INTEGER Timeout;+  ULONG NumberOfHandles;+  ULONG Exclusive;+  AFD_POLL_HANDLE_INFO Handles[1];+} AFD_POLL_INFO, *PAFD_POLL_INFO;++#define UV_MSAFD_PROVIDER_COUNT 3+++/**+ * It should be possible to cast uv_buf_t[] to WSABUF[]+ * see http://msdn.microsoft.com/en-us/library/ms741542(v=vs.85).aspx+ */+typedef struct uv_buf_t {+  ULONG len;+  char* base;+} uv_buf_t;++typedef int uv_file;+typedef SOCKET uv_os_sock_t;+typedef HANDLE uv_os_fd_t;+typedef int uv_pid_t;++typedef HANDLE uv_thread_t;++typedef HANDLE uv_sem_t;++typedef CRITICAL_SECTION uv_mutex_t;++/* This condition variable implementation is based on the SetEvent solution+ * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html+ * We could not use the SignalObjectAndWait solution (section 3.4) because+ * it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and+ * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs.+ */++typedef union {+  CONDITION_VARIABLE cond_var;+  struct {+    unsigned int waiters_count;+    CRITICAL_SECTION waiters_count_lock;+    HANDLE signal_event;+    HANDLE broadcast_event;+  } unused_; /* TODO: retained for ABI compatibility; remove me in v2.x. */+} uv_cond_t;++typedef union {+  struct {+    unsigned int num_readers_;+    CRITICAL_SECTION num_readers_lock_;+    HANDLE write_semaphore_;+  } state_;+  /* TODO: remove me in v2.x. */+  struct {+    SRWLOCK unused_;+  } unused1_;+  /* TODO: remove me in v2.x. */+  struct {+    uv_mutex_t unused1_;+    uv_mutex_t unused2_;+  } unused2_;+} uv_rwlock_t;++typedef struct {+  unsigned int n;+  unsigned int count;+  uv_mutex_t mutex;+  uv_sem_t turnstile1;+  uv_sem_t turnstile2;+} uv_barrier_t;++typedef struct {+  DWORD tls_index;+} uv_key_t;++#define UV_ONCE_INIT { 0, NULL }++typedef struct uv_once_s {+  unsigned char ran;+  HANDLE event;+} uv_once_t;++/* Platform-specific definitions for uv_spawn support. */+typedef unsigned char uv_uid_t;+typedef unsigned char uv_gid_t;++typedef struct uv__dirent_s {+  int d_type;+  char d_name[1];+} uv__dirent_t;++#define HAVE_DIRENT_TYPES+#define UV__DT_DIR     UV_DIRENT_DIR+#define UV__DT_FILE    UV_DIRENT_FILE+#define UV__DT_LINK    UV_DIRENT_LINK+#define UV__DT_FIFO    UV_DIRENT_FIFO+#define UV__DT_SOCKET  UV_DIRENT_SOCKET+#define UV__DT_CHAR    UV_DIRENT_CHAR+#define UV__DT_BLOCK   UV_DIRENT_BLOCK++/* Platform-specific definitions for uv_dlopen support. */+#define UV_DYNAMIC FAR WINAPI+typedef struct {+  HMODULE handle;+  char* errmsg;+} uv_lib_t;++#define UV_LOOP_PRIVATE_FIELDS                                                \+    /* The loop's I/O completion port */                                      \+  HANDLE iocp;                                                                \+  /* The current time according to the event loop. in msecs. */               \+  uint64_t time;                                                              \+  /* Tail of a single-linked circular queue of pending reqs. If the queue */  \+  /* is empty, tail_ is NULL. If there is only one item, */                   \+  /* tail_->next_req == tail_ */                                              \+  uv_req_t* pending_reqs_tail;                                                \+  /* Head of a single-linked list of closed handles */                        \+  uv_handle_t* endgame_handles;                                               \+  /* TODO(bnoordhuis) Stop heap-allocating |timer_heap| in libuv v2.x. */     \+  void* timer_heap;                                                           \+    /* Lists of active loop (prepare / check / idle) watchers */              \+  uv_prepare_t* prepare_handles;                                              \+  uv_check_t* check_handles;                                                  \+  uv_idle_t* idle_handles;                                                    \+  /* This pointer will refer to the prepare/check/idle handle whose */        \+  /* callback is scheduled to be called next. This is needed to allow */      \+  /* safe removal from one of the lists above while that list being */        \+  /* iterated over. */                                                        \+  uv_prepare_t* next_prepare_handle;                                          \+  uv_check_t* next_check_handle;                                              \+  uv_idle_t* next_idle_handle;                                                \+  /* This handle holds the peer sockets for the fast variant of uv_poll_t */  \+  SOCKET poll_peer_sockets[UV_MSAFD_PROVIDER_COUNT];                          \+  /* Counter to keep track of active tcp streams */                           \+  unsigned int active_tcp_streams;                                            \+  /* Counter to keep track of active udp streams */                           \+  unsigned int active_udp_streams;                                            \+  /* Counter to started timer */                                              \+  uint64_t timer_counter;                                                     \+  /* Threadpool */                                                            \+  void* wq[2];                                                                \+  uv_mutex_t wq_mutex;                                                        \+  uv_async_t wq_async;++#define UV_REQ_TYPE_PRIVATE                                                   \+  /* TODO: remove the req suffix */                                           \+  UV_ACCEPT,                                                                  \+  UV_FS_EVENT_REQ,                                                            \+  UV_POLL_REQ,                                                                \+  UV_PROCESS_EXIT,                                                            \+  UV_READ,                                                                    \+  UV_UDP_RECV,                                                                \+  UV_WAKEUP,                                                                  \+  UV_SIGNAL_REQ,++#define UV_REQ_PRIVATE_FIELDS                                                 \+  union {                                                                     \+    /* Used by I/O operations */                                              \+    struct {                                                                  \+      OVERLAPPED overlapped;                                                  \+      size_t queued_bytes;                                                    \+    } io;                                                                     \+  } u;                                                                        \+  struct uv_req_s* next_req;++#define UV_WRITE_PRIVATE_FIELDS \+  int coalesced;                \+  uv_buf_t write_buffer;        \+  HANDLE event_handle;          \+  HANDLE wait_handle;++#define UV_CONNECT_PRIVATE_FIELDS                                             \+  /* empty */++#define UV_SHUTDOWN_PRIVATE_FIELDS                                            \+  /* empty */++#define UV_UDP_SEND_PRIVATE_FIELDS                                            \+  /* empty */++#define UV_PRIVATE_REQ_TYPES                                                  \+  typedef struct uv_pipe_accept_s {                                           \+    UV_REQ_FIELDS                                                             \+    HANDLE pipeHandle;                                                        \+    struct uv_pipe_accept_s* next_pending;                                    \+  } uv_pipe_accept_t;                                                         \+                                                                              \+  typedef struct uv_tcp_accept_s {                                            \+    UV_REQ_FIELDS                                                             \+    SOCKET accept_socket;                                                     \+    char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32];             \+    HANDLE event_handle;                                                      \+    HANDLE wait_handle;                                                       \+    struct uv_tcp_accept_s* next_pending;                                     \+  } uv_tcp_accept_t;                                                          \+                                                                              \+  typedef struct uv_read_s {                                                  \+    UV_REQ_FIELDS                                                             \+    HANDLE event_handle;                                                      \+    HANDLE wait_handle;                                                       \+  } uv_read_t;++#define uv_stream_connection_fields                                           \+  unsigned int write_reqs_pending;                                            \+  uv_shutdown_t* shutdown_req;++#define uv_stream_server_fields                                               \+  uv_connection_cb connection_cb;++#define UV_STREAM_PRIVATE_FIELDS                                              \+  unsigned int reqs_pending;                                                  \+  int activecnt;                                                              \+  uv_read_t read_req;                                                         \+  union {                                                                     \+    struct { uv_stream_connection_fields } conn;                              \+    struct { uv_stream_server_fields     } serv;                              \+  } stream;++#define uv_tcp_server_fields                                                  \+  uv_tcp_accept_t* accept_reqs;                                               \+  unsigned int processed_accepts;                                             \+  uv_tcp_accept_t* pending_accepts;                                           \+  LPFN_ACCEPTEX func_acceptex;++#define uv_tcp_connection_fields                                              \+  uv_buf_t read_buffer;                                                       \+  LPFN_CONNECTEX func_connectex;++#define UV_TCP_PRIVATE_FIELDS                                                 \+  SOCKET socket;                                                              \+  int delayed_error;                                                          \+  union {                                                                     \+    struct { uv_tcp_server_fields } serv;                                     \+    struct { uv_tcp_connection_fields } conn;                                 \+  } tcp;++#define UV_UDP_PRIVATE_FIELDS                                                 \+  SOCKET socket;                                                              \+  unsigned int reqs_pending;                                                  \+  int activecnt;                                                              \+  uv_req_t recv_req;                                                          \+  uv_buf_t recv_buffer;                                                       \+  struct sockaddr_storage recv_from;                                          \+  int recv_from_len;                                                          \+  uv_udp_recv_cb recv_cb;                                                     \+  uv_alloc_cb alloc_cb;                                                       \+  LPFN_WSARECV func_wsarecv;                                                  \+  LPFN_WSARECVFROM func_wsarecvfrom;++#define uv_pipe_server_fields                                                 \+  int pending_instances;                                                      \+  uv_pipe_accept_t* accept_reqs;                                              \+  uv_pipe_accept_t* pending_accepts;++#define uv_pipe_connection_fields                                             \+  uv_timer_t* eof_timer;                                                      \+  uv_write_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \+  DWORD ipc_remote_pid;                                                       \+  union {                                                                     \+    uint32_t payload_remaining;                                               \+    uint64_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \+  } ipc_data_frame;                                                           \+  void* ipc_xfer_queue[2];                                                    \+  int ipc_xfer_queue_length;                                                  \+  uv_write_t* non_overlapped_writes_tail;                                     \+  CRITICAL_SECTION readfile_thread_lock;                                      \+  volatile HANDLE readfile_thread_handle;++#define UV_PIPE_PRIVATE_FIELDS                                                \+  HANDLE handle;                                                              \+  WCHAR* name;                                                                \+  union {                                                                     \+    struct { uv_pipe_server_fields } serv;                                    \+    struct { uv_pipe_connection_fields } conn;                                \+  } pipe;++/* TODO: put the parser states in an union - TTY handles are always half-duplex+ * so read-state can safely overlap write-state. */+#define UV_TTY_PRIVATE_FIELDS                                                 \+  HANDLE handle;                                                              \+  union {                                                                     \+    struct {                                                                  \+      /* Used for readable TTY handles */                                     \+      /* TODO: remove me in v2.x. */                                          \+      HANDLE unused_;                                                         \+      uv_buf_t read_line_buffer;                                              \+      HANDLE read_raw_wait;                                                   \+      /* Fields used for translating win keystrokes into vt100 characters */  \+      char last_key[8];                                                       \+      unsigned char last_key_offset;                                          \+      unsigned char last_key_len;                                             \+      WCHAR last_utf16_high_surrogate;                                        \+      INPUT_RECORD last_input_record;                                         \+    } rd;                                                                     \+    struct {                                                                  \+      /* Used for writable TTY handles */                                     \+      /* utf8-to-utf16 conversion state */                                    \+      unsigned int utf8_codepoint;                                            \+      unsigned char utf8_bytes_left;                                          \+      /* eol conversion state */                                              \+      unsigned char previous_eol;                                             \+      /* ansi parser state */                                                 \+      unsigned char ansi_parser_state;                                        \+      unsigned char ansi_csi_argc;                                            \+      unsigned short ansi_csi_argv[4];                                        \+      COORD saved_position;                                                   \+      WORD saved_attributes;                                                  \+    } wr;                                                                     \+  } tty;++#define UV_POLL_PRIVATE_FIELDS                                                \+  SOCKET socket;                                                              \+  /* Used in fast mode */                                                     \+  SOCKET peer_socket;                                                         \+  AFD_POLL_INFO afd_poll_info_1;                                              \+  AFD_POLL_INFO afd_poll_info_2;                                              \+  /* Used in fast and slow mode. */                                           \+  uv_req_t poll_req_1;                                                        \+  uv_req_t poll_req_2;                                                        \+  unsigned char submitted_events_1;                                           \+  unsigned char submitted_events_2;                                           \+  unsigned char mask_events_1;                                                \+  unsigned char mask_events_2;                                                \+  unsigned char events;++#define UV_TIMER_PRIVATE_FIELDS                                               \+  void* heap_node[3];                                                         \+  int unused;                                                                 \+  uint64_t timeout;                                                           \+  uint64_t repeat;                                                            \+  uint64_t start_id;                                                          \+  uv_timer_cb timer_cb;++#define UV_ASYNC_PRIVATE_FIELDS                                               \+  struct uv_req_s async_req;                                                  \+  uv_async_cb async_cb;                                                       \+  /* char to avoid alignment issues */                                        \+  char volatile async_sent;++#define UV_PREPARE_PRIVATE_FIELDS                                             \+  uv_prepare_t* prepare_prev;                                                 \+  uv_prepare_t* prepare_next;                                                 \+  uv_prepare_cb prepare_cb;++#define UV_CHECK_PRIVATE_FIELDS                                               \+  uv_check_t* check_prev;                                                     \+  uv_check_t* check_next;                                                     \+  uv_check_cb check_cb;++#define UV_IDLE_PRIVATE_FIELDS                                                \+  uv_idle_t* idle_prev;                                                       \+  uv_idle_t* idle_next;                                                       \+  uv_idle_cb idle_cb;++#define UV_HANDLE_PRIVATE_FIELDS                                              \+  uv_handle_t* endgame_next;                                                  \+  unsigned int flags;++#define UV_GETADDRINFO_PRIVATE_FIELDS                                         \+  struct uv__work work_req;                                                   \+  uv_getaddrinfo_cb getaddrinfo_cb;                                           \+  void* alloc;                                                                \+  WCHAR* node;                                                                \+  WCHAR* service;                                                             \+  /* The addrinfoW field is used to store a pointer to the hints, and    */   \+  /* later on to store the result of GetAddrInfoW. The final result will */   \+  /* be converted to struct addrinfo* and stored in the addrinfo field.  */   \+  struct addrinfoW* addrinfow;                                                \+  struct addrinfo* addrinfo;                                                  \+  int retcode;++#define UV_GETNAMEINFO_PRIVATE_FIELDS                                         \+  struct uv__work work_req;                                                   \+  uv_getnameinfo_cb getnameinfo_cb;                                           \+  struct sockaddr_storage storage;                                            \+  int flags;                                                                  \+  char host[NI_MAXHOST];                                                      \+  char service[NI_MAXSERV];                                                   \+  int retcode;++#define UV_PROCESS_PRIVATE_FIELDS                                             \+  struct uv_process_exit_s {                                                  \+    UV_REQ_FIELDS                                                             \+  } exit_req;                                                                 \+  BYTE* child_stdio_buffer;                                                   \+  int exit_signal;                                                            \+  HANDLE wait_handle;                                                         \+  HANDLE process_handle;                                                      \+  volatile char exit_cb_pending;++#define UV_FS_PRIVATE_FIELDS                                                  \+  struct uv__work work_req;                                                   \+  int flags;                                                                  \+  DWORD sys_errno_;                                                           \+  union {                                                                     \+    /* TODO: remove me in 0.9. */                                             \+    WCHAR* pathw;                                                             \+    int fd;                                                                   \+  } file;                                                                     \+  union {                                                                     \+    struct {                                                                  \+      int mode;                                                               \+      WCHAR* new_pathw;                                                       \+      int file_flags;                                                         \+      int fd_out;                                                             \+      unsigned int nbufs;                                                     \+      uv_buf_t* bufs;                                                         \+      int64_t offset;                                                         \+      uv_buf_t bufsml[4];                                                     \+    } info;                                                                   \+    struct {                                                                  \+      double atime;                                                           \+      double mtime;                                                           \+    } time;                                                                   \+  } fs;++#define UV_WORK_PRIVATE_FIELDS                                                \+  struct uv__work work_req;++#define UV_FS_EVENT_PRIVATE_FIELDS                                            \+  struct uv_fs_event_req_s {                                                  \+    UV_REQ_FIELDS                                                             \+  } req;                                                                      \+  HANDLE dir_handle;                                                          \+  int req_pending;                                                            \+  uv_fs_event_cb cb;                                                          \+  WCHAR* filew;                                                               \+  WCHAR* short_filew;                                                         \+  WCHAR* dirw;                                                                \+  char* buffer;++#define UV_SIGNAL_PRIVATE_FIELDS                                              \+  RB_ENTRY(uv_signal_s) tree_entry;                                           \+  struct uv_req_s signal_req;                                                 \+  unsigned long pending_signum;++#ifndef F_OK+#define F_OK 0+#endif+#ifndef R_OK+#define R_OK 4+#endif+#ifndef W_OK+#define W_OK 2+#endif+#ifndef X_OK+#define X_OK 1+#endif++/* fs open() flags supported on this platform: */+#define UV_FS_O_APPEND       _O_APPEND+#define UV_FS_O_CREAT        _O_CREAT+#define UV_FS_O_EXCL         _O_EXCL+#define UV_FS_O_RANDOM       _O_RANDOM+#define UV_FS_O_RDONLY       _O_RDONLY+#define UV_FS_O_RDWR         _O_RDWR+#define UV_FS_O_SEQUENTIAL   _O_SEQUENTIAL+#define UV_FS_O_SHORT_LIVED  _O_SHORT_LIVED+#define UV_FS_O_TEMPORARY    _O_TEMPORARY+#define UV_FS_O_TRUNC        _O_TRUNC+#define UV_FS_O_WRONLY       _O_WRONLY++/* fs open() flags supported on other platforms (or mapped on this platform): */+#define UV_FS_O_DIRECT       0x02000000 /* FILE_FLAG_NO_BUFFERING */+#define UV_FS_O_DIRECTORY    0+#define UV_FS_O_DSYNC        0x04000000 /* FILE_FLAG_WRITE_THROUGH */+#define UV_FS_O_EXLOCK       0x10000000 /* EXCLUSIVE SHARING MODE */+#define UV_FS_O_NOATIME      0+#define UV_FS_O_NOCTTY       0+#define UV_FS_O_NOFOLLOW     0+#define UV_FS_O_NONBLOCK     0+#define UV_FS_O_SYMLINK      0+#define UV_FS_O_SYNC         0x08000000 /* FILE_FLAG_WRITE_THROUGH */
+ third_party/libuv/src/fs-poll.c view
@@ -0,0 +1,256 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include "uv.h"+#include "uv-common.h"++#include <assert.h>+#include <stdlib.h>+#include <string.h>++struct poll_ctx {+  uv_fs_poll_t* parent_handle; /* NULL if parent has been stopped or closed */+  int busy_polling;+  unsigned int interval;+  uint64_t start_time;+  uv_loop_t* loop;+  uv_fs_poll_cb poll_cb;+  uv_timer_t timer_handle;+  uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */+  uv_stat_t statbuf;+  char path[1]; /* variable length */+};++static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b);+static void poll_cb(uv_fs_t* req);+static void timer_cb(uv_timer_t* timer);+static void timer_close_cb(uv_handle_t* handle);++static uv_stat_t zero_statbuf;+++int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) {+  uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL);+  return 0;+}+++int uv_fs_poll_start(uv_fs_poll_t* handle,+                     uv_fs_poll_cb cb,+                     const char* path,+                     unsigned int interval) {+  struct poll_ctx* ctx;+  uv_loop_t* loop;+  size_t len;+  int err;++  if (uv__is_active(handle))+    return 0;++  loop = handle->loop;+  len = strlen(path);+  ctx = uv__calloc(1, sizeof(*ctx) + len);++  if (ctx == NULL)+    return UV_ENOMEM;++  ctx->loop = loop;+  ctx->poll_cb = cb;+  ctx->interval = interval ? interval : 1;+  ctx->start_time = uv_now(loop);+  ctx->parent_handle = handle;+  memcpy(ctx->path, path, len + 1);++  err = uv_timer_init(loop, &ctx->timer_handle);+  if (err < 0)+    goto error;++  ctx->timer_handle.flags |= UV_HANDLE_INTERNAL;+  uv__handle_unref(&ctx->timer_handle);++  err = uv_fs_stat(loop, &ctx->fs_req, ctx->path, poll_cb);+  if (err < 0)+    goto error;++  handle->poll_ctx = ctx;+  uv__handle_start(handle);++  return 0;++error:+  uv__free(ctx);+  return err;+}+++int uv_fs_poll_stop(uv_fs_poll_t* handle) {+  struct poll_ctx* ctx;++  if (!uv__is_active(handle))+    return 0;++  ctx = handle->poll_ctx;+  assert(ctx != NULL);+  assert(ctx->parent_handle != NULL);+  ctx->parent_handle = NULL;+  handle->poll_ctx = NULL;++  /* Close the timer if it's active. If it's inactive, there's a stat request+   * in progress and poll_cb will take care of the cleanup.+   */+  if (uv__is_active(&ctx->timer_handle))+    uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);++  uv__handle_stop(handle);++  return 0;+}+++int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {+  struct poll_ctx* ctx;+  size_t required_len;++  if (!uv__is_active(handle)) {+    *size = 0;+    return UV_EINVAL;+  }++  ctx = handle->poll_ctx;+  assert(ctx != NULL);++  required_len = strlen(ctx->path);+  if (required_len >= *size) {+    *size = required_len + 1;+    return UV_ENOBUFS;+  }++  memcpy(buffer, ctx->path, required_len);+  *size = required_len;+  buffer[required_len] = '\0';++  return 0;+}+++void uv__fs_poll_close(uv_fs_poll_t* handle) {+  uv_fs_poll_stop(handle);+}+++static void timer_cb(uv_timer_t* timer) {+  struct poll_ctx* ctx;++  ctx = container_of(timer, struct poll_ctx, timer_handle);+  assert(ctx->parent_handle != NULL);+  assert(ctx->parent_handle->poll_ctx == ctx);+  ctx->start_time = uv_now(ctx->loop);++  if (uv_fs_stat(ctx->loop, &ctx->fs_req, ctx->path, poll_cb))+    abort();+}+++static void poll_cb(uv_fs_t* req) {+  uv_stat_t* statbuf;+  struct poll_ctx* ctx;+  uint64_t interval;++  ctx = container_of(req, struct poll_ctx, fs_req);++  if (ctx->parent_handle == NULL) { /* handle has been stopped or closed */+    uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);+    uv_fs_req_cleanup(req);+    return;+  }++  if (req->result != 0) {+    if (ctx->busy_polling != req->result) {+      ctx->poll_cb(ctx->parent_handle,+                   req->result,+                   &ctx->statbuf,+                   &zero_statbuf);+      ctx->busy_polling = req->result;+    }+    goto out;+  }++  statbuf = &req->statbuf;++  if (ctx->busy_polling != 0)+    if (ctx->busy_polling < 0 || !statbuf_eq(&ctx->statbuf, statbuf))+      ctx->poll_cb(ctx->parent_handle, 0, &ctx->statbuf, statbuf);++  ctx->statbuf = *statbuf;+  ctx->busy_polling = 1;++out:+  uv_fs_req_cleanup(req);++  if (ctx->parent_handle == NULL) { /* handle has been stopped by callback */+    uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);+    return;+  }++  /* Reschedule timer, subtract the delay from doing the stat(). */+  interval = ctx->interval;+  interval -= (uv_now(ctx->loop) - ctx->start_time) % interval;++  if (uv_timer_start(&ctx->timer_handle, timer_cb, interval, 0))+    abort();+}+++static void timer_close_cb(uv_handle_t* handle) {+  uv__free(container_of(handle, struct poll_ctx, timer_handle));+}+++static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b) {+  return a->st_ctim.tv_nsec == b->st_ctim.tv_nsec+      && a->st_mtim.tv_nsec == b->st_mtim.tv_nsec+      && a->st_birthtim.tv_nsec == b->st_birthtim.tv_nsec+      && a->st_ctim.tv_sec == b->st_ctim.tv_sec+      && a->st_mtim.tv_sec == b->st_mtim.tv_sec+      && a->st_birthtim.tv_sec == b->st_birthtim.tv_sec+      && a->st_size == b->st_size+      && a->st_mode == b->st_mode+      && a->st_uid == b->st_uid+      && a->st_gid == b->st_gid+      && a->st_ino == b->st_ino+      && a->st_dev == b->st_dev+      && a->st_flags == b->st_flags+      && a->st_gen == b->st_gen;+}+++#if defined(_WIN32)++#include "win/internal.h"+#include "win/handle-inl.h"++void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) {+  assert(handle->flags & UV_HANDLE_CLOSING);+  assert(!(handle->flags & UV_HANDLE_CLOSED));+  uv__handle_close(handle);+}++#endif /* _WIN32 */
+ third_party/libuv/src/heap-inl.h view
@@ -0,0 +1,245 @@+/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>+ *+ * Permission to use, copy, modify, and/or distribute this software for any+ * purpose with or without fee is hereby granted, provided that the above+ * copyright notice and this permission notice appear in all copies.+ *+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.+ */++#ifndef UV_SRC_HEAP_H_+#define UV_SRC_HEAP_H_++#include <stddef.h>  /* NULL */++#if defined(__GNUC__)+# define HEAP_EXPORT(declaration) __attribute__((unused)) static declaration+#else+# define HEAP_EXPORT(declaration) static declaration+#endif++struct heap_node {+  struct heap_node* left;+  struct heap_node* right;+  struct heap_node* parent;+};++/* A binary min heap.  The usual properties hold: the root is the lowest+ * element in the set, the height of the tree is at most log2(nodes) and+ * it's always a complete binary tree.+ *+ * The heap function try hard to detect corrupted tree nodes at the cost+ * of a minor reduction in performance.  Compile with -DNDEBUG to disable.+ */+struct heap {+  struct heap_node* min;+  unsigned int nelts;+};++/* Return non-zero if a < b. */+typedef int (*heap_compare_fn)(const struct heap_node* a,+                               const struct heap_node* b);++/* Public functions. */+HEAP_EXPORT(void heap_init(struct heap* heap));+HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap));+HEAP_EXPORT(void heap_insert(struct heap* heap,+                             struct heap_node* newnode,+                             heap_compare_fn less_than));+HEAP_EXPORT(void heap_remove(struct heap* heap,+                             struct heap_node* node,+                             heap_compare_fn less_than));+HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than));++/* Implementation follows. */++HEAP_EXPORT(void heap_init(struct heap* heap)) {+  heap->min = NULL;+  heap->nelts = 0;+}++HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap)) {+  return heap->min;+}++/* Swap parent with child. Child moves closer to the root, parent moves away. */+static void heap_node_swap(struct heap* heap,+                           struct heap_node* parent,+                           struct heap_node* child) {+  struct heap_node* sibling;+  struct heap_node t;++  t = *parent;+  *parent = *child;+  *child = t;++  parent->parent = child;+  if (child->left == child) {+    child->left = parent;+    sibling = child->right;+  } else {+    child->right = parent;+    sibling = child->left;+  }+  if (sibling != NULL)+    sibling->parent = child;++  if (parent->left != NULL)+    parent->left->parent = parent;+  if (parent->right != NULL)+    parent->right->parent = parent;++  if (child->parent == NULL)+    heap->min = child;+  else if (child->parent->left == parent)+    child->parent->left = child;+  else+    child->parent->right = child;+}++HEAP_EXPORT(void heap_insert(struct heap* heap,+                             struct heap_node* newnode,+                             heap_compare_fn less_than)) {+  struct heap_node** parent;+  struct heap_node** child;+  unsigned int path;+  unsigned int n;+  unsigned int k;++  newnode->left = NULL;+  newnode->right = NULL;+  newnode->parent = NULL;++  /* Calculate the path from the root to the insertion point.  This is a min+   * heap so we always insert at the left-most free node of the bottom row.+   */+  path = 0;+  for (k = 0, n = 1 + heap->nelts; n >= 2; k += 1, n /= 2)+    path = (path << 1) | (n & 1);++  /* Now traverse the heap using the path we calculated in the previous step. */+  parent = child = &heap->min;+  while (k > 0) {+    parent = child;+    if (path & 1)+      child = &(*child)->right;+    else+      child = &(*child)->left;+    path >>= 1;+    k -= 1;+  }++  /* Insert the new node. */+  newnode->parent = *parent;+  *child = newnode;+  heap->nelts += 1;++  /* Walk up the tree and check at each node if the heap property holds.+   * It's a min heap so parent < child must be true.+   */+  while (newnode->parent != NULL && less_than(newnode, newnode->parent))+    heap_node_swap(heap, newnode->parent, newnode);+}++HEAP_EXPORT(void heap_remove(struct heap* heap,+                             struct heap_node* node,+                             heap_compare_fn less_than)) {+  struct heap_node* smallest;+  struct heap_node** max;+  struct heap_node* child;+  unsigned int path;+  unsigned int k;+  unsigned int n;++  if (heap->nelts == 0)+    return;++  /* Calculate the path from the min (the root) to the max, the left-most node+   * of the bottom row.+   */+  path = 0;+  for (k = 0, n = heap->nelts; n >= 2; k += 1, n /= 2)+    path = (path << 1) | (n & 1);++  /* Now traverse the heap using the path we calculated in the previous step. */+  max = &heap->min;+  while (k > 0) {+    if (path & 1)+      max = &(*max)->right;+    else+      max = &(*max)->left;+    path >>= 1;+    k -= 1;+  }++  heap->nelts -= 1;++  /* Unlink the max node. */+  child = *max;+  *max = NULL;++  if (child == node) {+    /* We're removing either the max or the last node in the tree. */+    if (child == heap->min) {+      heap->min = NULL;+    }+    return;+  }++  /* Replace the to be deleted node with the max node. */+  child->left = node->left;+  child->right = node->right;+  child->parent = node->parent;++  if (child->left != NULL) {+    child->left->parent = child;+  }++  if (child->right != NULL) {+    child->right->parent = child;+  }++  if (node->parent == NULL) {+    heap->min = child;+  } else if (node->parent->left == node) {+    node->parent->left = child;+  } else {+    node->parent->right = child;+  }++  /* Walk down the subtree and check at each node if the heap property holds.+   * It's a min heap so parent < child must be true.  If the parent is bigger,+   * swap it with the smallest child.+   */+  for (;;) {+    smallest = child;+    if (child->left != NULL && less_than(child->left, smallest))+      smallest = child->left;+    if (child->right != NULL && less_than(child->right, smallest))+      smallest = child->right;+    if (smallest == child)+      break;+    heap_node_swap(heap, child, smallest);+  }++  /* Walk up the subtree and check that each parent is less than the node+   * this is required, because `max` node is not guaranteed to be the+   * actual maximum in tree+   */+  while (child->parent != NULL && less_than(child, child->parent))+    heap_node_swap(heap, child->parent, child);+}++HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than)) {+  heap_remove(heap, heap->min, less_than);+}++#undef HEAP_EXPORT++#endif  /* UV_SRC_HEAP_H_ */
+ third_party/libuv/src/idna.c view
@@ -0,0 +1,291 @@+/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl>+ *+ * Permission to use, copy, modify, and/or distribute this software for any+ * purpose with or without fee is hereby granted, provided that the above+ * copyright notice and this permission notice appear in all copies.+ *+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.+ */++/* Derived from https://github.com/bnoordhuis/punycode+ * but updated to support IDNA 2008.+ */++#include "uv.h"+#include "idna.h"+#include <string.h>++static unsigned uv__utf8_decode1_slow(const char** p,+                                      const char* pe,+                                      unsigned a) {+  unsigned b;+  unsigned c;+  unsigned d;+  unsigned min;++  if (a > 0xF7)+    return -1;++  switch (*p - pe) {+  default:+    if (a > 0xEF) {+      min = 0x10000;+      a = a & 7;+      b = (unsigned char) *(*p)++;+      c = (unsigned char) *(*p)++;+      d = (unsigned char) *(*p)++;+      break;+    }+    /* Fall through. */+  case 2:+    if (a > 0xDF) {+      min = 0x800;+      b = 0x80 | (a & 15);+      c = (unsigned char) *(*p)++;+      d = (unsigned char) *(*p)++;+      a = 0;+      break;+    }+    /* Fall through. */+  case 1:+    if (a > 0xBF) {+      min = 0x80;+      b = 0x80;+      c = 0x80 | (a & 31);+      d = (unsigned char) *(*p)++;+      a = 0;+      break;+    }+    return -1;  /* Invalid continuation byte. */+  }++  if (0x80 != (0xC0 & (b ^ c ^ d)))+    return -1;  /* Invalid sequence. */++  b &= 63;+  c &= 63;+  d &= 63;+  a = (a << 18) | (b << 12) | (c << 6) | d;++  if (a < min)+    return -1;  /* Overlong sequence. */++  if (a > 0x10FFFF)+    return -1;  /* Four-byte sequence > U+10FFFF. */++  if (a >= 0xD800 && a <= 0xDFFF)+    return -1;  /* Surrogate pair. */++  return a;+}++unsigned uv__utf8_decode1(const char** p, const char* pe) {+  unsigned a;++  a = (unsigned char) *(*p)++;++  if (a < 128)+    return a;  /* ASCII, common case. */++  return uv__utf8_decode1_slow(p, pe, a);+}++#define foreach_codepoint(c, p, pe) \+  for (; (void) (*p <= pe && (c = uv__utf8_decode1(p, pe))), *p <= pe;)++static int uv__idna_toascii_label(const char* s, const char* se,+                                  char** d, char* de) {+  static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789";+  const char* ss;+  unsigned c;+  unsigned h;+  unsigned k;+  unsigned n;+  unsigned m;+  unsigned q;+  unsigned t;+  unsigned x;+  unsigned y;+  unsigned bias;+  unsigned delta;+  unsigned todo;+  int first;++  h = 0;+  ss = s;+  todo = 0;++  foreach_codepoint(c, &s, se) {+    if (c < 128)+      h++;+    else if (c == (unsigned) -1)+      return UV_EINVAL;+    else+      todo++;+  }++  if (todo > 0) {+    if (*d < de) *(*d)++ = 'x';+    if (*d < de) *(*d)++ = 'n';+    if (*d < de) *(*d)++ = '-';+    if (*d < de) *(*d)++ = '-';+  }++  x = 0;+  s = ss;+  foreach_codepoint(c, &s, se) {+    if (c > 127)+      continue;++    if (*d < de)+      *(*d)++ = c;++    if (++x == h)+      break;  /* Visited all ASCII characters. */+  }++  if (todo == 0)+    return h;++  /* Only write separator when we've written ASCII characters first. */+  if (h > 0)+    if (*d < de)+      *(*d)++ = '-';++  n = 128;+  bias = 72;+  delta = 0;+  first = 1;++  while (todo > 0) {+    m = -1;+    s = ss;+    foreach_codepoint(c, &s, se)+      if (c >= n)+        if (c < m)+          m = c;++    x = m - n;+    y = h + 1;++    if (x > ~delta / y)+      return UV_E2BIG;  /* Overflow. */++    delta += x * y;+    n = m;++    s = ss;+    foreach_codepoint(c, &s, se) {+      if (c < n)+        if (++delta == 0)+          return UV_E2BIG;  /* Overflow. */++      if (c != n)+        continue;++      for (k = 36, q = delta; /* empty */; k += 36) {+        t = 1;++        if (k > bias)+          t = k - bias;++        if (t > 26)+          t = 26;++        if (q < t)+          break;++        /* TODO(bnoordhuis) Since 1 <= t <= 26 and therefore+         * 10 <= y <= 35, we can optimize the long division+         * into a table-based reciprocal multiplication.+         */+        x = q - t;+        y = 36 - t;  /* 10 <= y <= 35 since 1 <= t <= 26. */+        q = x / y;+        t = t + x % y;  /* 1 <= t <= 35 because of y. */++        if (*d < de)+          *(*d)++ = alphabet[t];+      }++      if (*d < de)+        *(*d)++ = alphabet[q];++      delta /= 2;++      if (first) {+        delta /= 350;+        first = 0;+      }++      /* No overflow check is needed because |delta| was just+       * divided by 2 and |delta+delta >= delta + delta/h|.+       */+      h++;+      delta += delta / h;++      for (bias = 0; delta > 35 * 26 / 2; bias += 36)+        delta /= 35;++      bias += 36 * delta / (delta + 38);+      delta = 0;+      todo--;+    }++    delta++;+    n++;+  }++  return 0;+}++#undef foreach_codepoint++long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {+  const char* si;+  const char* st;+  unsigned c;+  char* ds;+  int rc;++  ds = d;++  for (si = s; si < se; /* empty */) {+    st = si;+    c = uv__utf8_decode1(&si, se);++    if (c != '.')+      if (c != 0x3002)  /* 。 */+        if (c != 0xFF0E)  /* . */+          if (c != 0xFF61)  /* 。 */+            continue;++    rc = uv__idna_toascii_label(s, st, &d, de);++    if (rc < 0)+      return rc;++    if (d < de)+      *d++ = '.';++    s = si;+  }++  if (s < se) {+    rc = uv__idna_toascii_label(s, se, &d, de);++    if (rc < 0)+      return rc;+  }++  if (d < de)+    *d++ = '\0';++  return d - ds;  /* Number of bytes written. */+}
+ third_party/libuv/src/idna.h view
@@ -0,0 +1,31 @@+/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl>+ *+ * Permission to use, copy, modify, and/or distribute this software for any+ * purpose with or without fee is hereby granted, provided that the above+ * copyright notice and this permission notice appear in all copies.+ *+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.+ */++#ifndef UV_SRC_IDNA_H_+#define UV_SRC_IDNA_H_++/* Decode a single codepoint. Returns the codepoint or UINT32_MAX on error.+ * |p| is updated on success _and_ error, i.e., bad multi-byte sequences are+ * skipped in their entirety, not just the first bad byte.+ */+unsigned uv__utf8_decode1(const char** p, const char* pe);++/* Convert a UTF-8 domain name to IDNA 2008 / Punycode. A return value >= 0+ * is the number of bytes written to |d|, including the trailing nul byte.+ * A return value < 0 is a libuv error code. |s| and |d| can not overlap.+ */+long uv__idna_toascii(const char* s, const char* se, char* d, char* de);++#endif  /* UV_SRC_IDNA_H_ */
+ third_party/libuv/src/inet.c view
@@ -0,0 +1,302 @@+/*+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")+ * Copyright (c) 1996-1999 by Internet Software Consortium.+ *+ * Permission to use, copy, modify, and distribute this software for any+ * purpose with or without fee is hereby granted, provided that the above+ * copyright notice and this permission notice appear in all copies.+ *+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.+ */++#include <stdio.h>+#include <string.h>++#if defined(_MSC_VER) && _MSC_VER < 1600+# include "uv/stdint-msvc2008.h"+#else+# include <stdint.h>+#endif++#include "uv.h"+#include "uv-common.h"++#define UV__INET_ADDRSTRLEN         16+#define UV__INET6_ADDRSTRLEN        46+++static int inet_ntop4(const unsigned char *src, char *dst, size_t size);+static int inet_ntop6(const unsigned char *src, char *dst, size_t size);+static int inet_pton4(const char *src, unsigned char *dst);+static int inet_pton6(const char *src, unsigned char *dst);+++int uv_inet_ntop(int af, const void* src, char* dst, size_t size) {+  switch (af) {+  case AF_INET:+    return (inet_ntop4(src, dst, size));+  case AF_INET6:+    return (inet_ntop6(src, dst, size));+  default:+    return UV_EAFNOSUPPORT;+  }+  /* NOTREACHED */+}+++static int inet_ntop4(const unsigned char *src, char *dst, size_t size) {+  static const char fmt[] = "%u.%u.%u.%u";+  char tmp[UV__INET_ADDRSTRLEN];+  int l;++  l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);+  if (l <= 0 || (size_t) l >= size) {+    return UV_ENOSPC;+  }+  uv__strscpy(dst, tmp, size);+  return 0;+}+++static int inet_ntop6(const unsigned char *src, char *dst, size_t size) {+  /*+   * Note that int32_t and int16_t need only be "at least" large enough+   * to contain a value of the specified size.  On some systems, like+   * Crays, there is no such thing as an integer variable with 16 bits.+   * Keep this in mind if you think this function should have been coded+   * to use pointer overlays.  All the world's not a VAX.+   */+  char tmp[UV__INET6_ADDRSTRLEN], *tp;+  struct { int base, len; } best, cur;+  unsigned int words[sizeof(struct in6_addr) / sizeof(uint16_t)];+  int i;++  /*+   * Preprocess:+   *  Copy the input (bytewise) array into a wordwise array.+   *  Find the longest run of 0x00's in src[] for :: shorthanding.+   */+  memset(words, '\0', sizeof words);+  for (i = 0; i < (int) sizeof(struct in6_addr); i++)+    words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));+  best.base = -1;+  best.len = 0;+  cur.base = -1;+  cur.len = 0;+  for (i = 0; i < (int) ARRAY_SIZE(words); i++) {+    if (words[i] == 0) {+      if (cur.base == -1)+        cur.base = i, cur.len = 1;+      else+        cur.len++;+    } else {+      if (cur.base != -1) {+        if (best.base == -1 || cur.len > best.len)+          best = cur;+        cur.base = -1;+      }+    }+  }+  if (cur.base != -1) {+    if (best.base == -1 || cur.len > best.len)+      best = cur;+  }+  if (best.base != -1 && best.len < 2)+    best.base = -1;++  /*+   * Format the result.+   */+  tp = tmp;+  for (i = 0; i < (int) ARRAY_SIZE(words); i++) {+    /* Are we inside the best run of 0x00's? */+    if (best.base != -1 && i >= best.base &&+        i < (best.base + best.len)) {+      if (i == best.base)+        *tp++ = ':';+      continue;+    }+    /* Are we following an initial run of 0x00s or any real hex? */+    if (i != 0)+      *tp++ = ':';+    /* Is this address an encapsulated IPv4? */+    if (i == 6 && best.base == 0 && (best.len == 6 ||+        (best.len == 7 && words[7] != 0x0001) ||+        (best.len == 5 && words[5] == 0xffff))) {+      int err = inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp));+      if (err)+        return err;+      tp += strlen(tp);+      break;+    }+    tp += sprintf(tp, "%x", words[i]);+  }+  /* Was it a trailing run of 0x00's? */+  if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words))+    *tp++ = ':';+  *tp++ = '\0';+  if (UV_E2BIG == uv__strscpy(dst, tmp, size))+    return UV_ENOSPC;+  return 0;+}+++int uv_inet_pton(int af, const char* src, void* dst) {+  if (src == NULL || dst == NULL)+    return UV_EINVAL;++  switch (af) {+  case AF_INET:+    return (inet_pton4(src, dst));+  case AF_INET6: {+    int len;+    char tmp[UV__INET6_ADDRSTRLEN], *s, *p;+    s = (char*) src;+    p = strchr(src, '%');+    if (p != NULL) {+      s = tmp;+      len = p - src;+      if (len > UV__INET6_ADDRSTRLEN-1)+        return UV_EINVAL;+      memcpy(s, src, len);+      s[len] = '\0';+    }+    return inet_pton6(s, dst);+  }+  default:+    return UV_EAFNOSUPPORT;+  }+  /* NOTREACHED */+}+++static int inet_pton4(const char *src, unsigned char *dst) {+  static const char digits[] = "0123456789";+  int saw_digit, octets, ch;+  unsigned char tmp[sizeof(struct in_addr)], *tp;++  saw_digit = 0;+  octets = 0;+  *(tp = tmp) = 0;+  while ((ch = *src++) != '\0') {+    const char *pch;++    if ((pch = strchr(digits, ch)) != NULL) {+      unsigned int nw = *tp * 10 + (pch - digits);++      if (saw_digit && *tp == 0)+        return UV_EINVAL;+      if (nw > 255)+        return UV_EINVAL;+      *tp = nw;+      if (!saw_digit) {+        if (++octets > 4)+          return UV_EINVAL;+        saw_digit = 1;+      }+    } else if (ch == '.' && saw_digit) {+      if (octets == 4)+        return UV_EINVAL;+      *++tp = 0;+      saw_digit = 0;+    } else+      return UV_EINVAL;+  }+  if (octets < 4)+    return UV_EINVAL;+  memcpy(dst, tmp, sizeof(struct in_addr));+  return 0;+}+++static int inet_pton6(const char *src, unsigned char *dst) {+  static const char xdigits_l[] = "0123456789abcdef",+                    xdigits_u[] = "0123456789ABCDEF";+  unsigned char tmp[sizeof(struct in6_addr)], *tp, *endp, *colonp;+  const char *xdigits, *curtok;+  int ch, seen_xdigits;+  unsigned int val;++  memset((tp = tmp), '\0', sizeof tmp);+  endp = tp + sizeof tmp;+  colonp = NULL;+  /* Leading :: requires some special handling. */+  if (*src == ':')+    if (*++src != ':')+      return UV_EINVAL;+  curtok = src;+  seen_xdigits = 0;+  val = 0;+  while ((ch = *src++) != '\0') {+    const char *pch;++    if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)+      pch = strchr((xdigits = xdigits_u), ch);+    if (pch != NULL) {+      val <<= 4;+      val |= (pch - xdigits);+      if (++seen_xdigits > 4)+        return UV_EINVAL;+      continue;+    }+    if (ch == ':') {+      curtok = src;+      if (!seen_xdigits) {+        if (colonp)+          return UV_EINVAL;+        colonp = tp;+        continue;+      } else if (*src == '\0') {+        return UV_EINVAL;+      }+      if (tp + sizeof(uint16_t) > endp)+        return UV_EINVAL;+      *tp++ = (unsigned char) (val >> 8) & 0xff;+      *tp++ = (unsigned char) val & 0xff;+      seen_xdigits = 0;+      val = 0;+      continue;+    }+    if (ch == '.' && ((tp + sizeof(struct in_addr)) <= endp)) {+      int err = inet_pton4(curtok, tp);+      if (err == 0) {+        tp += sizeof(struct in_addr);+        seen_xdigits = 0;+        break;  /*%< '\\0' was seen by inet_pton4(). */+      }+    }+    return UV_EINVAL;+  }+  if (seen_xdigits) {+    if (tp + sizeof(uint16_t) > endp)+      return UV_EINVAL;+    *tp++ = (unsigned char) (val >> 8) & 0xff;+    *tp++ = (unsigned char) val & 0xff;+  }+  if (colonp != NULL) {+    /*+     * Since some memmove()'s erroneously fail to handle+     * overlapping regions, we'll do the shift by hand.+     */+    const int n = tp - colonp;+    int i;++    if (tp == endp)+      return UV_EINVAL;+    for (i = 1; i <= n; i++) {+      endp[- i] = colonp[n - i];+      colonp[n - i] = 0;+    }+    tp = endp;+  }+  if (tp != endp)+    return UV_EINVAL;+  memcpy(dst, tmp, sizeof tmp);+  return 0;+}
+ third_party/libuv/src/queue.h view
@@ -0,0 +1,108 @@+/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>+ *+ * Permission to use, copy, modify, and/or distribute this software for any+ * purpose with or without fee is hereby granted, provided that the above+ * copyright notice and this permission notice appear in all copies.+ *+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.+ */++#ifndef QUEUE_H_+#define QUEUE_H_++#include <stddef.h>++typedef void *QUEUE[2];++/* Private macros. */+#define QUEUE_NEXT(q)       (*(QUEUE **) &((*(q))[0]))+#define QUEUE_PREV(q)       (*(QUEUE **) &((*(q))[1]))+#define QUEUE_PREV_NEXT(q)  (QUEUE_NEXT(QUEUE_PREV(q)))+#define QUEUE_NEXT_PREV(q)  (QUEUE_PREV(QUEUE_NEXT(q)))++/* Public macros. */+#define QUEUE_DATA(ptr, type, field)                                          \+  ((type *) ((char *) (ptr) - offsetof(type, field)))++/* Important note: mutating the list while QUEUE_FOREACH is+ * iterating over its elements results in undefined behavior.+ */+#define QUEUE_FOREACH(q, h)                                                   \+  for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q))++#define QUEUE_EMPTY(q)                                                        \+  ((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q))++#define QUEUE_HEAD(q)                                                         \+  (QUEUE_NEXT(q))++#define QUEUE_INIT(q)                                                         \+  do {                                                                        \+    QUEUE_NEXT(q) = (q);                                                      \+    QUEUE_PREV(q) = (q);                                                      \+  }                                                                           \+  while (0)++#define QUEUE_ADD(h, n)                                                       \+  do {                                                                        \+    QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n);                                       \+    QUEUE_NEXT_PREV(n) = QUEUE_PREV(h);                                       \+    QUEUE_PREV(h) = QUEUE_PREV(n);                                            \+    QUEUE_PREV_NEXT(h) = (h);                                                 \+  }                                                                           \+  while (0)++#define QUEUE_SPLIT(h, q, n)                                                  \+  do {                                                                        \+    QUEUE_PREV(n) = QUEUE_PREV(h);                                            \+    QUEUE_PREV_NEXT(n) = (n);                                                 \+    QUEUE_NEXT(n) = (q);                                                      \+    QUEUE_PREV(h) = QUEUE_PREV(q);                                            \+    QUEUE_PREV_NEXT(h) = (h);                                                 \+    QUEUE_PREV(q) = (n);                                                      \+  }                                                                           \+  while (0)++#define QUEUE_MOVE(h, n)                                                      \+  do {                                                                        \+    if (QUEUE_EMPTY(h))                                                       \+      QUEUE_INIT(n);                                                          \+    else {                                                                    \+      QUEUE* q = QUEUE_HEAD(h);                                               \+      QUEUE_SPLIT(h, q, n);                                                   \+    }                                                                         \+  }                                                                           \+  while (0)++#define QUEUE_INSERT_HEAD(h, q)                                               \+  do {                                                                        \+    QUEUE_NEXT(q) = QUEUE_NEXT(h);                                            \+    QUEUE_PREV(q) = (h);                                                      \+    QUEUE_NEXT_PREV(q) = (q);                                                 \+    QUEUE_NEXT(h) = (q);                                                      \+  }                                                                           \+  while (0)++#define QUEUE_INSERT_TAIL(h, q)                                               \+  do {                                                                        \+    QUEUE_NEXT(q) = (h);                                                      \+    QUEUE_PREV(q) = QUEUE_PREV(h);                                            \+    QUEUE_PREV_NEXT(q) = (q);                                                 \+    QUEUE_PREV(h) = (q);                                                      \+  }                                                                           \+  while (0)++#define QUEUE_REMOVE(q)                                                       \+  do {                                                                        \+    QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q);                                       \+    QUEUE_NEXT_PREV(q) = QUEUE_PREV(q);                                       \+  }                                                                           \+  while (0)++#endif /* QUEUE_H_ */
+ third_party/libuv/src/strscpy.c view
@@ -0,0 +1,17 @@+#include "strscpy.h"+#include <limits.h>  /* SSIZE_MAX */++ssize_t uv__strscpy(char* d, const char* s, size_t n) {+  size_t i;++  for (i = 0; i < n; i++)+    if ('\0' == (d[i] = s[i]))+      return i > SSIZE_MAX ? UV_E2BIG : (ssize_t) i;++  if (i == 0)+    return 0;++  d[--i] = '\0';++  return UV_E2BIG;+}
+ third_party/libuv/src/strscpy.h view
@@ -0,0 +1,18 @@+#ifndef UV_STRSCPY_H_+#define UV_STRSCPY_H_++/* Include uv.h for its definitions of size_t and ssize_t.+ * size_t can be obtained directly from <stddef.h> but ssize_t requires+ * some hoop jumping on Windows that I didn't want to duplicate here.+ */+#include "uv.h"++/* Copies up to |n-1| bytes from |d| to |s| and always zero-terminates+ * the result, except when |n==0|. Returns the number of bytes copied+ * or UV_E2BIG if |d| is too small.+ *+ * See https://www.kernel.org/doc/htmldocs/kernel-api/API-strscpy.html+ */+ssize_t uv__strscpy(char* d, const char* s, size_t n);++#endif  /* UV_STRSCPY_H_ */
+ third_party/libuv/src/threadpool.c view
@@ -0,0 +1,384 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include "uv-common.h"++#if !defined(_WIN32)+# include "unix/internal.h"+#endif++#include <stdlib.h>++#define MAX_THREADPOOL_SIZE 128++static uv_once_t once = UV_ONCE_INIT;+static uv_cond_t cond;+static uv_mutex_t mutex;+static unsigned int idle_threads;+static unsigned int slow_io_work_running;+static unsigned int nthreads;+static uv_thread_t* threads;+static uv_thread_t default_threads[4];+static QUEUE exit_message;+static QUEUE wq;+static QUEUE run_slow_work_message;+static QUEUE slow_io_pending_wq;++static unsigned int slow_work_thread_threshold(void) {+  return (nthreads + 1) / 2;+}++static void uv__cancelled(struct uv__work* w) {+  abort();+}+++/* To avoid deadlock with uv_cancel() it's crucial that the worker+ * never holds the global mutex and the loop-local mutex at the same time.+ */+static void worker(void* arg) {+  struct uv__work* w;+  QUEUE* q;+  int is_slow_work;++  uv_sem_post((uv_sem_t*) arg);+  arg = NULL;++  uv_mutex_lock(&mutex);+  for (;;) {+    /* `mutex` should always be locked at this point. */++    /* Keep waiting while either no work is present or only slow I/O+       and we're at the threshold for that. */+    while (QUEUE_EMPTY(&wq) ||+           (QUEUE_HEAD(&wq) == &run_slow_work_message &&+            QUEUE_NEXT(&run_slow_work_message) == &wq &&+            slow_io_work_running >= slow_work_thread_threshold())) {+      idle_threads += 1;+      uv_cond_wait(&cond, &mutex);+      idle_threads -= 1;+    }++    q = QUEUE_HEAD(&wq);+    if (q == &exit_message) {+      uv_cond_signal(&cond);+      uv_mutex_unlock(&mutex);+      break;+    }++    QUEUE_REMOVE(q);+    QUEUE_INIT(q);  /* Signal uv_cancel() that the work req is executing. */++    is_slow_work = 0;+    if (q == &run_slow_work_message) {+      /* If we're at the slow I/O threshold, re-schedule until after all+         other work in the queue is done. */+      if (slow_io_work_running >= slow_work_thread_threshold()) {+        QUEUE_INSERT_TAIL(&wq, q);+        continue;+      }++      /* If we encountered a request to run slow I/O work but there is none+         to run, that means it's cancelled => Start over. */+      if (QUEUE_EMPTY(&slow_io_pending_wq))+        continue;++      is_slow_work = 1;+      slow_io_work_running++;++      q = QUEUE_HEAD(&slow_io_pending_wq);+      QUEUE_REMOVE(q);+      QUEUE_INIT(q);++      /* If there is more slow I/O work, schedule it to be run as well. */+      if (!QUEUE_EMPTY(&slow_io_pending_wq)) {+        QUEUE_INSERT_TAIL(&wq, &run_slow_work_message);+        if (idle_threads > 0)+          uv_cond_signal(&cond);+      }+    }++    uv_mutex_unlock(&mutex);++    w = QUEUE_DATA(q, struct uv__work, wq);+    w->work(w);++    uv_mutex_lock(&w->loop->wq_mutex);+    w->work = NULL;  /* Signal uv_cancel() that the work req is done+                        executing. */+    QUEUE_INSERT_TAIL(&w->loop->wq, &w->wq);+    uv_async_send(&w->loop->wq_async);+    uv_mutex_unlock(&w->loop->wq_mutex);++    /* Lock `mutex` since that is expected at the start of the next+     * iteration. */+    uv_mutex_lock(&mutex);+    if (is_slow_work) {+      /* `slow_io_work_running` is protected by `mutex`. */+      slow_io_work_running--;+    }+  }+}+++static void post(QUEUE* q, enum uv__work_kind kind) {+  uv_mutex_lock(&mutex);+  if (kind == UV__WORK_SLOW_IO) {+    /* Insert into a separate queue. */+    QUEUE_INSERT_TAIL(&slow_io_pending_wq, q);+    if (!QUEUE_EMPTY(&run_slow_work_message)) {+      /* Running slow I/O tasks is already scheduled => Nothing to do here.+         The worker that runs said other task will schedule this one as well. */+      uv_mutex_unlock(&mutex);+      return;+    }+    q = &run_slow_work_message;+  }++  QUEUE_INSERT_TAIL(&wq, q);+  if (idle_threads > 0)+    uv_cond_signal(&cond);+  uv_mutex_unlock(&mutex);+}+++#ifndef _WIN32+UV_DESTRUCTOR(static void cleanup(void)) {+  unsigned int i;++  if (nthreads == 0)+    return;++  post(&exit_message, UV__WORK_CPU);++  for (i = 0; i < nthreads; i++)+    if (uv_thread_join(threads + i))+      abort();++  if (threads != default_threads)+    uv__free(threads);++  uv_mutex_destroy(&mutex);+  uv_cond_destroy(&cond);++  threads = NULL;+  nthreads = 0;+}+#endif+++static void init_threads(void) {+  unsigned int i;+  const char* val;+  uv_sem_t sem;++  nthreads = ARRAY_SIZE(default_threads);+  val = getenv("UV_THREADPOOL_SIZE");+  if (val != NULL)+    nthreads = atoi(val);+  if (nthreads == 0)+    nthreads = 1;+  if (nthreads > MAX_THREADPOOL_SIZE)+    nthreads = MAX_THREADPOOL_SIZE;++  threads = default_threads;+  if (nthreads > ARRAY_SIZE(default_threads)) {+    threads = uv__malloc(nthreads * sizeof(threads[0]));+    if (threads == NULL) {+      nthreads = ARRAY_SIZE(default_threads);+      threads = default_threads;+    }+  }++  if (uv_cond_init(&cond))+    abort();++  if (uv_mutex_init(&mutex))+    abort();++  QUEUE_INIT(&wq);+  QUEUE_INIT(&slow_io_pending_wq);+  QUEUE_INIT(&run_slow_work_message);++  if (uv_sem_init(&sem, 0))+    abort();++  for (i = 0; i < nthreads; i++)+    if (uv_thread_create(threads + i, worker, &sem))+      abort();++  for (i = 0; i < nthreads; i++)+    uv_sem_wait(&sem);++  uv_sem_destroy(&sem);+}+++#ifndef _WIN32+static void reset_once(void) {+  uv_once_t child_once = UV_ONCE_INIT;+  memcpy(&once, &child_once, sizeof(child_once));+}+#endif+++static void init_once(void) {+#ifndef _WIN32+  /* Re-initialize the threadpool after fork.+   * Note that this discards the global mutex and condition as well+   * as the work queue.+   */+  if (pthread_atfork(NULL, NULL, &reset_once))+    abort();+#endif+  init_threads();+}+++void uv__work_submit(uv_loop_t* loop,+                     struct uv__work* w,+                     enum uv__work_kind kind,+                     void (*work)(struct uv__work* w),+                     void (*done)(struct uv__work* w, int status)) {+  uv_once(&once, init_once);+  w->loop = loop;+  w->work = work;+  w->done = done;+  post(&w->wq, kind);+}+++static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) {+  int cancelled;++  uv_mutex_lock(&mutex);+  uv_mutex_lock(&w->loop->wq_mutex);++  cancelled = !QUEUE_EMPTY(&w->wq) && w->work != NULL;+  if (cancelled)+    QUEUE_REMOVE(&w->wq);++  uv_mutex_unlock(&w->loop->wq_mutex);+  uv_mutex_unlock(&mutex);++  if (!cancelled)+    return UV_EBUSY;++  w->work = uv__cancelled;+  uv_mutex_lock(&loop->wq_mutex);+  QUEUE_INSERT_TAIL(&loop->wq, &w->wq);+  uv_async_send(&loop->wq_async);+  uv_mutex_unlock(&loop->wq_mutex);++  return 0;+}+++void uv__work_done(uv_async_t* handle) {+  struct uv__work* w;+  uv_loop_t* loop;+  QUEUE* q;+  QUEUE wq;+  int err;++  loop = container_of(handle, uv_loop_t, wq_async);+  uv_mutex_lock(&loop->wq_mutex);+  QUEUE_MOVE(&loop->wq, &wq);+  uv_mutex_unlock(&loop->wq_mutex);++  while (!QUEUE_EMPTY(&wq)) {+    q = QUEUE_HEAD(&wq);+    QUEUE_REMOVE(q);++    w = container_of(q, struct uv__work, wq);+    err = (w->work == uv__cancelled) ? UV_ECANCELED : 0;+    w->done(w, err);+  }+}+++static void uv__queue_work(struct uv__work* w) {+  uv_work_t* req = container_of(w, uv_work_t, work_req);++  req->work_cb(req);+}+++static void uv__queue_done(struct uv__work* w, int err) {+  uv_work_t* req;++  req = container_of(w, uv_work_t, work_req);+  uv__req_unregister(req->loop, req);++  if (req->after_work_cb == NULL)+    return;++  req->after_work_cb(req, err);+}+++int uv_queue_work(uv_loop_t* loop,+                  uv_work_t* req,+                  uv_work_cb work_cb,+                  uv_after_work_cb after_work_cb) {+  if (work_cb == NULL)+    return UV_EINVAL;++  uv__req_init(loop, req, UV_WORK);+  req->loop = loop;+  req->work_cb = work_cb;+  req->after_work_cb = after_work_cb;+  uv__work_submit(loop,+                  &req->work_req,+                  UV__WORK_CPU,+                  uv__queue_work,+                  uv__queue_done);+  return 0;+}+++int uv_cancel(uv_req_t* req) {+  struct uv__work* wreq;+  uv_loop_t* loop;++  switch (req->type) {+  case UV_FS:+    loop =  ((uv_fs_t*) req)->loop;+    wreq = &((uv_fs_t*) req)->work_req;+    break;+  case UV_GETADDRINFO:+    loop =  ((uv_getaddrinfo_t*) req)->loop;+    wreq = &((uv_getaddrinfo_t*) req)->work_req;+    break;+  case UV_GETNAMEINFO:+    loop = ((uv_getnameinfo_t*) req)->loop;+    wreq = &((uv_getnameinfo_t*) req)->work_req;+    break;+  case UV_WORK:+    loop =  ((uv_work_t*) req)->loop;+    wreq = &((uv_work_t*) req)->work_req;+    break;+  default:+    return UV_EINVAL;+  }++  return uv__work_cancel(loop, req, wreq);+}
+ third_party/libuv/src/timer.c view
@@ -0,0 +1,181 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include "uv.h"+#include "uv-common.h"+#include "heap-inl.h"++#include <assert.h>+#include <limits.h>+++static struct heap *timer_heap(const uv_loop_t* loop) {+#ifdef _WIN32+  return (struct heap*) loop->timer_heap;+#else+  return (struct heap*) &loop->timer_heap;+#endif+}+++static int timer_less_than(const struct heap_node* ha,+                           const struct heap_node* hb) {+  const uv_timer_t* a;+  const uv_timer_t* b;++  a = container_of(ha, uv_timer_t, heap_node);+  b = container_of(hb, uv_timer_t, heap_node);++  if (a->timeout < b->timeout)+    return 1;+  if (b->timeout < a->timeout)+    return 0;++  /* Compare start_id when both have the same timeout. start_id is+   * allocated with loop->timer_counter in uv_timer_start().+   */+  if (a->start_id < b->start_id)+    return 1;+  if (b->start_id < a->start_id)+    return 0;++  return 0;+}+++int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {+  uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);+  handle->timer_cb = NULL;+  handle->repeat = 0;+  return 0;+}+++int uv_timer_start(uv_timer_t* handle,+                   uv_timer_cb cb,+                   uint64_t timeout,+                   uint64_t repeat) {+  uint64_t clamped_timeout;++  if (cb == NULL)+    return UV_EINVAL;++  if (uv__is_active(handle))+    uv_timer_stop(handle);++  clamped_timeout = handle->loop->time + timeout;+  if (clamped_timeout < timeout)+    clamped_timeout = (uint64_t) -1;++  handle->timer_cb = cb;+  handle->timeout = clamped_timeout;+  handle->repeat = repeat;+  /* start_id is the second index to be compared in uv__timer_cmp() */+  handle->start_id = handle->loop->timer_counter++;++  heap_insert(timer_heap(handle->loop),+              (struct heap_node*) &handle->heap_node,+              timer_less_than);+  uv__handle_start(handle);++  return 0;+}+++int uv_timer_stop(uv_timer_t* handle) {+  if (!uv__is_active(handle))+    return 0;++  heap_remove(timer_heap(handle->loop),+              (struct heap_node*) &handle->heap_node,+              timer_less_than);+  uv__handle_stop(handle);++  return 0;+}+++int uv_timer_again(uv_timer_t* handle) {+  if (handle->timer_cb == NULL)+    return UV_EINVAL;++  if (handle->repeat) {+    uv_timer_stop(handle);+    uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat);+  }++  return 0;+}+++void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) {+  handle->repeat = repeat;+}+++uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {+  return handle->repeat;+}+++int uv__next_timeout(const uv_loop_t* loop) {+  const struct heap_node* heap_node;+  const uv_timer_t* handle;+  uint64_t diff;++  heap_node = heap_min(timer_heap(loop));+  if (heap_node == NULL)+    return -1; /* block indefinitely */++  handle = container_of(heap_node, uv_timer_t, heap_node);+  if (handle->timeout <= loop->time)+    return 0;++  diff = handle->timeout - loop->time;+  if (diff > INT_MAX)+    diff = INT_MAX;++  return (int) diff;+}+++void uv__run_timers(uv_loop_t* loop) {+  struct heap_node* heap_node;+  uv_timer_t* handle;++  for (;;) {+    heap_node = heap_min(timer_heap(loop));+    if (heap_node == NULL)+      break;++    handle = container_of(heap_node, uv_timer_t, heap_node);+    if (handle->timeout > loop->time)+      break;++    uv_timer_stop(handle);+    uv_timer_again(handle);+    handle->timer_cb(handle);+  }+}+++void uv__timer_close(uv_timer_t* handle) {+  uv_timer_stop(handle);+}
+ third_party/libuv/src/uv-common.c view
@@ -0,0 +1,694 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include "uv.h"+#include "uv-common.h"++#include <assert.h>+#include <errno.h>+#include <stdarg.h>+#include <stddef.h> /* NULL */+#include <stdio.h>+#include <stdlib.h> /* malloc */+#include <string.h> /* memset */++#if defined(_WIN32)+# include <malloc.h> /* malloc */+#else+# include <net/if.h> /* if_nametoindex */+#endif+++typedef struct {+  uv_malloc_func local_malloc;+  uv_realloc_func local_realloc;+  uv_calloc_func local_calloc;+  uv_free_func local_free;+} uv__allocator_t;++static uv__allocator_t uv__allocator = {+  malloc,+  realloc,+  calloc,+  free,+};++char* uv__strdup(const char* s) {+  size_t len = strlen(s) + 1;+  char* m = uv__malloc(len);+  if (m == NULL)+    return NULL;+  return memcpy(m, s, len);+}++char* uv__strndup(const char* s, size_t n) {+  char* m;+  size_t len = strlen(s);+  if (n < len)+    len = n;+  m = uv__malloc(len + 1);+  if (m == NULL)+    return NULL;+  m[len] = '\0';+  return memcpy(m, s, len);+}++void* uv__malloc(size_t size) {+  if (size > 0)+    return uv__allocator.local_malloc(size);+  return NULL;+}++void uv__free(void* ptr) {+  int saved_errno;++  /* Libuv expects that free() does not clobber errno.  The system allocator+   * honors that assumption but custom allocators may not be so careful.+   */+  saved_errno = errno;+  uv__allocator.local_free(ptr);+  errno = saved_errno;+}++void* uv__calloc(size_t count, size_t size) {+  return uv__allocator.local_calloc(count, size);+}++void* uv__realloc(void* ptr, size_t size) {+  if (size > 0)+    return uv__allocator.local_realloc(ptr, size);+  uv__free(ptr);+  return NULL;+}++int uv_replace_allocator(uv_malloc_func malloc_func,+                         uv_realloc_func realloc_func,+                         uv_calloc_func calloc_func,+                         uv_free_func free_func) {+  if (malloc_func == NULL || realloc_func == NULL ||+      calloc_func == NULL || free_func == NULL) {+    return UV_EINVAL;+  }++  uv__allocator.local_malloc = malloc_func;+  uv__allocator.local_realloc = realloc_func;+  uv__allocator.local_calloc = calloc_func;+  uv__allocator.local_free = free_func;++  return 0;+}++#define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t);++size_t uv_handle_size(uv_handle_type type) {+  switch (type) {+    UV_HANDLE_TYPE_MAP(XX)+    default:+      return -1;+  }+}++size_t uv_req_size(uv_req_type type) {+  switch(type) {+    UV_REQ_TYPE_MAP(XX)+    default:+      return -1;+  }+}++#undef XX+++size_t uv_loop_size(void) {+  return sizeof(uv_loop_t);+}+++uv_buf_t uv_buf_init(char* base, unsigned int len) {+  uv_buf_t buf;+  buf.base = base;+  buf.len = len;+  return buf;+}+++static const char* uv__unknown_err_code(int err) {+  char buf[32];+  char* copy;++  snprintf(buf, sizeof(buf), "Unknown system error %d", err);+  copy = uv__strdup(buf);++  return copy != NULL ? copy : "Unknown system error";+}++#define UV_ERR_NAME_GEN_R(name, _) \+case UV_## name: \+  uv__strscpy(buf, #name, buflen); break;+char* uv_err_name_r(int err, char* buf, size_t buflen) {+  switch (err) {+    UV_ERRNO_MAP(UV_ERR_NAME_GEN_R)+    default: snprintf(buf, buflen, "Unknown system error %d", err);+  }+  return buf;+}+#undef UV_ERR_NAME_GEN_R+++#define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;+const char* uv_err_name(int err) {+  switch (err) {+    UV_ERRNO_MAP(UV_ERR_NAME_GEN)+  }+  return uv__unknown_err_code(err);+}+#undef UV_ERR_NAME_GEN+++#define UV_STRERROR_GEN_R(name, msg) \+case UV_ ## name: \+  snprintf(buf, buflen, "%s", msg); break;+char* uv_strerror_r(int err, char* buf, size_t buflen) {+  switch (err) {+    UV_ERRNO_MAP(UV_STRERROR_GEN_R)+    default: snprintf(buf, buflen, "Unknown system error %d", err);+  }+  return buf;+}+#undef UV_STRERROR_GEN_R+++#define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg;+const char* uv_strerror(int err) {+  switch (err) {+    UV_ERRNO_MAP(UV_STRERROR_GEN)+  }+  return uv__unknown_err_code(err);+}+#undef UV_STRERROR_GEN+++int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) {+  memset(addr, 0, sizeof(*addr));+  addr->sin_family = AF_INET;+  addr->sin_port = htons(port);+  return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr));+}+++int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {+  char address_part[40];+  size_t address_part_size;+  const char* zone_index;++  memset(addr, 0, sizeof(*addr));+  addr->sin6_family = AF_INET6;+  addr->sin6_port = htons(port);++  zone_index = strchr(ip, '%');+  if (zone_index != NULL) {+    address_part_size = zone_index - ip;+    if (address_part_size >= sizeof(address_part))+      address_part_size = sizeof(address_part) - 1;++    memcpy(address_part, ip, address_part_size);+    address_part[address_part_size] = '\0';+    ip = address_part;++    zone_index++; /* skip '%' */+    /* NOTE: unknown interface (id=0) is silently ignored */+#ifdef _WIN32+    addr->sin6_scope_id = atoi(zone_index);+#else+    addr->sin6_scope_id = if_nametoindex(zone_index);+#endif+  }++  return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr);+}+++int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) {+  return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size);+}+++int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) {+  return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);+}+++int uv_tcp_bind(uv_tcp_t* handle,+                const struct sockaddr* addr,+                unsigned int flags) {+  unsigned int addrlen;++  if (handle->type != UV_TCP)+    return UV_EINVAL;++  if (addr->sa_family == AF_INET)+    addrlen = sizeof(struct sockaddr_in);+  else if (addr->sa_family == AF_INET6)+    addrlen = sizeof(struct sockaddr_in6);+  else+    return UV_EINVAL;++  return uv__tcp_bind(handle, addr, addrlen, flags);+}+++int uv_udp_bind(uv_udp_t* handle,+                const struct sockaddr* addr,+                unsigned int flags) {+  unsigned int addrlen;++  if (handle->type != UV_UDP)+    return UV_EINVAL;++  if (addr->sa_family == AF_INET)+    addrlen = sizeof(struct sockaddr_in);+  else if (addr->sa_family == AF_INET6)+    addrlen = sizeof(struct sockaddr_in6);+  else+    return UV_EINVAL;++  return uv__udp_bind(handle, addr, addrlen, flags);+}+++int uv_tcp_connect(uv_connect_t* req,+                   uv_tcp_t* handle,+                   const struct sockaddr* addr,+                   uv_connect_cb cb) {+  unsigned int addrlen;++  if (handle->type != UV_TCP)+    return UV_EINVAL;++  if (addr->sa_family == AF_INET)+    addrlen = sizeof(struct sockaddr_in);+  else if (addr->sa_family == AF_INET6)+    addrlen = sizeof(struct sockaddr_in6);+  else+    return UV_EINVAL;++  return uv__tcp_connect(req, handle, addr, addrlen, cb);+}+++int uv_udp_send(uv_udp_send_t* req,+                uv_udp_t* handle,+                const uv_buf_t bufs[],+                unsigned int nbufs,+                const struct sockaddr* addr,+                uv_udp_send_cb send_cb) {+  unsigned int addrlen;++  if (handle->type != UV_UDP)+    return UV_EINVAL;++  if (addr->sa_family == AF_INET)+    addrlen = sizeof(struct sockaddr_in);+  else if (addr->sa_family == AF_INET6)+    addrlen = sizeof(struct sockaddr_in6);+  else+    return UV_EINVAL;++  return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);+}+++int uv_udp_try_send(uv_udp_t* handle,+                    const uv_buf_t bufs[],+                    unsigned int nbufs,+                    const struct sockaddr* addr) {+  unsigned int addrlen;++  if (handle->type != UV_UDP)+    return UV_EINVAL;++  if (addr->sa_family == AF_INET)+    addrlen = sizeof(struct sockaddr_in);+  else if (addr->sa_family == AF_INET6)+    addrlen = sizeof(struct sockaddr_in6);+  else+    return UV_EINVAL;++  return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);+}+++int uv_udp_recv_start(uv_udp_t* handle,+                      uv_alloc_cb alloc_cb,+                      uv_udp_recv_cb recv_cb) {+  if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL)+    return UV_EINVAL;+  else+    return uv__udp_recv_start(handle, alloc_cb, recv_cb);+}+++int uv_udp_recv_stop(uv_udp_t* handle) {+  if (handle->type != UV_UDP)+    return UV_EINVAL;+  else+    return uv__udp_recv_stop(handle);+}+++void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {+  QUEUE queue;+  QUEUE* q;+  uv_handle_t* h;++  QUEUE_MOVE(&loop->handle_queue, &queue);+  while (!QUEUE_EMPTY(&queue)) {+    q = QUEUE_HEAD(&queue);+    h = QUEUE_DATA(q, uv_handle_t, handle_queue);++    QUEUE_REMOVE(q);+    QUEUE_INSERT_TAIL(&loop->handle_queue, q);++    if (h->flags & UV_HANDLE_INTERNAL) continue;+    walk_cb(h, arg);+  }+}+++static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {+  const char* type;+  QUEUE* q;+  uv_handle_t* h;++  if (loop == NULL)+    loop = uv_default_loop();++  QUEUE_FOREACH(q, &loop->handle_queue) {+    h = QUEUE_DATA(q, uv_handle_t, handle_queue);++    if (only_active && !uv__is_active(h))+      continue;++    switch (h->type) {+#define X(uc, lc) case UV_##uc: type = #lc; break;+      UV_HANDLE_TYPE_MAP(X)+#undef X+      default: type = "<unknown>";+    }++    fprintf(stream,+            "[%c%c%c] %-8s %p\n",+            "R-"[!(h->flags & UV_HANDLE_REF)],+            "A-"[!(h->flags & UV_HANDLE_ACTIVE)],+            "I-"[!(h->flags & UV_HANDLE_INTERNAL)],+            type,+            (void*)h);+  }+}+++void uv_print_all_handles(uv_loop_t* loop, FILE* stream) {+  uv__print_handles(loop, 0, stream);+}+++void uv_print_active_handles(uv_loop_t* loop, FILE* stream) {+  uv__print_handles(loop, 1, stream);+}+++void uv_ref(uv_handle_t* handle) {+  uv__handle_ref(handle);+}+++void uv_unref(uv_handle_t* handle) {+  uv__handle_unref(handle);+}+++int uv_has_ref(const uv_handle_t* handle) {+  return uv__has_ref(handle);+}+++void uv_stop(uv_loop_t* loop) {+  loop->stop_flag = 1;+}+++uint64_t uv_now(const uv_loop_t* loop) {+  return loop->time;+}++++size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {+  unsigned int i;+  size_t bytes;++  bytes = 0;+  for (i = 0; i < nbufs; i++)+    bytes += (size_t) bufs[i].len;++  return bytes;+}++int uv_recv_buffer_size(uv_handle_t* handle, int* value) {+  return uv__socket_sockopt(handle, SO_RCVBUF, value);+}++int uv_send_buffer_size(uv_handle_t* handle, int *value) {+  return uv__socket_sockopt(handle, SO_SNDBUF, value);+}++int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) {+  size_t required_len;++  if (!uv__is_active(handle)) {+    *size = 0;+    return UV_EINVAL;+  }++  required_len = strlen(handle->path);+  if (required_len >= *size) {+    *size = required_len + 1;+    return UV_ENOBUFS;+  }++  memcpy(buffer, handle->path, required_len);+  *size = required_len;+  buffer[required_len] = '\0';++  return 0;+}++/* The windows implementation does not have the same structure layout as+ * the unix implementation (nbufs is not directly inside req but is+ * contained in a nested union/struct) so this function locates it.+*/+static unsigned int* uv__get_nbufs(uv_fs_t* req) {+#ifdef _WIN32+  return &req->fs.info.nbufs;+#else+  return &req->nbufs;+#endif+}++/* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows+ * systems. So, the memory should be released using free(). On Windows,+ * uv__malloc() is used, so use uv__free() to free memory.+*/+#ifdef _WIN32+# define uv__fs_scandir_free uv__free+#else+# define uv__fs_scandir_free free+#endif++void uv__fs_scandir_cleanup(uv_fs_t* req) {+  uv__dirent_t** dents;++  unsigned int* nbufs = uv__get_nbufs(req);++  dents = req->ptr;+  if (*nbufs > 0 && *nbufs != (unsigned int) req->result)+    (*nbufs)--;+  for (; *nbufs < (unsigned int) req->result; (*nbufs)++)+    uv__fs_scandir_free(dents[*nbufs]);++  uv__fs_scandir_free(req->ptr);+  req->ptr = NULL;+}+++int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {+  uv__dirent_t** dents;+  uv__dirent_t* dent;+  unsigned int* nbufs;++  /* Check to see if req passed */+  if (req->result < 0)+    return req->result;++  /* Ptr will be null if req was canceled or no files found */+  if (!req->ptr)+    return UV_EOF;++  nbufs = uv__get_nbufs(req);+  assert(nbufs);++  dents = req->ptr;++  /* Free previous entity */+  if (*nbufs > 0)+    uv__fs_scandir_free(dents[*nbufs - 1]);++  /* End was already reached */+  if (*nbufs == (unsigned int) req->result) {+    uv__fs_scandir_free(dents);+    req->ptr = NULL;+    return UV_EOF;+  }++  dent = dents[(*nbufs)++];++  ent->name = dent->d_name;+#ifdef HAVE_DIRENT_TYPES+  switch (dent->d_type) {+    case UV__DT_DIR:+      ent->type = UV_DIRENT_DIR;+      break;+    case UV__DT_FILE:+      ent->type = UV_DIRENT_FILE;+      break;+    case UV__DT_LINK:+      ent->type = UV_DIRENT_LINK;+      break;+    case UV__DT_FIFO:+      ent->type = UV_DIRENT_FIFO;+      break;+    case UV__DT_SOCKET:+      ent->type = UV_DIRENT_SOCKET;+      break;+    case UV__DT_CHAR:+      ent->type = UV_DIRENT_CHAR;+      break;+    case UV__DT_BLOCK:+      ent->type = UV_DIRENT_BLOCK;+      break;+    default:+      ent->type = UV_DIRENT_UNKNOWN;+  }+#else+  ent->type = UV_DIRENT_UNKNOWN;+#endif++  return 0;+}+++int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) {+  va_list ap;+  int err;++  va_start(ap, option);+  /* Any platform-agnostic options should be handled here. */+  err = uv__loop_configure(loop, option, ap);+  va_end(ap);++  return err;+}+++static uv_loop_t default_loop_struct;+static uv_loop_t* default_loop_ptr;+++uv_loop_t* uv_default_loop(void) {+  if (default_loop_ptr != NULL)+    return default_loop_ptr;++  if (uv_loop_init(&default_loop_struct))+    return NULL;++  default_loop_ptr = &default_loop_struct;+  return default_loop_ptr;+}+++uv_loop_t* uv_loop_new(void) {+  uv_loop_t* loop;++  loop = uv__malloc(sizeof(*loop));+  if (loop == NULL)+    return NULL;++  if (uv_loop_init(loop)) {+    uv__free(loop);+    return NULL;+  }++  return loop;+}+++int uv_loop_close(uv_loop_t* loop) {+  QUEUE* q;+  uv_handle_t* h;+#ifndef NDEBUG+  void* saved_data;+#endif++  if (uv__has_active_reqs(loop))+    return UV_EBUSY;++  QUEUE_FOREACH(q, &loop->handle_queue) {+    h = QUEUE_DATA(q, uv_handle_t, handle_queue);+    if (!(h->flags & UV_HANDLE_INTERNAL))+      return UV_EBUSY;+  }++  uv__loop_close(loop);++#ifndef NDEBUG+  saved_data = loop->data;+  memset(loop, -1, sizeof(*loop));+  loop->data = saved_data;+#endif+  if (loop == default_loop_ptr)+    default_loop_ptr = NULL;++  return 0;+}+++void uv_loop_delete(uv_loop_t* loop) {+  uv_loop_t* default_loop;+  int err;++  default_loop = default_loop_ptr;++  err = uv_loop_close(loop);+  (void) err;    /* Squelch compiler warnings. */+  assert(err == 0);+  if (loop != default_loop)+    uv__free(loop);+}
+ third_party/libuv/src/uv-common.h view
@@ -0,0 +1,315 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++/*+ * This file is private to libuv. It provides common functionality to both+ * Windows and Unix backends.+ */++#ifndef UV_COMMON_H_+#define UV_COMMON_H_++#include <assert.h>+#include <stdarg.h>+#include <stddef.h>++#if defined(_MSC_VER) && _MSC_VER < 1600+# include "uv/stdint-msvc2008.h"+#else+# include <stdint.h>+#endif++#include "uv.h"+#include "uv/tree.h"+#include "queue.h"+#include "strscpy.h"++#if EDOM > 0+# define UV__ERR(x) (-(x))+#else+# define UV__ERR(x) (x)+#endif++#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900+extern int snprintf(char*, size_t, const char*, ...);+#endif++#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))++#define container_of(ptr, type, member) \+  ((type *) ((char *) (ptr) - offsetof(type, member)))++#define STATIC_ASSERT(expr)                                                   \+  void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)])++/* Handle flags. Some flags are specific to Windows or UNIX. */+enum {+  /* Used by all handles. */+  UV_HANDLE_CLOSING                     = 0x00000001,+  UV_HANDLE_CLOSED                      = 0x00000002,+  UV_HANDLE_ACTIVE                      = 0x00000004,+  UV_HANDLE_REF                         = 0x00000008,+  UV_HANDLE_INTERNAL                    = 0x00000010,+  UV_HANDLE_ENDGAME_QUEUED              = 0x00000020,++  /* Used by streams. */+  UV_HANDLE_LISTENING                   = 0x00000040,+  UV_HANDLE_CONNECTION                  = 0x00000080,+  UV_HANDLE_SHUTTING                    = 0x00000100,+  UV_HANDLE_SHUT                        = 0x00000200,+  UV_HANDLE_READ_PARTIAL                = 0x00000400,+  UV_HANDLE_READ_EOF                    = 0x00000800,++  /* Used by streams and UDP handles. */+  UV_HANDLE_READING                     = 0x00001000,+  UV_HANDLE_BOUND                       = 0x00002000,+  UV_HANDLE_READABLE                    = 0x00004000,+  UV_HANDLE_WRITABLE                    = 0x00008000,+  UV_HANDLE_READ_PENDING                = 0x00010000,+  UV_HANDLE_SYNC_BYPASS_IOCP            = 0x00020000,+  UV_HANDLE_ZERO_READ                   = 0x00040000,+  UV_HANDLE_EMULATE_IOCP                = 0x00080000,+  UV_HANDLE_BLOCKING_WRITES             = 0x00100000,+  UV_HANDLE_CANCELLATION_PENDING        = 0x00200000,++  /* Used by uv_tcp_t and uv_udp_t handles */+  UV_HANDLE_IPV6                        = 0x00400000,++  /* Only used by uv_tcp_t handles. */+  UV_HANDLE_TCP_NODELAY                 = 0x01000000,+  UV_HANDLE_TCP_KEEPALIVE               = 0x02000000,+  UV_HANDLE_TCP_SINGLE_ACCEPT           = 0x04000000,+  UV_HANDLE_TCP_ACCEPT_STATE_CHANGING   = 0x08000000,+  UV_HANDLE_TCP_SOCKET_CLOSED           = 0x10000000,+  UV_HANDLE_SHARED_TCP_SOCKET           = 0x20000000,++  /* Only used by uv_udp_t handles. */+  UV_HANDLE_UDP_PROCESSING              = 0x01000000,++  /* Only used by uv_pipe_t handles. */+  UV_HANDLE_NON_OVERLAPPED_PIPE         = 0x01000000,+  UV_HANDLE_PIPESERVER                  = 0x02000000,++  /* Only used by uv_tty_t handles. */+  UV_HANDLE_TTY_READABLE                = 0x01000000,+  UV_HANDLE_TTY_RAW                     = 0x02000000,+  UV_HANDLE_TTY_SAVED_POSITION          = 0x04000000,+  UV_HANDLE_TTY_SAVED_ATTRIBUTES        = 0x08000000,++  /* Only used by uv_signal_t handles. */+  UV_SIGNAL_ONE_SHOT_DISPATCHED         = 0x01000000,+  UV_SIGNAL_ONE_SHOT                    = 0x02000000,++  /* Only used by uv_poll_t handles. */+  UV_HANDLE_POLL_SLOW                   = 0x01000000+};++int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);++void uv__loop_close(uv_loop_t* loop);++int uv__tcp_bind(uv_tcp_t* tcp,+                 const struct sockaddr* addr,+                 unsigned int addrlen,+                 unsigned int flags);++int uv__tcp_connect(uv_connect_t* req,+                   uv_tcp_t* handle,+                   const struct sockaddr* addr,+                   unsigned int addrlen,+                   uv_connect_cb cb);++int uv__udp_bind(uv_udp_t* handle,+                 const struct sockaddr* addr,+                 unsigned int  addrlen,+                 unsigned int flags);++int uv__udp_send(uv_udp_send_t* req,+                 uv_udp_t* handle,+                 const uv_buf_t bufs[],+                 unsigned int nbufs,+                 const struct sockaddr* addr,+                 unsigned int addrlen,+                 uv_udp_send_cb send_cb);++int uv__udp_try_send(uv_udp_t* handle,+                     const uv_buf_t bufs[],+                     unsigned int nbufs,+                     const struct sockaddr* addr,+                     unsigned int addrlen);++int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloccb,+                       uv_udp_recv_cb recv_cb);++int uv__udp_recv_stop(uv_udp_t* handle);++void uv__fs_poll_close(uv_fs_poll_t* handle);++int uv__getaddrinfo_translate_error(int sys_err);    /* EAI_* error. */++enum uv__work_kind {+  UV__WORK_CPU,+  UV__WORK_FAST_IO,+  UV__WORK_SLOW_IO+};++void uv__work_submit(uv_loop_t* loop,+                     struct uv__work *w,+                     enum uv__work_kind kind,+                     void (*work)(struct uv__work *w),+                     void (*done)(struct uv__work *w, int status));++void uv__work_done(uv_async_t* handle);++size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs);++int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);++void uv__fs_scandir_cleanup(uv_fs_t* req);++int uv__next_timeout(const uv_loop_t* loop);+void uv__run_timers(uv_loop_t* loop);+void uv__timer_close(uv_timer_t* handle);++#define uv__has_active_reqs(loop)                                             \+  ((loop)->active_reqs.count > 0)++#define uv__req_register(loop, req)                                           \+  do {                                                                        \+    (loop)->active_reqs.count++;                                              \+  }                                                                           \+  while (0)++#define uv__req_unregister(loop, req)                                         \+  do {                                                                        \+    assert(uv__has_active_reqs(loop));                                        \+    (loop)->active_reqs.count--;                                              \+  }                                                                           \+  while (0)++#define uv__has_active_handles(loop)                                          \+  ((loop)->active_handles > 0)++#define uv__active_handle_add(h)                                              \+  do {                                                                        \+    (h)->loop->active_handles++;                                              \+  }                                                                           \+  while (0)++#define uv__active_handle_rm(h)                                               \+  do {                                                                        \+    (h)->loop->active_handles--;                                              \+  }                                                                           \+  while (0)++#define uv__is_active(h)                                                      \+  (((h)->flags & UV_HANDLE_ACTIVE) != 0)++#define uv__is_closing(h)                                                     \+  (((h)->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED)) != 0)++#define uv__handle_start(h)                                                   \+  do {                                                                        \+    if (((h)->flags & UV_HANDLE_ACTIVE) != 0) break;                          \+    (h)->flags |= UV_HANDLE_ACTIVE;                                           \+    if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_add(h);          \+  }                                                                           \+  while (0)++#define uv__handle_stop(h)                                                    \+  do {                                                                        \+    if (((h)->flags & UV_HANDLE_ACTIVE) == 0) break;                          \+    (h)->flags &= ~UV_HANDLE_ACTIVE;                                          \+    if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_rm(h);           \+  }                                                                           \+  while (0)++#define uv__handle_ref(h)                                                     \+  do {                                                                        \+    if (((h)->flags & UV_HANDLE_REF) != 0) break;                             \+    (h)->flags |= UV_HANDLE_REF;                                              \+    if (((h)->flags & UV_HANDLE_CLOSING) != 0) break;                         \+    if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_add(h);       \+  }                                                                           \+  while (0)++#define uv__handle_unref(h)                                                   \+  do {                                                                        \+    if (((h)->flags & UV_HANDLE_REF) == 0) break;                             \+    (h)->flags &= ~UV_HANDLE_REF;                                             \+    if (((h)->flags & UV_HANDLE_CLOSING) != 0) break;                         \+    if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_rm(h);        \+  }                                                                           \+  while (0)++#define uv__has_ref(h)                                                        \+  (((h)->flags & UV_HANDLE_REF) != 0)++#if defined(_WIN32)+# define uv__handle_platform_init(h) ((h)->u.fd = -1)+#else+# define uv__handle_platform_init(h) ((h)->next_closing = NULL)+#endif++#define uv__handle_init(loop_, h, type_)                                      \+  do {                                                                        \+    (h)->loop = (loop_);                                                      \+    (h)->type = (type_);                                                      \+    (h)->flags = UV_HANDLE_REF;  /* Ref the loop when active. */              \+    QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue);            \+    uv__handle_platform_init(h);                                              \+  }                                                                           \+  while (0)++/* Note: uses an open-coded version of SET_REQ_SUCCESS() because of+ * a circular dependency between src/uv-common.h and src/win/internal.h.+ */+#if defined(_WIN32)+# define UV_REQ_INIT(req, typ)                                                \+  do {                                                                        \+    (req)->type = (typ);                                                      \+    (req)->u.io.overlapped.Internal = 0;  /* SET_REQ_SUCCESS() */             \+  }                                                                           \+  while (0)+#else+# define UV_REQ_INIT(req, typ)                                                \+  do {                                                                        \+    (req)->type = (typ);                                                      \+  }                                                                           \+  while (0)+#endif++#define uv__req_init(loop, req, typ)                                          \+  do {                                                                        \+    UV_REQ_INIT(req, typ);                                                    \+    uv__req_register(loop, req);                                              \+  }                                                                           \+  while (0)++/* Allocator prototypes */+void *uv__calloc(size_t count, size_t size);+char *uv__strdup(const char* s);+char *uv__strndup(const char* s, size_t n);+void* uv__malloc(size_t size);+void uv__free(void* ptr);+void* uv__realloc(void* ptr, size_t size);++#endif /* UV_COMMON_H_ */
+ third_party/libuv/src/uv-data-getter-setters.c view
@@ -0,0 +1,98 @@+#include "uv.h"++const char* uv_handle_type_name(uv_handle_type type) {+  switch (type) {+#define XX(uc,lc) case UV_##uc: return #lc;+  UV_HANDLE_TYPE_MAP(XX)+#undef XX+  case UV_FILE: return "file";+  case UV_HANDLE_TYPE_MAX:+  case UV_UNKNOWN_HANDLE: return NULL;+  }+  return NULL;+}++uv_handle_type uv_handle_get_type(const uv_handle_t* handle) {+  return handle->type;+}++void* uv_handle_get_data(const uv_handle_t* handle) {+  return handle->data;+}++uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle) {+  return handle->loop;+}++void uv_handle_set_data(uv_handle_t* handle, void* data) {+  handle->data = data;+}++const char* uv_req_type_name(uv_req_type type) {+  switch (type) {+#define XX(uc,lc) case UV_##uc: return #lc;+  UV_REQ_TYPE_MAP(XX)+#undef XX+  case UV_REQ_TYPE_MAX:+  case UV_UNKNOWN_REQ:+  default: /* UV_REQ_TYPE_PRIVATE */+     return NULL;+  }+  return NULL;+}++uv_req_type uv_req_get_type(const uv_req_t* req) {+  return req->type;+}++void* uv_req_get_data(const uv_req_t* req) {+  return req->data;+}++void uv_req_set_data(uv_req_t* req, void* data) {+  req->data = data;+}++size_t uv_stream_get_write_queue_size(const uv_stream_t* stream) {+  return stream->write_queue_size;+}++size_t uv_udp_get_send_queue_size(const uv_udp_t* handle) {+  return handle->send_queue_size;+}++size_t uv_udp_get_send_queue_count(const uv_udp_t* handle) {+  return handle->send_queue_count;+}++uv_pid_t uv_process_get_pid(const uv_process_t* proc) {+  return proc->pid;+}++uv_fs_type uv_fs_get_type(const uv_fs_t* req) {+  return req->fs_type;+}++ssize_t uv_fs_get_result(const uv_fs_t* req) {+  return req->result;+}++void* uv_fs_get_ptr(const uv_fs_t* req) {+  return req->ptr;+}++const char* uv_fs_get_path(const uv_fs_t* req) {+  return req->path;+}++uv_stat_t* uv_fs_get_statbuf(uv_fs_t* req) {+  return &req->statbuf;+}++void* uv_loop_get_data(const uv_loop_t* loop) {+  return loop->data;+}++void uv_loop_set_data(uv_loop_t* loop, void* data) {+  loop->data = data;+}
+ third_party/libuv/src/version.c view
@@ -0,0 +1,45 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include "uv.h"++#define UV_STRINGIFY(v) UV_STRINGIFY_HELPER(v)+#define UV_STRINGIFY_HELPER(v) #v++#define UV_VERSION_STRING_BASE  UV_STRINGIFY(UV_VERSION_MAJOR) "." \+                                UV_STRINGIFY(UV_VERSION_MINOR) "." \+                                UV_STRINGIFY(UV_VERSION_PATCH)++#if UV_VERSION_IS_RELEASE+# define UV_VERSION_STRING  UV_VERSION_STRING_BASE+#else+# define UV_VERSION_STRING  UV_VERSION_STRING_BASE "-" UV_VERSION_SUFFIX+#endif+++unsigned int uv_version(void) {+  return UV_VERSION_HEX;+}+++const char* uv_version_string(void) {+  return UV_VERSION_STRING;+}
+ third_party/libuv/src/win/async.c view
@@ -0,0 +1,98 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>++#include "uv.h"+#include "internal.h"+#include "atomicops-inl.h"+#include "handle-inl.h"+#include "req-inl.h"+++void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) {+  if (handle->flags & UV_HANDLE_CLOSING &&+      !handle->async_sent) {+    assert(!(handle->flags & UV_HANDLE_CLOSED));+    uv__handle_close(handle);+  }+}+++int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {+  uv_req_t* req;++  uv__handle_init(loop, (uv_handle_t*) handle, UV_ASYNC);+  handle->async_sent = 0;+  handle->async_cb = async_cb;++  req = &handle->async_req;+  UV_REQ_INIT(req, UV_WAKEUP);+  req->data = handle;++  uv__handle_start(handle);++  return 0;+}+++void uv_async_close(uv_loop_t* loop, uv_async_t* handle) {+  if (!((uv_async_t*)handle)->async_sent) {+    uv_want_endgame(loop, (uv_handle_t*) handle);+  }++  uv__handle_closing(handle);+}+++int uv_async_send(uv_async_t* handle) {+  uv_loop_t* loop = handle->loop;++  if (handle->type != UV_ASYNC) {+    /* Can't set errno because that's not thread-safe. */+    return -1;+  }++  /* The user should make sure never to call uv_async_send to a closing or+   * closed handle. */+  assert(!(handle->flags & UV_HANDLE_CLOSING));++  if (!uv__atomic_exchange_set(&handle->async_sent)) {+    POST_COMPLETION_FOR_REQ(loop, &handle->async_req);+  }++  return 0;+}+++void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,+    uv_req_t* req) {+  assert(handle->type == UV_ASYNC);+  assert(req->type == UV_WAKEUP);++  handle->async_sent = 0;++  if (handle->flags & UV_HANDLE_CLOSING) {+    uv_want_endgame(loop, (uv_handle_t*)handle);+  } else if (handle->async_cb != NULL) {+    handle->async_cb(handle);+  }+}
+ third_party/libuv/src/win/atomicops-inl.h view
@@ -0,0 +1,57 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#ifndef UV_WIN_ATOMICOPS_INL_H_+#define UV_WIN_ATOMICOPS_INL_H_++#include "uv.h"+#include "internal.h"+++/* Atomic set operation on char */+#ifdef _MSC_VER /* MSVC */++/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less+ * efficient than InterlockedExchange, but InterlockedExchange8 does not exist,+ * and interlocked operations on larger targets might require the target to be+ * aligned. */+#pragma intrinsic(_InterlockedOr8)++static char INLINE uv__atomic_exchange_set(char volatile* target) {+  return _InterlockedOr8(target, 1);+}++#else /* GCC */++/* Mingw-32 version, hopefully this works for 64-bit gcc as well. */+static inline char uv__atomic_exchange_set(char volatile* target) {+  const char one = 1;+  char old_value;+  __asm__ __volatile__ ("lock xchgb %0, %1\n\t"+                        : "=r"(old_value), "=m"(*target)+                        : "0"(one), "m"(*target)+                        : "memory");+  return old_value;+}++#endif++#endif /* UV_WIN_ATOMICOPS_INL_H_ */
+ third_party/libuv/src/win/core.c view
@@ -0,0 +1,625 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <errno.h>+#include <limits.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)+#include <crtdbg.h>+#endif++#include "uv.h"+#include "internal.h"+#include "queue.h"+#include "handle-inl.h"+#include "heap-inl.h"+#include "req-inl.h"++/* uv_once initialization guards */+static uv_once_t uv_init_guard_ = UV_ONCE_INIT;+++#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR))+/* Our crt debug report handler allows us to temporarily disable asserts+ * just for the current thread.+ */++UV_THREAD_LOCAL int uv__crt_assert_enabled = TRUE;++static int uv__crt_dbg_report_handler(int report_type, char *message, int *ret_val) {+  if (uv__crt_assert_enabled || report_type != _CRT_ASSERT)+    return FALSE;++  if (ret_val) {+    /* Set ret_val to 0 to continue with normal execution.+     * Set ret_val to 1 to trigger a breakpoint.+    */++    if(IsDebuggerPresent())+      *ret_val = 1;+    else+      *ret_val = 0;+  }++  /* Don't call _CrtDbgReport. */+  return TRUE;+}+#else+UV_THREAD_LOCAL int uv__crt_assert_enabled = FALSE;+#endif+++#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800+static void uv__crt_invalid_parameter_handler(const wchar_t* expression,+    const wchar_t* function, const wchar_t * file, unsigned int line,+    uintptr_t reserved) {+  /* No-op. */+}+#endif++static uv_loop_t** uv__loops;+static int uv__loops_size;+static int uv__loops_capacity;+#define UV__LOOPS_CHUNK_SIZE 8+static uv_mutex_t uv__loops_lock;++static void uv__loops_init(void) {+  uv_mutex_init(&uv__loops_lock);+}++static int uv__loops_add(uv_loop_t* loop) {+  uv_loop_t** new_loops;+  int new_capacity, i;++  uv_mutex_lock(&uv__loops_lock);++  if (uv__loops_size == uv__loops_capacity) {+    new_capacity = uv__loops_capacity + UV__LOOPS_CHUNK_SIZE;+    new_loops = uv__realloc(uv__loops, sizeof(uv_loop_t*) * new_capacity);+    if (!new_loops)+      goto failed_loops_realloc;+    uv__loops = new_loops;+    for (i = uv__loops_capacity; i < new_capacity; ++i)+      uv__loops[i] = NULL;+    uv__loops_capacity = new_capacity;+  }+  uv__loops[uv__loops_size] = loop;+  ++uv__loops_size;++  uv_mutex_unlock(&uv__loops_lock);+  return 0;++failed_loops_realloc:+  uv_mutex_unlock(&uv__loops_lock);+  return ERROR_OUTOFMEMORY;+}++static void uv__loops_remove(uv_loop_t* loop) {+  int loop_index;+  int smaller_capacity;+  uv_loop_t** new_loops;++  uv_mutex_lock(&uv__loops_lock);++  for (loop_index = 0; loop_index < uv__loops_size; ++loop_index) {+    if (uv__loops[loop_index] == loop)+      break;+  }+  /* If loop was not found, ignore */+  if (loop_index == uv__loops_size)+    goto loop_removed;++  uv__loops[loop_index] = uv__loops[uv__loops_size - 1];+  uv__loops[uv__loops_size - 1] = NULL;+  --uv__loops_size;++  if (uv__loops_size == 0) {+    uv__loops_capacity = 0;+    uv__free(uv__loops);+    uv__loops = NULL;+    goto loop_removed;+  }++  /* If we didn't grow to big skip downsizing */+  if (uv__loops_capacity < 4 * UV__LOOPS_CHUNK_SIZE)+    goto loop_removed;++  /* Downsize only if more than half of buffer is free */+  smaller_capacity = uv__loops_capacity / 2;+  if (uv__loops_size >= smaller_capacity)+    goto loop_removed;+  new_loops = uv__realloc(uv__loops, sizeof(uv_loop_t*) * smaller_capacity);+  if (!new_loops)+    goto loop_removed;+  uv__loops = new_loops;+  uv__loops_capacity = smaller_capacity;++loop_removed:+  uv_mutex_unlock(&uv__loops_lock);+}++void uv__wake_all_loops(void) {+  int i;+  uv_loop_t* loop;++  uv_mutex_lock(&uv__loops_lock);+  for (i = 0; i < uv__loops_size; ++i) {+    loop = uv__loops[i];+    assert(loop);+    if (loop->iocp != INVALID_HANDLE_VALUE)+      PostQueuedCompletionStatus(loop->iocp, 0, 0, NULL);+  }+  uv_mutex_unlock(&uv__loops_lock);+}++static void uv_init(void) {+  /* Tell Windows that we will handle critical errors. */+  SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |+               SEM_NOOPENFILEERRORBOX);++  /* Tell the CRT to not exit the application when an invalid parameter is+   * passed. The main issue is that invalid FDs will trigger this behavior.+   */+#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800+  _set_invalid_parameter_handler(uv__crt_invalid_parameter_handler);+#endif++  /* We also need to setup our debug report handler because some CRT+   * functions (eg _get_osfhandle) raise an assert when called with invalid+   * FDs even though they return the proper error code in the release build.+   */+#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR))+  _CrtSetReportHook(uv__crt_dbg_report_handler);+#endif++  /* Initialize tracking of all uv loops */+  uv__loops_init();++  /* Fetch winapi function pointers. This must be done first because other+   * initialization code might need these function pointers to be loaded.+   */+  uv_winapi_init();++  /* Initialize winsock */+  uv_winsock_init();++  /* Initialize FS */+  uv_fs_init();++  /* Initialize signal stuff */+  uv_signals_init();++  /* Initialize console */+  uv_console_init();++  /* Initialize utilities */+  uv__util_init();++  /* Initialize system wakeup detection */+  uv__init_detect_system_wakeup();+}+++int uv_loop_init(uv_loop_t* loop) {+  struct heap* timer_heap;+  int err;++  /* Initialize libuv itself first */+  uv__once_init();++  /* Create an I/O completion port */+  loop->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);+  if (loop->iocp == NULL)+    return uv_translate_sys_error(GetLastError());++  /* To prevent uninitialized memory access, loop->time must be initialized+   * to zero before calling uv_update_time for the first time.+   */+  loop->time = 0;+  uv_update_time(loop);++  QUEUE_INIT(&loop->wq);+  QUEUE_INIT(&loop->handle_queue);+  loop->active_reqs.count = 0;+  loop->active_handles = 0;++  loop->pending_reqs_tail = NULL;++  loop->endgame_handles = NULL;++  loop->timer_heap = timer_heap = uv__malloc(sizeof(*timer_heap));+  if (timer_heap == NULL) {+    err = UV_ENOMEM;+    goto fail_timers_alloc;+  }++  heap_init(timer_heap);++  loop->check_handles = NULL;+  loop->prepare_handles = NULL;+  loop->idle_handles = NULL;++  loop->next_prepare_handle = NULL;+  loop->next_check_handle = NULL;+  loop->next_idle_handle = NULL;++  memset(&loop->poll_peer_sockets, 0, sizeof loop->poll_peer_sockets);++  loop->active_tcp_streams = 0;+  loop->active_udp_streams = 0;++  loop->timer_counter = 0;+  loop->stop_flag = 0;++  err = uv_mutex_init(&loop->wq_mutex);+  if (err)+    goto fail_mutex_init;++  err = uv_async_init(loop, &loop->wq_async, uv__work_done);+  if (err)+    goto fail_async_init;++  uv__handle_unref(&loop->wq_async);+  loop->wq_async.flags |= UV_HANDLE_INTERNAL;++  err = uv__loops_add(loop);+  if (err)+    goto fail_async_init;++  return 0;++fail_async_init:+  uv_mutex_destroy(&loop->wq_mutex);++fail_mutex_init:+  uv__free(timer_heap);+  loop->timer_heap = NULL;++fail_timers_alloc:+  CloseHandle(loop->iocp);+  loop->iocp = INVALID_HANDLE_VALUE;++  return err;+}+++void uv_update_time(uv_loop_t* loop) {+  uint64_t new_time = uv__hrtime(1000);+  assert(new_time >= loop->time);+  loop->time = new_time;+}+++void uv__once_init(void) {+  uv_once(&uv_init_guard_, uv_init);+}+++void uv__loop_close(uv_loop_t* loop) {+  size_t i;++  uv__loops_remove(loop);++  /* close the async handle without needing an extra loop iteration */+  assert(!loop->wq_async.async_sent);+  loop->wq_async.close_cb = NULL;+  uv__handle_closing(&loop->wq_async);+  uv__handle_close(&loop->wq_async);++  for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) {+    SOCKET sock = loop->poll_peer_sockets[i];+    if (sock != 0 && sock != INVALID_SOCKET)+      closesocket(sock);+  }++  uv_mutex_lock(&loop->wq_mutex);+  assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!");+  assert(!uv__has_active_reqs(loop));+  uv_mutex_unlock(&loop->wq_mutex);+  uv_mutex_destroy(&loop->wq_mutex);++  uv__free(loop->timer_heap);+  loop->timer_heap = NULL;++  CloseHandle(loop->iocp);+}+++int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {+  return UV_ENOSYS;+}+++int uv_backend_fd(const uv_loop_t* loop) {+  return -1;+}+++int uv_loop_fork(uv_loop_t* loop) {+  return UV_ENOSYS;+}+++int uv_backend_timeout(const uv_loop_t* loop) {+  if (loop->stop_flag != 0)+    return 0;++  if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))+    return 0;++  if (loop->pending_reqs_tail)+    return 0;++  if (loop->endgame_handles)+    return 0;++  if (loop->idle_handles)+    return 0;++  return uv__next_timeout(loop);+}+++static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) {+  DWORD bytes;+  ULONG_PTR key;+  OVERLAPPED* overlapped;+  uv_req_t* req;+  int repeat;+  uint64_t timeout_time;++  timeout_time = loop->time + timeout;++  for (repeat = 0; ; repeat++) {+    GetQueuedCompletionStatus(loop->iocp,+                              &bytes,+                              &key,+                              &overlapped,+                              timeout);++    if (overlapped) {+      /* Package was dequeued */+      req = uv_overlapped_to_req(overlapped);+      uv_insert_pending_req(loop, req);++      /* Some time might have passed waiting for I/O,+       * so update the loop time here.+       */+      uv_update_time(loop);+    } else if (GetLastError() != WAIT_TIMEOUT) {+      /* Serious error */+      uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");+    } else if (timeout > 0) {+      /* GetQueuedCompletionStatus can occasionally return a little early.+       * Make sure that the desired timeout target time is reached.+       */+      uv_update_time(loop);+      if (timeout_time > loop->time) {+        timeout = (DWORD)(timeout_time - loop->time);+        /* The first call to GetQueuedCompletionStatus should return very+         * close to the target time and the second should reach it, but+         * this is not stated in the documentation. To make sure a busy+         * loop cannot happen, the timeout is increased exponentially+         * starting on the third round.+         */+        timeout += repeat ? (1 << (repeat - 1)) : 0;+        continue;+      }+    }+    break;+  }+}+++static void uv__poll(uv_loop_t* loop, DWORD timeout) {+  BOOL success;+  uv_req_t* req;+  OVERLAPPED_ENTRY overlappeds[128];+  ULONG count;+  ULONG i;+  int repeat;+  uint64_t timeout_time;++  timeout_time = loop->time + timeout;++  for (repeat = 0; ; repeat++) {+    success = GetQueuedCompletionStatusEx(loop->iocp,+                                          overlappeds,+                                          ARRAY_SIZE(overlappeds),+                                          &count,+                                          timeout,+                                          FALSE);++    if (success) {+      for (i = 0; i < count; i++) {+        /* Package was dequeued, but see if it is not a empty package+         * meant only to wake us up.+         */+        if (overlappeds[i].lpOverlapped) {+          req = uv_overlapped_to_req(overlappeds[i].lpOverlapped);+          uv_insert_pending_req(loop, req);+        }+      }++      /* Some time might have passed waiting for I/O,+       * so update the loop time here.+       */+      uv_update_time(loop);+    } else if (GetLastError() != WAIT_TIMEOUT) {+      /* Serious error */+      uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx");+    } else if (timeout > 0) {+      /* GetQueuedCompletionStatus can occasionally return a little early.+       * Make sure that the desired timeout target time is reached.+       */+      uv_update_time(loop);+      if (timeout_time > loop->time) {+        timeout = (DWORD)(timeout_time - loop->time);+        /* The first call to GetQueuedCompletionStatus should return very+         * close to the target time and the second should reach it, but+         * this is not stated in the documentation. To make sure a busy+         * loop cannot happen, the timeout is increased exponentially+         * starting on the third round.+         */+        timeout += repeat ? (1 << (repeat - 1)) : 0;+        continue;+      }+    }+    break;+  }+}+++static int uv__loop_alive(const uv_loop_t* loop) {+  return uv__has_active_handles(loop) ||+         uv__has_active_reqs(loop) ||+         loop->endgame_handles != NULL;+}+++int uv_loop_alive(const uv_loop_t* loop) {+    return uv__loop_alive(loop);+}+++int uv_run(uv_loop_t *loop, uv_run_mode mode) {+  DWORD timeout;+  int r;+  int ran_pending;++  r = uv__loop_alive(loop);+  if (!r)+    uv_update_time(loop);++  while (r != 0 && loop->stop_flag == 0) {+    uv_update_time(loop);+    uv__run_timers(loop);++    ran_pending = uv_process_reqs(loop);+    uv_idle_invoke(loop);+    uv_prepare_invoke(loop);++    timeout = 0;+    if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)+      timeout = uv_backend_timeout(loop);++    if (pGetQueuedCompletionStatusEx)+      uv__poll(loop, timeout);+    else+      uv__poll_wine(loop, timeout);+++    uv_check_invoke(loop);+    uv_process_endgames(loop);++    if (mode == UV_RUN_ONCE) {+      /* UV_RUN_ONCE implies forward progress: at least one callback must have+       * been invoked when it returns. uv__io_poll() can return without doing+       * I/O (meaning: no callbacks) when its timeout expires - which means we+       * have pending timers that satisfy the forward progress constraint.+       *+       * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from+       * the check.+       */+      uv__run_timers(loop);+    }++    r = uv__loop_alive(loop);+    if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)+      break;+  }++  /* The if statement lets the compiler compile it to a conditional store.+   * Avoids dirtying a cache line.+   */+  if (loop->stop_flag != 0)+    loop->stop_flag = 0;++  return r;+}+++int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {+  uv_os_fd_t fd_out;++  switch (handle->type) {+  case UV_TCP:+    fd_out = (uv_os_fd_t)((uv_tcp_t*) handle)->socket;+    break;++  case UV_NAMED_PIPE:+    fd_out = ((uv_pipe_t*) handle)->handle;+    break;++  case UV_TTY:+    fd_out = ((uv_tty_t*) handle)->handle;+    break;++  case UV_UDP:+    fd_out = (uv_os_fd_t)((uv_udp_t*) handle)->socket;+    break;++  case UV_POLL:+    fd_out = (uv_os_fd_t)((uv_poll_t*) handle)->socket;+    break;++  default:+    return UV_EINVAL;+  }++  if (uv_is_closing(handle) || fd_out == INVALID_HANDLE_VALUE)+    return UV_EBADF;++  *fd = fd_out;+  return 0;+}+++int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {+  int r;+  int len;+  SOCKET socket;++  if (handle == NULL || value == NULL)+    return UV_EINVAL;++  if (handle->type == UV_TCP)+    socket = ((uv_tcp_t*) handle)->socket;+  else if (handle->type == UV_UDP)+    socket = ((uv_udp_t*) handle)->socket;+  else+    return UV_ENOTSUP;++  len = sizeof(*value);++  if (*value == 0)+    r = getsockopt(socket, SOL_SOCKET, optname, (char*) value, &len);+  else+    r = setsockopt(socket, SOL_SOCKET, optname, (const char*) value, len);++  if (r == SOCKET_ERROR)+    return uv_translate_sys_error(WSAGetLastError());++  return 0;+}
+ third_party/libuv/src/win/detect-wakeup.c view
@@ -0,0 +1,35 @@+#include "uv.h"+#include "internal.h"+#include "winapi.h"++static void uv__register_system_resume_callback(void);++void uv__init_detect_system_wakeup(void) {+  /* Try registering system power event callback. This is the cleanest+   * method, but it will only work on Win8 and above.+   */+  uv__register_system_resume_callback();+}++static ULONG CALLBACK uv__system_resume_callback(PVOID Context,+                                                 ULONG Type,+                                                 PVOID Setting) {+  if (Type == PBT_APMRESUMESUSPEND || Type == PBT_APMRESUMEAUTOMATIC)+    uv__wake_all_loops();++  return 0;+}++static void uv__register_system_resume_callback(void) {+  _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS recipient;+  _HPOWERNOTIFY registration_handle;++  if (pPowerRegisterSuspendResumeNotification == NULL)+    return;++  recipient.Callback = uv__system_resume_callback;+  recipient.Context = NULL;+  (*pPowerRegisterSuspendResumeNotification)(DEVICE_NOTIFY_CALLBACK,+                                             &recipient,+                                             &registration_handle);+}
+ third_party/libuv/src/win/dl.c view
@@ -0,0 +1,136 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include "uv.h"+#include "internal.h"++static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno);+++int uv_dlopen(const char* filename, uv_lib_t* lib) {+  WCHAR filename_w[32768];++  lib->handle = NULL;+  lib->errmsg = NULL;++  if (!MultiByteToWideChar(CP_UTF8,+                           0,+                           filename,+                           -1,+                           filename_w,+                           ARRAY_SIZE(filename_w))) {+    return uv__dlerror(lib, filename, GetLastError());+  }++  lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);+  if (lib->handle == NULL) {+    return uv__dlerror(lib, filename, GetLastError());+  }++  return 0;+}+++void uv_dlclose(uv_lib_t* lib) {+  if (lib->errmsg) {+    LocalFree((void*)lib->errmsg);+    lib->errmsg = NULL;+  }++  if (lib->handle) {+    /* Ignore errors. No good way to signal them without leaking memory. */+    FreeLibrary(lib->handle);+    lib->handle = NULL;+  }+}+++int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {+  /* Cast though integer to suppress pedantic warning about forbidden cast. */+  *ptr = (void*)(uintptr_t) GetProcAddress(lib->handle, name);+  return uv__dlerror(lib, "", *ptr ? 0 : GetLastError());+}+++const char* uv_dlerror(const uv_lib_t* lib) {+  return lib->errmsg ? lib->errmsg : "no error";+}+++static void uv__format_fallback_error(uv_lib_t* lib, int errorno){+  static const CHAR fallback_error[] = "error: %1!d!";+  DWORD_PTR args[1];+  args[0] = (DWORD_PTR) errorno;++  FormatMessageA(FORMAT_MESSAGE_FROM_STRING |+                 FORMAT_MESSAGE_ARGUMENT_ARRAY |+                 FORMAT_MESSAGE_ALLOCATE_BUFFER,+                 fallback_error, 0, 0,+                 (LPSTR) &lib->errmsg,+                 0, (va_list*) args);+}++++static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno) {+  DWORD_PTR arg;+  DWORD res;+  char* msg;++  if (lib->errmsg) {+    LocalFree(lib->errmsg);+    lib->errmsg = NULL;+  }++  if (errorno == 0)+    return 0;++  res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |+                       FORMAT_MESSAGE_FROM_SYSTEM |+                       FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,+                       MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),+                       (LPSTR) &lib->errmsg, 0, NULL);++  if (!res && (GetLastError() == ERROR_MUI_FILE_NOT_FOUND ||+               GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND)) {+    res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |+                         FORMAT_MESSAGE_FROM_SYSTEM |+                         FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,+                         0, (LPSTR) &lib->errmsg, 0, NULL);+  }++  if (res && errorno == ERROR_BAD_EXE_FORMAT && strstr(lib->errmsg, "%1")) {+    msg = lib->errmsg;+    lib->errmsg = NULL;+    arg = (DWORD_PTR) filename;+    res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |+                         FORMAT_MESSAGE_ARGUMENT_ARRAY |+                         FORMAT_MESSAGE_FROM_STRING,+                         msg,+                         0, 0, (LPSTR) &lib->errmsg, 0, (va_list*) &arg);+    LocalFree(msg);+  }++  if (!res)+    uv__format_fallback_error(lib, errorno);++  return -1;+}
+ third_party/libuv/src/win/error.c view
@@ -0,0 +1,171 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <errno.h>+#include <stdio.h>+#include <string.h>+#include <stdlib.h>++#include "uv.h"+#include "internal.h"+++/*+ * Display an error message and abort the event loop.+ */+void uv_fatal_error(const int errorno, const char* syscall) {+  char* buf = NULL;+  const char* errmsg;++  FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |+      FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,+      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buf, 0, NULL);++  if (buf) {+    errmsg = buf;+  } else {+    errmsg = "Unknown error";+  }++  /* FormatMessage messages include a newline character already, so don't add+   * another. */+  if (syscall) {+    fprintf(stderr, "%s: (%d) %s", syscall, errorno, errmsg);+  } else {+    fprintf(stderr, "(%d) %s", errorno, errmsg);+  }++  if (buf) {+    LocalFree(buf);+  }++  DebugBreak();+  abort();+}+++int uv_translate_sys_error(int sys_errno) {+  if (sys_errno <= 0) {+    return sys_errno;  /* If < 0 then it's already a libuv error. */+  }++  switch (sys_errno) {+    case ERROR_NOACCESS:                    return UV_EACCES;+    case WSAEACCES:                         return UV_EACCES;+    case ERROR_ELEVATION_REQUIRED:          return UV_EACCES;+    case ERROR_ADDRESS_ALREADY_ASSOCIATED:  return UV_EADDRINUSE;+    case WSAEADDRINUSE:                     return UV_EADDRINUSE;+    case WSAEADDRNOTAVAIL:                  return UV_EADDRNOTAVAIL;+    case WSAEAFNOSUPPORT:                   return UV_EAFNOSUPPORT;+    case WSAEWOULDBLOCK:                    return UV_EAGAIN;+    case WSAEALREADY:                       return UV_EALREADY;+    case ERROR_INVALID_FLAGS:               return UV_EBADF;+    case ERROR_INVALID_HANDLE:              return UV_EBADF;+    case ERROR_LOCK_VIOLATION:              return UV_EBUSY;+    case ERROR_PIPE_BUSY:                   return UV_EBUSY;+    case ERROR_SHARING_VIOLATION:           return UV_EBUSY;+    case ERROR_OPERATION_ABORTED:           return UV_ECANCELED;+    case WSAEINTR:                          return UV_ECANCELED;+    case ERROR_NO_UNICODE_TRANSLATION:      return UV_ECHARSET;+    case ERROR_CONNECTION_ABORTED:          return UV_ECONNABORTED;+    case WSAECONNABORTED:                   return UV_ECONNABORTED;+    case ERROR_CONNECTION_REFUSED:          return UV_ECONNREFUSED;+    case WSAECONNREFUSED:                   return UV_ECONNREFUSED;+    case ERROR_NETNAME_DELETED:             return UV_ECONNRESET;+    case WSAECONNRESET:                     return UV_ECONNRESET;+    case ERROR_ALREADY_EXISTS:              return UV_EEXIST;+    case ERROR_FILE_EXISTS:                 return UV_EEXIST;+    case ERROR_BUFFER_OVERFLOW:             return UV_EFAULT;+    case WSAEFAULT:                         return UV_EFAULT;+    case ERROR_HOST_UNREACHABLE:            return UV_EHOSTUNREACH;+    case WSAEHOSTUNREACH:                   return UV_EHOSTUNREACH;+    case ERROR_INSUFFICIENT_BUFFER:         return UV_EINVAL;+    case ERROR_INVALID_DATA:                return UV_EINVAL;+    case ERROR_INVALID_PARAMETER:           return UV_EINVAL;+    case ERROR_SYMLINK_NOT_SUPPORTED:       return UV_EINVAL;+    case WSAEINVAL:                         return UV_EINVAL;+    case WSAEPFNOSUPPORT:                   return UV_EINVAL;+    case WSAESOCKTNOSUPPORT:                return UV_EINVAL;+    case ERROR_BEGINNING_OF_MEDIA:          return UV_EIO;+    case ERROR_BUS_RESET:                   return UV_EIO;+    case ERROR_CRC:                         return UV_EIO;+    case ERROR_DEVICE_DOOR_OPEN:            return UV_EIO;+    case ERROR_DEVICE_REQUIRES_CLEANING:    return UV_EIO;+    case ERROR_DISK_CORRUPT:                return UV_EIO;+    case ERROR_EOM_OVERFLOW:                return UV_EIO;+    case ERROR_FILEMARK_DETECTED:           return UV_EIO;+    case ERROR_GEN_FAILURE:                 return UV_EIO;+    case ERROR_INVALID_BLOCK_LENGTH:        return UV_EIO;+    case ERROR_IO_DEVICE:                   return UV_EIO;+    case ERROR_NO_DATA_DETECTED:            return UV_EIO;+    case ERROR_NO_SIGNAL_SENT:              return UV_EIO;+    case ERROR_OPEN_FAILED:                 return UV_EIO;+    case ERROR_SETMARK_DETECTED:            return UV_EIO;+    case ERROR_SIGNAL_REFUSED:              return UV_EIO;+    case WSAEISCONN:                        return UV_EISCONN;+    case ERROR_CANT_RESOLVE_FILENAME:       return UV_ELOOP;+    case ERROR_TOO_MANY_OPEN_FILES:         return UV_EMFILE;+    case WSAEMFILE:                         return UV_EMFILE;+    case WSAEMSGSIZE:                       return UV_EMSGSIZE;+    case ERROR_FILENAME_EXCED_RANGE:        return UV_ENAMETOOLONG;+    case ERROR_NETWORK_UNREACHABLE:         return UV_ENETUNREACH;+    case WSAENETUNREACH:                    return UV_ENETUNREACH;+    case WSAENOBUFS:                        return UV_ENOBUFS;+    case ERROR_BAD_PATHNAME:                return UV_ENOENT;+    case ERROR_DIRECTORY:                   return UV_ENOENT;+    case ERROR_FILE_NOT_FOUND:              return UV_ENOENT;+    case ERROR_INVALID_NAME:                return UV_ENOENT;+    case ERROR_INVALID_DRIVE:               return UV_ENOENT;+    case ERROR_INVALID_REPARSE_DATA:        return UV_ENOENT;+    case ERROR_MOD_NOT_FOUND:               return UV_ENOENT;+    case ERROR_PATH_NOT_FOUND:              return UV_ENOENT;+    case WSAHOST_NOT_FOUND:                 return UV_ENOENT;+    case WSANO_DATA:                        return UV_ENOENT;+    case ERROR_NOT_ENOUGH_MEMORY:           return UV_ENOMEM;+    case ERROR_OUTOFMEMORY:                 return UV_ENOMEM;+    case ERROR_CANNOT_MAKE:                 return UV_ENOSPC;+    case ERROR_DISK_FULL:                   return UV_ENOSPC;+    case ERROR_EA_TABLE_FULL:               return UV_ENOSPC;+    case ERROR_END_OF_MEDIA:                return UV_ENOSPC;+    case ERROR_HANDLE_DISK_FULL:            return UV_ENOSPC;+    case ERROR_NOT_CONNECTED:               return UV_ENOTCONN;+    case WSAENOTCONN:                       return UV_ENOTCONN;+    case ERROR_DIR_NOT_EMPTY:               return UV_ENOTEMPTY;+    case WSAENOTSOCK:                       return UV_ENOTSOCK;+    case ERROR_NOT_SUPPORTED:               return UV_ENOTSUP;+    case ERROR_BROKEN_PIPE:                 return UV_EOF;+    case ERROR_ACCESS_DENIED:               return UV_EPERM;+    case ERROR_PRIVILEGE_NOT_HELD:          return UV_EPERM;+    case ERROR_BAD_PIPE:                    return UV_EPIPE;+    case ERROR_NO_DATA:                     return UV_EPIPE;+    case ERROR_PIPE_NOT_CONNECTED:          return UV_EPIPE;+    case WSAESHUTDOWN:                      return UV_EPIPE;+    case WSAEPROTONOSUPPORT:                return UV_EPROTONOSUPPORT;+    case ERROR_WRITE_PROTECT:               return UV_EROFS;+    case ERROR_SEM_TIMEOUT:                 return UV_ETIMEDOUT;+    case WSAETIMEDOUT:                      return UV_ETIMEDOUT;+    case ERROR_NOT_SAME_DEVICE:             return UV_EXDEV;+    case ERROR_INVALID_FUNCTION:            return UV_EISDIR;+    case ERROR_META_EXPANSION_TOO_LONG:     return UV_E2BIG;+    default:                                return UV_UNKNOWN;+  }+}
+ third_party/libuv/src/win/fs-event.c view
@@ -0,0 +1,589 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <errno.h>+#include <stdio.h>+#include <string.h>++#include "uv.h"+#include "internal.h"+#include "handle-inl.h"+#include "req-inl.h"+++const unsigned int uv_directory_watcher_buffer_size = 4096;+++static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop,+    uv_fs_event_t* handle) {+  assert(handle->dir_handle != INVALID_HANDLE_VALUE);+  assert(!handle->req_pending);++  memset(&(handle->req.u.io.overlapped), 0,+         sizeof(handle->req.u.io.overlapped));+  if (!ReadDirectoryChangesW(handle->dir_handle,+                             handle->buffer,+                             uv_directory_watcher_buffer_size,+                             (handle->flags & UV_FS_EVENT_RECURSIVE) ? TRUE : FALSE,+                             FILE_NOTIFY_CHANGE_FILE_NAME      |+                               FILE_NOTIFY_CHANGE_DIR_NAME     |+                               FILE_NOTIFY_CHANGE_ATTRIBUTES   |+                               FILE_NOTIFY_CHANGE_SIZE         |+                               FILE_NOTIFY_CHANGE_LAST_WRITE   |+                               FILE_NOTIFY_CHANGE_LAST_ACCESS  |+                               FILE_NOTIFY_CHANGE_CREATION     |+                               FILE_NOTIFY_CHANGE_SECURITY,+                             NULL,+                             &handle->req.u.io.overlapped,+                             NULL)) {+    /* Make this req pending reporting an error. */+    SET_REQ_ERROR(&handle->req, GetLastError());+    uv_insert_pending_req(loop, (uv_req_t*)&handle->req);+  }++  handle->req_pending = 1;+}++static void uv_relative_path(const WCHAR* filename,+                             const WCHAR* dir,+                             WCHAR** relpath) {+  size_t relpathlen;+  size_t filenamelen = wcslen(filename);+  size_t dirlen = wcslen(dir);+  assert(!_wcsnicmp(filename, dir, dirlen));+  if (dirlen > 0 && dir[dirlen - 1] == '\\')+    dirlen--;+  relpathlen = filenamelen - dirlen - 1;+  *relpath = uv__malloc((relpathlen + 1) * sizeof(WCHAR));+  if (!*relpath)+    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+  wcsncpy(*relpath, filename + dirlen + 1, relpathlen);+  (*relpath)[relpathlen] = L'\0';+}++static int uv_split_path(const WCHAR* filename, WCHAR** dir,+    WCHAR** file) {+  size_t len, i;++  if (filename == NULL) {+    if (dir != NULL)+      *dir = NULL;+    *file = NULL;+    return 0;+  }++  len = wcslen(filename);+  i = len;+  while (i > 0 && filename[--i] != '\\' && filename[i] != '/');++  if (i == 0) {+    if (dir) {+      *dir = (WCHAR*)uv__malloc((MAX_PATH + 1) * sizeof(WCHAR));+      if (!*dir) {+        uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+      }++      if (!GetCurrentDirectoryW(MAX_PATH, *dir)) {+        uv__free(*dir);+        *dir = NULL;+        return -1;+      }+    }++    *file = wcsdup(filename);+  } else {+    if (dir) {+      *dir = (WCHAR*)uv__malloc((i + 2) * sizeof(WCHAR));+      if (!*dir) {+        uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+      }+      wcsncpy(*dir, filename, i + 1);+      (*dir)[i + 1] = L'\0';+    }++    *file = (WCHAR*)uv__malloc((len - i) * sizeof(WCHAR));+    if (!*file) {+      uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+    }+    wcsncpy(*file, filename + i + 1, len - i - 1);+    (*file)[len - i - 1] = L'\0';+  }++  return 0;+}+++int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {+  uv__handle_init(loop, (uv_handle_t*) handle, UV_FS_EVENT);+  handle->dir_handle = INVALID_HANDLE_VALUE;+  handle->buffer = NULL;+  handle->req_pending = 0;+  handle->filew = NULL;+  handle->short_filew = NULL;+  handle->dirw = NULL;++  UV_REQ_INIT(&handle->req, UV_FS_EVENT_REQ);+  handle->req.data = handle;++  return 0;+}+++int uv_fs_event_start(uv_fs_event_t* handle,+                      uv_fs_event_cb cb,+                      const char* path,+                      unsigned int flags) {+  int name_size, is_path_dir, size;+  DWORD attr, last_error;+  WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL;+  WCHAR short_path_buffer[MAX_PATH];+  WCHAR* short_path, *long_path;++  if (uv__is_active(handle))+    return UV_EINVAL;++  handle->cb = cb;+  handle->path = uv__strdup(path);+  if (!handle->path) {+    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+  }++  uv__handle_start(handle);++  /* Convert name to UTF16. */++  name_size = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0) *+              sizeof(WCHAR);+  pathw = (WCHAR*)uv__malloc(name_size);+  if (!pathw) {+    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+  }++  if (!MultiByteToWideChar(CP_UTF8,+                           0,+                           path,+                           -1,+                           pathw,+                           name_size / sizeof(WCHAR))) {+    return uv_translate_sys_error(GetLastError());+  }++  /* Determine whether path is a file or a directory. */+  attr = GetFileAttributesW(pathw);+  if (attr == INVALID_FILE_ATTRIBUTES) {+    last_error = GetLastError();+    goto error;+  }++  is_path_dir = (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;++  if (is_path_dir) {+     /* path is a directory, so that's the directory that we will watch. */++    /* Convert to long path. */+    size = GetLongPathNameW(pathw, NULL, 0);++    if (size) {+      long_path = (WCHAR*)uv__malloc(size * sizeof(WCHAR));+      if (!long_path) {+        uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+      }++      size = GetLongPathNameW(pathw, long_path, size);+      if (size) {+        long_path[size] = '\0';+      } else {+        uv__free(long_path);+        long_path = NULL;+      }++      if (long_path) {+        uv__free(pathw);+        pathw = long_path;+      }+    }++    dir_to_watch = pathw;+  } else {+    /*+     * path is a file.  So we split path into dir & file parts, and+     * watch the dir directory.+     */++    /* Convert to short path. */+    if (GetShortPathNameW(pathw,+                          short_path_buffer,+                          ARRAY_SIZE(short_path_buffer))) {+      short_path = short_path_buffer;+    } else {+      short_path = NULL;+    }++    if (uv_split_path(pathw, &dir, &handle->filew) != 0) {+      last_error = GetLastError();+      goto error;+    }++    if (uv_split_path(short_path, NULL, &handle->short_filew) != 0) {+      last_error = GetLastError();+      goto error;+    }++    dir_to_watch = dir;+    uv__free(pathw);+    pathw = NULL;+  }++  handle->dir_handle = CreateFileW(dir_to_watch,+                                   FILE_LIST_DIRECTORY,+                                   FILE_SHARE_READ | FILE_SHARE_DELETE |+                                     FILE_SHARE_WRITE,+                                   NULL,+                                   OPEN_EXISTING,+                                   FILE_FLAG_BACKUP_SEMANTICS |+                                     FILE_FLAG_OVERLAPPED,+                                   NULL);++  if (dir) {+    uv__free(dir);+    dir = NULL;+  }++  if (handle->dir_handle == INVALID_HANDLE_VALUE) {+    last_error = GetLastError();+    goto error;+  }++  if (CreateIoCompletionPort(handle->dir_handle,+                             handle->loop->iocp,+                             (ULONG_PTR)handle,+                             0) == NULL) {+    last_error = GetLastError();+    goto error;+  }++  if (!handle->buffer) {+    handle->buffer = (char*)uv__malloc(uv_directory_watcher_buffer_size);+  }+  if (!handle->buffer) {+    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+  }++  memset(&(handle->req.u.io.overlapped), 0,+         sizeof(handle->req.u.io.overlapped));++  if (!ReadDirectoryChangesW(handle->dir_handle,+                             handle->buffer,+                             uv_directory_watcher_buffer_size,+                             (flags & UV_FS_EVENT_RECURSIVE) ? TRUE : FALSE,+                             FILE_NOTIFY_CHANGE_FILE_NAME      |+                               FILE_NOTIFY_CHANGE_DIR_NAME     |+                               FILE_NOTIFY_CHANGE_ATTRIBUTES   |+                               FILE_NOTIFY_CHANGE_SIZE         |+                               FILE_NOTIFY_CHANGE_LAST_WRITE   |+                               FILE_NOTIFY_CHANGE_LAST_ACCESS  |+                               FILE_NOTIFY_CHANGE_CREATION     |+                               FILE_NOTIFY_CHANGE_SECURITY,+                             NULL,+                             &handle->req.u.io.overlapped,+                             NULL)) {+    last_error = GetLastError();+    goto error;+  }++  assert(is_path_dir ? pathw != NULL : pathw == NULL);+  handle->dirw = pathw;+  handle->req_pending = 1;+  return 0;++error:+  if (handle->path) {+    uv__free(handle->path);+    handle->path = NULL;+  }++  if (handle->filew) {+    uv__free(handle->filew);+    handle->filew = NULL;+  }++  if (handle->short_filew) {+    uv__free(handle->short_filew);+    handle->short_filew = NULL;+  }++  uv__free(pathw);++  if (handle->dir_handle != INVALID_HANDLE_VALUE) {+    CloseHandle(handle->dir_handle);+    handle->dir_handle = INVALID_HANDLE_VALUE;+  }++  if (handle->buffer) {+    uv__free(handle->buffer);+    handle->buffer = NULL;+  }++  if (uv__is_active(handle))+    uv__handle_stop(handle);++  return uv_translate_sys_error(last_error);+}+++int uv_fs_event_stop(uv_fs_event_t* handle) {+  if (!uv__is_active(handle))+    return 0;++  if (handle->dir_handle != INVALID_HANDLE_VALUE) {+    CloseHandle(handle->dir_handle);+    handle->dir_handle = INVALID_HANDLE_VALUE;+  }++  uv__handle_stop(handle);++  if (handle->filew) {+    uv__free(handle->filew);+    handle->filew = NULL;+  }++  if (handle->short_filew) {+    uv__free(handle->short_filew);+    handle->short_filew = NULL;+  }++  if (handle->path) {+    uv__free(handle->path);+    handle->path = NULL;+  }++  if (handle->dirw) {+    uv__free(handle->dirw);+    handle->dirw = NULL;+  }++  return 0;+}+++static int file_info_cmp(WCHAR* str, WCHAR* file_name, size_t file_name_len) {+  size_t str_len;++  if (str == NULL)+    return -1;++  str_len = wcslen(str);++  /*+    Since we only care about equality, return early if the strings+    aren't the same length+  */+  if (str_len != (file_name_len / sizeof(WCHAR)))+    return -1;++  return _wcsnicmp(str, file_name, str_len);+}+++void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,+    uv_fs_event_t* handle) {+  FILE_NOTIFY_INFORMATION* file_info;+  int err, sizew, size;+  char* filename = NULL;+  WCHAR* filenamew = NULL;+  WCHAR* long_filenamew = NULL;+  DWORD offset = 0;++  assert(req->type == UV_FS_EVENT_REQ);+  assert(handle->req_pending);+  handle->req_pending = 0;++  /* Don't report any callbacks if:+   * - We're closing, just push the handle onto the endgame queue+   * - We are not active, just ignore the callback+   */+  if (!uv__is_active(handle)) {+    if (handle->flags & UV_HANDLE_CLOSING) {+      uv_want_endgame(loop, (uv_handle_t*) handle);+    }+    return;+  }++  file_info = (FILE_NOTIFY_INFORMATION*)(handle->buffer + offset);++  if (REQ_SUCCESS(req)) {+    if (req->u.io.overlapped.InternalHigh > 0) {+      do {+        file_info = (FILE_NOTIFY_INFORMATION*)((char*)file_info + offset);+        assert(!filename);+        assert(!filenamew);+        assert(!long_filenamew);++        /*+         * Fire the event only if we were asked to watch a directory,+         * or if the filename filter matches.+         */+        if (handle->dirw ||+            file_info_cmp(handle->filew,+                          file_info->FileName,+                          file_info->FileNameLength) == 0 ||+            file_info_cmp(handle->short_filew,+                          file_info->FileName,+                          file_info->FileNameLength) == 0) {++          if (handle->dirw) {+            /*+             * We attempt to resolve the long form of the file name explicitly.+             * We only do this for file names that might still exist on disk.+             * If this fails, we use the name given by ReadDirectoryChangesW.+             * This may be the long form or the 8.3 short name in some cases.+             */+            if (file_info->Action != FILE_ACTION_REMOVED &&+              file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) {+              /* Construct a full path to the file. */+              size = wcslen(handle->dirw) ++                file_info->FileNameLength / sizeof(WCHAR) + 2;++              filenamew = (WCHAR*)uv__malloc(size * sizeof(WCHAR));+              if (!filenamew) {+                uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+              }++              _snwprintf(filenamew, size, L"%s\\%.*s", handle->dirw,+                file_info->FileNameLength / (DWORD)sizeof(WCHAR),+                file_info->FileName);++              filenamew[size - 1] = L'\0';++              /* Convert to long name. */+              size = GetLongPathNameW(filenamew, NULL, 0);++              if (size) {+                long_filenamew = (WCHAR*)uv__malloc(size * sizeof(WCHAR));+                if (!long_filenamew) {+                  uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+                }++                size = GetLongPathNameW(filenamew, long_filenamew, size);+                if (size) {+                  long_filenamew[size] = '\0';+                } else {+                  uv__free(long_filenamew);+                  long_filenamew = NULL;+                }+              }++              uv__free(filenamew);++              if (long_filenamew) {+                /* Get the file name out of the long path. */+                uv_relative_path(long_filenamew,+                                 handle->dirw,+                                 &filenamew);+                uv__free(long_filenamew);+                long_filenamew = filenamew;+                sizew = -1;+              } else {+                /* We couldn't get the long filename, use the one reported. */+                filenamew = file_info->FileName;+                sizew = file_info->FileNameLength / sizeof(WCHAR);+              }+            } else {+              /*+               * Removed or renamed events cannot be resolved to the long form.+               * We therefore use the name given by ReadDirectoryChangesW.+               * This may be the long form or the 8.3 short name in some cases.+               */+              filenamew = file_info->FileName;+              sizew = file_info->FileNameLength / sizeof(WCHAR);+            }+          } else {+            /* We already have the long name of the file, so just use it. */+            filenamew = handle->filew;+            sizew = -1;+          }++          /* Convert the filename to utf8. */+          uv__convert_utf16_to_utf8(filenamew, sizew, &filename);++          switch (file_info->Action) {+            case FILE_ACTION_ADDED:+            case FILE_ACTION_REMOVED:+            case FILE_ACTION_RENAMED_OLD_NAME:+            case FILE_ACTION_RENAMED_NEW_NAME:+              handle->cb(handle, filename, UV_RENAME, 0);+              break;++            case FILE_ACTION_MODIFIED:+              handle->cb(handle, filename, UV_CHANGE, 0);+              break;+          }++          uv__free(filename);+          filename = NULL;+          uv__free(long_filenamew);+          long_filenamew = NULL;+          filenamew = NULL;+        }++        offset = file_info->NextEntryOffset;+      } while (offset && !(handle->flags & UV_HANDLE_CLOSING));+    } else {+      handle->cb(handle, NULL, UV_CHANGE, 0);+    }+  } else {+    err = GET_REQ_ERROR(req);+    handle->cb(handle, NULL, 0, uv_translate_sys_error(err));+  }++  if (!(handle->flags & UV_HANDLE_CLOSING)) {+    uv_fs_event_queue_readdirchanges(loop, handle);+  } else {+    uv_want_endgame(loop, (uv_handle_t*)handle);+  }+}+++void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) {+  uv_fs_event_stop(handle);++  uv__handle_closing(handle);++  if (!handle->req_pending) {+    uv_want_endgame(loop, (uv_handle_t*)handle);+  }++}+++void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {+  if ((handle->flags & UV_HANDLE_CLOSING) && !handle->req_pending) {+    assert(!(handle->flags & UV_HANDLE_CLOSED));++    if (handle->buffer) {+      uv__free(handle->buffer);+      handle->buffer = NULL;+    }++    uv__handle_close(handle);+  }+}
+ third_party/libuv/src/win/fs.c view
@@ -0,0 +1,2518 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <stdlib.h>+#include <direct.h>+#include <errno.h>+#include <fcntl.h>+#include <io.h>+#include <limits.h>+#include <sys/stat.h>+#include <sys/utime.h>+#include <stdio.h>++#include "uv.h"+#include "internal.h"+#include "req-inl.h"+#include "handle-inl.h"++#include <wincrypt.h>+++#define UV_FS_FREE_PATHS         0x0002+#define UV_FS_FREE_PTR           0x0008+#define UV_FS_CLEANEDUP          0x0010+++#define INIT(subtype)                                                         \+  do {                                                                        \+    if (req == NULL)                                                          \+      return UV_EINVAL;                                                       \+    uv_fs_req_init(loop, req, subtype, cb);                                   \+  }                                                                           \+  while (0)++#define POST                                                                  \+  do {                                                                        \+    if (cb != NULL) {                                                         \+      uv__req_register(loop, req);                                            \+      uv__work_submit(loop,                                                   \+                      &req->work_req,                                         \+                      UV__WORK_FAST_IO,                                       \+                      uv__fs_work,                                            \+                      uv__fs_done);                                           \+      return 0;                                                               \+    } else {                                                                  \+      uv__fs_work(&req->work_req);                                            \+      return req->result;                                                     \+    }                                                                         \+  }                                                                           \+  while (0)++#define SET_REQ_RESULT(req, result_value)                                   \+  do {                                                                      \+    req->result = (result_value);                                           \+    if (req->result == -1) {                                                \+      req->sys_errno_ = _doserrno;                                          \+      req->result = uv_translate_sys_error(req->sys_errno_);                \+    }                                                                       \+  } while (0)++#define SET_REQ_WIN32_ERROR(req, sys_errno)                                 \+  do {                                                                      \+    req->sys_errno_ = (sys_errno);                                          \+    req->result = uv_translate_sys_error(req->sys_errno_);                  \+  } while (0)++#define SET_REQ_UV_ERROR(req, uv_errno, sys_errno)                          \+  do {                                                                      \+    req->result = (uv_errno);                                               \+    req->sys_errno_ = (sys_errno);                                          \+  } while (0)++#define VERIFY_FD(fd, req)                                                  \+  if (fd == -1) {                                                           \+    req->result = UV_EBADF;                                                 \+    req->sys_errno_ = ERROR_INVALID_HANDLE;                                 \+    return;                                                                 \+  }++#define MILLIONu (1000U * 1000U)+#define BILLIONu (1000U * 1000U * 1000U)++#define FILETIME_TO_UINT(filetime)                                          \+   (*((uint64_t*) &(filetime)) - (uint64_t) 116444736 * BILLIONu)++#define FILETIME_TO_TIME_T(filetime)                                        \+   (FILETIME_TO_UINT(filetime) / (10u * MILLIONu))++#define FILETIME_TO_TIME_NS(filetime, secs)                                 \+   ((FILETIME_TO_UINT(filetime) - (secs * (uint64_t) 10 * MILLIONu)) * 100U)++#define FILETIME_TO_TIMESPEC(ts, filetime)                                  \+   do {                                                                     \+     (ts).tv_sec = (long) FILETIME_TO_TIME_T(filetime);                     \+     (ts).tv_nsec = (long) FILETIME_TO_TIME_NS(filetime, (ts).tv_sec);      \+   } while(0)++#define TIME_T_TO_FILETIME(time, filetime_ptr)                              \+  do {                                                                      \+    uint64_t bigtime = ((uint64_t) ((time) * (uint64_t) 10 * MILLIONu)) +   \+                       (uint64_t) 116444736 * BILLIONu;                     \+    (filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF;                   \+    (filetime_ptr)->dwHighDateTime = bigtime >> 32;                         \+  } while(0)++#define IS_SLASH(c) ((c) == L'\\' || (c) == L'/')+#define IS_LETTER(c) (((c) >= L'a' && (c) <= L'z') || \+  ((c) >= L'A' && (c) <= L'Z'))++const WCHAR JUNCTION_PREFIX[] = L"\\??\\";+const WCHAR JUNCTION_PREFIX_LEN = 4;++const WCHAR LONG_PATH_PREFIX[] = L"\\\\?\\";+const WCHAR LONG_PATH_PREFIX_LEN = 4;++const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\";+const WCHAR UNC_PATH_PREFIX_LEN = 8;++static int uv__file_symlink_usermode_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;++void uv_fs_init(void) {+  _fmode = _O_BINARY;+}+++INLINE static int fs__capture_path(uv_fs_t* req, const char* path,+    const char* new_path, const int copy_path) {+  char* buf;+  char* pos;+  ssize_t buf_sz = 0, path_len = 0, pathw_len = 0, new_pathw_len = 0;++  /* new_path can only be set if path is also set. */+  assert(new_path == NULL || path != NULL);++  if (path != NULL) {+    pathw_len = MultiByteToWideChar(CP_UTF8,+                                    0,+                                    path,+                                    -1,+                                    NULL,+                                    0);+    if (pathw_len == 0) {+      return GetLastError();+    }++    buf_sz += pathw_len * sizeof(WCHAR);+  }++  if (path != NULL && copy_path) {+    path_len = 1 + strlen(path);+    buf_sz += path_len;+  }++  if (new_path != NULL) {+    new_pathw_len = MultiByteToWideChar(CP_UTF8,+                                        0,+                                        new_path,+                                        -1,+                                        NULL,+                                        0);+    if (new_pathw_len == 0) {+      return GetLastError();+    }++    buf_sz += new_pathw_len * sizeof(WCHAR);+  }+++  if (buf_sz == 0) {+    req->file.pathw = NULL;+    req->fs.info.new_pathw = NULL;+    req->path = NULL;+    return 0;+  }++  buf = (char*) uv__malloc(buf_sz);+  if (buf == NULL) {+    return ERROR_OUTOFMEMORY;+  }++  pos = buf;++  if (path != NULL) {+    DWORD r = MultiByteToWideChar(CP_UTF8,+                                  0,+                                  path,+                                  -1,+                                  (WCHAR*) pos,+                                  pathw_len);+    assert(r == (DWORD) pathw_len);+    req->file.pathw = (WCHAR*) pos;+    pos += r * sizeof(WCHAR);+  } else {+    req->file.pathw = NULL;+  }++  if (new_path != NULL) {+    DWORD r = MultiByteToWideChar(CP_UTF8,+                                  0,+                                  new_path,+                                  -1,+                                  (WCHAR*) pos,+                                  new_pathw_len);+    assert(r == (DWORD) new_pathw_len);+    req->fs.info.new_pathw = (WCHAR*) pos;+    pos += r * sizeof(WCHAR);+  } else {+    req->fs.info.new_pathw = NULL;+  }++  req->path = path;+  if (path != NULL && copy_path) {+    memcpy(pos, path, path_len);+    assert(path_len == buf_sz - (pos - buf));+    req->path = pos;+  }++  req->flags |= UV_FS_FREE_PATHS;++  return 0;+}++++INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,+    uv_fs_type fs_type, const uv_fs_cb cb) {+  uv__once_init();+  UV_REQ_INIT(req, UV_FS);+  req->loop = loop;+  req->flags = 0;+  req->fs_type = fs_type;+  req->result = 0;+  req->ptr = NULL;+  req->path = NULL;+  req->cb = cb;+  memset(&req->fs, 0, sizeof(req->fs));+}+++static int fs__wide_to_utf8(WCHAR* w_source_ptr,+                               DWORD w_source_len,+                               char** target_ptr,+                               uint64_t* target_len_ptr) {+  int r;+  int target_len;+  char* target;+  target_len = WideCharToMultiByte(CP_UTF8,+                                   0,+                                   w_source_ptr,+                                   w_source_len,+                                   NULL,+                                   0,+                                   NULL,+                                   NULL);++  if (target_len == 0) {+    return -1;+  }++  if (target_len_ptr != NULL) {+    *target_len_ptr = target_len;+  }++  if (target_ptr == NULL) {+    return 0;+  }++  target = uv__malloc(target_len + 1);+  if (target == NULL) {+    SetLastError(ERROR_OUTOFMEMORY);+    return -1;+  }++  r = WideCharToMultiByte(CP_UTF8,+                          0,+                          w_source_ptr,+                          w_source_len,+                          target,+                          target_len,+                          NULL,+                          NULL);+  assert(r == target_len);+  target[target_len] = '\0';+  *target_ptr = target;+  return 0;+}+++INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,+    uint64_t* target_len_ptr) {+  char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];+  REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer;+  WCHAR* w_target;+  DWORD w_target_len;+  DWORD bytes;++  if (!DeviceIoControl(handle,+                       FSCTL_GET_REPARSE_POINT,+                       NULL,+                       0,+                       buffer,+                       sizeof buffer,+                       &bytes,+                       NULL)) {+    return -1;+  }++  if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {+    /* Real symlink */+    w_target = reparse_data->SymbolicLinkReparseBuffer.PathBuffer ++        (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset /+        sizeof(WCHAR));+    w_target_len =+        reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /+        sizeof(WCHAR);++    /* Real symlinks can contain pretty much everything, but the only thing we+     * really care about is undoing the implicit conversion to an NT namespaced+     * path that CreateSymbolicLink will perform on absolute paths. If the path+     * is win32-namespaced then the user must have explicitly made it so, and+     * we better just return the unmodified reparse data. */+    if (w_target_len >= 4 &&+        w_target[0] == L'\\' &&+        w_target[1] == L'?' &&+        w_target[2] == L'?' &&+        w_target[3] == L'\\') {+      /* Starts with \??\ */+      if (w_target_len >= 6 &&+          ((w_target[4] >= L'A' && w_target[4] <= L'Z') ||+           (w_target[4] >= L'a' && w_target[4] <= L'z')) &&+          w_target[5] == L':' &&+          (w_target_len == 6 || w_target[6] == L'\\')) {+        /* \??\<drive>:\ */+        w_target += 4;+        w_target_len -= 4;++      } else if (w_target_len >= 8 &&+                 (w_target[4] == L'U' || w_target[4] == L'u') &&+                 (w_target[5] == L'N' || w_target[5] == L'n') &&+                 (w_target[6] == L'C' || w_target[6] == L'c') &&+                 w_target[7] == L'\\') {+        /* \??\UNC\<server>\<share>\ - make sure the final path looks like+         * \\<server>\<share>\ */+        w_target += 6;+        w_target[0] = L'\\';+        w_target_len -= 6;+      }+    }++  } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {+    /* Junction. */+    w_target = reparse_data->MountPointReparseBuffer.PathBuffer ++        (reparse_data->MountPointReparseBuffer.SubstituteNameOffset /+        sizeof(WCHAR));+    w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength /+        sizeof(WCHAR);++    /* Only treat junctions that look like \??\<drive>:\ as symlink. Junctions+     * can also be used as mount points, like \??\Volume{<guid>}, but that's+     * confusing for programs since they wouldn't be able to actually+     * understand such a path when returned by uv_readlink(). UNC paths are+     * never valid for junctions so we don't care about them. */+    if (!(w_target_len >= 6 &&+          w_target[0] == L'\\' &&+          w_target[1] == L'?' &&+          w_target[2] == L'?' &&+          w_target[3] == L'\\' &&+          ((w_target[4] >= L'A' && w_target[4] <= L'Z') ||+           (w_target[4] >= L'a' && w_target[4] <= L'z')) &&+          w_target[5] == L':' &&+          (w_target_len == 6 || w_target[6] == L'\\'))) {+      SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);+      return -1;+    }++    /* Remove leading \??\ */+    w_target += 4;+    w_target_len -= 4;++  } else {+    /* Reparse tag does not indicate a symlink. */+    SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);+    return -1;+  }++  return fs__wide_to_utf8(w_target, w_target_len, target_ptr, target_len_ptr);+}+++void fs__open(uv_fs_t* req) {+  DWORD access;+  DWORD share;+  DWORD disposition;+  DWORD attributes = 0;+  HANDLE file;+  int fd, current_umask;+  int flags = req->fs.info.file_flags;++  /* Obtain the active umask. umask() never fails and returns the previous+   * umask. */+  current_umask = umask(0);+  umask(current_umask);++  /* convert flags and mode to CreateFile parameters */+  switch (flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR)) {+  case UV_FS_O_RDONLY:+    access = FILE_GENERIC_READ;+    break;+  case UV_FS_O_WRONLY:+    access = FILE_GENERIC_WRITE;+    break;+  case UV_FS_O_RDWR:+    access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;+    break;+  default:+    goto einval;+  }++  if (flags & UV_FS_O_APPEND) {+    access &= ~FILE_WRITE_DATA;+    access |= FILE_APPEND_DATA;+  }++  /*+   * Here is where we deviate significantly from what CRT's _open()+   * does. We indiscriminately use all the sharing modes, to match+   * UNIX semantics. In particular, this ensures that the file can+   * be deleted even whilst it's open, fixing issue #1449.+   * We still support exclusive sharing mode, since it is necessary+   * for opening raw block devices, otherwise Windows will prevent+   * any attempt to write past the master boot record.+   */+  if (flags & UV_FS_O_EXLOCK) {+    share = 0;+  } else {+    share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;+  }++  switch (flags & (UV_FS_O_CREAT | UV_FS_O_EXCL | UV_FS_O_TRUNC)) {+  case 0:+  case UV_FS_O_EXCL:+    disposition = OPEN_EXISTING;+    break;+  case UV_FS_O_CREAT:+    disposition = OPEN_ALWAYS;+    break;+  case UV_FS_O_CREAT | UV_FS_O_EXCL:+  case UV_FS_O_CREAT | UV_FS_O_TRUNC | UV_FS_O_EXCL:+    disposition = CREATE_NEW;+    break;+  case UV_FS_O_TRUNC:+  case UV_FS_O_TRUNC | UV_FS_O_EXCL:+    disposition = TRUNCATE_EXISTING;+    break;+  case UV_FS_O_CREAT | UV_FS_O_TRUNC:+    disposition = CREATE_ALWAYS;+    break;+  default:+    goto einval;+  }++  attributes |= FILE_ATTRIBUTE_NORMAL;+  if (flags & UV_FS_O_CREAT) {+    if (!((req->fs.info.mode & ~current_umask) & _S_IWRITE)) {+      attributes |= FILE_ATTRIBUTE_READONLY;+    }+  }++  if (flags & UV_FS_O_TEMPORARY ) {+    attributes |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY;+    access |= DELETE;+  }++  if (flags & UV_FS_O_SHORT_LIVED) {+    attributes |= FILE_ATTRIBUTE_TEMPORARY;+  }++  switch (flags & (UV_FS_O_SEQUENTIAL | UV_FS_O_RANDOM)) {+  case 0:+    break;+  case UV_FS_O_SEQUENTIAL:+    attributes |= FILE_FLAG_SEQUENTIAL_SCAN;+    break;+  case UV_FS_O_RANDOM:+    attributes |= FILE_FLAG_RANDOM_ACCESS;+    break;+  default:+    goto einval;+  }++  if (flags & UV_FS_O_DIRECT) {+    /*+     * FILE_APPEND_DATA and FILE_FLAG_NO_BUFFERING are mutually exclusive.+     * Windows returns 87, ERROR_INVALID_PARAMETER if these are combined.+     *+     * FILE_APPEND_DATA is included in FILE_GENERIC_WRITE:+     *+     * FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE |+     *                      FILE_WRITE_DATA |+     *                      FILE_WRITE_ATTRIBUTES |+     *                      FILE_WRITE_EA |+     *                      FILE_APPEND_DATA |+     *                      SYNCHRONIZE+     *+     * Note: Appends are also permitted by FILE_WRITE_DATA.+     *+     * In order for direct writes and direct appends to succeed, we therefore+     * exclude FILE_APPEND_DATA if FILE_WRITE_DATA is specified, and otherwise+     * fail if the user's sole permission is a direct append, since this+     * particular combination is invalid.+     */+    if (access & FILE_APPEND_DATA) {+      if (access & FILE_WRITE_DATA) {+        access &= ~FILE_APPEND_DATA;+      } else {+        goto einval;+      }+    }+    attributes |= FILE_FLAG_NO_BUFFERING;+  }++  switch (flags & (UV_FS_O_DSYNC | UV_FS_O_SYNC)) {+  case 0:+    break;+  case UV_FS_O_DSYNC:+  case UV_FS_O_SYNC:+    attributes |= FILE_FLAG_WRITE_THROUGH;+    break;+  default:+    goto einval;+  }++  /* Setting this flag makes it possible to open a directory. */+  attributes |= FILE_FLAG_BACKUP_SEMANTICS;++  file = CreateFileW(req->file.pathw,+                     access,+                     share,+                     NULL,+                     disposition,+                     attributes,+                     NULL);+  if (file == INVALID_HANDLE_VALUE) {+    DWORD error = GetLastError();+    if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) &&+        !(flags & UV_FS_O_EXCL)) {+      /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was+       * specified, it means the path referred to a directory. */+      SET_REQ_UV_ERROR(req, UV_EISDIR, error);+    } else {+      SET_REQ_WIN32_ERROR(req, GetLastError());+    }+    return;+  }++  fd = _open_osfhandle((intptr_t) file, flags);+  if (fd < 0) {+    /* The only known failure mode for _open_osfhandle() is EMFILE, in which+     * case GetLastError() will return zero. However we'll try to handle other+     * errors as well, should they ever occur.+     */+    if (errno == EMFILE)+      SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES);+    else if (GetLastError() != ERROR_SUCCESS)+      SET_REQ_WIN32_ERROR(req, GetLastError());+    else+      SET_REQ_WIN32_ERROR(req, UV_UNKNOWN);+    CloseHandle(file);+    return;+  }++  SET_REQ_RESULT(req, fd);+  return;++ einval:+  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);+}++void fs__close(uv_fs_t* req) {+  int fd = req->file.fd;+  int result;++  VERIFY_FD(fd, req);++  if (fd > 2)+    result = _close(fd);+  else+    result = 0;++  /* _close doesn't set _doserrno on failure, but it does always set errno+   * to EBADF on failure.+   */+  if (result == -1) {+    assert(errno == EBADF);+    SET_REQ_UV_ERROR(req, UV_EBADF, ERROR_INVALID_HANDLE);+  } else {+    req->result = 0;+  }+}+++void fs__read(uv_fs_t* req) {+  int fd = req->file.fd;+  int64_t offset = req->fs.info.offset;+  HANDLE handle;+  OVERLAPPED overlapped, *overlapped_ptr;+  LARGE_INTEGER offset_;+  DWORD bytes;+  DWORD error;+  int result;+  unsigned int index;+  LARGE_INTEGER original_position;+  LARGE_INTEGER zero_offset;+  int restore_position;++  VERIFY_FD(fd, req);++  zero_offset.QuadPart = 0;+  restore_position = 0;+  handle = uv__get_osfhandle(fd);++  if (handle == INVALID_HANDLE_VALUE) {+    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);+    return;+  }++  if (offset != -1) {+    memset(&overlapped, 0, sizeof overlapped);+    overlapped_ptr = &overlapped;+    if (SetFilePointerEx(handle, zero_offset, &original_position,+                         FILE_CURRENT)) {+      restore_position = 1;+    }+  } else {+    overlapped_ptr = NULL;+  }++  index = 0;+  bytes = 0;+  do {+    DWORD incremental_bytes;++    if (offset != -1) {+      offset_.QuadPart = offset + bytes;+      overlapped.Offset = offset_.LowPart;+      overlapped.OffsetHigh = offset_.HighPart;+    }++    result = ReadFile(handle,+                      req->fs.info.bufs[index].base,+                      req->fs.info.bufs[index].len,+                      &incremental_bytes,+                      overlapped_ptr);+    bytes += incremental_bytes;+    ++index;+  } while (result && index < req->fs.info.nbufs);++  if (restore_position)+    SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);++  if (result || bytes > 0) {+    SET_REQ_RESULT(req, bytes);+  } else {+    error = GetLastError();+    if (error == ERROR_HANDLE_EOF) {+      SET_REQ_RESULT(req, bytes);+    } else {+      SET_REQ_WIN32_ERROR(req, error);+    }+  }+}+++void fs__write(uv_fs_t* req) {+  int fd = req->file.fd;+  int64_t offset = req->fs.info.offset;+  HANDLE handle;+  OVERLAPPED overlapped, *overlapped_ptr;+  LARGE_INTEGER offset_;+  DWORD bytes;+  int result;+  unsigned int index;+  LARGE_INTEGER original_position;+  LARGE_INTEGER zero_offset;+  int restore_position;++  VERIFY_FD(fd, req);++  zero_offset.QuadPart = 0;+  restore_position = 0;+  handle = uv__get_osfhandle(fd);+  if (handle == INVALID_HANDLE_VALUE) {+    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);+    return;+  }++  if (offset != -1) {+    memset(&overlapped, 0, sizeof overlapped);+    overlapped_ptr = &overlapped;+    if (SetFilePointerEx(handle, zero_offset, &original_position,+                         FILE_CURRENT)) {+      restore_position = 1;+    }+  } else {+    overlapped_ptr = NULL;+  }++  index = 0;+  bytes = 0;+  do {+    DWORD incremental_bytes;++    if (offset != -1) {+      offset_.QuadPart = offset + bytes;+      overlapped.Offset = offset_.LowPart;+      overlapped.OffsetHigh = offset_.HighPart;+    }++    result = WriteFile(handle,+                       req->fs.info.bufs[index].base,+                       req->fs.info.bufs[index].len,+                       &incremental_bytes,+                       overlapped_ptr);+    bytes += incremental_bytes;+    ++index;+  } while (result && index < req->fs.info.nbufs);++  if (restore_position)+    SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);++  if (result || bytes > 0) {+    SET_REQ_RESULT(req, bytes);+  } else {+    SET_REQ_WIN32_ERROR(req, GetLastError());+  }+}+++void fs__rmdir(uv_fs_t* req) {+  int result = _wrmdir(req->file.pathw);+  SET_REQ_RESULT(req, result);+}+++void fs__unlink(uv_fs_t* req) {+  const WCHAR* pathw = req->file.pathw;+  HANDLE handle;+  BY_HANDLE_FILE_INFORMATION info;+  FILE_DISPOSITION_INFORMATION disposition;+  IO_STATUS_BLOCK iosb;+  NTSTATUS status;++  handle = CreateFileW(pathw,+                       FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | DELETE,+                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,+                       NULL,+                       OPEN_EXISTING,+                       FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,+                       NULL);++  if (handle == INVALID_HANDLE_VALUE) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  if (!GetFileInformationByHandle(handle, &info)) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    CloseHandle(handle);+    return;+  }++  if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {+    /* Do not allow deletion of directories, unless it is a symlink. When the+     * path refers to a non-symlink directory, report EPERM as mandated by+     * POSIX.1. */++    /* Check if it is a reparse point. If it's not, it's a normal directory. */+    if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {+      SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);+      CloseHandle(handle);+      return;+    }++    /* Read the reparse point and check if it is a valid symlink. If not, don't+     * unlink. */+    if (fs__readlink_handle(handle, NULL, NULL) < 0) {+      DWORD error = GetLastError();+      if (error == ERROR_SYMLINK_NOT_SUPPORTED)+        error = ERROR_ACCESS_DENIED;+      SET_REQ_WIN32_ERROR(req, error);+      CloseHandle(handle);+      return;+    }+  }++  if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {+    /* Remove read-only attribute */+    FILE_BASIC_INFORMATION basic = { 0 };++    basic.FileAttributes = (info.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY) |+                           FILE_ATTRIBUTE_ARCHIVE;++    status = pNtSetInformationFile(handle,+                                   &iosb,+                                   &basic,+                                   sizeof basic,+                                   FileBasicInformation);+    if (!NT_SUCCESS(status)) {+      SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));+      CloseHandle(handle);+      return;+    }+  }++  /* Try to set the delete flag. */+  disposition.DeleteFile = TRUE;+  status = pNtSetInformationFile(handle,+                                 &iosb,+                                 &disposition,+                                 sizeof disposition,+                                 FileDispositionInformation);+  if (NT_SUCCESS(status)) {+    SET_REQ_SUCCESS(req);+  } else {+    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));+  }++  CloseHandle(handle);+}+++void fs__mkdir(uv_fs_t* req) {+  /* TODO: use req->mode. */+  int result = _wmkdir(req->file.pathw);+  SET_REQ_RESULT(req, result);+}+++/* OpenBSD original: lib/libc/stdio/mktemp.c */+void fs__mkdtemp(uv_fs_t* req) {+  static const WCHAR *tempchars =+    L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";+  static const size_t num_chars = 62;+  static const size_t num_x = 6;+  WCHAR *cp, *ep;+  unsigned int tries, i;+  size_t len;+  HCRYPTPROV h_crypt_prov;+  uint64_t v;+  BOOL released;++  len = wcslen(req->file.pathw);+  ep = req->file.pathw + len;+  if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) {+    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);+    return;+  }++  if (!CryptAcquireContext(&h_crypt_prov, NULL, NULL, PROV_RSA_FULL,+                           CRYPT_VERIFYCONTEXT)) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  tries = TMP_MAX;+  do {+    if (!CryptGenRandom(h_crypt_prov, sizeof(v), (BYTE*) &v)) {+      SET_REQ_WIN32_ERROR(req, GetLastError());+      break;+    }++    cp = ep - num_x;+    for (i = 0; i < num_x; i++) {+      *cp++ = tempchars[v % num_chars];+      v /= num_chars;+    }++    if (_wmkdir(req->file.pathw) == 0) {+      len = strlen(req->path);+      wcstombs((char*) req->path + len - num_x, ep - num_x, num_x);+      SET_REQ_RESULT(req, 0);+      break;+    } else if (errno != EEXIST) {+      SET_REQ_RESULT(req, -1);+      break;+    }+  } while (--tries);++  released = CryptReleaseContext(h_crypt_prov, 0);+  assert(released);+  if (tries == 0) {+    SET_REQ_RESULT(req, -1);+  }+}+++void fs__scandir(uv_fs_t* req) {+  static const size_t dirents_initial_size = 32;++  HANDLE dir_handle = INVALID_HANDLE_VALUE;++  uv__dirent_t** dirents = NULL;+  size_t dirents_size = 0;+  size_t dirents_used = 0;++  IO_STATUS_BLOCK iosb;+  NTSTATUS status;++  /* Buffer to hold directory entries returned by NtQueryDirectoryFile.+   * It's important that this buffer can hold at least one entry, regardless+   * of the length of the file names present in the enumerated directory.+   * A file name is at most 256 WCHARs long.+   * According to MSDN, the buffer must be aligned at an 8-byte boundary.+   */+#if _MSC_VER+  __declspec(align(8)) char buffer[8192];+#else+  __attribute__ ((aligned (8))) char buffer[8192];+#endif++  STATIC_ASSERT(sizeof buffer >=+                sizeof(FILE_DIRECTORY_INFORMATION) + 256 * sizeof(WCHAR));++  /* Open the directory. */+  dir_handle =+      CreateFileW(req->file.pathw,+                  FILE_LIST_DIRECTORY | SYNCHRONIZE,+                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,+                  NULL,+                  OPEN_EXISTING,+                  FILE_FLAG_BACKUP_SEMANTICS,+                  NULL);+  if (dir_handle == INVALID_HANDLE_VALUE)+    goto win32_error;++  /* Read the first chunk. */+  status = pNtQueryDirectoryFile(dir_handle,+                                 NULL,+                                 NULL,+                                 NULL,+                                 &iosb,+                                 &buffer,+                                 sizeof buffer,+                                 FileDirectoryInformation,+                                 FALSE,+                                 NULL,+                                 TRUE);++  /* If the handle is not a directory, we'll get STATUS_INVALID_PARAMETER.+   * This should be reported back as UV_ENOTDIR.+   */+  if (status == STATUS_INVALID_PARAMETER)+    goto not_a_directory_error;++  while (NT_SUCCESS(status)) {+    char* position = buffer;+    size_t next_entry_offset = 0;++    do {+      FILE_DIRECTORY_INFORMATION* info;+      uv__dirent_t* dirent;++      size_t wchar_len;+      size_t utf8_len;++      /* Obtain a pointer to the current directory entry. */+      position += next_entry_offset;+      info = (FILE_DIRECTORY_INFORMATION*) position;++      /* Fetch the offset to the next directory entry. */+      next_entry_offset = info->NextEntryOffset;++      /* Compute the length of the filename in WCHARs. */+      wchar_len = info->FileNameLength / sizeof info->FileName[0];++      /* Skip over '.' and '..' entries.  It has been reported that+       * the SharePoint driver includes the terminating zero byte in+       * the filename length.  Strip those first.+       */+      while (wchar_len > 0 && info->FileName[wchar_len - 1] == L'\0')+        wchar_len -= 1;++      if (wchar_len == 0)+        continue;+      if (wchar_len == 1 && info->FileName[0] == L'.')+        continue;+      if (wchar_len == 2 && info->FileName[0] == L'.' &&+          info->FileName[1] == L'.')+        continue;++      /* Compute the space required to store the filename as UTF-8. */+      utf8_len = WideCharToMultiByte(+          CP_UTF8, 0, &info->FileName[0], wchar_len, NULL, 0, NULL, NULL);+      if (utf8_len == 0)+        goto win32_error;++      /* Resize the dirent array if needed. */+      if (dirents_used >= dirents_size) {+        size_t new_dirents_size =+            dirents_size == 0 ? dirents_initial_size : dirents_size << 1;+        uv__dirent_t** new_dirents =+            uv__realloc(dirents, new_dirents_size * sizeof *dirents);++        if (new_dirents == NULL)+          goto out_of_memory_error;++        dirents_size = new_dirents_size;+        dirents = new_dirents;+      }++      /* Allocate space for the uv dirent structure. The dirent structure+       * includes room for the first character of the filename, but `utf8_len`+       * doesn't count the NULL terminator at this point.+       */+      dirent = uv__malloc(sizeof *dirent + utf8_len);+      if (dirent == NULL)+        goto out_of_memory_error;++      dirents[dirents_used++] = dirent;++      /* Convert file name to UTF-8. */+      if (WideCharToMultiByte(CP_UTF8,+                              0,+                              &info->FileName[0],+                              wchar_len,+                              &dirent->d_name[0],+                              utf8_len,+                              NULL,+                              NULL) == 0)+        goto win32_error;++      /* Add a null terminator to the filename. */+      dirent->d_name[utf8_len] = '\0';++      /* Fill out the type field. */+      if (info->FileAttributes & FILE_ATTRIBUTE_DEVICE)+        dirent->d_type = UV__DT_CHAR;+      else if (info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)+        dirent->d_type = UV__DT_LINK;+      else if (info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)+        dirent->d_type = UV__DT_DIR;+      else+        dirent->d_type = UV__DT_FILE;+    } while (next_entry_offset != 0);++    /* Read the next chunk. */+    status = pNtQueryDirectoryFile(dir_handle,+                                   NULL,+                                   NULL,+                                   NULL,+                                   &iosb,+                                   &buffer,+                                   sizeof buffer,+                                   FileDirectoryInformation,+                                   FALSE,+                                   NULL,+                                   FALSE);++    /* After the first pNtQueryDirectoryFile call, the function may return+     * STATUS_SUCCESS even if the buffer was too small to hold at least one+     * directory entry.+     */+    if (status == STATUS_SUCCESS && iosb.Information == 0)+      status = STATUS_BUFFER_OVERFLOW;+  }++  if (status != STATUS_NO_MORE_FILES)+    goto nt_error;++  CloseHandle(dir_handle);++  /* Store the result in the request object. */+  req->ptr = dirents;+  if (dirents != NULL)+    req->flags |= UV_FS_FREE_PTR;++  SET_REQ_RESULT(req, dirents_used);++  /* `nbufs` will be used as index by uv_fs_scandir_next. */+  req->fs.info.nbufs = 0;++  return;++nt_error:+  SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));+  goto cleanup;++win32_error:+  SET_REQ_WIN32_ERROR(req, GetLastError());+  goto cleanup;++not_a_directory_error:+  SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);+  goto cleanup;++out_of_memory_error:+  SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);+  goto cleanup;++cleanup:+  if (dir_handle != INVALID_HANDLE_VALUE)+    CloseHandle(dir_handle);+  while (dirents_used > 0)+    uv__free(dirents[--dirents_used]);+  if (dirents != NULL)+    uv__free(dirents);+}+++INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,+    int do_lstat) {+  FILE_ALL_INFORMATION file_info;+  FILE_FS_VOLUME_INFORMATION volume_info;+  NTSTATUS nt_status;+  IO_STATUS_BLOCK io_status;++  nt_status = pNtQueryInformationFile(handle,+                                      &io_status,+                                      &file_info,+                                      sizeof file_info,+                                      FileAllInformation);++  /* Buffer overflow (a warning status code) is expected here. */+  if (NT_ERROR(nt_status)) {+    SetLastError(pRtlNtStatusToDosError(nt_status));+    return -1;+  }++  nt_status = pNtQueryVolumeInformationFile(handle,+                                            &io_status,+                                            &volume_info,+                                            sizeof volume_info,+                                            FileFsVolumeInformation);++  /* Buffer overflow (a warning status code) is expected here. */+  if (io_status.Status == STATUS_NOT_IMPLEMENTED) {+    statbuf->st_dev = 0;+  } else if (NT_ERROR(nt_status)) {+    SetLastError(pRtlNtStatusToDosError(nt_status));+    return -1;+  } else {+    statbuf->st_dev = volume_info.VolumeSerialNumber;+  }++  /* Todo: st_mode should probably always be 0666 for everyone. We might also+   * want to report 0777 if the file is a .exe or a directory.+   *+   * Currently it's based on whether the 'readonly' attribute is set, which+   * makes little sense because the semantics are so different: the 'read-only'+   * flag is just a way for a user to protect against accidental deletion, and+   * serves no security purpose. Windows uses ACLs for that.+   *+   * Also people now use uv_fs_chmod() to take away the writable bit for good+   * reasons. Windows however just makes the file read-only, which makes it+   * impossible to delete the file afterwards, since read-only files can't be+   * deleted.+   *+   * IOW it's all just a clusterfuck and we should think of something that+   * makes slightly more sense.+   *+   * And uv_fs_chmod should probably just fail on windows or be a total no-op.+   * There's nothing sensible it can do anyway.+   */+  statbuf->st_mode = 0;++  /*+  * On Windows, FILE_ATTRIBUTE_REPARSE_POINT is a general purpose mechanism+  * by which filesystem drivers can intercept and alter file system requests.+  *+  * The only reparse points we care about are symlinks and mount points, both+  * of which are treated as POSIX symlinks. Further, we only care when+  * invoked via lstat, which seeks information about the link instead of its+  * target. Otherwise, reparse points must be treated as regular files.+  */+  if (do_lstat &&+      (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {+    /*+     * If reading the link fails, the reparse point is not a symlink and needs+     * to be treated as a regular file. The higher level lstat function will+     * detect this failure and retry without do_lstat if appropriate.+     */+    if (fs__readlink_handle(handle, NULL, &statbuf->st_size) != 0)+      return -1;+    statbuf->st_mode |= S_IFLNK;+  }++  if (statbuf->st_mode == 0) {+    if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {+      statbuf->st_mode |= _S_IFDIR;+      statbuf->st_size = 0;+    } else {+      statbuf->st_mode |= _S_IFREG;+      statbuf->st_size = file_info.StandardInformation.EndOfFile.QuadPart;+    }+  }++  if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_READONLY)+    statbuf->st_mode |= _S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6);+  else+    statbuf->st_mode |= (_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) |+                        ((_S_IREAD | _S_IWRITE) >> 6);++  FILETIME_TO_TIMESPEC(statbuf->st_atim, file_info.BasicInformation.LastAccessTime);+  FILETIME_TO_TIMESPEC(statbuf->st_ctim, file_info.BasicInformation.ChangeTime);+  FILETIME_TO_TIMESPEC(statbuf->st_mtim, file_info.BasicInformation.LastWriteTime);+  FILETIME_TO_TIMESPEC(statbuf->st_birthtim, file_info.BasicInformation.CreationTime);++  statbuf->st_ino = file_info.InternalInformation.IndexNumber.QuadPart;++  /* st_blocks contains the on-disk allocation size in 512-byte units. */+  statbuf->st_blocks =+      (uint64_t) file_info.StandardInformation.AllocationSize.QuadPart >> 9;++  statbuf->st_nlink = file_info.StandardInformation.NumberOfLinks;++  /* The st_blksize is supposed to be the 'optimal' number of bytes for reading+   * and writing to the disk. That is, for any definition of 'optimal' - it's+   * supposed to at least avoid read-update-write behavior when writing to the+   * disk.+   *+   * However nobody knows this and even fewer people actually use this value,+   * and in order to fill it out we'd have to make another syscall to query the+   * volume for FILE_FS_SECTOR_SIZE_INFORMATION.+   *+   * Therefore we'll just report a sensible value that's quite commonly okay+   * on modern hardware.+   *+   * 4096 is the minimum required to be compatible with newer Advanced Format+   * drives (which have 4096 bytes per physical sector), and to be backwards+   * compatible with older drives (which have 512 bytes per physical sector).+   */+  statbuf->st_blksize = 4096;++  /* Todo: set st_flags to something meaningful. Also provide a wrapper for+   * chattr(2).+   */+  statbuf->st_flags = 0;++  /* Windows has nothing sensible to say about these values, so they'll just+   * remain empty.+   */+  statbuf->st_gid = 0;+  statbuf->st_uid = 0;+  statbuf->st_rdev = 0;+  statbuf->st_gen = 0;++  return 0;+}+++INLINE static void fs__stat_prepare_path(WCHAR* pathw) {+  size_t len = wcslen(pathw);++  /* TODO: ignore namespaced paths. */+  if (len > 1 && pathw[len - 2] != L':' &&+      (pathw[len - 1] == L'\\' || pathw[len - 1] == L'/')) {+    pathw[len - 1] = '\0';+  }+}+++INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) {+  HANDLE handle;+  DWORD flags;++  flags = FILE_FLAG_BACKUP_SEMANTICS;+  if (do_lstat) {+    flags |= FILE_FLAG_OPEN_REPARSE_POINT;+  }++  handle = CreateFileW(req->file.pathw,+                       FILE_READ_ATTRIBUTES,+                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,+                       NULL,+                       OPEN_EXISTING,+                       flags,+                       NULL);+  if (handle == INVALID_HANDLE_VALUE) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  if (fs__stat_handle(handle, &req->statbuf, do_lstat) != 0) {+    DWORD error = GetLastError();+    if (do_lstat &&+        (error == ERROR_SYMLINK_NOT_SUPPORTED ||+         error == ERROR_NOT_A_REPARSE_POINT)) {+      /* We opened a reparse point but it was not a symlink. Try again. */+      fs__stat_impl(req, 0);++    } else {+      /* Stat failed. */+      SET_REQ_WIN32_ERROR(req, GetLastError());+    }++    CloseHandle(handle);+    return;+  }++  req->ptr = &req->statbuf;+  req->result = 0;+  CloseHandle(handle);+}+++static void fs__stat(uv_fs_t* req) {+  fs__stat_prepare_path(req->file.pathw);+  fs__stat_impl(req, 0);+}+++static void fs__lstat(uv_fs_t* req) {+  fs__stat_prepare_path(req->file.pathw);+  fs__stat_impl(req, 1);+}+++static void fs__fstat(uv_fs_t* req) {+  int fd = req->file.fd;+  HANDLE handle;++  VERIFY_FD(fd, req);++  handle = uv__get_osfhandle(fd);++  if (handle == INVALID_HANDLE_VALUE) {+    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);+    return;+  }++  if (fs__stat_handle(handle, &req->statbuf, 0) != 0) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  req->ptr = &req->statbuf;+  req->result = 0;+}+++static void fs__rename(uv_fs_t* req) {+  if (!MoveFileExW(req->file.pathw, req->fs.info.new_pathw, MOVEFILE_REPLACE_EXISTING)) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  SET_REQ_RESULT(req, 0);+}+++INLINE static void fs__sync_impl(uv_fs_t* req) {+  int fd = req->file.fd;+  int result;++  VERIFY_FD(fd, req);++  result = FlushFileBuffers(uv__get_osfhandle(fd)) ? 0 : -1;+  if (result == -1) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+  } else {+    SET_REQ_RESULT(req, result);+  }+}+++static void fs__fsync(uv_fs_t* req) {+  fs__sync_impl(req);+}+++static void fs__fdatasync(uv_fs_t* req) {+  fs__sync_impl(req);+}+++static void fs__ftruncate(uv_fs_t* req) {+  int fd = req->file.fd;+  HANDLE handle;+  NTSTATUS status;+  IO_STATUS_BLOCK io_status;+  FILE_END_OF_FILE_INFORMATION eof_info;++  VERIFY_FD(fd, req);++  handle = uv__get_osfhandle(fd);++  eof_info.EndOfFile.QuadPart = req->fs.info.offset;++  status = pNtSetInformationFile(handle,+                                 &io_status,+                                 &eof_info,+                                 sizeof eof_info,+                                 FileEndOfFileInformation);++  if (NT_SUCCESS(status)) {+    SET_REQ_RESULT(req, 0);+  } else {+    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));+  }+}+++static void fs__copyfile(uv_fs_t* req) {+  int flags;+  int overwrite;++  flags = req->fs.info.file_flags;++  if (flags & UV_FS_COPYFILE_FICLONE_FORCE) {+    SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);+    return;+  }++  overwrite = flags & UV_FS_COPYFILE_EXCL;++  if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) == 0) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  SET_REQ_RESULT(req, 0);+}+++static void fs__sendfile(uv_fs_t* req) {+  int fd_in = req->file.fd, fd_out = req->fs.info.fd_out;+  size_t length = req->fs.info.bufsml[0].len;+  int64_t offset = req->fs.info.offset;+  const size_t max_buf_size = 65536;+  size_t buf_size = length < max_buf_size ? length : max_buf_size;+  int n, result = 0;+  int64_t result_offset = 0;+  char* buf = (char*) uv__malloc(buf_size);+  if (!buf) {+    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+  }++  if (offset != -1) {+    result_offset = _lseeki64(fd_in, offset, SEEK_SET);+  }++  if (result_offset == -1) {+    result = -1;+  } else {+    while (length > 0) {+      n = _read(fd_in, buf, length < buf_size ? length : buf_size);+      if (n == 0) {+        break;+      } else if (n == -1) {+        result = -1;+        break;+      }++      length -= n;++      n = _write(fd_out, buf, n);+      if (n == -1) {+        result = -1;+        break;+      }++      result += n;+    }+  }++  uv__free(buf);++  SET_REQ_RESULT(req, result);+}+++static void fs__access(uv_fs_t* req) {+  DWORD attr = GetFileAttributesW(req->file.pathw);++  if (attr == INVALID_FILE_ATTRIBUTES) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  /*+   * Access is possible if+   * - write access wasn't requested,+   * - or the file isn't read-only,+   * - or it's a directory.+   * (Directories cannot be read-only on Windows.)+   */+  if (!(req->fs.info.mode & W_OK) ||+      !(attr & FILE_ATTRIBUTE_READONLY) ||+      (attr & FILE_ATTRIBUTE_DIRECTORY)) {+    SET_REQ_RESULT(req, 0);+  } else {+    SET_REQ_WIN32_ERROR(req, UV_EPERM);+  }++}+++static void fs__chmod(uv_fs_t* req) {+  int result = _wchmod(req->file.pathw, req->fs.info.mode);+  SET_REQ_RESULT(req, result);+}+++static void fs__fchmod(uv_fs_t* req) {+  int fd = req->file.fd;+  int clear_archive_flag;+  HANDLE handle;+  NTSTATUS nt_status;+  IO_STATUS_BLOCK io_status;+  FILE_BASIC_INFORMATION file_info;++  VERIFY_FD(fd, req);++  handle = ReOpenFile(uv__get_osfhandle(fd), FILE_WRITE_ATTRIBUTES, 0, 0);+  if (handle == INVALID_HANDLE_VALUE) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  nt_status = pNtQueryInformationFile(handle,+                                      &io_status,+                                      &file_info,+                                      sizeof file_info,+                                      FileBasicInformation);++  if (!NT_SUCCESS(nt_status)) {+    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));+    goto fchmod_cleanup;+  }++  /* Test if the Archive attribute is cleared */+  if ((file_info.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == 0) {+      /* Set Archive flag, otherwise setting or clearing the read-only+         flag will not work */+      file_info.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;+      nt_status = pNtSetInformationFile(handle,+                                        &io_status,+                                        &file_info,+                                        sizeof file_info,+                                        FileBasicInformation);+      if (!NT_SUCCESS(nt_status)) {+        SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));+        goto fchmod_cleanup;+      }+      /* Remeber to clear the flag later on */+      clear_archive_flag = 1;+  } else {+      clear_archive_flag = 0;+  }++  if (req->fs.info.mode & _S_IWRITE) {+    file_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;+  } else {+    file_info.FileAttributes |= FILE_ATTRIBUTE_READONLY;+  }++  nt_status = pNtSetInformationFile(handle,+                                    &io_status,+                                    &file_info,+                                    sizeof file_info,+                                    FileBasicInformation);++  if (!NT_SUCCESS(nt_status)) {+    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));+    goto fchmod_cleanup;+  }++  if (clear_archive_flag) {+      file_info.FileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE;+      if (file_info.FileAttributes == 0) {+          file_info.FileAttributes = FILE_ATTRIBUTE_NORMAL;+      }+      nt_status = pNtSetInformationFile(handle,+                                        &io_status,+                                        &file_info,+                                        sizeof file_info,+                                        FileBasicInformation);+      if (!NT_SUCCESS(nt_status)) {+        SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));+        goto fchmod_cleanup;+      }+  }++  SET_REQ_SUCCESS(req);+fchmod_cleanup:+  CloseHandle(handle);+}+++INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {+  FILETIME filetime_a, filetime_m;++  TIME_T_TO_FILETIME(atime, &filetime_a);+  TIME_T_TO_FILETIME(mtime, &filetime_m);++  if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) {+    return -1;+  }++  return 0;+}+++static void fs__utime(uv_fs_t* req) {+  HANDLE handle;++  handle = CreateFileW(req->file.pathw,+                       FILE_WRITE_ATTRIBUTES,+                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,+                       NULL,+                       OPEN_EXISTING,+                       FILE_FLAG_BACKUP_SEMANTICS,+                       NULL);++  if (handle == INVALID_HANDLE_VALUE) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    CloseHandle(handle);+    return;+  }++  CloseHandle(handle);++  req->result = 0;+}+++static void fs__futime(uv_fs_t* req) {+  int fd = req->file.fd;+  HANDLE handle;+  VERIFY_FD(fd, req);++  handle = uv__get_osfhandle(fd);++  if (handle == INVALID_HANDLE_VALUE) {+    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);+    return;+  }++  if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  req->result = 0;+}+++static void fs__link(uv_fs_t* req) {+  DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL);+  if (r == 0) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+  } else {+    req->result = 0;+  }+}+++static void fs__create_junction(uv_fs_t* req, const WCHAR* path,+    const WCHAR* new_path) {+  HANDLE handle = INVALID_HANDLE_VALUE;+  REPARSE_DATA_BUFFER *buffer = NULL;+  int created = 0;+  int target_len;+  int is_absolute, is_long_path;+  int needed_buf_size, used_buf_size, used_data_size, path_buf_len;+  int start, len, i;+  int add_slash;+  DWORD bytes;+  WCHAR* path_buf;++  target_len = wcslen(path);+  is_long_path = wcsncmp(path, LONG_PATH_PREFIX, LONG_PATH_PREFIX_LEN) == 0;++  if (is_long_path) {+    is_absolute = 1;+  } else {+    is_absolute = target_len >= 3 && IS_LETTER(path[0]) &&+      path[1] == L':' && IS_SLASH(path[2]);+  }++  if (!is_absolute) {+    /* Not supporting relative paths */+    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_NOT_SUPPORTED);+    return;+  }++  /* Do a pessimistic calculation of the required buffer size */+  needed_buf_size =+      FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) ++      JUNCTION_PREFIX_LEN * sizeof(WCHAR) ++      2 * (target_len + 2) * sizeof(WCHAR);++  /* Allocate the buffer */+  buffer = (REPARSE_DATA_BUFFER*)uv__malloc(needed_buf_size);+  if (!buffer) {+    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+  }++  /* Grab a pointer to the part of the buffer where filenames go */+  path_buf = (WCHAR*)&(buffer->MountPointReparseBuffer.PathBuffer);+  path_buf_len = 0;++  /* Copy the substitute (internal) target path */+  start = path_buf_len;++  wcsncpy((WCHAR*)&path_buf[path_buf_len], JUNCTION_PREFIX,+    JUNCTION_PREFIX_LEN);+  path_buf_len += JUNCTION_PREFIX_LEN;++  add_slash = 0;+  for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {+    if (IS_SLASH(path[i])) {+      add_slash = 1;+      continue;+    }++    if (add_slash) {+      path_buf[path_buf_len++] = L'\\';+      add_slash = 0;+    }++    path_buf[path_buf_len++] = path[i];+  }+  path_buf[path_buf_len++] = L'\\';+  len = path_buf_len - start;++  /* Set the info about the substitute name */+  buffer->MountPointReparseBuffer.SubstituteNameOffset = start * sizeof(WCHAR);+  buffer->MountPointReparseBuffer.SubstituteNameLength = len * sizeof(WCHAR);++  /* Insert null terminator */+  path_buf[path_buf_len++] = L'\0';++  /* Copy the print name of the target path */+  start = path_buf_len;+  add_slash = 0;+  for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {+    if (IS_SLASH(path[i])) {+      add_slash = 1;+      continue;+    }++    if (add_slash) {+      path_buf[path_buf_len++] = L'\\';+      add_slash = 0;+    }++    path_buf[path_buf_len++] = path[i];+  }+  len = path_buf_len - start;+  if (len == 2) {+    path_buf[path_buf_len++] = L'\\';+    len++;+  }++  /* Set the info about the print name */+  buffer->MountPointReparseBuffer.PrintNameOffset = start * sizeof(WCHAR);+  buffer->MountPointReparseBuffer.PrintNameLength = len * sizeof(WCHAR);++  /* Insert another null terminator */+  path_buf[path_buf_len++] = L'\0';++  /* Calculate how much buffer space was actually used */+  used_buf_size = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) ++    path_buf_len * sizeof(WCHAR);+  used_data_size = used_buf_size -+    FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer);++  /* Put general info in the data buffer */+  buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;+  buffer->ReparseDataLength = used_data_size;+  buffer->Reserved = 0;++  /* Create a new directory */+  if (!CreateDirectoryW(new_path, NULL)) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    goto error;+  }+  created = 1;++  /* Open the directory */+  handle = CreateFileW(new_path,+                       GENERIC_WRITE,+                       0,+                       NULL,+                       OPEN_EXISTING,+                       FILE_FLAG_BACKUP_SEMANTICS |+                         FILE_FLAG_OPEN_REPARSE_POINT,+                       NULL);+  if (handle == INVALID_HANDLE_VALUE) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    goto error;+  }++  /* Create the actual reparse point */+  if (!DeviceIoControl(handle,+                       FSCTL_SET_REPARSE_POINT,+                       buffer,+                       used_buf_size,+                       NULL,+                       0,+                       &bytes,+                       NULL)) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    goto error;+  }++  /* Clean up */+  CloseHandle(handle);+  uv__free(buffer);++  SET_REQ_RESULT(req, 0);+  return;++error:+  uv__free(buffer);++  if (handle != INVALID_HANDLE_VALUE) {+    CloseHandle(handle);+  }++  if (created) {+    RemoveDirectoryW(new_path);+  }+}+++static void fs__symlink(uv_fs_t* req) {+  WCHAR* pathw;+  WCHAR* new_pathw;+  int flags;+  int err;++  pathw = req->file.pathw;+  new_pathw = req->fs.info.new_pathw;++  if (req->fs.info.file_flags & UV_FS_SYMLINK_JUNCTION) {+    fs__create_junction(req, pathw, new_pathw);+    return;+  }++  if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR)+    flags = SYMBOLIC_LINK_FLAG_DIRECTORY | uv__file_symlink_usermode_flag;+  else+    flags = uv__file_symlink_usermode_flag;++  if (CreateSymbolicLinkW(new_pathw, pathw, flags)) {+    SET_REQ_RESULT(req, 0);+    return;+  }++  /* Something went wrong. We will test if it is because of user-mode+   * symlinks.+   */+  err = GetLastError();+  if (err == ERROR_INVALID_PARAMETER &&+      flags & SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) {+    /* This system does not support user-mode symlinks. We will clear the+     * unsupported flag and retry.+     */+    uv__file_symlink_usermode_flag = 0;+    fs__symlink(req);+  } else {+    SET_REQ_WIN32_ERROR(req, err);+  }+}+++static void fs__readlink(uv_fs_t* req) {+  HANDLE handle;++  handle = CreateFileW(req->file.pathw,+                       0,+                       0,+                       NULL,+                       OPEN_EXISTING,+                       FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,+                       NULL);++  if (handle == INVALID_HANDLE_VALUE) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  if (fs__readlink_handle(handle, (char**) &req->ptr, NULL) != 0) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    CloseHandle(handle);+    return;+  }++  req->flags |= UV_FS_FREE_PTR;+  SET_REQ_RESULT(req, 0);++  CloseHandle(handle);+}+++static ssize_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {+  int r;+  DWORD w_realpath_len;+  WCHAR* w_realpath_ptr = NULL;+  WCHAR* w_realpath_buf;++  w_realpath_len = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);+  if (w_realpath_len == 0) {+    return -1;+  }++  w_realpath_buf = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR));+  if (w_realpath_buf == NULL) {+    SetLastError(ERROR_OUTOFMEMORY);+    return -1;+  }+  w_realpath_ptr = w_realpath_buf;++  if (GetFinalPathNameByHandleW(+          handle, w_realpath_ptr, w_realpath_len, VOLUME_NAME_DOS) == 0) {+    uv__free(w_realpath_buf);+    SetLastError(ERROR_INVALID_HANDLE);+    return -1;+  }++  /* convert UNC path to long path */+  if (wcsncmp(w_realpath_ptr,+              UNC_PATH_PREFIX,+              UNC_PATH_PREFIX_LEN) == 0) {+    w_realpath_ptr += 6;+    *w_realpath_ptr = L'\\';+    w_realpath_len -= 6;+  } else if (wcsncmp(w_realpath_ptr,+                      LONG_PATH_PREFIX,+                      LONG_PATH_PREFIX_LEN) == 0) {+    w_realpath_ptr += 4;+    w_realpath_len -= 4;+  } else {+    uv__free(w_realpath_buf);+    SetLastError(ERROR_INVALID_HANDLE);+    return -1;+  }++  r = fs__wide_to_utf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL);+  uv__free(w_realpath_buf);+  return r;+}++static void fs__realpath(uv_fs_t* req) {+  HANDLE handle;++  handle = CreateFileW(req->file.pathw,+                       0,+                       0,+                       NULL,+                       OPEN_EXISTING,+                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,+                       NULL);+  if (handle == INVALID_HANDLE_VALUE) {+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  if (fs__realpath_handle(handle, (char**) &req->ptr) == -1) {+    CloseHandle(handle);+    SET_REQ_WIN32_ERROR(req, GetLastError());+    return;+  }++  CloseHandle(handle);+  req->flags |= UV_FS_FREE_PTR;+  SET_REQ_RESULT(req, 0);+}+++static void fs__chown(uv_fs_t* req) {+  req->result = 0;+}+++static void fs__fchown(uv_fs_t* req) {+  req->result = 0;+}+++static void fs__lchown(uv_fs_t* req) {+  req->result = 0;+}++static void uv__fs_work(struct uv__work* w) {+  uv_fs_t* req;++  req = container_of(w, uv_fs_t, work_req);+  assert(req->type == UV_FS);++#define XX(uc, lc)  case UV_FS_##uc: fs__##lc(req); break;+  switch (req->fs_type) {+    XX(OPEN, open)+    XX(CLOSE, close)+    XX(READ, read)+    XX(WRITE, write)+    XX(COPYFILE, copyfile)+    XX(SENDFILE, sendfile)+    XX(STAT, stat)+    XX(LSTAT, lstat)+    XX(FSTAT, fstat)+    XX(FTRUNCATE, ftruncate)+    XX(UTIME, utime)+    XX(FUTIME, futime)+    XX(ACCESS, access)+    XX(CHMOD, chmod)+    XX(FCHMOD, fchmod)+    XX(FSYNC, fsync)+    XX(FDATASYNC, fdatasync)+    XX(UNLINK, unlink)+    XX(RMDIR, rmdir)+    XX(MKDIR, mkdir)+    XX(MKDTEMP, mkdtemp)+    XX(RENAME, rename)+    XX(SCANDIR, scandir)+    XX(LINK, link)+    XX(SYMLINK, symlink)+    XX(READLINK, readlink)+    XX(REALPATH, realpath)+    XX(CHOWN, chown)+    XX(FCHOWN, fchown);+    XX(LCHOWN, lchown);+    default:+      assert(!"bad uv_fs_type");+  }+}+++static void uv__fs_done(struct uv__work* w, int status) {+  uv_fs_t* req;++  req = container_of(w, uv_fs_t, work_req);+  uv__req_unregister(req->loop, req);++  if (status == UV_ECANCELED) {+    assert(req->result == 0);+    req->result = UV_ECANCELED;+  }++  req->cb(req);+}+++void uv_fs_req_cleanup(uv_fs_t* req) {+  if (req == NULL)+    return;++  if (req->flags & UV_FS_CLEANEDUP)+    return;++  if (req->flags & UV_FS_FREE_PATHS)+    uv__free(req->file.pathw);++  if (req->flags & UV_FS_FREE_PTR) {+    if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)+      uv__fs_scandir_cleanup(req);+    else+      uv__free(req->ptr);+  }++  if (req->fs.info.bufs != req->fs.info.bufsml)+    uv__free(req->fs.info.bufs);++  req->path = NULL;+  req->file.pathw = NULL;+  req->fs.info.new_pathw = NULL;+  req->fs.info.bufs = NULL;+  req->ptr = NULL;++  req->flags |= UV_FS_CLEANEDUP;+}+++int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,+    int mode, uv_fs_cb cb) {+  int err;++  INIT(UV_FS_OPEN);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  req->fs.info.file_flags = flags;+  req->fs.info.mode = mode;+  POST;+}+++int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {+  INIT(UV_FS_CLOSE);+  req->file.fd = fd;+  POST;+}+++int uv_fs_read(uv_loop_t* loop,+               uv_fs_t* req,+               uv_file fd,+               const uv_buf_t bufs[],+               unsigned int nbufs,+               int64_t offset,+               uv_fs_cb cb) {+  INIT(UV_FS_READ);++  if (bufs == NULL || nbufs == 0)+    return UV_EINVAL;++  req->file.fd = fd;++  req->fs.info.nbufs = nbufs;+  req->fs.info.bufs = req->fs.info.bufsml;+  if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))+    req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));++  if (req->fs.info.bufs == NULL)+    return UV_ENOMEM;++  memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));++  req->fs.info.offset = offset;+  POST;+}+++int uv_fs_write(uv_loop_t* loop,+                uv_fs_t* req,+                uv_file fd,+                const uv_buf_t bufs[],+                unsigned int nbufs,+                int64_t offset,+                uv_fs_cb cb) {+  INIT(UV_FS_WRITE);++  if (bufs == NULL || nbufs == 0)+    return UV_EINVAL;++  req->file.fd = fd;++  req->fs.info.nbufs = nbufs;+  req->fs.info.bufs = req->fs.info.bufsml;+  if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))+    req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));++  if (req->fs.info.bufs == NULL)+    return UV_ENOMEM;++  memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));++  req->fs.info.offset = offset;+  POST;+}+++int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,+    uv_fs_cb cb) {+  int err;++  INIT(UV_FS_UNLINK);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  POST;+}+++int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,+    uv_fs_cb cb) {+  int err;++  INIT(UV_FS_MKDIR);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  req->fs.info.mode = mode;+  POST;+}+++int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl,+    uv_fs_cb cb) {+  int err;++  INIT(UV_FS_MKDTEMP);+  err = fs__capture_path(req, tpl, NULL, TRUE);+  if (err)+    return uv_translate_sys_error(err);++  POST;+}+++int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {+  int err;++  INIT(UV_FS_RMDIR);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  POST;+}+++int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,+    uv_fs_cb cb) {+  int err;++  INIT(UV_FS_SCANDIR);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  req->fs.info.file_flags = flags;+  POST;+}+++int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,+    const char* new_path, uv_fs_cb cb) {+  int err;++  INIT(UV_FS_LINK);+  err = fs__capture_path(req, path, new_path, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  POST;+}+++int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,+    const char* new_path, int flags, uv_fs_cb cb) {+  int err;++  INIT(UV_FS_SYMLINK);+  err = fs__capture_path(req, path, new_path, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  req->fs.info.file_flags = flags;+  POST;+}+++int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,+    uv_fs_cb cb) {+  int err;++  INIT(UV_FS_READLINK);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  POST;+}+++int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path,+    uv_fs_cb cb) {+  int err;++  INIT(UV_FS_REALPATH);++  if (!path) {+    return UV_EINVAL;+  }++  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  POST;+}+++int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,+    uv_gid_t gid, uv_fs_cb cb) {+  int err;++  INIT(UV_FS_CHOWN);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  POST;+}+++int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid,+    uv_gid_t gid, uv_fs_cb cb) {+  INIT(UV_FS_FCHOWN);+  POST;+}+++int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,+    uv_gid_t gid, uv_fs_cb cb) {+  int err;++  INIT(UV_FS_LCHOWN);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }+  POST;+}+++int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {+  int err;++  INIT(UV_FS_STAT);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  POST;+}+++int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {+  int err;++  INIT(UV_FS_LSTAT);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  POST;+}+++int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {+  INIT(UV_FS_FSTAT);+  req->file.fd = fd;+  POST;+}+++int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,+    const char* new_path, uv_fs_cb cb) {+  int err;++  INIT(UV_FS_RENAME);+  err = fs__capture_path(req, path, new_path, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  POST;+}+++int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {+  INIT(UV_FS_FSYNC);+  req->file.fd = fd;+  POST;+}+++int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {+  INIT(UV_FS_FDATASYNC);+  req->file.fd = fd;+  POST;+}+++int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file fd,+    int64_t offset, uv_fs_cb cb) {+  INIT(UV_FS_FTRUNCATE);+  req->file.fd = fd;+  req->fs.info.offset = offset;+  POST;+}+++int uv_fs_copyfile(uv_loop_t* loop,+                   uv_fs_t* req,+                   const char* path,+                   const char* new_path,+                   int flags,+                   uv_fs_cb cb) {+  int err;++  INIT(UV_FS_COPYFILE);++  if (flags & ~(UV_FS_COPYFILE_EXCL |+                UV_FS_COPYFILE_FICLONE |+                UV_FS_COPYFILE_FICLONE_FORCE)) {+    return UV_EINVAL;+  }++  err = fs__capture_path(req, path, new_path, cb != NULL);++  if (err)+    return uv_translate_sys_error(err);++  req->fs.info.file_flags = flags;+  POST;+}+++int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out,+    uv_file fd_in, int64_t in_offset, size_t length, uv_fs_cb cb) {+  INIT(UV_FS_SENDFILE);+  req->file.fd = fd_in;+  req->fs.info.fd_out = fd_out;+  req->fs.info.offset = in_offset;+  req->fs.info.bufsml[0].len = length;+  POST;+}+++int uv_fs_access(uv_loop_t* loop,+                 uv_fs_t* req,+                 const char* path,+                 int flags,+                 uv_fs_cb cb) {+  int err;++  INIT(UV_FS_ACCESS);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err)+    return uv_translate_sys_error(err);++  req->fs.info.mode = flags;+  POST;+}+++int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,+    uv_fs_cb cb) {+  int err;++  INIT(UV_FS_CHMOD);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  req->fs.info.mode = mode;+  POST;+}+++int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int mode,+    uv_fs_cb cb) {+  INIT(UV_FS_FCHMOD);+  req->file.fd = fd;+  req->fs.info.mode = mode;+  POST;+}+++int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,+    double mtime, uv_fs_cb cb) {+  int err;++  INIT(UV_FS_UTIME);+  err = fs__capture_path(req, path, NULL, cb != NULL);+  if (err) {+    return uv_translate_sys_error(err);+  }++  req->fs.time.atime = atime;+  req->fs.time.mtime = mtime;+  POST;+}+++int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime,+    double mtime, uv_fs_cb cb) {+  INIT(UV_FS_FUTIME);+  req->file.fd = fd;+  req->fs.time.atime = atime;+  req->fs.time.mtime = mtime;+  POST;+}
+ third_party/libuv/src/win/getaddrinfo.c view
@@ -0,0 +1,463 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>++#include "uv.h"+#include "internal.h"+#include "req-inl.h"+#include "idna.h"++/* EAI_* constants. */+#include <winsock2.h>++/* Needed for ConvertInterfaceIndexToLuid and ConvertInterfaceLuidToNameA */+#include <iphlpapi.h>++int uv__getaddrinfo_translate_error(int sys_err) {+  switch (sys_err) {+    case 0:                       return 0;+    case WSATRY_AGAIN:            return UV_EAI_AGAIN;+    case WSAEINVAL:               return UV_EAI_BADFLAGS;+    case WSANO_RECOVERY:          return UV_EAI_FAIL;+    case WSAEAFNOSUPPORT:         return UV_EAI_FAMILY;+    case WSA_NOT_ENOUGH_MEMORY:   return UV_EAI_MEMORY;+    case WSAHOST_NOT_FOUND:       return UV_EAI_NONAME;+    case WSATYPE_NOT_FOUND:       return UV_EAI_SERVICE;+    case WSAESOCKTNOSUPPORT:      return UV_EAI_SOCKTYPE;+    default:                      return uv_translate_sys_error(sys_err);+  }+}+++/*+ * MinGW is missing this+ */+#if !defined(_MSC_VER) && !defined(__MINGW64_VERSION_MAJOR)+  typedef struct addrinfoW {+    int ai_flags;+    int ai_family;+    int ai_socktype;+    int ai_protocol;+    size_t ai_addrlen;+    WCHAR* ai_canonname;+    struct sockaddr* ai_addr;+    struct addrinfoW* ai_next;+  } ADDRINFOW, *PADDRINFOW;++  DECLSPEC_IMPORT int WSAAPI GetAddrInfoW(const WCHAR* node,+                                          const WCHAR* service,+                                          const ADDRINFOW* hints,+                                          PADDRINFOW* result);++  DECLSPEC_IMPORT void WSAAPI FreeAddrInfoW(PADDRINFOW pAddrInfo);+#endif+++/* Adjust size value to be multiple of 4. Use to keep pointer aligned.+ * Do we need different versions of this for different architectures? */+#define ALIGNED_SIZE(X)     ((((X) + 3) >> 2) << 2)++#ifndef NDIS_IF_MAX_STRING_SIZE+#define NDIS_IF_MAX_STRING_SIZE IF_MAX_STRING_SIZE+#endif++static void uv__getaddrinfo_work(struct uv__work* w) {+  uv_getaddrinfo_t* req;+  struct addrinfoW* hints;+  int err;++  req = container_of(w, uv_getaddrinfo_t, work_req);+  hints = req->addrinfow;+  req->addrinfow = NULL;+  err = GetAddrInfoW(req->node, req->service, hints, &req->addrinfow);+  req->retcode = uv__getaddrinfo_translate_error(err);+}+++/*+ * Called from uv_run when complete. Call user specified callback+ * then free returned addrinfo+ * Returned addrinfo strings are converted from UTF-16 to UTF-8.+ *+ * To minimize allocation we calculate total size required,+ * and copy all structs and referenced strings into the one block.+ * Each size calculation is adjusted to avoid unaligned pointers.+ */+static void uv__getaddrinfo_done(struct uv__work* w, int status) {+  uv_getaddrinfo_t* req;+  int addrinfo_len = 0;+  int name_len = 0;+  size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo));+  struct addrinfoW* addrinfow_ptr;+  struct addrinfo* addrinfo_ptr;+  char* alloc_ptr = NULL;+  char* cur_ptr = NULL;++  req = container_of(w, uv_getaddrinfo_t, work_req);++  /* release input parameter memory */+  uv__free(req->alloc);+  req->alloc = NULL;++  if (status == UV_ECANCELED) {+    assert(req->retcode == 0);+    req->retcode = UV_EAI_CANCELED;+    goto complete;+  }++  if (req->retcode == 0) {+    /* Convert addrinfoW to addrinfo. First calculate required length. */+    addrinfow_ptr = req->addrinfow;+    while (addrinfow_ptr != NULL) {+      addrinfo_len += addrinfo_struct_len ++          ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);+      if (addrinfow_ptr->ai_canonname != NULL) {+        name_len = WideCharToMultiByte(CP_UTF8,+                                       0,+                                       addrinfow_ptr->ai_canonname,+                                       -1,+                                       NULL,+                                       0,+                                       NULL,+                                       NULL);+        if (name_len == 0) {+          req->retcode = uv_translate_sys_error(GetLastError());+          goto complete;+        }+        addrinfo_len += ALIGNED_SIZE(name_len);+      }+      addrinfow_ptr = addrinfow_ptr->ai_next;+    }++    /* allocate memory for addrinfo results */+    alloc_ptr = (char*)uv__malloc(addrinfo_len);++    /* do conversions */+    if (alloc_ptr != NULL) {+      cur_ptr = alloc_ptr;+      addrinfow_ptr = req->addrinfow;++      while (addrinfow_ptr != NULL) {+        /* copy addrinfo struct data */+        assert(cur_ptr + addrinfo_struct_len <= alloc_ptr + addrinfo_len);+        addrinfo_ptr = (struct addrinfo*)cur_ptr;+        addrinfo_ptr->ai_family = addrinfow_ptr->ai_family;+        addrinfo_ptr->ai_socktype = addrinfow_ptr->ai_socktype;+        addrinfo_ptr->ai_protocol = addrinfow_ptr->ai_protocol;+        addrinfo_ptr->ai_flags = addrinfow_ptr->ai_flags;+        addrinfo_ptr->ai_addrlen = addrinfow_ptr->ai_addrlen;+        addrinfo_ptr->ai_canonname = NULL;+        addrinfo_ptr->ai_addr = NULL;+        addrinfo_ptr->ai_next = NULL;++        cur_ptr += addrinfo_struct_len;++        /* copy sockaddr */+        if (addrinfo_ptr->ai_addrlen > 0) {+          assert(cur_ptr + addrinfo_ptr->ai_addrlen <=+                 alloc_ptr + addrinfo_len);+          memcpy(cur_ptr, addrinfow_ptr->ai_addr, addrinfo_ptr->ai_addrlen);+          addrinfo_ptr->ai_addr = (struct sockaddr*)cur_ptr;+          cur_ptr += ALIGNED_SIZE(addrinfo_ptr->ai_addrlen);+        }++        /* convert canonical name to UTF-8 */+        if (addrinfow_ptr->ai_canonname != NULL) {+          name_len = WideCharToMultiByte(CP_UTF8,+                                         0,+                                         addrinfow_ptr->ai_canonname,+                                         -1,+                                         NULL,+                                         0,+                                         NULL,+                                         NULL);+          assert(name_len > 0);+          assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len);+          name_len = WideCharToMultiByte(CP_UTF8,+                                         0,+                                         addrinfow_ptr->ai_canonname,+                                         -1,+                                         cur_ptr,+                                         name_len,+                                         NULL,+                                         NULL);+          assert(name_len > 0);+          addrinfo_ptr->ai_canonname = cur_ptr;+          cur_ptr += ALIGNED_SIZE(name_len);+        }+        assert(cur_ptr <= alloc_ptr + addrinfo_len);++        /* set next ptr */+        addrinfow_ptr = addrinfow_ptr->ai_next;+        if (addrinfow_ptr != NULL) {+          addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr;+        }+      }+      req->addrinfo = (struct addrinfo*)alloc_ptr;+    } else {+      req->retcode = UV_EAI_MEMORY;+    }+  }++  /* return memory to system */+  if (req->addrinfow != NULL) {+    FreeAddrInfoW(req->addrinfow);+    req->addrinfow = NULL;+  }++complete:+  uv__req_unregister(req->loop, req);++  /* finally do callback with converted result */+  if (req->getaddrinfo_cb)+    req->getaddrinfo_cb(req, req->retcode, req->addrinfo);+}+++void uv_freeaddrinfo(struct addrinfo* ai) {+  char* alloc_ptr = (char*)ai;++  /* release copied result memory */+  uv__free(alloc_ptr);+}+++/*+ * Entry point for getaddrinfo+ * we convert the UTF-8 strings to UNICODE+ * and save the UNICODE string pointers in the req+ * We also copy hints so that caller does not need to keep memory until the+ * callback.+ * return 0 if a callback will be made+ * return error code if validation fails+ *+ * To minimize allocation we calculate total size required,+ * and copy all structs and referenced strings into the one block.+ * Each size calculation is adjusted to avoid unaligned pointers.+ */+int uv_getaddrinfo(uv_loop_t* loop,+                   uv_getaddrinfo_t* req,+                   uv_getaddrinfo_cb getaddrinfo_cb,+                   const char* node,+                   const char* service,+                   const struct addrinfo* hints) {+  char hostname_ascii[256];+  int nodesize = 0;+  int servicesize = 0;+  int hintssize = 0;+  char* alloc_ptr = NULL;+  int err;+  long rc;++  if (req == NULL || (node == NULL && service == NULL)) {+    return UV_EINVAL;+  }++  UV_REQ_INIT(req, UV_GETADDRINFO);+  req->getaddrinfo_cb = getaddrinfo_cb;+  req->addrinfo = NULL;+  req->loop = loop;+  req->retcode = 0;++  /* calculate required memory size for all input values */+  if (node != NULL) {+    rc = uv__idna_toascii(node,+                          node + strlen(node),+                          hostname_ascii,+                          hostname_ascii + sizeof(hostname_ascii));+    if (rc < 0)+      return rc;+    nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, hostname_ascii,+                                                -1, NULL, 0) * sizeof(WCHAR));+    if (nodesize == 0) {+      err = GetLastError();+      goto error;+    }+    node = hostname_ascii;+  }++  if (service != NULL) {+    servicesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8,+                                                   0,+                                                   service,+                                                   -1,+                                                   NULL,+                                                   0) *+                               sizeof(WCHAR));+    if (servicesize == 0) {+      err = GetLastError();+      goto error;+    }+  }+  if (hints != NULL) {+    hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW));+  }++  /* allocate memory for inputs, and partition it as needed */+  alloc_ptr = (char*)uv__malloc(nodesize + servicesize + hintssize);+  if (!alloc_ptr) {+    err = WSAENOBUFS;+    goto error;+  }++  /* save alloc_ptr now so we can free if error */+  req->alloc = (void*)alloc_ptr;++  /* Convert node string to UTF16 into allocated memory and save pointer in the+   * request. */+  if (node != NULL) {+    req->node = (WCHAR*)alloc_ptr;+    if (MultiByteToWideChar(CP_UTF8,+                            0,+                            node,+                            -1,+                            (WCHAR*) alloc_ptr,+                            nodesize / sizeof(WCHAR)) == 0) {+      err = GetLastError();+      goto error;+    }+    alloc_ptr += nodesize;+  } else {+    req->node = NULL;+  }++  /* Convert service string to UTF16 into allocated memory and save pointer in+   * the req. */+  if (service != NULL) {+    req->service = (WCHAR*)alloc_ptr;+    if (MultiByteToWideChar(CP_UTF8,+                            0,+                            service,+                            -1,+                            (WCHAR*) alloc_ptr,+                            servicesize / sizeof(WCHAR)) == 0) {+      err = GetLastError();+      goto error;+    }+    alloc_ptr += servicesize;+  } else {+    req->service = NULL;+  }++  /* copy hints to allocated memory and save pointer in req */+  if (hints != NULL) {+    req->addrinfow = (struct addrinfoW*)alloc_ptr;+    req->addrinfow->ai_family = hints->ai_family;+    req->addrinfow->ai_socktype = hints->ai_socktype;+    req->addrinfow->ai_protocol = hints->ai_protocol;+    req->addrinfow->ai_flags = hints->ai_flags;+    req->addrinfow->ai_addrlen = 0;+    req->addrinfow->ai_canonname = NULL;+    req->addrinfow->ai_addr = NULL;+    req->addrinfow->ai_next = NULL;+  } else {+    req->addrinfow = NULL;+  }++  uv__req_register(loop, req);++  if (getaddrinfo_cb) {+    uv__work_submit(loop,+                    &req->work_req,+                    UV__WORK_SLOW_IO,+                    uv__getaddrinfo_work,+                    uv__getaddrinfo_done);+    return 0;+  } else {+    uv__getaddrinfo_work(&req->work_req);+    uv__getaddrinfo_done(&req->work_req, 0);+    return req->retcode;+  }++error:+  if (req != NULL) {+    uv__free(req->alloc);+    req->alloc = NULL;+  }+  return uv_translate_sys_error(err);+}++int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {+  NET_LUID luid;+  wchar_t wname[NDIS_IF_MAX_STRING_SIZE + 1]; /* Add one for the NUL. */+  DWORD bufsize;+  int r;++  if (buffer == NULL || size == NULL || *size == 0)+    return UV_EINVAL;++  r = ConvertInterfaceIndexToLuid(ifindex, &luid);++  if (r != 0)+    return uv_translate_sys_error(r);++  r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));++  if (r != 0)+    return uv_translate_sys_error(r);++  /* Check how much space we need */+  bufsize = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL);++  if (bufsize == 0) {+    return uv_translate_sys_error(GetLastError());+  } else if (bufsize > *size) {+    *size = bufsize;+    return UV_ENOBUFS;+  }++  /* Convert to UTF-8 */+  bufsize = WideCharToMultiByte(CP_UTF8,+                                0,+                                wname,+                                -1,+                                buffer,+                                *size,+                                NULL,+                                NULL);++  if (bufsize == 0)+    return uv_translate_sys_error(GetLastError());++  *size = bufsize - 1;+  return 0;+}++int uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) {+  int r;++  if (buffer == NULL || size == NULL || *size == 0)+    return UV_EINVAL;++  r = snprintf(buffer, *size, "%d", ifindex);++  if (r < 0)+    return uv_translate_sys_error(r);++  if (r >= (int) *size) {+    *size = r + 1;+    return UV_ENOBUFS;+  }++  *size = r;+  return 0;+}
+ third_party/libuv/src/win/getnameinfo.c view
@@ -0,0 +1,157 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+*+* Permission is hereby granted, free of charge, to any person obtaining a copy+* of this software and associated documentation files (the "Software"), to+* deal in the Software without restriction, including without limitation the+* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+* sell copies of the Software, and to permit persons to whom the Software is+* furnished to do so, subject to the following conditions:+*+* The above copyright notice and this permission notice shall be included in+* all copies or substantial portions of the Software.+*+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+* IN THE SOFTWARE.+*/++#include <assert.h>+#include <stdio.h>++#include "uv.h"+#include "internal.h"+#include "req-inl.h"++#ifndef GetNameInfo+int WSAAPI GetNameInfoW(+  const SOCKADDR *pSockaddr,+  socklen_t SockaddrLength,+  PWCHAR pNodeBuffer,+  DWORD NodeBufferSize,+  PWCHAR pServiceBuffer,+  DWORD ServiceBufferSize,+  INT Flags+);+#endif++static void uv__getnameinfo_work(struct uv__work* w) {+  uv_getnameinfo_t* req;+  WCHAR host[NI_MAXHOST];+  WCHAR service[NI_MAXSERV];+  int ret;++  req = container_of(w, uv_getnameinfo_t, work_req);+  if (GetNameInfoW((struct sockaddr*)&req->storage,+                   sizeof(req->storage),+                   host,+                   ARRAY_SIZE(host),+                   service,+                   ARRAY_SIZE(service),+                   req->flags)) {+    ret = WSAGetLastError();+    req->retcode = uv__getaddrinfo_translate_error(ret);+    return;+  }++  ret = WideCharToMultiByte(CP_UTF8,+                            0,+                            host,+                            -1,+                            req->host,+                            sizeof(req->host),+                            NULL,+                            NULL);+  if (ret == 0) {+    req->retcode = uv_translate_sys_error(GetLastError());+    return;+  }++  ret = WideCharToMultiByte(CP_UTF8,+                            0,+                            service,+                            -1,+                            req->service,+                            sizeof(req->service),+                            NULL,+                            NULL);+  if (ret == 0) {+    req->retcode = uv_translate_sys_error(GetLastError());+  }+}+++/*+* Called from uv_run when complete.+*/+static void uv__getnameinfo_done(struct uv__work* w, int status) {+  uv_getnameinfo_t* req;+  char* host;+  char* service;++  req = container_of(w, uv_getnameinfo_t, work_req);+  uv__req_unregister(req->loop, req);+  host = service = NULL;++  if (status == UV_ECANCELED) {+    assert(req->retcode == 0);+    req->retcode = UV_EAI_CANCELED;+  } else if (req->retcode == 0) {+    host = req->host;+    service = req->service;+  }++  if (req->getnameinfo_cb)+    req->getnameinfo_cb(req, req->retcode, host, service);+}+++/*+* Entry point for getnameinfo+* return 0 if a callback will be made+* return error code if validation fails+*/+int uv_getnameinfo(uv_loop_t* loop,+                   uv_getnameinfo_t* req,+                   uv_getnameinfo_cb getnameinfo_cb,+                   const struct sockaddr* addr,+                   int flags) {+  if (req == NULL || addr == NULL)+    return UV_EINVAL;++  if (addr->sa_family == AF_INET) {+    memcpy(&req->storage,+           addr,+           sizeof(struct sockaddr_in));+  } else if (addr->sa_family == AF_INET6) {+    memcpy(&req->storage,+           addr,+           sizeof(struct sockaddr_in6));+  } else {+    return UV_EINVAL;+  }++  UV_REQ_INIT(req, UV_GETNAMEINFO);+  uv__req_register(loop, req);++  req->getnameinfo_cb = getnameinfo_cb;+  req->flags = flags;+  req->loop = loop;+  req->retcode = 0;++  if (getnameinfo_cb) {+    uv__work_submit(loop,+                    &req->work_req,+                    UV__WORK_SLOW_IO,+                    uv__getnameinfo_work,+                    uv__getnameinfo_done);+    return 0;+  } else {+    uv__getnameinfo_work(&req->work_req);+    uv__getnameinfo_done(&req->work_req, 0);+    return req->retcode;+  }+}
+ third_party/libuv/src/win/handle-inl.h view
@@ -0,0 +1,180 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#ifndef UV_WIN_HANDLE_INL_H_+#define UV_WIN_HANDLE_INL_H_++#include <assert.h>+#include <io.h>++#include "uv.h"+#include "internal.h"+++#define DECREASE_ACTIVE_COUNT(loop, handle)                             \+  do {                                                                  \+    if (--(handle)->activecnt == 0 &&                                   \+        !((handle)->flags & UV_HANDLE_CLOSING)) {                       \+      uv__handle_stop((handle));                                        \+    }                                                                   \+    assert((handle)->activecnt >= 0);                                   \+  } while (0)+++#define INCREASE_ACTIVE_COUNT(loop, handle)                             \+  do {                                                                  \+    if ((handle)->activecnt++ == 0) {                                   \+      uv__handle_start((handle));                                       \+    }                                                                   \+    assert((handle)->activecnt > 0);                                    \+  } while (0)+++#define DECREASE_PENDING_REQ_COUNT(handle)                              \+  do {                                                                  \+    assert(handle->reqs_pending > 0);                                   \+    handle->reqs_pending--;                                             \+                                                                        \+    if (handle->flags & UV_HANDLE_CLOSING &&                            \+        handle->reqs_pending == 0) {                                    \+      uv_want_endgame(loop, (uv_handle_t*)handle);                      \+    }                                                                   \+  } while (0)+++#define uv__handle_closing(handle)                                      \+  do {                                                                  \+    assert(!((handle)->flags & UV_HANDLE_CLOSING));                     \+                                                                        \+    if (!(((handle)->flags & UV_HANDLE_ACTIVE) &&                       \+          ((handle)->flags & UV_HANDLE_REF)))                           \+      uv__active_handle_add((uv_handle_t*) (handle));                   \+                                                                        \+    (handle)->flags |= UV_HANDLE_CLOSING;                               \+    (handle)->flags &= ~UV_HANDLE_ACTIVE;                               \+  } while (0)+++#define uv__handle_close(handle)                                        \+  do {                                                                  \+    QUEUE_REMOVE(&(handle)->handle_queue);                              \+    uv__active_handle_rm((uv_handle_t*) (handle));                      \+                                                                        \+    (handle)->flags |= UV_HANDLE_CLOSED;                                \+                                                                        \+    if ((handle)->close_cb)                                             \+      (handle)->close_cb((uv_handle_t*) (handle));                      \+  } while (0)+++INLINE static void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) {+  if (!(handle->flags & UV_HANDLE_ENDGAME_QUEUED)) {+    handle->flags |= UV_HANDLE_ENDGAME_QUEUED;++    handle->endgame_next = loop->endgame_handles;+    loop->endgame_handles = handle;+  }+}+++INLINE static void uv_process_endgames(uv_loop_t* loop) {+  uv_handle_t* handle;++  while (loop->endgame_handles) {+    handle = loop->endgame_handles;+    loop->endgame_handles = handle->endgame_next;++    handle->flags &= ~UV_HANDLE_ENDGAME_QUEUED;++    switch (handle->type) {+      case UV_TCP:+        uv_tcp_endgame(loop, (uv_tcp_t*) handle);+        break;++      case UV_NAMED_PIPE:+        uv_pipe_endgame(loop, (uv_pipe_t*) handle);+        break;++      case UV_TTY:+        uv_tty_endgame(loop, (uv_tty_t*) handle);+        break;++      case UV_UDP:+        uv_udp_endgame(loop, (uv_udp_t*) handle);+        break;++      case UV_POLL:+        uv_poll_endgame(loop, (uv_poll_t*) handle);+        break;++      case UV_TIMER:+        uv__timer_close((uv_timer_t*) handle);+        uv__handle_close(handle);+        break;++      case UV_PREPARE:+      case UV_CHECK:+      case UV_IDLE:+        uv_loop_watcher_endgame(loop, handle);+        break;++      case UV_ASYNC:+        uv_async_endgame(loop, (uv_async_t*) handle);+        break;++      case UV_SIGNAL:+        uv_signal_endgame(loop, (uv_signal_t*) handle);+        break;++      case UV_PROCESS:+        uv_process_endgame(loop, (uv_process_t*) handle);+        break;++      case UV_FS_EVENT:+        uv_fs_event_endgame(loop, (uv_fs_event_t*) handle);+        break;++      case UV_FS_POLL:+        uv__fs_poll_endgame(loop, (uv_fs_poll_t*) handle);+        break;++      default:+        assert(0);+        break;+    }+  }+}++INLINE static HANDLE uv__get_osfhandle(int fd)+{+  /* _get_osfhandle() raises an assert in debug builds if the FD is invalid.+   * But it also correctly checks the FD and returns INVALID_HANDLE_VALUE for+   * invalid FDs in release builds (or if you let the assert continue). So this+   * wrapper function disables asserts when calling _get_osfhandle. */++  HANDLE handle;+  UV_BEGIN_DISABLE_CRT_ASSERT();+  handle = (HANDLE) _get_osfhandle(fd);+  UV_END_DISABLE_CRT_ASSERT();+  return handle;+}++#endif /* UV_WIN_HANDLE_INL_H_ */
+ third_party/libuv/src/win/handle.c view
@@ -0,0 +1,163 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <io.h>+#include <stdlib.h>++#include "uv.h"+#include "internal.h"+#include "handle-inl.h"+++uv_handle_type uv_guess_handle(uv_file file) {+  HANDLE handle;+  DWORD mode;++  if (file < 0) {+    return UV_UNKNOWN_HANDLE;+  }++  handle = uv__get_osfhandle(file);++  switch (GetFileType(handle)) {+    case FILE_TYPE_CHAR:+      if (GetConsoleMode(handle, &mode)) {+        return UV_TTY;+      } else {+        return UV_FILE;+      }++    case FILE_TYPE_PIPE:+      return UV_NAMED_PIPE;++    case FILE_TYPE_DISK:+      return UV_FILE;++    default:+      return UV_UNKNOWN_HANDLE;+  }+}+++int uv_is_active(const uv_handle_t* handle) {+  return (handle->flags & UV_HANDLE_ACTIVE) &&+        !(handle->flags & UV_HANDLE_CLOSING);+}+++void uv_close(uv_handle_t* handle, uv_close_cb cb) {+  uv_loop_t* loop = handle->loop;++  if (handle->flags & UV_HANDLE_CLOSING) {+    assert(0);+    return;+  }++  handle->close_cb = cb;++  /* Handle-specific close actions */+  switch (handle->type) {+    case UV_TCP:+      uv_tcp_close(loop, (uv_tcp_t*)handle);+      return;++    case UV_NAMED_PIPE:+      uv_pipe_close(loop, (uv_pipe_t*) handle);+      return;++    case UV_TTY:+      uv_tty_close((uv_tty_t*) handle);+      return;++    case UV_UDP:+      uv_udp_close(loop, (uv_udp_t*) handle);+      return;++    case UV_POLL:+      uv_poll_close(loop, (uv_poll_t*) handle);+      return;++    case UV_TIMER:+      uv_timer_stop((uv_timer_t*)handle);+      uv__handle_closing(handle);+      uv_want_endgame(loop, handle);+      return;++    case UV_PREPARE:+      uv_prepare_stop((uv_prepare_t*)handle);+      uv__handle_closing(handle);+      uv_want_endgame(loop, handle);+      return;++    case UV_CHECK:+      uv_check_stop((uv_check_t*)handle);+      uv__handle_closing(handle);+      uv_want_endgame(loop, handle);+      return;++    case UV_IDLE:+      uv_idle_stop((uv_idle_t*)handle);+      uv__handle_closing(handle);+      uv_want_endgame(loop, handle);+      return;++    case UV_ASYNC:+      uv_async_close(loop, (uv_async_t*) handle);+      return;++    case UV_SIGNAL:+      uv_signal_close(loop, (uv_signal_t*) handle);+      return;++    case UV_PROCESS:+      uv_process_close(loop, (uv_process_t*) handle);+      return;++    case UV_FS_EVENT:+      uv_fs_event_close(loop, (uv_fs_event_t*) handle);+      return;++    case UV_FS_POLL:+      uv__fs_poll_close((uv_fs_poll_t*) handle);+      uv__handle_closing(handle);+      uv_want_endgame(loop, handle);+      return;++    default:+      /* Not supported */+      abort();+  }+}+++int uv_is_closing(const uv_handle_t* handle) {+  return !!(handle->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED));+}+++uv_os_fd_t uv_get_osfhandle(int fd) {+  return uv__get_osfhandle(fd);+}++int uv_open_osfhandle(uv_os_fd_t os_fd) {+  return _open_osfhandle((intptr_t) os_fd, 0);+}
+ third_party/libuv/src/win/internal.h view
@@ -0,0 +1,334 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#ifndef UV_WIN_INTERNAL_H_+#define UV_WIN_INTERNAL_H_++#include "uv.h"+#include "../uv-common.h"++#include "uv/tree.h"+#include "winapi.h"+#include "winsock.h"++#ifdef _MSC_VER+# define INLINE __inline+# define UV_THREAD_LOCAL __declspec( thread )+#else+# define INLINE inline+# define UV_THREAD_LOCAL __thread+#endif+++#ifdef _DEBUG++extern UV_THREAD_LOCAL int uv__crt_assert_enabled;++#define UV_BEGIN_DISABLE_CRT_ASSERT()                           \+  {                                                             \+    int uv__saved_crt_assert_enabled = uv__crt_assert_enabled;  \+    uv__crt_assert_enabled = FALSE;+++#define UV_END_DISABLE_CRT_ASSERT()                             \+    uv__crt_assert_enabled = uv__saved_crt_assert_enabled;      \+  }++#else+#define UV_BEGIN_DISABLE_CRT_ASSERT()+#define UV_END_DISABLE_CRT_ASSERT()+#endif++/*+ * TCP+ */++typedef enum {+  UV__IPC_SOCKET_XFER_NONE = 0,+  UV__IPC_SOCKET_XFER_TCP_CONNECTION,+  UV__IPC_SOCKET_XFER_TCP_SERVER+} uv__ipc_socket_xfer_type_t;++typedef struct {+  WSAPROTOCOL_INFOW socket_info;+  uint32_t delayed_error;+} uv__ipc_socket_xfer_info_t;++int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);+int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client);+int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,+    uv_read_cb read_cb);+int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,+    const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);+int uv__tcp_try_write(uv_tcp_t* handle, const uv_buf_t bufs[],+    unsigned int nbufs);++void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req);+void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,+    uv_write_t* req);+void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,+    uv_req_t* req);+void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,+    uv_connect_t* req);++void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);+void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);++int uv__tcp_xfer_export(uv_tcp_t* handle,+                        int pid,+                        uv__ipc_socket_xfer_type_t* xfer_type,+                        uv__ipc_socket_xfer_info_t* xfer_info);+int uv__tcp_xfer_import(uv_tcp_t* tcp,+                        uv__ipc_socket_xfer_type_t xfer_type,+                        uv__ipc_socket_xfer_info_t* xfer_info);+++/*+ * UDP+ */+void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, uv_req_t* req);+void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,+    uv_udp_send_t* req);++void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle);+void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle);+++/*+ * Pipes+ */+int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,+    char* name, size_t nameSize);++int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);+int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client);+int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,+    uv_read_cb read_cb);+void uv__pipe_read_stop(uv_pipe_t* handle);+int uv__pipe_write(uv_loop_t* loop,+                   uv_write_t* req,+                   uv_pipe_t* handle,+                   const uv_buf_t bufs[],+                   size_t nbufs,+                   uv_stream_t* send_handle,+                   uv_write_cb cb);++void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,+    uv_req_t* req);+void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,+    uv_write_t* req);+void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,+    uv_req_t* raw_req);+void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,+    uv_connect_t* req);+void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,+    uv_shutdown_t* req);++void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle);+void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle);+void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle);+++/*+ * TTY+ */+void uv_console_init(void);++int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,+    uv_read_cb read_cb);+int uv_tty_read_stop(uv_tty_t* handle);+int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle,+    const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);+int uv__tty_try_write(uv_tty_t* handle, const uv_buf_t bufs[],+    unsigned int nbufs);+void uv_tty_close(uv_tty_t* handle);++void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,+    uv_req_t* req);+void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,+    uv_write_t* req);+/*+ * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working+ * TODO: find a way to remove it+ */+void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,+    uv_req_t* raw_req);+/*+ * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working+ * TODO: find a way to remove it+ */+void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,+    uv_connect_t* req);++void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle);+++/*+ * Poll watchers+ */+void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,+    uv_req_t* req);++int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle);+void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle);+++/*+ * Loop watchers+ */+void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle);++void uv_prepare_invoke(uv_loop_t* loop);+void uv_check_invoke(uv_loop_t* loop);+void uv_idle_invoke(uv_loop_t* loop);++void uv__once_init(void);+++/*+ * Async watcher+ */+void uv_async_close(uv_loop_t* loop, uv_async_t* handle);+void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle);++void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,+    uv_req_t* req);+++/*+ * Signal watcher+ */+void uv_signals_init(void);+int uv__signal_dispatch(int signum);++void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle);+void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle);++void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,+    uv_req_t* req);+++/*+ * Spawn+ */+void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle);+void uv_process_close(uv_loop_t* loop, uv_process_t* handle);+void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle);+++/*+ * Error+ */+int uv_translate_sys_error(int sys_errno);+++/*+ * FS+ */+void uv_fs_init(void);+++/*+ * FS Event+ */+void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,+    uv_fs_event_t* handle);+void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle);+void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle);+++/*+ * Stat poller.+ */+void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle);+++/*+ * Utilities.+ */+void uv__util_init(void);++uint64_t uv__hrtime(double scale);+__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);+int uv__getpwuid_r(uv_passwd_t* pwd);+int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);+int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);+++/*+ * Process stdio handles.+ */+int uv__stdio_create(uv_loop_t* loop,+                     const uv_process_options_t* options,+                     BYTE** buffer_ptr);+void uv__stdio_destroy(BYTE* buffer);+void uv__stdio_noinherit(BYTE* buffer);+int uv__stdio_verify(BYTE* buffer, WORD size);+WORD uv__stdio_size(BYTE* buffer);+HANDLE uv__stdio_handle(BYTE* buffer, int fd);+++/*+ * Winapi and ntapi utility functions+ */+void uv_winapi_init(void);+++/*+ * Winsock utility functions+ */+void uv_winsock_init(void);++int uv_ntstatus_to_winsock_error(NTSTATUS status);++BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target);+BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target);++int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers,+    DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped,+    LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);+int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,+    DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr,+    int* addr_len, WSAOVERLAPPED *overlapped,+    LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);++int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,+    AFD_POLL_INFO* info_out, OVERLAPPED* overlapped);++/* Whether there are any non-IFS LSPs stacked on TCP */+extern int uv_tcp_non_ifs_lsp_ipv4;+extern int uv_tcp_non_ifs_lsp_ipv6;++/* Ip address used to bind to any port at any interface */+extern struct sockaddr_in uv_addr_ip4_any_;+extern struct sockaddr_in6 uv_addr_ip6_any_;++/*+ * Wake all loops with fake message+ */+void uv__wake_all_loops(void);++/*+ * Init system wake-up detection+ */+void uv__init_detect_system_wakeup(void);++#endif /* UV_WIN_INTERNAL_H_ */
+ third_party/libuv/src/win/loop-watcher.c view
@@ -0,0 +1,122 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>++#include "uv.h"+#include "internal.h"+#include "handle-inl.h"+++void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {+  if (handle->flags & UV_HANDLE_CLOSING) {+    assert(!(handle->flags & UV_HANDLE_CLOSED));+    handle->flags |= UV_HANDLE_CLOSED;+    uv__handle_close(handle);+  }+}+++#define UV_LOOP_WATCHER_DEFINE(name, NAME)                                    \+  int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) {              \+    uv__handle_init(loop, (uv_handle_t*) handle, UV_##NAME);                  \+                                                                              \+    return 0;                                                                 \+  }                                                                           \+                                                                              \+                                                                              \+  int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) {           \+    uv_loop_t* loop = handle->loop;                                           \+    uv_##name##_t* old_head;                                                  \+                                                                              \+    assert(handle->type == UV_##NAME);                                        \+                                                                              \+    if (uv__is_active(handle))                                                \+      return 0;                                                               \+                                                                              \+    if (cb == NULL)                                                           \+      return UV_EINVAL;                                                       \+                                                                              \+    old_head = loop->name##_handles;                                          \+                                                                              \+    handle->name##_next = old_head;                                           \+    handle->name##_prev = NULL;                                               \+                                                                              \+    if (old_head) {                                                           \+      old_head->name##_prev = handle;                                         \+    }                                                                         \+                                                                              \+    loop->name##_handles = handle;                                            \+                                                                              \+    handle->name##_cb = cb;                                                   \+    uv__handle_start(handle);                                                 \+                                                                              \+    return 0;                                                                 \+  }                                                                           \+                                                                              \+                                                                              \+  int uv_##name##_stop(uv_##name##_t* handle) {                               \+    uv_loop_t* loop = handle->loop;                                           \+                                                                              \+    assert(handle->type == UV_##NAME);                                        \+                                                                              \+    if (!uv__is_active(handle))                                               \+      return 0;                                                               \+                                                                              \+    /* Update loop head if needed */                                          \+    if (loop->name##_handles == handle) {                                     \+      loop->name##_handles = handle->name##_next;                             \+    }                                                                         \+                                                                              \+    /* Update the iterator-next pointer of needed */                          \+    if (loop->next_##name##_handle == handle) {                               \+      loop->next_##name##_handle = handle->name##_next;                       \+    }                                                                         \+                                                                              \+    if (handle->name##_prev) {                                                \+      handle->name##_prev->name##_next = handle->name##_next;                 \+    }                                                                         \+    if (handle->name##_next) {                                                \+      handle->name##_next->name##_prev = handle->name##_prev;                 \+    }                                                                         \+                                                                              \+    uv__handle_stop(handle);                                                  \+                                                                              \+    return 0;                                                                 \+  }                                                                           \+                                                                              \+                                                                              \+  void uv_##name##_invoke(uv_loop_t* loop) {                                  \+    uv_##name##_t* handle;                                                    \+                                                                              \+    (loop)->next_##name##_handle = (loop)->name##_handles;                    \+                                                                              \+    while ((loop)->next_##name##_handle != NULL) {                            \+      handle = (loop)->next_##name##_handle;                                  \+      (loop)->next_##name##_handle = handle->name##_next;                     \+                                                                              \+      handle->name##_cb(handle);                                              \+    }                                                                         \+  }++UV_LOOP_WATCHER_DEFINE(prepare, PREPARE)+UV_LOOP_WATCHER_DEFINE(check, CHECK)+UV_LOOP_WATCHER_DEFINE(idle, IDLE)
+ third_party/libuv/src/win/pipe.c view
@@ -0,0 +1,2386 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <io.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>++#include "handle-inl.h"+#include "internal.h"+#include "req-inl.h"+#include "stream-inl.h"+#include "uv-common.h"+#include "uv.h"++#include <aclapi.h>+#include <accctrl.h>++/* A zero-size buffer for use by uv_pipe_read */+static char uv_zero_[] = "";++/* Null uv_buf_t */+static const uv_buf_t uv_null_buf_ = { 0, NULL };++/* The timeout that the pipe will wait for the remote end to write data when+ * the local ends wants to shut it down. */+static const int64_t eof_timeout = 50; /* ms */++static const int default_pending_pipe_instances = 4;++/* Pipe prefix */+static char pipe_prefix[] = "\\\\?\\pipe";+static const int pipe_prefix_len = sizeof(pipe_prefix) - 1;++/* IPC incoming xfer queue item. */+typedef struct {+  uv__ipc_socket_xfer_type_t xfer_type;+  uv__ipc_socket_xfer_info_t xfer_info;+  QUEUE member;+} uv__ipc_xfer_queue_item_t;++/* IPC frame header flags. */+/* clang-format off */+enum {+  UV__IPC_FRAME_HAS_DATA                = 0x01,+  UV__IPC_FRAME_HAS_SOCKET_XFER         = 0x02,+  UV__IPC_FRAME_XFER_IS_TCP_CONNECTION  = 0x04,+  /* These are combinations of the flags above. */+  UV__IPC_FRAME_XFER_FLAGS              = 0x06,+  UV__IPC_FRAME_VALID_FLAGS             = 0x07+};+/* clang-format on */++/* IPC frame header. */+typedef struct {+  uint32_t flags;+  uint32_t reserved1;   /* Ignored. */+  uint32_t data_length; /* Must be zero if there is no data. */+  uint32_t reserved2;   /* Must be zero. */+} uv__ipc_frame_header_t;++/* To implement the IPC protocol correctly, these structures must have exactly+ * the right size. */+STATIC_ASSERT(sizeof(uv__ipc_frame_header_t) == 16);+STATIC_ASSERT(sizeof(uv__ipc_socket_xfer_info_t) == 632);++/* Coalesced write request. */+typedef struct {+  uv_write_t req;       /* Internal heap-allocated write request. */+  uv_write_t* user_req; /* Pointer to user-specified uv_write_t. */+} uv__coalesced_write_t;+++static void eof_timer_init(uv_pipe_t* pipe);+static void eof_timer_start(uv_pipe_t* pipe);+static void eof_timer_stop(uv_pipe_t* pipe);+static void eof_timer_cb(uv_timer_t* timer);+static void eof_timer_destroy(uv_pipe_t* pipe);+static void eof_timer_close_cb(uv_handle_t* handle);+++static void uv_unique_pipe_name(char* ptr, char* name, size_t size) {+  snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%lu", ptr, GetCurrentProcessId());+}+++int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {+  uv_stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);++  handle->reqs_pending = 0;+  handle->handle = INVALID_HANDLE_VALUE;+  handle->name = NULL;+  handle->pipe.conn.ipc_remote_pid = 0;+  handle->pipe.conn.ipc_data_frame.payload_remaining = 0;+  QUEUE_INIT(&handle->pipe.conn.ipc_xfer_queue);+  handle->pipe.conn.ipc_xfer_queue_length = 0;+  handle->ipc = ipc;+  handle->pipe.conn.non_overlapped_writes_tail = NULL;++  return 0;+}+++static void uv_pipe_connection_init(uv_pipe_t* handle) {+  uv_connection_init((uv_stream_t*) handle);+  handle->read_req.data = handle;+  handle->pipe.conn.eof_timer = NULL;+  assert(!(handle->flags & UV_HANDLE_PIPESERVER));+  if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {+    handle->pipe.conn.readfile_thread_handle = NULL;+    InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock);+  }+}+++static HANDLE open_named_pipe(const WCHAR* name, DWORD* duplex_flags) {+  HANDLE pipeHandle;++  /*+   * Assume that we have a duplex pipe first, so attempt to+   * connect with GENERIC_READ | GENERIC_WRITE.+   */+  pipeHandle = CreateFileW(name,+                           GENERIC_READ | GENERIC_WRITE,+                           0,+                           NULL,+                           OPEN_EXISTING,+                           FILE_FLAG_OVERLAPPED,+                           NULL);+  if (pipeHandle != INVALID_HANDLE_VALUE) {+    *duplex_flags = UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;+    return pipeHandle;+  }++  /*+   * If the pipe is not duplex CreateFileW fails with+   * ERROR_ACCESS_DENIED.  In that case try to connect+   * as a read-only or write-only.+   */+  if (GetLastError() == ERROR_ACCESS_DENIED) {+    pipeHandle = CreateFileW(name,+                             GENERIC_READ | FILE_WRITE_ATTRIBUTES,+                             0,+                             NULL,+                             OPEN_EXISTING,+                             FILE_FLAG_OVERLAPPED,+                             NULL);++    if (pipeHandle != INVALID_HANDLE_VALUE) {+      *duplex_flags = UV_HANDLE_READABLE;+      return pipeHandle;+    }+  }++  if (GetLastError() == ERROR_ACCESS_DENIED) {+    pipeHandle = CreateFileW(name,+                             GENERIC_WRITE | FILE_READ_ATTRIBUTES,+                             0,+                             NULL,+                             OPEN_EXISTING,+                             FILE_FLAG_OVERLAPPED,+                             NULL);++    if (pipeHandle != INVALID_HANDLE_VALUE) {+      *duplex_flags = UV_HANDLE_WRITABLE;+      return pipeHandle;+    }+  }++  return INVALID_HANDLE_VALUE;+}+++static void close_pipe(uv_pipe_t* pipe) {+  assert(pipe->u.fd == -1 || pipe->u.fd > 2);+  if (pipe->u.fd == -1)+    CloseHandle(pipe->handle);+  else+    close(pipe->u.fd);++  pipe->u.fd = -1;+  pipe->handle = INVALID_HANDLE_VALUE;+}+++int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,+    char* name, size_t nameSize) {+  HANDLE pipeHandle;+  int err;+  char* ptr = (char*)handle;++  for (;;) {+    uv_unique_pipe_name(ptr, name, nameSize);++    pipeHandle = CreateNamedPipeA(name,+      access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,+      PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0,+      NULL);++    if (pipeHandle != INVALID_HANDLE_VALUE) {+      /* No name collisions.  We're done. */+      break;+    }++    err = GetLastError();+    if (err != ERROR_PIPE_BUSY && err != ERROR_ACCESS_DENIED) {+      goto error;+    }++    /* Pipe name collision.  Increment the pointer and try again. */+    ptr++;+  }++  if (CreateIoCompletionPort(pipeHandle,+                             loop->iocp,+                             (ULONG_PTR)handle,+                             0) == NULL) {+    err = GetLastError();+    goto error;+  }++  uv_pipe_connection_init(handle);+  handle->handle = pipeHandle;++  return 0;++ error:+  if (pipeHandle != INVALID_HANDLE_VALUE) {+    CloseHandle(pipeHandle);+  }++  return err;+}+++static int uv_set_pipe_handle(uv_loop_t* loop,+                              uv_pipe_t* handle,+                              HANDLE pipeHandle,+                              int fd,+                              DWORD duplex_flags) {+  NTSTATUS nt_status;+  IO_STATUS_BLOCK io_status;+  FILE_MODE_INFORMATION mode_info;+  DWORD mode = PIPE_READMODE_BYTE | PIPE_WAIT;+  DWORD current_mode = 0;+  DWORD err = 0;++  if (!(handle->flags & UV_HANDLE_PIPESERVER) &&+      handle->handle != INVALID_HANDLE_VALUE)+    return UV_EBUSY;++  if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) {+    err = GetLastError();+    if (err == ERROR_ACCESS_DENIED) {+      /*+       * SetNamedPipeHandleState can fail if the handle doesn't have either+       * GENERIC_WRITE  or FILE_WRITE_ATTRIBUTES.+       * But if the handle already has the desired wait and blocking modes+       * we can continue.+       */+      if (!GetNamedPipeHandleState(pipeHandle, &current_mode, NULL, NULL,+                                   NULL, NULL, 0)) {+        return -1;+      } else if (current_mode & PIPE_NOWAIT) {+        SetLastError(ERROR_ACCESS_DENIED);+        return -1;+      }+    } else {+      /* If this returns ERROR_INVALID_PARAMETER we probably opened+       * something that is not a pipe. */+      if (err == ERROR_INVALID_PARAMETER) {+        SetLastError(WSAENOTSOCK);+      }+      return -1;+    }+  }++  /* Check if the pipe was created with FILE_FLAG_OVERLAPPED. */+  nt_status = pNtQueryInformationFile(pipeHandle,+                                      &io_status,+                                      &mode_info,+                                      sizeof(mode_info),+                                      FileModeInformation);+  if (nt_status != STATUS_SUCCESS) {+    return -1;+  }++  if (mode_info.Mode & FILE_SYNCHRONOUS_IO_ALERT ||+      mode_info.Mode & FILE_SYNCHRONOUS_IO_NONALERT) {+    /* Non-overlapped pipe. */+    handle->flags |= UV_HANDLE_NON_OVERLAPPED_PIPE;+  } else {+    /* Overlapped pipe.  Try to associate with IOCP. */+    if (CreateIoCompletionPort(pipeHandle,+                               loop->iocp,+                               (ULONG_PTR)handle,+                               0) == NULL) {+      handle->flags |= UV_HANDLE_EMULATE_IOCP;+    }+  }++  handle->handle = pipeHandle;+  handle->u.fd = fd;+  handle->flags |= duplex_flags;++  return 0;+}+++static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) {+  uv_loop_t* loop;+  uv_pipe_t* handle;+  uv_shutdown_t* req;++  req = (uv_shutdown_t*) parameter;+  assert(req);+  handle = (uv_pipe_t*) req->handle;+  assert(handle);+  loop = handle->loop;+  assert(loop);++  FlushFileBuffers(handle->handle);++  /* Post completed */+  POST_COMPLETION_FOR_REQ(loop, req);++  return 0;+}+++void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {+  int err;+  DWORD result;+  uv_shutdown_t* req;+  NTSTATUS nt_status;+  IO_STATUS_BLOCK io_status;+  FILE_PIPE_LOCAL_INFORMATION pipe_info;+  uv__ipc_xfer_queue_item_t* xfer_queue_item;++  if ((handle->flags & UV_HANDLE_CONNECTION) &&+      handle->stream.conn.shutdown_req != NULL &&+      handle->stream.conn.write_reqs_pending == 0) {+    req = handle->stream.conn.shutdown_req;++    /* Clear the shutdown_req field so we don't go here again. */+    handle->stream.conn.shutdown_req = NULL;++    if (handle->flags & UV_HANDLE_CLOSING) {+      UNREGISTER_HANDLE_REQ(loop, handle, req);++      /* Already closing. Cancel the shutdown. */+      if (req->cb) {+        req->cb(req, UV_ECANCELED);+      }++      DECREASE_PENDING_REQ_COUNT(handle);+      return;+    }++    /* Try to avoid flushing the pipe buffer in the thread pool. */+    nt_status = pNtQueryInformationFile(handle->handle,+                                        &io_status,+                                        &pipe_info,+                                        sizeof pipe_info,+                                        FilePipeLocalInformation);++    if (nt_status != STATUS_SUCCESS) {+      /* Failure */+      UNREGISTER_HANDLE_REQ(loop, handle, req);++      handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */+      if (req->cb) {+        err = pRtlNtStatusToDosError(nt_status);+        req->cb(req, uv_translate_sys_error(err));+      }++      DECREASE_PENDING_REQ_COUNT(handle);+      return;+    }++    if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) {+      /* Short-circuit, no need to call FlushFileBuffers. */+      uv_insert_pending_req(loop, (uv_req_t*) req);+      return;+    }++    /* Run FlushFileBuffers in the thread pool. */+    result = QueueUserWorkItem(pipe_shutdown_thread_proc,+                               req,+                               WT_EXECUTELONGFUNCTION);+    if (result) {+      return;++    } else {+      /* Failure. */+      UNREGISTER_HANDLE_REQ(loop, handle, req);++      handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */+      if (req->cb) {+        err = GetLastError();+        req->cb(req, uv_translate_sys_error(err));+      }++      DECREASE_PENDING_REQ_COUNT(handle);+      return;+    }+  }++  if (handle->flags & UV_HANDLE_CLOSING &&+      handle->reqs_pending == 0) {+    assert(!(handle->flags & UV_HANDLE_CLOSED));++    if (handle->flags & UV_HANDLE_CONNECTION) {+      /* Free pending sockets */+      while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) {+        QUEUE* q;+        SOCKET socket;++        q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue);+        QUEUE_REMOVE(q);+        xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);++        /* Materialize socket and close it */+        socket = WSASocketW(FROM_PROTOCOL_INFO,+                            FROM_PROTOCOL_INFO,+                            FROM_PROTOCOL_INFO,+                            &xfer_queue_item->xfer_info.socket_info,+                            0,+                            WSA_FLAG_OVERLAPPED);+        uv__free(xfer_queue_item);++        if (socket != INVALID_SOCKET)+          closesocket(socket);+      }+      handle->pipe.conn.ipc_xfer_queue_length = 0;++      if (handle->flags & UV_HANDLE_EMULATE_IOCP) {+        if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {+          UnregisterWait(handle->read_req.wait_handle);+          handle->read_req.wait_handle = INVALID_HANDLE_VALUE;+        }+        if (handle->read_req.event_handle) {+          CloseHandle(handle->read_req.event_handle);+          handle->read_req.event_handle = NULL;+        }+      }++      if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)+        DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock);+    }++    if (handle->flags & UV_HANDLE_PIPESERVER) {+      assert(handle->pipe.serv.accept_reqs);+      uv__free(handle->pipe.serv.accept_reqs);+      handle->pipe.serv.accept_reqs = NULL;+    }++    uv__handle_close(handle);+  }+}+++void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {+  if (handle->flags & UV_HANDLE_BOUND)+    return;+  handle->pipe.serv.pending_instances = count;+  handle->flags |= UV_HANDLE_PIPESERVER;+}+++/* Creates a pipe server. */+int uv_pipe_bind(uv_pipe_t* handle, const char* name) {+  uv_loop_t* loop = handle->loop;+  int i, err, nameSize;+  uv_pipe_accept_t* req;++  if (handle->flags & UV_HANDLE_BOUND) {+    return UV_EINVAL;+  }++  if (!name) {+    return UV_EINVAL;+  }++  if (!(handle->flags & UV_HANDLE_PIPESERVER)) {+    handle->pipe.serv.pending_instances = default_pending_pipe_instances;+  }++  handle->pipe.serv.accept_reqs = (uv_pipe_accept_t*)+    uv__malloc(sizeof(uv_pipe_accept_t) * handle->pipe.serv.pending_instances);+  if (!handle->pipe.serv.accept_reqs) {+    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+  }++  for (i = 0; i < handle->pipe.serv.pending_instances; i++) {+    req = &handle->pipe.serv.accept_reqs[i];+    UV_REQ_INIT(req, UV_ACCEPT);+    req->data = handle;+    req->pipeHandle = INVALID_HANDLE_VALUE;+    req->next_pending = NULL;+  }++  /* Convert name to UTF16. */+  nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);+  handle->name = (WCHAR*)uv__malloc(nameSize);+  if (!handle->name) {+    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+  }++  if (!MultiByteToWideChar(CP_UTF8,+                           0,+                           name,+                           -1,+                           handle->name,+                           nameSize / sizeof(WCHAR))) {+    err = GetLastError();+    goto error;+  }++  /*+   * Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE.+   * If this fails then there's already a pipe server for the given pipe name.+   */+  handle->pipe.serv.accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name,+      PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |+      FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,+      PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,+      PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);++  if (handle->pipe.serv.accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) {+    err = GetLastError();+    if (err == ERROR_ACCESS_DENIED) {+      err = WSAEADDRINUSE;  /* Translates to UV_EADDRINUSE. */+    } else if (err == ERROR_PATH_NOT_FOUND || err == ERROR_INVALID_NAME) {+      err = WSAEACCES;  /* Translates to UV_EACCES. */+    }+    goto error;+  }++  if (uv_set_pipe_handle(loop,+                         handle,+                         handle->pipe.serv.accept_reqs[0].pipeHandle,+                         -1,+                         0)) {+    err = GetLastError();+    goto error;+  }++  handle->pipe.serv.pending_accepts = NULL;+  handle->flags |= UV_HANDLE_PIPESERVER;+  handle->flags |= UV_HANDLE_BOUND;++  return 0;++error:+  if (handle->name) {+    uv__free(handle->name);+    handle->name = NULL;+  }++  if (handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) {+    CloseHandle(handle->pipe.serv.accept_reqs[0].pipeHandle);+    handle->pipe.serv.accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE;+  }++  return uv_translate_sys_error(err);+}+++static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {+  uv_loop_t* loop;+  uv_pipe_t* handle;+  uv_connect_t* req;+  HANDLE pipeHandle = INVALID_HANDLE_VALUE;+  DWORD duplex_flags;++  req = (uv_connect_t*) parameter;+  assert(req);+  handle = (uv_pipe_t*) req->handle;+  assert(handle);+  loop = handle->loop;+  assert(loop);++  /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait+   * for the pipe to become available with WaitNamedPipe. */+  while (WaitNamedPipeW(handle->name, 30000)) {+    /* The pipe is now available, try to connect. */+    pipeHandle = open_named_pipe(handle->name, &duplex_flags);+    if (pipeHandle != INVALID_HANDLE_VALUE) {+      break;+    }++    SwitchToThread();+  }++  if (pipeHandle != INVALID_HANDLE_VALUE &&+      !uv_set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags)) {+    SET_REQ_SUCCESS(req);+  } else {+    SET_REQ_ERROR(req, GetLastError());+  }++  /* Post completed */+  POST_COMPLETION_FOR_REQ(loop, req);++  return 0;+}+++void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,+    const char* name, uv_connect_cb cb) {+  uv_loop_t* loop = handle->loop;+  int err, nameSize;+  HANDLE pipeHandle = INVALID_HANDLE_VALUE;+  DWORD duplex_flags;++  UV_REQ_INIT(req, UV_CONNECT);+  req->handle = (uv_stream_t*) handle;+  req->cb = cb;++  /* Convert name to UTF16. */+  nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);+  handle->name = (WCHAR*)uv__malloc(nameSize);+  if (!handle->name) {+    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+  }++  if (!MultiByteToWideChar(CP_UTF8,+                           0,+                           name,+                           -1,+                           handle->name,+                           nameSize / sizeof(WCHAR))) {+    err = GetLastError();+    goto error;+  }++  pipeHandle = open_named_pipe(handle->name, &duplex_flags);+  if (pipeHandle == INVALID_HANDLE_VALUE) {+    if (GetLastError() == ERROR_PIPE_BUSY) {+      /* Wait for the server to make a pipe instance available. */+      if (!QueueUserWorkItem(&pipe_connect_thread_proc,+                             req,+                             WT_EXECUTELONGFUNCTION)) {+        err = GetLastError();+        goto error;+      }++      REGISTER_HANDLE_REQ(loop, handle, req);+      handle->reqs_pending++;++      return;+    }++    err = GetLastError();+    goto error;+  }++  assert(pipeHandle != INVALID_HANDLE_VALUE);++  if (uv_set_pipe_handle(loop,+                         (uv_pipe_t*) req->handle,+                         pipeHandle,+                         -1,+                         duplex_flags)) {+    err = GetLastError();+    goto error;+  }++  SET_REQ_SUCCESS(req);+  uv_insert_pending_req(loop, (uv_req_t*) req);+  handle->reqs_pending++;+  REGISTER_HANDLE_REQ(loop, handle, req);+  return;++error:+  if (handle->name) {+    uv__free(handle->name);+    handle->name = NULL;+  }++  if (pipeHandle != INVALID_HANDLE_VALUE) {+    CloseHandle(pipeHandle);+  }++  /* Make this req pending reporting an error. */+  SET_REQ_ERROR(req, err);+  uv_insert_pending_req(loop, (uv_req_t*) req);+  handle->reqs_pending++;+  REGISTER_HANDLE_REQ(loop, handle, req);+  return;+}+++void uv__pipe_interrupt_read(uv_pipe_t* handle) {+  BOOL r;++  if (!(handle->flags & UV_HANDLE_READ_PENDING))+    return; /* No pending reads. */+  if (handle->flags & UV_HANDLE_CANCELLATION_PENDING)+    return; /* Already cancelled. */+  if (handle->handle == INVALID_HANDLE_VALUE)+    return; /* Pipe handle closed. */++  if (!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)) {+    /* Cancel asynchronous read. */+    r = CancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);+    assert(r || GetLastError() == ERROR_NOT_FOUND);++  } else {+    /* Cancel synchronous read (which is happening in the thread pool). */+    HANDLE thread;+    volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle;++    EnterCriticalSection(&handle->pipe.conn.readfile_thread_lock);++    thread = *thread_ptr;+    if (thread == NULL) {+      /* The thread pool thread has not yet reached the point of blocking, we+       * can pre-empt it by setting thread_handle to INVALID_HANDLE_VALUE. */+      *thread_ptr = INVALID_HANDLE_VALUE;++    } else {+      /* Spin until the thread has acknowledged (by setting the thread to+       * INVALID_HANDLE_VALUE) that it is past the point of blocking. */+      while (thread != INVALID_HANDLE_VALUE) {+        r = CancelSynchronousIo(thread);+        assert(r || GetLastError() == ERROR_NOT_FOUND);+        SwitchToThread(); /* Yield thread. */+        thread = *thread_ptr;+      }+    }++    LeaveCriticalSection(&handle->pipe.conn.readfile_thread_lock);+  }++  /* Set flag to indicate that read has been cancelled. */+  handle->flags |= UV_HANDLE_CANCELLATION_PENDING;+}+++void uv__pipe_read_stop(uv_pipe_t* handle) {+  handle->flags &= ~UV_HANDLE_READING;+  DECREASE_ACTIVE_COUNT(handle->loop, handle);++  uv__pipe_interrupt_read(handle);+}+++/* Cleans up uv_pipe_t (server or connection) and all resources associated with+ * it. */+void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {+  int i;+  HANDLE pipeHandle;++  uv__pipe_interrupt_read(handle);++  if (handle->name) {+    uv__free(handle->name);+    handle->name = NULL;+  }++  if (handle->flags & UV_HANDLE_PIPESERVER) {+    for (i = 0; i < handle->pipe.serv.pending_instances; i++) {+      pipeHandle = handle->pipe.serv.accept_reqs[i].pipeHandle;+      if (pipeHandle != INVALID_HANDLE_VALUE) {+        CloseHandle(pipeHandle);+        handle->pipe.serv.accept_reqs[i].pipeHandle = INVALID_HANDLE_VALUE;+      }+    }+    handle->handle = INVALID_HANDLE_VALUE;+  }++  if (handle->flags & UV_HANDLE_CONNECTION) {+    handle->flags &= ~UV_HANDLE_WRITABLE;+    eof_timer_destroy(handle);+  }++  if ((handle->flags & UV_HANDLE_CONNECTION)+      && handle->handle != INVALID_HANDLE_VALUE)+    close_pipe(handle);+}+++void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle) {+  if (handle->flags & UV_HANDLE_READING) {+    handle->flags &= ~UV_HANDLE_READING;+    DECREASE_ACTIVE_COUNT(loop, handle);+  }++  if (handle->flags & UV_HANDLE_LISTENING) {+    handle->flags &= ~UV_HANDLE_LISTENING;+    DECREASE_ACTIVE_COUNT(loop, handle);+  }++  uv_pipe_cleanup(loop, handle);++  if (handle->reqs_pending == 0) {+    uv_want_endgame(loop, (uv_handle_t*) handle);+  }++  handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);+  uv__handle_closing(handle);+}+++void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,+    uv_pipe_accept_t* req, BOOL firstInstance) {+  assert(handle->flags & UV_HANDLE_LISTENING);++  if (!firstInstance) {+    assert(req->pipeHandle == INVALID_HANDLE_VALUE);++    req->pipeHandle = CreateNamedPipeW(handle->name,+        PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_DAC,+        PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,+        PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);++    if (req->pipeHandle == INVALID_HANDLE_VALUE) {+      SET_REQ_ERROR(req, GetLastError());+      uv_insert_pending_req(loop, (uv_req_t*) req);+      handle->reqs_pending++;+      return;+    }++    if (uv_set_pipe_handle(loop, handle, req->pipeHandle, -1, 0)) {+      CloseHandle(req->pipeHandle);+      req->pipeHandle = INVALID_HANDLE_VALUE;+      SET_REQ_ERROR(req, GetLastError());+      uv_insert_pending_req(loop, (uv_req_t*) req);+      handle->reqs_pending++;+      return;+    }+  }++  assert(req->pipeHandle != INVALID_HANDLE_VALUE);++  /* Prepare the overlapped structure. */+  memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));++  if (!ConnectNamedPipe(req->pipeHandle, &req->u.io.overlapped) &&+      GetLastError() != ERROR_IO_PENDING) {+    if (GetLastError() == ERROR_PIPE_CONNECTED) {+      SET_REQ_SUCCESS(req);+    } else {+      CloseHandle(req->pipeHandle);+      req->pipeHandle = INVALID_HANDLE_VALUE;+      /* Make this req pending reporting an error. */+      SET_REQ_ERROR(req, GetLastError());+    }+    uv_insert_pending_req(loop, (uv_req_t*) req);+    handle->reqs_pending++;+    return;+  }++  /* Wait for completion via IOCP */+  handle->reqs_pending++;+}+++int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {+  uv_loop_t* loop = server->loop;+  uv_pipe_t* pipe_client;+  uv_pipe_accept_t* req;+  QUEUE* q;+  uv__ipc_xfer_queue_item_t* item;+  int err;++  if (server->ipc) {+    if (QUEUE_EMPTY(&server->pipe.conn.ipc_xfer_queue)) {+      /* No valid pending sockets. */+      return WSAEWOULDBLOCK;+    }++    q = QUEUE_HEAD(&server->pipe.conn.ipc_xfer_queue);+    QUEUE_REMOVE(q);+    server->pipe.conn.ipc_xfer_queue_length--;+    item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);++    err = uv__tcp_xfer_import(+        (uv_tcp_t*) client, item->xfer_type, &item->xfer_info);+    if (err != 0)+      return err;++    uv__free(item);++  } else {+    pipe_client = (uv_pipe_t*)client;++    /* Find a connection instance that has been connected, but not yet+     * accepted. */+    req = server->pipe.serv.pending_accepts;++    if (!req) {+      /* No valid connections found, so we error out. */+      return WSAEWOULDBLOCK;+    }++    /* Initialize the client handle and copy the pipeHandle to the client */+    uv_pipe_connection_init(pipe_client);+    pipe_client->handle = req->pipeHandle;+    pipe_client->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;++    /* Prepare the req to pick up a new connection */+    server->pipe.serv.pending_accepts = req->next_pending;+    req->next_pending = NULL;+    req->pipeHandle = INVALID_HANDLE_VALUE;++    if (!(server->flags & UV_HANDLE_CLOSING)) {+      uv_pipe_queue_accept(loop, server, req, FALSE);+    }+  }++  return 0;+}+++/* Starts listening for connections for the given pipe. */+int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {+  uv_loop_t* loop = handle->loop;+  int i;++  if (handle->flags & UV_HANDLE_LISTENING) {+    handle->stream.serv.connection_cb = cb;+  }++  if (!(handle->flags & UV_HANDLE_BOUND)) {+    return WSAEINVAL;+  }++  if (handle->flags & UV_HANDLE_READING) {+    return WSAEISCONN;+  }++  if (!(handle->flags & UV_HANDLE_PIPESERVER)) {+    return ERROR_NOT_SUPPORTED;+  }++  handle->flags |= UV_HANDLE_LISTENING;+  INCREASE_ACTIVE_COUNT(loop, handle);+  handle->stream.serv.connection_cb = cb;++  /* First pipe handle should have already been created in uv_pipe_bind */+  assert(handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE);++  for (i = 0; i < handle->pipe.serv.pending_instances; i++) {+    uv_pipe_queue_accept(loop, handle, &handle->pipe.serv.accept_reqs[i], i == 0);+  }++  return 0;+}+++static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* arg) {+  uv_read_t* req = (uv_read_t*) arg;+  uv_pipe_t* handle = (uv_pipe_t*) req->data;+  uv_loop_t* loop = handle->loop;+  volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle;+  CRITICAL_SECTION* lock = &handle->pipe.conn.readfile_thread_lock;+  HANDLE thread;+  DWORD bytes;+  DWORD err;++  assert(req->type == UV_READ);+  assert(handle->type == UV_NAMED_PIPE);++  err = 0;++  /* Create a handle to the current thread. */+  if (!DuplicateHandle(GetCurrentProcess(),+                       GetCurrentThread(),+                       GetCurrentProcess(),+                       &thread,+                       0,+                       FALSE,+                       DUPLICATE_SAME_ACCESS)) {+    err = GetLastError();+    goto out1;+  }++  /* The lock needs to be held when thread handle is modified. */+  EnterCriticalSection(lock);+  if (*thread_ptr == INVALID_HANDLE_VALUE) {+    /* uv__pipe_interrupt_read() cancelled reading before we got here. */+    err = ERROR_OPERATION_ABORTED;+  } else {+    /* Let main thread know which worker thread is doing the blocking read. */+    assert(*thread_ptr == NULL);+    *thread_ptr = thread;+  }+  LeaveCriticalSection(lock);++  if (err)+    goto out2;++  /* Block the thread until data is available on the pipe, or the read is+   * cancelled. */+  if (!ReadFile(handle->handle, &uv_zero_, 0, &bytes, NULL))+    err = GetLastError();++  /* Let the main thread know the worker is past the point of blocking. */+  assert(thread == *thread_ptr);+  *thread_ptr = INVALID_HANDLE_VALUE;++  /* Briefly acquire the mutex. Since the main thread holds the lock while it+   * is spinning trying to cancel this thread's I/O, we will block here until+   * it stops doing that. */+  EnterCriticalSection(lock);+  LeaveCriticalSection(lock);++out2:+  /* Close the handle to the current thread. */+  CloseHandle(thread);++out1:+  /* Set request status and post a completion record to the IOCP. */+  if (err)+    SET_REQ_ERROR(req, err);+  else+    SET_REQ_SUCCESS(req);+  POST_COMPLETION_FOR_REQ(loop, req);++  return 0;+}+++static DWORD WINAPI uv_pipe_writefile_thread_proc(void* parameter) {+  int result;+  DWORD bytes;+  uv_write_t* req = (uv_write_t*) parameter;+  uv_pipe_t* handle = (uv_pipe_t*) req->handle;+  uv_loop_t* loop = handle->loop;++  assert(req != NULL);+  assert(req->type == UV_WRITE);+  assert(handle->type == UV_NAMED_PIPE);+  assert(req->write_buffer.base);++  result = WriteFile(handle->handle,+                     req->write_buffer.base,+                     req->write_buffer.len,+                     &bytes,+                     NULL);++  if (!result) {+    SET_REQ_ERROR(req, GetLastError());+  }++  POST_COMPLETION_FOR_REQ(loop, req);+  return 0;+}+++static void CALLBACK post_completion_read_wait(void* context, BOOLEAN timed_out) {+  uv_read_t* req;+  uv_tcp_t* handle;++  req = (uv_read_t*) context;+  assert(req != NULL);+  handle = (uv_tcp_t*)req->data;+  assert(handle != NULL);+  assert(!timed_out);++  if (!PostQueuedCompletionStatus(handle->loop->iocp,+                                  req->u.io.overlapped.InternalHigh,+                                  0,+                                  &req->u.io.overlapped)) {+    uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");+  }+}+++static void CALLBACK post_completion_write_wait(void* context, BOOLEAN timed_out) {+  uv_write_t* req;+  uv_tcp_t* handle;++  req = (uv_write_t*) context;+  assert(req != NULL);+  handle = (uv_tcp_t*)req->handle;+  assert(handle != NULL);+  assert(!timed_out);++  if (!PostQueuedCompletionStatus(handle->loop->iocp,+                                  req->u.io.overlapped.InternalHigh,+                                  0,+                                  &req->u.io.overlapped)) {+    uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");+  }+}+++static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) {+  uv_read_t* req;+  int result;++  assert(handle->flags & UV_HANDLE_READING);+  assert(!(handle->flags & UV_HANDLE_READ_PENDING));++  assert(handle->handle != INVALID_HANDLE_VALUE);++  req = &handle->read_req;++  if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {+    handle->pipe.conn.readfile_thread_handle = NULL; /* Reset cancellation. */+    if (!QueueUserWorkItem(&uv_pipe_zero_readfile_thread_proc,+                           req,+                           WT_EXECUTELONGFUNCTION)) {+      /* Make this req pending reporting an error. */+      SET_REQ_ERROR(req, GetLastError());+      goto error;+    }+  } else {+    memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));+    if (handle->flags & UV_HANDLE_EMULATE_IOCP) {+      req->u.io.overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1);+    }++    /* Do 0-read */+    result = ReadFile(handle->handle,+                      &uv_zero_,+                      0,+                      NULL,+                      &req->u.io.overlapped);++    if (!result && GetLastError() != ERROR_IO_PENDING) {+      /* Make this req pending reporting an error. */+      SET_REQ_ERROR(req, GetLastError());+      goto error;+    }++    if (handle->flags & UV_HANDLE_EMULATE_IOCP) {+      if (!req->event_handle) {+        req->event_handle = CreateEvent(NULL, 0, 0, NULL);+        if (!req->event_handle) {+          uv_fatal_error(GetLastError(), "CreateEvent");+        }+      }+      if (req->wait_handle == INVALID_HANDLE_VALUE) {+        if (!RegisterWaitForSingleObject(&req->wait_handle,+            req->u.io.overlapped.hEvent, post_completion_read_wait, (void*) req,+            INFINITE, WT_EXECUTEINWAITTHREAD)) {+          SET_REQ_ERROR(req, GetLastError());+          goto error;+        }+      }+    }+  }++  /* Start the eof timer if there is one */+  eof_timer_start(handle);+  handle->flags |= UV_HANDLE_READ_PENDING;+  handle->reqs_pending++;+  return;++error:+  uv_insert_pending_req(loop, (uv_req_t*)req);+  handle->flags |= UV_HANDLE_READ_PENDING;+  handle->reqs_pending++;+}+++int uv_pipe_read_start(uv_pipe_t* handle,+                       uv_alloc_cb alloc_cb,+                       uv_read_cb read_cb) {+  uv_loop_t* loop = handle->loop;++  handle->flags |= UV_HANDLE_READING;+  INCREASE_ACTIVE_COUNT(loop, handle);+  handle->read_cb = read_cb;+  handle->alloc_cb = alloc_cb;++  /* If reading was stopped and then started again, there could still be a read+   * request pending. */+  if (!(handle->flags & UV_HANDLE_READ_PENDING))+    uv_pipe_queue_read(loop, handle);++  return 0;+}+++static void uv_insert_non_overlapped_write_req(uv_pipe_t* handle,+    uv_write_t* req) {+  req->next_req = NULL;+  if (handle->pipe.conn.non_overlapped_writes_tail) {+    req->next_req =+      handle->pipe.conn.non_overlapped_writes_tail->next_req;+    handle->pipe.conn.non_overlapped_writes_tail->next_req = (uv_req_t*)req;+    handle->pipe.conn.non_overlapped_writes_tail = req;+  } else {+    req->next_req = (uv_req_t*)req;+    handle->pipe.conn.non_overlapped_writes_tail = req;+  }+}+++static uv_write_t* uv_remove_non_overlapped_write_req(uv_pipe_t* handle) {+  uv_write_t* req;++  if (handle->pipe.conn.non_overlapped_writes_tail) {+    req = (uv_write_t*)handle->pipe.conn.non_overlapped_writes_tail->next_req;++    if (req == handle->pipe.conn.non_overlapped_writes_tail) {+      handle->pipe.conn.non_overlapped_writes_tail = NULL;+    } else {+      handle->pipe.conn.non_overlapped_writes_tail->next_req =+        req->next_req;+    }++    return req;+  } else {+    /* queue empty */+    return NULL;+  }+}+++static void uv_queue_non_overlapped_write(uv_pipe_t* handle) {+  uv_write_t* req = uv_remove_non_overlapped_write_req(handle);+  if (req) {+    if (!QueueUserWorkItem(&uv_pipe_writefile_thread_proc,+                           req,+                           WT_EXECUTELONGFUNCTION)) {+      uv_fatal_error(GetLastError(), "QueueUserWorkItem");+    }+  }+}+++static int uv__build_coalesced_write_req(uv_write_t* user_req,+                                         const uv_buf_t bufs[],+                                         size_t nbufs,+                                         uv_write_t** req_out,+                                         uv_buf_t* write_buf_out) {+  /* Pack into a single heap-allocated buffer:+   *   (a) a uv_write_t structure where libuv stores the actual state.+   *   (b) a pointer to the original uv_write_t.+   *   (c) data from all `bufs` entries.+   */+  char* heap_buffer;+  size_t heap_buffer_length, heap_buffer_offset;+  uv__coalesced_write_t* coalesced_write_req; /* (a) + (b) */+  char* data_start;                           /* (c) */+  size_t data_length;+  unsigned int i;++  /* Compute combined size of all combined buffers from `bufs`. */+  data_length = 0;+  for (i = 0; i < nbufs; i++)+    data_length += bufs[i].len;++  /* The total combined size of data buffers should not exceed UINT32_MAX,+   * because WriteFile() won't accept buffers larger than that. */+  if (data_length > UINT32_MAX)+    return WSAENOBUFS; /* Maps to UV_ENOBUFS. */++  /* Compute heap buffer size. */+  heap_buffer_length = sizeof *coalesced_write_req + /* (a) + (b) */+                       data_length;                  /* (c) */++  /* Allocate buffer. */+  heap_buffer = uv__malloc(heap_buffer_length);+  if (heap_buffer == NULL)+    return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */++  /* Copy uv_write_t information to the buffer. */+  coalesced_write_req = (uv__coalesced_write_t*) heap_buffer;+  coalesced_write_req->req = *user_req; /* copy (a) */+  coalesced_write_req->req.coalesced = 1;+  coalesced_write_req->user_req = user_req;         /* copy (b) */+  heap_buffer_offset = sizeof *coalesced_write_req; /* offset (a) + (b) */++  /* Copy data buffers to the heap buffer. */+  data_start = &heap_buffer[heap_buffer_offset];+  for (i = 0; i < nbufs; i++) {+    memcpy(&heap_buffer[heap_buffer_offset],+           bufs[i].base,+           bufs[i].len);               /* copy (c) */+    heap_buffer_offset += bufs[i].len; /* offset (c) */+  }+  assert(heap_buffer_offset == heap_buffer_length);++  /* Set out arguments and return. */+  *req_out = &coalesced_write_req->req;+  *write_buf_out = uv_buf_init(data_start, (unsigned int) data_length);+  return 0;+}+++static int uv__pipe_write_data(uv_loop_t* loop,+                               uv_write_t* req,+                               uv_pipe_t* handle,+                               const uv_buf_t bufs[],+                               size_t nbufs,+                               uv_write_cb cb,+                               int copy_always) {+  int err;+  int result;+  uv_buf_t write_buf;++  assert(handle->handle != INVALID_HANDLE_VALUE);++  UV_REQ_INIT(req, UV_WRITE);+  req->handle = (uv_stream_t*) handle;+  req->send_handle = NULL;+  req->cb = cb;+  /* Private fields. */+  req->coalesced = 0;+  req->event_handle = NULL;+  req->wait_handle = INVALID_HANDLE_VALUE;+  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));+  req->write_buffer = uv_null_buf_;++  if (nbufs == 0) {+    /* Write empty buffer. */+    write_buf = uv_null_buf_;+  } else if (nbufs == 1 && !copy_always) {+    /* Write directly from bufs[0]. */+    write_buf = bufs[0];+  } else {+    /* Coalesce all `bufs` into one big buffer. This also creates a new+     * write-request structure that replaces the old one. */+    err = uv__build_coalesced_write_req(req, bufs, nbufs, &req, &write_buf);+    if (err != 0)+      return err;+  }++  if ((handle->flags &+      (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) ==+      (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) {+    DWORD bytes;+    result =+        WriteFile(handle->handle, write_buf.base, write_buf.len, &bytes, NULL);++    if (!result) {+      err = GetLastError();+      return err;+    } else {+      /* Request completed immediately. */+      req->u.io.queued_bytes = 0;+    }++    REGISTER_HANDLE_REQ(loop, handle, req);+    handle->reqs_pending++;+    handle->stream.conn.write_reqs_pending++;+    POST_COMPLETION_FOR_REQ(loop, req);+    return 0;+  } else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {+    req->write_buffer = write_buf;+    uv_insert_non_overlapped_write_req(handle, req);+    if (handle->stream.conn.write_reqs_pending == 0) {+      uv_queue_non_overlapped_write(handle);+    }++    /* Request queued by the kernel. */+    req->u.io.queued_bytes = write_buf.len;+    handle->write_queue_size += req->u.io.queued_bytes;+  } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) {+    /* Using overlapped IO, but wait for completion before returning */+    req->u.io.overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL);+    if (!req->u.io.overlapped.hEvent) {+      uv_fatal_error(GetLastError(), "CreateEvent");+    }++    result = WriteFile(handle->handle,+                       write_buf.base,+                       write_buf.len,+                       NULL,+                       &req->u.io.overlapped);++    if (!result && GetLastError() != ERROR_IO_PENDING) {+      err = GetLastError();+      CloseHandle(req->u.io.overlapped.hEvent);+      return err;+    }++    if (result) {+      /* Request completed immediately. */+      req->u.io.queued_bytes = 0;+    } else {+      /* Request queued by the kernel. */+      req->u.io.queued_bytes = write_buf.len;+      handle->write_queue_size += req->u.io.queued_bytes;+      if (WaitForSingleObject(req->u.io.overlapped.hEvent, INFINITE) !=+          WAIT_OBJECT_0) {+        err = GetLastError();+        CloseHandle(req->u.io.overlapped.hEvent);+        return err;+      }+    }+    CloseHandle(req->u.io.overlapped.hEvent);++    REGISTER_HANDLE_REQ(loop, handle, req);+    handle->reqs_pending++;+    handle->stream.conn.write_reqs_pending++;+    return 0;+  } else {+    result = WriteFile(handle->handle,+                       write_buf.base,+                       write_buf.len,+                       NULL,+                       &req->u.io.overlapped);++    if (!result && GetLastError() != ERROR_IO_PENDING) {+      return GetLastError();+    }++    if (result) {+      /* Request completed immediately. */+      req->u.io.queued_bytes = 0;+    } else {+      /* Request queued by the kernel. */+      req->u.io.queued_bytes = write_buf.len;+      handle->write_queue_size += req->u.io.queued_bytes;+    }++    if (handle->flags & UV_HANDLE_EMULATE_IOCP) {+      req->event_handle = CreateEvent(NULL, 0, 0, NULL);+      if (!req->event_handle) {+        uv_fatal_error(GetLastError(), "CreateEvent");+      }+      if (!RegisterWaitForSingleObject(&req->wait_handle,+          req->u.io.overlapped.hEvent, post_completion_write_wait, (void*) req,+          INFINITE, WT_EXECUTEINWAITTHREAD)) {+        return GetLastError();+      }+    }+  }++  REGISTER_HANDLE_REQ(loop, handle, req);+  handle->reqs_pending++;+  handle->stream.conn.write_reqs_pending++;++  return 0;+}+++static DWORD uv__pipe_get_ipc_remote_pid(uv_pipe_t* handle) {+  DWORD* pid = &handle->pipe.conn.ipc_remote_pid;++  /* If the both ends of the IPC pipe are owned by the same process,+   * the remote end pid may not yet be set. If so, do it here.+   * TODO: this is weird; it'd probably better to use a handshake. */+  if (*pid == 0)+    *pid = GetCurrentProcessId();++  return *pid;+}+++int uv__pipe_write_ipc(uv_loop_t* loop,+                       uv_write_t* req,+                       uv_pipe_t* handle,+                       const uv_buf_t data_bufs[],+                       size_t data_buf_count,+                       uv_stream_t* send_handle,+                       uv_write_cb cb) {+  uv_buf_t stack_bufs[6];+  uv_buf_t* bufs;+  size_t buf_count, buf_index;+  uv__ipc_frame_header_t frame_header;+  uv__ipc_socket_xfer_type_t xfer_type = UV__IPC_SOCKET_XFER_NONE;+  uv__ipc_socket_xfer_info_t xfer_info;+  uint64_t data_length;+  size_t i;+  int err;++  /* Compute the combined size of data buffers. */+  data_length = 0;+  for (i = 0; i < data_buf_count; i++)+    data_length += data_bufs[i].len;+  if (data_length > UINT32_MAX)+    return WSAENOBUFS; /* Maps to UV_ENOBUFS. */++  /* Prepare the frame's socket xfer payload. */+  if (send_handle != NULL) {+    uv_tcp_t* send_tcp_handle = (uv_tcp_t*) send_handle;++    /* Verify that `send_handle` it is indeed a tcp handle. */+    if (send_tcp_handle->type != UV_TCP)+      return ERROR_NOT_SUPPORTED;++    /* Export the tcp handle. */+    err = uv__tcp_xfer_export(send_tcp_handle,+                              uv__pipe_get_ipc_remote_pid(handle),+                              &xfer_type,+                              &xfer_info);+    if (err != 0)+      return err;+  }++  /* Compute the number of uv_buf_t's required. */+  buf_count = 1 + data_buf_count; /* Frame header and data buffers. */+  if (send_handle != NULL)+    buf_count += 1; /* One extra for the socket xfer information. */++  /* Use the on-stack buffer array if it is big enough; otherwise allocate+   * space for it on the heap. */+  if (buf_count < ARRAY_SIZE(stack_bufs)) {+    /* Use on-stack buffer array. */+    bufs = stack_bufs;+  } else {+    /* Use heap-allocated buffer array. */+    bufs = uv__calloc(buf_count, sizeof(uv_buf_t));+    if (bufs == NULL)+      return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */+  }+  buf_index = 0;++  /* Initialize frame header and add it to the buffers list. */+  memset(&frame_header, 0, sizeof frame_header);+  bufs[buf_index++] = uv_buf_init((char*) &frame_header, sizeof frame_header);++  if (send_handle != NULL) {+    /* Add frame header flags. */+    switch (xfer_type) {+      case UV__IPC_SOCKET_XFER_TCP_CONNECTION:+        frame_header.flags |= UV__IPC_FRAME_HAS_SOCKET_XFER |+                              UV__IPC_FRAME_XFER_IS_TCP_CONNECTION;+        break;+      case UV__IPC_SOCKET_XFER_TCP_SERVER:+        frame_header.flags |= UV__IPC_FRAME_HAS_SOCKET_XFER;+        break;+      default:+        assert(0);  /* Unreachable. */+    }+    /* Add xfer info buffer. */+    bufs[buf_index++] = uv_buf_init((char*) &xfer_info, sizeof xfer_info);+  }++  if (data_length > 0) {+    /* Update frame header. */+    frame_header.flags |= UV__IPC_FRAME_HAS_DATA;+    frame_header.data_length = (uint32_t) data_length;+    /* Add data buffers to buffers list. */+    for (i = 0; i < data_buf_count; i++)+      bufs[buf_index++] = data_bufs[i];+  }++  /* Write buffers. We set the `always_copy` flag, so it is not a problem that+   * some of the written data lives on the stack. */+  err = uv__pipe_write_data(loop, req, handle, bufs, buf_count, cb, 1);++  /* If we had to heap-allocate the bufs array, free it now. */+  if (bufs != stack_bufs) {+    uv__free(bufs);+  }++  return err;+}+++int uv__pipe_write(uv_loop_t* loop,+                   uv_write_t* req,+                   uv_pipe_t* handle,+                   const uv_buf_t bufs[],+                   size_t nbufs,+                   uv_stream_t* send_handle,+                   uv_write_cb cb) {+  if (handle->ipc) {+    /* IPC pipe write: use framing protocol. */+    return uv__pipe_write_ipc(loop, req, handle, bufs, nbufs, send_handle, cb);+  } else {+    /* Non-IPC pipe write: put data on the wire directly. */+    assert(send_handle == NULL);+    return uv__pipe_write_data(loop, req, handle, bufs, nbufs, cb, 0);+  }+}+++static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle,+    uv_buf_t buf) {+  /* If there is an eof timer running, we don't need it any more, so discard+   * it. */+  eof_timer_destroy(handle);++  handle->flags &= ~UV_HANDLE_READABLE;+  uv_read_stop((uv_stream_t*) handle);++  handle->read_cb((uv_stream_t*) handle, UV_EOF, &buf);+}+++static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,+    uv_buf_t buf) {+  /* If there is an eof timer running, we don't need it any more, so discard+   * it. */+  eof_timer_destroy(handle);++  uv_read_stop((uv_stream_t*) handle);++  handle->read_cb((uv_stream_t*)handle, uv_translate_sys_error(error), &buf);+}+++static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,+    int error, uv_buf_t buf) {+  if (error == ERROR_BROKEN_PIPE) {+    uv_pipe_read_eof(loop, handle, buf);+  } else {+    uv_pipe_read_error(loop, handle, error, buf);+  }+}+++static void uv__pipe_queue_ipc_xfer_info(+    uv_pipe_t* handle,+    uv__ipc_socket_xfer_type_t xfer_type,+    uv__ipc_socket_xfer_info_t* xfer_info) {+  uv__ipc_xfer_queue_item_t* item;++  item = (uv__ipc_xfer_queue_item_t*) uv__malloc(sizeof(*item));+  if (item == NULL)+    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");++  item->xfer_type = xfer_type;+  item->xfer_info = *xfer_info;++  QUEUE_INSERT_TAIL(&handle->pipe.conn.ipc_xfer_queue, &item->member);+  handle->pipe.conn.ipc_xfer_queue_length++;+}+++/* Read an exact number of bytes from a pipe. If an error or end-of-file is+ * encountered before the requested number of bytes are read, an error is+ * returned. */+static int uv__pipe_read_exactly(HANDLE h, void* buffer, DWORD count) {+  DWORD bytes_read, bytes_read_now;++  bytes_read = 0;+  while (bytes_read < count) {+    if (!ReadFile(h,+                  (char*) buffer + bytes_read,+                  count - bytes_read,+                  &bytes_read_now,+                  NULL)) {+      return GetLastError();+    }++    bytes_read += bytes_read_now;+  }++  assert(bytes_read == count);+  return 0;+}+++static DWORD uv__pipe_read_data(uv_loop_t* loop,+                                uv_pipe_t* handle,+                                DWORD suggested_bytes,+                                DWORD max_bytes) {+  DWORD bytes_read;+  uv_buf_t buf;++  /* Ask the user for a buffer to read data into. */+  buf = uv_buf_init(NULL, 0);+  handle->alloc_cb((uv_handle_t*) handle, suggested_bytes, &buf);+  if (buf.base == NULL || buf.len == 0) {+    handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf);+    return 0; /* Break out of read loop. */+  }++  /* Ensure we read at most the smaller of:+   *   (a) the length of the user-allocated buffer.+   *   (b) the maximum data length as specified by the `max_bytes` argument.+   */+  if (max_bytes > buf.len)+    max_bytes = buf.len;++  /* Read into the user buffer. */+  if (!ReadFile(handle->handle, buf.base, max_bytes, &bytes_read, NULL)) {+    uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf);+    return 0; /* Break out of read loop. */+  }++  /* Call the read callback. */+  handle->read_cb((uv_stream_t*) handle, bytes_read, &buf);++  return bytes_read;+}+++static DWORD uv__pipe_read_ipc(uv_loop_t* loop, uv_pipe_t* handle) {+  uint32_t* data_remaining = &handle->pipe.conn.ipc_data_frame.payload_remaining;+  int err;++  if (*data_remaining > 0) {+    /* Read frame data payload. */+    DWORD bytes_read =+        uv__pipe_read_data(loop, handle, *data_remaining, *data_remaining);+    *data_remaining -= bytes_read;+    return bytes_read;++  } else {+    /* Start of a new IPC frame. */+    uv__ipc_frame_header_t frame_header;+    uint32_t xfer_flags;+    uv__ipc_socket_xfer_type_t xfer_type;+    uv__ipc_socket_xfer_info_t xfer_info;++    /* Read the IPC frame header. */+    err = uv__pipe_read_exactly(+        handle->handle, &frame_header, sizeof frame_header);+    if (err)+      goto error;++    /* Validate that flags are valid. */+    if ((frame_header.flags & ~UV__IPC_FRAME_VALID_FLAGS) != 0)+      goto invalid;+    /* Validate that reserved2 is zero. */+    if (frame_header.reserved2 != 0)+      goto invalid;++    /* Parse xfer flags. */+    xfer_flags = frame_header.flags & UV__IPC_FRAME_XFER_FLAGS;+    if (xfer_flags & UV__IPC_FRAME_HAS_SOCKET_XFER) {+      /* Socket coming -- determine the type. */+      xfer_type = xfer_flags & UV__IPC_FRAME_XFER_IS_TCP_CONNECTION+                      ? UV__IPC_SOCKET_XFER_TCP_CONNECTION+                      : UV__IPC_SOCKET_XFER_TCP_SERVER;+    } else if (xfer_flags == 0) {+      /* No socket. */+      xfer_type = UV__IPC_SOCKET_XFER_NONE;+    } else {+      /* Invalid flags. */+      goto invalid;+    }++    /* Parse data frame information. */+    if (frame_header.flags & UV__IPC_FRAME_HAS_DATA) {+      *data_remaining = frame_header.data_length;+    } else if (frame_header.data_length != 0) {+      /* Data length greater than zero but data flag not set -- invalid. */+      goto invalid;+    }++    /* If no socket xfer info follows, return here. Data will be read in a+     * subsequent invocation of uv__pipe_read_ipc(). */+    if (xfer_type == UV__IPC_SOCKET_XFER_NONE)+      return sizeof frame_header; /* Number of bytes read. */++    /* Read transferred socket information. */+    err = uv__pipe_read_exactly(handle->handle, &xfer_info, sizeof xfer_info);+    if (err)+      goto error;++    /* Store the pending socket info. */+    uv__pipe_queue_ipc_xfer_info(handle, xfer_type, &xfer_info);++    /* Return number of bytes read. */+    return sizeof frame_header + sizeof xfer_info;+  }++invalid:+  /* Invalid frame. */+  err = WSAECONNABORTED; /* Maps to UV_ECONNABORTED. */++error:+  uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);+  return 0; /* Break out of read loop. */+}+++void uv_process_pipe_read_req(uv_loop_t* loop,+                              uv_pipe_t* handle,+                              uv_req_t* req) {+  assert(handle->type == UV_NAMED_PIPE);++  handle->flags &= ~(UV_HANDLE_READ_PENDING | UV_HANDLE_CANCELLATION_PENDING);+  DECREASE_PENDING_REQ_COUNT(handle);+  eof_timer_stop(handle);++  /* At this point, we're done with bookkeeping. If the user has stopped+   * reading the pipe in the meantime, there is nothing left to do, since there+   * is no callback that we can call. */+  if (!(handle->flags & UV_HANDLE_READING))+    return;++  if (!REQ_SUCCESS(req)) {+    /* An error occurred doing the zero-read. */+    DWORD err = GET_REQ_ERROR(req);++    /* If the read was cancelled by uv__pipe_interrupt_read(), the request may+     * indicate an ERROR_OPERATION_ABORTED error. This error isn't relevant to+     * the user; we'll start a new zero-read at the end of this function. */+    if (err != ERROR_OPERATION_ABORTED)+      uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);++  } else {+    /* The zero-read completed without error, indicating there is data+     * available in the kernel buffer. */+    DWORD avail;++    /* Get the number of bytes available. */+    avail = 0;+    if (!PeekNamedPipe(handle->handle, NULL, 0, NULL, &avail, NULL))+      uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_);++    /* Read until we've either read all the bytes available, or the 'reading'+     * flag is cleared. */+    while (avail > 0 && handle->flags & UV_HANDLE_READING) {+      /* Depending on the type of pipe, read either IPC frames or raw data. */+      DWORD bytes_read =+          handle->ipc ? uv__pipe_read_ipc(loop, handle)+                      : uv__pipe_read_data(loop, handle, avail, (DWORD) -1);++      /* If no bytes were read, treat this as an indication that an error+       * occurred, and break out of the read loop. */+      if (bytes_read == 0)+        break;++      /* It is possible that more bytes were read than we thought were+       * available. To prevent `avail` from underflowing, break out of the loop+       * if this is the case. */+      if (bytes_read > avail)+        break;++      /* Recompute the number of bytes available. */+      avail -= bytes_read;+    }+  }++  /* Start another zero-read request if necessary. */+  if ((handle->flags & UV_HANDLE_READING) &&+      !(handle->flags & UV_HANDLE_READ_PENDING)) {+    uv_pipe_queue_read(loop, handle);+  }+}+++void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,+    uv_write_t* req) {+  int err;++  assert(handle->type == UV_NAMED_PIPE);++  assert(handle->write_queue_size >= req->u.io.queued_bytes);+  handle->write_queue_size -= req->u.io.queued_bytes;++  UNREGISTER_HANDLE_REQ(loop, handle, req);++  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {+    if (req->wait_handle != INVALID_HANDLE_VALUE) {+      UnregisterWait(req->wait_handle);+      req->wait_handle = INVALID_HANDLE_VALUE;+    }+    if (req->event_handle) {+      CloseHandle(req->event_handle);+      req->event_handle = NULL;+    }+  }++  err = GET_REQ_ERROR(req);++  /* If this was a coalesced write, extract pointer to the user_provided+   * uv_write_t structure so we can pass the expected pointer to the callback,+   * then free the heap-allocated write req. */+  if (req->coalesced) {+    uv__coalesced_write_t* coalesced_write =+        container_of(req, uv__coalesced_write_t, req);+    req = coalesced_write->user_req;+    uv__free(coalesced_write);+  }+  if (req->cb) {+    req->cb(req, uv_translate_sys_error(err));+  }++  handle->stream.conn.write_reqs_pending--;++  if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE &&+      handle->pipe.conn.non_overlapped_writes_tail) {+    assert(handle->stream.conn.write_reqs_pending > 0);+    uv_queue_non_overlapped_write(handle);+  }++  if (handle->stream.conn.shutdown_req != NULL &&+      handle->stream.conn.write_reqs_pending == 0) {+    uv_want_endgame(loop, (uv_handle_t*)handle);+  }++  DECREASE_PENDING_REQ_COUNT(handle);+}+++void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,+    uv_req_t* raw_req) {+  uv_pipe_accept_t* req = (uv_pipe_accept_t*) raw_req;++  assert(handle->type == UV_NAMED_PIPE);++  if (handle->flags & UV_HANDLE_CLOSING) {+    /* The req->pipeHandle should be freed already in uv_pipe_cleanup(). */+    assert(req->pipeHandle == INVALID_HANDLE_VALUE);+    DECREASE_PENDING_REQ_COUNT(handle);+    return;+  }++  if (REQ_SUCCESS(req)) {+    assert(req->pipeHandle != INVALID_HANDLE_VALUE);+    req->next_pending = handle->pipe.serv.pending_accepts;+    handle->pipe.serv.pending_accepts = req;++    if (handle->stream.serv.connection_cb) {+      handle->stream.serv.connection_cb((uv_stream_t*)handle, 0);+    }+  } else {+    if (req->pipeHandle != INVALID_HANDLE_VALUE) {+      CloseHandle(req->pipeHandle);+      req->pipeHandle = INVALID_HANDLE_VALUE;+    }+    if (!(handle->flags & UV_HANDLE_CLOSING)) {+      uv_pipe_queue_accept(loop, handle, req, FALSE);+    }+  }++  DECREASE_PENDING_REQ_COUNT(handle);+}+++void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,+    uv_connect_t* req) {+  int err;++  assert(handle->type == UV_NAMED_PIPE);++  UNREGISTER_HANDLE_REQ(loop, handle, req);++  if (req->cb) {+    err = 0;+    if (REQ_SUCCESS(req)) {+      uv_pipe_connection_init(handle);+    } else {+      err = GET_REQ_ERROR(req);+    }+    req->cb(req, uv_translate_sys_error(err));+  }++  DECREASE_PENDING_REQ_COUNT(handle);+}+++void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,+    uv_shutdown_t* req) {+  assert(handle->type == UV_NAMED_PIPE);++  UNREGISTER_HANDLE_REQ(loop, handle, req);++  if (handle->flags & UV_HANDLE_READABLE) {+    /* Initialize and optionally start the eof timer. Only do this if the pipe+     * is readable and we haven't seen EOF come in ourselves. */+    eof_timer_init(handle);++    /* If reading start the timer right now. Otherwise uv_pipe_queue_read will+     * start it. */+    if (handle->flags & UV_HANDLE_READ_PENDING) {+      eof_timer_start(handle);+    }++  } else {+    /* This pipe is not readable. We can just close it to let the other end+     * know that we're done writing. */+    close_pipe(handle);+  }++  if (req->cb) {+    req->cb(req, 0);+  }++  DECREASE_PENDING_REQ_COUNT(handle);+}+++static void eof_timer_init(uv_pipe_t* pipe) {+  int r;++  assert(pipe->pipe.conn.eof_timer == NULL);+  assert(pipe->flags & UV_HANDLE_CONNECTION);++  pipe->pipe.conn.eof_timer = (uv_timer_t*) uv__malloc(sizeof *pipe->pipe.conn.eof_timer);++  r = uv_timer_init(pipe->loop, pipe->pipe.conn.eof_timer);+  assert(r == 0); /* timers can't fail */+  pipe->pipe.conn.eof_timer->data = pipe;+  uv_unref((uv_handle_t*) pipe->pipe.conn.eof_timer);+}+++static void eof_timer_start(uv_pipe_t* pipe) {+  assert(pipe->flags & UV_HANDLE_CONNECTION);++  if (pipe->pipe.conn.eof_timer != NULL) {+    uv_timer_start(pipe->pipe.conn.eof_timer, eof_timer_cb, eof_timeout, 0);+  }+}+++static void eof_timer_stop(uv_pipe_t* pipe) {+  assert(pipe->flags & UV_HANDLE_CONNECTION);++  if (pipe->pipe.conn.eof_timer != NULL) {+    uv_timer_stop(pipe->pipe.conn.eof_timer);+  }+}+++static void eof_timer_cb(uv_timer_t* timer) {+  uv_pipe_t* pipe = (uv_pipe_t*) timer->data;+  uv_loop_t* loop = timer->loop;++  assert(pipe->type == UV_NAMED_PIPE);++  /* This should always be true, since we start the timer only in+   * uv_pipe_queue_read after successfully calling ReadFile, or in+   * uv_process_pipe_shutdown_req if a read is pending, and we always+   * immediately stop the timer in uv_process_pipe_read_req. */+  assert(pipe->flags & UV_HANDLE_READ_PENDING);++  /* If there are many packets coming off the iocp then the timer callback may+   * be called before the read request is coming off the queue. Therefore we+   * check here if the read request has completed but will be processed later.+   */+  if ((pipe->flags & UV_HANDLE_READ_PENDING) &&+      HasOverlappedIoCompleted(&pipe->read_req.u.io.overlapped)) {+    return;+  }++  /* Force both ends off the pipe. */+  close_pipe(pipe);++  /* Stop reading, so the pending read that is going to fail will not be+   * reported to the user. */+  uv_read_stop((uv_stream_t*) pipe);++  /* Report the eof and update flags. This will get reported even if the user+   * stopped reading in the meantime. TODO: is that okay? */+  uv_pipe_read_eof(loop, pipe, uv_null_buf_);+}+++static void eof_timer_destroy(uv_pipe_t* pipe) {+  assert(pipe->flags & UV_HANDLE_CONNECTION);++  if (pipe->pipe.conn.eof_timer) {+    uv_close((uv_handle_t*) pipe->pipe.conn.eof_timer, eof_timer_close_cb);+    pipe->pipe.conn.eof_timer = NULL;+  }+}+++static void eof_timer_close_cb(uv_handle_t* handle) {+  assert(handle->type == UV_TIMER);+  uv__free(handle);+}+++int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {+  HANDLE os_handle = uv__get_osfhandle(file);+  NTSTATUS nt_status;+  IO_STATUS_BLOCK io_status;+  FILE_ACCESS_INFORMATION access;+  DWORD duplex_flags = 0;++  if (os_handle == INVALID_HANDLE_VALUE)+    return UV_EBADF;++  uv__once_init();+  /* In order to avoid closing a stdio file descriptor 0-2, duplicate the+   * underlying OS handle and forget about the original fd.+   * We could also opt to use the original OS handle and just never close it,+   * but then there would be no reliable way to cancel pending read operations+   * upon close.+   */+  if (file <= 2) {+    if (!DuplicateHandle(INVALID_HANDLE_VALUE,+                         os_handle,+                         INVALID_HANDLE_VALUE,+                         &os_handle,+                         0,+                         FALSE,+                         DUPLICATE_SAME_ACCESS))+      return uv_translate_sys_error(GetLastError());+    file = -1;+  }++  /* Determine what kind of permissions we have on this handle.+   * Cygwin opens the pipe in message mode, but we can support it,+   * just query the access flags and set the stream flags accordingly.+   */+  nt_status = pNtQueryInformationFile(os_handle,+                                      &io_status,+                                      &access,+                                      sizeof(access),+                                      FileAccessInformation);+  if (nt_status != STATUS_SUCCESS)+    return UV_EINVAL;++  if (pipe->ipc) {+    if (!(access.AccessFlags & FILE_WRITE_DATA) ||+        !(access.AccessFlags & FILE_READ_DATA)) {+      return UV_EINVAL;+    }+  }++  if (access.AccessFlags & FILE_WRITE_DATA)+    duplex_flags |= UV_HANDLE_WRITABLE;+  if (access.AccessFlags & FILE_READ_DATA)+    duplex_flags |= UV_HANDLE_READABLE;++  if (os_handle == INVALID_HANDLE_VALUE ||+      uv_set_pipe_handle(pipe->loop,+                         pipe,+                         os_handle,+                         file,+                         duplex_flags) == -1) {+    return UV_EINVAL;+  }++  uv_pipe_connection_init(pipe);++  if (pipe->ipc) {+    assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));+    pipe->pipe.conn.ipc_remote_pid = uv_os_getppid();+    assert(pipe->pipe.conn.ipc_remote_pid != (DWORD) -1);+  }+  return 0;+}+++static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) {+  NTSTATUS nt_status;+  IO_STATUS_BLOCK io_status;+  FILE_NAME_INFORMATION tmp_name_info;+  FILE_NAME_INFORMATION* name_info;+  WCHAR* name_buf;+  unsigned int addrlen;+  unsigned int name_size;+  unsigned int name_len;+  int err;++  uv__once_init();+  name_info = NULL;++  if (handle->handle == INVALID_HANDLE_VALUE) {+    *size = 0;+    return UV_EINVAL;+  }++  /* NtQueryInformationFile will block if another thread is performing a+   * blocking operation on the queried handle. If the pipe handle is+   * synchronous, there may be a worker thread currently calling ReadFile() on+   * the pipe handle, which could cause a deadlock. To avoid this, interrupt+   * the read. */+  if (handle->flags & UV_HANDLE_CONNECTION &&+      handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {+    uv__pipe_interrupt_read((uv_pipe_t*) handle); /* cast away const warning */+  }++  nt_status = pNtQueryInformationFile(handle->handle,+                                      &io_status,+                                      &tmp_name_info,+                                      sizeof tmp_name_info,+                                      FileNameInformation);+  if (nt_status == STATUS_BUFFER_OVERFLOW) {+    name_size = sizeof(*name_info) + tmp_name_info.FileNameLength;+    name_info = uv__malloc(name_size);+    if (!name_info) {+      *size = 0;+      err = UV_ENOMEM;+      goto cleanup;+    }++    nt_status = pNtQueryInformationFile(handle->handle,+                                        &io_status,+                                        name_info,+                                        name_size,+                                        FileNameInformation);+  }++  if (nt_status != STATUS_SUCCESS) {+    *size = 0;+    err = uv_translate_sys_error(pRtlNtStatusToDosError(nt_status));+    goto error;+  }++  if (!name_info) {+    /* the struct on stack was used */+    name_buf = tmp_name_info.FileName;+    name_len = tmp_name_info.FileNameLength;+  } else {+    name_buf = name_info->FileName;+    name_len = name_info->FileNameLength;+  }++  if (name_len == 0) {+    *size = 0;+    err = 0;+    goto error;+  }++  name_len /= sizeof(WCHAR);++  /* check how much space we need */+  addrlen = WideCharToMultiByte(CP_UTF8,+                                0,+                                name_buf,+                                name_len,+                                NULL,+                                0,+                                NULL,+                                NULL);+  if (!addrlen) {+    *size = 0;+    err = uv_translate_sys_error(GetLastError());+    goto error;+  } else if (pipe_prefix_len + addrlen >= *size) {+    /* "\\\\.\\pipe" + name */+    *size = pipe_prefix_len + addrlen + 1;+    err = UV_ENOBUFS;+    goto error;+  }++  memcpy(buffer, pipe_prefix, pipe_prefix_len);+  addrlen = WideCharToMultiByte(CP_UTF8,+                                0,+                                name_buf,+                                name_len,+                                buffer+pipe_prefix_len,+                                *size-pipe_prefix_len,+                                NULL,+                                NULL);+  if (!addrlen) {+    *size = 0;+    err = uv_translate_sys_error(GetLastError());+    goto error;+  }++  addrlen += pipe_prefix_len;+  *size = addrlen;+  buffer[addrlen] = '\0';++  err = 0;++error:+  uv__free(name_info);++cleanup:+  return err;+}+++int uv_pipe_pending_count(uv_pipe_t* handle) {+  if (!handle->ipc)+    return 0;+  return handle->pipe.conn.ipc_xfer_queue_length;+}+++int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {+  if (handle->flags & UV_HANDLE_BOUND)+    return uv__pipe_getname(handle, buffer, size);++  if (handle->flags & UV_HANDLE_CONNECTION ||+      handle->handle != INVALID_HANDLE_VALUE) {+    *size = 0;+    return 0;+  }++  return UV_EBADF;+}+++int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {+  /* emulate unix behaviour */+  if (handle->flags & UV_HANDLE_BOUND)+    return UV_ENOTCONN;++  if (handle->handle != INVALID_HANDLE_VALUE)+    return uv__pipe_getname(handle, buffer, size);++  return UV_EBADF;+}+++uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {+  if (!handle->ipc)+    return UV_UNKNOWN_HANDLE;+  if (handle->pipe.conn.ipc_xfer_queue_length == 0)+    return UV_UNKNOWN_HANDLE;+  else+    return UV_TCP;+}++int uv_pipe_chmod(uv_pipe_t* handle, int mode) {+  SID_IDENTIFIER_AUTHORITY sid_world = { SECURITY_WORLD_SID_AUTHORITY };+  PACL old_dacl, new_dacl;+  PSECURITY_DESCRIPTOR sd;+  EXPLICIT_ACCESS ea;+  PSID everyone;+  int error;++  if (handle == NULL || handle->handle == INVALID_HANDLE_VALUE)+    return UV_EBADF;++  if (mode != UV_READABLE &&+      mode != UV_WRITABLE &&+      mode != (UV_WRITABLE | UV_READABLE))+    return UV_EINVAL;++  if (!AllocateAndInitializeSid(&sid_world,+                                1,+                                SECURITY_WORLD_RID,+                                0, 0, 0, 0, 0, 0, 0,+                                &everyone)) {+    error = GetLastError();+    goto done;+  }++  if (GetSecurityInfo(handle->handle,+                      SE_KERNEL_OBJECT,+                      DACL_SECURITY_INFORMATION,+                      NULL,+                      NULL,+                      &old_dacl,+                      NULL,+                      &sd)) {+    error = GetLastError();+    goto clean_sid;+  }++  memset(&ea, 0, sizeof(EXPLICIT_ACCESS));+  if (mode & UV_READABLE)+    ea.grfAccessPermissions |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;+  if (mode & UV_WRITABLE)+    ea.grfAccessPermissions |= GENERIC_WRITE | FILE_READ_ATTRIBUTES;+  ea.grfAccessPermissions |= SYNCHRONIZE;+  ea.grfAccessMode = SET_ACCESS;+  ea.grfInheritance = NO_INHERITANCE;+  ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;+  ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;+  ea.Trustee.ptstrName = (LPTSTR)everyone;++  if (SetEntriesInAcl(1, &ea, old_dacl, &new_dacl)) {+    error = GetLastError();+    goto clean_sd;+  }++  if (SetSecurityInfo(handle->handle,+                      SE_KERNEL_OBJECT,+                      DACL_SECURITY_INFORMATION,+                      NULL,+                      NULL,+                      new_dacl,+                      NULL)) {+    error = GetLastError();+    goto clean_dacl;+  }++  error = 0;++clean_dacl:+  LocalFree((HLOCAL) new_dacl);+clean_sd:+  LocalFree((HLOCAL) sd);+clean_sid:+  FreeSid(everyone);+done:+  return uv_translate_sys_error(error);+}
+ third_party/libuv/src/win/poll.c view
@@ -0,0 +1,643 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <io.h>++#include "uv.h"+#include "internal.h"+#include "handle-inl.h"+#include "req-inl.h"+++static const GUID uv_msafd_provider_ids[UV_MSAFD_PROVIDER_COUNT] = {+  {0xe70f1aa0, 0xab8b, 0x11cf,+      {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},+  {0xf9eab0c0, 0x26d4, 0x11d0,+      {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}},+  {0x9fc48064, 0x7298, 0x43e4,+      {0xb7, 0xbd, 0x18, 0x1f, 0x20, 0x89, 0x79, 0x2a}}+};++typedef struct uv_single_fd_set_s {+  unsigned int fd_count;+  SOCKET fd_array[1];+} uv_single_fd_set_t;+++static OVERLAPPED overlapped_dummy_;+static uv_once_t overlapped_dummy_init_guard_ = UV_ONCE_INIT;++static AFD_POLL_INFO afd_poll_info_dummy_;+++static void uv__init_overlapped_dummy(void) {+  HANDLE event;++  event = CreateEvent(NULL, TRUE, TRUE, NULL);+  if (event == NULL)+    uv_fatal_error(GetLastError(), "CreateEvent");++  memset(&overlapped_dummy_, 0, sizeof overlapped_dummy_);+  overlapped_dummy_.hEvent = (HANDLE) ((uintptr_t) event | 1);+}+++static OVERLAPPED* uv__get_overlapped_dummy(void) {+  uv_once(&overlapped_dummy_init_guard_, uv__init_overlapped_dummy);+  return &overlapped_dummy_;+}+++static AFD_POLL_INFO* uv__get_afd_poll_info_dummy(void) {+  return &afd_poll_info_dummy_;+}+++static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {+  uv_req_t* req;+  AFD_POLL_INFO* afd_poll_info;+  int result;++  /* Find a yet unsubmitted req to submit. */+  if (handle->submitted_events_1 == 0) {+    req = &handle->poll_req_1;+    afd_poll_info = &handle->afd_poll_info_1;+    handle->submitted_events_1 = handle->events;+    handle->mask_events_1 = 0;+    handle->mask_events_2 = handle->events;+  } else if (handle->submitted_events_2 == 0) {+    req = &handle->poll_req_2;+    afd_poll_info = &handle->afd_poll_info_2;+    handle->submitted_events_2 = handle->events;+    handle->mask_events_1 = handle->events;+    handle->mask_events_2 = 0;+  } else {+    /* Just wait until there's an unsubmitted req. This will happen almost+     * immediately as one of the 2 outstanding requests is about to return.+     * When this happens, uv__fast_poll_process_poll_req will be called, and+     * the pending events, if needed, will be processed in a subsequent+     * request. */+    return;+  }++  /* Setting Exclusive to TRUE makes the other poll request return if there is+   * any. */+  afd_poll_info->Exclusive = TRUE;+  afd_poll_info->NumberOfHandles = 1;+  afd_poll_info->Timeout.QuadPart = INT64_MAX;+  afd_poll_info->Handles[0].Handle = (HANDLE) handle->socket;+  afd_poll_info->Handles[0].Status = 0;+  afd_poll_info->Handles[0].Events = 0;++  if (handle->events & UV_READABLE) {+    afd_poll_info->Handles[0].Events |= AFD_POLL_RECEIVE |+        AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT;+  } else {+    if (handle->events & UV_DISCONNECT) {+      afd_poll_info->Handles[0].Events |= AFD_POLL_DISCONNECT;+    }+  }+  if (handle->events & UV_WRITABLE) {+    afd_poll_info->Handles[0].Events |= AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL;+  }++  memset(&req->u.io.overlapped, 0, sizeof req->u.io.overlapped);++  result = uv_msafd_poll((SOCKET) handle->peer_socket,+                         afd_poll_info,+                         afd_poll_info,+                         &req->u.io.overlapped);+  if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) {+    /* Queue this req, reporting an error. */+    SET_REQ_ERROR(req, WSAGetLastError());+    uv_insert_pending_req(loop, req);+  }+}+++static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) {+  AFD_POLL_INFO afd_poll_info;+  int result;++  afd_poll_info.Exclusive = TRUE;+  afd_poll_info.NumberOfHandles = 1;+  afd_poll_info.Timeout.QuadPart = INT64_MAX;+  afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket;+  afd_poll_info.Handles[0].Status = 0;+  afd_poll_info.Handles[0].Events = AFD_POLL_ALL;++  result = uv_msafd_poll(handle->socket,+                         &afd_poll_info,+                         uv__get_afd_poll_info_dummy(),+                         uv__get_overlapped_dummy());++  if (result == SOCKET_ERROR) {+    DWORD error = WSAGetLastError();+    if (error != WSA_IO_PENDING)+      return error;+  }++  return 0;+}+++static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,+    uv_req_t* req) {+  unsigned char mask_events;+  AFD_POLL_INFO* afd_poll_info;++  if (req == &handle->poll_req_1) {+    afd_poll_info = &handle->afd_poll_info_1;+    handle->submitted_events_1 = 0;+    mask_events = handle->mask_events_1;+  } else if (req == &handle->poll_req_2) {+    afd_poll_info = &handle->afd_poll_info_2;+    handle->submitted_events_2 = 0;+    mask_events = handle->mask_events_2;+  } else {+    assert(0);+    return;+  }++  /* Report an error unless the select was just interrupted. */+  if (!REQ_SUCCESS(req)) {+    DWORD error = GET_REQ_SOCK_ERROR(req);+    if (error != WSAEINTR && handle->events != 0) {+      handle->events = 0; /* Stop the watcher */+      handle->poll_cb(handle, uv_translate_sys_error(error), 0);+    }++  } else if (afd_poll_info->NumberOfHandles >= 1) {+    unsigned char events = 0;++    if ((afd_poll_info->Handles[0].Events & (AFD_POLL_RECEIVE |+        AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT)) != 0) {+      events |= UV_READABLE;+      if ((afd_poll_info->Handles[0].Events & AFD_POLL_DISCONNECT) != 0) {+        events |= UV_DISCONNECT;+      }+    }+    if ((afd_poll_info->Handles[0].Events & (AFD_POLL_SEND |+        AFD_POLL_CONNECT_FAIL)) != 0) {+      events |= UV_WRITABLE;+    }++    events &= handle->events & ~mask_events;++    if (afd_poll_info->Handles[0].Events & AFD_POLL_LOCAL_CLOSE) {+      /* Stop polling. */+      handle->events = 0;+      if (uv__is_active(handle))+        uv__handle_stop(handle);+    }++    if (events != 0) {+      handle->poll_cb(handle, 0, events);+    }+  }++  if ((handle->events & ~(handle->submitted_events_1 |+      handle->submitted_events_2)) != 0) {+    uv__fast_poll_submit_poll_req(loop, handle);+  } else if ((handle->flags & UV_HANDLE_CLOSING) &&+             handle->submitted_events_1 == 0 &&+             handle->submitted_events_2 == 0) {+    uv_want_endgame(loop, (uv_handle_t*) handle);+  }+}+++static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {+  assert(handle->type == UV_POLL);+  assert(!(handle->flags & UV_HANDLE_CLOSING));+  assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);++  handle->events = events;++  if (handle->events != 0) {+    uv__handle_start(handle);+  } else {+    uv__handle_stop(handle);+  }++  if ((handle->events & ~(handle->submitted_events_1 |+      handle->submitted_events_2)) != 0) {+    uv__fast_poll_submit_poll_req(handle->loop, handle);+  }++  return 0;+}+++static int uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) {+  handle->events = 0;+  uv__handle_closing(handle);++  if (handle->submitted_events_1 == 0 &&+      handle->submitted_events_2 == 0) {+    uv_want_endgame(loop, (uv_handle_t*) handle);+    return 0;+  } else {+    /* Cancel outstanding poll requests by executing another, unique poll+     * request that forces the outstanding ones to return. */+    return uv__fast_poll_cancel_poll_req(loop, handle);+  }+}+++static SOCKET uv__fast_poll_create_peer_socket(HANDLE iocp,+    WSAPROTOCOL_INFOW* protocol_info) {+  SOCKET sock = 0;++  sock = WSASocketW(protocol_info->iAddressFamily,+                    protocol_info->iSocketType,+                    protocol_info->iProtocol,+                    protocol_info,+                    0,+                    WSA_FLAG_OVERLAPPED);+  if (sock == INVALID_SOCKET) {+    return INVALID_SOCKET;+  }++  if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) {+    goto error;+  };++  if (CreateIoCompletionPort((HANDLE) sock,+                             iocp,+                             (ULONG_PTR) sock,+                             0) == NULL) {+    goto error;+  }++  return sock;++ error:+  closesocket(sock);+  return INVALID_SOCKET;+}+++static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop,+    WSAPROTOCOL_INFOW* protocol_info) {+  int index, i;+  SOCKET peer_socket;++  index = -1;+  for (i = 0; (size_t) i < ARRAY_SIZE(uv_msafd_provider_ids); i++) {+    if (memcmp((void*) &protocol_info->ProviderId,+               (void*) &uv_msafd_provider_ids[i],+               sizeof protocol_info->ProviderId) == 0) {+      index = i;+    }+  }++  /* Check if the protocol uses an msafd socket. */+  if (index < 0) {+    return INVALID_SOCKET;+  }++  /* If we didn't (try) to create a peer socket yet, try to make one. Don't try+   * again if the peer socket creation failed earlier for the same protocol. */+  peer_socket = loop->poll_peer_sockets[index];+  if (peer_socket == 0) {+    peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info);+    loop->poll_peer_sockets[index] = peer_socket;+  }++  return peer_socket;+}+++static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) {+  uv_req_t* req = (uv_req_t*) arg;+  uv_poll_t* handle = (uv_poll_t*) req->data;+  unsigned char reported_events;+  int r;+  uv_single_fd_set_t rfds, wfds, efds;+  struct timeval timeout;++  assert(handle->type == UV_POLL);+  assert(req->type == UV_POLL_REQ);++  if (handle->events & UV_READABLE) {+    rfds.fd_count = 1;+    rfds.fd_array[0] = handle->socket;+  } else {+    rfds.fd_count = 0;+  }++  if (handle->events & UV_WRITABLE) {+    wfds.fd_count = 1;+    wfds.fd_array[0] = handle->socket;+    efds.fd_count = 1;+    efds.fd_array[0] = handle->socket;+  } else {+    wfds.fd_count = 0;+    efds.fd_count = 0;+  }++  /* Make the select() time out after 3 minutes. If select() hangs because the+   * user closed the socket, we will at least not hang indefinitely. */+  timeout.tv_sec = 3 * 60;+  timeout.tv_usec = 0;++  r = select(1, (fd_set*) &rfds, (fd_set*) &wfds, (fd_set*) &efds, &timeout);+  if (r == SOCKET_ERROR) {+    /* Queue this req, reporting an error. */+    SET_REQ_ERROR(&handle->poll_req_1, WSAGetLastError());+    POST_COMPLETION_FOR_REQ(handle->loop, req);+    return 0;+  }++  reported_events = 0;++  if (r > 0) {+    if (rfds.fd_count > 0) {+      assert(rfds.fd_count == 1);+      assert(rfds.fd_array[0] == handle->socket);+      reported_events |= UV_READABLE;+    }++    if (wfds.fd_count > 0) {+      assert(wfds.fd_count == 1);+      assert(wfds.fd_array[0] == handle->socket);+      reported_events |= UV_WRITABLE;+    } else if (efds.fd_count > 0) {+      assert(efds.fd_count == 1);+      assert(efds.fd_array[0] == handle->socket);+      reported_events |= UV_WRITABLE;+    }+  }++  SET_REQ_SUCCESS(req);+  req->u.io.overlapped.InternalHigh = (DWORD) reported_events;+  POST_COMPLETION_FOR_REQ(handle->loop, req);++  return 0;+}+++static void uv__slow_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {+  uv_req_t* req;++  /* Find a yet unsubmitted req to submit. */+  if (handle->submitted_events_1 == 0) {+    req = &handle->poll_req_1;+    handle->submitted_events_1 = handle->events;+    handle->mask_events_1 = 0;+    handle->mask_events_2 = handle->events;+  } else if (handle->submitted_events_2 == 0) {+    req = &handle->poll_req_2;+    handle->submitted_events_2 = handle->events;+    handle->mask_events_1 = handle->events;+    handle->mask_events_2 = 0;+  } else {+    assert(0);+    return;+  }++  if (!QueueUserWorkItem(uv__slow_poll_thread_proc,+                         (void*) req,+                         WT_EXECUTELONGFUNCTION)) {+    /* Make this req pending, reporting an error. */+    SET_REQ_ERROR(req, GetLastError());+    uv_insert_pending_req(loop, req);+  }+}++++static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,+    uv_req_t* req) {+  unsigned char mask_events;+  int err;++  if (req == &handle->poll_req_1) {+    handle->submitted_events_1 = 0;+    mask_events = handle->mask_events_1;+  } else if (req == &handle->poll_req_2) {+    handle->submitted_events_2 = 0;+    mask_events = handle->mask_events_2;+  } else {+    assert(0);+    return;+  }++  if (!REQ_SUCCESS(req)) {+    /* Error. */+    if (handle->events != 0) {+      err = GET_REQ_ERROR(req);+      handle->events = 0; /* Stop the watcher */+      handle->poll_cb(handle, uv_translate_sys_error(err), 0);+    }+  } else {+    /* Got some events. */+    int events = req->u.io.overlapped.InternalHigh & handle->events & ~mask_events;+    if (events != 0) {+      handle->poll_cb(handle, 0, events);+    }+  }++  if ((handle->events & ~(handle->submitted_events_1 |+      handle->submitted_events_2)) != 0) {+    uv__slow_poll_submit_poll_req(loop, handle);+  } else if ((handle->flags & UV_HANDLE_CLOSING) &&+             handle->submitted_events_1 == 0 &&+             handle->submitted_events_2 == 0) {+    uv_want_endgame(loop, (uv_handle_t*) handle);+  }+}+++static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {+  assert(handle->type == UV_POLL);+  assert(!(handle->flags & UV_HANDLE_CLOSING));+  assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0);++  handle->events = events;++  if (handle->events != 0) {+    uv__handle_start(handle);+  } else {+    uv__handle_stop(handle);+  }++  if ((handle->events &+      ~(handle->submitted_events_1 | handle->submitted_events_2)) != 0) {+    uv__slow_poll_submit_poll_req(handle->loop, handle);+  }++  return 0;+}+++static int uv__slow_poll_close(uv_loop_t* loop, uv_poll_t* handle) {+  handle->events = 0;+  uv__handle_closing(handle);++  if (handle->submitted_events_1 == 0 &&+      handle->submitted_events_2 == 0) {+    uv_want_endgame(loop, (uv_handle_t*) handle);+  }++  return 0;+}+++int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {+  return uv_poll_init_socket(loop, handle, (SOCKET) uv__get_osfhandle(fd));+}+++int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,+    uv_os_sock_t socket) {+  WSAPROTOCOL_INFOW protocol_info;+  int len;+  SOCKET peer_socket, base_socket;+  DWORD bytes;+  DWORD yes = 1;++  /* Set the socket to nonblocking mode */+  if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR)+    return uv_translate_sys_error(WSAGetLastError());++/* Try to obtain a base handle for the socket. This increases this chances that+ * we find an AFD handle and are able to use the fast poll mechanism. This will+ * always fail on windows XP/2k3, since they don't support the. SIO_BASE_HANDLE+ * ioctl. */+#ifndef NDEBUG+  base_socket = INVALID_SOCKET;+#endif++  if (WSAIoctl(socket,+               SIO_BASE_HANDLE,+               NULL,+               0,+               &base_socket,+               sizeof base_socket,+               &bytes,+               NULL,+               NULL) == 0) {+    assert(base_socket != 0 && base_socket != INVALID_SOCKET);+    socket = base_socket;+  }++  uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL);+  handle->socket = socket;+  handle->events = 0;++  /* Obtain protocol information about the socket. */+  len = sizeof protocol_info;+  if (getsockopt(socket,+                 SOL_SOCKET,+                 SO_PROTOCOL_INFOW,+                 (char*) &protocol_info,+                 &len) != 0) {+    return uv_translate_sys_error(WSAGetLastError());+  }++  /* Get the peer socket that is needed to enable fast poll. If the returned+   * value is NULL, the protocol is not implemented by MSAFD and we'll have to+   * use slow mode. */+  peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info);++  if (peer_socket != INVALID_SOCKET) {+    /* Initialize fast poll specific fields. */+    handle->peer_socket = peer_socket;+  } else {+    /* Initialize slow poll specific fields. */+    handle->flags |= UV_HANDLE_POLL_SLOW;+  }++  /* Initialize 2 poll reqs. */+  handle->submitted_events_1 = 0;+  UV_REQ_INIT(&handle->poll_req_1, UV_POLL_REQ);+  handle->poll_req_1.data = handle;++  handle->submitted_events_2 = 0;+  UV_REQ_INIT(&handle->poll_req_2, UV_POLL_REQ);+  handle->poll_req_2.data = handle;++  return 0;+}+++int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) {+  int err;++  if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {+    err = uv__fast_poll_set(handle->loop, handle, events);+  } else {+    err = uv__slow_poll_set(handle->loop, handle, events);+  }++  if (err) {+    return uv_translate_sys_error(err);+  }++  handle->poll_cb = cb;++  return 0;+}+++int uv_poll_stop(uv_poll_t* handle) {+  int err;++  if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {+    err = uv__fast_poll_set(handle->loop, handle, 0);+  } else {+    err = uv__slow_poll_set(handle->loop, handle, 0);+  }++  return uv_translate_sys_error(err);+}+++void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) {+  if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {+    uv__fast_poll_process_poll_req(loop, handle, req);+  } else {+    uv__slow_poll_process_poll_req(loop, handle, req);+  }+}+++int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) {+  if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {+    return uv__fast_poll_close(loop, handle);+  } else {+    return uv__slow_poll_close(loop, handle);+  }+}+++void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {+  assert(handle->flags & UV_HANDLE_CLOSING);+  assert(!(handle->flags & UV_HANDLE_CLOSED));++  assert(handle->submitted_events_1 == 0);+  assert(handle->submitted_events_2 == 0);++  uv__handle_close(handle);+}
+ third_party/libuv/src/win/process-stdio.c view
@@ -0,0 +1,512 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <io.h>+#include <stdio.h>+#include <stdlib.h>++#include "uv.h"+#include "internal.h"+#include "handle-inl.h"+++/*+ * The `child_stdio_buffer` buffer has the following layout:+ *   int number_of_fds+ *   unsigned char crt_flags[number_of_fds]+ *   HANDLE os_handle[number_of_fds]+ */+#define CHILD_STDIO_SIZE(count)                     \+    (sizeof(int) +                                  \+     sizeof(unsigned char) * (count) +              \+     sizeof(uintptr_t) * (count))++#define CHILD_STDIO_COUNT(buffer)                   \+    *((unsigned int*) (buffer))++#define CHILD_STDIO_CRT_FLAGS(buffer, fd)           \+    *((unsigned char*) (buffer) + sizeof(int) + fd)++#define CHILD_STDIO_HANDLE(buffer, fd)              \+    *((HANDLE*) ((unsigned char*) (buffer) +        \+                 sizeof(int) +                      \+                 sizeof(unsigned char) *            \+                 CHILD_STDIO_COUNT((buffer)) +      \+                 sizeof(HANDLE) * (fd)))+++/* CRT file descriptor mode flags */+#define FOPEN       0x01+#define FEOFLAG     0x02+#define FCRLF       0x04+#define FPIPE       0x08+#define FNOINHERIT  0x10+#define FAPPEND     0x20+#define FDEV        0x40+#define FTEXT       0x80+++/*+ * Clear the HANDLE_FLAG_INHERIT flag from all HANDLEs that were inherited+ * the parent process. Don't check for errors - the stdio handles may not be+ * valid, or may be closed already. There is no guarantee that this function+ * does a perfect job.+ */+void uv_disable_stdio_inheritance(void) {+  HANDLE handle;+  STARTUPINFOW si;++  /* Make the windows stdio handles non-inheritable. */+  handle = GetStdHandle(STD_INPUT_HANDLE);+  if (handle != NULL && handle != INVALID_HANDLE_VALUE)+    SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);++  handle = GetStdHandle(STD_OUTPUT_HANDLE);+  if (handle != NULL && handle != INVALID_HANDLE_VALUE)+    SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);++  handle = GetStdHandle(STD_ERROR_HANDLE);+  if (handle != NULL && handle != INVALID_HANDLE_VALUE)+    SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);++  /* Make inherited CRT FDs non-inheritable. */+  GetStartupInfoW(&si);+  if (uv__stdio_verify(si.lpReserved2, si.cbReserved2))+    uv__stdio_noinherit(si.lpReserved2);+}+++static int uv__create_stdio_pipe_pair(uv_loop_t* loop,+    uv_pipe_t* server_pipe, HANDLE* child_pipe_ptr, unsigned int flags) {+  char pipe_name[64];+  SECURITY_ATTRIBUTES sa;+  DWORD server_access = 0;+  DWORD client_access = 0;+  HANDLE child_pipe = INVALID_HANDLE_VALUE;+  int err;+  int overlap;++  if (flags & UV_READABLE_PIPE) {+    /* The server needs inbound access too, otherwise CreateNamedPipe() won't+     * give us the FILE_READ_ATTRIBUTES permission. We need that to probe the+     * state of the write buffer when we're trying to shutdown the pipe. */+    server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND;+    client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;+  }+  if (flags & UV_WRITABLE_PIPE) {+    server_access |= PIPE_ACCESS_INBOUND;+    client_access |= GENERIC_WRITE | FILE_READ_ATTRIBUTES;+  }++  /* Create server pipe handle. */+  err = uv_stdio_pipe_server(loop,+                             server_pipe,+                             server_access,+                             pipe_name,+                             sizeof(pipe_name));+  if (err)+    goto error;++  /* Create child pipe handle. */+  sa.nLength = sizeof sa;+  sa.lpSecurityDescriptor = NULL;+  sa.bInheritHandle = TRUE;++  overlap = server_pipe->ipc || (flags & UV_OVERLAPPED_PIPE);+  child_pipe = CreateFileA(pipe_name,+                           client_access,+                           0,+                           &sa,+                           OPEN_EXISTING,+                           overlap ? FILE_FLAG_OVERLAPPED : 0,+                           NULL);+  if (child_pipe == INVALID_HANDLE_VALUE) {+    err = GetLastError();+    goto error;+  }++#ifndef NDEBUG+  /* Validate that the pipe was opened in the right mode. */+  {+    DWORD mode;+    BOOL r = GetNamedPipeHandleState(child_pipe,+                                     &mode,+                                     NULL,+                                     NULL,+                                     NULL,+                                     NULL,+                                     0);+    assert(r == TRUE);+    assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));+  }+#endif++  /* Do a blocking ConnectNamedPipe. This should not block because we have both+   * ends of the pipe created. */+  if (!ConnectNamedPipe(server_pipe->handle, NULL)) {+    if (GetLastError() != ERROR_PIPE_CONNECTED) {+      err = GetLastError();+      goto error;+    }+  }++  /* The server end is now readable and/or writable. */+  if (flags & UV_READABLE_PIPE)+    server_pipe->flags |= UV_HANDLE_WRITABLE;+  if (flags & UV_WRITABLE_PIPE)+    server_pipe->flags |= UV_HANDLE_READABLE;++  *child_pipe_ptr = child_pipe;+  return 0;++ error:+  if (server_pipe->handle != INVALID_HANDLE_VALUE) {+    uv_pipe_cleanup(loop, server_pipe);+  }++  if (child_pipe != INVALID_HANDLE_VALUE) {+    CloseHandle(child_pipe);+  }++  return err;+}+++static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {+  HANDLE current_process;+++  /* _get_osfhandle will sometimes return -2 in case of an error. This seems to+   * happen when fd <= 2 and the process' corresponding stdio handle is set to+   * NULL. Unfortunately DuplicateHandle will happily duplicate (HANDLE) -2, so+   * this situation goes unnoticed until someone tries to use the duplicate.+   * Therefore we filter out known-invalid handles here. */+  if (handle == INVALID_HANDLE_VALUE ||+      handle == NULL ||+      handle == (HANDLE) -2) {+    *dup = INVALID_HANDLE_VALUE;+    return ERROR_INVALID_HANDLE;+  }++  current_process = GetCurrentProcess();++  if (!DuplicateHandle(current_process,+                       handle,+                       current_process,+                       dup,+                       0,+                       TRUE,+                       DUPLICATE_SAME_ACCESS)) {+    *dup = INVALID_HANDLE_VALUE;+    return GetLastError();+  }++  return 0;+}+++static int uv__duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) {+  HANDLE handle;++  if (fd == -1) {+    *dup = INVALID_HANDLE_VALUE;+    return ERROR_INVALID_HANDLE;+  }++  handle = uv__get_osfhandle(fd);+  return uv__duplicate_handle(loop, handle, dup);+}+++int uv__create_nul_handle(HANDLE* handle_ptr,+    DWORD access) {+  HANDLE handle;+  SECURITY_ATTRIBUTES sa;++  sa.nLength = sizeof sa;+  sa.lpSecurityDescriptor = NULL;+  sa.bInheritHandle = TRUE;++  handle = CreateFileW(L"NUL",+                       access,+                       FILE_SHARE_READ | FILE_SHARE_WRITE,+                       &sa,+                       OPEN_EXISTING,+                       0,+                       NULL);+  if (handle == INVALID_HANDLE_VALUE) {+    return GetLastError();+  }++  *handle_ptr = handle;+  return 0;+}+++int uv__stdio_create(uv_loop_t* loop,+                     const uv_process_options_t* options,+                     BYTE** buffer_ptr) {+  BYTE* buffer;+  int count, i;+  int err;++  count = options->stdio_count;++  if (count < 0 || count > 255) {+    /* Only support FDs 0-255 */+    return ERROR_NOT_SUPPORTED;+  } else if (count < 3) {+    /* There should always be at least 3 stdio handles. */+    count = 3;+  }++  /* Allocate the child stdio buffer */+  buffer = (BYTE*) uv__malloc(CHILD_STDIO_SIZE(count));+  if (buffer == NULL) {+    return ERROR_OUTOFMEMORY;+  }++  /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can clean+   * up on failure. */+  CHILD_STDIO_COUNT(buffer) = count;+  for (i = 0; i < count; i++) {+    CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;+    CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;+  }++  for (i = 0; i < count; i++) {+    uv_stdio_container_t fdopt;+    if (i < options->stdio_count) {+      fdopt = options->stdio[i];+    } else {+      fdopt.flags = UV_IGNORE;+    }++    switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |+            UV_INHERIT_STREAM)) {+      case UV_IGNORE:+        /* Starting a process with no stdin/stout/stderr can confuse it. So no+         * matter what the user specified, we make sure the first three FDs are+         * always open in their typical modes, e. g. stdin be readable and+         * stdout/err should be writable. For FDs > 2, don't do anything - all+         * handles in the stdio buffer are initialized with.+         * INVALID_HANDLE_VALUE, which should be okay. */+        if (i <= 2) {+          DWORD access = (i == 0) ? FILE_GENERIC_READ :+                                    FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES;++          err = uv__create_nul_handle(&CHILD_STDIO_HANDLE(buffer, i),+                                      access);+          if (err)+            goto error;++          CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;+        }+        break;++      case UV_CREATE_PIPE: {+        /* Create a pair of two connected pipe ends; one end is turned into an+         * uv_pipe_t for use by the parent. The other one is given to the+         * child. */+        uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream;+        HANDLE child_pipe = INVALID_HANDLE_VALUE;++        /* Create a new, connected pipe pair. stdio[i]. stream should point to+         * an uninitialized, but not connected pipe handle. */+        assert(fdopt.data.stream->type == UV_NAMED_PIPE);+        assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION));+        assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER));++        err = uv__create_stdio_pipe_pair(loop,+                                         parent_pipe,+                                         &child_pipe,+                                         fdopt.flags);+        if (err)+          goto error;++        CHILD_STDIO_HANDLE(buffer, i) = child_pipe;+        CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;+        break;+      }++      case UV_INHERIT_FD: {+        /* Inherit a raw FD. */+        HANDLE child_handle;++        /* Make an inheritable duplicate of the handle. */+        err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle);+        if (err) {+          /* If fdopt. data. fd is not valid and fd <= 2, then ignore the+           * error. */+          if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) {+            CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;+            CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;+            break;+          }+          goto error;+        }++        /* Figure out what the type is. */+        switch (GetFileType(child_handle)) {+          case FILE_TYPE_DISK:+            CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN;+            break;++          case FILE_TYPE_PIPE:+            CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;+            break;++          case FILE_TYPE_CHAR:+          case FILE_TYPE_REMOTE:+            CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;+            break;++          case FILE_TYPE_UNKNOWN:+            if (GetLastError() != 0) {+              err = GetLastError();+              CloseHandle(child_handle);+              goto error;+            }+            CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;+            break;++          default:+            assert(0);+            return -1;+        }++        CHILD_STDIO_HANDLE(buffer, i) = child_handle;+        break;+      }++      case UV_INHERIT_STREAM: {+        /* Use an existing stream as the stdio handle for the child. */+        HANDLE stream_handle, child_handle;+        unsigned char crt_flags;+        uv_stream_t* stream = fdopt.data.stream;++        /* Leech the handle out of the stream. */+        if (stream->type == UV_TTY) {+          stream_handle = ((uv_tty_t*) stream)->handle;+          crt_flags = FOPEN | FDEV;+        } else if (stream->type == UV_NAMED_PIPE &&+                   stream->flags & UV_HANDLE_CONNECTION) {+          stream_handle = ((uv_pipe_t*) stream)->handle;+          crt_flags = FOPEN | FPIPE;+        } else {+          stream_handle = INVALID_HANDLE_VALUE;+          crt_flags = 0;+        }++        if (stream_handle == NULL ||+            stream_handle == INVALID_HANDLE_VALUE) {+          /* The handle is already closed, or not yet created, or the stream+           * type is not supported. */+          err = ERROR_NOT_SUPPORTED;+          goto error;+        }++        /* Make an inheritable copy of the handle. */+        err = uv__duplicate_handle(loop, stream_handle, &child_handle);+        if (err)+          goto error;++        CHILD_STDIO_HANDLE(buffer, i) = child_handle;+        CHILD_STDIO_CRT_FLAGS(buffer, i) = crt_flags;+        break;+      }++      default:+        assert(0);+        return -1;+    }+  }++  *buffer_ptr  = buffer;+  return 0;++ error:+  uv__stdio_destroy(buffer);+  return err;+}+++void uv__stdio_destroy(BYTE* buffer) {+  int i, count;++  count = CHILD_STDIO_COUNT(buffer);+  for (i = 0; i < count; i++) {+    HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);+    if (handle != INVALID_HANDLE_VALUE) {+      CloseHandle(handle);+    }+  }++  uv__free(buffer);+}+++void uv__stdio_noinherit(BYTE* buffer) {+  int i, count;++  count = CHILD_STDIO_COUNT(buffer);+  for (i = 0; i < count; i++) {+    HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);+    if (handle != INVALID_HANDLE_VALUE) {+      SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);+    }+  }+}+++int uv__stdio_verify(BYTE* buffer, WORD size) {+  unsigned int count;++  /* Check the buffer pointer. */+  if (buffer == NULL)+    return 0;++  /* Verify that the buffer is at least big enough to hold the count. */+  if (size < CHILD_STDIO_SIZE(0))+    return 0;++  /* Verify if the count is within range. */+  count = CHILD_STDIO_COUNT(buffer);+  if (count > 256)+    return 0;++  /* Verify that the buffer size is big enough to hold info for N FDs. */+  if (size < CHILD_STDIO_SIZE(count))+    return 0;++  return 1;+}+++WORD uv__stdio_size(BYTE* buffer) {+  return (WORD) CHILD_STDIO_SIZE(CHILD_STDIO_COUNT((buffer)));+}+++HANDLE uv__stdio_handle(BYTE* buffer, int fd) {+  return CHILD_STDIO_HANDLE(buffer, fd);+}
+ third_party/libuv/src/win/process.c view
@@ -0,0 +1,1282 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <io.h>+#include <stdio.h>+#include <stdlib.h>+#include <signal.h>+#include <limits.h>+#include <wchar.h>+#include <malloc.h>    /* alloca */++#include "uv.h"+#include "internal.h"+#include "handle-inl.h"+#include "req-inl.h"+++#define SIGKILL         9+++typedef struct env_var {+  const WCHAR* const wide;+  const WCHAR* const wide_eq;+  const size_t len; /* including null or '=' */+} env_var_t;++#define E_V(str) { L##str, L##str L"=", sizeof(str) }++static const env_var_t required_vars[] = { /* keep me sorted */+  E_V("HOMEDRIVE"),+  E_V("HOMEPATH"),+  E_V("LOGONSERVER"),+  E_V("PATH"),+  E_V("SYSTEMDRIVE"),+  E_V("SYSTEMROOT"),+  E_V("TEMP"),+  E_V("USERDOMAIN"),+  E_V("USERNAME"),+  E_V("USERPROFILE"),+  E_V("WINDIR"),+};+static size_t n_required_vars = ARRAY_SIZE(required_vars);+++static HANDLE uv_global_job_handle_;+static uv_once_t uv_global_job_handle_init_guard_ = UV_ONCE_INIT;+++static void uv__init_global_job_handle(void) {+  /* Create a job object and set it up to kill all contained processes when+   * it's closed. Since this handle is made non-inheritable and we're not+   * giving it to anyone, we're the only process holding a reference to it.+   * That means that if this process exits it is closed and all the processes+   * it contains are killed. All processes created with uv_spawn that are not+   * spawned with the UV_PROCESS_DETACHED flag are assigned to this job.+   *+   * We're setting the JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag so only the+   * processes that we explicitly add are affected, and *their* subprocesses+   * are not. This ensures that our child processes are not limited in their+   * ability to use job control on Windows versions that don't deal with+   * nested jobs (prior to Windows 8 / Server 2012). It also lets our child+   * processes created detached processes without explicitly breaking away+   * from job control (which uv_spawn doesn't, either).+   */+  SECURITY_ATTRIBUTES attr;+  JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;++  memset(&attr, 0, sizeof attr);+  attr.bInheritHandle = FALSE;++  memset(&info, 0, sizeof info);+  info.BasicLimitInformation.LimitFlags =+      JOB_OBJECT_LIMIT_BREAKAWAY_OK |+      JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK |+      JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION |+      JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;++  uv_global_job_handle_ = CreateJobObjectW(&attr, NULL);+  if (uv_global_job_handle_ == NULL)+    uv_fatal_error(GetLastError(), "CreateJobObjectW");++  if (!SetInformationJobObject(uv_global_job_handle_,+                               JobObjectExtendedLimitInformation,+                               &info,+                               sizeof info))+    uv_fatal_error(GetLastError(), "SetInformationJobObject");+}+++static int uv_utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) {+  int ws_len, r;+  WCHAR* ws;++  ws_len = MultiByteToWideChar(CP_UTF8,+                               0,+                               s,+                               -1,+                               NULL,+                               0);+  if (ws_len <= 0) {+    return GetLastError();+  }++  ws = (WCHAR*) uv__malloc(ws_len * sizeof(WCHAR));+  if (ws == NULL) {+    return ERROR_OUTOFMEMORY;+  }++  r = MultiByteToWideChar(CP_UTF8,+                          0,+                          s,+                          -1,+                          ws,+                          ws_len);+  assert(r == ws_len);++  *ws_ptr = ws;+  return 0;+}+++static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {+  uv__handle_init(loop, (uv_handle_t*) handle, UV_PROCESS);+  handle->exit_cb = NULL;+  handle->pid = 0;+  handle->exit_signal = 0;+  handle->wait_handle = INVALID_HANDLE_VALUE;+  handle->process_handle = INVALID_HANDLE_VALUE;+  handle->child_stdio_buffer = NULL;+  handle->exit_cb_pending = 0;++  UV_REQ_INIT(&handle->exit_req, UV_PROCESS_EXIT);+  handle->exit_req.data = handle;+}+++/*+ * Path search functions+ */++/*+ * Helper function for search_path+ */+static WCHAR* search_path_join_test(const WCHAR* dir,+                                    size_t dir_len,+                                    const WCHAR* name,+                                    size_t name_len,+                                    const WCHAR* ext,+                                    size_t ext_len,+                                    const WCHAR* cwd,+                                    size_t cwd_len) {+  WCHAR *result, *result_pos;+  DWORD attrs;+  if (dir_len > 2 && dir[0] == L'\\' && dir[1] == L'\\') {+    /* It's a UNC path so ignore cwd */+    cwd_len = 0;+  } else if (dir_len >= 1 && (dir[0] == L'/' || dir[0] == L'\\')) {+    /* It's a full path without drive letter, use cwd's drive letter only */+    cwd_len = 2;+  } else if (dir_len >= 2 && dir[1] == L':' &&+      (dir_len < 3 || (dir[2] != L'/' && dir[2] != L'\\'))) {+    /* It's a relative path with drive letter (ext.g. D:../some/file)+     * Replace drive letter in dir by full cwd if it points to the same drive,+     * otherwise use the dir only.+     */+    if (cwd_len < 2 || _wcsnicmp(cwd, dir, 2) != 0) {+      cwd_len = 0;+    } else {+      dir += 2;+      dir_len -= 2;+    }+  } else if (dir_len > 2 && dir[1] == L':') {+    /* It's an absolute path with drive letter+     * Don't use the cwd at all+     */+    cwd_len = 0;+  }++  /* Allocate buffer for output */+  result = result_pos = (WCHAR*)uv__malloc(sizeof(WCHAR) *+      (cwd_len + 1 + dir_len + 1 + name_len + 1 + ext_len + 1));++  /* Copy cwd */+  wcsncpy(result_pos, cwd, cwd_len);+  result_pos += cwd_len;++  /* Add a path separator if cwd didn't end with one */+  if (cwd_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) {+    result_pos[0] = L'\\';+    result_pos++;+  }++  /* Copy dir */+  wcsncpy(result_pos, dir, dir_len);+  result_pos += dir_len;++  /* Add a separator if the dir didn't end with one */+  if (dir_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) {+    result_pos[0] = L'\\';+    result_pos++;+  }++  /* Copy filename */+  wcsncpy(result_pos, name, name_len);+  result_pos += name_len;++  if (ext_len) {+    /* Add a dot if the filename didn't end with one */+    if (name_len && result_pos[-1] != '.') {+      result_pos[0] = L'.';+      result_pos++;+    }++    /* Copy extension */+    wcsncpy(result_pos, ext, ext_len);+    result_pos += ext_len;+  }++  /* Null terminator */+  result_pos[0] = L'\0';++  attrs = GetFileAttributesW(result);++  if (attrs != INVALID_FILE_ATTRIBUTES &&+      !(attrs & FILE_ATTRIBUTE_DIRECTORY)) {+    return result;+  }++  uv__free(result);+  return NULL;+}+++/*+ * Helper function for search_path+ */+static WCHAR* path_search_walk_ext(const WCHAR *dir,+                                   size_t dir_len,+                                   const WCHAR *name,+                                   size_t name_len,+                                   WCHAR *cwd,+                                   size_t cwd_len,+                                   int name_has_ext) {+  WCHAR* result;++  /* If the name itself has a nonempty extension, try this extension first */+  if (name_has_ext) {+    result = search_path_join_test(dir, dir_len,+                                   name, name_len,+                                   L"", 0,+                                   cwd, cwd_len);+    if (result != NULL) {+      return result;+    }+  }++  /* Try .com extension */+  result = search_path_join_test(dir, dir_len,+                                 name, name_len,+                                 L"com", 3,+                                 cwd, cwd_len);+  if (result != NULL) {+    return result;+  }++  /* Try .exe extension */+  result = search_path_join_test(dir, dir_len,+                                 name, name_len,+                                 L"exe", 3,+                                 cwd, cwd_len);+  if (result != NULL) {+    return result;+  }++  return NULL;+}+++/*+ * search_path searches the system path for an executable filename -+ * the windows API doesn't provide this as a standalone function nor as an+ * option to CreateProcess.+ *+ * It tries to return an absolute filename.+ *+ * Furthermore, it tries to follow the semantics that cmd.exe, with this+ * exception that PATHEXT environment variable isn't used. Since CreateProcess+ * can start only .com and .exe files, only those extensions are tried. This+ * behavior equals that of msvcrt's spawn functions.+ *+ * - Do not search the path if the filename already contains a path (either+ *   relative or absolute).+ *+ * - If there's really only a filename, check the current directory for file,+ *   then search all path directories.+ *+ * - If filename specified has *any* extension, search for the file with the+ *   specified extension first.+ *+ * - If the literal filename is not found in a directory, try *appending*+ *   (not replacing) .com first and then .exe.+ *+ * - The path variable may contain relative paths; relative paths are relative+ *   to the cwd.+ *+ * - Directories in path may or may not end with a trailing backslash.+ *+ * - CMD does not trim leading/trailing whitespace from path/pathex entries+ *   nor from the environment variables as a whole.+ *+ * - When cmd.exe cannot read a directory, it will just skip it and go on+ *   searching. However, unlike posix-y systems, it will happily try to run a+ *   file that is not readable/executable; if the spawn fails it will not+ *   continue searching.+ *+ * UNC path support: we are dealing with UNC paths in both the path and the+ * filename. This is a deviation from what cmd.exe does (it does not let you+ * start a program by specifying an UNC path on the command line) but this is+ * really a pointless restriction.+ *+ */+static WCHAR* search_path(const WCHAR *file,+                            WCHAR *cwd,+                            const WCHAR *path) {+  int file_has_dir;+  WCHAR* result = NULL;+  WCHAR *file_name_start;+  WCHAR *dot;+  const WCHAR *dir_start, *dir_end, *dir_path;+  size_t dir_len;+  int name_has_ext;++  size_t file_len = wcslen(file);+  size_t cwd_len = wcslen(cwd);++  /* If the caller supplies an empty filename,+   * we're not gonna return c:\windows\.exe -- GFY!+   */+  if (file_len == 0+      || (file_len == 1 && file[0] == L'.')) {+    return NULL;+  }++  /* Find the start of the filename so we can split the directory from the+   * name. */+  for (file_name_start = (WCHAR*)file + file_len;+       file_name_start > file+           && file_name_start[-1] != L'\\'+           && file_name_start[-1] != L'/'+           && file_name_start[-1] != L':';+       file_name_start--);++  file_has_dir = file_name_start != file;++  /* Check if the filename includes an extension */+  dot = wcschr(file_name_start, L'.');+  name_has_ext = (dot != NULL && dot[1] != L'\0');++  if (file_has_dir) {+    /* The file has a path inside, don't use path */+    result = path_search_walk_ext(+        file, file_name_start - file,+        file_name_start, file_len - (file_name_start - file),+        cwd, cwd_len,+        name_has_ext);++  } else {+    dir_end = path;++    /* The file is really only a name; look in cwd first, then scan path */+    result = path_search_walk_ext(L"", 0,+                                  file, file_len,+                                  cwd, cwd_len,+                                  name_has_ext);++    while (result == NULL) {+      if (*dir_end == L'\0') {+        break;+      }++      /* Skip the separator that dir_end now points to */+      if (dir_end != path || *path == L';') {+        dir_end++;+      }++      /* Next slice starts just after where the previous one ended */+      dir_start = dir_end;++      /* If path is quoted, find quote end */+      if (*dir_start == L'"' || *dir_start == L'\'') {+        dir_end = wcschr(dir_start + 1, *dir_start);+        if (dir_end == NULL) {+          dir_end = wcschr(dir_start, L'\0');+        }+      }+      /* Slice until the next ; or \0 is found */+      dir_end = wcschr(dir_end, L';');+      if (dir_end == NULL) {+        dir_end = wcschr(dir_start, L'\0');+      }++      /* If the slice is zero-length, don't bother */+      if (dir_end - dir_start == 0) {+        continue;+      }++      dir_path = dir_start;+      dir_len = dir_end - dir_start;++      /* Adjust if the path is quoted. */+      if (dir_path[0] == '"' || dir_path[0] == '\'') {+        ++dir_path;+        --dir_len;+      }++      if (dir_path[dir_len - 1] == '"' || dir_path[dir_len - 1] == '\'') {+        --dir_len;+      }++      result = path_search_walk_ext(dir_path, dir_len,+                                    file, file_len,+                                    cwd, cwd_len,+                                    name_has_ext);+    }+  }++  return result;+}+++/*+ * Quotes command line arguments+ * Returns a pointer to the end (next char to be written) of the buffer+ */+WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target) {+  size_t len = wcslen(source);+  size_t i;+  int quote_hit;+  WCHAR* start;++  if (len == 0) {+    /* Need double quotation for empty argument */+    *(target++) = L'"';+    *(target++) = L'"';+    return target;+  }++  if (NULL == wcspbrk(source, L" \t\"")) {+    /* No quotation needed */+    wcsncpy(target, source, len);+    target += len;+    return target;+  }++  if (NULL == wcspbrk(source, L"\"\\")) {+    /*+     * No embedded double quotes or backlashes, so I can just wrap+     * quote marks around the whole thing.+     */+    *(target++) = L'"';+    wcsncpy(target, source, len);+    target += len;+    *(target++) = L'"';+    return target;+  }++  /*+   * Expected input/output:+   *   input : hello"world+   *   output: "hello\"world"+   *   input : hello""world+   *   output: "hello\"\"world"+   *   input : hello\world+   *   output: hello\world+   *   input : hello\\world+   *   output: hello\\world+   *   input : hello\"world+   *   output: "hello\\\"world"+   *   input : hello\\"world+   *   output: "hello\\\\\"world"+   *   input : hello world\+   *   output: "hello world\\"+   */++  *(target++) = L'"';+  start = target;+  quote_hit = 1;++  for (i = len; i > 0; --i) {+    *(target++) = source[i - 1];++    if (quote_hit && source[i - 1] == L'\\') {+      *(target++) = L'\\';+    } else if(source[i - 1] == L'"') {+      quote_hit = 1;+      *(target++) = L'\\';+    } else {+      quote_hit = 0;+    }+  }+  target[0] = L'\0';+  wcsrev(start);+  *(target++) = L'"';+  return target;+}+++int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) {+  char** arg;+  WCHAR* dst = NULL;+  WCHAR* temp_buffer = NULL;+  size_t dst_len = 0;+  size_t temp_buffer_len = 0;+  WCHAR* pos;+  int arg_count = 0;+  int err = 0;++  /* Count the required size. */+  for (arg = args; *arg; arg++) {+    DWORD arg_len;++    arg_len = MultiByteToWideChar(CP_UTF8,+                                  0,+                                  *arg,+                                  -1,+                                  NULL,+                                  0);+    if (arg_len == 0) {+      return GetLastError();+    }++    dst_len += arg_len;++    if (arg_len > temp_buffer_len)+      temp_buffer_len = arg_len;++    arg_count++;+  }++  /* Adjust for potential quotes. Also assume the worst-case scenario that+   * every character needs escaping, so we need twice as much space. */+  dst_len = dst_len * 2 + arg_count * 2;++  /* Allocate buffer for the final command line. */+  dst = (WCHAR*) uv__malloc(dst_len * sizeof(WCHAR));+  if (dst == NULL) {+    err = ERROR_OUTOFMEMORY;+    goto error;+  }++  /* Allocate temporary working buffer. */+  temp_buffer = (WCHAR*) uv__malloc(temp_buffer_len * sizeof(WCHAR));+  if (temp_buffer == NULL) {+    err = ERROR_OUTOFMEMORY;+    goto error;+  }++  pos = dst;+  for (arg = args; *arg; arg++) {+    DWORD arg_len;++    /* Convert argument to wide char. */+    arg_len = MultiByteToWideChar(CP_UTF8,+                                  0,+                                  *arg,+                                  -1,+                                  temp_buffer,+                                  (int) (dst + dst_len - pos));+    if (arg_len == 0) {+      err = GetLastError();+      goto error;+    }++    if (verbatim_arguments) {+      /* Copy verbatim. */+      wcscpy(pos, temp_buffer);+      pos += arg_len - 1;+    } else {+      /* Quote/escape, if needed. */+      pos = quote_cmd_arg(temp_buffer, pos);+    }++    *pos++ = *(arg + 1) ? L' ' : L'\0';+  }++  uv__free(temp_buffer);++  *dst_ptr = dst;+  return 0;++error:+  uv__free(dst);+  uv__free(temp_buffer);+  return err;+}+++int env_strncmp(const wchar_t* a, int na, const wchar_t* b) {+  wchar_t* a_eq;+  wchar_t* b_eq;+  wchar_t* A;+  wchar_t* B;+  int nb;+  int r;++  if (na < 0) {+    a_eq = wcschr(a, L'=');+    assert(a_eq);+    na = (int)(long)(a_eq - a);+  } else {+    na--;+  }+  b_eq = wcschr(b, L'=');+  assert(b_eq);+  nb = b_eq - b;++  A = alloca((na+1) * sizeof(wchar_t));+  B = alloca((nb+1) * sizeof(wchar_t));++  r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, a, na, A, na);+  assert(r==na);+  A[na] = L'\0';+  r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, b, nb, B, nb);+  assert(r==nb);+  B[nb] = L'\0';++  while (1) {+    wchar_t AA = *A++;+    wchar_t BB = *B++;+    if (AA < BB) {+      return -1;+    } else if (AA > BB) {+      return 1;+    } else if (!AA && !BB) {+      return 0;+    }+  }+}+++static int qsort_wcscmp(const void *a, const void *b) {+  wchar_t* astr = *(wchar_t* const*)a;+  wchar_t* bstr = *(wchar_t* const*)b;+  return env_strncmp(astr, -1, bstr);+}+++/*+ * The way windows takes environment variables is different than what C does;+ * Windows wants a contiguous block of null-terminated strings, terminated+ * with an additional null.+ *+ * Windows has a few "essential" environment variables. winsock will fail+ * to initialize if SYSTEMROOT is not defined; some APIs make reference to+ * TEMP. SYSTEMDRIVE is probably also important. We therefore ensure that+ * these get defined if the input environment block does not contain any+ * values for them.+ *+ * Also add variables known to Cygwin to be required for correct+ * subprocess operation in many cases:+ * https://github.com/Alexpux/Cygwin/blob/b266b04fbbd3a595f02ea149e4306d3ab9b1fe3d/winsup/cygwin/environ.cc#L955+ *+ */+int make_program_env(char* env_block[], WCHAR** dst_ptr) {+  WCHAR* dst;+  WCHAR* ptr;+  char** env;+  size_t env_len = 0;+  int len;+  size_t i;+  DWORD var_size;+  size_t env_block_count = 1; /* 1 for null-terminator */+  WCHAR* dst_copy;+  WCHAR** ptr_copy;+  WCHAR** env_copy;+  DWORD* required_vars_value_len = alloca(n_required_vars * sizeof(DWORD*));++  /* first pass: determine size in UTF-16 */+  for (env = env_block; *env; env++) {+    int len;+    if (strchr(*env, '=')) {+      len = MultiByteToWideChar(CP_UTF8,+                                0,+                                *env,+                                -1,+                                NULL,+                                0);+      if (len <= 0) {+        return GetLastError();+      }+      env_len += len;+      env_block_count++;+    }+  }++  /* second pass: copy to UTF-16 environment block */+  dst_copy = (WCHAR*)uv__malloc(env_len * sizeof(WCHAR));+  if (!dst_copy) {+    return ERROR_OUTOFMEMORY;+  }+  env_copy = alloca(env_block_count * sizeof(WCHAR*));++  ptr = dst_copy;+  ptr_copy = env_copy;+  for (env = env_block; *env; env++) {+    if (strchr(*env, '=')) {+      len = MultiByteToWideChar(CP_UTF8,+                                0,+                                *env,+                                -1,+                                ptr,+                                (int) (env_len - (ptr - dst_copy)));+      if (len <= 0) {+        DWORD err = GetLastError();+        uv__free(dst_copy);+        return err;+      }+      *ptr_copy++ = ptr;+      ptr += len;+    }+  }+  *ptr_copy = NULL;+  assert(env_len == (size_t) (ptr - dst_copy));++  /* sort our (UTF-16) copy */+  qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp);++  /* third pass: check for required variables */+  for (ptr_copy = env_copy, i = 0; i < n_required_vars; ) {+    int cmp;+    if (!*ptr_copy) {+      cmp = -1;+    } else {+      cmp = env_strncmp(required_vars[i].wide_eq,+                       required_vars[i].len,+                        *ptr_copy);+    }+    if (cmp < 0) {+      /* missing required var */+      var_size = GetEnvironmentVariableW(required_vars[i].wide, NULL, 0);+      required_vars_value_len[i] = var_size;+      if (var_size != 0) {+        env_len += required_vars[i].len;+        env_len += var_size;+      }+      i++;+    } else {+      ptr_copy++;+      if (cmp == 0)+        i++;+    }+  }++  /* final pass: copy, in sort order, and inserting required variables */+  dst = uv__malloc((1+env_len) * sizeof(WCHAR));+  if (!dst) {+    uv__free(dst_copy);+    return ERROR_OUTOFMEMORY;+  }++  for (ptr = dst, ptr_copy = env_copy, i = 0;+       *ptr_copy || i < n_required_vars;+       ptr += len) {+    int cmp;+    if (i >= n_required_vars) {+      cmp = 1;+    } else if (!*ptr_copy) {+      cmp = -1;+    } else {+      cmp = env_strncmp(required_vars[i].wide_eq,+                        required_vars[i].len,+                        *ptr_copy);+    }+    if (cmp < 0) {+      /* missing required var */+      len = required_vars_value_len[i];+      if (len) {+        wcscpy(ptr, required_vars[i].wide_eq);+        ptr += required_vars[i].len;+        var_size = GetEnvironmentVariableW(required_vars[i].wide,+                                           ptr,+                                           (int) (env_len - (ptr - dst)));+        if (var_size != (DWORD) (len - 1)) { /* TODO: handle race condition? */+          uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");+        }+      }+      i++;+    } else {+      /* copy var from env_block */+      len = wcslen(*ptr_copy) + 1;+      wmemcpy(ptr, *ptr_copy, len);+      ptr_copy++;+      if (cmp == 0)+        i++;+    }+  }++  /* Terminate with an extra NULL. */+  assert(env_len == (size_t) (ptr - dst));+  *ptr = L'\0';++  uv__free(dst_copy);+  *dst_ptr = dst;+  return 0;+}++/*+ * Attempt to find the value of the PATH environment variable in the child's+ * preprocessed environment.+ *+ * If found, a pointer into `env` is returned. If not found, NULL is returned.+ */+static WCHAR* find_path(WCHAR *env) {+  for (; env != NULL && *env != 0; env += wcslen(env) + 1) {+    if ((env[0] == L'P' || env[0] == L'p') &&+        (env[1] == L'A' || env[1] == L'a') &&+        (env[2] == L'T' || env[2] == L't') &&+        (env[3] == L'H' || env[3] == L'h') &&+        (env[4] == L'=')) {+      return &env[5];+    }+  }++  return NULL;+}++/*+ * Called on Windows thread-pool thread to indicate that+ * a child process has exited.+ */+static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout) {+  uv_process_t* process = (uv_process_t*) data;+  uv_loop_t* loop = process->loop;++  assert(didTimeout == FALSE);+  assert(process);+  assert(!process->exit_cb_pending);++  process->exit_cb_pending = 1;++  /* Post completed */+  POST_COMPLETION_FOR_REQ(loop, &process->exit_req);+}+++/* Called on main thread after a child process has exited. */+void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {+  int64_t exit_code;+  DWORD status;++  assert(handle->exit_cb_pending);+  handle->exit_cb_pending = 0;++  /* If we're closing, don't call the exit callback. Just schedule a close+   * callback now. */+  if (handle->flags & UV_HANDLE_CLOSING) {+    uv_want_endgame(loop, (uv_handle_t*) handle);+    return;+  }++  /* Unregister from process notification. */+  if (handle->wait_handle != INVALID_HANDLE_VALUE) {+    UnregisterWait(handle->wait_handle);+    handle->wait_handle = INVALID_HANDLE_VALUE;+  }++  /* Set the handle to inactive: no callbacks will be made after the exit+   * callback. */+  uv__handle_stop(handle);++  if (GetExitCodeProcess(handle->process_handle, &status)) {+    exit_code = status;+  } else {+    /* Unable to obtain the exit code. This should never happen. */+    exit_code = uv_translate_sys_error(GetLastError());+  }++  /* Fire the exit callback. */+  if (handle->exit_cb) {+    handle->exit_cb(handle, exit_code, handle->exit_signal);+  }+}+++void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {+  uv__handle_closing(handle);++  if (handle->wait_handle != INVALID_HANDLE_VALUE) {+    /* This blocks until either the wait was cancelled, or the callback has+     * completed. */+    BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE);+    if (!r) {+      /* This should never happen, and if it happens, we can't recover... */+      uv_fatal_error(GetLastError(), "UnregisterWaitEx");+    }++    handle->wait_handle = INVALID_HANDLE_VALUE;+  }++  if (!handle->exit_cb_pending) {+    uv_want_endgame(loop, (uv_handle_t*)handle);+  }+}+++void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {+  assert(!handle->exit_cb_pending);+  assert(handle->flags & UV_HANDLE_CLOSING);+  assert(!(handle->flags & UV_HANDLE_CLOSED));++  /* Clean-up the process handle. */+  CloseHandle(handle->process_handle);++  uv__handle_close(handle);+}+++int uv_spawn(uv_loop_t* loop,+             uv_process_t* process,+             const uv_process_options_t* options) {+  int i;+  int err = 0;+  WCHAR* path = NULL, *alloc_path = NULL;+  BOOL result;+  WCHAR* application_path = NULL, *application = NULL, *arguments = NULL,+         *env = NULL, *cwd = NULL;+  STARTUPINFOW startup;+  PROCESS_INFORMATION info;+  DWORD process_flags;++  uv_process_init(loop, process);+  process->exit_cb = options->exit_cb;++  if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {+    return UV_ENOTSUP;+  }++  if (options->file == NULL ||+      options->args == NULL) {+    return UV_EINVAL;+  }++  assert(options->file != NULL);+  assert(!(options->flags & ~(UV_PROCESS_DETACHED |+                              UV_PROCESS_SETGID |+                              UV_PROCESS_SETUID |+                              UV_PROCESS_WINDOWS_HIDE |+                              UV_PROCESS_WINDOWS_HIDE_CONSOLE |+                              UV_PROCESS_WINDOWS_HIDE_GUI |+                              UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));++  err = uv_utf8_to_utf16_alloc(options->file, &application);+  if (err)+    goto done;++  err = make_program_args(+      options->args,+      options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS,+      &arguments);+  if (err)+    goto done;++  if (options->env) {+     err = make_program_env(options->env, &env);+     if (err)+       goto done;+  }++  if (options->cwd) {+    /* Explicit cwd */+    err = uv_utf8_to_utf16_alloc(options->cwd, &cwd);+    if (err)+      goto done;++  } else {+    /* Inherit cwd */+    DWORD cwd_len, r;++    cwd_len = GetCurrentDirectoryW(0, NULL);+    if (!cwd_len) {+      err = GetLastError();+      goto done;+    }++    cwd = (WCHAR*) uv__malloc(cwd_len * sizeof(WCHAR));+    if (cwd == NULL) {+      err = ERROR_OUTOFMEMORY;+      goto done;+    }++    r = GetCurrentDirectoryW(cwd_len, cwd);+    if (r == 0 || r >= cwd_len) {+      err = GetLastError();+      goto done;+    }+  }++  /* Get PATH environment variable. */+  path = find_path(env);+  if (path == NULL) {+    DWORD path_len, r;++    path_len = GetEnvironmentVariableW(L"PATH", NULL, 0);+    if (path_len == 0) {+      err = GetLastError();+      goto done;+    }++    alloc_path = (WCHAR*) uv__malloc(path_len * sizeof(WCHAR));+    if (alloc_path == NULL) {+      err = ERROR_OUTOFMEMORY;+      goto done;+    }+    path = alloc_path;++    r = GetEnvironmentVariableW(L"PATH", path, path_len);+    if (r == 0 || r >= path_len) {+      err = GetLastError();+      goto done;+    }+  }++  err = uv__stdio_create(loop, options, &process->child_stdio_buffer);+  if (err)+    goto done;++  application_path = search_path(application,+                                 cwd,+                                 path);+  if (application_path == NULL) {+    /* Not found. */+    err = ERROR_FILE_NOT_FOUND;+    goto done;+  }++  startup.cb = sizeof(startup);+  startup.lpReserved = NULL;+  startup.lpDesktop = NULL;+  startup.lpTitle = NULL;+  startup.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;++  startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer);+  startup.lpReserved2 = (BYTE*) process->child_stdio_buffer;++  startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0);+  startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1);+  startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2);++  process_flags = CREATE_UNICODE_ENVIRONMENT;++  if ((options->flags & UV_PROCESS_WINDOWS_HIDE_CONSOLE) ||+      (options->flags & UV_PROCESS_WINDOWS_HIDE)) {+    /* Avoid creating console window if stdio is not inherited. */+    for (i = 0; i < options->stdio_count; i++) {+      if (options->stdio[i].flags & UV_INHERIT_FD)+        break;+      if (i == options->stdio_count - 1)+        process_flags |= CREATE_NO_WINDOW;+    }+  }+  if ((options->flags & UV_PROCESS_WINDOWS_HIDE_GUI) ||+      (options->flags & UV_PROCESS_WINDOWS_HIDE)) {+    /* Use SW_HIDE to avoid any potential process window. */+    startup.wShowWindow = SW_HIDE;+  } else {+    startup.wShowWindow = SW_SHOWDEFAULT;+  }++  if (options->flags & UV_PROCESS_DETACHED) {+    /* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That+     * means that libuv might not let you create a fully daemonized process+     * when run under job control. However the type of job control that libuv+     * itself creates doesn't trickle down to subprocesses so they can still+     * daemonize.+     *+     * A reason to not do this is that CREATE_BREAKAWAY_FROM_JOB makes the+     * CreateProcess call fail if we're under job control that doesn't allow+     * breakaway.+     */+    process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;+  }++  if (!CreateProcessW(application_path,+                     arguments,+                     NULL,+                     NULL,+                     1,+                     process_flags,+                     env,+                     cwd,+                     &startup,+                     &info)) {+    /* CreateProcessW failed. */+    err = GetLastError();+    goto done;+  }++  /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */++  process->process_handle = info.hProcess;+  process->pid = info.dwProcessId;++  /* If the process isn't spawned as detached, assign to the global job object+   * so windows will kill it when the parent process dies. */+  if (!(options->flags & UV_PROCESS_DETACHED)) {+    uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);++    if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) {+      /* AssignProcessToJobObject might fail if this process is under job+       * control and the job doesn't have the+       * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version+       * that doesn't support nested jobs.+       *+       * When that happens we just swallow the error and continue without+       * establishing a kill-child-on-parent-exit relationship, otherwise+       * there would be no way for libuv applications run under job control+       * to spawn processes at all.+       */+      DWORD err = GetLastError();+      if (err != ERROR_ACCESS_DENIED)+        uv_fatal_error(err, "AssignProcessToJobObject");+    }+  }++  /* Set IPC pid to all IPC pipes. */+  for (i = 0; i < options->stdio_count; i++) {+    const uv_stdio_container_t* fdopt = &options->stdio[i];+    if (fdopt->flags & UV_CREATE_PIPE &&+        fdopt->data.stream->type == UV_NAMED_PIPE &&+        ((uv_pipe_t*) fdopt->data.stream)->ipc) {+      ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_remote_pid =+          info.dwProcessId;+    }+  }++  /* Setup notifications for when the child process exits. */+  result = RegisterWaitForSingleObject(&process->wait_handle,+      process->process_handle, exit_wait_callback, (void*)process, INFINITE,+      WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE);+  if (!result) {+    uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject");+  }++  CloseHandle(info.hThread);++  assert(!err);++  /* Make the handle active. It will remain active until the exit callback is+   * made or the handle is closed, whichever happens first. */+  uv__handle_start(process);++  /* Cleanup, whether we succeeded or failed. */+ done:+  uv__free(application);+  uv__free(application_path);+  uv__free(arguments);+  uv__free(cwd);+  uv__free(env);+  uv__free(alloc_path);++  if (process->child_stdio_buffer != NULL) {+    /* Clean up child stdio handles. */+    uv__stdio_destroy(process->child_stdio_buffer);+    process->child_stdio_buffer = NULL;+  }++  return uv_translate_sys_error(err);+}+++static int uv__kill(HANDLE process_handle, int signum) {+  if (signum < 0 || signum >= NSIG) {+    return UV_EINVAL;+  }++  switch (signum) {+    case SIGTERM:+    case SIGKILL:+    case SIGINT: {+      /* Unconditionally terminate the process. On Windows, killed processes+       * normally return 1. */+      DWORD status;+      int err;++      if (TerminateProcess(process_handle, 1))+        return 0;++      /* If the process already exited before TerminateProcess was called,.+       * TerminateProcess will fail with ERROR_ACCESS_DENIED. */+      err = GetLastError();+      if (err == ERROR_ACCESS_DENIED &&+          GetExitCodeProcess(process_handle, &status) &&+          status != STILL_ACTIVE) {+        return UV_ESRCH;+      }++      return uv_translate_sys_error(err);+    }++    case 0: {+      /* Health check: is the process still alive? */+      DWORD status;++      if (!GetExitCodeProcess(process_handle, &status))+        return uv_translate_sys_error(GetLastError());++      if (status != STILL_ACTIVE)+        return UV_ESRCH;++      return 0;+    }++    default:+      /* Unsupported signal. */+      return UV_ENOSYS;+  }+}+++int uv_process_kill(uv_process_t* process, int signum) {+  int err;++  if (process->process_handle == INVALID_HANDLE_VALUE) {+    return UV_EINVAL;+  }++  err = uv__kill(process->process_handle, signum);+  if (err) {+    return err;  /* err is already translated. */+  }++  process->exit_signal = signum;++  return 0;+}+++int uv_kill(int pid, int signum) {+  int err;+  HANDLE process_handle;++  if (pid == 0) {+    process_handle = GetCurrentProcess();+  } else {+    process_handle = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION,+                                 FALSE,+                                 pid);+  }++  if (process_handle == NULL) {+    err = GetLastError();+    if (err == ERROR_INVALID_PARAMETER) {+      return UV_ESRCH;+    } else {+      return uv_translate_sys_error(err);+    }+  }++  err = uv__kill(process_handle, signum);+  CloseHandle(process_handle);++  return err;  /* err is already translated. */+}
+ third_party/libuv/src/win/req-inl.h view
@@ -0,0 +1,221 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#ifndef UV_WIN_REQ_INL_H_+#define UV_WIN_REQ_INL_H_++#include <assert.h>++#include "uv.h"+#include "internal.h"+++#define SET_REQ_STATUS(req, status)                                     \+   (req)->u.io.overlapped.Internal = (ULONG_PTR) (status)++#define SET_REQ_ERROR(req, error)                                       \+  SET_REQ_STATUS((req), NTSTATUS_FROM_WIN32((error)))++/* Note: used open-coded in UV_REQ_INIT() because of a circular dependency+ * between src/uv-common.h and src/win/internal.h.+ */+#define SET_REQ_SUCCESS(req)                                            \+  SET_REQ_STATUS((req), STATUS_SUCCESS)++#define GET_REQ_STATUS(req)                                             \+  ((NTSTATUS) (req)->u.io.overlapped.Internal)++#define REQ_SUCCESS(req)                                                \+  (NT_SUCCESS(GET_REQ_STATUS((req))))++#define GET_REQ_ERROR(req)                                              \+  (pRtlNtStatusToDosError(GET_REQ_STATUS((req))))++#define GET_REQ_SOCK_ERROR(req)                                         \+  (uv_ntstatus_to_winsock_error(GET_REQ_STATUS((req))))+++#define REGISTER_HANDLE_REQ(loop, handle, req)                          \+  do {                                                                  \+    INCREASE_ACTIVE_COUNT((loop), (handle));                            \+    uv__req_register((loop), (req));                                    \+  } while (0)++#define UNREGISTER_HANDLE_REQ(loop, handle, req)                        \+  do {                                                                  \+    DECREASE_ACTIVE_COUNT((loop), (handle));                            \+    uv__req_unregister((loop), (req));                                  \+  } while (0)+++#define UV_SUCCEEDED_WITHOUT_IOCP(result)                               \+  ((result) && (handle->flags & UV_HANDLE_SYNC_BYPASS_IOCP))++#define UV_SUCCEEDED_WITH_IOCP(result)                                  \+  ((result) || (GetLastError() == ERROR_IO_PENDING))+++#define POST_COMPLETION_FOR_REQ(loop, req)                              \+  if (!PostQueuedCompletionStatus((loop)->iocp,                         \+                                  0,                                    \+                                  0,                                    \+                                  &((req)->u.io.overlapped))) {         \+    uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");       \+  }+++INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) {+  return CONTAINING_RECORD(overlapped, uv_req_t, u.io.overlapped);+}+++INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) {+  req->next_req = NULL;+  if (loop->pending_reqs_tail) {+#ifdef _DEBUG+    /* Ensure the request is not already in the queue, or the queue+     * will get corrupted.+     */+    uv_req_t* current = loop->pending_reqs_tail;+    do {+      assert(req != current);+      current = current->next_req;+    } while(current != loop->pending_reqs_tail);+#endif++    req->next_req = loop->pending_reqs_tail->next_req;+    loop->pending_reqs_tail->next_req = req;+    loop->pending_reqs_tail = req;+  } else {+    req->next_req = req;+    loop->pending_reqs_tail = req;+  }+}+++#define DELEGATE_STREAM_REQ(loop, req, method, handle_at)                     \+  do {                                                                        \+    switch (((uv_handle_t*) (req)->handle_at)->type) {                        \+      case UV_TCP:                                                            \+        uv_process_tcp_##method##_req(loop,                                   \+                                      (uv_tcp_t*) ((req)->handle_at),         \+                                      req);                                   \+        break;                                                                \+                                                                              \+      case UV_NAMED_PIPE:                                                     \+        uv_process_pipe_##method##_req(loop,                                  \+                                       (uv_pipe_t*) ((req)->handle_at),       \+                                       req);                                  \+        break;                                                                \+                                                                              \+      case UV_TTY:                                                            \+        uv_process_tty_##method##_req(loop,                                   \+                                      (uv_tty_t*) ((req)->handle_at),         \+                                      req);                                   \+        break;                                                                \+                                                                              \+      default:                                                                \+        assert(0);                                                            \+    }                                                                         \+  } while (0)+++INLINE static int uv_process_reqs(uv_loop_t* loop) {+  uv_req_t* req;+  uv_req_t* first;+  uv_req_t* next;++  if (loop->pending_reqs_tail == NULL)+    return 0;++  first = loop->pending_reqs_tail->next_req;+  next = first;+  loop->pending_reqs_tail = NULL;++  while (next != NULL) {+    req = next;+    next = req->next_req != first ? req->next_req : NULL;++    switch (req->type) {+      case UV_READ:+        DELEGATE_STREAM_REQ(loop, req, read, data);+        break;++      case UV_WRITE:+        DELEGATE_STREAM_REQ(loop, (uv_write_t*) req, write, handle);+        break;++      case UV_ACCEPT:+        DELEGATE_STREAM_REQ(loop, req, accept, data);+        break;++      case UV_CONNECT:+        DELEGATE_STREAM_REQ(loop, (uv_connect_t*) req, connect, handle);+        break;++      case UV_SHUTDOWN:+        /* Tcp shutdown requests don't come here. */+        assert(((uv_shutdown_t*) req)->handle->type == UV_NAMED_PIPE);+        uv_process_pipe_shutdown_req(+            loop,+            (uv_pipe_t*) ((uv_shutdown_t*) req)->handle,+            (uv_shutdown_t*) req);+        break;++      case UV_UDP_RECV:+        uv_process_udp_recv_req(loop, (uv_udp_t*) req->data, req);+        break;++      case UV_UDP_SEND:+        uv_process_udp_send_req(loop,+                                ((uv_udp_send_t*) req)->handle,+                                (uv_udp_send_t*) req);+        break;++      case UV_WAKEUP:+        uv_process_async_wakeup_req(loop, (uv_async_t*) req->data, req);+        break;++      case UV_SIGNAL_REQ:+        uv_process_signal_req(loop, (uv_signal_t*) req->data, req);+        break;++      case UV_POLL_REQ:+        uv_process_poll_req(loop, (uv_poll_t*) req->data, req);+        break;++      case UV_PROCESS_EXIT:+        uv_process_proc_exit(loop, (uv_process_t*) req->data);+        break;++      case UV_FS_EVENT_REQ:+        uv_process_fs_event_req(loop, req, (uv_fs_event_t*) req->data);+        break;++      default:+        assert(0);+    }+  }++  return 1;+}++#endif /* UV_WIN_REQ_INL_H_ */
+ third_party/libuv/src/win/signal.c view
@@ -0,0 +1,277 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <signal.h>++#include "uv.h"+#include "internal.h"+#include "handle-inl.h"+#include "req-inl.h"+++RB_HEAD(uv_signal_tree_s, uv_signal_s);++static struct uv_signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree);+static CRITICAL_SECTION uv__signal_lock;++static BOOL WINAPI uv__signal_control_handler(DWORD type);++int uv__signal_start(uv_signal_t* handle,+                     uv_signal_cb signal_cb,+                     int signum,+                     int oneshot);++void uv_signals_init(void) {+  InitializeCriticalSection(&uv__signal_lock);+  if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))+    abort();+}+++static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {+  /* Compare signums first so all watchers with the same signnum end up+   * adjacent. */+  if (w1->signum < w2->signum) return -1;+  if (w1->signum > w2->signum) return 1;++  /* Sort by loop pointer, so we can easily look up the first item after+   * { .signum = x, .loop = NULL }. */+  if ((uintptr_t) w1->loop < (uintptr_t) w2->loop) return -1;+  if ((uintptr_t) w1->loop > (uintptr_t) w2->loop) return 1;++  if ((uintptr_t) w1 < (uintptr_t) w2) return -1;+  if ((uintptr_t) w1 > (uintptr_t) w2) return 1;++  return 0;+}+++RB_GENERATE_STATIC(uv_signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare)+++/*+ * Dispatches signal {signum} to all active uv_signal_t watchers in all loops.+ * Returns 1 if the signal was dispatched to any watcher, or 0 if there were+ * no active signal watchers observing this signal.+ */+int uv__signal_dispatch(int signum) {+  uv_signal_t lookup;+  uv_signal_t* handle;+  int dispatched;++  dispatched = 0;++  EnterCriticalSection(&uv__signal_lock);++  lookup.signum = signum;+  lookup.loop = NULL;++  for (handle = RB_NFIND(uv_signal_tree_s, &uv__signal_tree, &lookup);+       handle != NULL && handle->signum == signum;+       handle = RB_NEXT(uv_signal_tree_s, &uv__signal_tree, handle)) {+    unsigned long previous = InterlockedExchange(+            (volatile LONG*) &handle->pending_signum, signum);++    if (handle->flags & UV_SIGNAL_ONE_SHOT_DISPATCHED)+      continue;++    if (!previous) {+      POST_COMPLETION_FOR_REQ(handle->loop, &handle->signal_req);+    }++    dispatched = 1;+    if (handle->flags & UV_SIGNAL_ONE_SHOT)+      handle->flags |= UV_SIGNAL_ONE_SHOT_DISPATCHED;+  }++  LeaveCriticalSection(&uv__signal_lock);++  return dispatched;+}+++static BOOL WINAPI uv__signal_control_handler(DWORD type) {+  switch (type) {+    case CTRL_C_EVENT:+      return uv__signal_dispatch(SIGINT);++    case CTRL_BREAK_EVENT:+      return uv__signal_dispatch(SIGBREAK);++    case CTRL_CLOSE_EVENT:+      if (uv__signal_dispatch(SIGHUP)) {+        /* Windows will terminate the process after the control handler+         * returns. After that it will just terminate our process. Therefore+         * block the signal handler so the main loop has some time to pick up+         * the signal and do something for a few seconds. */+        Sleep(INFINITE);+        return TRUE;+      }+      return FALSE;++    case CTRL_LOGOFF_EVENT:+    case CTRL_SHUTDOWN_EVENT:+      /* These signals are only sent to services. Services have their own+       * notification mechanism, so there's no point in handling these. */++    default:+      /* We don't handle these. */+      return FALSE;+  }+}+++int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {+  uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL);+  handle->pending_signum = 0;+  handle->signum = 0;+  handle->signal_cb = NULL;++  UV_REQ_INIT(&handle->signal_req, UV_SIGNAL_REQ);+  handle->signal_req.data = handle;++  return 0;+}+++int uv_signal_stop(uv_signal_t* handle) {+  uv_signal_t* removed_handle;++  /* If the watcher wasn't started, this is a no-op. */+  if (handle->signum == 0)+    return 0;++  EnterCriticalSection(&uv__signal_lock);++  removed_handle = RB_REMOVE(uv_signal_tree_s, &uv__signal_tree, handle);+  assert(removed_handle == handle);++  LeaveCriticalSection(&uv__signal_lock);++  handle->signum = 0;+  uv__handle_stop(handle);++  return 0;+}+++int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {+  return uv__signal_start(handle, signal_cb, signum, 0);+}+++int uv_signal_start_oneshot(uv_signal_t* handle,+                            uv_signal_cb signal_cb,+                            int signum) {+  return uv__signal_start(handle, signal_cb, signum, 1);+}+++int uv__signal_start(uv_signal_t* handle,+                            uv_signal_cb signal_cb,+                            int signum,+                            int oneshot) {+  /* Test for invalid signal values. */+  if (signum <= 0 || signum >= NSIG)+    return UV_EINVAL;++  /* Short circuit: if the signal watcher is already watching {signum} don't go+   * through the process of deregistering and registering the handler.+   * Additionally, this avoids pending signals getting lost in the (small) time+   * frame that handle->signum == 0. */+  if (signum == handle->signum) {+    handle->signal_cb = signal_cb;+    return 0;+  }++  /* If the signal handler was already active, stop it first. */+  if (handle->signum != 0) {+    int r = uv_signal_stop(handle);+    /* uv_signal_stop is infallible. */+    assert(r == 0);+  }++  EnterCriticalSection(&uv__signal_lock);++  handle->signum = signum;+  if (oneshot)+    handle->flags |= UV_SIGNAL_ONE_SHOT;++  RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle);++  LeaveCriticalSection(&uv__signal_lock);++  handle->signal_cb = signal_cb;+  uv__handle_start(handle);++  return 0;+}+++void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,+    uv_req_t* req) {+  long dispatched_signum;++  assert(handle->type == UV_SIGNAL);+  assert(req->type == UV_SIGNAL_REQ);++  dispatched_signum = InterlockedExchange(+          (volatile LONG*) &handle->pending_signum, 0);+  assert(dispatched_signum != 0);++  /* Check if the pending signal equals the signum that we are watching for.+   * These can get out of sync when the handler is stopped and restarted while+   * the signal_req is pending. */+  if (dispatched_signum == handle->signum)+    handle->signal_cb(handle, dispatched_signum);++  if (handle->flags & UV_SIGNAL_ONE_SHOT)+    uv_signal_stop(handle);++  if (handle->flags & UV_HANDLE_CLOSING) {+    /* When it is closing, it must be stopped at this point. */+    assert(handle->signum == 0);+    uv_want_endgame(loop, (uv_handle_t*) handle);+  }+}+++void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle) {+  uv_signal_stop(handle);+  uv__handle_closing(handle);++  if (handle->pending_signum == 0) {+    uv_want_endgame(loop, (uv_handle_t*) handle);+  }+}+++void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle) {+  assert(handle->flags & UV_HANDLE_CLOSING);+  assert(!(handle->flags & UV_HANDLE_CLOSED));++  assert(handle->signum == 0);+  assert(handle->pending_signum == 0);++  handle->flags |= UV_HANDLE_CLOSED;++  uv__handle_close(handle);+}
+ third_party/libuv/src/win/snprintf.c view
@@ -0,0 +1,42 @@+/* Copyright the libuv project contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#if defined(_MSC_VER) && _MSC_VER < 1900++#include <stdio.h>+#include <stdarg.h>++/* Emulate snprintf() on MSVC<2015, _snprintf() doesn't zero-terminate the buffer+ * on overflow...+ */+int snprintf(char* buf, size_t len, const char* fmt, ...) {+  int n;+  va_list ap;+  va_start(ap, fmt);++  n = _vscprintf(fmt, ap);+  vsnprintf_s(buf, len, _TRUNCATE, fmt, ap);++  va_end(ap);+  return n;+}++#endif
+ third_party/libuv/src/win/stream-inl.h view
@@ -0,0 +1,54 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#ifndef UV_WIN_STREAM_INL_H_+#define UV_WIN_STREAM_INL_H_++#include <assert.h>++#include "uv.h"+#include "internal.h"+#include "handle-inl.h"+#include "req-inl.h"+++INLINE static void uv_stream_init(uv_loop_t* loop,+                                  uv_stream_t* handle,+                                  uv_handle_type type) {+  uv__handle_init(loop, (uv_handle_t*) handle, type);+  handle->write_queue_size = 0;+  handle->activecnt = 0;+  handle->stream.conn.shutdown_req = NULL;+  handle->stream.conn.write_reqs_pending = 0;++  UV_REQ_INIT(&handle->read_req, UV_READ);+  handle->read_req.event_handle = NULL;+  handle->read_req.wait_handle = INVALID_HANDLE_VALUE;+  handle->read_req.data = handle;+}+++INLINE static void uv_connection_init(uv_stream_t* handle) {+  handle->flags |= UV_HANDLE_CONNECTION;+}+++#endif /* UV_WIN_STREAM_INL_H_ */
+ third_party/libuv/src/win/stream.c view
@@ -0,0 +1,240 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>++#include "uv.h"+#include "internal.h"+#include "handle-inl.h"+#include "req-inl.h"+++int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {+  int err;++  err = ERROR_INVALID_PARAMETER;+  switch (stream->type) {+    case UV_TCP:+      err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb);+      break;+    case UV_NAMED_PIPE:+      err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb);+      break;+    default:+      assert(0);+  }++  return uv_translate_sys_error(err);+}+++int uv_accept(uv_stream_t* server, uv_stream_t* client) {+  int err;++  err = ERROR_INVALID_PARAMETER;+  switch (server->type) {+    case UV_TCP:+      err = uv_tcp_accept((uv_tcp_t*)server, (uv_tcp_t*)client);+      break;+    case UV_NAMED_PIPE:+      err = uv_pipe_accept((uv_pipe_t*)server, client);+      break;+    default:+      assert(0);+  }++  return uv_translate_sys_error(err);+}+++int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb,+    uv_read_cb read_cb) {+  int err;++  if (handle->flags & UV_HANDLE_READING) {+    return UV_EALREADY;+  }++  if (!(handle->flags & UV_HANDLE_READABLE)) {+    return UV_ENOTCONN;+  }++  err = ERROR_INVALID_PARAMETER;+  switch (handle->type) {+    case UV_TCP:+      err = uv_tcp_read_start((uv_tcp_t*)handle, alloc_cb, read_cb);+      break;+    case UV_NAMED_PIPE:+      err = uv_pipe_read_start((uv_pipe_t*)handle, alloc_cb, read_cb);+      break;+    case UV_TTY:+      err = uv_tty_read_start((uv_tty_t*) handle, alloc_cb, read_cb);+      break;+    default:+      assert(0);+  }++  return uv_translate_sys_error(err);+}+++int uv_read_stop(uv_stream_t* handle) {+  int err;++  if (!(handle->flags & UV_HANDLE_READING))+    return 0;++  err = 0;+  if (handle->type == UV_TTY) {+    err = uv_tty_read_stop((uv_tty_t*) handle);+  } else if (handle->type == UV_NAMED_PIPE) {+    uv__pipe_read_stop((uv_pipe_t*) handle);+  } else {+    handle->flags &= ~UV_HANDLE_READING;+    DECREASE_ACTIVE_COUNT(handle->loop, handle);+  }++  return uv_translate_sys_error(err);+}+++int uv_write(uv_write_t* req,+             uv_stream_t* handle,+             const uv_buf_t bufs[],+             unsigned int nbufs,+             uv_write_cb cb) {+  uv_loop_t* loop = handle->loop;+  int err;++  if (!(handle->flags & UV_HANDLE_WRITABLE)) {+    return UV_EPIPE;+  }++  err = ERROR_INVALID_PARAMETER;+  switch (handle->type) {+    case UV_TCP:+      err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb);+      break;+    case UV_NAMED_PIPE:+      err = uv__pipe_write(+          loop, req, (uv_pipe_t*) handle, bufs, nbufs, NULL, cb);+      break;+    case UV_TTY:+      err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb);+      break;+    default:+      assert(0);+  }++  return uv_translate_sys_error(err);+}+++int uv_write2(uv_write_t* req,+              uv_stream_t* handle,+              const uv_buf_t bufs[],+              unsigned int nbufs,+              uv_stream_t* send_handle,+              uv_write_cb cb) {+  uv_loop_t* loop = handle->loop;+  int err;++  if (send_handle == NULL) {+    return uv_write(req, handle, bufs, nbufs, cb);+  }++  if (handle->type != UV_NAMED_PIPE || !((uv_pipe_t*) handle)->ipc) {+    return UV_EINVAL;+  } else if (!(handle->flags & UV_HANDLE_WRITABLE)) {+    return UV_EPIPE;+  }++  err = uv__pipe_write(+      loop, req, (uv_pipe_t*) handle, bufs, nbufs, send_handle, cb);+  return uv_translate_sys_error(err);+}+++int uv_try_write(uv_stream_t* stream,+                 const uv_buf_t bufs[],+                 unsigned int nbufs) {+  if (stream->flags & UV_HANDLE_CLOSING)+    return UV_EBADF;+  if (!(stream->flags & UV_HANDLE_WRITABLE))+    return UV_EPIPE;++  switch (stream->type) {+    case UV_TCP:+      return uv__tcp_try_write((uv_tcp_t*) stream, bufs, nbufs);+    case UV_TTY:+      return uv__tty_try_write((uv_tty_t*) stream, bufs, nbufs);+    case UV_NAMED_PIPE:+      return UV_EAGAIN;+    default:+      assert(0);+      return UV_ENOSYS;+  }+}+++int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {+  uv_loop_t* loop = handle->loop;++  if (!(handle->flags & UV_HANDLE_WRITABLE)) {+    return UV_EPIPE;+  }++  UV_REQ_INIT(req, UV_SHUTDOWN);+  req->handle = handle;+  req->cb = cb;++  handle->flags &= ~UV_HANDLE_WRITABLE;+  handle->stream.conn.shutdown_req = req;+  handle->reqs_pending++;+  REGISTER_HANDLE_REQ(loop, handle, req);++  uv_want_endgame(loop, (uv_handle_t*)handle);++  return 0;+}+++int uv_is_readable(const uv_stream_t* handle) {+  return !!(handle->flags & UV_HANDLE_READABLE);+}+++int uv_is_writable(const uv_stream_t* handle) {+  return !!(handle->flags & UV_HANDLE_WRITABLE);+}+++int uv_stream_set_blocking(uv_stream_t* handle, int blocking) {+  if (handle->type != UV_NAMED_PIPE)+    return UV_EINVAL;++  if (blocking != 0)+    handle->flags |= UV_HANDLE_BLOCKING_WRITES;+  else+    handle->flags &= ~UV_HANDLE_BLOCKING_WRITES;++  return 0;+}
+ third_party/libuv/src/win/tcp.c view
@@ -0,0 +1,1525 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <stdlib.h>++#include "uv.h"+#include "internal.h"+#include "handle-inl.h"+#include "stream-inl.h"+#include "req-inl.h"+++/*+ * Threshold of active tcp streams for which to preallocate tcp read buffers.+ * (Due to node slab allocator performing poorly under this pattern,+ *  the optimization is temporarily disabled (threshold=0).  This will be+ *  revisited once node allocator is improved.)+ */+const unsigned int uv_active_tcp_streams_threshold = 0;++/*+ * Number of simultaneous pending AcceptEx calls.+ */+const unsigned int uv_simultaneous_server_accepts = 32;++/* A zero-size buffer for use by uv_tcp_read */+static char uv_zero_[] = "";++static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) {+  if (setsockopt(socket,+                 IPPROTO_TCP,+                 TCP_NODELAY,+                 (const char*)&enable,+                 sizeof enable) == -1) {+    return WSAGetLastError();+  }+  return 0;+}+++static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay) {+  if (setsockopt(socket,+                 SOL_SOCKET,+                 SO_KEEPALIVE,+                 (const char*)&enable,+                 sizeof enable) == -1) {+    return WSAGetLastError();+  }++  if (enable && setsockopt(socket,+                           IPPROTO_TCP,+                           TCP_KEEPALIVE,+                           (const char*)&delay,+                           sizeof delay) == -1) {+    return WSAGetLastError();+  }++  return 0;+}+++static int uv_tcp_set_socket(uv_loop_t* loop,+                             uv_tcp_t* handle,+                             SOCKET socket,+                             int family,+                             int imported) {+  DWORD yes = 1;+  int non_ifs_lsp;+  int err;++  if (handle->socket != INVALID_SOCKET)+    return UV_EBUSY;++  /* Set the socket to nonblocking mode */+  if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {+    return WSAGetLastError();+  }++  /* Make the socket non-inheritable */+  if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0))+    return GetLastError();++  /* Associate it with the I/O completion port. Use uv_handle_t pointer as+   * completion key. */+  if (CreateIoCompletionPort((HANDLE)socket,+                             loop->iocp,+                             (ULONG_PTR)socket,+                             0) == NULL) {+    if (imported) {+      handle->flags |= UV_HANDLE_EMULATE_IOCP;+    } else {+      return GetLastError();+    }+  }++  if (family == AF_INET6) {+    non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv6;+  } else {+    non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4;+  }++  if (!(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) {+    UCHAR sfcnm_flags =+        FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;+    if (!SetFileCompletionNotificationModes((HANDLE) socket, sfcnm_flags))+      return GetLastError();+    handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;+  }++  if (handle->flags & UV_HANDLE_TCP_NODELAY) {+    err = uv__tcp_nodelay(handle, socket, 1);+    if (err)+      return err;+  }++  /* TODO: Use stored delay. */+  if (handle->flags & UV_HANDLE_TCP_KEEPALIVE) {+    err = uv__tcp_keepalive(handle, socket, 1, 60);+    if (err)+      return err;+  }++  handle->socket = socket;++  if (family == AF_INET6) {+    handle->flags |= UV_HANDLE_IPV6;+  } else {+    assert(!(handle->flags & UV_HANDLE_IPV6));+  }++  return 0;+}+++int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) {+  int domain;++  /* Use the lower 8 bits for the domain */+  domain = flags & 0xFF;+  if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)+    return UV_EINVAL;++  if (flags & ~0xFF)+    return UV_EINVAL;++  uv_stream_init(loop, (uv_stream_t*) handle, UV_TCP);+  handle->tcp.serv.accept_reqs = NULL;+  handle->tcp.serv.pending_accepts = NULL;+  handle->socket = INVALID_SOCKET;+  handle->reqs_pending = 0;+  handle->tcp.serv.func_acceptex = NULL;+  handle->tcp.conn.func_connectex = NULL;+  handle->tcp.serv.processed_accepts = 0;+  handle->delayed_error = 0;++  /* If anything fails beyond this point we need to remove the handle from+   * the handle queue, since it was added by uv__handle_init in uv_stream_init.+   */++  if (domain != AF_UNSPEC) {+    SOCKET sock;+    DWORD err;++    sock = socket(domain, SOCK_STREAM, 0);+    if (sock == INVALID_SOCKET) {+      err = WSAGetLastError();+      QUEUE_REMOVE(&handle->handle_queue);+      return uv_translate_sys_error(err);+    }++    err = uv_tcp_set_socket(handle->loop, handle, sock, domain, 0);+    if (err) {+      closesocket(sock);+      QUEUE_REMOVE(&handle->handle_queue);+      return uv_translate_sys_error(err);+    }++  }++  return 0;+}+++int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {+  return uv_tcp_init_ex(loop, handle, AF_UNSPEC);+}+++void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {+  int err;+  unsigned int i;+  uv_tcp_accept_t* req;++  if (handle->flags & UV_HANDLE_CONNECTION &&+      handle->stream.conn.shutdown_req != NULL &&+      handle->stream.conn.write_reqs_pending == 0) {++    UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req);++    err = 0;+    if (handle->flags & UV_HANDLE_CLOSING) {+      err = ERROR_OPERATION_ABORTED;+    } else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) {+      err = WSAGetLastError();+    }++    if (handle->stream.conn.shutdown_req->cb) {+      handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req,+                               uv_translate_sys_error(err));+    }++    handle->stream.conn.shutdown_req = NULL;+    DECREASE_PENDING_REQ_COUNT(handle);+    return;+  }++  if (handle->flags & UV_HANDLE_CLOSING &&+      handle->reqs_pending == 0) {+    assert(!(handle->flags & UV_HANDLE_CLOSED));++    if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) {+      closesocket(handle->socket);+      handle->socket = INVALID_SOCKET;+      handle->flags |= UV_HANDLE_TCP_SOCKET_CLOSED;+    }++    if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) {+      if (handle->flags & UV_HANDLE_EMULATE_IOCP) {+        for (i = 0; i < uv_simultaneous_server_accepts; i++) {+          req = &handle->tcp.serv.accept_reqs[i];+          if (req->wait_handle != INVALID_HANDLE_VALUE) {+            UnregisterWait(req->wait_handle);+            req->wait_handle = INVALID_HANDLE_VALUE;+          }+          if (req->event_handle) {+            CloseHandle(req->event_handle);+            req->event_handle = NULL;+          }+        }+      }++      uv__free(handle->tcp.serv.accept_reqs);+      handle->tcp.serv.accept_reqs = NULL;+    }++    if (handle->flags & UV_HANDLE_CONNECTION &&+        handle->flags & UV_HANDLE_EMULATE_IOCP) {+      if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {+        UnregisterWait(handle->read_req.wait_handle);+        handle->read_req.wait_handle = INVALID_HANDLE_VALUE;+      }+      if (handle->read_req.event_handle) {+        CloseHandle(handle->read_req.event_handle);+        handle->read_req.event_handle = NULL;+      }+    }++    uv__handle_close(handle);+    loop->active_tcp_streams--;+  }+}+++/* Unlike on Unix, here we don't set SO_REUSEADDR, because it doesn't just+ * allow binding to addresses that are in use by sockets in TIME_WAIT, it+ * effectively allows 'stealing' a port which is in use by another application.+ *+ * SO_EXCLUSIVEADDRUSE is also not good here because it does check all sockets,+ * regardless of state, so we'd get an error even if the port is in use by a+ * socket in TIME_WAIT state.+ *+ * See issue #1360.+ *+ */+static int uv_tcp_try_bind(uv_tcp_t* handle,+                           const struct sockaddr* addr,+                           unsigned int addrlen,+                           unsigned int flags) {+  DWORD err;+  int r;++  if (handle->socket == INVALID_SOCKET) {+    SOCKET sock;++    /* Cannot set IPv6-only mode on non-IPv6 socket. */+    if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)+      return ERROR_INVALID_PARAMETER;++    sock = socket(addr->sa_family, SOCK_STREAM, 0);+    if (sock == INVALID_SOCKET) {+      return WSAGetLastError();+    }++    err = uv_tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0);+    if (err) {+      closesocket(sock);+      return err;+    }+  }++#ifdef IPV6_V6ONLY+  if (addr->sa_family == AF_INET6) {+    int on;++    on = (flags & UV_TCP_IPV6ONLY) != 0;++    /* TODO: how to handle errors? This may fail if there is no ipv4 stack+     * available, or when run on XP/2003 which have no support for dualstack+     * sockets. For now we're silently ignoring the error. */+    setsockopt(handle->socket,+               IPPROTO_IPV6,+               IPV6_V6ONLY,+               (const char*)&on,+               sizeof on);+  }+#endif++  r = bind(handle->socket, addr, addrlen);++  if (r == SOCKET_ERROR) {+    err = WSAGetLastError();+    if (err == WSAEADDRINUSE) {+      /* Some errors are not to be reported until connect() or listen() */+      handle->delayed_error = err;+    } else {+      return err;+    }+  }++  handle->flags |= UV_HANDLE_BOUND;++  return 0;+}+++static void CALLBACK post_completion(void* context, BOOLEAN timed_out) {+  uv_req_t* req;+  uv_tcp_t* handle;++  req = (uv_req_t*) context;+  assert(req != NULL);+  handle = (uv_tcp_t*)req->data;+  assert(handle != NULL);+  assert(!timed_out);++  if (!PostQueuedCompletionStatus(handle->loop->iocp,+                                  req->u.io.overlapped.InternalHigh,+                                  0,+                                  &req->u.io.overlapped)) {+    uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");+  }+}+++static void CALLBACK post_write_completion(void* context, BOOLEAN timed_out) {+  uv_write_t* req;+  uv_tcp_t* handle;++  req = (uv_write_t*) context;+  assert(req != NULL);+  handle = (uv_tcp_t*)req->handle;+  assert(handle != NULL);+  assert(!timed_out);++  if (!PostQueuedCompletionStatus(handle->loop->iocp,+                                  req->u.io.overlapped.InternalHigh,+                                  0,+                                  &req->u.io.overlapped)) {+    uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");+  }+}+++void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {+  uv_loop_t* loop = handle->loop;+  BOOL success;+  DWORD bytes;+  SOCKET accept_socket;+  short family;++  assert(handle->flags & UV_HANDLE_LISTENING);+  assert(req->accept_socket == INVALID_SOCKET);++  /* choose family and extension function */+  if (handle->flags & UV_HANDLE_IPV6) {+    family = AF_INET6;+  } else {+    family = AF_INET;+  }++  /* Open a socket for the accepted connection. */+  accept_socket = socket(family, SOCK_STREAM, 0);+  if (accept_socket == INVALID_SOCKET) {+    SET_REQ_ERROR(req, WSAGetLastError());+    uv_insert_pending_req(loop, (uv_req_t*)req);+    handle->reqs_pending++;+    return;+  }++  /* Make the socket non-inheritable */+  if (!SetHandleInformation((HANDLE) accept_socket, HANDLE_FLAG_INHERIT, 0)) {+    SET_REQ_ERROR(req, GetLastError());+    uv_insert_pending_req(loop, (uv_req_t*)req);+    handle->reqs_pending++;+    closesocket(accept_socket);+    return;+  }++  /* Prepare the overlapped structure. */+  memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));+  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {+    req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);+  }++  success = handle->tcp.serv.func_acceptex(handle->socket,+                                          accept_socket,+                                          (void*)req->accept_buffer,+                                          0,+                                          sizeof(struct sockaddr_storage),+                                          sizeof(struct sockaddr_storage),+                                          &bytes,+                                          &req->u.io.overlapped);++  if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {+    /* Process the req without IOCP. */+    req->accept_socket = accept_socket;+    handle->reqs_pending++;+    uv_insert_pending_req(loop, (uv_req_t*)req);+  } else if (UV_SUCCEEDED_WITH_IOCP(success)) {+    /* The req will be processed with IOCP. */+    req->accept_socket = accept_socket;+    handle->reqs_pending++;+    if (handle->flags & UV_HANDLE_EMULATE_IOCP &&+        req->wait_handle == INVALID_HANDLE_VALUE &&+        !RegisterWaitForSingleObject(&req->wait_handle,+          req->event_handle, post_completion, (void*) req,+          INFINITE, WT_EXECUTEINWAITTHREAD)) {+      SET_REQ_ERROR(req, GetLastError());+      uv_insert_pending_req(loop, (uv_req_t*)req);+    }+  } else {+    /* Make this req pending reporting an error. */+    SET_REQ_ERROR(req, WSAGetLastError());+    uv_insert_pending_req(loop, (uv_req_t*)req);+    handle->reqs_pending++;+    /* Destroy the preallocated client socket. */+    closesocket(accept_socket);+    /* Destroy the event handle */+    if (handle->flags & UV_HANDLE_EMULATE_IOCP) {+      CloseHandle(req->u.io.overlapped.hEvent);+      req->event_handle = NULL;+    }+  }+}+++static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {+  uv_read_t* req;+  uv_buf_t buf;+  int result;+  DWORD bytes, flags;++  assert(handle->flags & UV_HANDLE_READING);+  assert(!(handle->flags & UV_HANDLE_READ_PENDING));++  req = &handle->read_req;+  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));++  /*+   * Preallocate a read buffer if the number of active streams is below+   * the threshold.+  */+  if (loop->active_tcp_streams < uv_active_tcp_streams_threshold) {+    handle->flags &= ~UV_HANDLE_ZERO_READ;+    handle->tcp.conn.read_buffer = uv_buf_init(NULL, 0);+    handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->tcp.conn.read_buffer);+    if (handle->tcp.conn.read_buffer.base == NULL ||+        handle->tcp.conn.read_buffer.len == 0) {+      handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &handle->tcp.conn.read_buffer);+      return;+    }+    assert(handle->tcp.conn.read_buffer.base != NULL);+    buf = handle->tcp.conn.read_buffer;+  } else {+    handle->flags |= UV_HANDLE_ZERO_READ;+    buf.base = (char*) &uv_zero_;+    buf.len = 0;+  }++  /* Prepare the overlapped structure. */+  memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));+  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {+    assert(req->event_handle);+    req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);+  }++  flags = 0;+  result = WSARecv(handle->socket,+                   (WSABUF*)&buf,+                   1,+                   &bytes,+                   &flags,+                   &req->u.io.overlapped,+                   NULL);++  if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {+    /* Process the req without IOCP. */+    handle->flags |= UV_HANDLE_READ_PENDING;+    req->u.io.overlapped.InternalHigh = bytes;+    handle->reqs_pending++;+    uv_insert_pending_req(loop, (uv_req_t*)req);+  } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {+    /* The req will be processed with IOCP. */+    handle->flags |= UV_HANDLE_READ_PENDING;+    handle->reqs_pending++;+    if (handle->flags & UV_HANDLE_EMULATE_IOCP &&+        req->wait_handle == INVALID_HANDLE_VALUE &&+        !RegisterWaitForSingleObject(&req->wait_handle,+          req->event_handle, post_completion, (void*) req,+          INFINITE, WT_EXECUTEINWAITTHREAD)) {+      SET_REQ_ERROR(req, GetLastError());+      uv_insert_pending_req(loop, (uv_req_t*)req);+    }+  } else {+    /* Make this req pending reporting an error. */+    SET_REQ_ERROR(req, WSAGetLastError());+    uv_insert_pending_req(loop, (uv_req_t*)req);+    handle->reqs_pending++;+  }+}+++int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {+  unsigned int i, simultaneous_accepts;+  uv_tcp_accept_t* req;+  int err;++  assert(backlog > 0);++  if (handle->flags & UV_HANDLE_LISTENING) {+    handle->stream.serv.connection_cb = cb;+  }++  if (handle->flags & UV_HANDLE_READING) {+    return WSAEISCONN;+  }++  if (handle->delayed_error) {+    return handle->delayed_error;+  }++  if (!(handle->flags & UV_HANDLE_BOUND)) {+    err = uv_tcp_try_bind(handle,+                          (const struct sockaddr*) &uv_addr_ip4_any_,+                          sizeof(uv_addr_ip4_any_),+                          0);+    if (err)+      return err;+    if (handle->delayed_error)+      return handle->delayed_error;+  }++  if (!handle->tcp.serv.func_acceptex) {+    if (!uv_get_acceptex_function(handle->socket, &handle->tcp.serv.func_acceptex)) {+      return WSAEAFNOSUPPORT;+    }+  }++  if (!(handle->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&+      listen(handle->socket, backlog) == SOCKET_ERROR) {+    return WSAGetLastError();+  }++  handle->flags |= UV_HANDLE_LISTENING;+  handle->stream.serv.connection_cb = cb;+  INCREASE_ACTIVE_COUNT(loop, handle);++  simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1+    : uv_simultaneous_server_accepts;++  if(!handle->tcp.serv.accept_reqs) {+    handle->tcp.serv.accept_reqs = (uv_tcp_accept_t*)+      uv__malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t));+    if (!handle->tcp.serv.accept_reqs) {+      uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+    }++    for (i = 0; i < simultaneous_accepts; i++) {+      req = &handle->tcp.serv.accept_reqs[i];+      UV_REQ_INIT(req, UV_ACCEPT);+      req->accept_socket = INVALID_SOCKET;+      req->data = handle;++      req->wait_handle = INVALID_HANDLE_VALUE;+      if (handle->flags & UV_HANDLE_EMULATE_IOCP) {+        req->event_handle = CreateEvent(NULL, 0, 0, NULL);+        if (!req->event_handle) {+          uv_fatal_error(GetLastError(), "CreateEvent");+        }+      } else {+        req->event_handle = NULL;+      }++      uv_tcp_queue_accept(handle, req);+    }++    /* Initialize other unused requests too, because uv_tcp_endgame doesn't+     * know how many requests were initialized, so it will try to clean up+     * {uv_simultaneous_server_accepts} requests. */+    for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) {+      req = &handle->tcp.serv.accept_reqs[i];+      UV_REQ_INIT(req, UV_ACCEPT);+      req->accept_socket = INVALID_SOCKET;+      req->data = handle;+      req->wait_handle = INVALID_HANDLE_VALUE;+      req->event_handle = NULL;+    }+  }++  return 0;+}+++int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {+  uv_loop_t* loop = server->loop;+  int err = 0;+  int family;++  uv_tcp_accept_t* req = server->tcp.serv.pending_accepts;++  if (!req) {+    /* No valid connections found, so we error out. */+    return WSAEWOULDBLOCK;+  }++  if (req->accept_socket == INVALID_SOCKET) {+    return WSAENOTCONN;+  }++  if (server->flags & UV_HANDLE_IPV6) {+    family = AF_INET6;+  } else {+    family = AF_INET;+  }++  err = uv_tcp_set_socket(client->loop,+                          client,+                          req->accept_socket,+                          family,+                          0);+  if (err) {+    closesocket(req->accept_socket);+  } else {+    uv_connection_init((uv_stream_t*) client);+    /* AcceptEx() implicitly binds the accepted socket. */+    client->flags |= UV_HANDLE_BOUND | UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;+  }++  /* Prepare the req to pick up a new connection */+  server->tcp.serv.pending_accepts = req->next_pending;+  req->next_pending = NULL;+  req->accept_socket = INVALID_SOCKET;++  if (!(server->flags & UV_HANDLE_CLOSING)) {+    /* Check if we're in a middle of changing the number of pending accepts. */+    if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) {+      uv_tcp_queue_accept(server, req);+    } else {+      /* We better be switching to a single pending accept. */+      assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT);++      server->tcp.serv.processed_accepts++;++      if (server->tcp.serv.processed_accepts >= uv_simultaneous_server_accepts) {+        server->tcp.serv.processed_accepts = 0;+        /*+         * All previously queued accept requests are now processed.+         * We now switch to queueing just a single accept.+         */+        uv_tcp_queue_accept(server, &server->tcp.serv.accept_reqs[0]);+        server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING;+        server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;+      }+    }+  }++  loop->active_tcp_streams++;++  return err;+}+++int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,+    uv_read_cb read_cb) {+  uv_loop_t* loop = handle->loop;++  handle->flags |= UV_HANDLE_READING;+  handle->read_cb = read_cb;+  handle->alloc_cb = alloc_cb;+  INCREASE_ACTIVE_COUNT(loop, handle);++  /* If reading was stopped and then started again, there could still be a read+   * request pending. */+  if (!(handle->flags & UV_HANDLE_READ_PENDING)) {+    if (handle->flags & UV_HANDLE_EMULATE_IOCP &&+        !handle->read_req.event_handle) {+      handle->read_req.event_handle = CreateEvent(NULL, 0, 0, NULL);+      if (!handle->read_req.event_handle) {+        uv_fatal_error(GetLastError(), "CreateEvent");+      }+    }+    uv_tcp_queue_read(loop, handle);+  }++  return 0;+}+++static int uv_tcp_try_connect(uv_connect_t* req,+                              uv_tcp_t* handle,+                              const struct sockaddr* addr,+                              unsigned int addrlen,+                              uv_connect_cb cb) {+  uv_loop_t* loop = handle->loop;+  const struct sockaddr* bind_addr;+  struct sockaddr_storage converted;+  BOOL success;+  DWORD bytes;+  int err;++  err = uv__convert_to_localhost_if_unspecified(addr, &converted);+  if (err)+    return err;++  if (handle->delayed_error) {+    return handle->delayed_error;+  }++  if (!(handle->flags & UV_HANDLE_BOUND)) {+    if (addrlen == sizeof(uv_addr_ip4_any_)) {+      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;+    } else if (addrlen == sizeof(uv_addr_ip6_any_)) {+      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;+    } else {+      abort();+    }+    err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0);+    if (err)+      return err;+    if (handle->delayed_error)+      return handle->delayed_error;+  }++  if (!handle->tcp.conn.func_connectex) {+    if (!uv_get_connectex_function(handle->socket, &handle->tcp.conn.func_connectex)) {+      return WSAEAFNOSUPPORT;+    }+  }++  UV_REQ_INIT(req, UV_CONNECT);+  req->handle = (uv_stream_t*) handle;+  req->cb = cb;+  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));++  success = handle->tcp.conn.func_connectex(handle->socket,+                                            (const struct sockaddr*) &converted,+                                            addrlen,+                                            NULL,+                                            0,+                                            &bytes,+                                            &req->u.io.overlapped);++  if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {+    /* Process the req without IOCP. */+    handle->reqs_pending++;+    REGISTER_HANDLE_REQ(loop, handle, req);+    uv_insert_pending_req(loop, (uv_req_t*)req);+  } else if (UV_SUCCEEDED_WITH_IOCP(success)) {+    /* The req will be processed with IOCP. */+    handle->reqs_pending++;+    REGISTER_HANDLE_REQ(loop, handle, req);+  } else {+    return WSAGetLastError();+  }++  return 0;+}+++int uv_tcp_getsockname(const uv_tcp_t* handle,+                       struct sockaddr* name,+                       int* namelen) {+  int result;++  if (handle->socket == INVALID_SOCKET) {+    return UV_EINVAL;+  }++  if (handle->delayed_error) {+    return uv_translate_sys_error(handle->delayed_error);+  }++  result = getsockname(handle->socket, name, namelen);+  if (result != 0) {+    return uv_translate_sys_error(WSAGetLastError());+  }++  return 0;+}+++int uv_tcp_getpeername(const uv_tcp_t* handle,+                       struct sockaddr* name,+                       int* namelen) {+  int result;++  if (handle->socket == INVALID_SOCKET) {+    return UV_EINVAL;+  }++  if (handle->delayed_error) {+    return uv_translate_sys_error(handle->delayed_error);+  }++  result = getpeername(handle->socket, name, namelen);+  if (result != 0) {+    return uv_translate_sys_error(WSAGetLastError());+  }++  return 0;+}+++int uv_tcp_write(uv_loop_t* loop,+                 uv_write_t* req,+                 uv_tcp_t* handle,+                 const uv_buf_t bufs[],+                 unsigned int nbufs,+                 uv_write_cb cb) {+  int result;+  DWORD bytes;++  UV_REQ_INIT(req, UV_WRITE);+  req->handle = (uv_stream_t*) handle;+  req->cb = cb;++  /* Prepare the overlapped structure. */+  memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));+  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {+    req->event_handle = CreateEvent(NULL, 0, 0, NULL);+    if (!req->event_handle) {+      uv_fatal_error(GetLastError(), "CreateEvent");+    }+    req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);+    req->wait_handle = INVALID_HANDLE_VALUE;+  }++  result = WSASend(handle->socket,+                   (WSABUF*) bufs,+                   nbufs,+                   &bytes,+                   0,+                   &req->u.io.overlapped,+                   NULL);++  if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {+    /* Request completed immediately. */+    req->u.io.queued_bytes = 0;+    handle->reqs_pending++;+    handle->stream.conn.write_reqs_pending++;+    REGISTER_HANDLE_REQ(loop, handle, req);+    uv_insert_pending_req(loop, (uv_req_t*) req);+  } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {+    /* Request queued by the kernel. */+    req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs);+    handle->reqs_pending++;+    handle->stream.conn.write_reqs_pending++;+    REGISTER_HANDLE_REQ(loop, handle, req);+    handle->write_queue_size += req->u.io.queued_bytes;+    if (handle->flags & UV_HANDLE_EMULATE_IOCP &&+        !RegisterWaitForSingleObject(&req->wait_handle,+          req->event_handle, post_write_completion, (void*) req,+          INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) {+      SET_REQ_ERROR(req, GetLastError());+      uv_insert_pending_req(loop, (uv_req_t*)req);+    }+  } else {+    /* Send failed due to an error, report it later */+    req->u.io.queued_bytes = 0;+    handle->reqs_pending++;+    handle->stream.conn.write_reqs_pending++;+    REGISTER_HANDLE_REQ(loop, handle, req);+    SET_REQ_ERROR(req, WSAGetLastError());+    uv_insert_pending_req(loop, (uv_req_t*) req);+  }++  return 0;+}+++int uv__tcp_try_write(uv_tcp_t* handle,+                     const uv_buf_t bufs[],+                     unsigned int nbufs) {+  int result;+  DWORD bytes;++  if (handle->stream.conn.write_reqs_pending > 0)+    return UV_EAGAIN;++  result = WSASend(handle->socket,+                   (WSABUF*) bufs,+                   nbufs,+                   &bytes,+                   0,+                   NULL,+                   NULL);++  if (result == SOCKET_ERROR)+    return uv_translate_sys_error(WSAGetLastError());+  else+    return bytes;+}+++void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,+    uv_req_t* req) {+  DWORD bytes, flags, err;+  uv_buf_t buf;+  int count;++  assert(handle->type == UV_TCP);++  handle->flags &= ~UV_HANDLE_READ_PENDING;++  if (!REQ_SUCCESS(req)) {+    /* An error occurred doing the read. */+    if ((handle->flags & UV_HANDLE_READING) ||+        !(handle->flags & UV_HANDLE_ZERO_READ)) {+      handle->flags &= ~UV_HANDLE_READING;+      DECREASE_ACTIVE_COUNT(loop, handle);+      buf = (handle->flags & UV_HANDLE_ZERO_READ) ?+            uv_buf_init(NULL, 0) : handle->tcp.conn.read_buffer;++      err = GET_REQ_SOCK_ERROR(req);++      if (err == WSAECONNABORTED) {+        /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix.+         */+        err = WSAECONNRESET;+      }++      handle->read_cb((uv_stream_t*)handle,+                      uv_translate_sys_error(err),+                      &buf);+    }+  } else {+    if (!(handle->flags & UV_HANDLE_ZERO_READ)) {+      /* The read was done with a non-zero buffer length. */+      if (req->u.io.overlapped.InternalHigh > 0) {+        /* Successful read */+        handle->read_cb((uv_stream_t*)handle,+                        req->u.io.overlapped.InternalHigh,+                        &handle->tcp.conn.read_buffer);+        /* Read again only if bytes == buf.len */+        if (req->u.io.overlapped.InternalHigh < handle->tcp.conn.read_buffer.len) {+          goto done;+        }+      } else {+        /* Connection closed */+        if (handle->flags & UV_HANDLE_READING) {+          handle->flags &= ~UV_HANDLE_READING;+          DECREASE_ACTIVE_COUNT(loop, handle);+        }+        handle->flags &= ~UV_HANDLE_READABLE;++        buf.base = 0;+        buf.len = 0;+        handle->read_cb((uv_stream_t*)handle, UV_EOF, &handle->tcp.conn.read_buffer);+        goto done;+      }+    }++    /* Do nonblocking reads until the buffer is empty */+    count = 32;+    while ((handle->flags & UV_HANDLE_READING) && (count-- > 0)) {+      buf = uv_buf_init(NULL, 0);+      handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);+      if (buf.base == NULL || buf.len == 0) {+        handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf);+        break;+      }+      assert(buf.base != NULL);++      flags = 0;+      if (WSARecv(handle->socket,+                  (WSABUF*)&buf,+                  1,+                  &bytes,+                  &flags,+                  NULL,+                  NULL) != SOCKET_ERROR) {+        if (bytes > 0) {+          /* Successful read */+          handle->read_cb((uv_stream_t*)handle, bytes, &buf);+          /* Read again only if bytes == buf.len */+          if (bytes < buf.len) {+            break;+          }+        } else {+          /* Connection closed */+          handle->flags &= ~(UV_HANDLE_READING | UV_HANDLE_READABLE);+          DECREASE_ACTIVE_COUNT(loop, handle);++          handle->read_cb((uv_stream_t*)handle, UV_EOF, &buf);+          break;+        }+      } else {+        err = WSAGetLastError();+        if (err == WSAEWOULDBLOCK) {+          /* Read buffer was completely empty, report a 0-byte read. */+          handle->read_cb((uv_stream_t*)handle, 0, &buf);+        } else {+          /* Ouch! serious error. */+          handle->flags &= ~UV_HANDLE_READING;+          DECREASE_ACTIVE_COUNT(loop, handle);++          if (err == WSAECONNABORTED) {+            /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with+             * Unix. */+            err = WSAECONNRESET;+          }++          handle->read_cb((uv_stream_t*)handle,+                          uv_translate_sys_error(err),+                          &buf);+        }+        break;+      }+    }++done:+    /* Post another read if still reading and not closing. */+    if ((handle->flags & UV_HANDLE_READING) &&+        !(handle->flags & UV_HANDLE_READ_PENDING)) {+      uv_tcp_queue_read(loop, handle);+    }+  }++  DECREASE_PENDING_REQ_COUNT(handle);+}+++void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,+    uv_write_t* req) {+  int err;++  assert(handle->type == UV_TCP);++  assert(handle->write_queue_size >= req->u.io.queued_bytes);+  handle->write_queue_size -= req->u.io.queued_bytes;++  UNREGISTER_HANDLE_REQ(loop, handle, req);++  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {+    if (req->wait_handle != INVALID_HANDLE_VALUE) {+      UnregisterWait(req->wait_handle);+      req->wait_handle = INVALID_HANDLE_VALUE;+    }+    if (req->event_handle) {+      CloseHandle(req->event_handle);+      req->event_handle = NULL;+    }+  }++  if (req->cb) {+    err = uv_translate_sys_error(GET_REQ_SOCK_ERROR(req));+    if (err == UV_ECONNABORTED) {+      /* use UV_ECANCELED for consistency with Unix */+      err = UV_ECANCELED;+    }+    req->cb(req, err);+  }++  handle->stream.conn.write_reqs_pending--;+  if (handle->stream.conn.shutdown_req != NULL &&+      handle->stream.conn.write_reqs_pending == 0) {+    uv_want_endgame(loop, (uv_handle_t*)handle);+  }++  DECREASE_PENDING_REQ_COUNT(handle);+}+++void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,+    uv_req_t* raw_req) {+  uv_tcp_accept_t* req = (uv_tcp_accept_t*) raw_req;+  int err;++  assert(handle->type == UV_TCP);++  /* If handle->accepted_socket is not a valid socket, then uv_queue_accept+   * must have failed. This is a serious error. We stop accepting connections+   * and report this error to the connection callback. */+  if (req->accept_socket == INVALID_SOCKET) {+    if (handle->flags & UV_HANDLE_LISTENING) {+      handle->flags &= ~UV_HANDLE_LISTENING;+      DECREASE_ACTIVE_COUNT(loop, handle);+      if (handle->stream.serv.connection_cb) {+        err = GET_REQ_SOCK_ERROR(req);+        handle->stream.serv.connection_cb((uv_stream_t*)handle,+                                      uv_translate_sys_error(err));+      }+    }+  } else if (REQ_SUCCESS(req) &&+      setsockopt(req->accept_socket,+                  SOL_SOCKET,+                  SO_UPDATE_ACCEPT_CONTEXT,+                  (char*)&handle->socket,+                  sizeof(handle->socket)) == 0) {+    req->next_pending = handle->tcp.serv.pending_accepts;+    handle->tcp.serv.pending_accepts = req;++    /* Accept and SO_UPDATE_ACCEPT_CONTEXT were successful. */+    if (handle->stream.serv.connection_cb) {+      handle->stream.serv.connection_cb((uv_stream_t*)handle, 0);+    }+  } else {+    /* Error related to accepted socket is ignored because the server socket+     * may still be healthy. If the server socket is broken uv_queue_accept+     * will detect it. */+    closesocket(req->accept_socket);+    req->accept_socket = INVALID_SOCKET;+    if (handle->flags & UV_HANDLE_LISTENING) {+      uv_tcp_queue_accept(handle, req);+    }+  }++  DECREASE_PENDING_REQ_COUNT(handle);+}+++void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,+    uv_connect_t* req) {+  int err;++  assert(handle->type == UV_TCP);++  UNREGISTER_HANDLE_REQ(loop, handle, req);++  err = 0;+  if (REQ_SUCCESS(req)) {+    if (handle->flags & UV_HANDLE_CLOSING) {+      /* use UV_ECANCELED for consistency with Unix */+      err = ERROR_OPERATION_ABORTED;+    } else if (setsockopt(handle->socket,+                          SOL_SOCKET,+                          SO_UPDATE_CONNECT_CONTEXT,+                          NULL,+                          0) == 0) {+      uv_connection_init((uv_stream_t*)handle);+      handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;+      loop->active_tcp_streams++;+    } else {+      err = WSAGetLastError();+    }+  } else {+    err = GET_REQ_SOCK_ERROR(req);+  }+  req->cb(req, uv_translate_sys_error(err));++  DECREASE_PENDING_REQ_COUNT(handle);+}+++int uv__tcp_xfer_export(uv_tcp_t* handle,+                        int target_pid,+                        uv__ipc_socket_xfer_type_t* xfer_type,+                        uv__ipc_socket_xfer_info_t* xfer_info) {+  if (handle->flags & UV_HANDLE_CONNECTION) {+    *xfer_type = UV__IPC_SOCKET_XFER_TCP_CONNECTION;+  } else {+    *xfer_type = UV__IPC_SOCKET_XFER_TCP_SERVER;+    /* We're about to share the socket with another process. Because this is a+     * listening socket, we assume that the other process will be accepting+     * connections on it. Thus, before sharing the socket with another process,+     * we call listen here in the parent process. */+    if (!(handle->flags & UV_HANDLE_LISTENING)) {+      if (!(handle->flags & UV_HANDLE_BOUND)) {+        return ERROR_NOT_SUPPORTED;+      }+      if (handle->delayed_error == 0 &&+          listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {+        handle->delayed_error = WSAGetLastError();+      }+    }+  }++  if (WSADuplicateSocketW(handle->socket, target_pid, &xfer_info->socket_info))+    return WSAGetLastError();+  xfer_info->delayed_error = handle->delayed_error;++  /* Mark the local copy of the handle as 'shared' so we behave in a way that's+   * friendly to the process(es) that we share the socket with. */+  handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET;++  return 0;+}+++int uv__tcp_xfer_import(uv_tcp_t* tcp,+                        uv__ipc_socket_xfer_type_t xfer_type,+                        uv__ipc_socket_xfer_info_t* xfer_info) {+  int err;+  SOCKET socket;++  assert(xfer_type == UV__IPC_SOCKET_XFER_TCP_SERVER ||+         xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION);++  socket = WSASocketW(FROM_PROTOCOL_INFO,+                      FROM_PROTOCOL_INFO,+                      FROM_PROTOCOL_INFO,+                      &xfer_info->socket_info,+                      0,+                      WSA_FLAG_OVERLAPPED);++  if (socket == INVALID_SOCKET) {+    return WSAGetLastError();+  }++  err = uv_tcp_set_socket(+      tcp->loop, tcp, socket, xfer_info->socket_info.iAddressFamily, 1);+  if (err) {+    closesocket(socket);+    return err;+  }++  tcp->delayed_error = xfer_info->delayed_error;+  tcp->flags |= UV_HANDLE_BOUND | UV_HANDLE_SHARED_TCP_SOCKET;++  if (xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION) {+    uv_connection_init((uv_stream_t*)tcp);+    tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;+  }++  tcp->loop->active_tcp_streams++;+  return 0;+}+++int uv_tcp_nodelay(uv_tcp_t* handle, int enable) {+  int err;++  if (handle->socket != INVALID_SOCKET) {+    err = uv__tcp_nodelay(handle, handle->socket, enable);+    if (err)+      return err;+  }++  if (enable) {+    handle->flags |= UV_HANDLE_TCP_NODELAY;+  } else {+    handle->flags &= ~UV_HANDLE_TCP_NODELAY;+  }++  return 0;+}+++int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {+  int err;++  if (handle->socket != INVALID_SOCKET) {+    err = uv__tcp_keepalive(handle, handle->socket, enable, delay);+    if (err)+      return err;+  }++  if (enable) {+    handle->flags |= UV_HANDLE_TCP_KEEPALIVE;+  } else {+    handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;+  }++  /* TODO: Store delay if handle->socket isn't created yet. */++  return 0;+}+++int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {+  if (handle->flags & UV_HANDLE_CONNECTION) {+    return UV_EINVAL;+  }++  /* Check if we're already in the desired mode. */+  if ((enable && !(handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) ||+      (!enable && handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) {+    return 0;+  }++  /* Don't allow switching from single pending accept to many. */+  if (enable) {+    return UV_ENOTSUP;+  }++  /* Check if we're in a middle of changing the number of pending accepts. */+  if (handle->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING) {+    return 0;+  }++  handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;++  /* Flip the changing flag if we have already queued multiple accepts. */+  if (handle->flags & UV_HANDLE_LISTENING) {+    handle->flags |= UV_HANDLE_TCP_ACCEPT_STATE_CHANGING;+  }++  return 0;+}+++static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) {+  SOCKET socket = tcp->socket;+  int non_ifs_lsp;++  /* Check if we have any non-IFS LSPs stacked on top of TCP */+  non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :+                                                uv_tcp_non_ifs_lsp_ipv4;++  /* If there are non-ifs LSPs then try to obtain a base handle for the socket.+   * This will always fail on Windows XP/3k. */+  if (non_ifs_lsp) {+    DWORD bytes;+    if (WSAIoctl(socket,+                 SIO_BASE_HANDLE,+                 NULL,+                 0,+                 &socket,+                 sizeof socket,+                 &bytes,+                 NULL,+                 NULL) != 0) {+      /* Failed. We can't do CancelIo. */+      return -1;+    }+  }++  assert(socket != 0 && socket != INVALID_SOCKET);++  if (!CancelIo((HANDLE) socket)) {+    return GetLastError();+  }++  /* It worked. */+  return 0;+}+++void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {+  int close_socket = 1;++  if (tcp->flags & UV_HANDLE_READ_PENDING) {+    /* In order for winsock to do a graceful close there must not be any any+     * pending reads, or the socket must be shut down for writing */+    if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) {+      /* Just do shutdown on non-shared sockets, which ensures graceful close. */+      shutdown(tcp->socket, SD_SEND);++    } else if (uv_tcp_try_cancel_io(tcp) == 0) {+      /* In case of a shared socket, we try to cancel all outstanding I/O,. If+       * that works, don't close the socket yet - wait for the read req to+       * return and close the socket in uv_tcp_endgame. */+      close_socket = 0;++    } else {+      /* When cancelling isn't possible - which could happen when an LSP is+       * present on an old Windows version, we will have to close the socket+       * with a read pending. That is not nice because trailing sent bytes may+       * not make it to the other side. */+    }++  } else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&+             tcp->tcp.serv.accept_reqs != NULL) {+    /* Under normal circumstances closesocket() will ensure that all pending+     * accept reqs are canceled. However, when the socket is shared the+     * presence of another reference to the socket in another process will keep+     * the accept reqs going, so we have to ensure that these are canceled. */+    if (uv_tcp_try_cancel_io(tcp) != 0) {+      /* When cancellation is not possible, there is another option: we can+       * close the incoming sockets, which will also cancel the accept+       * operations. However this is not cool because we might inadvertently+       * close a socket that just accepted a new connection, which will cause+       * the connection to be aborted. */+      unsigned int i;+      for (i = 0; i < uv_simultaneous_server_accepts; i++) {+        uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i];+        if (req->accept_socket != INVALID_SOCKET &&+            !HasOverlappedIoCompleted(&req->u.io.overlapped)) {+          closesocket(req->accept_socket);+          req->accept_socket = INVALID_SOCKET;+        }+      }+    }+  }++  if (tcp->flags & UV_HANDLE_READING) {+    tcp->flags &= ~UV_HANDLE_READING;+    DECREASE_ACTIVE_COUNT(loop, tcp);+  }++  if (tcp->flags & UV_HANDLE_LISTENING) {+    tcp->flags &= ~UV_HANDLE_LISTENING;+    DECREASE_ACTIVE_COUNT(loop, tcp);+  }++  if (close_socket) {+    closesocket(tcp->socket);+    tcp->socket = INVALID_SOCKET;+    tcp->flags |= UV_HANDLE_TCP_SOCKET_CLOSED;+  }++  tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);+  uv__handle_closing(tcp);++  if (tcp->reqs_pending == 0) {+    uv_want_endgame(tcp->loop, (uv_handle_t*)tcp);+  }+}+++int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {+  WSAPROTOCOL_INFOW protocol_info;+  int opt_len;+  int err;+  struct sockaddr_storage saddr;+  int saddr_len;++  /* Detect the address family of the socket. */+  opt_len = (int) sizeof protocol_info;+  if (getsockopt(sock,+                 SOL_SOCKET,+                 SO_PROTOCOL_INFOW,+                 (char*) &protocol_info,+                 &opt_len) == SOCKET_ERROR) {+    return uv_translate_sys_error(GetLastError());+  }++  err = uv_tcp_set_socket(handle->loop,+                          handle,+                          sock,+                          protocol_info.iAddressFamily,+                          1);+  if (err) {+    return uv_translate_sys_error(err);+  }++  /* Support already active socket. */+  saddr_len = sizeof(saddr);+  if (!uv_tcp_getsockname(handle, (struct sockaddr*) &saddr, &saddr_len)) {+    /* Socket is already bound. */+    handle->flags |= UV_HANDLE_BOUND;+    saddr_len = sizeof(saddr);+    if (!uv_tcp_getpeername(handle, (struct sockaddr*) &saddr, &saddr_len)) {+      /* Socket is already connected. */+      uv_connection_init((uv_stream_t*) handle);+      handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;+    }+  }++  return 0;+}+++/* This function is an egress point, i.e. it returns libuv errors rather than+ * system errors.+ */+int uv__tcp_bind(uv_tcp_t* handle,+                 const struct sockaddr* addr,+                 unsigned int addrlen,+                 unsigned int flags) {+  int err;++  err = uv_tcp_try_bind(handle, addr, addrlen, flags);+  if (err)+    return uv_translate_sys_error(err);++  return 0;+}+++/* This function is an egress point, i.e. it returns libuv errors rather than+ * system errors.+ */+int uv__tcp_connect(uv_connect_t* req,+                    uv_tcp_t* handle,+                    const struct sockaddr* addr,+                    unsigned int addrlen,+                    uv_connect_cb cb) {+  int err;++  err = uv_tcp_try_connect(req, handle, addr, addrlen, cb);+  if (err)+    return uv_translate_sys_error(err);++  return 0;+}
+ third_party/libuv/src/win/thread.c view
@@ -0,0 +1,520 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <limits.h>+#include <stdlib.h>++#if defined(__MINGW64_VERSION_MAJOR)+/* MemoryBarrier expands to __mm_mfence in some cases (x86+sse2), which may+ * require this header in some versions of mingw64. */+#include <intrin.h>+#endif++#include "uv.h"+#include "internal.h"++static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {+  DWORD result;+  HANDLE existing_event, created_event;++  created_event = CreateEvent(NULL, 1, 0, NULL);+  if (created_event == 0) {+    /* Could fail in a low-memory situation? */+    uv_fatal_error(GetLastError(), "CreateEvent");+  }++  existing_event = InterlockedCompareExchangePointer(&guard->event,+                                                     created_event,+                                                     NULL);++  if (existing_event == NULL) {+    /* We won the race */+    callback();++    result = SetEvent(created_event);+    assert(result);+    guard->ran = 1;++  } else {+    /* We lost the race. Destroy the event we created and wait for the existing+     * one to become signaled. */+    CloseHandle(created_event);+    result = WaitForSingleObject(existing_event, INFINITE);+    assert(result == WAIT_OBJECT_0);+  }+}+++void uv_once(uv_once_t* guard, void (*callback)(void)) {+  /* Fast case - avoid WaitForSingleObject. */+  if (guard->ran) {+    return;+  }++  uv__once_inner(guard, callback);+}+++/* Verify that uv_thread_t can be stored in a TLS slot. */+STATIC_ASSERT(sizeof(uv_thread_t) <= sizeof(void*));++static uv_key_t uv__current_thread_key;+static uv_once_t uv__current_thread_init_guard = UV_ONCE_INIT;+++static void uv__init_current_thread_key(void) {+  if (uv_key_create(&uv__current_thread_key))+    abort();+}+++struct thread_ctx {+  void (*entry)(void* arg);+  void* arg;+  uv_thread_t self;+};+++static UINT __stdcall uv__thread_start(void* arg) {+  struct thread_ctx *ctx_p;+  struct thread_ctx ctx;++  ctx_p = arg;+  ctx = *ctx_p;+  uv__free(ctx_p);++  uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);+  uv_key_set(&uv__current_thread_key, (void*) ctx.self);++  ctx.entry(ctx.arg);++  return 0;+}+++int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {+  uv_thread_options_t params;+  params.flags = UV_THREAD_NO_FLAGS;+  return uv_thread_create_ex(tid, &params, entry, arg);+}++int uv_thread_create_ex(uv_thread_t* tid,+                        const uv_thread_options_t* params,+                        void (*entry)(void *arg),+                        void *arg) {+  struct thread_ctx* ctx;+  int err;+  HANDLE thread;+  SYSTEM_INFO sysinfo;+  size_t stack_size;+  size_t pagesize;++  stack_size =+      params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;++  if (stack_size != 0) {+    GetNativeSystemInfo(&sysinfo);+    pagesize = (size_t)sysinfo.dwPageSize;+    /* Round up to the nearest page boundary. */+    stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);++    if ((unsigned)stack_size != stack_size)+      return UV_EINVAL;+  }++  ctx = uv__malloc(sizeof(*ctx));+  if (ctx == NULL)+    return UV_ENOMEM;++  ctx->entry = entry;+  ctx->arg = arg;++  /* Create the thread in suspended state so we have a chance to pass+   * its own creation handle to it */+  thread = (HANDLE) _beginthreadex(NULL,+                                   (unsigned)stack_size,+                                   uv__thread_start,+                                   ctx,+                                   CREATE_SUSPENDED,+                                   NULL);+  if (thread == NULL) {+    err = errno;+    uv__free(ctx);+  } else {+    err = 0;+    *tid = thread;+    ctx->self = thread;+    ResumeThread(thread);+  }++  switch (err) {+    case 0:+      return 0;+    case EACCES:+      return UV_EACCES;+    case EAGAIN:+      return UV_EAGAIN;+    case EINVAL:+      return UV_EINVAL;+  }++  return UV_EIO;+}+++uv_thread_t uv_thread_self(void) {+  uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);+  return (uv_thread_t) uv_key_get(&uv__current_thread_key);+}+++int uv_thread_join(uv_thread_t *tid) {+  if (WaitForSingleObject(*tid, INFINITE))+    return uv_translate_sys_error(GetLastError());+  else {+    CloseHandle(*tid);+    *tid = 0;+    MemoryBarrier();  /* For feature parity with pthread_join(). */+    return 0;+  }+}+++int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {+  return *t1 == *t2;+}+++int uv_mutex_init(uv_mutex_t* mutex) {+  InitializeCriticalSection(mutex);+  return 0;+}+++int uv_mutex_init_recursive(uv_mutex_t* mutex) {+  return uv_mutex_init(mutex);+}+++void uv_mutex_destroy(uv_mutex_t* mutex) {+  DeleteCriticalSection(mutex);+}+++void uv_mutex_lock(uv_mutex_t* mutex) {+  EnterCriticalSection(mutex);+}+++int uv_mutex_trylock(uv_mutex_t* mutex) {+  if (TryEnterCriticalSection(mutex))+    return 0;+  else+    return UV_EBUSY;+}+++void uv_mutex_unlock(uv_mutex_t* mutex) {+  LeaveCriticalSection(mutex);+}+++int uv_rwlock_init(uv_rwlock_t* rwlock) {+  /* Initialize the semaphore that acts as the write lock. */+  HANDLE handle = CreateSemaphoreW(NULL, 1, 1, NULL);+  if (handle == NULL)+    return uv_translate_sys_error(GetLastError());+  rwlock->state_.write_semaphore_ = handle;++  /* Initialize the critical section protecting the reader count. */+  InitializeCriticalSection(&rwlock->state_.num_readers_lock_);++  /* Initialize the reader count. */+  rwlock->state_.num_readers_ = 0;++  return 0;+}+++void uv_rwlock_destroy(uv_rwlock_t* rwlock) {+  DeleteCriticalSection(&rwlock->state_.num_readers_lock_);+  CloseHandle(rwlock->state_.write_semaphore_);+}+++void uv_rwlock_rdlock(uv_rwlock_t* rwlock) {+  /* Acquire the lock that protects the reader count. */+  EnterCriticalSection(&rwlock->state_.num_readers_lock_);++  /* Increase the reader count, and lock for write if this is the first+   * reader.+   */+  if (++rwlock->state_.num_readers_ == 1) {+    DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, INFINITE);+    if (r != WAIT_OBJECT_0)+      uv_fatal_error(GetLastError(), "WaitForSingleObject");+  }++  /* Release the lock that protects the reader count. */+  LeaveCriticalSection(&rwlock->state_.num_readers_lock_);+}+++int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {+  int err;++  if (!TryEnterCriticalSection(&rwlock->state_.num_readers_lock_))+    return UV_EBUSY;++  err = 0;++  if (rwlock->state_.num_readers_ == 0) {+    /* Currently there are no other readers, which means that the write lock+     * needs to be acquired.+     */+    DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, 0);+    if (r == WAIT_OBJECT_0)+      rwlock->state_.num_readers_++;+    else if (r == WAIT_TIMEOUT)+      err = UV_EBUSY;+    else if (r == WAIT_FAILED)+      uv_fatal_error(GetLastError(), "WaitForSingleObject");++  } else {+    /* The write lock has already been acquired because there are other+     * active readers.+     */+    rwlock->state_.num_readers_++;+  }++  LeaveCriticalSection(&rwlock->state_.num_readers_lock_);+  return err;+}+++void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {+  EnterCriticalSection(&rwlock->state_.num_readers_lock_);++  if (--rwlock->state_.num_readers_ == 0) {+    if (!ReleaseSemaphore(rwlock->state_.write_semaphore_, 1, NULL))+      uv_fatal_error(GetLastError(), "ReleaseSemaphore");+  }++  LeaveCriticalSection(&rwlock->state_.num_readers_lock_);+}+++void uv_rwlock_wrlock(uv_rwlock_t* rwlock) {+  DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, INFINITE);+  if (r != WAIT_OBJECT_0)+    uv_fatal_error(GetLastError(), "WaitForSingleObject");+}+++int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {+  DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, 0);+  if (r == WAIT_OBJECT_0)+    return 0;+  else if (r == WAIT_TIMEOUT)+    return UV_EBUSY;+  else+    uv_fatal_error(GetLastError(), "WaitForSingleObject");+}+++void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {+  if (!ReleaseSemaphore(rwlock->state_.write_semaphore_, 1, NULL))+    uv_fatal_error(GetLastError(), "ReleaseSemaphore");+}+++int uv_sem_init(uv_sem_t* sem, unsigned int value) {+  *sem = CreateSemaphore(NULL, value, INT_MAX, NULL);+  if (*sem == NULL)+    return uv_translate_sys_error(GetLastError());+  else+    return 0;+}+++void uv_sem_destroy(uv_sem_t* sem) {+  if (!CloseHandle(*sem))+    abort();+}+++void uv_sem_post(uv_sem_t* sem) {+  if (!ReleaseSemaphore(*sem, 1, NULL))+    abort();+}+++void uv_sem_wait(uv_sem_t* sem) {+  if (WaitForSingleObject(*sem, INFINITE) != WAIT_OBJECT_0)+    abort();+}+++int uv_sem_trywait(uv_sem_t* sem) {+  DWORD r = WaitForSingleObject(*sem, 0);++  if (r == WAIT_OBJECT_0)+    return 0;++  if (r == WAIT_TIMEOUT)+    return UV_EAGAIN;++  abort();+  return -1; /* Satisfy the compiler. */+}+++int uv_cond_init(uv_cond_t* cond) {+  InitializeConditionVariable(&cond->cond_var);+  return 0;+}+++void uv_cond_destroy(uv_cond_t* cond) {+  /* nothing to do */+  (void) &cond;+}+++void uv_cond_signal(uv_cond_t* cond) {+  WakeConditionVariable(&cond->cond_var);+}+++void uv_cond_broadcast(uv_cond_t* cond) {+  WakeAllConditionVariable(&cond->cond_var);+}+++void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {+  if (!SleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))+    abort();+}++int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {+  if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))+    return 0;+  if (GetLastError() != ERROR_TIMEOUT)+    abort();+  return UV_ETIMEDOUT;+}+++int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {+  int err;++  barrier->n = count;+  barrier->count = 0;++  err = uv_mutex_init(&barrier->mutex);+  if (err)+    return err;++  err = uv_sem_init(&barrier->turnstile1, 0);+  if (err)+    goto error2;++  err = uv_sem_init(&barrier->turnstile2, 1);+  if (err)+    goto error;++  return 0;++error:+  uv_sem_destroy(&barrier->turnstile1);+error2:+  uv_mutex_destroy(&barrier->mutex);+  return err;++}+++void uv_barrier_destroy(uv_barrier_t* barrier) {+  uv_sem_destroy(&barrier->turnstile2);+  uv_sem_destroy(&barrier->turnstile1);+  uv_mutex_destroy(&barrier->mutex);+}+++int uv_barrier_wait(uv_barrier_t* barrier) {+  int serial_thread;++  uv_mutex_lock(&barrier->mutex);+  if (++barrier->count == barrier->n) {+    uv_sem_wait(&barrier->turnstile2);+    uv_sem_post(&barrier->turnstile1);+  }+  uv_mutex_unlock(&barrier->mutex);++  uv_sem_wait(&barrier->turnstile1);+  uv_sem_post(&barrier->turnstile1);++  uv_mutex_lock(&barrier->mutex);+  serial_thread = (--barrier->count == 0);+  if (serial_thread) {+    uv_sem_wait(&barrier->turnstile1);+    uv_sem_post(&barrier->turnstile2);+  }+  uv_mutex_unlock(&barrier->mutex);++  uv_sem_wait(&barrier->turnstile2);+  uv_sem_post(&barrier->turnstile2);+  return serial_thread;+}+++int uv_key_create(uv_key_t* key) {+  key->tls_index = TlsAlloc();+  if (key->tls_index == TLS_OUT_OF_INDEXES)+    return UV_ENOMEM;+  return 0;+}+++void uv_key_delete(uv_key_t* key) {+  if (TlsFree(key->tls_index) == FALSE)+    abort();+  key->tls_index = TLS_OUT_OF_INDEXES;+}+++void* uv_key_get(uv_key_t* key) {+  void* value;++  value = TlsGetValue(key->tls_index);+  if (value == NULL)+    if (GetLastError() != ERROR_SUCCESS)+      abort();++  return value;+}+++void uv_key_set(uv_key_t* key, void* value) {+  if (TlsSetValue(key->tls_index, value) == FALSE)+    abort();+}
+ third_party/libuv/src/win/tty.c view
@@ -0,0 +1,2331 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <io.h>+#include <string.h>+#include <stdlib.h>++#if defined(_MSC_VER) && _MSC_VER < 1600+# include "uv/stdint-msvc2008.h"+#else+# include <stdint.h>+#endif++#ifndef COMMON_LVB_REVERSE_VIDEO+# define COMMON_LVB_REVERSE_VIDEO 0x4000+#endif++#include "uv.h"+#include "internal.h"+#include "handle-inl.h"+#include "stream-inl.h"+#include "req-inl.h"++#ifndef InterlockedOr+# define InterlockedOr _InterlockedOr+#endif++#define UNICODE_REPLACEMENT_CHARACTER (0xfffd)++#define ANSI_NORMAL           0x00+#define ANSI_ESCAPE_SEEN      0x02+#define ANSI_CSI              0x04+#define ANSI_ST_CONTROL       0x08+#define ANSI_IGNORE           0x10+#define ANSI_IN_ARG           0x20+#define ANSI_IN_STRING        0x40+#define ANSI_BACKSLASH_SEEN   0x80++#define MAX_INPUT_BUFFER_LENGTH 8192+#define MAX_CONSOLE_CHAR 8192++#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004+#endif++static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info);+static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info);+static int uv__cancel_read_console(uv_tty_t* handle);+++/* Null uv_buf_t */+static const uv_buf_t uv_null_buf_ = { 0, NULL };++enum uv__read_console_status_e {+  NOT_STARTED,+  IN_PROGRESS,+  TRAP_REQUESTED,+  COMPLETED+};++static volatile LONG uv__read_console_status = NOT_STARTED;+static volatile LONG uv__restore_screen_state;+static CONSOLE_SCREEN_BUFFER_INFO uv__saved_screen_state;+++/*+ * The console virtual window.+ *+ * Normally cursor movement in windows is relative to the console screen buffer,+ * e.g. the application is allowed to overwrite the 'history'. This is very+ * inconvenient, it makes absolute cursor movement pretty useless. There is+ * also the concept of 'client rect' which is defined by the actual size of+ * the console window and the scroll position of the screen buffer, but it's+ * very volatile because it changes when the user scrolls.+ *+ * To make cursor movement behave sensibly we define a virtual window to which+ * cursor movement is confined. The virtual window is always as wide as the+ * console screen buffer, but it's height is defined by the size of the+ * console window. The top of the virtual window aligns with the position+ * of the caret when the first stdout/err handle is created, unless that would+ * mean that it would extend beyond the bottom of the screen buffer -  in that+ * that case it's located as far down as possible.+ *+ * When the user writes a long text or many newlines, such that the output+ * reaches beyond the bottom of the virtual window, the virtual window is+ * shifted downwards, but not resized.+ *+ * Since all tty i/o happens on the same console, this window is shared+ * between all stdout/stderr handles.+ */++static int uv_tty_virtual_offset = -1;+static int uv_tty_virtual_height = -1;+static int uv_tty_virtual_width = -1;++/* The console window size+ * We keep this separate from uv_tty_virtual_*. We use those values to only+ * handle signalling SIGWINCH+ */++static HANDLE uv__tty_console_handle = INVALID_HANDLE_VALUE;+static int uv__tty_console_height = -1;+static int uv__tty_console_width = -1;++static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param);+static void CALLBACK uv__tty_console_resize_event(HWINEVENTHOOK hWinEventHook,+                                                  DWORD event,+                                                  HWND hwnd,+                                                  LONG idObject,+                                                  LONG idChild,+                                                  DWORD dwEventThread,+                                                  DWORD dwmsEventTime);++/* We use a semaphore rather than a mutex or critical section because in some+   cases (uv__cancel_read_console) we need take the lock in the main thread and+   release it in another thread. Using a semaphore ensures that in such+   scenario the main thread will still block when trying to acquire the lock. */+static uv_sem_t uv_tty_output_lock;++static WORD uv_tty_default_text_attributes =+    FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;++static char uv_tty_default_fg_color = 7;+static char uv_tty_default_bg_color = 0;+static char uv_tty_default_fg_bright = 0;+static char uv_tty_default_bg_bright = 0;+static char uv_tty_default_inverse = 0;++typedef enum {+  UV_SUPPORTED,+  UV_UNCHECKED,+  UV_UNSUPPORTED+} uv_vtermstate_t;+/* Determine whether or not ANSI support is enabled. */+static uv_vtermstate_t uv__vterm_state = UV_UNCHECKED;+static void uv__determine_vterm_state(HANDLE handle);++void uv_console_init(void) {+  if (uv_sem_init(&uv_tty_output_lock, 1))+    abort();+  uv__tty_console_handle = CreateFileW(L"CONOUT$",+                                       GENERIC_READ | GENERIC_WRITE,+                                       FILE_SHARE_WRITE,+                                       0,+                                       OPEN_EXISTING,+                                       0,+                                       0);+  if (uv__tty_console_handle != INVALID_HANDLE_VALUE) {+    QueueUserWorkItem(uv__tty_console_resize_message_loop_thread,+                      NULL,+                      WT_EXECUTELONGFUNCTION);+  }+}+++int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {+  BOOL readable;+  DWORD NumberOfEvents;+  HANDLE handle;+  CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;+  (void)unused;++  uv__once_init();+  handle = (HANDLE) uv__get_osfhandle(fd);+  if (handle == INVALID_HANDLE_VALUE)+    return UV_EBADF;++  if (fd <= 2) {+    /* In order to avoid closing a stdio file descriptor 0-2, duplicate the+     * underlying OS handle and forget about the original fd.+     * We could also opt to use the original OS handle and just never close it,+     * but then there would be no reliable way to cancel pending read operations+     * upon close.+     */+    if (!DuplicateHandle(INVALID_HANDLE_VALUE,+                         handle,+                         INVALID_HANDLE_VALUE,+                         &handle,+                         0,+                         FALSE,+                         DUPLICATE_SAME_ACCESS))+      return uv_translate_sys_error(GetLastError());+    fd = -1;+  }++  readable = GetNumberOfConsoleInputEvents(handle, &NumberOfEvents);+  if (!readable) {+    /* Obtain the screen buffer info with the output handle. */+    if (!GetConsoleScreenBufferInfo(handle, &screen_buffer_info)) {+      return uv_translate_sys_error(GetLastError());+    }++    /* Obtain the tty_output_lock because the virtual window state is shared+     * between all uv_tty_t handles. */+    uv_sem_wait(&uv_tty_output_lock);++    if (uv__vterm_state == UV_UNCHECKED)+      uv__determine_vterm_state(handle);++    /* Remember the original console text attributes. */+    uv_tty_capture_initial_style(&screen_buffer_info);++    uv_tty_update_virtual_window(&screen_buffer_info);++    uv_sem_post(&uv_tty_output_lock);+  }+++  uv_stream_init(loop, (uv_stream_t*) tty, UV_TTY);+  uv_connection_init((uv_stream_t*) tty);++  tty->handle = handle;+  tty->u.fd = fd;+  tty->reqs_pending = 0;+  tty->flags |= UV_HANDLE_BOUND;++  if (readable) {+    /* Initialize TTY input specific fields. */+    tty->flags |= UV_HANDLE_TTY_READABLE | UV_HANDLE_READABLE;+    /* TODO: remove me in v2.x. */+    tty->tty.rd.unused_ = NULL;+    tty->tty.rd.read_line_buffer = uv_null_buf_;+    tty->tty.rd.read_raw_wait = NULL;++    /* Init keycode-to-vt100 mapper state. */+    tty->tty.rd.last_key_len = 0;+    tty->tty.rd.last_key_offset = 0;+    tty->tty.rd.last_utf16_high_surrogate = 0;+    memset(&tty->tty.rd.last_input_record, 0, sizeof tty->tty.rd.last_input_record);+  } else {+    /* TTY output specific fields. */+    tty->flags |= UV_HANDLE_WRITABLE;++    /* Init utf8-to-utf16 conversion state. */+    tty->tty.wr.utf8_bytes_left = 0;+    tty->tty.wr.utf8_codepoint = 0;++    /* Initialize eol conversion state */+    tty->tty.wr.previous_eol = 0;++    /* Init ANSI parser state. */+    tty->tty.wr.ansi_parser_state = ANSI_NORMAL;+  }++  return 0;+}+++/* Set the default console text attributes based on how the console was+ * configured when libuv started.+ */+static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info) {+  static int style_captured = 0;++  /* Only do this once.+     Assumption: Caller has acquired uv_tty_output_lock. */+  if (style_captured)+    return;++  /* Save raw win32 attributes. */+  uv_tty_default_text_attributes = info->wAttributes;++  /* Convert black text on black background to use white text. */+  if (uv_tty_default_text_attributes == 0)+    uv_tty_default_text_attributes = 7;++  /* Convert Win32 attributes to ANSI colors. */+  uv_tty_default_fg_color = 0;+  uv_tty_default_bg_color = 0;+  uv_tty_default_fg_bright = 0;+  uv_tty_default_bg_bright = 0;+  uv_tty_default_inverse = 0;++  if (uv_tty_default_text_attributes & FOREGROUND_RED)+    uv_tty_default_fg_color |= 1;++  if (uv_tty_default_text_attributes & FOREGROUND_GREEN)+    uv_tty_default_fg_color |= 2;++  if (uv_tty_default_text_attributes & FOREGROUND_BLUE)+    uv_tty_default_fg_color |= 4;++  if (uv_tty_default_text_attributes & BACKGROUND_RED)+    uv_tty_default_bg_color |= 1;++  if (uv_tty_default_text_attributes & BACKGROUND_GREEN)+    uv_tty_default_bg_color |= 2;++  if (uv_tty_default_text_attributes & BACKGROUND_BLUE)+    uv_tty_default_bg_color |= 4;++  if (uv_tty_default_text_attributes & FOREGROUND_INTENSITY)+    uv_tty_default_fg_bright = 1;++  if (uv_tty_default_text_attributes & BACKGROUND_INTENSITY)+    uv_tty_default_bg_bright = 1;++  if (uv_tty_default_text_attributes & COMMON_LVB_REVERSE_VIDEO)+    uv_tty_default_inverse = 1;++  style_captured = 1;+}+++int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {+  DWORD flags;+  unsigned char was_reading;+  uv_alloc_cb alloc_cb;+  uv_read_cb read_cb;+  int err;++  if (!(tty->flags & UV_HANDLE_TTY_READABLE)) {+    return UV_EINVAL;+  }++  if (!!mode == !!(tty->flags & UV_HANDLE_TTY_RAW)) {+    return 0;+  }++  switch (mode) {+    case UV_TTY_MODE_NORMAL:+      flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;+      break;+    case UV_TTY_MODE_RAW:+      flags = ENABLE_WINDOW_INPUT;+      break;+    case UV_TTY_MODE_IO:+      return UV_ENOTSUP;+    default:+      return UV_EINVAL;+  }++  /* If currently reading, stop, and restart reading. */+  if (tty->flags & UV_HANDLE_READING) {+    was_reading = 1;+    alloc_cb = tty->alloc_cb;+    read_cb = tty->read_cb;+    err = uv_tty_read_stop(tty);+    if (err) {+      return uv_translate_sys_error(err);+    }+  } else {+    was_reading = 0;+    alloc_cb = NULL;+    read_cb = NULL;+  }++  uv_sem_wait(&uv_tty_output_lock);+  if (!SetConsoleMode(tty->handle, flags)) {+    err = uv_translate_sys_error(GetLastError());+    uv_sem_post(&uv_tty_output_lock);+    return err;+  }+  uv_sem_post(&uv_tty_output_lock);++  /* Update flag. */+  tty->flags &= ~UV_HANDLE_TTY_RAW;+  tty->flags |= mode ? UV_HANDLE_TTY_RAW : 0;++  /* If we just stopped reading, restart. */+  if (was_reading) {+    err = uv_tty_read_start(tty, alloc_cb, read_cb);+    if (err) {+      return uv_translate_sys_error(err);+    }+  }++  return 0;+}+++int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {+  CONSOLE_SCREEN_BUFFER_INFO info;++  if (!GetConsoleScreenBufferInfo(tty->handle, &info)) {+    return uv_translate_sys_error(GetLastError());+  }++  uv_sem_wait(&uv_tty_output_lock);+  uv_tty_update_virtual_window(&info);+  uv_sem_post(&uv_tty_output_lock);++  *width = uv_tty_virtual_width;+  *height = uv_tty_virtual_height;++  return 0;+}+++static void CALLBACK uv_tty_post_raw_read(void* data, BOOLEAN didTimeout) {+  uv_loop_t* loop;+  uv_tty_t* handle;+  uv_req_t* req;++  assert(data);+  assert(!didTimeout);++  req = (uv_req_t*) data;+  handle = (uv_tty_t*) req->data;+  loop = handle->loop;++  UnregisterWait(handle->tty.rd.read_raw_wait);+  handle->tty.rd.read_raw_wait = NULL;++  SET_REQ_SUCCESS(req);+  POST_COMPLETION_FOR_REQ(loop, req);+}+++static void uv_tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) {+  uv_read_t* req;+  BOOL r;++  assert(handle->flags & UV_HANDLE_READING);+  assert(!(handle->flags & UV_HANDLE_READ_PENDING));++  assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE);++  handle->tty.rd.read_line_buffer = uv_null_buf_;++  req = &handle->read_req;+  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));++  r = RegisterWaitForSingleObject(&handle->tty.rd.read_raw_wait,+                                  handle->handle,+                                  uv_tty_post_raw_read,+                                  (void*) req,+                                  INFINITE,+                                  WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE);+  if (!r) {+    handle->tty.rd.read_raw_wait = NULL;+    SET_REQ_ERROR(req, GetLastError());+    uv_insert_pending_req(loop, (uv_req_t*)req);+  }++  handle->flags |= UV_HANDLE_READ_PENDING;+  handle->reqs_pending++;+}+++static DWORD CALLBACK uv_tty_line_read_thread(void* data) {+  uv_loop_t* loop;+  uv_tty_t* handle;+  uv_req_t* req;+  DWORD bytes, read_bytes;+  WCHAR utf16[MAX_INPUT_BUFFER_LENGTH / 3];+  DWORD chars, read_chars;+  LONG status;+  COORD pos;+  BOOL read_console_success;++  assert(data);++  req = (uv_req_t*) data;+  handle = (uv_tty_t*) req->data;+  loop = handle->loop;++  assert(handle->tty.rd.read_line_buffer.base != NULL);+  assert(handle->tty.rd.read_line_buffer.len > 0);++  /* ReadConsole can't handle big buffers. */+  if (handle->tty.rd.read_line_buffer.len < MAX_INPUT_BUFFER_LENGTH) {+    bytes = handle->tty.rd.read_line_buffer.len;+  } else {+    bytes = MAX_INPUT_BUFFER_LENGTH;+  }++  /* At last, unicode! One utf-16 codeunit never takes more than 3 utf-8+   * codeunits to encode. */+  chars = bytes / 3;++  status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS);+  if (status == TRAP_REQUESTED) {+    SET_REQ_SUCCESS(req);+    req->u.io.overlapped.InternalHigh = 0;+    POST_COMPLETION_FOR_REQ(loop, req);+    return 0;+  }++  read_console_success = ReadConsoleW(handle->handle,+                                      (void*) utf16,+                                      chars,+                                      &read_chars,+                                      NULL);++  if (read_console_success) {+    read_bytes = WideCharToMultiByte(CP_UTF8,+                                     0,+                                     utf16,+                                     read_chars,+                                     handle->tty.rd.read_line_buffer.base,+                                     bytes,+                                     NULL,+                                     NULL);+    SET_REQ_SUCCESS(req);+    req->u.io.overlapped.InternalHigh = read_bytes;+  } else {+    SET_REQ_ERROR(req, GetLastError());+  }++  status = InterlockedExchange(&uv__read_console_status, COMPLETED);++  if (status ==  TRAP_REQUESTED) {+    /* If we canceled the read by sending a VK_RETURN event, restore the+       screen state to undo the visual effect of the VK_RETURN */+    if (read_console_success && InterlockedOr(&uv__restore_screen_state, 0)) {+      HANDLE active_screen_buffer;+      active_screen_buffer = CreateFileA("conout$",+                                         GENERIC_READ | GENERIC_WRITE,+                                         FILE_SHARE_READ | FILE_SHARE_WRITE,+                                         NULL,+                                         OPEN_EXISTING,+                                         FILE_ATTRIBUTE_NORMAL,+                                         NULL);+      if (active_screen_buffer != INVALID_HANDLE_VALUE) {+        pos = uv__saved_screen_state.dwCursorPosition;++        /* If the cursor was at the bottom line of the screen buffer, the+           VK_RETURN would have caused the buffer contents to scroll up by one+           line. The right position to reset the cursor to is therefore one line+           higher */+        if (pos.Y == uv__saved_screen_state.dwSize.Y - 1)+          pos.Y--;++        SetConsoleCursorPosition(active_screen_buffer, pos);+        CloseHandle(active_screen_buffer);+      }+    }+    uv_sem_post(&uv_tty_output_lock);+  }+  POST_COMPLETION_FOR_REQ(loop, req);+  return 0;+}+++static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) {+  uv_read_t* req;+  BOOL r;++  assert(handle->flags & UV_HANDLE_READING);+  assert(!(handle->flags & UV_HANDLE_READ_PENDING));+  assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE);++  req = &handle->read_req;+  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));++  handle->tty.rd.read_line_buffer = uv_buf_init(NULL, 0);+  handle->alloc_cb((uv_handle_t*) handle, 8192, &handle->tty.rd.read_line_buffer);+  if (handle->tty.rd.read_line_buffer.base == NULL ||+      handle->tty.rd.read_line_buffer.len == 0) {+    handle->read_cb((uv_stream_t*) handle,+                    UV_ENOBUFS,+                    &handle->tty.rd.read_line_buffer);+    return;+  }+  assert(handle->tty.rd.read_line_buffer.base != NULL);++  /* Reset flags  No locking is required since there cannot be a line read+     in progress. We are also relying on the memory barrier provided by+     QueueUserWorkItem*/+  uv__restore_screen_state = FALSE;+  uv__read_console_status = NOT_STARTED;+  r = QueueUserWorkItem(uv_tty_line_read_thread,+                        (void*) req,+                        WT_EXECUTELONGFUNCTION);+  if (!r) {+    SET_REQ_ERROR(req, GetLastError());+    uv_insert_pending_req(loop, (uv_req_t*)req);+  }++  handle->flags |= UV_HANDLE_READ_PENDING;+  handle->reqs_pending++;+}+++static void uv_tty_queue_read(uv_loop_t* loop, uv_tty_t* handle) {+  if (handle->flags & UV_HANDLE_TTY_RAW) {+    uv_tty_queue_read_raw(loop, handle);+  } else {+    uv_tty_queue_read_line(loop, handle);+  }+}+++static const char* get_vt100_fn_key(DWORD code, char shift, char ctrl,+    size_t* len) {+#define VK_CASE(vk, normal_str, shift_str, ctrl_str, shift_ctrl_str)          \+    case (vk):                                                                \+      if (shift && ctrl) {                                                    \+        *len = sizeof shift_ctrl_str;                                         \+        return "\033" shift_ctrl_str;                                         \+      } else if (shift) {                                                     \+        *len = sizeof shift_str ;                                             \+        return "\033" shift_str;                                              \+      } else if (ctrl) {                                                      \+        *len = sizeof ctrl_str;                                               \+        return "\033" ctrl_str;                                               \+      } else {                                                                \+        *len = sizeof normal_str;                                             \+        return "\033" normal_str;                                             \+      }++  switch (code) {+    /* These mappings are the same as Cygwin's. Unmodified and alt-modified+     * keypad keys comply with linux console, modifiers comply with xterm+     * modifier usage. F1. f12 and shift-f1. f10 comply with linux console, f6.+     * f12 with and without modifiers comply with rxvt. */+    VK_CASE(VK_INSERT,  "[2~",  "[2;2~", "[2;5~", "[2;6~")+    VK_CASE(VK_END,     "[4~",  "[4;2~", "[4;5~", "[4;6~")+    VK_CASE(VK_DOWN,    "[B",   "[1;2B", "[1;5B", "[1;6B")+    VK_CASE(VK_NEXT,    "[6~",  "[6;2~", "[6;5~", "[6;6~")+    VK_CASE(VK_LEFT,    "[D",   "[1;2D", "[1;5D", "[1;6D")+    VK_CASE(VK_CLEAR,   "[G",   "[1;2G", "[1;5G", "[1;6G")+    VK_CASE(VK_RIGHT,   "[C",   "[1;2C", "[1;5C", "[1;6C")+    VK_CASE(VK_UP,      "[A",   "[1;2A", "[1;5A", "[1;6A")+    VK_CASE(VK_HOME,    "[1~",  "[1;2~", "[1;5~", "[1;6~")+    VK_CASE(VK_PRIOR,   "[5~",  "[5;2~", "[5;5~", "[5;6~")+    VK_CASE(VK_DELETE,  "[3~",  "[3;2~", "[3;5~", "[3;6~")+    VK_CASE(VK_NUMPAD0, "[2~",  "[2;2~", "[2;5~", "[2;6~")+    VK_CASE(VK_NUMPAD1, "[4~",  "[4;2~", "[4;5~", "[4;6~")+    VK_CASE(VK_NUMPAD2, "[B",   "[1;2B", "[1;5B", "[1;6B")+    VK_CASE(VK_NUMPAD3, "[6~",  "[6;2~", "[6;5~", "[6;6~")+    VK_CASE(VK_NUMPAD4, "[D",   "[1;2D", "[1;5D", "[1;6D")+    VK_CASE(VK_NUMPAD5, "[G",   "[1;2G", "[1;5G", "[1;6G")+    VK_CASE(VK_NUMPAD6, "[C",   "[1;2C", "[1;5C", "[1;6C")+    VK_CASE(VK_NUMPAD7, "[A",   "[1;2A", "[1;5A", "[1;6A")+    VK_CASE(VK_NUMPAD8, "[1~",  "[1;2~", "[1;5~", "[1;6~")+    VK_CASE(VK_NUMPAD9, "[5~",  "[5;2~", "[5;5~", "[5;6~")+    VK_CASE(VK_DECIMAL, "[3~",  "[3;2~", "[3;5~", "[3;6~")+    VK_CASE(VK_F1,      "[[A",  "[23~",  "[11^",  "[23^" )+    VK_CASE(VK_F2,      "[[B",  "[24~",  "[12^",  "[24^" )+    VK_CASE(VK_F3,      "[[C",  "[25~",  "[13^",  "[25^" )+    VK_CASE(VK_F4,      "[[D",  "[26~",  "[14^",  "[26^" )+    VK_CASE(VK_F5,      "[[E",  "[28~",  "[15^",  "[28^" )+    VK_CASE(VK_F6,      "[17~", "[29~",  "[17^",  "[29^" )+    VK_CASE(VK_F7,      "[18~", "[31~",  "[18^",  "[31^" )+    VK_CASE(VK_F8,      "[19~", "[32~",  "[19^",  "[32^" )+    VK_CASE(VK_F9,      "[20~", "[33~",  "[20^",  "[33^" )+    VK_CASE(VK_F10,     "[21~", "[34~",  "[21^",  "[34^" )+    VK_CASE(VK_F11,     "[23~", "[23$",  "[23^",  "[23@" )+    VK_CASE(VK_F12,     "[24~", "[24$",  "[24^",  "[24@" )++    default:+      *len = 0;+      return NULL;+  }+#undef VK_CASE+}+++void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,+    uv_req_t* req) {+  /* Shortcut for handle->tty.rd.last_input_record.Event.KeyEvent. */+#define KEV handle->tty.rd.last_input_record.Event.KeyEvent++  DWORD records_left, records_read;+  uv_buf_t buf;+  off_t buf_used;++  assert(handle->type == UV_TTY);+  assert(handle->flags & UV_HANDLE_TTY_READABLE);+  handle->flags &= ~UV_HANDLE_READ_PENDING;++  if (!(handle->flags & UV_HANDLE_READING) ||+      !(handle->flags & UV_HANDLE_TTY_RAW)) {+    goto out;+  }++  if (!REQ_SUCCESS(req)) {+    /* An error occurred while waiting for the event. */+    if ((handle->flags & UV_HANDLE_READING)) {+      handle->flags &= ~UV_HANDLE_READING;+      handle->read_cb((uv_stream_t*)handle,+                      uv_translate_sys_error(GET_REQ_ERROR(req)),+                      &uv_null_buf_);+    }+    goto out;+  }++  /* Fetch the number of events  */+  if (!GetNumberOfConsoleInputEvents(handle->handle, &records_left)) {+    handle->flags &= ~UV_HANDLE_READING;+    DECREASE_ACTIVE_COUNT(loop, handle);+    handle->read_cb((uv_stream_t*)handle,+                    uv_translate_sys_error(GetLastError()),+                    &uv_null_buf_);+    goto out;+  }++  /* Windows sends a lot of events that we're not interested in, so buf will be+   * allocated on demand, when there's actually something to emit. */+  buf = uv_null_buf_;+  buf_used = 0;++  while ((records_left > 0 || handle->tty.rd.last_key_len > 0) &&+         (handle->flags & UV_HANDLE_READING)) {+    if (handle->tty.rd.last_key_len == 0) {+      /* Read the next input record */+      if (!ReadConsoleInputW(handle->handle,+                             &handle->tty.rd.last_input_record,+                             1,+                             &records_read)) {+        handle->flags &= ~UV_HANDLE_READING;+        DECREASE_ACTIVE_COUNT(loop, handle);+        handle->read_cb((uv_stream_t*) handle,+                        uv_translate_sys_error(GetLastError()),+                        &buf);+        goto out;+      }+      records_left--;++      /* Ignore other events that are not key events. */+      if (handle->tty.rd.last_input_record.EventType != KEY_EVENT) {+        continue;+      }++      /* Ignore keyup events, unless the left alt key was held and a valid+       * unicode character was emitted. */+      if (!KEV.bKeyDown &&+          (KEV.wVirtualKeyCode != VK_MENU ||+           KEV.uChar.UnicodeChar == 0)) {+        continue;+      }++      /* Ignore keypresses to numpad number keys if the left alt is held+       * because the user is composing a character, or windows simulating this.+       */+      if ((KEV.dwControlKeyState & LEFT_ALT_PRESSED) &&+          !(KEV.dwControlKeyState & ENHANCED_KEY) &&+          (KEV.wVirtualKeyCode == VK_INSERT ||+          KEV.wVirtualKeyCode == VK_END ||+          KEV.wVirtualKeyCode == VK_DOWN ||+          KEV.wVirtualKeyCode == VK_NEXT ||+          KEV.wVirtualKeyCode == VK_LEFT ||+          KEV.wVirtualKeyCode == VK_CLEAR ||+          KEV.wVirtualKeyCode == VK_RIGHT ||+          KEV.wVirtualKeyCode == VK_HOME ||+          KEV.wVirtualKeyCode == VK_UP ||+          KEV.wVirtualKeyCode == VK_PRIOR ||+          KEV.wVirtualKeyCode == VK_NUMPAD0 ||+          KEV.wVirtualKeyCode == VK_NUMPAD1 ||+          KEV.wVirtualKeyCode == VK_NUMPAD2 ||+          KEV.wVirtualKeyCode == VK_NUMPAD3 ||+          KEV.wVirtualKeyCode == VK_NUMPAD4 ||+          KEV.wVirtualKeyCode == VK_NUMPAD5 ||+          KEV.wVirtualKeyCode == VK_NUMPAD6 ||+          KEV.wVirtualKeyCode == VK_NUMPAD7 ||+          KEV.wVirtualKeyCode == VK_NUMPAD8 ||+          KEV.wVirtualKeyCode == VK_NUMPAD9)) {+        continue;+      }++      if (KEV.uChar.UnicodeChar != 0) {+        int prefix_len, char_len;++        /* Character key pressed */+        if (KEV.uChar.UnicodeChar >= 0xD800 &&+            KEV.uChar.UnicodeChar < 0xDC00) {+          /* UTF-16 high surrogate */+          handle->tty.rd.last_utf16_high_surrogate = KEV.uChar.UnicodeChar;+          continue;+        }++        /* Prefix with \u033 if alt was held, but alt was not used as part a+         * compose sequence. */+        if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))+            && !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED |+            RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) {+          handle->tty.rd.last_key[0] = '\033';+          prefix_len = 1;+        } else {+          prefix_len = 0;+        }++        if (KEV.uChar.UnicodeChar >= 0xDC00 &&+            KEV.uChar.UnicodeChar < 0xE000) {+          /* UTF-16 surrogate pair */+          WCHAR utf16_buffer[2];+          utf16_buffer[0] = handle->tty.rd.last_utf16_high_surrogate;+          utf16_buffer[1] = KEV.uChar.UnicodeChar;+          char_len = WideCharToMultiByte(CP_UTF8,+                                         0,+                                         utf16_buffer,+                                         2,+                                         &handle->tty.rd.last_key[prefix_len],+                                         sizeof handle->tty.rd.last_key,+                                         NULL,+                                         NULL);+        } else {+          /* Single UTF-16 character */+          char_len = WideCharToMultiByte(CP_UTF8,+                                         0,+                                         &KEV.uChar.UnicodeChar,+                                         1,+                                         &handle->tty.rd.last_key[prefix_len],+                                         sizeof handle->tty.rd.last_key,+                                         NULL,+                                         NULL);+        }++        /* Whatever happened, the last character wasn't a high surrogate. */+        handle->tty.rd.last_utf16_high_surrogate = 0;++        /* If the utf16 character(s) couldn't be converted something must be+         * wrong. */+        if (!char_len) {+          handle->flags &= ~UV_HANDLE_READING;+          DECREASE_ACTIVE_COUNT(loop, handle);+          handle->read_cb((uv_stream_t*) handle,+                          uv_translate_sys_error(GetLastError()),+                          &buf);+          goto out;+        }++        handle->tty.rd.last_key_len = (unsigned char) (prefix_len + char_len);+        handle->tty.rd.last_key_offset = 0;+        continue;++      } else {+        /* Function key pressed */+        const char* vt100;+        size_t prefix_len, vt100_len;++        vt100 = get_vt100_fn_key(KEV.wVirtualKeyCode,+                                  !!(KEV.dwControlKeyState & SHIFT_PRESSED),+                                  !!(KEV.dwControlKeyState & (+                                    LEFT_CTRL_PRESSED |+                                    RIGHT_CTRL_PRESSED)),+                                  &vt100_len);++        /* If we were unable to map to a vt100 sequence, just ignore. */+        if (!vt100) {+          continue;+        }++        /* Prefix with \x033 when the alt key was held. */+        if (KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {+          handle->tty.rd.last_key[0] = '\033';+          prefix_len = 1;+        } else {+          prefix_len = 0;+        }++        /* Copy the vt100 sequence to the handle buffer. */+        assert(prefix_len + vt100_len < sizeof handle->tty.rd.last_key);+        memcpy(&handle->tty.rd.last_key[prefix_len], vt100, vt100_len);++        handle->tty.rd.last_key_len = (unsigned char) (prefix_len + vt100_len);+        handle->tty.rd.last_key_offset = 0;+        continue;+      }+    } else {+      /* Copy any bytes left from the last keypress to the user buffer. */+      if (handle->tty.rd.last_key_offset < handle->tty.rd.last_key_len) {+        /* Allocate a buffer if needed */+        if (buf_used == 0) {+          buf = uv_buf_init(NULL, 0);+          handle->alloc_cb((uv_handle_t*) handle, 1024, &buf);+          if (buf.base == NULL || buf.len == 0) {+            handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf);+            goto out;+          }+          assert(buf.base != NULL);+        }++        buf.base[buf_used++] = handle->tty.rd.last_key[handle->tty.rd.last_key_offset++];++        /* If the buffer is full, emit it */+        if ((size_t) buf_used == buf.len) {+          handle->read_cb((uv_stream_t*) handle, buf_used, &buf);+          buf = uv_null_buf_;+          buf_used = 0;+        }++        continue;+      }++      /* Apply dwRepeat from the last input record. */+      if (--KEV.wRepeatCount > 0) {+        handle->tty.rd.last_key_offset = 0;+        continue;+      }++      handle->tty.rd.last_key_len = 0;+      continue;+    }+  }++  /* Send the buffer back to the user */+  if (buf_used > 0) {+    handle->read_cb((uv_stream_t*) handle, buf_used, &buf);+  }++ out:+  /* Wait for more input events. */+  if ((handle->flags & UV_HANDLE_READING) &&+      !(handle->flags & UV_HANDLE_READ_PENDING)) {+    uv_tty_queue_read(loop, handle);+  }++  DECREASE_PENDING_REQ_COUNT(handle);++#undef KEV+}++++void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle,+    uv_req_t* req) {+  uv_buf_t buf;++  assert(handle->type == UV_TTY);+  assert(handle->flags & UV_HANDLE_TTY_READABLE);++  buf = handle->tty.rd.read_line_buffer;++  handle->flags &= ~UV_HANDLE_READ_PENDING;+  handle->tty.rd.read_line_buffer = uv_null_buf_;++  if (!REQ_SUCCESS(req)) {+    /* Read was not successful */+    if (handle->flags & UV_HANDLE_READING) {+      /* Real error */+      handle->flags &= ~UV_HANDLE_READING;+      DECREASE_ACTIVE_COUNT(loop, handle);+      handle->read_cb((uv_stream_t*) handle,+                      uv_translate_sys_error(GET_REQ_ERROR(req)),+                      &buf);+    }+  } else {+    if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING) &&+        req->u.io.overlapped.InternalHigh != 0) {+      /* Read successful. TODO: read unicode, convert to utf-8 */+      DWORD bytes = req->u.io.overlapped.InternalHigh;+      handle->read_cb((uv_stream_t*) handle, bytes, &buf);+    }+    handle->flags &= ~UV_HANDLE_CANCELLATION_PENDING;+  }++  /* Wait for more input events. */+  if ((handle->flags & UV_HANDLE_READING) &&+      !(handle->flags & UV_HANDLE_READ_PENDING)) {+    uv_tty_queue_read(loop, handle);+  }++  DECREASE_PENDING_REQ_COUNT(handle);+}+++void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,+    uv_req_t* req) {+  assert(handle->type == UV_TTY);+  assert(handle->flags & UV_HANDLE_TTY_READABLE);++  /* If the read_line_buffer member is zero, it must have been an raw read.+   * Otherwise it was a line-buffered read. FIXME: This is quite obscure. Use a+   * flag or something. */+  if (handle->tty.rd.read_line_buffer.len == 0) {+    uv_process_tty_read_raw_req(loop, handle, req);+  } else {+    uv_process_tty_read_line_req(loop, handle, req);+  }+}+++int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,+    uv_read_cb read_cb) {+  uv_loop_t* loop = handle->loop;++  if (!(handle->flags & UV_HANDLE_TTY_READABLE)) {+    return ERROR_INVALID_PARAMETER;+  }++  handle->flags |= UV_HANDLE_READING;+  INCREASE_ACTIVE_COUNT(loop, handle);+  handle->read_cb = read_cb;+  handle->alloc_cb = alloc_cb;++  /* If reading was stopped and then started again, there could still be a read+   * request pending. */+  if (handle->flags & UV_HANDLE_READ_PENDING) {+    return 0;+  }++  /* Maybe the user stopped reading half-way while processing key events.+   * Short-circuit if this could be the case. */+  if (handle->tty.rd.last_key_len > 0) {+    SET_REQ_SUCCESS(&handle->read_req);+    uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req);+    /* Make sure no attempt is made to insert it again until it's handled. */+    handle->flags |= UV_HANDLE_READ_PENDING;+    handle->reqs_pending++;+    return 0;+  }++  uv_tty_queue_read(loop, handle);++  return 0;+}+++int uv_tty_read_stop(uv_tty_t* handle) {+  INPUT_RECORD record;+  DWORD written, err;++  handle->flags &= ~UV_HANDLE_READING;+  DECREASE_ACTIVE_COUNT(handle->loop, handle);++  if (!(handle->flags & UV_HANDLE_READ_PENDING))+    return 0;++  if (handle->flags & UV_HANDLE_TTY_RAW) {+    /* Cancel raw read. Write some bullshit event to force the console wait to+     * return. */+    memset(&record, 0, sizeof record);+    record.EventType = FOCUS_EVENT;+    if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) {+      return GetLastError();+    }+  } else if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) {+    /* Cancel line-buffered read if not already pending */+    err = uv__cancel_read_console(handle);+    if (err)+      return err;++    handle->flags |= UV_HANDLE_CANCELLATION_PENDING;+  }++  return 0;+}++static int uv__cancel_read_console(uv_tty_t* handle) {+  HANDLE active_screen_buffer = INVALID_HANDLE_VALUE;+  INPUT_RECORD record;+  DWORD written;+  DWORD err = 0;+  LONG status;++  assert(!(handle->flags & UV_HANDLE_CANCELLATION_PENDING));++  /* Hold the output lock during the cancellation, to ensure that further+     writes don't interfere with the screen state. It will be the ReadConsole+     thread's responsibility to release the lock. */+  uv_sem_wait(&uv_tty_output_lock);+  status = InterlockedExchange(&uv__read_console_status, TRAP_REQUESTED);+  if (status != IN_PROGRESS) {+    /* Either we have managed to set a trap for the other thread before+       ReadConsole is called, or ReadConsole has returned because the user+       has pressed ENTER. In either case, there is nothing else to do. */+    uv_sem_post(&uv_tty_output_lock);+    return 0;+  }++  /* Save screen state before sending the VK_RETURN event */+  active_screen_buffer = CreateFileA("conout$",+                                     GENERIC_READ | GENERIC_WRITE,+                                     FILE_SHARE_READ | FILE_SHARE_WRITE,+                                     NULL,+                                     OPEN_EXISTING,+                                     FILE_ATTRIBUTE_NORMAL,+                                     NULL);++  if (active_screen_buffer != INVALID_HANDLE_VALUE &&+      GetConsoleScreenBufferInfo(active_screen_buffer,+                                 &uv__saved_screen_state)) {+    InterlockedOr(&uv__restore_screen_state, 1);+  }++  /* Write enter key event to force the console wait to return. */+  record.EventType = KEY_EVENT;+  record.Event.KeyEvent.bKeyDown = TRUE;+  record.Event.KeyEvent.wRepeatCount = 1;+  record.Event.KeyEvent.wVirtualKeyCode = VK_RETURN;+  record.Event.KeyEvent.wVirtualScanCode =+    MapVirtualKeyW(VK_RETURN, MAPVK_VK_TO_VSC);+  record.Event.KeyEvent.uChar.UnicodeChar = L'\r';+  record.Event.KeyEvent.dwControlKeyState = 0;+  if (!WriteConsoleInputW(handle->handle, &record, 1, &written))+    err = GetLastError();++  if (active_screen_buffer != INVALID_HANDLE_VALUE)+    CloseHandle(active_screen_buffer);++  return err;+}+++static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {+  uv_tty_virtual_width = info->dwSize.X;+  uv_tty_virtual_height = info->srWindow.Bottom - info->srWindow.Top + 1;++  /* Recompute virtual window offset row. */+  if (uv_tty_virtual_offset == -1) {+    uv_tty_virtual_offset = info->dwCursorPosition.Y;+  } else if (uv_tty_virtual_offset < info->dwCursorPosition.Y -+             uv_tty_virtual_height + 1) {+    /* If suddenly find the cursor outside of the virtual window, it must have+     * somehow scrolled. Update the virtual window offset. */+    uv_tty_virtual_offset = info->dwCursorPosition.Y -+                            uv_tty_virtual_height + 1;+  }+  if (uv_tty_virtual_offset + uv_tty_virtual_height > info->dwSize.Y) {+    uv_tty_virtual_offset = info->dwSize.Y - uv_tty_virtual_height;+  }+  if (uv_tty_virtual_offset < 0) {+    uv_tty_virtual_offset = 0;+  }+}+++static COORD uv_tty_make_real_coord(uv_tty_t* handle,+    CONSOLE_SCREEN_BUFFER_INFO* info, int x, unsigned char x_relative, int y,+    unsigned char y_relative) {+  COORD result;++  uv_tty_update_virtual_window(info);++  /* Adjust y position */+  if (y_relative) {+    y = info->dwCursorPosition.Y + y;+  } else {+    y = uv_tty_virtual_offset + y;+  }+  /* Clip y to virtual client rectangle */+  if (y < uv_tty_virtual_offset) {+    y = uv_tty_virtual_offset;+  } else if (y >= uv_tty_virtual_offset + uv_tty_virtual_height) {+    y = uv_tty_virtual_offset + uv_tty_virtual_height - 1;+  }++  /* Adjust x */+  if (x_relative) {+    x = info->dwCursorPosition.X + x;+  }+  /* Clip x */+  if (x < 0) {+    x = 0;+  } else if (x >= uv_tty_virtual_width) {+    x = uv_tty_virtual_width - 1;+  }++  result.X = (unsigned short) x;+  result.Y = (unsigned short) y;+  return result;+}+++static int uv_tty_emit_text(uv_tty_t* handle, WCHAR buffer[], DWORD length,+    DWORD* error) {+  DWORD written;++  if (*error != ERROR_SUCCESS) {+    return -1;+  }++  if (!WriteConsoleW(handle->handle,+                     (void*) buffer,+                     length,+                     &written,+                     NULL)) {+    *error = GetLastError();+    return -1;+  }++  return 0;+}+++static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative,+    int y, unsigned char y_relative, DWORD* error) {+  CONSOLE_SCREEN_BUFFER_INFO info;+  COORD pos;++  if (*error != ERROR_SUCCESS) {+    return -1;+  }++ retry:+  if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {+    *error = GetLastError();+  }++  pos = uv_tty_make_real_coord(handle, &info, x, x_relative, y, y_relative);++  if (!SetConsoleCursorPosition(handle->handle, pos)) {+    if (GetLastError() == ERROR_INVALID_PARAMETER) {+      /* The console may be resized - retry */+      goto retry;+    } else {+      *error = GetLastError();+      return -1;+    }+  }++  return 0;+}+++static int uv_tty_reset(uv_tty_t* handle, DWORD* error) {+  const COORD origin = {0, 0};+  const WORD char_attrs = uv_tty_default_text_attributes;+  CONSOLE_SCREEN_BUFFER_INFO info;+  DWORD count, written;++  if (*error != ERROR_SUCCESS) {+    return -1;+  }++  /* Reset original text attributes. */+  if (!SetConsoleTextAttribute(handle->handle, char_attrs)) {+    *error = GetLastError();+    return -1;+  }++  /* Move the cursor position to (0, 0). */+  if (!SetConsoleCursorPosition(handle->handle, origin)) {+    *error = GetLastError();+    return -1;+  }++  /* Clear the screen buffer. */+ retry:+  if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {+    *error = GetLastError();+    return -1;+  }++  count = info.dwSize.X * info.dwSize.Y;++  if (!(FillConsoleOutputCharacterW(handle->handle,+                                    L'\x20',+                                    count,+                                    origin,+                                    &written) &&+        FillConsoleOutputAttribute(handle->handle,+                                   char_attrs,+                                   written,+                                   origin,+                                   &written))) {+    if (GetLastError() == ERROR_INVALID_PARAMETER) {+      /* The console may be resized - retry */+      goto retry;+    } else {+      *error = GetLastError();+      return -1;+    }+  }++  /* Move the virtual window up to the top. */+  uv_tty_virtual_offset = 0;+  uv_tty_update_virtual_window(&info);++  return 0;+}+++static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen,+    DWORD* error) {+  CONSOLE_SCREEN_BUFFER_INFO info;+  COORD start, end;+  DWORD count, written;++  int x1, x2, y1, y2;+  int x1r, x2r, y1r, y2r;++  if (*error != ERROR_SUCCESS) {+    return -1;+  }++  if (dir == 0) {+    /* Clear from current position */+    x1 = 0;+    x1r = 1;+  } else {+    /* Clear from column 0 */+    x1 = 0;+    x1r = 0;+  }++  if (dir == 1) {+    /* Clear to current position */+    x2 = 0;+    x2r = 1;+  } else {+    /* Clear to end of row. We pretend the console is 65536 characters wide,+     * uv_tty_make_real_coord will clip it to the actual console width. */+    x2 = 0xffff;+    x2r = 0;+  }++  if (!entire_screen) {+    /* Stay on our own row */+    y1 = y2 = 0;+    y1r = y2r = 1;+  } else {+    /* Apply columns direction to row */+    y1 = x1;+    y1r = x1r;+    y2 = x2;+    y2r = x2r;+  }++ retry:+  if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {+    *error = GetLastError();+    return -1;+  }++  start = uv_tty_make_real_coord(handle, &info, x1, x1r, y1, y1r);+  end = uv_tty_make_real_coord(handle, &info, x2, x2r, y2, y2r);+  count = (end.Y * info.dwSize.X + end.X) -+          (start.Y * info.dwSize.X + start.X) + 1;++  if (!(FillConsoleOutputCharacterW(handle->handle,+                              L'\x20',+                              count,+                              start,+                              &written) &&+        FillConsoleOutputAttribute(handle->handle,+                                   info.wAttributes,+                                   written,+                                   start,+                                   &written))) {+    if (GetLastError() == ERROR_INVALID_PARAMETER) {+      /* The console may be resized - retry */+      goto retry;+    } else {+      *error = GetLastError();+      return -1;+    }+  }++  return 0;+}++#define FLIP_FGBG                                                             \+    do {                                                                      \+      WORD fg = info.wAttributes & 0xF;                                       \+      WORD bg = info.wAttributes & 0xF0;                                      \+      info.wAttributes &= 0xFF00;                                             \+      info.wAttributes |= fg << 4;                                            \+      info.wAttributes |= bg >> 4;                                            \+    } while (0)++static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) {+  unsigned short argc = handle->tty.wr.ansi_csi_argc;+  unsigned short* argv = handle->tty.wr.ansi_csi_argv;+  int i;+  CONSOLE_SCREEN_BUFFER_INFO info;++  char fg_color = -1, bg_color = -1;+  char fg_bright = -1, bg_bright = -1;+  char inverse = -1;++  if (argc == 0) {+    /* Reset mode */+    fg_color = uv_tty_default_fg_color;+    bg_color = uv_tty_default_bg_color;+    fg_bright = uv_tty_default_fg_bright;+    bg_bright = uv_tty_default_bg_bright;+    inverse = uv_tty_default_inverse;+  }++  for (i = 0; i < argc; i++) {+    short arg = argv[i];++    if (arg == 0) {+      /* Reset mode */+      fg_color = uv_tty_default_fg_color;+      bg_color = uv_tty_default_bg_color;+      fg_bright = uv_tty_default_fg_bright;+      bg_bright = uv_tty_default_bg_bright;+      inverse = uv_tty_default_inverse;++    } else if (arg == 1) {+      /* Foreground bright on */+      fg_bright = 1;++    } else if (arg == 2) {+      /* Both bright off */+      fg_bright = 0;+      bg_bright = 0;++    } else if (arg == 5) {+      /* Background bright on */+      bg_bright = 1;++    } else if (arg == 7) {+      /* Inverse: on */+      inverse = 1;++    } else if (arg == 21 || arg == 22) {+      /* Foreground bright off */+      fg_bright = 0;++    } else if (arg == 25) {+      /* Background bright off */+      bg_bright = 0;++    } else if (arg == 27) {+      /* Inverse: off */+      inverse = 0;++    } else if (arg >= 30 && arg <= 37) {+      /* Set foreground color */+      fg_color = arg - 30;++    } else if (arg == 39) {+      /* Default text color */+      fg_color = uv_tty_default_fg_color;+      fg_bright = uv_tty_default_fg_bright;++    } else if (arg >= 40 && arg <= 47) {+      /* Set background color */+      bg_color = arg - 40;++    } else if (arg ==  49) {+      /* Default background color */+      bg_color = uv_tty_default_bg_color;+      bg_bright = uv_tty_default_bg_bright;++    } else if (arg >= 90 && arg <= 97) {+      /* Set bold foreground color */+      fg_bright = 1;+      fg_color = arg - 90;++    } else if (arg >= 100 && arg <= 107) {+      /* Set bold background color */+      bg_bright = 1;+      bg_color = arg - 100;++    }+  }++  if (fg_color == -1 && bg_color == -1 && fg_bright == -1 &&+      bg_bright == -1 && inverse == -1) {+    /* Nothing changed */+    return 0;+  }++  if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {+    *error = GetLastError();+    return -1;+  }++  if ((info.wAttributes & COMMON_LVB_REVERSE_VIDEO) > 0) {+    FLIP_FGBG;+  }++  if (fg_color != -1) {+    info.wAttributes &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);+    if (fg_color & 1) info.wAttributes |= FOREGROUND_RED;+    if (fg_color & 2) info.wAttributes |= FOREGROUND_GREEN;+    if (fg_color & 4) info.wAttributes |= FOREGROUND_BLUE;+  }++  if (fg_bright != -1) {+    if (fg_bright) {+      info.wAttributes |= FOREGROUND_INTENSITY;+    } else {+      info.wAttributes &= ~FOREGROUND_INTENSITY;+    }+  }++  if (bg_color != -1) {+    info.wAttributes &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);+    if (bg_color & 1) info.wAttributes |= BACKGROUND_RED;+    if (bg_color & 2) info.wAttributes |= BACKGROUND_GREEN;+    if (bg_color & 4) info.wAttributes |= BACKGROUND_BLUE;+  }++  if (bg_bright != -1) {+    if (bg_bright) {+      info.wAttributes |= BACKGROUND_INTENSITY;+    } else {+      info.wAttributes &= ~BACKGROUND_INTENSITY;+    }+  }++  if (inverse != -1) {+    if (inverse) {+      info.wAttributes |= COMMON_LVB_REVERSE_VIDEO;+    } else {+      info.wAttributes &= ~COMMON_LVB_REVERSE_VIDEO;+    }+  }++  if ((info.wAttributes & COMMON_LVB_REVERSE_VIDEO) > 0) {+    FLIP_FGBG;+  }++  if (!SetConsoleTextAttribute(handle->handle, info.wAttributes)) {+    *error = GetLastError();+    return -1;+  }++  return 0;+}+++static int uv_tty_save_state(uv_tty_t* handle, unsigned char save_attributes,+    DWORD* error) {+  CONSOLE_SCREEN_BUFFER_INFO info;++  if (*error != ERROR_SUCCESS) {+    return -1;+  }++  if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {+    *error = GetLastError();+    return -1;+  }++  uv_tty_update_virtual_window(&info);++  handle->tty.wr.saved_position.X = info.dwCursorPosition.X;+  handle->tty.wr.saved_position.Y = info.dwCursorPosition.Y - uv_tty_virtual_offset;+  handle->flags |= UV_HANDLE_TTY_SAVED_POSITION;++  if (save_attributes) {+    handle->tty.wr.saved_attributes = info.wAttributes &+        (FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);+    handle->flags |= UV_HANDLE_TTY_SAVED_ATTRIBUTES;+  }++  return 0;+}+++static int uv_tty_restore_state(uv_tty_t* handle,+    unsigned char restore_attributes, DWORD* error) {+  CONSOLE_SCREEN_BUFFER_INFO info;+  WORD new_attributes;++  if (*error != ERROR_SUCCESS) {+    return -1;+  }++  if (handle->flags & UV_HANDLE_TTY_SAVED_POSITION) {+    if (uv_tty_move_caret(handle,+                          handle->tty.wr.saved_position.X,+                          0,+                          handle->tty.wr.saved_position.Y,+                          0,+                          error) != 0) {+      return -1;+    }+  }++  if (restore_attributes &&+      (handle->flags & UV_HANDLE_TTY_SAVED_ATTRIBUTES)) {+    if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {+      *error = GetLastError();+      return -1;+    }++    new_attributes = info.wAttributes;+    new_attributes &= ~(FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);+    new_attributes |= handle->tty.wr.saved_attributes;++    if (!SetConsoleTextAttribute(handle->handle, new_attributes)) {+      *error = GetLastError();+      return -1;+    }+  }++  return 0;+}++static int uv_tty_set_cursor_visibility(uv_tty_t* handle,+                                        BOOL visible,+                                        DWORD* error) {+  CONSOLE_CURSOR_INFO cursor_info;++  if (!GetConsoleCursorInfo(handle->handle, &cursor_info)) {+    *error = GetLastError();+    return -1;+  }++  cursor_info.bVisible = visible;++  if (!SetConsoleCursorInfo(handle->handle, &cursor_info)) {+    *error = GetLastError();+    return -1;+  }++  return 0;+}++static int uv_tty_write_bufs(uv_tty_t* handle,+                             const uv_buf_t bufs[],+                             unsigned int nbufs,+                             DWORD* error) {+  /* We can only write 8k characters at a time. Windows can't handle much more+   * characters in a single console write anyway. */+  WCHAR utf16_buf[MAX_CONSOLE_CHAR];+  WCHAR* utf16_buffer;+  DWORD utf16_buf_used = 0;+  unsigned int i, len, max_len, pos;+  int allocate = 0;++#define FLUSH_TEXT()                                                 \+  do {                                                               \+    pos = 0;                                                         \+    do {                                                             \+      len = utf16_buf_used - pos;                                    \+      if (len > MAX_CONSOLE_CHAR)                                    \+        len = MAX_CONSOLE_CHAR;                                      \+      uv_tty_emit_text(handle, &utf16_buffer[pos], len, error);      \+      pos += len;                                                    \+    } while (pos < utf16_buf_used);                                  \+    if (allocate) {                                                  \+      uv__free(utf16_buffer);                                        \+      allocate = 0;                                                  \+      utf16_buffer = utf16_buf;                                      \+    }                                                                \+    utf16_buf_used = 0;                                              \+ } while (0)++#define ENSURE_BUFFER_SPACE(wchars_needed)                          \+  if (wchars_needed > ARRAY_SIZE(utf16_buf) - utf16_buf_used) {     \+    FLUSH_TEXT();                                                   \+  }++  /* Cache for fast access */+  unsigned char utf8_bytes_left = handle->tty.wr.utf8_bytes_left;+  unsigned int utf8_codepoint = handle->tty.wr.utf8_codepoint;+  unsigned char previous_eol = handle->tty.wr.previous_eol;+  unsigned char ansi_parser_state = handle->tty.wr.ansi_parser_state;++  /* Store the error here. If we encounter an error, stop trying to do i/o but+   * keep parsing the buffer so we leave the parser in a consistent state. */+  *error = ERROR_SUCCESS;++  utf16_buffer = utf16_buf;++  uv_sem_wait(&uv_tty_output_lock);++  for (i = 0; i < nbufs; i++) {+    uv_buf_t buf = bufs[i];+    unsigned int j;++    if (uv__vterm_state == UV_SUPPORTED && buf.len > 0) {+      utf16_buf_used = MultiByteToWideChar(CP_UTF8,+                                           0,+                                           buf.base,+                                           buf.len,+                                           NULL,+                                           0);++      if (utf16_buf_used == 0) {+        *error = GetLastError();+        break;+      }++      max_len = (utf16_buf_used + 1) * sizeof(WCHAR);+      allocate = max_len > MAX_CONSOLE_CHAR;+      if (allocate)+        utf16_buffer = uv__malloc(max_len);+      if (!MultiByteToWideChar(CP_UTF8,+                               0,+                               buf.base,+                               buf.len,+                               utf16_buffer,+                               utf16_buf_used)) {+        if (allocate)+          uv__free(utf16_buffer);+        *error = GetLastError();+        break;+      }++      FLUSH_TEXT();++      continue;+    }++    for (j = 0; j < buf.len; j++) {+      unsigned char c = buf.base[j];++      /* Run the character through the utf8 decoder We happily accept non+       * shortest form encodings and invalid code points - there's no real harm+       * that can be done. */+      if (utf8_bytes_left == 0) {+        /* Read utf-8 start byte */+        DWORD first_zero_bit;+        unsigned char not_c = ~c;+#ifdef _MSC_VER /* msvc */+        if (_BitScanReverse(&first_zero_bit, not_c)) {+#else /* assume gcc */+        if (c != 0) {+          first_zero_bit = (sizeof(int) * 8) - 1 - __builtin_clz(not_c);+#endif+          if (first_zero_bit == 7) {+            /* Ascii - pass right through */+            utf8_codepoint = (unsigned int) c;++          } else if (first_zero_bit <= 5) {+            /* Multibyte sequence */+            utf8_codepoint = (0xff >> (8 - first_zero_bit)) & c;+            utf8_bytes_left = (char) (6 - first_zero_bit);++          } else {+            /* Invalid continuation */+            utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;+          }++        } else {+          /* 0xff -- invalid */+          utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;+        }++      } else if ((c & 0xc0) == 0x80) {+        /* Valid continuation of utf-8 multibyte sequence */+        utf8_bytes_left--;+        utf8_codepoint <<= 6;+        utf8_codepoint |= ((unsigned int) c & 0x3f);++      } else {+        /* Start byte where continuation was expected. */+        utf8_bytes_left = 0;+        utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;+        /* Patch buf offset so this character will be parsed again as a start+         * byte. */+        j--;+      }++      /* Maybe we need to parse more bytes to find a character. */+      if (utf8_bytes_left != 0) {+        continue;+      }++      /* Parse vt100/ansi escape codes */+      if (ansi_parser_state == ANSI_NORMAL) {+        switch (utf8_codepoint) {+          case '\033':+            ansi_parser_state = ANSI_ESCAPE_SEEN;+            continue;++          case 0233:+            ansi_parser_state = ANSI_CSI;+            handle->tty.wr.ansi_csi_argc = 0;+            continue;+        }++      } else if (ansi_parser_state == ANSI_ESCAPE_SEEN) {+        switch (utf8_codepoint) {+          case '[':+            ansi_parser_state = ANSI_CSI;+            handle->tty.wr.ansi_csi_argc = 0;+            continue;++          case '^':+          case '_':+          case 'P':+          case ']':+            /* Not supported, but we'll have to parse until we see a stop code,+             * e. g. ESC \ or BEL. */+            ansi_parser_state = ANSI_ST_CONTROL;+            continue;++          case '\033':+            /* Ignore double escape. */+            continue;++          case 'c':+            /* Full console reset. */+            FLUSH_TEXT();+            uv_tty_reset(handle, error);+            ansi_parser_state = ANSI_NORMAL;+            continue;++          case '7':+            /* Save the cursor position and text attributes. */+            FLUSH_TEXT();+            uv_tty_save_state(handle, 1, error);+            ansi_parser_state = ANSI_NORMAL;+            continue;++           case '8':+            /* Restore the cursor position and text attributes */+            FLUSH_TEXT();+            uv_tty_restore_state(handle, 1, error);+            ansi_parser_state = ANSI_NORMAL;+            continue;++          default:+            if (utf8_codepoint >= '@' && utf8_codepoint <= '_') {+              /* Single-char control. */+              ansi_parser_state = ANSI_NORMAL;+              continue;+            } else {+              /* Invalid - proceed as normal, */+              ansi_parser_state = ANSI_NORMAL;+            }+        }++      } else if (ansi_parser_state & ANSI_CSI) {+        if (!(ansi_parser_state & ANSI_IGNORE)) {+          if (utf8_codepoint >= '0' && utf8_codepoint <= '9') {+            /* Parsing a numerical argument */++            if (!(ansi_parser_state & ANSI_IN_ARG)) {+              /* We were not currently parsing a number */++              /* Check for too many arguments */+              if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) {+                ansi_parser_state |= ANSI_IGNORE;+                continue;+              }++              ansi_parser_state |= ANSI_IN_ARG;+              handle->tty.wr.ansi_csi_argc++;+              handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] =+                  (unsigned short) utf8_codepoint - '0';+              continue;+            } else {+              /* We were already parsing a number. Parse next digit. */+              uint32_t value = 10 *+                  handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1];++              /* Check for overflow. */+              if (value > UINT16_MAX) {+                ansi_parser_state |= ANSI_IGNORE;+                continue;+              }++               handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] =+                   (unsigned short) value + (utf8_codepoint - '0');+               continue;+            }++          } else if (utf8_codepoint == ';') {+            /* Denotes the end of an argument. */+            if (ansi_parser_state & ANSI_IN_ARG) {+              ansi_parser_state &= ~ANSI_IN_ARG;+              continue;++            } else {+              /* If ANSI_IN_ARG is not set, add another argument and default it+               * to 0. */++              /* Check for too many arguments */+              if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) {+                ansi_parser_state |= ANSI_IGNORE;+                continue;+              }++              handle->tty.wr.ansi_csi_argc++;+              handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = 0;+              continue;+            }++          } else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) &&+                     handle->tty.wr.ansi_csi_argc == 0) {+            /* Ignores '?' if it is the first character after CSI[. This is an+             * extension character from the VT100 codeset that is supported and+             * used by most ANSI terminals today. */+            continue;++          } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' &&+                     (handle->tty.wr.ansi_csi_argc > 0 || utf8_codepoint != '[')) {+            int x, y, d;++            /* Command byte */+            switch (utf8_codepoint) {+              case 'A':+                /* cursor up */+                FLUSH_TEXT();+                y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1);+                uv_tty_move_caret(handle, 0, 1, y, 1, error);+                break;++              case 'B':+                /* cursor down */+                FLUSH_TEXT();+                y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1;+                uv_tty_move_caret(handle, 0, 1, y, 1, error);+                break;++              case 'C':+                /* cursor forward */+                FLUSH_TEXT();+                x = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1;+                uv_tty_move_caret(handle, x, 1, 0, 1, error);+                break;++              case 'D':+                /* cursor back */+                FLUSH_TEXT();+                x = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1);+                uv_tty_move_caret(handle, x, 1, 0, 1, error);+                break;++              case 'E':+                /* cursor next line */+                FLUSH_TEXT();+                y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1;+                uv_tty_move_caret(handle, 0, 0, y, 1, error);+                break;++              case 'F':+                /* cursor previous line */+                FLUSH_TEXT();+                y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1);+                uv_tty_move_caret(handle, 0, 0, y, 1, error);+                break;++              case 'G':+                /* cursor horizontal move absolute */+                FLUSH_TEXT();+                x = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0])+                  ? handle->tty.wr.ansi_csi_argv[0] - 1 : 0;+                uv_tty_move_caret(handle, x, 0, 0, 1, error);+                break;++              case 'H':+              case 'f':+                /* cursor move absolute */+                FLUSH_TEXT();+                y = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0])+                  ? handle->tty.wr.ansi_csi_argv[0] - 1 : 0;+                x = (handle->tty.wr.ansi_csi_argc >= 2 && handle->tty.wr.ansi_csi_argv[1])+                  ? handle->tty.wr.ansi_csi_argv[1] - 1 : 0;+                uv_tty_move_caret(handle, x, 0, y, 0, error);+                break;++              case 'J':+                /* Erase screen */+                FLUSH_TEXT();+                d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0;+                if (d >= 0 && d <= 2) {+                  uv_tty_clear(handle, d, 1, error);+                }+                break;++              case 'K':+                /* Erase line */+                FLUSH_TEXT();+                d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0;+                if (d >= 0 && d <= 2) {+                  uv_tty_clear(handle, d, 0, error);+                }+                break;++              case 'm':+                /* Set style */+                FLUSH_TEXT();+                uv_tty_set_style(handle, error);+                break;++              case 's':+                /* Save the cursor position. */+                FLUSH_TEXT();+                uv_tty_save_state(handle, 0, error);+                break;++              case 'u':+                /* Restore the cursor position */+                FLUSH_TEXT();+                uv_tty_restore_state(handle, 0, error);+                break;++              case 'l':+                /* Hide the cursor */+                if (handle->tty.wr.ansi_csi_argc == 1 &&+                    handle->tty.wr.ansi_csi_argv[0] == 25) {+                  FLUSH_TEXT();+                  uv_tty_set_cursor_visibility(handle, 0, error);+                }+                break;++              case 'h':+                /* Show the cursor */+                if (handle->tty.wr.ansi_csi_argc == 1 &&+                    handle->tty.wr.ansi_csi_argv[0] == 25) {+                  FLUSH_TEXT();+                  uv_tty_set_cursor_visibility(handle, 1, error);+                }+                break;+            }++            /* Sequence ended - go back to normal state. */+            ansi_parser_state = ANSI_NORMAL;+            continue;++          } else {+            /* We don't support commands that use private mode characters or+             * intermediaries. Ignore the rest of the sequence. */+            ansi_parser_state |= ANSI_IGNORE;+            continue;+          }+        } else {+          /* We're ignoring this command. Stop only on command character. */+          if (utf8_codepoint >= '@' && utf8_codepoint <= '~') {+            ansi_parser_state = ANSI_NORMAL;+          }+          continue;+        }++      } else if (ansi_parser_state & ANSI_ST_CONTROL) {+        /* Unsupported control code.+         * Ignore everything until we see `BEL` or `ESC \`. */+        if (ansi_parser_state & ANSI_IN_STRING) {+          if (!(ansi_parser_state & ANSI_BACKSLASH_SEEN)) {+            if (utf8_codepoint == '"') {+              ansi_parser_state &= ~ANSI_IN_STRING;+            } else if (utf8_codepoint == '\\') {+              ansi_parser_state |= ANSI_BACKSLASH_SEEN;+            }+          } else {+            ansi_parser_state &= ~ANSI_BACKSLASH_SEEN;+          }+        } else {+          if (utf8_codepoint == '\007' || (utf8_codepoint == '\\' &&+              (ansi_parser_state & ANSI_ESCAPE_SEEN))) {+            /* End of sequence */+            ansi_parser_state = ANSI_NORMAL;+          } else if (utf8_codepoint == '\033') {+            /* Escape character */+            ansi_parser_state |= ANSI_ESCAPE_SEEN;+          } else if (utf8_codepoint == '"') {+             /* String starting */+            ansi_parser_state |= ANSI_IN_STRING;+            ansi_parser_state &= ~ANSI_ESCAPE_SEEN;+            ansi_parser_state &= ~ANSI_BACKSLASH_SEEN;+          } else {+            ansi_parser_state &= ~ANSI_ESCAPE_SEEN;+          }+        }+        continue;+      } else {+        /* Inconsistent state */+        abort();+      }++      /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the windows+       * console doesn't really support UTF-16, so just emit the replacement+       * character. */+      if (utf8_codepoint > 0xffff) {+        utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;+      }++      if (utf8_codepoint == 0x0a || utf8_codepoint == 0x0d) {+        /* EOL conversion - emit \r\n when we see \n. */++        if (utf8_codepoint == 0x0a && previous_eol != 0x0d) {+          /* \n was not preceded by \r; print \r\n. */+          ENSURE_BUFFER_SPACE(2);+          utf16_buf[utf16_buf_used++] = L'\r';+          utf16_buf[utf16_buf_used++] = L'\n';+        } else if (utf8_codepoint == 0x0d && previous_eol == 0x0a) {+          /* \n was followed by \r; do not print the \r, since the source was+           * either \r\n\r (so the second \r is redundant) or was \n\r (so the+           * \n was processed by the last case and an \r automatically+           * inserted). */+        } else {+          /* \r without \n; print \r as-is. */+          ENSURE_BUFFER_SPACE(1);+          utf16_buf[utf16_buf_used++] = (WCHAR) utf8_codepoint;+        }++        previous_eol = (char) utf8_codepoint;++      } else if (utf8_codepoint <= 0xffff) {+        /* Encode character into utf-16 buffer. */+        ENSURE_BUFFER_SPACE(1);+        utf16_buf[utf16_buf_used++] = (WCHAR) utf8_codepoint;+        previous_eol = 0;+      }+    }+  }++  /* Flush remaining characters */+  FLUSH_TEXT();++  /* Copy cached values back to struct. */+  handle->tty.wr.utf8_bytes_left = utf8_bytes_left;+  handle->tty.wr.utf8_codepoint = utf8_codepoint;+  handle->tty.wr.previous_eol = previous_eol;+  handle->tty.wr.ansi_parser_state = ansi_parser_state;++  uv_sem_post(&uv_tty_output_lock);++  if (*error == STATUS_SUCCESS) {+    return 0;+  } else {+    return -1;+  }++#undef FLUSH_TEXT+}+++int uv_tty_write(uv_loop_t* loop,+                 uv_write_t* req,+                 uv_tty_t* handle,+                 const uv_buf_t bufs[],+                 unsigned int nbufs,+                 uv_write_cb cb) {+  DWORD error;++  UV_REQ_INIT(req, UV_WRITE);+  req->handle = (uv_stream_t*) handle;+  req->cb = cb;++  handle->reqs_pending++;+  handle->stream.conn.write_reqs_pending++;+  REGISTER_HANDLE_REQ(loop, handle, req);++  req->u.io.queued_bytes = 0;++  if (!uv_tty_write_bufs(handle, bufs, nbufs, &error)) {+    SET_REQ_SUCCESS(req);+  } else {+    SET_REQ_ERROR(req, error);+  }++  uv_insert_pending_req(loop, (uv_req_t*) req);++  return 0;+}+++int uv__tty_try_write(uv_tty_t* handle,+                      const uv_buf_t bufs[],+                      unsigned int nbufs) {+  DWORD error;++  if (handle->stream.conn.write_reqs_pending > 0)+    return UV_EAGAIN;++  if (uv_tty_write_bufs(handle, bufs, nbufs, &error))+    return uv_translate_sys_error(error);++  return uv__count_bufs(bufs, nbufs);+}+++void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,+  uv_write_t* req) {+  int err;++  handle->write_queue_size -= req->u.io.queued_bytes;+  UNREGISTER_HANDLE_REQ(loop, handle, req);++  if (req->cb) {+    err = GET_REQ_ERROR(req);+    req->cb(req, uv_translate_sys_error(err));+  }++  handle->stream.conn.write_reqs_pending--;+  if (handle->stream.conn.shutdown_req != NULL &&+      handle->stream.conn.write_reqs_pending == 0) {+    uv_want_endgame(loop, (uv_handle_t*)handle);+  }++  DECREASE_PENDING_REQ_COUNT(handle);+}+++void uv_tty_close(uv_tty_t* handle) {+  assert(handle->u.fd == -1 || handle->u.fd > 2);+  if (handle->flags & UV_HANDLE_READING)+    uv_tty_read_stop(handle);++  if (handle->u.fd == -1)+    CloseHandle(handle->handle);+  else+    close(handle->u.fd);++  handle->u.fd = -1;+  handle->handle = INVALID_HANDLE_VALUE;+  handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);+  uv__handle_closing(handle);++  if (handle->reqs_pending == 0) {+    uv_want_endgame(handle->loop, (uv_handle_t*) handle);+  }+}+++void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {+  if (!(handle->flags & UV_HANDLE_TTY_READABLE) &&+      handle->stream.conn.shutdown_req != NULL &&+      handle->stream.conn.write_reqs_pending == 0) {+    UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req);++    /* TTY shutdown is really just a no-op */+    if (handle->stream.conn.shutdown_req->cb) {+      if (handle->flags & UV_HANDLE_CLOSING) {+        handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, UV_ECANCELED);+      } else {+        handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, 0);+      }+    }++    handle->stream.conn.shutdown_req = NULL;++    DECREASE_PENDING_REQ_COUNT(handle);+    return;+  }++  if (handle->flags & UV_HANDLE_CLOSING &&+      handle->reqs_pending == 0) {+    /* The wait handle used for raw reading should be unregistered when the+     * wait callback runs. */+    assert(!(handle->flags & UV_HANDLE_TTY_READABLE) ||+           handle->tty.rd.read_raw_wait == NULL);++    assert(!(handle->flags & UV_HANDLE_CLOSED));+    uv__handle_close(handle);+  }+}+++/*+ * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working+ * TODO: find a way to remove it+ */+void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,+    uv_req_t* raw_req) {+  abort();+}+++/*+ * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working+ * TODO: find a way to remove it+ */+void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,+    uv_connect_t* req) {+  abort();+}+++int uv_tty_reset_mode(void) {+  /* Not necessary to do anything. */+  return 0;+}++/* Determine whether or not this version of windows supports+ * proper ANSI color codes. Should be supported as of windows+ * 10 version 1511, build number 10.0.10586.+ */+static void uv__determine_vterm_state(HANDLE handle) {+  DWORD dwMode = 0;++  if (!GetConsoleMode(handle, &dwMode)) {+    uv__vterm_state = UV_UNSUPPORTED;+    return;+  }++  dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;+  if (!SetConsoleMode(handle, dwMode)) {+    uv__vterm_state = UV_UNSUPPORTED;+    return;+  }++  uv__vterm_state = UV_SUPPORTED;+}++static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) {+  CONSOLE_SCREEN_BUFFER_INFO sb_info;+  MSG msg;++  if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info))+    return 0;++  uv__tty_console_width = sb_info.dwSize.X;+  uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1;++  if (pSetWinEventHook == NULL)+    return 0;++  if (!pSetWinEventHook(EVENT_CONSOLE_LAYOUT,+                        EVENT_CONSOLE_LAYOUT,+                        NULL,+                        uv__tty_console_resize_event,+                        0,+                        0,+                        WINEVENT_OUTOFCONTEXT))+    return 0;++  while (GetMessage(&msg, NULL, 0, 0)) {+    TranslateMessage(&msg);+    DispatchMessage(&msg);+  }+  return 0;+}++static void CALLBACK uv__tty_console_resize_event(HWINEVENTHOOK hWinEventHook,+                                                  DWORD event,+                                                  HWND hwnd,+                                                  LONG idObject,+                                                  LONG idChild,+                                                  DWORD dwEventThread,+                                                  DWORD dwmsEventTime) {+  CONSOLE_SCREEN_BUFFER_INFO sb_info;+  int width, height;++  if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info))+    return;++  width = sb_info.dwSize.X;+  height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1;++  if (width != uv__tty_console_width || height != uv__tty_console_height) {+    uv__tty_console_width = width;+    uv__tty_console_height = height;+    uv__signal_dispatch(SIGWINCH);+  }+}
+ third_party/libuv/src/win/udp.c view
@@ -0,0 +1,962 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <stdlib.h>++#include "uv.h"+#include "internal.h"+#include "handle-inl.h"+#include "stream-inl.h"+#include "req-inl.h"+++/*+ * Threshold of active udp streams for which to preallocate udp read buffers.+ */+const unsigned int uv_active_udp_streams_threshold = 0;++/* A zero-size buffer for use by uv_udp_read */+static char uv_zero_[] = "";++int uv_udp_getsockname(const uv_udp_t* handle,+                       struct sockaddr* name,+                       int* namelen) {+  int result;++  if (handle->socket == INVALID_SOCKET) {+    return UV_EINVAL;+  }++  result = getsockname(handle->socket, name, namelen);+  if (result != 0) {+    return uv_translate_sys_error(WSAGetLastError());+  }++  return 0;+}+++static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,+    int family) {+  DWORD yes = 1;+  WSAPROTOCOL_INFOW info;+  int opt_len;++  if (handle->socket != INVALID_SOCKET)+    return UV_EBUSY;++  /* Set the socket to nonblocking mode */+  if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {+    return WSAGetLastError();+  }++  /* Make the socket non-inheritable */+  if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) {+    return GetLastError();+  }++  /* Associate it with the I/O completion port. Use uv_handle_t pointer as+   * completion key. */+  if (CreateIoCompletionPort((HANDLE)socket,+                             loop->iocp,+                             (ULONG_PTR)socket,+                             0) == NULL) {+    return GetLastError();+  }++  /* All known Windows that support SetFileCompletionNotificationModes have a+   * bug that makes it impossible to use this function in conjunction with+   * datagram sockets. We can work around that but only if the user is using+   * the default UDP driver (AFD) and has no other. LSPs stacked on top. Here+   * we check whether that is the case. */+  opt_len = (int) sizeof info;+  if (getsockopt(+          socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &info, &opt_len) ==+      SOCKET_ERROR) {+    return GetLastError();+  }++  if (info.ProtocolChain.ChainLen == 1) {+    if (SetFileCompletionNotificationModes(+            (HANDLE) socket,+            FILE_SKIP_SET_EVENT_ON_HANDLE |+                FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {+      handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;+      handle->func_wsarecv = uv_wsarecv_workaround;+      handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;+    } else if (GetLastError() != ERROR_INVALID_FUNCTION) {+      return GetLastError();+    }+  }++  handle->socket = socket;++  if (family == AF_INET6) {+    handle->flags |= UV_HANDLE_IPV6;+  } else {+    assert(!(handle->flags & UV_HANDLE_IPV6));+  }++  return 0;+}+++int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {+  int domain;++  /* Use the lower 8 bits for the domain */+  domain = flags & 0xFF;+  if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)+    return UV_EINVAL;++  if (flags & ~0xFF)+    return UV_EINVAL;++  uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP);+  handle->socket = INVALID_SOCKET;+  handle->reqs_pending = 0;+  handle->activecnt = 0;+  handle->func_wsarecv = WSARecv;+  handle->func_wsarecvfrom = WSARecvFrom;+  handle->send_queue_size = 0;+  handle->send_queue_count = 0;+  UV_REQ_INIT(&handle->recv_req, UV_UDP_RECV);+  handle->recv_req.data = handle;++  /* If anything fails beyond this point we need to remove the handle from+   * the handle queue, since it was added by uv__handle_init.+   */++  if (domain != AF_UNSPEC) {+    SOCKET sock;+    DWORD err;++    sock = socket(domain, SOCK_DGRAM, 0);+    if (sock == INVALID_SOCKET) {+      err = WSAGetLastError();+      QUEUE_REMOVE(&handle->handle_queue);+      return uv_translate_sys_error(err);+    }++    err = uv_udp_set_socket(handle->loop, handle, sock, domain);+    if (err) {+      closesocket(sock);+      QUEUE_REMOVE(&handle->handle_queue);+      return uv_translate_sys_error(err);+    }+  }++  return 0;+}+++int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {+  return uv_udp_init_ex(loop, handle, AF_UNSPEC);+}+++void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) {+  uv_udp_recv_stop(handle);+  closesocket(handle->socket);+  handle->socket = INVALID_SOCKET;++  uv__handle_closing(handle);++  if (handle->reqs_pending == 0) {+    uv_want_endgame(loop, (uv_handle_t*) handle);+  }+}+++void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {+  if (handle->flags & UV_HANDLE_CLOSING &&+      handle->reqs_pending == 0) {+    assert(!(handle->flags & UV_HANDLE_CLOSED));+    uv__handle_close(handle);+  }+}+++static int uv_udp_maybe_bind(uv_udp_t* handle,+                             const struct sockaddr* addr,+                             unsigned int addrlen,+                             unsigned int flags) {+  int r;+  int err;+  DWORD no = 0;++  if (handle->flags & UV_HANDLE_BOUND)+    return 0;++  if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) {+    /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */+    return ERROR_INVALID_PARAMETER;+  }++  if (handle->socket == INVALID_SOCKET) {+    SOCKET sock = socket(addr->sa_family, SOCK_DGRAM, 0);+    if (sock == INVALID_SOCKET) {+      return WSAGetLastError();+    }++    err = uv_udp_set_socket(handle->loop, handle, sock, addr->sa_family);+    if (err) {+      closesocket(sock);+      return err;+    }+  }++  if (flags & UV_UDP_REUSEADDR) {+    DWORD yes = 1;+    /* Set SO_REUSEADDR on the socket. */+    if (setsockopt(handle->socket,+                   SOL_SOCKET,+                   SO_REUSEADDR,+                   (char*) &yes,+                   sizeof yes) == SOCKET_ERROR) {+      err = WSAGetLastError();+      return err;+    }+  }++  if (addr->sa_family == AF_INET6)+    handle->flags |= UV_HANDLE_IPV6;++  if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {+    /* On windows IPV6ONLY is on by default. If the user doesn't specify it+     * libuv turns it off. */++    /* TODO: how to handle errors? This may fail if there is no ipv4 stack+     * available, or when run on XP/2003 which have no support for dualstack+     * sockets. For now we're silently ignoring the error. */+    setsockopt(handle->socket,+               IPPROTO_IPV6,+               IPV6_V6ONLY,+               (char*) &no,+               sizeof no);+  }++  r = bind(handle->socket, addr, addrlen);+  if (r == SOCKET_ERROR) {+    return WSAGetLastError();+  }++  handle->flags |= UV_HANDLE_BOUND;++  return 0;+}+++static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {+  uv_req_t* req;+  uv_buf_t buf;+  DWORD bytes, flags;+  int result;++  assert(handle->flags & UV_HANDLE_READING);+  assert(!(handle->flags & UV_HANDLE_READ_PENDING));++  req = &handle->recv_req;+  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));++  /*+   * Preallocate a read buffer if the number of active streams is below+   * the threshold.+  */+  if (loop->active_udp_streams < uv_active_udp_streams_threshold) {+    handle->flags &= ~UV_HANDLE_ZERO_READ;++    handle->recv_buffer = uv_buf_init(NULL, 0);+    handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->recv_buffer);+    if (handle->recv_buffer.base == NULL || handle->recv_buffer.len == 0) {+      handle->recv_cb(handle, UV_ENOBUFS, &handle->recv_buffer, NULL, 0);+      return;+    }+    assert(handle->recv_buffer.base != NULL);++    buf = handle->recv_buffer;+    memset(&handle->recv_from, 0, sizeof handle->recv_from);+    handle->recv_from_len = sizeof handle->recv_from;+    flags = 0;++    result = handle->func_wsarecvfrom(handle->socket,+                                      (WSABUF*) &buf,+                                      1,+                                      &bytes,+                                      &flags,+                                      (struct sockaddr*) &handle->recv_from,+                                      &handle->recv_from_len,+                                      &req->u.io.overlapped,+                                      NULL);++    if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {+      /* Process the req without IOCP. */+      handle->flags |= UV_HANDLE_READ_PENDING;+      req->u.io.overlapped.InternalHigh = bytes;+      handle->reqs_pending++;+      uv_insert_pending_req(loop, req);+    } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {+      /* The req will be processed with IOCP. */+      handle->flags |= UV_HANDLE_READ_PENDING;+      handle->reqs_pending++;+    } else {+      /* Make this req pending reporting an error. */+      SET_REQ_ERROR(req, WSAGetLastError());+      uv_insert_pending_req(loop, req);+      handle->reqs_pending++;+    }++  } else {+    handle->flags |= UV_HANDLE_ZERO_READ;++    buf.base = (char*) uv_zero_;+    buf.len = 0;+    flags = MSG_PEEK;++    result = handle->func_wsarecv(handle->socket,+                                  (WSABUF*) &buf,+                                  1,+                                  &bytes,+                                  &flags,+                                  &req->u.io.overlapped,+                                  NULL);++    if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {+      /* Process the req without IOCP. */+      handle->flags |= UV_HANDLE_READ_PENDING;+      req->u.io.overlapped.InternalHigh = bytes;+      handle->reqs_pending++;+      uv_insert_pending_req(loop, req);+    } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {+      /* The req will be processed with IOCP. */+      handle->flags |= UV_HANDLE_READ_PENDING;+      handle->reqs_pending++;+    } else {+      /* Make this req pending reporting an error. */+      SET_REQ_ERROR(req, WSAGetLastError());+      uv_insert_pending_req(loop, req);+      handle->reqs_pending++;+    }+  }+}+++int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,+    uv_udp_recv_cb recv_cb) {+  uv_loop_t* loop = handle->loop;+  int err;++  if (handle->flags & UV_HANDLE_READING) {+    return UV_EALREADY;+  }++  err = uv_udp_maybe_bind(handle,+                          (const struct sockaddr*) &uv_addr_ip4_any_,+                          sizeof(uv_addr_ip4_any_),+                          0);+  if (err)+    return uv_translate_sys_error(err);++  handle->flags |= UV_HANDLE_READING;+  INCREASE_ACTIVE_COUNT(loop, handle);+  loop->active_udp_streams++;++  handle->recv_cb = recv_cb;+  handle->alloc_cb = alloc_cb;++  /* If reading was stopped and then started again, there could still be a recv+   * request pending. */+  if (!(handle->flags & UV_HANDLE_READ_PENDING))+    uv_udp_queue_recv(loop, handle);++  return 0;+}+++int uv__udp_recv_stop(uv_udp_t* handle) {+  if (handle->flags & UV_HANDLE_READING) {+    handle->flags &= ~UV_HANDLE_READING;+    handle->loop->active_udp_streams--;+    DECREASE_ACTIVE_COUNT(loop, handle);+  }++  return 0;+}+++static int uv__send(uv_udp_send_t* req,+                    uv_udp_t* handle,+                    const uv_buf_t bufs[],+                    unsigned int nbufs,+                    const struct sockaddr* addr,+                    unsigned int addrlen,+                    uv_udp_send_cb cb) {+  uv_loop_t* loop = handle->loop;+  DWORD result, bytes;++  UV_REQ_INIT(req, UV_UDP_SEND);+  req->handle = handle;+  req->cb = cb;+  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));++  result = WSASendTo(handle->socket,+                     (WSABUF*)bufs,+                     nbufs,+                     &bytes,+                     0,+                     addr,+                     addrlen,+                     &req->u.io.overlapped,+                     NULL);++  if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {+    /* Request completed immediately. */+    req->u.io.queued_bytes = 0;+    handle->reqs_pending++;+    handle->send_queue_size += req->u.io.queued_bytes;+    handle->send_queue_count++;+    REGISTER_HANDLE_REQ(loop, handle, req);+    uv_insert_pending_req(loop, (uv_req_t*)req);+  } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {+    /* Request queued by the kernel. */+    req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs);+    handle->reqs_pending++;+    handle->send_queue_size += req->u.io.queued_bytes;+    handle->send_queue_count++;+    REGISTER_HANDLE_REQ(loop, handle, req);+  } else {+    /* Send failed due to an error. */+    return WSAGetLastError();+  }++  return 0;+}+++void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,+    uv_req_t* req) {+  uv_buf_t buf;+  int partial;++  assert(handle->type == UV_UDP);++  handle->flags &= ~UV_HANDLE_READ_PENDING;++  if (!REQ_SUCCESS(req)) {+    DWORD err = GET_REQ_SOCK_ERROR(req);+    if (err == WSAEMSGSIZE) {+      /* Not a real error, it just indicates that the received packet was+       * bigger than the receive buffer. */+    } else if (err == WSAECONNRESET || err == WSAENETRESET) {+      /* A previous sendto operation failed; ignore this error. If zero-reading+       * we need to call WSARecv/WSARecvFrom _without_ the. MSG_PEEK flag to+       * clear out the error queue. For nonzero reads, immediately queue a new+       * receive. */+      if (!(handle->flags & UV_HANDLE_ZERO_READ)) {+        goto done;+      }+    } else {+      /* A real error occurred. Report the error to the user only if we're+       * currently reading. */+      if (handle->flags & UV_HANDLE_READING) {+        uv_udp_recv_stop(handle);+        buf = (handle->flags & UV_HANDLE_ZERO_READ) ?+              uv_buf_init(NULL, 0) : handle->recv_buffer;+        handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0);+      }+      goto done;+    }+  }++  if (!(handle->flags & UV_HANDLE_ZERO_READ)) {+    /* Successful read */+    partial = !REQ_SUCCESS(req);+    handle->recv_cb(handle,+                    req->u.io.overlapped.InternalHigh,+                    &handle->recv_buffer,+                    (const struct sockaddr*) &handle->recv_from,+                    partial ? UV_UDP_PARTIAL : 0);+  } else if (handle->flags & UV_HANDLE_READING) {+    DWORD bytes, err, flags;+    struct sockaddr_storage from;+    int from_len;++    /* Do a nonblocking receive.+     * TODO: try to read multiple datagrams at once. FIONREAD maybe? */+    buf = uv_buf_init(NULL, 0);+    handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);+    if (buf.base == NULL || buf.len == 0) {+      handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0);+      goto done;+    }+    assert(buf.base != NULL);++    memset(&from, 0, sizeof from);+    from_len = sizeof from;++    flags = 0;++    if (WSARecvFrom(handle->socket,+                    (WSABUF*)&buf,+                    1,+                    &bytes,+                    &flags,+                    (struct sockaddr*) &from,+                    &from_len,+                    NULL,+                    NULL) != SOCKET_ERROR) {++      /* Message received */+      handle->recv_cb(handle, bytes, &buf, (const struct sockaddr*) &from, 0);+    } else {+      err = WSAGetLastError();+      if (err == WSAEMSGSIZE) {+        /* Message truncated */+        handle->recv_cb(handle,+                        bytes,+                        &buf,+                        (const struct sockaddr*) &from,+                        UV_UDP_PARTIAL);+      } else if (err == WSAEWOULDBLOCK) {+        /* Kernel buffer empty */+        handle->recv_cb(handle, 0, &buf, NULL, 0);+      } else if (err == WSAECONNRESET || err == WSAENETRESET) {+        /* WSAECONNRESET/WSANETRESET is ignored because this just indicates+         * that a previous sendto operation failed.+         */+        handle->recv_cb(handle, 0, &buf, NULL, 0);+      } else {+        /* Any other error that we want to report back to the user. */+        uv_udp_recv_stop(handle);+        handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0);+      }+    }+  }++done:+  /* Post another read if still reading and not closing. */+  if ((handle->flags & UV_HANDLE_READING) &&+      !(handle->flags & UV_HANDLE_READ_PENDING)) {+    uv_udp_queue_recv(loop, handle);+  }++  DECREASE_PENDING_REQ_COUNT(handle);+}+++void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,+    uv_udp_send_t* req) {+  int err;++  assert(handle->type == UV_UDP);++  assert(handle->send_queue_size >= req->u.io.queued_bytes);+  assert(handle->send_queue_count >= 1);+  handle->send_queue_size -= req->u.io.queued_bytes;+  handle->send_queue_count--;++  UNREGISTER_HANDLE_REQ(loop, handle, req);++  if (req->cb) {+    err = 0;+    if (!REQ_SUCCESS(req)) {+      err = GET_REQ_SOCK_ERROR(req);+    }+    req->cb(req, uv_translate_sys_error(err));+  }++  DECREASE_PENDING_REQ_COUNT(handle);+}+++static int uv__udp_set_membership4(uv_udp_t* handle,+                                   const struct sockaddr_in* multicast_addr,+                                   const char* interface_addr,+                                   uv_membership membership) {+  int err;+  int optname;+  struct ip_mreq mreq;++  if (handle->flags & UV_HANDLE_IPV6)+    return UV_EINVAL;++  /* If the socket is unbound, bind to inaddr_any. */+  err = uv_udp_maybe_bind(handle,+                          (const struct sockaddr*) &uv_addr_ip4_any_,+                          sizeof(uv_addr_ip4_any_),+                          UV_UDP_REUSEADDR);+  if (err)+    return uv_translate_sys_error(err);++  memset(&mreq, 0, sizeof mreq);++  if (interface_addr) {+    err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);+    if (err)+      return err;+  } else {+    mreq.imr_interface.s_addr = htonl(INADDR_ANY);+  }++  mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;++  switch (membership) {+    case UV_JOIN_GROUP:+      optname = IP_ADD_MEMBERSHIP;+      break;+    case UV_LEAVE_GROUP:+      optname = IP_DROP_MEMBERSHIP;+      break;+    default:+      return UV_EINVAL;+  }++  if (setsockopt(handle->socket,+                 IPPROTO_IP,+                 optname,+                 (char*) &mreq,+                 sizeof mreq) == SOCKET_ERROR) {+    return uv_translate_sys_error(WSAGetLastError());+  }++  return 0;+}+++int uv__udp_set_membership6(uv_udp_t* handle,+                            const struct sockaddr_in6* multicast_addr,+                            const char* interface_addr,+                            uv_membership membership) {+  int optname;+  int err;+  struct ipv6_mreq mreq;+  struct sockaddr_in6 addr6;++  if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6))+    return UV_EINVAL;++  err = uv_udp_maybe_bind(handle,+                          (const struct sockaddr*) &uv_addr_ip6_any_,+                          sizeof(uv_addr_ip6_any_),+                          UV_UDP_REUSEADDR);++  if (err)+    return uv_translate_sys_error(err);++  memset(&mreq, 0, sizeof(mreq));++  if (interface_addr) {+    if (uv_ip6_addr(interface_addr, 0, &addr6))+      return UV_EINVAL;+    mreq.ipv6mr_interface = addr6.sin6_scope_id;+  } else {+    mreq.ipv6mr_interface = 0;+  }++  mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr;++  switch (membership) {+  case UV_JOIN_GROUP:+    optname = IPV6_ADD_MEMBERSHIP;+    break;+  case UV_LEAVE_GROUP:+    optname = IPV6_DROP_MEMBERSHIP;+    break;+  default:+    return UV_EINVAL;+  }++  if (setsockopt(handle->socket,+                 IPPROTO_IPV6,+                 optname,+                 (char*) &mreq,+                 sizeof mreq) == SOCKET_ERROR) {+    return uv_translate_sys_error(WSAGetLastError());+  }++  return 0;+}+++int uv_udp_set_membership(uv_udp_t* handle,+                          const char* multicast_addr,+                          const char* interface_addr,+                          uv_membership membership) {+  struct sockaddr_in addr4;+  struct sockaddr_in6 addr6;++  if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0)+    return uv__udp_set_membership4(handle, &addr4, interface_addr, membership);+  else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0)+    return uv__udp_set_membership6(handle, &addr6, interface_addr, membership);+  else+    return UV_EINVAL;+}+++int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {+  struct sockaddr_storage addr_st;+  struct sockaddr_in* addr4;+  struct sockaddr_in6* addr6;++  addr4 = (struct sockaddr_in*) &addr_st;+  addr6 = (struct sockaddr_in6*) &addr_st;++  if (!interface_addr) {+    memset(&addr_st, 0, sizeof addr_st);+    if (handle->flags & UV_HANDLE_IPV6) {+      addr_st.ss_family = AF_INET6;+      addr6->sin6_scope_id = 0;+    } else {+      addr_st.ss_family = AF_INET;+      addr4->sin_addr.s_addr = htonl(INADDR_ANY);+    }+  } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) {+    /* nothing, address was parsed */+  } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) {+    /* nothing, address was parsed */+  } else {+    return UV_EINVAL;+  }++  if (handle->socket == INVALID_SOCKET)+    return UV_EBADF;++  if (addr_st.ss_family == AF_INET) {+    if (setsockopt(handle->socket,+                   IPPROTO_IP,+                   IP_MULTICAST_IF,+                   (char*) &addr4->sin_addr,+                   sizeof(addr4->sin_addr)) == SOCKET_ERROR) {+      return uv_translate_sys_error(WSAGetLastError());+    }+  } else if (addr_st.ss_family == AF_INET6) {+    if (setsockopt(handle->socket,+                   IPPROTO_IPV6,+                   IPV6_MULTICAST_IF,+                   (char*) &addr6->sin6_scope_id,+                   sizeof(addr6->sin6_scope_id)) == SOCKET_ERROR) {+      return uv_translate_sys_error(WSAGetLastError());+    }+  } else {+    assert(0 && "unexpected address family");+    abort();+  }++  return 0;+}+++int uv_udp_set_broadcast(uv_udp_t* handle, int value) {+  BOOL optval = (BOOL) value;++  if (handle->socket == INVALID_SOCKET)+    return UV_EBADF;++  if (setsockopt(handle->socket,+                 SOL_SOCKET,+                 SO_BROADCAST,+                 (char*) &optval,+                 sizeof optval)) {+    return uv_translate_sys_error(WSAGetLastError());+  }++  return 0;+}+++int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {+  WSAPROTOCOL_INFOW protocol_info;+  int opt_len;+  int err;++  /* Detect the address family of the socket. */+  opt_len = (int) sizeof protocol_info;+  if (getsockopt(sock,+                 SOL_SOCKET,+                 SO_PROTOCOL_INFOW,+                 (char*) &protocol_info,+                 &opt_len) == SOCKET_ERROR) {+    return uv_translate_sys_error(GetLastError());+  }++  err = uv_udp_set_socket(handle->loop,+                          handle,+                          sock,+                          protocol_info.iAddressFamily);+  return uv_translate_sys_error(err);+}+++#define SOCKOPT_SETTER(name, option4, option6, validate)                      \+  int uv_udp_set_##name(uv_udp_t* handle, int value) {                        \+    DWORD optval = (DWORD) value;                                             \+                                                                              \+    if (!(validate(value))) {                                                 \+      return UV_EINVAL;                                                       \+    }                                                                         \+                                                                              \+    if (handle->socket == INVALID_SOCKET)                                     \+      return UV_EBADF;                                                        \+                                                                              \+    if (!(handle->flags & UV_HANDLE_IPV6)) {                                  \+      /* Set IPv4 socket option */                                            \+      if (setsockopt(handle->socket,                                          \+                     IPPROTO_IP,                                              \+                     option4,                                                 \+                     (char*) &optval,                                         \+                     sizeof optval)) {                                        \+        return uv_translate_sys_error(WSAGetLastError());                     \+      }                                                                       \+    } else {                                                                  \+      /* Set IPv6 socket option */                                            \+      if (setsockopt(handle->socket,                                          \+                     IPPROTO_IPV6,                                            \+                     option6,                                                 \+                     (char*) &optval,                                         \+                     sizeof optval)) {                                        \+        return uv_translate_sys_error(WSAGetLastError());                     \+      }                                                                       \+    }                                                                         \+    return 0;                                                                 \+  }++#define VALIDATE_TTL(value) ((value) >= 1 && (value) <= 255)+#define VALIDATE_MULTICAST_TTL(value) ((value) >= -1 && (value) <= 255)+#define VALIDATE_MULTICAST_LOOP(value) (1)++SOCKOPT_SETTER(ttl,+               IP_TTL,+               IPV6_HOPLIMIT,+               VALIDATE_TTL)+SOCKOPT_SETTER(multicast_ttl,+               IP_MULTICAST_TTL,+               IPV6_MULTICAST_HOPS,+               VALIDATE_MULTICAST_TTL)+SOCKOPT_SETTER(multicast_loop,+               IP_MULTICAST_LOOP,+               IPV6_MULTICAST_LOOP,+               VALIDATE_MULTICAST_LOOP)++#undef SOCKOPT_SETTER+#undef VALIDATE_TTL+#undef VALIDATE_MULTICAST_TTL+#undef VALIDATE_MULTICAST_LOOP+++/* This function is an egress point, i.e. it returns libuv errors rather than+ * system errors.+ */+int uv__udp_bind(uv_udp_t* handle,+                 const struct sockaddr* addr,+                 unsigned int addrlen,+                 unsigned int flags) {+  int err;++  err = uv_udp_maybe_bind(handle, addr, addrlen, flags);+  if (err)+    return uv_translate_sys_error(err);++  return 0;+}+++/* This function is an egress point, i.e. it returns libuv errors rather than+ * system errors.+ */+int uv__udp_send(uv_udp_send_t* req,+                 uv_udp_t* handle,+                 const uv_buf_t bufs[],+                 unsigned int nbufs,+                 const struct sockaddr* addr,+                 unsigned int addrlen,+                 uv_udp_send_cb send_cb) {+  const struct sockaddr* bind_addr;+  int err;++  if (!(handle->flags & UV_HANDLE_BOUND)) {+    if (addrlen == sizeof(uv_addr_ip4_any_))+      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;+    else if (addrlen == sizeof(uv_addr_ip6_any_))+      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;+    else+      return UV_EINVAL;+    err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);+    if (err)+      return uv_translate_sys_error(err);+  }++  err = uv__send(req, handle, bufs, nbufs, addr, addrlen, send_cb);+  if (err)+    return uv_translate_sys_error(err);++  return 0;+}+++int uv__udp_try_send(uv_udp_t* handle,+                     const uv_buf_t bufs[],+                     unsigned int nbufs,+                     const struct sockaddr* addr,+                     unsigned int addrlen) {+  DWORD bytes;+  const struct sockaddr* bind_addr;+  struct sockaddr_storage converted;+  int err;++  assert(nbufs > 0);++  err = uv__convert_to_localhost_if_unspecified(addr, &converted);+  if (err)+    return err;++  /* Already sending a message.*/+  if (handle->send_queue_count != 0)+    return UV_EAGAIN;++  if (!(handle->flags & UV_HANDLE_BOUND)) {+    if (addrlen == sizeof(uv_addr_ip4_any_))+      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;+    else if (addrlen == sizeof(uv_addr_ip6_any_))+      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;+    else+      return UV_EINVAL;+    err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);+    if (err)+      return uv_translate_sys_error(err);+  }++  err = WSASendTo(handle->socket,+                  (WSABUF*)bufs,+                  nbufs,+                  &bytes,+                  0,+                  (const struct sockaddr*) &converted,+                  addrlen,+                  NULL,+                  NULL);++  if (err)+    return uv_translate_sys_error(WSAGetLastError());++  return bytes;+}
+ third_party/libuv/src/win/util.c view
@@ -0,0 +1,1780 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <direct.h>+#include <limits.h>+#include <stdio.h>+#include <string.h>+#include <time.h>+#include <wchar.h>++#include "uv.h"+#include "internal.h"++#include <winsock2.h>+#include <winperf.h>+#include <iphlpapi.h>+#include <psapi.h>+#include <tlhelp32.h>+#include <windows.h>+#include <userenv.h>+#include <math.h>++/*+ * Max title length; the only thing MSDN tells us about the maximum length+ * of the console title is that it is smaller than 64K. However in practice+ * it is much smaller, and there is no way to figure out what the exact length+ * of the title is or can be, at least not on XP. To make it even more+ * annoying, GetConsoleTitle fails when the buffer to be read into is bigger+ * than the actual maximum length. So we make a conservative guess here;+ * just don't put the novel you're writing in the title, unless the plot+ * survives truncation.+ */+#define MAX_TITLE_LENGTH 8192++/* The number of nanoseconds in one second. */+#define UV__NANOSEC 1000000000++/* Max user name length, from iphlpapi.h */+#ifndef UNLEN+# define UNLEN 256+#endif+++/* Maximum environment variable size, including the terminating null */+#define MAX_ENV_VAR_LENGTH 32767++/* Cached copy of the process title, plus a mutex guarding it. */+static char *process_title;+static CRITICAL_SECTION process_title_lock;++/* Interval (in seconds) of the high-resolution clock. */+static double hrtime_interval_ = 0;+++/*+ * One-time initialization code for functionality defined in util.c.+ */+void uv__util_init(void) {+  LARGE_INTEGER perf_frequency;++  /* Initialize process title access mutex. */+  InitializeCriticalSection(&process_title_lock);++  /* Retrieve high-resolution timer frequency+   * and precompute its reciprocal.+   */+  if (QueryPerformanceFrequency(&perf_frequency)) {+    hrtime_interval_ = 1.0 / perf_frequency.QuadPart;+  } else {+    hrtime_interval_= 0;+  }+}+++int uv_exepath(char* buffer, size_t* size_ptr) {+  int utf8_len, utf16_buffer_len, utf16_len;+  WCHAR* utf16_buffer;+  int err;++  if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) {+    return UV_EINVAL;+  }++  if (*size_ptr > 32768) {+    /* Windows paths can never be longer than this. */+    utf16_buffer_len = 32768;+  } else {+    utf16_buffer_len = (int) *size_ptr;+  }++  utf16_buffer = (WCHAR*) uv__malloc(sizeof(WCHAR) * utf16_buffer_len);+  if (!utf16_buffer) {+    return UV_ENOMEM;+  }++  /* Get the path as UTF-16. */+  utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len);+  if (utf16_len <= 0) {+    err = GetLastError();+    goto error;+  }++  /* utf16_len contains the length, *not* including the terminating null. */+  utf16_buffer[utf16_len] = L'\0';++  /* Convert to UTF-8 */+  utf8_len = WideCharToMultiByte(CP_UTF8,+                                 0,+                                 utf16_buffer,+                                 -1,+                                 buffer,+                                 (int) *size_ptr,+                                 NULL,+                                 NULL);+  if (utf8_len == 0) {+    err = GetLastError();+    goto error;+  }++  uv__free(utf16_buffer);++  /* utf8_len *does* include the terminating null at this point, but the+   * returned size shouldn't. */+  *size_ptr = utf8_len - 1;+  return 0;++ error:+  uv__free(utf16_buffer);+  return uv_translate_sys_error(err);+}+++int uv_cwd(char* buffer, size_t* size) {+  DWORD utf16_len;+  WCHAR utf16_buffer[MAX_PATH];+  int r;++  if (buffer == NULL || size == NULL) {+    return UV_EINVAL;+  }++  utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);+  if (utf16_len == 0) {+    return uv_translate_sys_error(GetLastError());+  } else if (utf16_len > MAX_PATH) {+    /* This should be impossible; however the CRT has a code path to deal with+     * this scenario, so I added a check anyway. */+    return UV_EIO;+  }++  /* utf16_len contains the length, *not* including the terminating null. */+  utf16_buffer[utf16_len] = L'\0';++  /* The returned directory should not have a trailing slash, unless it points+   * at a drive root, like c:\. Remove it if needed. */+  if (utf16_buffer[utf16_len - 1] == L'\\' &&+      !(utf16_len == 3 && utf16_buffer[1] == L':')) {+    utf16_len--;+    utf16_buffer[utf16_len] = L'\0';+  }++  /* Check how much space we need */+  r = WideCharToMultiByte(CP_UTF8,+                          0,+                          utf16_buffer,+                          -1,+                          NULL,+                          0,+                          NULL,+                          NULL);+  if (r == 0) {+    return uv_translate_sys_error(GetLastError());+  } else if (r > (int) *size) {+    *size = r;+    return UV_ENOBUFS;+  }++  /* Convert to UTF-8 */+  r = WideCharToMultiByte(CP_UTF8,+                          0,+                          utf16_buffer,+                          -1,+                          buffer,+                          *size > INT_MAX ? INT_MAX : (int) *size,+                          NULL,+                          NULL);+  if (r == 0) {+    return uv_translate_sys_error(GetLastError());+  }++  *size = r - 1;+  return 0;+}+++int uv_chdir(const char* dir) {+  WCHAR utf16_buffer[MAX_PATH];+  size_t utf16_len;+  WCHAR drive_letter, env_var[4];++  if (dir == NULL) {+    return UV_EINVAL;+  }++  if (MultiByteToWideChar(CP_UTF8,+                          0,+                          dir,+                          -1,+                          utf16_buffer,+                          MAX_PATH) == 0) {+    DWORD error = GetLastError();+    /* The maximum length of the current working directory is 260 chars,+     * including terminating null. If it doesn't fit, the path name must be too+     * long. */+    if (error == ERROR_INSUFFICIENT_BUFFER) {+      return UV_ENAMETOOLONG;+    } else {+      return uv_translate_sys_error(error);+    }+  }++  if (!SetCurrentDirectoryW(utf16_buffer)) {+    return uv_translate_sys_error(GetLastError());+  }++  /* Windows stores the drive-local path in an "hidden" environment variable,+   * which has the form "=C:=C:\Windows". SetCurrentDirectory does not update+   * this, so we'll have to do it. */+  utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);+  if (utf16_len == 0) {+    return uv_translate_sys_error(GetLastError());+  } else if (utf16_len > MAX_PATH) {+    return UV_EIO;+  }++  /* The returned directory should not have a trailing slash, unless it points+   * at a drive root, like c:\. Remove it if needed. */+  if (utf16_buffer[utf16_len - 1] == L'\\' &&+      !(utf16_len == 3 && utf16_buffer[1] == L':')) {+    utf16_len--;+    utf16_buffer[utf16_len] = L'\0';+  }++  if (utf16_len < 2 || utf16_buffer[1] != L':') {+    /* Doesn't look like a drive letter could be there - probably an UNC path.+     * TODO: Need to handle win32 namespaces like \\?\C:\ ? */+    drive_letter = 0;+  } else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {+    drive_letter = utf16_buffer[0];+  } else if (utf16_buffer[0] >= L'a' && utf16_buffer[0] <= L'z') {+    /* Convert to uppercase. */+    drive_letter = utf16_buffer[0] - L'a' + L'A';+  } else {+    /* Not valid. */+    drive_letter = 0;+  }++  if (drive_letter != 0) {+    /* Construct the environment variable name and set it. */+    env_var[0] = L'=';+    env_var[1] = drive_letter;+    env_var[2] = L':';+    env_var[3] = L'\0';++    if (!SetEnvironmentVariableW(env_var, utf16_buffer)) {+      return uv_translate_sys_error(GetLastError());+    }+  }++  return 0;+}+++void uv_loadavg(double avg[3]) {+  /* Can't be implemented */+  avg[0] = avg[1] = avg[2] = 0;+}+++uint64_t uv_get_free_memory(void) {+  MEMORYSTATUSEX memory_status;+  memory_status.dwLength = sizeof(memory_status);++  if (!GlobalMemoryStatusEx(&memory_status)) {+     return -1;+  }++  return (uint64_t)memory_status.ullAvailPhys;+}+++uint64_t uv_get_total_memory(void) {+  MEMORYSTATUSEX memory_status;+  memory_status.dwLength = sizeof(memory_status);++  if (!GlobalMemoryStatusEx(&memory_status)) {+    return -1;+  }++  return (uint64_t)memory_status.ullTotalPhys;+}+++uv_pid_t uv_os_getpid(void) {+  return GetCurrentProcessId();+}+++uv_pid_t uv_os_getppid(void) {+  int parent_pid = -1;+  HANDLE handle;+  PROCESSENTRY32 pe;+  DWORD current_pid = GetCurrentProcessId();++  pe.dwSize = sizeof(PROCESSENTRY32);+  handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);++  if (Process32First(handle, &pe)) {+    do {+      if (pe.th32ProcessID == current_pid) {+        parent_pid = pe.th32ParentProcessID;+        break;+      }+    } while( Process32Next(handle, &pe));+  }++  CloseHandle(handle);+  return parent_pid;+}+++char** uv_setup_args(int argc, char** argv) {+  return argv;+}+++int uv_set_process_title(const char* title) {+  int err;+  int length;+  WCHAR* title_w = NULL;++  uv__once_init();++  /* Find out how big the buffer for the wide-char title must be */+  length = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0);+  if (!length) {+    err = GetLastError();+    goto done;+  }++  /* Convert to wide-char string */+  title_w = (WCHAR*)uv__malloc(sizeof(WCHAR) * length);+  if (!title_w) {+    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");+  }++  length = MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, length);+  if (!length) {+    err = GetLastError();+    goto done;+  }++  /* If the title must be truncated insert a \0 terminator there */+  if (length > MAX_TITLE_LENGTH) {+    title_w[MAX_TITLE_LENGTH - 1] = L'\0';+  }++  if (!SetConsoleTitleW(title_w)) {+    err = GetLastError();+    goto done;+  }++  EnterCriticalSection(&process_title_lock);+  uv__free(process_title);+  process_title = uv__strdup(title);+  LeaveCriticalSection(&process_title_lock);++  err = 0;++done:+  uv__free(title_w);+  return uv_translate_sys_error(err);+}+++static int uv__get_process_title(void) {+  WCHAR title_w[MAX_TITLE_LENGTH];++  if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) {+    return -1;+  }++  if (uv__convert_utf16_to_utf8(title_w, -1, &process_title) != 0)+    return -1;++  return 0;+}+++int uv_get_process_title(char* buffer, size_t size) {+  size_t len;++  if (buffer == NULL || size == 0)+    return UV_EINVAL;++  uv__once_init();++  EnterCriticalSection(&process_title_lock);+  /*+   * If the process_title was never read before nor explicitly set,+   * we must query it with getConsoleTitleW+   */+  if (!process_title && uv__get_process_title() == -1) {+    LeaveCriticalSection(&process_title_lock);+    return uv_translate_sys_error(GetLastError());+  }++  assert(process_title);+  len = strlen(process_title) + 1;++  if (size < len) {+    LeaveCriticalSection(&process_title_lock);+    return UV_ENOBUFS;+  }++  memcpy(buffer, process_title, len);+  LeaveCriticalSection(&process_title_lock);++  return 0;+}+++uint64_t uv_hrtime(void) {+  uv__once_init();+  return uv__hrtime(UV__NANOSEC);+}++uint64_t uv__hrtime(double scale) {+  LARGE_INTEGER counter;++  /* If the performance interval is zero, there's no support. */+  if (hrtime_interval_ == 0) {+    return 0;+  }++  if (!QueryPerformanceCounter(&counter)) {+    return 0;+  }++  /* Because we have no guarantee about the order of magnitude of the+   * performance counter interval, integer math could cause this computation+   * to overflow. Therefore we resort to floating point math.+   */+  return (uint64_t) ((double) counter.QuadPart * hrtime_interval_ * scale);+}+++int uv_resident_set_memory(size_t* rss) {+  HANDLE current_process;+  PROCESS_MEMORY_COUNTERS pmc;++  current_process = GetCurrentProcess();++  if (!GetProcessMemoryInfo(current_process, &pmc, sizeof(pmc))) {+    return uv_translate_sys_error(GetLastError());+  }++  *rss = pmc.WorkingSetSize;++  return 0;+}+++int uv_uptime(double* uptime) {+  BYTE stack_buffer[4096];+  BYTE* malloced_buffer = NULL;+  BYTE* buffer = (BYTE*) stack_buffer;+  size_t buffer_size = sizeof(stack_buffer);+  DWORD data_size;++  PERF_DATA_BLOCK* data_block;+  PERF_OBJECT_TYPE* object_type;+  PERF_COUNTER_DEFINITION* counter_definition;++  DWORD i;++  for (;;) {+    LONG result;++    data_size = (DWORD) buffer_size;+    result = RegQueryValueExW(HKEY_PERFORMANCE_DATA,+                              L"2",+                              NULL,+                              NULL,+                              buffer,+                              &data_size);+    if (result == ERROR_SUCCESS) {+      break;+    } else if (result != ERROR_MORE_DATA) {+      *uptime = 0;+      return uv_translate_sys_error(result);+    }++    buffer_size *= 2;+    /* Don't let the buffer grow infinitely. */+    if (buffer_size > 1 << 20) {+      goto internalError;+    }++    uv__free(malloced_buffer);++    buffer = malloced_buffer = (BYTE*) uv__malloc(buffer_size);+    if (malloced_buffer == NULL) {+      *uptime = 0;+      return UV_ENOMEM;+    }+  }++  if (data_size < sizeof(*data_block))+    goto internalError;++  data_block = (PERF_DATA_BLOCK*) buffer;++  if (wmemcmp(data_block->Signature, L"PERF", 4) != 0)+    goto internalError;++  if (data_size < data_block->HeaderLength + sizeof(*object_type))+    goto internalError;++  object_type = (PERF_OBJECT_TYPE*) (buffer + data_block->HeaderLength);++  if (object_type->NumInstances != PERF_NO_INSTANCES)+    goto internalError;++  counter_definition = (PERF_COUNTER_DEFINITION*) (buffer ++      data_block->HeaderLength + object_type->HeaderLength);+  for (i = 0; i < object_type->NumCounters; i++) {+    if ((BYTE*) counter_definition + sizeof(*counter_definition) >+        buffer + data_size) {+      break;+    }++    if (counter_definition->CounterNameTitleIndex == 674 &&+        counter_definition->CounterSize == sizeof(uint64_t)) {+      if (counter_definition->CounterOffset + sizeof(uint64_t) > data_size ||+          !(counter_definition->CounterType & PERF_OBJECT_TIMER)) {+        goto internalError;+      } else {+        BYTE* address = (BYTE*) object_type + object_type->DefinitionLength ++                        counter_definition->CounterOffset;+        uint64_t value = *((uint64_t*) address);+        *uptime = floor((double) (object_type->PerfTime.QuadPart - value) /+                        (double) object_type->PerfFreq.QuadPart);+        uv__free(malloced_buffer);+        return 0;+      }+    }++    counter_definition = (PERF_COUNTER_DEFINITION*)+        ((BYTE*) counter_definition + counter_definition->ByteLength);+  }++  /* If we get here, the uptime value was not found. */+  uv__free(malloced_buffer);+  *uptime = 0;+  return UV_ENOSYS;++ internalError:+  uv__free(malloced_buffer);+  *uptime = 0;+  return UV_EIO;+}+++int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {+  uv_cpu_info_t* cpu_infos;+  SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;+  DWORD sppi_size;+  SYSTEM_INFO system_info;+  DWORD cpu_count, i;+  NTSTATUS status;+  ULONG result_size;+  int err;+  uv_cpu_info_t* cpu_info;++  cpu_infos = NULL;+  cpu_count = 0;+  sppi = NULL;++  uv__once_init();++  GetSystemInfo(&system_info);+  cpu_count = system_info.dwNumberOfProcessors;++  cpu_infos = uv__calloc(cpu_count, sizeof *cpu_infos);+  if (cpu_infos == NULL) {+    err = ERROR_OUTOFMEMORY;+    goto error;+  }++  sppi_size = cpu_count * sizeof(*sppi);+  sppi = uv__malloc(sppi_size);+  if (sppi == NULL) {+    err = ERROR_OUTOFMEMORY;+    goto error;+  }++  status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation,+                                     sppi,+                                     sppi_size,+                                     &result_size);+  if (!NT_SUCCESS(status)) {+    err = pRtlNtStatusToDosError(status);+    goto error;+  }++  assert(result_size == sppi_size);++  for (i = 0; i < cpu_count; i++) {+    WCHAR key_name[128];+    HKEY processor_key;+    DWORD cpu_speed;+    DWORD cpu_speed_size = sizeof(cpu_speed);+    WCHAR cpu_brand[256];+    DWORD cpu_brand_size = sizeof(cpu_brand);+    size_t len;++    len = _snwprintf(key_name,+                     ARRAY_SIZE(key_name),+                     L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d",+                     i);++    assert(len > 0 && len < ARRAY_SIZE(key_name));++    err = RegOpenKeyExW(HKEY_LOCAL_MACHINE,+                        key_name,+                        0,+                        KEY_QUERY_VALUE,+                        &processor_key);+    if (err != ERROR_SUCCESS) {+      goto error;+    }++    err = RegQueryValueExW(processor_key,+                           L"~MHz",+                           NULL,+                           NULL,+                           (BYTE*)&cpu_speed,+                           &cpu_speed_size);+    if (err != ERROR_SUCCESS) {+      RegCloseKey(processor_key);+      goto error;+    }++    err = RegQueryValueExW(processor_key,+                           L"ProcessorNameString",+                           NULL,+                           NULL,+                           (BYTE*)&cpu_brand,+                           &cpu_brand_size);+    RegCloseKey(processor_key);+    if (err != ERROR_SUCCESS)+      goto error;++    cpu_info = &cpu_infos[i];+    cpu_info->speed = cpu_speed;+    cpu_info->cpu_times.user = sppi[i].UserTime.QuadPart / 10000;+    cpu_info->cpu_times.sys = (sppi[i].KernelTime.QuadPart -+        sppi[i].IdleTime.QuadPart) / 10000;+    cpu_info->cpu_times.idle = sppi[i].IdleTime.QuadPart / 10000;+    cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000;+    cpu_info->cpu_times.nice = 0;++    uv__convert_utf16_to_utf8(cpu_brand,+                              cpu_brand_size / sizeof(WCHAR),+                              &(cpu_info->model));+  }++  uv__free(sppi);++  *cpu_count_ptr = cpu_count;+  *cpu_infos_ptr = cpu_infos;++  return 0;++ error:+  /* This is safe because the cpu_infos array is zeroed on allocation. */+  for (i = 0; i < cpu_count; i++)+    uv__free(cpu_infos[i].model);++  uv__free(cpu_infos);+  uv__free(sppi);++  return uv_translate_sys_error(err);+}+++void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {+  int i;++  for (i = 0; i < count; i++) {+    uv__free(cpu_infos[i].model);+  }++  uv__free(cpu_infos);+}+++static int is_windows_version_or_greater(DWORD os_major,+                                         DWORD os_minor,+                                         WORD service_pack_major,+                                         WORD service_pack_minor) {+  OSVERSIONINFOEX osvi;+  DWORDLONG condition_mask = 0;+  int op = VER_GREATER_EQUAL;++  /* Initialize the OSVERSIONINFOEX structure. */+  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));+  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);+  osvi.dwMajorVersion = os_major;+  osvi.dwMinorVersion = os_minor;+  osvi.wServicePackMajor = service_pack_major;+  osvi.wServicePackMinor = service_pack_minor;++  /* Initialize the condition mask. */+  VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, op);+  VER_SET_CONDITION(condition_mask, VER_MINORVERSION, op);+  VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, op);+  VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, op);++  /* Perform the test. */+  return (int) VerifyVersionInfo(+    &osvi,+    VER_MAJORVERSION | VER_MINORVERSION |+    VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,+    condition_mask);+}+++static int address_prefix_match(int family,+                                struct sockaddr* address,+                                struct sockaddr* prefix_address,+                                int prefix_len) {+  uint8_t* address_data;+  uint8_t* prefix_address_data;+  int i;++  assert(address->sa_family == family);+  assert(prefix_address->sa_family == family);++  if (family == AF_INET6) {+    address_data = (uint8_t*) &(((struct sockaddr_in6 *) address)->sin6_addr);+    prefix_address_data =+      (uint8_t*) &(((struct sockaddr_in6 *) prefix_address)->sin6_addr);+  } else {+    address_data = (uint8_t*) &(((struct sockaddr_in *) address)->sin_addr);+    prefix_address_data =+      (uint8_t*) &(((struct sockaddr_in *) prefix_address)->sin_addr);+  }++  for (i = 0; i < prefix_len >> 3; i++) {+    if (address_data[i] != prefix_address_data[i])+      return 0;+  }++  if (prefix_len % 8)+    return prefix_address_data[i] ==+      (address_data[i] & (0xff << (8 - prefix_len % 8)));++  return 1;+}+++int uv_interface_addresses(uv_interface_address_t** addresses_ptr,+    int* count_ptr) {+  IP_ADAPTER_ADDRESSES* win_address_buf;+  ULONG win_address_buf_size;+  IP_ADAPTER_ADDRESSES* adapter;++  uv_interface_address_t* uv_address_buf;+  char* name_buf;+  size_t uv_address_buf_size;+  uv_interface_address_t* uv_address;++  int count;++  int is_vista_or_greater;+  ULONG flags;++  *addresses_ptr = NULL;+  *count_ptr = 0;++  is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0);+  if (is_vista_or_greater) {+    flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |+      GAA_FLAG_SKIP_DNS_SERVER;+  } else {+    /* We need at least XP SP1. */+    if (!is_windows_version_or_greater(5, 1, 1, 0))+      return UV_ENOTSUP;++    flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |+      GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX;+  }+++  /* Fetch the size of the adapters reported by windows, and then get the list+   * itself. */+  win_address_buf_size = 0;+  win_address_buf = NULL;++  for (;;) {+    ULONG r;++    /* If win_address_buf is 0, then GetAdaptersAddresses will fail with.+     * ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in+     * win_address_buf_size. */+    r = GetAdaptersAddresses(AF_UNSPEC,+                             flags,+                             NULL,+                             win_address_buf,+                             &win_address_buf_size);++    if (r == ERROR_SUCCESS)+      break;++    uv__free(win_address_buf);++    switch (r) {+      case ERROR_BUFFER_OVERFLOW:+        /* This happens when win_address_buf is NULL or too small to hold all+         * adapters. */+        win_address_buf = uv__malloc(win_address_buf_size);+        if (win_address_buf == NULL)+          return UV_ENOMEM;++        continue;++      case ERROR_NO_DATA: {+        /* No adapters were found. */+        uv_address_buf = uv__malloc(1);+        if (uv_address_buf == NULL)+          return UV_ENOMEM;++        *count_ptr = 0;+        *addresses_ptr = uv_address_buf;++        return 0;+      }++      case ERROR_ADDRESS_NOT_ASSOCIATED:+        return UV_EAGAIN;++      case ERROR_INVALID_PARAMETER:+        /* MSDN says:+         *   "This error is returned for any of the following conditions: the+         *   SizePointer parameter is NULL, the Address parameter is not+         *   AF_INET, AF_INET6, or AF_UNSPEC, or the address information for+         *   the parameters requested is greater than ULONG_MAX."+         * Since the first two conditions are not met, it must be that the+         * adapter data is too big.+         */+        return UV_ENOBUFS;++      default:+        /* Other (unspecified) errors can happen, but we don't have any special+         * meaning for them. */+        assert(r != ERROR_SUCCESS);+        return uv_translate_sys_error(r);+    }+  }++  /* Count the number of enabled interfaces and compute how much space is+   * needed to store their info. */+  count = 0;+  uv_address_buf_size = 0;++  for (adapter = win_address_buf;+       adapter != NULL;+       adapter = adapter->Next) {+    IP_ADAPTER_UNICAST_ADDRESS* unicast_address;+    int name_size;++    /* Interfaces that are not 'up' should not be reported. Also skip+     * interfaces that have no associated unicast address, as to avoid+     * allocating space for the name for this interface. */+    if (adapter->OperStatus != IfOperStatusUp ||+        adapter->FirstUnicastAddress == NULL)+      continue;++    /* Compute the size of the interface name. */+    name_size = WideCharToMultiByte(CP_UTF8,+                                    0,+                                    adapter->FriendlyName,+                                    -1,+                                    NULL,+                                    0,+                                    NULL,+                                    FALSE);+    if (name_size <= 0) {+      uv__free(win_address_buf);+      return uv_translate_sys_error(GetLastError());+    }+    uv_address_buf_size += name_size;++    /* Count the number of addresses associated with this interface, and+     * compute the size. */+    for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)+                           adapter->FirstUnicastAddress;+         unicast_address != NULL;+         unicast_address = unicast_address->Next) {+      count++;+      uv_address_buf_size += sizeof(uv_interface_address_t);+    }+  }++  /* Allocate space to store interface data plus adapter names. */+  uv_address_buf = uv__malloc(uv_address_buf_size);+  if (uv_address_buf == NULL) {+    uv__free(win_address_buf);+    return UV_ENOMEM;+  }++  /* Compute the start of the uv_interface_address_t array, and the place in+   * the buffer where the interface names will be stored. */+  uv_address = uv_address_buf;+  name_buf = (char*) (uv_address_buf + count);++  /* Fill out the output buffer. */+  for (adapter = win_address_buf;+       adapter != NULL;+       adapter = adapter->Next) {+    IP_ADAPTER_UNICAST_ADDRESS* unicast_address;+    int name_size;+    size_t max_name_size;++    if (adapter->OperStatus != IfOperStatusUp ||+        adapter->FirstUnicastAddress == NULL)+      continue;++    /* Convert the interface name to UTF8. */+    max_name_size = (char*) uv_address_buf + uv_address_buf_size - name_buf;+    if (max_name_size > (size_t) INT_MAX)+      max_name_size = INT_MAX;+    name_size = WideCharToMultiByte(CP_UTF8,+                                    0,+                                    adapter->FriendlyName,+                                    -1,+                                    name_buf,+                                    (int) max_name_size,+                                    NULL,+                                    FALSE);+    if (name_size <= 0) {+      uv__free(win_address_buf);+      uv__free(uv_address_buf);+      return uv_translate_sys_error(GetLastError());+    }++    /* Add an uv_interface_address_t element for every unicast address. */+    for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)+                           adapter->FirstUnicastAddress;+         unicast_address != NULL;+         unicast_address = unicast_address->Next) {+      struct sockaddr* sa;+      ULONG prefix_len;++      sa = unicast_address->Address.lpSockaddr;++      /* XP has no OnLinkPrefixLength field. */+      if (is_vista_or_greater) {+        prefix_len =+          ((IP_ADAPTER_UNICAST_ADDRESS_LH*) unicast_address)->OnLinkPrefixLength;+      } else {+        /* Prior to Windows Vista the FirstPrefix pointed to the list with+         * single prefix for each IP address assigned to the adapter.+         * Order of FirstPrefix does not match order of FirstUnicastAddress,+         * so we need to find corresponding prefix.+         */+        IP_ADAPTER_PREFIX* prefix;+        prefix_len = 0;++        for (prefix = adapter->FirstPrefix; prefix; prefix = prefix->Next) {+          /* We want the longest matching prefix. */+          if (prefix->Address.lpSockaddr->sa_family != sa->sa_family ||+              prefix->PrefixLength <= prefix_len)+            continue;++          if (address_prefix_match(sa->sa_family, sa,+              prefix->Address.lpSockaddr, prefix->PrefixLength)) {+            prefix_len = prefix->PrefixLength;+          }+        }++        /* If there is no matching prefix information, return a single-host+         * subnet mask (e.g. 255.255.255.255 for IPv4).+         */+        if (!prefix_len)+          prefix_len = (sa->sa_family == AF_INET6) ? 128 : 32;+      }++      memset(uv_address, 0, sizeof *uv_address);++      uv_address->name = name_buf;++      if (adapter->PhysicalAddressLength == sizeof(uv_address->phys_addr)) {+        memcpy(uv_address->phys_addr,+               adapter->PhysicalAddress,+               sizeof(uv_address->phys_addr));+      }++      uv_address->is_internal =+          (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK);++      if (sa->sa_family == AF_INET6) {+        uv_address->address.address6 = *((struct sockaddr_in6 *) sa);++        uv_address->netmask.netmask6.sin6_family = AF_INET6;+        memset(uv_address->netmask.netmask6.sin6_addr.s6_addr, 0xff, prefix_len >> 3);+        /* This check ensures that we don't write past the size of the data. */+        if (prefix_len % 8) {+          uv_address->netmask.netmask6.sin6_addr.s6_addr[prefix_len >> 3] =+              0xff << (8 - prefix_len % 8);+        }++      } else {+        uv_address->address.address4 = *((struct sockaddr_in *) sa);++        uv_address->netmask.netmask4.sin_family = AF_INET;+        uv_address->netmask.netmask4.sin_addr.s_addr = (prefix_len > 0) ?+            htonl(0xffffffff << (32 - prefix_len)) : 0;+      }++      uv_address++;+    }++    name_buf += name_size;+  }++  uv__free(win_address_buf);++  *addresses_ptr = uv_address_buf;+  *count_ptr = count;++  return 0;+}+++void uv_free_interface_addresses(uv_interface_address_t* addresses,+    int count) {+  uv__free(addresses);+}+++int uv_getrusage(uv_rusage_t *uv_rusage) {+  FILETIME createTime, exitTime, kernelTime, userTime;+  SYSTEMTIME kernelSystemTime, userSystemTime;+  PROCESS_MEMORY_COUNTERS memCounters;+  IO_COUNTERS ioCounters;+  int ret;++  ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime);+  if (ret == 0) {+    return uv_translate_sys_error(GetLastError());+  }++  ret = FileTimeToSystemTime(&kernelTime, &kernelSystemTime);+  if (ret == 0) {+    return uv_translate_sys_error(GetLastError());+  }++  ret = FileTimeToSystemTime(&userTime, &userSystemTime);+  if (ret == 0) {+    return uv_translate_sys_error(GetLastError());+  }++  ret = GetProcessMemoryInfo(GetCurrentProcess(),+                             &memCounters,+                             sizeof(memCounters));+  if (ret == 0) {+    return uv_translate_sys_error(GetLastError());+  }++  ret = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);+  if (ret == 0) {+    return uv_translate_sys_error(GetLastError());+  }++  memset(uv_rusage, 0, sizeof(*uv_rusage));++  uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 ++                               userSystemTime.wMinute * 60 ++                               userSystemTime.wSecond;+  uv_rusage->ru_utime.tv_usec = userSystemTime.wMilliseconds * 1000;++  uv_rusage->ru_stime.tv_sec = kernelSystemTime.wHour * 3600 ++                               kernelSystemTime.wMinute * 60 ++                               kernelSystemTime.wSecond;+  uv_rusage->ru_stime.tv_usec = kernelSystemTime.wMilliseconds * 1000;++  uv_rusage->ru_majflt = (uint64_t) memCounters.PageFaultCount;+  uv_rusage->ru_maxrss = (uint64_t) memCounters.PeakWorkingSetSize / 1024;++  uv_rusage->ru_oublock = (uint64_t) ioCounters.WriteOperationCount;+  uv_rusage->ru_inblock = (uint64_t) ioCounters.ReadOperationCount;++  return 0;+}+++int uv_os_homedir(char* buffer, size_t* size) {+  uv_passwd_t pwd;+  size_t len;+  int r;++  /* Check if the USERPROFILE environment variable is set first. The task of+     performing input validation on buffer and size is taken care of by+     uv_os_getenv(). */+  r = uv_os_getenv("USERPROFILE", buffer, size);++  /* Don't return an error if USERPROFILE was not found. */+  if (r != UV_ENOENT)+    return r;++  /* USERPROFILE is not set, so call uv__getpwuid_r() */+  r = uv__getpwuid_r(&pwd);++  if (r != 0) {+    return r;+  }++  len = strlen(pwd.homedir);++  if (len >= *size) {+    *size = len + 1;+    uv_os_free_passwd(&pwd);+    return UV_ENOBUFS;+  }++  memcpy(buffer, pwd.homedir, len + 1);+  *size = len;+  uv_os_free_passwd(&pwd);++  return 0;+}+++int uv_os_tmpdir(char* buffer, size_t* size) {+  wchar_t path[MAX_PATH + 1];+  DWORD bufsize;+  size_t len;++  if (buffer == NULL || size == NULL || *size == 0)+    return UV_EINVAL;++  len = GetTempPathW(MAX_PATH + 1, path);++  if (len == 0) {+    return uv_translate_sys_error(GetLastError());+  } else if (len > MAX_PATH + 1) {+    /* This should not be possible */+    return UV_EIO;+  }++  /* The returned directory should not have a trailing slash, unless it points+   * at a drive root, like c:\. Remove it if needed. */+  if (path[len - 1] == L'\\' &&+      !(len == 3 && path[1] == L':')) {+    len--;+    path[len] = L'\0';+  }++  /* Check how much space we need */+  bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL);++  if (bufsize == 0) {+    return uv_translate_sys_error(GetLastError());+  } else if (bufsize > *size) {+    *size = bufsize;+    return UV_ENOBUFS;+  }++  /* Convert to UTF-8 */+  bufsize = WideCharToMultiByte(CP_UTF8,+                                0,+                                path,+                                -1,+                                buffer,+                                *size,+                                NULL,+                                NULL);++  if (bufsize == 0)+    return uv_translate_sys_error(GetLastError());++  *size = bufsize - 1;+  return 0;+}+++void uv_os_free_passwd(uv_passwd_t* pwd) {+  if (pwd == NULL)+    return;++  uv__free(pwd->username);+  uv__free(pwd->homedir);+  pwd->username = NULL;+  pwd->homedir = NULL;+}+++/*+ * Converts a UTF-16 string into a UTF-8 one. The resulting string is+ * null-terminated.+ *+ * If utf16 is null terminated, utf16len can be set to -1, otherwise it must+ * be specified.+ */+int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) {+  DWORD bufsize;++  if (utf16 == NULL)+    return UV_EINVAL;++  /* Check how much space we need */+  bufsize = WideCharToMultiByte(CP_UTF8,+                                0,+                                utf16,+                                utf16len,+                                NULL,+                                0,+                                NULL,+                                NULL);++  if (bufsize == 0)+    return uv_translate_sys_error(GetLastError());++  /* Allocate the destination buffer adding an extra byte for the terminating+   * NULL. If utf16len is not -1 WideCharToMultiByte will not add it, so+   * we do it ourselves always, just in case. */+  *utf8 = uv__malloc(bufsize + 1);++  if (*utf8 == NULL)+    return UV_ENOMEM;++  /* Convert to UTF-8 */+  bufsize = WideCharToMultiByte(CP_UTF8,+                                0,+                                utf16,+                                utf16len,+                                *utf8,+                                bufsize,+                                NULL,+                                NULL);++  if (bufsize == 0) {+    uv__free(*utf8);+    *utf8 = NULL;+    return uv_translate_sys_error(GetLastError());+  }++  (*utf8)[bufsize] = '\0';+  return 0;+}+++/*+ * Converts a UTF-8 string into a UTF-16 one. The resulting string is+ * null-terminated.+ *+ * If utf8 is null terminated, utf8len can be set to -1, otherwise it must+ * be specified.+ */+int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) {+  int bufsize;++  if (utf8 == NULL)+    return UV_EINVAL;++  /* Check how much space we need */+  bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, NULL, 0);++  if (bufsize == 0)+    return uv_translate_sys_error(GetLastError());++  /* Allocate the destination buffer adding an extra byte for the terminating+   * NULL. If utf8len is not -1 MultiByteToWideChar will not add it, so+   * we do it ourselves always, just in case. */+  *utf16 = uv__malloc(sizeof(WCHAR) * (bufsize + 1));++  if (*utf16 == NULL)+    return UV_ENOMEM;++  /* Convert to UTF-16 */+  bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize);++  if (bufsize == 0) {+    uv__free(*utf16);+    *utf16 = NULL;+    return uv_translate_sys_error(GetLastError());+  }++  (*utf16)[bufsize] = '\0';+  return 0;+}+++int uv__getpwuid_r(uv_passwd_t* pwd) {+  HANDLE token;+  wchar_t username[UNLEN + 1];+  wchar_t path[MAX_PATH];+  DWORD bufsize;+  int r;++  if (pwd == NULL)+    return UV_EINVAL;++  /* Get the home directory using GetUserProfileDirectoryW() */+  if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0)+    return uv_translate_sys_error(GetLastError());++  bufsize = ARRAY_SIZE(path);+  if (!GetUserProfileDirectoryW(token, path, &bufsize)) {+    r = GetLastError();+    CloseHandle(token);++    /* This should not be possible */+    if (r == ERROR_INSUFFICIENT_BUFFER)+      return UV_ENOMEM;++    return uv_translate_sys_error(r);+  }++  CloseHandle(token);++  /* Get the username using GetUserNameW() */+  bufsize = ARRAY_SIZE(username);+  if (!GetUserNameW(username, &bufsize)) {+    r = GetLastError();++    /* This should not be possible */+    if (r == ERROR_INSUFFICIENT_BUFFER)+      return UV_ENOMEM;++    return uv_translate_sys_error(r);+  }++  pwd->homedir = NULL;+  r = uv__convert_utf16_to_utf8(path, -1, &pwd->homedir);++  if (r != 0)+    return r;++  pwd->username = NULL;+  r = uv__convert_utf16_to_utf8(username, -1, &pwd->username);++  if (r != 0) {+    uv__free(pwd->homedir);+    return r;+  }++  pwd->shell = NULL;+  pwd->uid = -1;+  pwd->gid = -1;++  return 0;+}+++int uv_os_get_passwd(uv_passwd_t* pwd) {+  return uv__getpwuid_r(pwd);+}+++int uv_os_getenv(const char* name, char* buffer, size_t* size) {+  wchar_t var[MAX_ENV_VAR_LENGTH];+  wchar_t* name_w;+  DWORD bufsize;+  size_t len;+  int r;++  if (name == NULL || buffer == NULL || size == NULL || *size == 0)+    return UV_EINVAL;++  r = uv__convert_utf8_to_utf16(name, -1, &name_w);++  if (r != 0)+    return r;++  len = GetEnvironmentVariableW(name_w, var, MAX_ENV_VAR_LENGTH);+  uv__free(name_w);+  assert(len < MAX_ENV_VAR_LENGTH); /* len does not include the null */++  if (len == 0) {+    r = GetLastError();++    if (r == ERROR_ENVVAR_NOT_FOUND)+      return UV_ENOENT;++    return uv_translate_sys_error(r);+  }++  /* Check how much space we need */+  bufsize = WideCharToMultiByte(CP_UTF8, 0, var, -1, NULL, 0, NULL, NULL);++  if (bufsize == 0) {+    return uv_translate_sys_error(GetLastError());+  } else if (bufsize > *size) {+    *size = bufsize;+    return UV_ENOBUFS;+  }++  /* Convert to UTF-8 */+  bufsize = WideCharToMultiByte(CP_UTF8,+                                0,+                                var,+                                -1,+                                buffer,+                                *size,+                                NULL,+                                NULL);++  if (bufsize == 0)+    return uv_translate_sys_error(GetLastError());++  *size = bufsize - 1;+  return 0;+}+++int uv_os_setenv(const char* name, const char* value) {+  wchar_t* name_w;+  wchar_t* value_w;+  int r;++  if (name == NULL || value == NULL)+    return UV_EINVAL;++  r = uv__convert_utf8_to_utf16(name, -1, &name_w);++  if (r != 0)+    return r;++  r = uv__convert_utf8_to_utf16(value, -1, &value_w);++  if (r != 0) {+    uv__free(name_w);+    return r;+  }++  r = SetEnvironmentVariableW(name_w, value_w);+  uv__free(name_w);+  uv__free(value_w);++  if (r == 0)+    return uv_translate_sys_error(GetLastError());++  return 0;+}+++int uv_os_unsetenv(const char* name) {+  wchar_t* name_w;+  int r;++  if (name == NULL)+    return UV_EINVAL;++  r = uv__convert_utf8_to_utf16(name, -1, &name_w);++  if (r != 0)+    return r;++  r = SetEnvironmentVariableW(name_w, NULL);+  uv__free(name_w);++  if (r == 0)+    return uv_translate_sys_error(GetLastError());++  return 0;+}+++int uv_os_gethostname(char* buffer, size_t* size) {+  char buf[UV_MAXHOSTNAMESIZE];+  size_t len;++  if (buffer == NULL || size == NULL || *size == 0)+    return UV_EINVAL;++  uv__once_init(); /* Initialize winsock */++  if (gethostname(buf, sizeof(buf)) != 0)+    return uv_translate_sys_error(WSAGetLastError());++  buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */+  len = strlen(buf);++  if (len >= *size) {+    *size = len + 1;+    return UV_ENOBUFS;+  }++  memcpy(buffer, buf, len + 1);+  *size = len;+  return 0;+}+++static int uv__get_handle(uv_pid_t pid, int access, HANDLE* handle) {+  int r;++  if (pid == 0)+    *handle = GetCurrentProcess();+  else+    *handle = OpenProcess(access, FALSE, pid);++  if (*handle == NULL) {+    r = GetLastError();++    if (r == ERROR_INVALID_PARAMETER)+      return UV_ESRCH;+    else+      return uv_translate_sys_error(r);+  }++  return 0;+}+++int uv_os_getpriority(uv_pid_t pid, int* priority) {+  HANDLE handle;+  int r;++  if (priority == NULL)+    return UV_EINVAL;++  r = uv__get_handle(pid, PROCESS_QUERY_LIMITED_INFORMATION, &handle);++  if (r != 0)+    return r;++  r = GetPriorityClass(handle);++  if (r == 0) {+    r = uv_translate_sys_error(GetLastError());+  } else {+    /* Map Windows priority classes to Unix nice values. */+    if (r == REALTIME_PRIORITY_CLASS)+      *priority = UV_PRIORITY_HIGHEST;+    else if (r == HIGH_PRIORITY_CLASS)+      *priority = UV_PRIORITY_HIGH;+    else if (r == ABOVE_NORMAL_PRIORITY_CLASS)+      *priority = UV_PRIORITY_ABOVE_NORMAL;+    else if (r == NORMAL_PRIORITY_CLASS)+      *priority = UV_PRIORITY_NORMAL;+    else if (r == BELOW_NORMAL_PRIORITY_CLASS)+      *priority = UV_PRIORITY_BELOW_NORMAL;+    else  /* IDLE_PRIORITY_CLASS */+      *priority = UV_PRIORITY_LOW;++    r = 0;+  }++  CloseHandle(handle);+  return r;+}+++int uv_os_setpriority(uv_pid_t pid, int priority) {+  HANDLE handle;+  int priority_class;+  int r;++  /* Map Unix nice values to Windows priority classes. */+  if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)+    return UV_EINVAL;+  else if (priority < UV_PRIORITY_HIGH)+    priority_class = REALTIME_PRIORITY_CLASS;+  else if (priority < UV_PRIORITY_ABOVE_NORMAL)+    priority_class = HIGH_PRIORITY_CLASS;+  else if (priority < UV_PRIORITY_NORMAL)+    priority_class = ABOVE_NORMAL_PRIORITY_CLASS;+  else if (priority < UV_PRIORITY_BELOW_NORMAL)+    priority_class = NORMAL_PRIORITY_CLASS;+  else if (priority < UV_PRIORITY_LOW)+    priority_class = BELOW_NORMAL_PRIORITY_CLASS;+  else+    priority_class = IDLE_PRIORITY_CLASS;++  r = uv__get_handle(pid, PROCESS_SET_INFORMATION, &handle);++  if (r != 0)+    return r;++  if (SetPriorityClass(handle, priority_class) == 0)+    r = uv_translate_sys_error(GetLastError());++  CloseHandle(handle);+  return r;+}+++int uv_os_uname(uv_utsname_t* buffer) {+  /* Implementation loosely based on+     https://github.com/gagern/gnulib/blob/master/lib/uname.c */+  OSVERSIONINFOW os_info;+  SYSTEM_INFO system_info;+  HKEY registry_key;+  WCHAR product_name_w[256];+  DWORD product_name_w_size;+  int version_size;+  int processor_level;+  int r;++  if (buffer == NULL)+    return UV_EINVAL;++  uv__once_init();+  os_info.dwOSVersionInfoSize = sizeof(os_info);+  os_info.szCSDVersion[0] = L'\0';++  /* Try calling RtlGetVersion(), and fall back to the deprecated GetVersionEx()+     if RtlGetVersion() is not available. */+  if (pRtlGetVersion) {+    pRtlGetVersion(&os_info);+  } else {+    /* Silence GetVersionEx() deprecation warning. */+    #pragma warning(suppress : 4996)+    if (GetVersionExW(&os_info) == 0) {+      r = uv_translate_sys_error(GetLastError());+      goto error;+    }+  }++  /* Populate the version field. */+  version_size = 0;+  r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,+                    L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",+                    0,+                    KEY_QUERY_VALUE,+                    &registry_key);++  if (r == ERROR_SUCCESS) {+    product_name_w_size = sizeof(product_name_w);+    r = RegGetValueW(registry_key,+                     NULL,+                     L"ProductName",+                     RRF_RT_REG_SZ,+                     NULL,+                     (PVOID) product_name_w,+                     &product_name_w_size);+    RegCloseKey(registry_key);++    if (r == ERROR_SUCCESS) {+      version_size = WideCharToMultiByte(CP_UTF8,+                                         0,+                                         product_name_w,+                                         -1,+                                         buffer->version,+                                         sizeof(buffer->version),+                                         NULL,+                                         NULL);+      if (version_size == 0) {+        r = uv_translate_sys_error(GetLastError());+        goto error;+      }+    }+  }++  /* Append service pack information to the version if present. */+  if (os_info.szCSDVersion[0] != L'\0') {+    if (version_size > 0)+      buffer->version[version_size - 1] = ' ';++    if (WideCharToMultiByte(CP_UTF8,+                            0,+                            os_info.szCSDVersion,+                            -1,+                            buffer->version + version_size,+                            sizeof(buffer->version) - version_size,+                            NULL,+                            NULL) == 0) {+      r = uv_translate_sys_error(GetLastError());+      goto error;+    }+  }++  /* Populate the sysname field. */+#ifdef __MINGW32__+  r = snprintf(buffer->sysname,+               sizeof(buffer->sysname),+               "MINGW32_NT-%u.%u",+               (unsigned int) os_info.dwMajorVersion,+               (unsigned int) os_info.dwMinorVersion);+  assert(r < sizeof(buffer->sysname));+#else+  uv__strscpy(buffer->sysname, "Windows_NT", sizeof(buffer->sysname));+#endif++  /* Populate the release field. */+  r = snprintf(buffer->release,+               sizeof(buffer->release),+               "%d.%d.%d",+               (unsigned int) os_info.dwMajorVersion,+               (unsigned int) os_info.dwMinorVersion,+               (unsigned int) os_info.dwBuildNumber);+  assert(r < sizeof(buffer->release));++  /* Populate the machine field. */+  GetSystemInfo(&system_info);++  switch (system_info.wProcessorArchitecture) {+    case PROCESSOR_ARCHITECTURE_AMD64:+      uv__strscpy(buffer->machine, "x86_64", sizeof(buffer->machine));+      break;+    case PROCESSOR_ARCHITECTURE_IA64:+      uv__strscpy(buffer->machine, "ia64", sizeof(buffer->machine));+      break;+    case PROCESSOR_ARCHITECTURE_INTEL:+      uv__strscpy(buffer->machine, "i386", sizeof(buffer->machine));++      if (system_info.wProcessorLevel > 3) {+        processor_level = system_info.wProcessorLevel < 6 ?+                          system_info.wProcessorLevel : 6;+        buffer->machine[1] = '0' + processor_level;+      }++      break;+    case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:+      uv__strscpy(buffer->machine, "i686", sizeof(buffer->machine));+      break;+    case PROCESSOR_ARCHITECTURE_MIPS:+      uv__strscpy(buffer->machine, "mips", sizeof(buffer->machine));+      break;+    case PROCESSOR_ARCHITECTURE_ALPHA:+    case PROCESSOR_ARCHITECTURE_ALPHA64:+      uv__strscpy(buffer->machine, "alpha", sizeof(buffer->machine));+      break;+    case PROCESSOR_ARCHITECTURE_PPC:+      uv__strscpy(buffer->machine, "powerpc", sizeof(buffer->machine));+      break;+    case PROCESSOR_ARCHITECTURE_SHX:+      uv__strscpy(buffer->machine, "sh", sizeof(buffer->machine));+      break;+    case PROCESSOR_ARCHITECTURE_ARM:+      uv__strscpy(buffer->machine, "arm", sizeof(buffer->machine));+      break;+    default:+      uv__strscpy(buffer->machine, "unknown", sizeof(buffer->machine));+      break;+  }++  return 0;++error:+  buffer->sysname[0] = '\0';+  buffer->release[0] = '\0';+  buffer->version[0] = '\0';+  buffer->machine[0] = '\0';+  return r;+}
+ third_party/libuv/src/win/winapi.c view
@@ -0,0 +1,130 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>++#include "uv.h"+#include "internal.h"+++/* Ntdll function pointers */+sRtlGetVersion pRtlGetVersion;+sRtlNtStatusToDosError pRtlNtStatusToDosError;+sNtDeviceIoControlFile pNtDeviceIoControlFile;+sNtQueryInformationFile pNtQueryInformationFile;+sNtSetInformationFile pNtSetInformationFile;+sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;+sNtQueryDirectoryFile pNtQueryDirectoryFile;+sNtQuerySystemInformation pNtQuerySystemInformation;++/* Kernel32 function pointers */+sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;++/* Powrprof.dll function pointer */+sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;++/* User32.dll function pointer */+sSetWinEventHook pSetWinEventHook;+++void uv_winapi_init(void) {+  HMODULE ntdll_module;+  HMODULE powrprof_module;+  HMODULE user32_module;+  HMODULE kernel32_module;++  ntdll_module = GetModuleHandleA("ntdll.dll");+  if (ntdll_module == NULL) {+    uv_fatal_error(GetLastError(), "GetModuleHandleA");+  }++  pRtlGetVersion = (sRtlGetVersion) GetProcAddress(ntdll_module,+                                                   "RtlGetVersion");++  pRtlNtStatusToDosError = (sRtlNtStatusToDosError) GetProcAddress(+      ntdll_module,+      "RtlNtStatusToDosError");+  if (pRtlNtStatusToDosError == NULL) {+    uv_fatal_error(GetLastError(), "GetProcAddress");+  }++  pNtDeviceIoControlFile = (sNtDeviceIoControlFile) GetProcAddress(+      ntdll_module,+      "NtDeviceIoControlFile");+  if (pNtDeviceIoControlFile == NULL) {+    uv_fatal_error(GetLastError(), "GetProcAddress");+  }++  pNtQueryInformationFile = (sNtQueryInformationFile) GetProcAddress(+      ntdll_module,+      "NtQueryInformationFile");+  if (pNtQueryInformationFile == NULL) {+    uv_fatal_error(GetLastError(), "GetProcAddress");+  }++  pNtSetInformationFile = (sNtSetInformationFile) GetProcAddress(+      ntdll_module,+      "NtSetInformationFile");+  if (pNtSetInformationFile == NULL) {+    uv_fatal_error(GetLastError(), "GetProcAddress");+  }++  pNtQueryVolumeInformationFile = (sNtQueryVolumeInformationFile)+      GetProcAddress(ntdll_module, "NtQueryVolumeInformationFile");+  if (pNtQueryVolumeInformationFile == NULL) {+    uv_fatal_error(GetLastError(), "GetProcAddress");+  }++  pNtQueryDirectoryFile = (sNtQueryDirectoryFile)+      GetProcAddress(ntdll_module, "NtQueryDirectoryFile");+  if (pNtQueryVolumeInformationFile == NULL) {+    uv_fatal_error(GetLastError(), "GetProcAddress");+  }++  pNtQuerySystemInformation = (sNtQuerySystemInformation) GetProcAddress(+      ntdll_module,+      "NtQuerySystemInformation");+  if (pNtQuerySystemInformation == NULL) {+    uv_fatal_error(GetLastError(), "GetProcAddress");+  }++  kernel32_module = GetModuleHandleA("kernel32.dll");+  if (kernel32_module == NULL) {+    uv_fatal_error(GetLastError(), "GetModuleHandleA");+  }++  pGetQueuedCompletionStatusEx = (sGetQueuedCompletionStatusEx) GetProcAddress(+      kernel32_module,+      "GetQueuedCompletionStatusEx");++  powrprof_module = LoadLibraryA("powrprof.dll");+  if (powrprof_module != NULL) {+    pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification)+      GetProcAddress(powrprof_module, "PowerRegisterSuspendResumeNotification");+  }++  user32_module = LoadLibraryA("user32.dll");+  if (user32_module != NULL) {+    pSetWinEventHook = (sSetWinEventHook)+      GetProcAddress(user32_module, "SetWinEventHook");+  }++}
+ third_party/libuv/src/win/winapi.h view
@@ -0,0 +1,4731 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#ifndef UV_WIN_WINAPI_H_+#define UV_WIN_WINAPI_H_++#include <windows.h>+++/*+ * Ntdll headers+ */+#ifndef STATUS_SEVERITY_SUCCESS+# define STATUS_SEVERITY_SUCCESS 0x0+#endif++#ifndef STATUS_SEVERITY_INFORMATIONAL+# define STATUS_SEVERITY_INFORMATIONAL 0x1+#endif++#ifndef STATUS_SEVERITY_WARNING+# define STATUS_SEVERITY_WARNING 0x2+#endif++#ifndef STATUS_SEVERITY_ERROR+# define STATUS_SEVERITY_ERROR 0x3+#endif++#ifndef FACILITY_NTWIN32+# define FACILITY_NTWIN32 0x7+#endif++#ifndef NT_SUCCESS+# define NT_SUCCESS(status) (((NTSTATUS) (status)) >= 0)+#endif++#ifndef NT_INFORMATION+# define NT_INFORMATION(status) ((((ULONG) (status)) >> 30) == 1)+#endif++#ifndef NT_WARNING+# define NT_WARNING(status) ((((ULONG) (status)) >> 30) == 2)+#endif++#ifndef NT_ERROR+# define NT_ERROR(status) ((((ULONG) (status)) >> 30) == 3)+#endif++#ifndef STATUS_SUCCESS+# define STATUS_SUCCESS ((NTSTATUS) 0x00000000L)+#endif++#ifndef STATUS_WAIT_0+# define STATUS_WAIT_0 ((NTSTATUS) 0x00000000L)+#endif++#ifndef STATUS_WAIT_1+# define STATUS_WAIT_1 ((NTSTATUS) 0x00000001L)+#endif++#ifndef STATUS_WAIT_2+# define STATUS_WAIT_2 ((NTSTATUS) 0x00000002L)+#endif++#ifndef STATUS_WAIT_3+# define STATUS_WAIT_3 ((NTSTATUS) 0x00000003L)+#endif++#ifndef STATUS_WAIT_63+# define STATUS_WAIT_63 ((NTSTATUS) 0x0000003FL)+#endif++#ifndef STATUS_ABANDONED+# define STATUS_ABANDONED ((NTSTATUS) 0x00000080L)+#endif++#ifndef STATUS_ABANDONED_WAIT_0+# define STATUS_ABANDONED_WAIT_0 ((NTSTATUS) 0x00000080L)+#endif++#ifndef STATUS_ABANDONED_WAIT_63+# define STATUS_ABANDONED_WAIT_63 ((NTSTATUS) 0x000000BFL)+#endif++#ifndef STATUS_USER_APC+# define STATUS_USER_APC ((NTSTATUS) 0x000000C0L)+#endif++#ifndef STATUS_KERNEL_APC+# define STATUS_KERNEL_APC ((NTSTATUS) 0x00000100L)+#endif++#ifndef STATUS_ALERTED+# define STATUS_ALERTED ((NTSTATUS) 0x00000101L)+#endif++#ifndef STATUS_TIMEOUT+# define STATUS_TIMEOUT ((NTSTATUS) 0x00000102L)+#endif++#ifndef STATUS_PENDING+# define STATUS_PENDING ((NTSTATUS) 0x00000103L)+#endif++#ifndef STATUS_REPARSE+# define STATUS_REPARSE ((NTSTATUS) 0x00000104L)+#endif++#ifndef STATUS_MORE_ENTRIES+# define STATUS_MORE_ENTRIES ((NTSTATUS) 0x00000105L)+#endif++#ifndef STATUS_NOT_ALL_ASSIGNED+# define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106L)+#endif++#ifndef STATUS_SOME_NOT_MAPPED+# define STATUS_SOME_NOT_MAPPED ((NTSTATUS) 0x00000107L)+#endif++#ifndef STATUS_OPLOCK_BREAK_IN_PROGRESS+# define STATUS_OPLOCK_BREAK_IN_PROGRESS ((NTSTATUS) 0x00000108L)+#endif++#ifndef STATUS_VOLUME_MOUNTED+# define STATUS_VOLUME_MOUNTED ((NTSTATUS) 0x00000109L)+#endif++#ifndef STATUS_RXACT_COMMITTED+# define STATUS_RXACT_COMMITTED ((NTSTATUS) 0x0000010AL)+#endif++#ifndef STATUS_NOTIFY_CLEANUP+# define STATUS_NOTIFY_CLEANUP ((NTSTATUS) 0x0000010BL)+#endif++#ifndef STATUS_NOTIFY_ENUM_DIR+# define STATUS_NOTIFY_ENUM_DIR ((NTSTATUS) 0x0000010CL)+#endif++#ifndef STATUS_NO_QUOTAS_FOR_ACCOUNT+# define STATUS_NO_QUOTAS_FOR_ACCOUNT ((NTSTATUS) 0x0000010DL)+#endif++#ifndef STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED+# define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED ((NTSTATUS) 0x0000010EL)+#endif++#ifndef STATUS_PAGE_FAULT_TRANSITION+# define STATUS_PAGE_FAULT_TRANSITION ((NTSTATUS) 0x00000110L)+#endif++#ifndef STATUS_PAGE_FAULT_DEMAND_ZERO+# define STATUS_PAGE_FAULT_DEMAND_ZERO ((NTSTATUS) 0x00000111L)+#endif++#ifndef STATUS_PAGE_FAULT_COPY_ON_WRITE+# define STATUS_PAGE_FAULT_COPY_ON_WRITE ((NTSTATUS) 0x00000112L)+#endif++#ifndef STATUS_PAGE_FAULT_GUARD_PAGE+# define STATUS_PAGE_FAULT_GUARD_PAGE ((NTSTATUS) 0x00000113L)+#endif++#ifndef STATUS_PAGE_FAULT_PAGING_FILE+# define STATUS_PAGE_FAULT_PAGING_FILE ((NTSTATUS) 0x00000114L)+#endif++#ifndef STATUS_CACHE_PAGE_LOCKED+# define STATUS_CACHE_PAGE_LOCKED ((NTSTATUS) 0x00000115L)+#endif++#ifndef STATUS_CRASH_DUMP+# define STATUS_CRASH_DUMP ((NTSTATUS) 0x00000116L)+#endif++#ifndef STATUS_BUFFER_ALL_ZEROS+# define STATUS_BUFFER_ALL_ZEROS ((NTSTATUS) 0x00000117L)+#endif++#ifndef STATUS_REPARSE_OBJECT+# define STATUS_REPARSE_OBJECT ((NTSTATUS) 0x00000118L)+#endif++#ifndef STATUS_RESOURCE_REQUIREMENTS_CHANGED+# define STATUS_RESOURCE_REQUIREMENTS_CHANGED ((NTSTATUS) 0x00000119L)+#endif++#ifndef STATUS_TRANSLATION_COMPLETE+# define STATUS_TRANSLATION_COMPLETE ((NTSTATUS) 0x00000120L)+#endif++#ifndef STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY+# define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY ((NTSTATUS) 0x00000121L)+#endif++#ifndef STATUS_NOTHING_TO_TERMINATE+# define STATUS_NOTHING_TO_TERMINATE ((NTSTATUS) 0x00000122L)+#endif++#ifndef STATUS_PROCESS_NOT_IN_JOB+# define STATUS_PROCESS_NOT_IN_JOB ((NTSTATUS) 0x00000123L)+#endif++#ifndef STATUS_PROCESS_IN_JOB+# define STATUS_PROCESS_IN_JOB ((NTSTATUS) 0x00000124L)+#endif++#ifndef STATUS_VOLSNAP_HIBERNATE_READY+# define STATUS_VOLSNAP_HIBERNATE_READY ((NTSTATUS) 0x00000125L)+#endif++#ifndef STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY+# define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY ((NTSTATUS) 0x00000126L)+#endif++#ifndef STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED+# define STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED ((NTSTATUS) 0x00000127L)+#endif++#ifndef STATUS_INTERRUPT_STILL_CONNECTED+# define STATUS_INTERRUPT_STILL_CONNECTED ((NTSTATUS) 0x00000128L)+#endif++#ifndef STATUS_PROCESS_CLONED+# define STATUS_PROCESS_CLONED ((NTSTATUS) 0x00000129L)+#endif++#ifndef STATUS_FILE_LOCKED_WITH_ONLY_READERS+# define STATUS_FILE_LOCKED_WITH_ONLY_READERS ((NTSTATUS) 0x0000012AL)+#endif++#ifndef STATUS_FILE_LOCKED_WITH_WRITERS+# define STATUS_FILE_LOCKED_WITH_WRITERS ((NTSTATUS) 0x0000012BL)+#endif++#ifndef STATUS_RESOURCEMANAGER_READ_ONLY+# define STATUS_RESOURCEMANAGER_READ_ONLY ((NTSTATUS) 0x00000202L)+#endif++#ifndef STATUS_RING_PREVIOUSLY_EMPTY+# define STATUS_RING_PREVIOUSLY_EMPTY ((NTSTATUS) 0x00000210L)+#endif++#ifndef STATUS_RING_PREVIOUSLY_FULL+# define STATUS_RING_PREVIOUSLY_FULL ((NTSTATUS) 0x00000211L)+#endif++#ifndef STATUS_RING_PREVIOUSLY_ABOVE_QUOTA+# define STATUS_RING_PREVIOUSLY_ABOVE_QUOTA ((NTSTATUS) 0x00000212L)+#endif++#ifndef STATUS_RING_NEWLY_EMPTY+# define STATUS_RING_NEWLY_EMPTY ((NTSTATUS) 0x00000213L)+#endif++#ifndef STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT+# define STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT ((NTSTATUS) 0x00000214L)+#endif++#ifndef STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE+# define STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE ((NTSTATUS) 0x00000215L)+#endif++#ifndef STATUS_OPLOCK_HANDLE_CLOSED+# define STATUS_OPLOCK_HANDLE_CLOSED ((NTSTATUS) 0x00000216L)+#endif++#ifndef STATUS_WAIT_FOR_OPLOCK+# define STATUS_WAIT_FOR_OPLOCK ((NTSTATUS) 0x00000367L)+#endif++#ifndef STATUS_OBJECT_NAME_EXISTS+# define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS) 0x40000000L)+#endif++#ifndef STATUS_THREAD_WAS_SUSPENDED+# define STATUS_THREAD_WAS_SUSPENDED ((NTSTATUS) 0x40000001L)+#endif++#ifndef STATUS_WORKING_SET_LIMIT_RANGE+# define STATUS_WORKING_SET_LIMIT_RANGE ((NTSTATUS) 0x40000002L)+#endif++#ifndef STATUS_IMAGE_NOT_AT_BASE+# define STATUS_IMAGE_NOT_AT_BASE ((NTSTATUS) 0x40000003L)+#endif++#ifndef STATUS_RXACT_STATE_CREATED+# define STATUS_RXACT_STATE_CREATED ((NTSTATUS) 0x40000004L)+#endif++#ifndef STATUS_SEGMENT_NOTIFICATION+# define STATUS_SEGMENT_NOTIFICATION ((NTSTATUS) 0x40000005L)+#endif++#ifndef STATUS_LOCAL_USER_SESSION_KEY+# define STATUS_LOCAL_USER_SESSION_KEY ((NTSTATUS) 0x40000006L)+#endif++#ifndef STATUS_BAD_CURRENT_DIRECTORY+# define STATUS_BAD_CURRENT_DIRECTORY ((NTSTATUS) 0x40000007L)+#endif++#ifndef STATUS_SERIAL_MORE_WRITES+# define STATUS_SERIAL_MORE_WRITES ((NTSTATUS) 0x40000008L)+#endif++#ifndef STATUS_REGISTRY_RECOVERED+# define STATUS_REGISTRY_RECOVERED ((NTSTATUS) 0x40000009L)+#endif++#ifndef STATUS_FT_READ_RECOVERY_FROM_BACKUP+# define STATUS_FT_READ_RECOVERY_FROM_BACKUP ((NTSTATUS) 0x4000000AL)+#endif++#ifndef STATUS_FT_WRITE_RECOVERY+# define STATUS_FT_WRITE_RECOVERY ((NTSTATUS) 0x4000000BL)+#endif++#ifndef STATUS_SERIAL_COUNTER_TIMEOUT+# define STATUS_SERIAL_COUNTER_TIMEOUT ((NTSTATUS) 0x4000000CL)+#endif++#ifndef STATUS_NULL_LM_PASSWORD+# define STATUS_NULL_LM_PASSWORD ((NTSTATUS) 0x4000000DL)+#endif++#ifndef STATUS_IMAGE_MACHINE_TYPE_MISMATCH+# define STATUS_IMAGE_MACHINE_TYPE_MISMATCH ((NTSTATUS) 0x4000000EL)+#endif++#ifndef STATUS_RECEIVE_PARTIAL+# define STATUS_RECEIVE_PARTIAL ((NTSTATUS) 0x4000000FL)+#endif++#ifndef STATUS_RECEIVE_EXPEDITED+# define STATUS_RECEIVE_EXPEDITED ((NTSTATUS) 0x40000010L)+#endif++#ifndef STATUS_RECEIVE_PARTIAL_EXPEDITED+# define STATUS_RECEIVE_PARTIAL_EXPEDITED ((NTSTATUS) 0x40000011L)+#endif++#ifndef STATUS_EVENT_DONE+# define STATUS_EVENT_DONE ((NTSTATUS) 0x40000012L)+#endif++#ifndef STATUS_EVENT_PENDING+# define STATUS_EVENT_PENDING ((NTSTATUS) 0x40000013L)+#endif++#ifndef STATUS_CHECKING_FILE_SYSTEM+# define STATUS_CHECKING_FILE_SYSTEM ((NTSTATUS) 0x40000014L)+#endif++#ifndef STATUS_FATAL_APP_EXIT+# define STATUS_FATAL_APP_EXIT ((NTSTATUS) 0x40000015L)+#endif++#ifndef STATUS_PREDEFINED_HANDLE+# define STATUS_PREDEFINED_HANDLE ((NTSTATUS) 0x40000016L)+#endif++#ifndef STATUS_WAS_UNLOCKED+# define STATUS_WAS_UNLOCKED ((NTSTATUS) 0x40000017L)+#endif++#ifndef STATUS_SERVICE_NOTIFICATION+# define STATUS_SERVICE_NOTIFICATION ((NTSTATUS) 0x40000018L)+#endif++#ifndef STATUS_WAS_LOCKED+# define STATUS_WAS_LOCKED ((NTSTATUS) 0x40000019L)+#endif++#ifndef STATUS_LOG_HARD_ERROR+# define STATUS_LOG_HARD_ERROR ((NTSTATUS) 0x4000001AL)+#endif++#ifndef STATUS_ALREADY_WIN32+# define STATUS_ALREADY_WIN32 ((NTSTATUS) 0x4000001BL)+#endif++#ifndef STATUS_WX86_UNSIMULATE+# define STATUS_WX86_UNSIMULATE ((NTSTATUS) 0x4000001CL)+#endif++#ifndef STATUS_WX86_CONTINUE+# define STATUS_WX86_CONTINUE ((NTSTATUS) 0x4000001DL)+#endif++#ifndef STATUS_WX86_SINGLE_STEP+# define STATUS_WX86_SINGLE_STEP ((NTSTATUS) 0x4000001EL)+#endif++#ifndef STATUS_WX86_BREAKPOINT+# define STATUS_WX86_BREAKPOINT ((NTSTATUS) 0x4000001FL)+#endif++#ifndef STATUS_WX86_EXCEPTION_CONTINUE+# define STATUS_WX86_EXCEPTION_CONTINUE ((NTSTATUS) 0x40000020L)+#endif++#ifndef STATUS_WX86_EXCEPTION_LASTCHANCE+# define STATUS_WX86_EXCEPTION_LASTCHANCE ((NTSTATUS) 0x40000021L)+#endif++#ifndef STATUS_WX86_EXCEPTION_CHAIN+# define STATUS_WX86_EXCEPTION_CHAIN ((NTSTATUS) 0x40000022L)+#endif++#ifndef STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE+# define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE ((NTSTATUS) 0x40000023L)+#endif++#ifndef STATUS_NO_YIELD_PERFORMED+# define STATUS_NO_YIELD_PERFORMED ((NTSTATUS) 0x40000024L)+#endif++#ifndef STATUS_TIMER_RESUME_IGNORED+# define STATUS_TIMER_RESUME_IGNORED ((NTSTATUS) 0x40000025L)+#endif++#ifndef STATUS_ARBITRATION_UNHANDLED+# define STATUS_ARBITRATION_UNHANDLED ((NTSTATUS) 0x40000026L)+#endif++#ifndef STATUS_CARDBUS_NOT_SUPPORTED+# define STATUS_CARDBUS_NOT_SUPPORTED ((NTSTATUS) 0x40000027L)+#endif++#ifndef STATUS_WX86_CREATEWX86TIB+# define STATUS_WX86_CREATEWX86TIB ((NTSTATUS) 0x40000028L)+#endif++#ifndef STATUS_MP_PROCESSOR_MISMATCH+# define STATUS_MP_PROCESSOR_MISMATCH ((NTSTATUS) 0x40000029L)+#endif++#ifndef STATUS_HIBERNATED+# define STATUS_HIBERNATED ((NTSTATUS) 0x4000002AL)+#endif++#ifndef STATUS_RESUME_HIBERNATION+# define STATUS_RESUME_HIBERNATION ((NTSTATUS) 0x4000002BL)+#endif++#ifndef STATUS_FIRMWARE_UPDATED+# define STATUS_FIRMWARE_UPDATED ((NTSTATUS) 0x4000002CL)+#endif++#ifndef STATUS_DRIVERS_LEAKING_LOCKED_PAGES+# define STATUS_DRIVERS_LEAKING_LOCKED_PAGES ((NTSTATUS) 0x4000002DL)+#endif++#ifndef STATUS_MESSAGE_RETRIEVED+# define STATUS_MESSAGE_RETRIEVED ((NTSTATUS) 0x4000002EL)+#endif++#ifndef STATUS_SYSTEM_POWERSTATE_TRANSITION+# define STATUS_SYSTEM_POWERSTATE_TRANSITION ((NTSTATUS) 0x4000002FL)+#endif++#ifndef STATUS_ALPC_CHECK_COMPLETION_LIST+# define STATUS_ALPC_CHECK_COMPLETION_LIST ((NTSTATUS) 0x40000030L)+#endif++#ifndef STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION+# define STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION ((NTSTATUS) 0x40000031L)+#endif++#ifndef STATUS_ACCESS_AUDIT_BY_POLICY+# define STATUS_ACCESS_AUDIT_BY_POLICY ((NTSTATUS) 0x40000032L)+#endif++#ifndef STATUS_ABANDON_HIBERFILE+# define STATUS_ABANDON_HIBERFILE ((NTSTATUS) 0x40000033L)+#endif++#ifndef STATUS_BIZRULES_NOT_ENABLED+# define STATUS_BIZRULES_NOT_ENABLED ((NTSTATUS) 0x40000034L)+#endif++#ifndef STATUS_GUARD_PAGE_VIOLATION+# define STATUS_GUARD_PAGE_VIOLATION ((NTSTATUS) 0x80000001L)+#endif++#ifndef STATUS_DATATYPE_MISALIGNMENT+# define STATUS_DATATYPE_MISALIGNMENT ((NTSTATUS) 0x80000002L)+#endif++#ifndef STATUS_BREAKPOINT+# define STATUS_BREAKPOINT ((NTSTATUS) 0x80000003L)+#endif++#ifndef STATUS_SINGLE_STEP+# define STATUS_SINGLE_STEP ((NTSTATUS) 0x80000004L)+#endif++#ifndef STATUS_BUFFER_OVERFLOW+# define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005L)+#endif++#ifndef STATUS_NO_MORE_FILES+# define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006L)+#endif++#ifndef STATUS_WAKE_SYSTEM_DEBUGGER+# define STATUS_WAKE_SYSTEM_DEBUGGER ((NTSTATUS) 0x80000007L)+#endif++#ifndef STATUS_HANDLES_CLOSED+# define STATUS_HANDLES_CLOSED ((NTSTATUS) 0x8000000AL)+#endif++#ifndef STATUS_NO_INHERITANCE+# define STATUS_NO_INHERITANCE ((NTSTATUS) 0x8000000BL)+#endif++#ifndef STATUS_GUID_SUBSTITUTION_MADE+# define STATUS_GUID_SUBSTITUTION_MADE ((NTSTATUS) 0x8000000CL)+#endif++#ifndef STATUS_PARTIAL_COPY+# define STATUS_PARTIAL_COPY ((NTSTATUS) 0x8000000DL)+#endif++#ifndef STATUS_DEVICE_PAPER_EMPTY+# define STATUS_DEVICE_PAPER_EMPTY ((NTSTATUS) 0x8000000EL)+#endif++#ifndef STATUS_DEVICE_POWERED_OFF+# define STATUS_DEVICE_POWERED_OFF ((NTSTATUS) 0x8000000FL)+#endif++#ifndef STATUS_DEVICE_OFF_LINE+# define STATUS_DEVICE_OFF_LINE ((NTSTATUS) 0x80000010L)+#endif++#ifndef STATUS_DEVICE_BUSY+# define STATUS_DEVICE_BUSY ((NTSTATUS) 0x80000011L)+#endif++#ifndef STATUS_NO_MORE_EAS+# define STATUS_NO_MORE_EAS ((NTSTATUS) 0x80000012L)+#endif++#ifndef STATUS_INVALID_EA_NAME+# define STATUS_INVALID_EA_NAME ((NTSTATUS) 0x80000013L)+#endif++#ifndef STATUS_EA_LIST_INCONSISTENT+# define STATUS_EA_LIST_INCONSISTENT ((NTSTATUS) 0x80000014L)+#endif++#ifndef STATUS_INVALID_EA_FLAG+# define STATUS_INVALID_EA_FLAG ((NTSTATUS) 0x80000015L)+#endif++#ifndef STATUS_VERIFY_REQUIRED+# define STATUS_VERIFY_REQUIRED ((NTSTATUS) 0x80000016L)+#endif++#ifndef STATUS_EXTRANEOUS_INFORMATION+# define STATUS_EXTRANEOUS_INFORMATION ((NTSTATUS) 0x80000017L)+#endif++#ifndef STATUS_RXACT_COMMIT_NECESSARY+# define STATUS_RXACT_COMMIT_NECESSARY ((NTSTATUS) 0x80000018L)+#endif++#ifndef STATUS_NO_MORE_ENTRIES+# define STATUS_NO_MORE_ENTRIES ((NTSTATUS) 0x8000001AL)+#endif++#ifndef STATUS_FILEMARK_DETECTED+# define STATUS_FILEMARK_DETECTED ((NTSTATUS) 0x8000001BL)+#endif++#ifndef STATUS_MEDIA_CHANGED+# define STATUS_MEDIA_CHANGED ((NTSTATUS) 0x8000001CL)+#endif++#ifndef STATUS_BUS_RESET+# define STATUS_BUS_RESET ((NTSTATUS) 0x8000001DL)+#endif++#ifndef STATUS_END_OF_MEDIA+# define STATUS_END_OF_MEDIA ((NTSTATUS) 0x8000001EL)+#endif++#ifndef STATUS_BEGINNING_OF_MEDIA+# define STATUS_BEGINNING_OF_MEDIA ((NTSTATUS) 0x8000001FL)+#endif++#ifndef STATUS_MEDIA_CHECK+# define STATUS_MEDIA_CHECK ((NTSTATUS) 0x80000020L)+#endif++#ifndef STATUS_SETMARK_DETECTED+# define STATUS_SETMARK_DETECTED ((NTSTATUS) 0x80000021L)+#endif++#ifndef STATUS_NO_DATA_DETECTED+# define STATUS_NO_DATA_DETECTED ((NTSTATUS) 0x80000022L)+#endif++#ifndef STATUS_REDIRECTOR_HAS_OPEN_HANDLES+# define STATUS_REDIRECTOR_HAS_OPEN_HANDLES ((NTSTATUS) 0x80000023L)+#endif++#ifndef STATUS_SERVER_HAS_OPEN_HANDLES+# define STATUS_SERVER_HAS_OPEN_HANDLES ((NTSTATUS) 0x80000024L)+#endif++#ifndef STATUS_ALREADY_DISCONNECTED+# define STATUS_ALREADY_DISCONNECTED ((NTSTATUS) 0x80000025L)+#endif++#ifndef STATUS_LONGJUMP+# define STATUS_LONGJUMP ((NTSTATUS) 0x80000026L)+#endif++#ifndef STATUS_CLEANER_CARTRIDGE_INSTALLED+# define STATUS_CLEANER_CARTRIDGE_INSTALLED ((NTSTATUS) 0x80000027L)+#endif++#ifndef STATUS_PLUGPLAY_QUERY_VETOED+# define STATUS_PLUGPLAY_QUERY_VETOED ((NTSTATUS) 0x80000028L)+#endif++#ifndef STATUS_UNWIND_CONSOLIDATE+# define STATUS_UNWIND_CONSOLIDATE ((NTSTATUS) 0x80000029L)+#endif++#ifndef STATUS_REGISTRY_HIVE_RECOVERED+# define STATUS_REGISTRY_HIVE_RECOVERED ((NTSTATUS) 0x8000002AL)+#endif++#ifndef STATUS_DLL_MIGHT_BE_INSECURE+# define STATUS_DLL_MIGHT_BE_INSECURE ((NTSTATUS) 0x8000002BL)+#endif++#ifndef STATUS_DLL_MIGHT_BE_INCOMPATIBLE+# define STATUS_DLL_MIGHT_BE_INCOMPATIBLE ((NTSTATUS) 0x8000002CL)+#endif++#ifndef STATUS_STOPPED_ON_SYMLINK+# define STATUS_STOPPED_ON_SYMLINK ((NTSTATUS) 0x8000002DL)+#endif++#ifndef STATUS_CANNOT_GRANT_REQUESTED_OPLOCK+# define STATUS_CANNOT_GRANT_REQUESTED_OPLOCK ((NTSTATUS) 0x8000002EL)+#endif++#ifndef STATUS_NO_ACE_CONDITION+# define STATUS_NO_ACE_CONDITION ((NTSTATUS) 0x8000002FL)+#endif++#ifndef STATUS_UNSUCCESSFUL+# define STATUS_UNSUCCESSFUL ((NTSTATUS) 0xC0000001L)+#endif++#ifndef STATUS_NOT_IMPLEMENTED+# define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xC0000002L)+#endif++#ifndef STATUS_INVALID_INFO_CLASS+# define STATUS_INVALID_INFO_CLASS ((NTSTATUS) 0xC0000003L)+#endif++#ifndef STATUS_INFO_LENGTH_MISMATCH+# define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xC0000004L)+#endif++#ifndef STATUS_ACCESS_VIOLATION+# define STATUS_ACCESS_VIOLATION ((NTSTATUS) 0xC0000005L)+#endif++#ifndef STATUS_IN_PAGE_ERROR+# define STATUS_IN_PAGE_ERROR ((NTSTATUS) 0xC0000006L)+#endif++#ifndef STATUS_PAGEFILE_QUOTA+# define STATUS_PAGEFILE_QUOTA ((NTSTATUS) 0xC0000007L)+#endif++#ifndef STATUS_INVALID_HANDLE+# define STATUS_INVALID_HANDLE ((NTSTATUS) 0xC0000008L)+#endif++#ifndef STATUS_BAD_INITIAL_STACK+# define STATUS_BAD_INITIAL_STACK ((NTSTATUS) 0xC0000009L)+#endif++#ifndef STATUS_BAD_INITIAL_PC+# define STATUS_BAD_INITIAL_PC ((NTSTATUS) 0xC000000AL)+#endif++#ifndef STATUS_INVALID_CID+# define STATUS_INVALID_CID ((NTSTATUS) 0xC000000BL)+#endif++#ifndef STATUS_TIMER_NOT_CANCELED+# define STATUS_TIMER_NOT_CANCELED ((NTSTATUS) 0xC000000CL)+#endif++#ifndef STATUS_INVALID_PARAMETER+# define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL)+#endif++#ifndef STATUS_NO_SUCH_DEVICE+# define STATUS_NO_SUCH_DEVICE ((NTSTATUS) 0xC000000EL)+#endif++#ifndef STATUS_NO_SUCH_FILE+# define STATUS_NO_SUCH_FILE ((NTSTATUS) 0xC000000FL)+#endif++#ifndef STATUS_INVALID_DEVICE_REQUEST+# define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xC0000010L)+#endif++#ifndef STATUS_END_OF_FILE+# define STATUS_END_OF_FILE ((NTSTATUS) 0xC0000011L)+#endif++#ifndef STATUS_WRONG_VOLUME+# define STATUS_WRONG_VOLUME ((NTSTATUS) 0xC0000012L)+#endif++#ifndef STATUS_NO_MEDIA_IN_DEVICE+# define STATUS_NO_MEDIA_IN_DEVICE ((NTSTATUS) 0xC0000013L)+#endif++#ifndef STATUS_UNRECOGNIZED_MEDIA+# define STATUS_UNRECOGNIZED_MEDIA ((NTSTATUS) 0xC0000014L)+#endif++#ifndef STATUS_NONEXISTENT_SECTOR+# define STATUS_NONEXISTENT_SECTOR ((NTSTATUS) 0xC0000015L)+#endif++#ifndef STATUS_MORE_PROCESSING_REQUIRED+# define STATUS_MORE_PROCESSING_REQUIRED ((NTSTATUS) 0xC0000016L)+#endif++#ifndef STATUS_NO_MEMORY+# define STATUS_NO_MEMORY ((NTSTATUS) 0xC0000017L)+#endif++#ifndef STATUS_CONFLICTING_ADDRESSES+# define STATUS_CONFLICTING_ADDRESSES ((NTSTATUS) 0xC0000018L)+#endif++#ifndef STATUS_NOT_MAPPED_VIEW+# define STATUS_NOT_MAPPED_VIEW ((NTSTATUS) 0xC0000019L)+#endif++#ifndef STATUS_UNABLE_TO_FREE_VM+# define STATUS_UNABLE_TO_FREE_VM ((NTSTATUS) 0xC000001AL)+#endif++#ifndef STATUS_UNABLE_TO_DELETE_SECTION+# define STATUS_UNABLE_TO_DELETE_SECTION ((NTSTATUS) 0xC000001BL)+#endif++#ifndef STATUS_INVALID_SYSTEM_SERVICE+# define STATUS_INVALID_SYSTEM_SERVICE ((NTSTATUS) 0xC000001CL)+#endif++#ifndef STATUS_ILLEGAL_INSTRUCTION+# define STATUS_ILLEGAL_INSTRUCTION ((NTSTATUS) 0xC000001DL)+#endif++#ifndef STATUS_INVALID_LOCK_SEQUENCE+# define STATUS_INVALID_LOCK_SEQUENCE ((NTSTATUS) 0xC000001EL)+#endif++#ifndef STATUS_INVALID_VIEW_SIZE+# define STATUS_INVALID_VIEW_SIZE ((NTSTATUS) 0xC000001FL)+#endif++#ifndef STATUS_INVALID_FILE_FOR_SECTION+# define STATUS_INVALID_FILE_FOR_SECTION ((NTSTATUS) 0xC0000020L)+#endif++#ifndef STATUS_ALREADY_COMMITTED+# define STATUS_ALREADY_COMMITTED ((NTSTATUS) 0xC0000021L)+#endif++#ifndef STATUS_ACCESS_DENIED+# define STATUS_ACCESS_DENIED ((NTSTATUS) 0xC0000022L)+#endif++#ifndef STATUS_BUFFER_TOO_SMALL+# define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xC0000023L)+#endif++#ifndef STATUS_OBJECT_TYPE_MISMATCH+# define STATUS_OBJECT_TYPE_MISMATCH ((NTSTATUS) 0xC0000024L)+#endif++#ifndef STATUS_NONCONTINUABLE_EXCEPTION+# define STATUS_NONCONTINUABLE_EXCEPTION ((NTSTATUS) 0xC0000025L)+#endif++#ifndef STATUS_INVALID_DISPOSITION+# define STATUS_INVALID_DISPOSITION ((NTSTATUS) 0xC0000026L)+#endif++#ifndef STATUS_UNWIND+# define STATUS_UNWIND ((NTSTATUS) 0xC0000027L)+#endif++#ifndef STATUS_BAD_STACK+# define STATUS_BAD_STACK ((NTSTATUS) 0xC0000028L)+#endif++#ifndef STATUS_INVALID_UNWIND_TARGET+# define STATUS_INVALID_UNWIND_TARGET ((NTSTATUS) 0xC0000029L)+#endif++#ifndef STATUS_NOT_LOCKED+# define STATUS_NOT_LOCKED ((NTSTATUS) 0xC000002AL)+#endif++#ifndef STATUS_PARITY_ERROR+# define STATUS_PARITY_ERROR ((NTSTATUS) 0xC000002BL)+#endif++#ifndef STATUS_UNABLE_TO_DECOMMIT_VM+# define STATUS_UNABLE_TO_DECOMMIT_VM ((NTSTATUS) 0xC000002CL)+#endif++#ifndef STATUS_NOT_COMMITTED+# define STATUS_NOT_COMMITTED ((NTSTATUS) 0xC000002DL)+#endif++#ifndef STATUS_INVALID_PORT_ATTRIBUTES+# define STATUS_INVALID_PORT_ATTRIBUTES ((NTSTATUS) 0xC000002EL)+#endif++#ifndef STATUS_PORT_MESSAGE_TOO_LONG+# define STATUS_PORT_MESSAGE_TOO_LONG ((NTSTATUS) 0xC000002FL)+#endif++#ifndef STATUS_INVALID_PARAMETER_MIX+# define STATUS_INVALID_PARAMETER_MIX ((NTSTATUS) 0xC0000030L)+#endif++#ifndef STATUS_INVALID_QUOTA_LOWER+# define STATUS_INVALID_QUOTA_LOWER ((NTSTATUS) 0xC0000031L)+#endif++#ifndef STATUS_DISK_CORRUPT_ERROR+# define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS) 0xC0000032L)+#endif++#ifndef STATUS_OBJECT_NAME_INVALID+# define STATUS_OBJECT_NAME_INVALID ((NTSTATUS) 0xC0000033L)+#endif++#ifndef STATUS_OBJECT_NAME_NOT_FOUND+# define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xC0000034L)+#endif++#ifndef STATUS_OBJECT_NAME_COLLISION+# define STATUS_OBJECT_NAME_COLLISION ((NTSTATUS) 0xC0000035L)+#endif++#ifndef STATUS_PORT_DISCONNECTED+# define STATUS_PORT_DISCONNECTED ((NTSTATUS) 0xC0000037L)+#endif++#ifndef STATUS_DEVICE_ALREADY_ATTACHED+# define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS) 0xC0000038L)+#endif++#ifndef STATUS_OBJECT_PATH_INVALID+# define STATUS_OBJECT_PATH_INVALID ((NTSTATUS) 0xC0000039L)+#endif++#ifndef STATUS_OBJECT_PATH_NOT_FOUND+# define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xC000003AL)+#endif++#ifndef STATUS_OBJECT_PATH_SYNTAX_BAD+# define STATUS_OBJECT_PATH_SYNTAX_BAD ((NTSTATUS) 0xC000003BL)+#endif++#ifndef STATUS_DATA_OVERRUN+# define STATUS_DATA_OVERRUN ((NTSTATUS) 0xC000003CL)+#endif++#ifndef STATUS_DATA_LATE_ERROR+# define STATUS_DATA_LATE_ERROR ((NTSTATUS) 0xC000003DL)+#endif++#ifndef STATUS_DATA_ERROR+# define STATUS_DATA_ERROR ((NTSTATUS) 0xC000003EL)+#endif++#ifndef STATUS_CRC_ERROR+# define STATUS_CRC_ERROR ((NTSTATUS) 0xC000003FL)+#endif++#ifndef STATUS_SECTION_TOO_BIG+# define STATUS_SECTION_TOO_BIG ((NTSTATUS) 0xC0000040L)+#endif++#ifndef STATUS_PORT_CONNECTION_REFUSED+# define STATUS_PORT_CONNECTION_REFUSED ((NTSTATUS) 0xC0000041L)+#endif++#ifndef STATUS_INVALID_PORT_HANDLE+# define STATUS_INVALID_PORT_HANDLE ((NTSTATUS) 0xC0000042L)+#endif++#ifndef STATUS_SHARING_VIOLATION+# define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xC0000043L)+#endif++#ifndef STATUS_QUOTA_EXCEEDED+# define STATUS_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000044L)+#endif++#ifndef STATUS_INVALID_PAGE_PROTECTION+# define STATUS_INVALID_PAGE_PROTECTION ((NTSTATUS) 0xC0000045L)+#endif++#ifndef STATUS_MUTANT_NOT_OWNED+# define STATUS_MUTANT_NOT_OWNED ((NTSTATUS) 0xC0000046L)+#endif++#ifndef STATUS_SEMAPHORE_LIMIT_EXCEEDED+# define STATUS_SEMAPHORE_LIMIT_EXCEEDED ((NTSTATUS) 0xC0000047L)+#endif++#ifndef STATUS_PORT_ALREADY_SET+# define STATUS_PORT_ALREADY_SET ((NTSTATUS) 0xC0000048L)+#endif++#ifndef STATUS_SECTION_NOT_IMAGE+# define STATUS_SECTION_NOT_IMAGE ((NTSTATUS) 0xC0000049L)+#endif++#ifndef STATUS_SUSPEND_COUNT_EXCEEDED+# define STATUS_SUSPEND_COUNT_EXCEEDED ((NTSTATUS) 0xC000004AL)+#endif++#ifndef STATUS_THREAD_IS_TERMINATING+# define STATUS_THREAD_IS_TERMINATING ((NTSTATUS) 0xC000004BL)+#endif++#ifndef STATUS_BAD_WORKING_SET_LIMIT+# define STATUS_BAD_WORKING_SET_LIMIT ((NTSTATUS) 0xC000004CL)+#endif++#ifndef STATUS_INCOMPATIBLE_FILE_MAP+# define STATUS_INCOMPATIBLE_FILE_MAP ((NTSTATUS) 0xC000004DL)+#endif++#ifndef STATUS_SECTION_PROTECTION+# define STATUS_SECTION_PROTECTION ((NTSTATUS) 0xC000004EL)+#endif++#ifndef STATUS_EAS_NOT_SUPPORTED+# define STATUS_EAS_NOT_SUPPORTED ((NTSTATUS) 0xC000004FL)+#endif++#ifndef STATUS_EA_TOO_LARGE+# define STATUS_EA_TOO_LARGE ((NTSTATUS) 0xC0000050L)+#endif++#ifndef STATUS_NONEXISTENT_EA_ENTRY+# define STATUS_NONEXISTENT_EA_ENTRY ((NTSTATUS) 0xC0000051L)+#endif++#ifndef STATUS_NO_EAS_ON_FILE+# define STATUS_NO_EAS_ON_FILE ((NTSTATUS) 0xC0000052L)+#endif++#ifndef STATUS_EA_CORRUPT_ERROR+# define STATUS_EA_CORRUPT_ERROR ((NTSTATUS) 0xC0000053L)+#endif++#ifndef STATUS_FILE_LOCK_CONFLICT+# define STATUS_FILE_LOCK_CONFLICT ((NTSTATUS) 0xC0000054L)+#endif++#ifndef STATUS_LOCK_NOT_GRANTED+# define STATUS_LOCK_NOT_GRANTED ((NTSTATUS) 0xC0000055L)+#endif++#ifndef STATUS_DELETE_PENDING+# define STATUS_DELETE_PENDING ((NTSTATUS) 0xC0000056L)+#endif++#ifndef STATUS_CTL_FILE_NOT_SUPPORTED+# define STATUS_CTL_FILE_NOT_SUPPORTED ((NTSTATUS) 0xC0000057L)+#endif++#ifndef STATUS_UNKNOWN_REVISION+# define STATUS_UNKNOWN_REVISION ((NTSTATUS) 0xC0000058L)+#endif++#ifndef STATUS_REVISION_MISMATCH+# define STATUS_REVISION_MISMATCH ((NTSTATUS) 0xC0000059L)+#endif++#ifndef STATUS_INVALID_OWNER+# define STATUS_INVALID_OWNER ((NTSTATUS) 0xC000005AL)+#endif++#ifndef STATUS_INVALID_PRIMARY_GROUP+# define STATUS_INVALID_PRIMARY_GROUP ((NTSTATUS) 0xC000005BL)+#endif++#ifndef STATUS_NO_IMPERSONATION_TOKEN+# define STATUS_NO_IMPERSONATION_TOKEN ((NTSTATUS) 0xC000005CL)+#endif++#ifndef STATUS_CANT_DISABLE_MANDATORY+# define STATUS_CANT_DISABLE_MANDATORY ((NTSTATUS) 0xC000005DL)+#endif++#ifndef STATUS_NO_LOGON_SERVERS+# define STATUS_NO_LOGON_SERVERS ((NTSTATUS) 0xC000005EL)+#endif++#ifndef STATUS_NO_SUCH_LOGON_SESSION+# define STATUS_NO_SUCH_LOGON_SESSION ((NTSTATUS) 0xC000005FL)+#endif++#ifndef STATUS_NO_SUCH_PRIVILEGE+# define STATUS_NO_SUCH_PRIVILEGE ((NTSTATUS) 0xC0000060L)+#endif++#ifndef STATUS_PRIVILEGE_NOT_HELD+# define STATUS_PRIVILEGE_NOT_HELD ((NTSTATUS) 0xC0000061L)+#endif++#ifndef STATUS_INVALID_ACCOUNT_NAME+# define STATUS_INVALID_ACCOUNT_NAME ((NTSTATUS) 0xC0000062L)+#endif++#ifndef STATUS_USER_EXISTS+# define STATUS_USER_EXISTS ((NTSTATUS) 0xC0000063L)+#endif++#ifndef STATUS_NO_SUCH_USER+# define STATUS_NO_SUCH_USER ((NTSTATUS) 0xC0000064L)+#endif++#ifndef STATUS_GROUP_EXISTS+# define STATUS_GROUP_EXISTS ((NTSTATUS) 0xC0000065L)+#endif++#ifndef STATUS_NO_SUCH_GROUP+# define STATUS_NO_SUCH_GROUP ((NTSTATUS) 0xC0000066L)+#endif++#ifndef STATUS_MEMBER_IN_GROUP+# define STATUS_MEMBER_IN_GROUP ((NTSTATUS) 0xC0000067L)+#endif++#ifndef STATUS_MEMBER_NOT_IN_GROUP+# define STATUS_MEMBER_NOT_IN_GROUP ((NTSTATUS) 0xC0000068L)+#endif++#ifndef STATUS_LAST_ADMIN+# define STATUS_LAST_ADMIN ((NTSTATUS) 0xC0000069L)+#endif++#ifndef STATUS_WRONG_PASSWORD+# define STATUS_WRONG_PASSWORD ((NTSTATUS) 0xC000006AL)+#endif++#ifndef STATUS_ILL_FORMED_PASSWORD+# define STATUS_ILL_FORMED_PASSWORD ((NTSTATUS) 0xC000006BL)+#endif++#ifndef STATUS_PASSWORD_RESTRICTION+# define STATUS_PASSWORD_RESTRICTION ((NTSTATUS) 0xC000006CL)+#endif++#ifndef STATUS_LOGON_FAILURE+# define STATUS_LOGON_FAILURE ((NTSTATUS) 0xC000006DL)+#endif++#ifndef STATUS_ACCOUNT_RESTRICTION+# define STATUS_ACCOUNT_RESTRICTION ((NTSTATUS) 0xC000006EL)+#endif++#ifndef STATUS_INVALID_LOGON_HOURS+# define STATUS_INVALID_LOGON_HOURS ((NTSTATUS) 0xC000006FL)+#endif++#ifndef STATUS_INVALID_WORKSTATION+# define STATUS_INVALID_WORKSTATION ((NTSTATUS) 0xC0000070L)+#endif++#ifndef STATUS_PASSWORD_EXPIRED+# define STATUS_PASSWORD_EXPIRED ((NTSTATUS) 0xC0000071L)+#endif++#ifndef STATUS_ACCOUNT_DISABLED+# define STATUS_ACCOUNT_DISABLED ((NTSTATUS) 0xC0000072L)+#endif++#ifndef STATUS_NONE_MAPPED+# define STATUS_NONE_MAPPED ((NTSTATUS) 0xC0000073L)+#endif++#ifndef STATUS_TOO_MANY_LUIDS_REQUESTED+# define STATUS_TOO_MANY_LUIDS_REQUESTED ((NTSTATUS) 0xC0000074L)+#endif++#ifndef STATUS_LUIDS_EXHAUSTED+# define STATUS_LUIDS_EXHAUSTED ((NTSTATUS) 0xC0000075L)+#endif++#ifndef STATUS_INVALID_SUB_AUTHORITY+# define STATUS_INVALID_SUB_AUTHORITY ((NTSTATUS) 0xC0000076L)+#endif++#ifndef STATUS_INVALID_ACL+# define STATUS_INVALID_ACL ((NTSTATUS) 0xC0000077L)+#endif++#ifndef STATUS_INVALID_SID+# define STATUS_INVALID_SID ((NTSTATUS) 0xC0000078L)+#endif++#ifndef STATUS_INVALID_SECURITY_DESCR+# define STATUS_INVALID_SECURITY_DESCR ((NTSTATUS) 0xC0000079L)+#endif++#ifndef STATUS_PROCEDURE_NOT_FOUND+# define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS) 0xC000007AL)+#endif++#ifndef STATUS_INVALID_IMAGE_FORMAT+# define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS) 0xC000007BL)+#endif++#ifndef STATUS_NO_TOKEN+# define STATUS_NO_TOKEN ((NTSTATUS) 0xC000007CL)+#endif++#ifndef STATUS_BAD_INHERITANCE_ACL+# define STATUS_BAD_INHERITANCE_ACL ((NTSTATUS) 0xC000007DL)+#endif++#ifndef STATUS_RANGE_NOT_LOCKED+# define STATUS_RANGE_NOT_LOCKED ((NTSTATUS) 0xC000007EL)+#endif++#ifndef STATUS_DISK_FULL+# define STATUS_DISK_FULL ((NTSTATUS) 0xC000007FL)+#endif++#ifndef STATUS_SERVER_DISABLED+# define STATUS_SERVER_DISABLED ((NTSTATUS) 0xC0000080L)+#endif++#ifndef STATUS_SERVER_NOT_DISABLED+# define STATUS_SERVER_NOT_DISABLED ((NTSTATUS) 0xC0000081L)+#endif++#ifndef STATUS_TOO_MANY_GUIDS_REQUESTED+# define STATUS_TOO_MANY_GUIDS_REQUESTED ((NTSTATUS) 0xC0000082L)+#endif++#ifndef STATUS_GUIDS_EXHAUSTED+# define STATUS_GUIDS_EXHAUSTED ((NTSTATUS) 0xC0000083L)+#endif++#ifndef STATUS_INVALID_ID_AUTHORITY+# define STATUS_INVALID_ID_AUTHORITY ((NTSTATUS) 0xC0000084L)+#endif++#ifndef STATUS_AGENTS_EXHAUSTED+# define STATUS_AGENTS_EXHAUSTED ((NTSTATUS) 0xC0000085L)+#endif++#ifndef STATUS_INVALID_VOLUME_LABEL+# define STATUS_INVALID_VOLUME_LABEL ((NTSTATUS) 0xC0000086L)+#endif++#ifndef STATUS_SECTION_NOT_EXTENDED+# define STATUS_SECTION_NOT_EXTENDED ((NTSTATUS) 0xC0000087L)+#endif++#ifndef STATUS_NOT_MAPPED_DATA+# define STATUS_NOT_MAPPED_DATA ((NTSTATUS) 0xC0000088L)+#endif++#ifndef STATUS_RESOURCE_DATA_NOT_FOUND+# define STATUS_RESOURCE_DATA_NOT_FOUND ((NTSTATUS) 0xC0000089L)+#endif++#ifndef STATUS_RESOURCE_TYPE_NOT_FOUND+# define STATUS_RESOURCE_TYPE_NOT_FOUND ((NTSTATUS) 0xC000008AL)+#endif++#ifndef STATUS_RESOURCE_NAME_NOT_FOUND+# define STATUS_RESOURCE_NAME_NOT_FOUND ((NTSTATUS) 0xC000008BL)+#endif++#ifndef STATUS_ARRAY_BOUNDS_EXCEEDED+# define STATUS_ARRAY_BOUNDS_EXCEEDED ((NTSTATUS) 0xC000008CL)+#endif++#ifndef STATUS_FLOAT_DENORMAL_OPERAND+# define STATUS_FLOAT_DENORMAL_OPERAND ((NTSTATUS) 0xC000008DL)+#endif++#ifndef STATUS_FLOAT_DIVIDE_BY_ZERO+# define STATUS_FLOAT_DIVIDE_BY_ZERO ((NTSTATUS) 0xC000008EL)+#endif++#ifndef STATUS_FLOAT_INEXACT_RESULT+# define STATUS_FLOAT_INEXACT_RESULT ((NTSTATUS) 0xC000008FL)+#endif++#ifndef STATUS_FLOAT_INVALID_OPERATION+# define STATUS_FLOAT_INVALID_OPERATION ((NTSTATUS) 0xC0000090L)+#endif++#ifndef STATUS_FLOAT_OVERFLOW+# define STATUS_FLOAT_OVERFLOW ((NTSTATUS) 0xC0000091L)+#endif++#ifndef STATUS_FLOAT_STACK_CHECK+# define STATUS_FLOAT_STACK_CHECK ((NTSTATUS) 0xC0000092L)+#endif++#ifndef STATUS_FLOAT_UNDERFLOW+# define STATUS_FLOAT_UNDERFLOW ((NTSTATUS) 0xC0000093L)+#endif++#ifndef STATUS_INTEGER_DIVIDE_BY_ZERO+# define STATUS_INTEGER_DIVIDE_BY_ZERO ((NTSTATUS) 0xC0000094L)+#endif++#ifndef STATUS_INTEGER_OVERFLOW+# define STATUS_INTEGER_OVERFLOW ((NTSTATUS) 0xC0000095L)+#endif++#ifndef STATUS_PRIVILEGED_INSTRUCTION+# define STATUS_PRIVILEGED_INSTRUCTION ((NTSTATUS) 0xC0000096L)+#endif++#ifndef STATUS_TOO_MANY_PAGING_FILES+# define STATUS_TOO_MANY_PAGING_FILES ((NTSTATUS) 0xC0000097L)+#endif++#ifndef STATUS_FILE_INVALID+# define STATUS_FILE_INVALID ((NTSTATUS) 0xC0000098L)+#endif++#ifndef STATUS_ALLOTTED_SPACE_EXCEEDED+# define STATUS_ALLOTTED_SPACE_EXCEEDED ((NTSTATUS) 0xC0000099L)+#endif++#ifndef STATUS_INSUFFICIENT_RESOURCES+# define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS) 0xC000009AL)+#endif++#ifndef STATUS_DFS_EXIT_PATH_FOUND+# define STATUS_DFS_EXIT_PATH_FOUND ((NTSTATUS) 0xC000009BL)+#endif++#ifndef STATUS_DEVICE_DATA_ERROR+# define STATUS_DEVICE_DATA_ERROR ((NTSTATUS) 0xC000009CL)+#endif++#ifndef STATUS_DEVICE_NOT_CONNECTED+# define STATUS_DEVICE_NOT_CONNECTED ((NTSTATUS) 0xC000009DL)+#endif++#ifndef STATUS_DEVICE_POWER_FAILURE+# define STATUS_DEVICE_POWER_FAILURE ((NTSTATUS) 0xC000009EL)+#endif++#ifndef STATUS_FREE_VM_NOT_AT_BASE+# define STATUS_FREE_VM_NOT_AT_BASE ((NTSTATUS) 0xC000009FL)+#endif++#ifndef STATUS_MEMORY_NOT_ALLOCATED+# define STATUS_MEMORY_NOT_ALLOCATED ((NTSTATUS) 0xC00000A0L)+#endif++#ifndef STATUS_WORKING_SET_QUOTA+# define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xC00000A1L)+#endif++#ifndef STATUS_MEDIA_WRITE_PROTECTED+# define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS) 0xC00000A2L)+#endif++#ifndef STATUS_DEVICE_NOT_READY+# define STATUS_DEVICE_NOT_READY ((NTSTATUS) 0xC00000A3L)+#endif++#ifndef STATUS_INVALID_GROUP_ATTRIBUTES+# define STATUS_INVALID_GROUP_ATTRIBUTES ((NTSTATUS) 0xC00000A4L)+#endif++#ifndef STATUS_BAD_IMPERSONATION_LEVEL+# define STATUS_BAD_IMPERSONATION_LEVEL ((NTSTATUS) 0xC00000A5L)+#endif++#ifndef STATUS_CANT_OPEN_ANONYMOUS+# define STATUS_CANT_OPEN_ANONYMOUS ((NTSTATUS) 0xC00000A6L)+#endif++#ifndef STATUS_BAD_VALIDATION_CLASS+# define STATUS_BAD_VALIDATION_CLASS ((NTSTATUS) 0xC00000A7L)+#endif++#ifndef STATUS_BAD_TOKEN_TYPE+# define STATUS_BAD_TOKEN_TYPE ((NTSTATUS) 0xC00000A8L)+#endif++#ifndef STATUS_BAD_MASTER_BOOT_RECORD+# define STATUS_BAD_MASTER_BOOT_RECORD ((NTSTATUS) 0xC00000A9L)+#endif++#ifndef STATUS_INSTRUCTION_MISALIGNMENT+# define STATUS_INSTRUCTION_MISALIGNMENT ((NTSTATUS) 0xC00000AAL)+#endif++#ifndef STATUS_INSTANCE_NOT_AVAILABLE+# define STATUS_INSTANCE_NOT_AVAILABLE ((NTSTATUS) 0xC00000ABL)+#endif++#ifndef STATUS_PIPE_NOT_AVAILABLE+# define STATUS_PIPE_NOT_AVAILABLE ((NTSTATUS) 0xC00000ACL)+#endif++#ifndef STATUS_INVALID_PIPE_STATE+# define STATUS_INVALID_PIPE_STATE ((NTSTATUS) 0xC00000ADL)+#endif++#ifndef STATUS_PIPE_BUSY+# define STATUS_PIPE_BUSY ((NTSTATUS) 0xC00000AEL)+#endif++#ifndef STATUS_ILLEGAL_FUNCTION+# define STATUS_ILLEGAL_FUNCTION ((NTSTATUS) 0xC00000AFL)+#endif++#ifndef STATUS_PIPE_DISCONNECTED+# define STATUS_PIPE_DISCONNECTED ((NTSTATUS) 0xC00000B0L)+#endif++#ifndef STATUS_PIPE_CLOSING+# define STATUS_PIPE_CLOSING ((NTSTATUS) 0xC00000B1L)+#endif++#ifndef STATUS_PIPE_CONNECTED+# define STATUS_PIPE_CONNECTED ((NTSTATUS) 0xC00000B2L)+#endif++#ifndef STATUS_PIPE_LISTENING+# define STATUS_PIPE_LISTENING ((NTSTATUS) 0xC00000B3L)+#endif++#ifndef STATUS_INVALID_READ_MODE+# define STATUS_INVALID_READ_MODE ((NTSTATUS) 0xC00000B4L)+#endif++#ifndef STATUS_IO_TIMEOUT+# define STATUS_IO_TIMEOUT ((NTSTATUS) 0xC00000B5L)+#endif++#ifndef STATUS_FILE_FORCED_CLOSED+# define STATUS_FILE_FORCED_CLOSED ((NTSTATUS) 0xC00000B6L)+#endif++#ifndef STATUS_PROFILING_NOT_STARTED+# define STATUS_PROFILING_NOT_STARTED ((NTSTATUS) 0xC00000B7L)+#endif++#ifndef STATUS_PROFILING_NOT_STOPPED+# define STATUS_PROFILING_NOT_STOPPED ((NTSTATUS) 0xC00000B8L)+#endif++#ifndef STATUS_COULD_NOT_INTERPRET+# define STATUS_COULD_NOT_INTERPRET ((NTSTATUS) 0xC00000B9L)+#endif++#ifndef STATUS_FILE_IS_A_DIRECTORY+# define STATUS_FILE_IS_A_DIRECTORY ((NTSTATUS) 0xC00000BAL)+#endif++#ifndef STATUS_NOT_SUPPORTED+# define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xC00000BBL)+#endif++#ifndef STATUS_REMOTE_NOT_LISTENING+# define STATUS_REMOTE_NOT_LISTENING ((NTSTATUS) 0xC00000BCL)+#endif++#ifndef STATUS_DUPLICATE_NAME+# define STATUS_DUPLICATE_NAME ((NTSTATUS) 0xC00000BDL)+#endif++#ifndef STATUS_BAD_NETWORK_PATH+# define STATUS_BAD_NETWORK_PATH ((NTSTATUS) 0xC00000BEL)+#endif++#ifndef STATUS_NETWORK_BUSY+# define STATUS_NETWORK_BUSY ((NTSTATUS) 0xC00000BFL)+#endif++#ifndef STATUS_DEVICE_DOES_NOT_EXIST+# define STATUS_DEVICE_DOES_NOT_EXIST ((NTSTATUS) 0xC00000C0L)+#endif++#ifndef STATUS_TOO_MANY_COMMANDS+# define STATUS_TOO_MANY_COMMANDS ((NTSTATUS) 0xC00000C1L)+#endif++#ifndef STATUS_ADAPTER_HARDWARE_ERROR+# define STATUS_ADAPTER_HARDWARE_ERROR ((NTSTATUS) 0xC00000C2L)+#endif++#ifndef STATUS_INVALID_NETWORK_RESPONSE+# define STATUS_INVALID_NETWORK_RESPONSE ((NTSTATUS) 0xC00000C3L)+#endif++#ifndef STATUS_UNEXPECTED_NETWORK_ERROR+# define STATUS_UNEXPECTED_NETWORK_ERROR ((NTSTATUS) 0xC00000C4L)+#endif++#ifndef STATUS_BAD_REMOTE_ADAPTER+# define STATUS_BAD_REMOTE_ADAPTER ((NTSTATUS) 0xC00000C5L)+#endif++#ifndef STATUS_PRINT_QUEUE_FULL+# define STATUS_PRINT_QUEUE_FULL ((NTSTATUS) 0xC00000C6L)+#endif++#ifndef STATUS_NO_SPOOL_SPACE+# define STATUS_NO_SPOOL_SPACE ((NTSTATUS) 0xC00000C7L)+#endif++#ifndef STATUS_PRINT_CANCELLED+# define STATUS_PRINT_CANCELLED ((NTSTATUS) 0xC00000C8L)+#endif++#ifndef STATUS_NETWORK_NAME_DELETED+# define STATUS_NETWORK_NAME_DELETED ((NTSTATUS) 0xC00000C9L)+#endif++#ifndef STATUS_NETWORK_ACCESS_DENIED+# define STATUS_NETWORK_ACCESS_DENIED ((NTSTATUS) 0xC00000CAL)+#endif++#ifndef STATUS_BAD_DEVICE_TYPE+# define STATUS_BAD_DEVICE_TYPE ((NTSTATUS) 0xC00000CBL)+#endif++#ifndef STATUS_BAD_NETWORK_NAME+# define STATUS_BAD_NETWORK_NAME ((NTSTATUS) 0xC00000CCL)+#endif++#ifndef STATUS_TOO_MANY_NAMES+# define STATUS_TOO_MANY_NAMES ((NTSTATUS) 0xC00000CDL)+#endif++#ifndef STATUS_TOO_MANY_SESSIONS+# define STATUS_TOO_MANY_SESSIONS ((NTSTATUS) 0xC00000CEL)+#endif++#ifndef STATUS_SHARING_PAUSED+# define STATUS_SHARING_PAUSED ((NTSTATUS) 0xC00000CFL)+#endif++#ifndef STATUS_REQUEST_NOT_ACCEPTED+# define STATUS_REQUEST_NOT_ACCEPTED ((NTSTATUS) 0xC00000D0L)+#endif++#ifndef STATUS_REDIRECTOR_PAUSED+# define STATUS_REDIRECTOR_PAUSED ((NTSTATUS) 0xC00000D1L)+#endif++#ifndef STATUS_NET_WRITE_FAULT+# define STATUS_NET_WRITE_FAULT ((NTSTATUS) 0xC00000D2L)+#endif++#ifndef STATUS_PROFILING_AT_LIMIT+# define STATUS_PROFILING_AT_LIMIT ((NTSTATUS) 0xC00000D3L)+#endif++#ifndef STATUS_NOT_SAME_DEVICE+# define STATUS_NOT_SAME_DEVICE ((NTSTATUS) 0xC00000D4L)+#endif++#ifndef STATUS_FILE_RENAMED+# define STATUS_FILE_RENAMED ((NTSTATUS) 0xC00000D5L)+#endif++#ifndef STATUS_VIRTUAL_CIRCUIT_CLOSED+# define STATUS_VIRTUAL_CIRCUIT_CLOSED ((NTSTATUS) 0xC00000D6L)+#endif++#ifndef STATUS_NO_SECURITY_ON_OBJECT+# define STATUS_NO_SECURITY_ON_OBJECT ((NTSTATUS) 0xC00000D7L)+#endif++#ifndef STATUS_CANT_WAIT+# define STATUS_CANT_WAIT ((NTSTATUS) 0xC00000D8L)+#endif++#ifndef STATUS_PIPE_EMPTY+# define STATUS_PIPE_EMPTY ((NTSTATUS) 0xC00000D9L)+#endif++#ifndef STATUS_CANT_ACCESS_DOMAIN_INFO+# define STATUS_CANT_ACCESS_DOMAIN_INFO ((NTSTATUS) 0xC00000DAL)+#endif++#ifndef STATUS_CANT_TERMINATE_SELF+# define STATUS_CANT_TERMINATE_SELF ((NTSTATUS) 0xC00000DBL)+#endif++#ifndef STATUS_INVALID_SERVER_STATE+# define STATUS_INVALID_SERVER_STATE ((NTSTATUS) 0xC00000DCL)+#endif++#ifndef STATUS_INVALID_DOMAIN_STATE+# define STATUS_INVALID_DOMAIN_STATE ((NTSTATUS) 0xC00000DDL)+#endif++#ifndef STATUS_INVALID_DOMAIN_ROLE+# define STATUS_INVALID_DOMAIN_ROLE ((NTSTATUS) 0xC00000DEL)+#endif++#ifndef STATUS_NO_SUCH_DOMAIN+# define STATUS_NO_SUCH_DOMAIN ((NTSTATUS) 0xC00000DFL)+#endif++#ifndef STATUS_DOMAIN_EXISTS+# define STATUS_DOMAIN_EXISTS ((NTSTATUS) 0xC00000E0L)+#endif++#ifndef STATUS_DOMAIN_LIMIT_EXCEEDED+# define STATUS_DOMAIN_LIMIT_EXCEEDED ((NTSTATUS) 0xC00000E1L)+#endif++#ifndef STATUS_OPLOCK_NOT_GRANTED+# define STATUS_OPLOCK_NOT_GRANTED ((NTSTATUS) 0xC00000E2L)+#endif++#ifndef STATUS_INVALID_OPLOCK_PROTOCOL+# define STATUS_INVALID_OPLOCK_PROTOCOL ((NTSTATUS) 0xC00000E3L)+#endif++#ifndef STATUS_INTERNAL_DB_CORRUPTION+# define STATUS_INTERNAL_DB_CORRUPTION ((NTSTATUS) 0xC00000E4L)+#endif++#ifndef STATUS_INTERNAL_ERROR+# define STATUS_INTERNAL_ERROR ((NTSTATUS) 0xC00000E5L)+#endif++#ifndef STATUS_GENERIC_NOT_MAPPED+# define STATUS_GENERIC_NOT_MAPPED ((NTSTATUS) 0xC00000E6L)+#endif++#ifndef STATUS_BAD_DESCRIPTOR_FORMAT+# define STATUS_BAD_DESCRIPTOR_FORMAT ((NTSTATUS) 0xC00000E7L)+#endif++#ifndef STATUS_INVALID_USER_BUFFER+# define STATUS_INVALID_USER_BUFFER ((NTSTATUS) 0xC00000E8L)+#endif++#ifndef STATUS_UNEXPECTED_IO_ERROR+# define STATUS_UNEXPECTED_IO_ERROR ((NTSTATUS) 0xC00000E9L)+#endif++#ifndef STATUS_UNEXPECTED_MM_CREATE_ERR+# define STATUS_UNEXPECTED_MM_CREATE_ERR ((NTSTATUS) 0xC00000EAL)+#endif++#ifndef STATUS_UNEXPECTED_MM_MAP_ERROR+# define STATUS_UNEXPECTED_MM_MAP_ERROR ((NTSTATUS) 0xC00000EBL)+#endif++#ifndef STATUS_UNEXPECTED_MM_EXTEND_ERR+# define STATUS_UNEXPECTED_MM_EXTEND_ERR ((NTSTATUS) 0xC00000ECL)+#endif++#ifndef STATUS_NOT_LOGON_PROCESS+# define STATUS_NOT_LOGON_PROCESS ((NTSTATUS) 0xC00000EDL)+#endif++#ifndef STATUS_LOGON_SESSION_EXISTS+# define STATUS_LOGON_SESSION_EXISTS ((NTSTATUS) 0xC00000EEL)+#endif++#ifndef STATUS_INVALID_PARAMETER_1+# define STATUS_INVALID_PARAMETER_1 ((NTSTATUS) 0xC00000EFL)+#endif++#ifndef STATUS_INVALID_PARAMETER_2+# define STATUS_INVALID_PARAMETER_2 ((NTSTATUS) 0xC00000F0L)+#endif++#ifndef STATUS_INVALID_PARAMETER_3+# define STATUS_INVALID_PARAMETER_3 ((NTSTATUS) 0xC00000F1L)+#endif++#ifndef STATUS_INVALID_PARAMETER_4+# define STATUS_INVALID_PARAMETER_4 ((NTSTATUS) 0xC00000F2L)+#endif++#ifndef STATUS_INVALID_PARAMETER_5+# define STATUS_INVALID_PARAMETER_5 ((NTSTATUS) 0xC00000F3L)+#endif++#ifndef STATUS_INVALID_PARAMETER_6+# define STATUS_INVALID_PARAMETER_6 ((NTSTATUS) 0xC00000F4L)+#endif++#ifndef STATUS_INVALID_PARAMETER_7+# define STATUS_INVALID_PARAMETER_7 ((NTSTATUS) 0xC00000F5L)+#endif++#ifndef STATUS_INVALID_PARAMETER_8+# define STATUS_INVALID_PARAMETER_8 ((NTSTATUS) 0xC00000F6L)+#endif++#ifndef STATUS_INVALID_PARAMETER_9+# define STATUS_INVALID_PARAMETER_9 ((NTSTATUS) 0xC00000F7L)+#endif++#ifndef STATUS_INVALID_PARAMETER_10+# define STATUS_INVALID_PARAMETER_10 ((NTSTATUS) 0xC00000F8L)+#endif++#ifndef STATUS_INVALID_PARAMETER_11+# define STATUS_INVALID_PARAMETER_11 ((NTSTATUS) 0xC00000F9L)+#endif++#ifndef STATUS_INVALID_PARAMETER_12+# define STATUS_INVALID_PARAMETER_12 ((NTSTATUS) 0xC00000FAL)+#endif++#ifndef STATUS_REDIRECTOR_NOT_STARTED+# define STATUS_REDIRECTOR_NOT_STARTED ((NTSTATUS) 0xC00000FBL)+#endif++#ifndef STATUS_REDIRECTOR_STARTED+# define STATUS_REDIRECTOR_STARTED ((NTSTATUS) 0xC00000FCL)+#endif++#ifndef STATUS_STACK_OVERFLOW+# define STATUS_STACK_OVERFLOW ((NTSTATUS) 0xC00000FDL)+#endif++#ifndef STATUS_NO_SUCH_PACKAGE+# define STATUS_NO_SUCH_PACKAGE ((NTSTATUS) 0xC00000FEL)+#endif++#ifndef STATUS_BAD_FUNCTION_TABLE+# define STATUS_BAD_FUNCTION_TABLE ((NTSTATUS) 0xC00000FFL)+#endif++#ifndef STATUS_VARIABLE_NOT_FOUND+# define STATUS_VARIABLE_NOT_FOUND ((NTSTATUS) 0xC0000100L)+#endif++#ifndef STATUS_DIRECTORY_NOT_EMPTY+# define STATUS_DIRECTORY_NOT_EMPTY ((NTSTATUS) 0xC0000101L)+#endif++#ifndef STATUS_FILE_CORRUPT_ERROR+# define STATUS_FILE_CORRUPT_ERROR ((NTSTATUS) 0xC0000102L)+#endif++#ifndef STATUS_NOT_A_DIRECTORY+# define STATUS_NOT_A_DIRECTORY ((NTSTATUS) 0xC0000103L)+#endif++#ifndef STATUS_BAD_LOGON_SESSION_STATE+# define STATUS_BAD_LOGON_SESSION_STATE ((NTSTATUS) 0xC0000104L)+#endif++#ifndef STATUS_LOGON_SESSION_COLLISION+# define STATUS_LOGON_SESSION_COLLISION ((NTSTATUS) 0xC0000105L)+#endif++#ifndef STATUS_NAME_TOO_LONG+# define STATUS_NAME_TOO_LONG ((NTSTATUS) 0xC0000106L)+#endif++#ifndef STATUS_FILES_OPEN+# define STATUS_FILES_OPEN ((NTSTATUS) 0xC0000107L)+#endif++#ifndef STATUS_CONNECTION_IN_USE+# define STATUS_CONNECTION_IN_USE ((NTSTATUS) 0xC0000108L)+#endif++#ifndef STATUS_MESSAGE_NOT_FOUND+# define STATUS_MESSAGE_NOT_FOUND ((NTSTATUS) 0xC0000109L)+#endif++#ifndef STATUS_PROCESS_IS_TERMINATING+# define STATUS_PROCESS_IS_TERMINATING ((NTSTATUS) 0xC000010AL)+#endif++#ifndef STATUS_INVALID_LOGON_TYPE+# define STATUS_INVALID_LOGON_TYPE ((NTSTATUS) 0xC000010BL)+#endif++#ifndef STATUS_NO_GUID_TRANSLATION+# define STATUS_NO_GUID_TRANSLATION ((NTSTATUS) 0xC000010CL)+#endif++#ifndef STATUS_CANNOT_IMPERSONATE+# define STATUS_CANNOT_IMPERSONATE ((NTSTATUS) 0xC000010DL)+#endif++#ifndef STATUS_IMAGE_ALREADY_LOADED+# define STATUS_IMAGE_ALREADY_LOADED ((NTSTATUS) 0xC000010EL)+#endif++#ifndef STATUS_ABIOS_NOT_PRESENT+# define STATUS_ABIOS_NOT_PRESENT ((NTSTATUS) 0xC000010FL)+#endif++#ifndef STATUS_ABIOS_LID_NOT_EXIST+# define STATUS_ABIOS_LID_NOT_EXIST ((NTSTATUS) 0xC0000110L)+#endif++#ifndef STATUS_ABIOS_LID_ALREADY_OWNED+# define STATUS_ABIOS_LID_ALREADY_OWNED ((NTSTATUS) 0xC0000111L)+#endif++#ifndef STATUS_ABIOS_NOT_LID_OWNER+# define STATUS_ABIOS_NOT_LID_OWNER ((NTSTATUS) 0xC0000112L)+#endif++#ifndef STATUS_ABIOS_INVALID_COMMAND+# define STATUS_ABIOS_INVALID_COMMAND ((NTSTATUS) 0xC0000113L)+#endif++#ifndef STATUS_ABIOS_INVALID_LID+# define STATUS_ABIOS_INVALID_LID ((NTSTATUS) 0xC0000114L)+#endif++#ifndef STATUS_ABIOS_SELECTOR_NOT_AVAILABLE+# define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE ((NTSTATUS) 0xC0000115L)+#endif++#ifndef STATUS_ABIOS_INVALID_SELECTOR+# define STATUS_ABIOS_INVALID_SELECTOR ((NTSTATUS) 0xC0000116L)+#endif++#ifndef STATUS_NO_LDT+# define STATUS_NO_LDT ((NTSTATUS) 0xC0000117L)+#endif++#ifndef STATUS_INVALID_LDT_SIZE+# define STATUS_INVALID_LDT_SIZE ((NTSTATUS) 0xC0000118L)+#endif++#ifndef STATUS_INVALID_LDT_OFFSET+# define STATUS_INVALID_LDT_OFFSET ((NTSTATUS) 0xC0000119L)+#endif++#ifndef STATUS_INVALID_LDT_DESCRIPTOR+# define STATUS_INVALID_LDT_DESCRIPTOR ((NTSTATUS) 0xC000011AL)+#endif++#ifndef STATUS_INVALID_IMAGE_NE_FORMAT+# define STATUS_INVALID_IMAGE_NE_FORMAT ((NTSTATUS) 0xC000011BL)+#endif++#ifndef STATUS_RXACT_INVALID_STATE+# define STATUS_RXACT_INVALID_STATE ((NTSTATUS) 0xC000011CL)+#endif++#ifndef STATUS_RXACT_COMMIT_FAILURE+# define STATUS_RXACT_COMMIT_FAILURE ((NTSTATUS) 0xC000011DL)+#endif++#ifndef STATUS_MAPPED_FILE_SIZE_ZERO+# define STATUS_MAPPED_FILE_SIZE_ZERO ((NTSTATUS) 0xC000011EL)+#endif++#ifndef STATUS_TOO_MANY_OPENED_FILES+# define STATUS_TOO_MANY_OPENED_FILES ((NTSTATUS) 0xC000011FL)+#endif++#ifndef STATUS_CANCELLED+# define STATUS_CANCELLED ((NTSTATUS) 0xC0000120L)+#endif++#ifndef STATUS_CANNOT_DELETE+# define STATUS_CANNOT_DELETE ((NTSTATUS) 0xC0000121L)+#endif++#ifndef STATUS_INVALID_COMPUTER_NAME+# define STATUS_INVALID_COMPUTER_NAME ((NTSTATUS) 0xC0000122L)+#endif++#ifndef STATUS_FILE_DELETED+# define STATUS_FILE_DELETED ((NTSTATUS) 0xC0000123L)+#endif++#ifndef STATUS_SPECIAL_ACCOUNT+# define STATUS_SPECIAL_ACCOUNT ((NTSTATUS) 0xC0000124L)+#endif++#ifndef STATUS_SPECIAL_GROUP+# define STATUS_SPECIAL_GROUP ((NTSTATUS) 0xC0000125L)+#endif++#ifndef STATUS_SPECIAL_USER+# define STATUS_SPECIAL_USER ((NTSTATUS) 0xC0000126L)+#endif++#ifndef STATUS_MEMBERS_PRIMARY_GROUP+# define STATUS_MEMBERS_PRIMARY_GROUP ((NTSTATUS) 0xC0000127L)+#endif++#ifndef STATUS_FILE_CLOSED+# define STATUS_FILE_CLOSED ((NTSTATUS) 0xC0000128L)+#endif++#ifndef STATUS_TOO_MANY_THREADS+# define STATUS_TOO_MANY_THREADS ((NTSTATUS) 0xC0000129L)+#endif++#ifndef STATUS_THREAD_NOT_IN_PROCESS+# define STATUS_THREAD_NOT_IN_PROCESS ((NTSTATUS) 0xC000012AL)+#endif++#ifndef STATUS_TOKEN_ALREADY_IN_USE+# define STATUS_TOKEN_ALREADY_IN_USE ((NTSTATUS) 0xC000012BL)+#endif++#ifndef STATUS_PAGEFILE_QUOTA_EXCEEDED+# define STATUS_PAGEFILE_QUOTA_EXCEEDED ((NTSTATUS) 0xC000012CL)+#endif++#ifndef STATUS_COMMITMENT_LIMIT+# define STATUS_COMMITMENT_LIMIT ((NTSTATUS) 0xC000012DL)+#endif++#ifndef STATUS_INVALID_IMAGE_LE_FORMAT+# define STATUS_INVALID_IMAGE_LE_FORMAT ((NTSTATUS) 0xC000012EL)+#endif++#ifndef STATUS_INVALID_IMAGE_NOT_MZ+# define STATUS_INVALID_IMAGE_NOT_MZ ((NTSTATUS) 0xC000012FL)+#endif++#ifndef STATUS_INVALID_IMAGE_PROTECT+# define STATUS_INVALID_IMAGE_PROTECT ((NTSTATUS) 0xC0000130L)+#endif++#ifndef STATUS_INVALID_IMAGE_WIN_16+# define STATUS_INVALID_IMAGE_WIN_16 ((NTSTATUS) 0xC0000131L)+#endif++#ifndef STATUS_LOGON_SERVER_CONFLICT+# define STATUS_LOGON_SERVER_CONFLICT ((NTSTATUS) 0xC0000132L)+#endif++#ifndef STATUS_TIME_DIFFERENCE_AT_DC+# define STATUS_TIME_DIFFERENCE_AT_DC ((NTSTATUS) 0xC0000133L)+#endif++#ifndef STATUS_SYNCHRONIZATION_REQUIRED+# define STATUS_SYNCHRONIZATION_REQUIRED ((NTSTATUS) 0xC0000134L)+#endif++#ifndef STATUS_DLL_NOT_FOUND+# define STATUS_DLL_NOT_FOUND ((NTSTATUS) 0xC0000135L)+#endif++#ifndef STATUS_OPEN_FAILED+# define STATUS_OPEN_FAILED ((NTSTATUS) 0xC0000136L)+#endif++#ifndef STATUS_IO_PRIVILEGE_FAILED+# define STATUS_IO_PRIVILEGE_FAILED ((NTSTATUS) 0xC0000137L)+#endif++#ifndef STATUS_ORDINAL_NOT_FOUND+# define STATUS_ORDINAL_NOT_FOUND ((NTSTATUS) 0xC0000138L)+#endif++#ifndef STATUS_ENTRYPOINT_NOT_FOUND+# define STATUS_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xC0000139L)+#endif++#ifndef STATUS_CONTROL_C_EXIT+# define STATUS_CONTROL_C_EXIT ((NTSTATUS) 0xC000013AL)+#endif++#ifndef STATUS_LOCAL_DISCONNECT+# define STATUS_LOCAL_DISCONNECT ((NTSTATUS) 0xC000013BL)+#endif++#ifndef STATUS_REMOTE_DISCONNECT+# define STATUS_REMOTE_DISCONNECT ((NTSTATUS) 0xC000013CL)+#endif++#ifndef STATUS_REMOTE_RESOURCES+# define STATUS_REMOTE_RESOURCES ((NTSTATUS) 0xC000013DL)+#endif++#ifndef STATUS_LINK_FAILED+# define STATUS_LINK_FAILED ((NTSTATUS) 0xC000013EL)+#endif++#ifndef STATUS_LINK_TIMEOUT+# define STATUS_LINK_TIMEOUT ((NTSTATUS) 0xC000013FL)+#endif++#ifndef STATUS_INVALID_CONNECTION+# define STATUS_INVALID_CONNECTION ((NTSTATUS) 0xC0000140L)+#endif++#ifndef STATUS_INVALID_ADDRESS+# define STATUS_INVALID_ADDRESS ((NTSTATUS) 0xC0000141L)+#endif++#ifndef STATUS_DLL_INIT_FAILED+# define STATUS_DLL_INIT_FAILED ((NTSTATUS) 0xC0000142L)+#endif++#ifndef STATUS_MISSING_SYSTEMFILE+# define STATUS_MISSING_SYSTEMFILE ((NTSTATUS) 0xC0000143L)+#endif++#ifndef STATUS_UNHANDLED_EXCEPTION+# define STATUS_UNHANDLED_EXCEPTION ((NTSTATUS) 0xC0000144L)+#endif++#ifndef STATUS_APP_INIT_FAILURE+# define STATUS_APP_INIT_FAILURE ((NTSTATUS) 0xC0000145L)+#endif++#ifndef STATUS_PAGEFILE_CREATE_FAILED+# define STATUS_PAGEFILE_CREATE_FAILED ((NTSTATUS) 0xC0000146L)+#endif++#ifndef STATUS_NO_PAGEFILE+# define STATUS_NO_PAGEFILE ((NTSTATUS) 0xC0000147L)+#endif++#ifndef STATUS_INVALID_LEVEL+# define STATUS_INVALID_LEVEL ((NTSTATUS) 0xC0000148L)+#endif++#ifndef STATUS_WRONG_PASSWORD_CORE+# define STATUS_WRONG_PASSWORD_CORE ((NTSTATUS) 0xC0000149L)+#endif++#ifndef STATUS_ILLEGAL_FLOAT_CONTEXT+# define STATUS_ILLEGAL_FLOAT_CONTEXT ((NTSTATUS) 0xC000014AL)+#endif++#ifndef STATUS_PIPE_BROKEN+# define STATUS_PIPE_BROKEN ((NTSTATUS) 0xC000014BL)+#endif++#ifndef STATUS_REGISTRY_CORRUPT+# define STATUS_REGISTRY_CORRUPT ((NTSTATUS) 0xC000014CL)+#endif++#ifndef STATUS_REGISTRY_IO_FAILED+# define STATUS_REGISTRY_IO_FAILED ((NTSTATUS) 0xC000014DL)+#endif++#ifndef STATUS_NO_EVENT_PAIR+# define STATUS_NO_EVENT_PAIR ((NTSTATUS) 0xC000014EL)+#endif++#ifndef STATUS_UNRECOGNIZED_VOLUME+# define STATUS_UNRECOGNIZED_VOLUME ((NTSTATUS) 0xC000014FL)+#endif++#ifndef STATUS_SERIAL_NO_DEVICE_INITED+# define STATUS_SERIAL_NO_DEVICE_INITED ((NTSTATUS) 0xC0000150L)+#endif++#ifndef STATUS_NO_SUCH_ALIAS+# define STATUS_NO_SUCH_ALIAS ((NTSTATUS) 0xC0000151L)+#endif++#ifndef STATUS_MEMBER_NOT_IN_ALIAS+# define STATUS_MEMBER_NOT_IN_ALIAS ((NTSTATUS) 0xC0000152L)+#endif++#ifndef STATUS_MEMBER_IN_ALIAS+# define STATUS_MEMBER_IN_ALIAS ((NTSTATUS) 0xC0000153L)+#endif++#ifndef STATUS_ALIAS_EXISTS+# define STATUS_ALIAS_EXISTS ((NTSTATUS) 0xC0000154L)+#endif++#ifndef STATUS_LOGON_NOT_GRANTED+# define STATUS_LOGON_NOT_GRANTED ((NTSTATUS) 0xC0000155L)+#endif++#ifndef STATUS_TOO_MANY_SECRETS+# define STATUS_TOO_MANY_SECRETS ((NTSTATUS) 0xC0000156L)+#endif++#ifndef STATUS_SECRET_TOO_LONG+# define STATUS_SECRET_TOO_LONG ((NTSTATUS) 0xC0000157L)+#endif++#ifndef STATUS_INTERNAL_DB_ERROR+# define STATUS_INTERNAL_DB_ERROR ((NTSTATUS) 0xC0000158L)+#endif++#ifndef STATUS_FULLSCREEN_MODE+# define STATUS_FULLSCREEN_MODE ((NTSTATUS) 0xC0000159L)+#endif++#ifndef STATUS_TOO_MANY_CONTEXT_IDS+# define STATUS_TOO_MANY_CONTEXT_IDS ((NTSTATUS) 0xC000015AL)+#endif++#ifndef STATUS_LOGON_TYPE_NOT_GRANTED+# define STATUS_LOGON_TYPE_NOT_GRANTED ((NTSTATUS) 0xC000015BL)+#endif++#ifndef STATUS_NOT_REGISTRY_FILE+# define STATUS_NOT_REGISTRY_FILE ((NTSTATUS) 0xC000015CL)+#endif++#ifndef STATUS_NT_CROSS_ENCRYPTION_REQUIRED+# define STATUS_NT_CROSS_ENCRYPTION_REQUIRED ((NTSTATUS) 0xC000015DL)+#endif++#ifndef STATUS_DOMAIN_CTRLR_CONFIG_ERROR+# define STATUS_DOMAIN_CTRLR_CONFIG_ERROR ((NTSTATUS) 0xC000015EL)+#endif++#ifndef STATUS_FT_MISSING_MEMBER+# define STATUS_FT_MISSING_MEMBER ((NTSTATUS) 0xC000015FL)+#endif++#ifndef STATUS_ILL_FORMED_SERVICE_ENTRY+# define STATUS_ILL_FORMED_SERVICE_ENTRY ((NTSTATUS) 0xC0000160L)+#endif++#ifndef STATUS_ILLEGAL_CHARACTER+# define STATUS_ILLEGAL_CHARACTER ((NTSTATUS) 0xC0000161L)+#endif++#ifndef STATUS_UNMAPPABLE_CHARACTER+# define STATUS_UNMAPPABLE_CHARACTER ((NTSTATUS) 0xC0000162L)+#endif++#ifndef STATUS_UNDEFINED_CHARACTER+# define STATUS_UNDEFINED_CHARACTER ((NTSTATUS) 0xC0000163L)+#endif++#ifndef STATUS_FLOPPY_VOLUME+# define STATUS_FLOPPY_VOLUME ((NTSTATUS) 0xC0000164L)+#endif++#ifndef STATUS_FLOPPY_ID_MARK_NOT_FOUND+# define STATUS_FLOPPY_ID_MARK_NOT_FOUND ((NTSTATUS) 0xC0000165L)+#endif++#ifndef STATUS_FLOPPY_WRONG_CYLINDER+# define STATUS_FLOPPY_WRONG_CYLINDER ((NTSTATUS) 0xC0000166L)+#endif++#ifndef STATUS_FLOPPY_UNKNOWN_ERROR+# define STATUS_FLOPPY_UNKNOWN_ERROR ((NTSTATUS) 0xC0000167L)+#endif++#ifndef STATUS_FLOPPY_BAD_REGISTERS+# define STATUS_FLOPPY_BAD_REGISTERS ((NTSTATUS) 0xC0000168L)+#endif++#ifndef STATUS_DISK_RECALIBRATE_FAILED+# define STATUS_DISK_RECALIBRATE_FAILED ((NTSTATUS) 0xC0000169L)+#endif++#ifndef STATUS_DISK_OPERATION_FAILED+# define STATUS_DISK_OPERATION_FAILED ((NTSTATUS) 0xC000016AL)+#endif++#ifndef STATUS_DISK_RESET_FAILED+# define STATUS_DISK_RESET_FAILED ((NTSTATUS) 0xC000016BL)+#endif++#ifndef STATUS_SHARED_IRQ_BUSY+# define STATUS_SHARED_IRQ_BUSY ((NTSTATUS) 0xC000016CL)+#endif++#ifndef STATUS_FT_ORPHANING+# define STATUS_FT_ORPHANING ((NTSTATUS) 0xC000016DL)+#endif++#ifndef STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT+# define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT ((NTSTATUS) 0xC000016EL)+#endif++#ifndef STATUS_PARTITION_FAILURE+# define STATUS_PARTITION_FAILURE ((NTSTATUS) 0xC0000172L)+#endif++#ifndef STATUS_INVALID_BLOCK_LENGTH+# define STATUS_INVALID_BLOCK_LENGTH ((NTSTATUS) 0xC0000173L)+#endif++#ifndef STATUS_DEVICE_NOT_PARTITIONED+# define STATUS_DEVICE_NOT_PARTITIONED ((NTSTATUS) 0xC0000174L)+#endif++#ifndef STATUS_UNABLE_TO_LOCK_MEDIA+# define STATUS_UNABLE_TO_LOCK_MEDIA ((NTSTATUS) 0xC0000175L)+#endif++#ifndef STATUS_UNABLE_TO_UNLOAD_MEDIA+# define STATUS_UNABLE_TO_UNLOAD_MEDIA ((NTSTATUS) 0xC0000176L)+#endif++#ifndef STATUS_EOM_OVERFLOW+# define STATUS_EOM_OVERFLOW ((NTSTATUS) 0xC0000177L)+#endif++#ifndef STATUS_NO_MEDIA+# define STATUS_NO_MEDIA ((NTSTATUS) 0xC0000178L)+#endif++#ifndef STATUS_NO_SUCH_MEMBER+# define STATUS_NO_SUCH_MEMBER ((NTSTATUS) 0xC000017AL)+#endif++#ifndef STATUS_INVALID_MEMBER+# define STATUS_INVALID_MEMBER ((NTSTATUS) 0xC000017BL)+#endif++#ifndef STATUS_KEY_DELETED+# define STATUS_KEY_DELETED ((NTSTATUS) 0xC000017CL)+#endif++#ifndef STATUS_NO_LOG_SPACE+# define STATUS_NO_LOG_SPACE ((NTSTATUS) 0xC000017DL)+#endif++#ifndef STATUS_TOO_MANY_SIDS+# define STATUS_TOO_MANY_SIDS ((NTSTATUS) 0xC000017EL)+#endif++#ifndef STATUS_LM_CROSS_ENCRYPTION_REQUIRED+# define STATUS_LM_CROSS_ENCRYPTION_REQUIRED ((NTSTATUS) 0xC000017FL)+#endif++#ifndef STATUS_KEY_HAS_CHILDREN+# define STATUS_KEY_HAS_CHILDREN ((NTSTATUS) 0xC0000180L)+#endif++#ifndef STATUS_CHILD_MUST_BE_VOLATILE+# define STATUS_CHILD_MUST_BE_VOLATILE ((NTSTATUS) 0xC0000181L)+#endif++#ifndef STATUS_DEVICE_CONFIGURATION_ERROR+# define STATUS_DEVICE_CONFIGURATION_ERROR ((NTSTATUS) 0xC0000182L)+#endif++#ifndef STATUS_DRIVER_INTERNAL_ERROR+# define STATUS_DRIVER_INTERNAL_ERROR ((NTSTATUS) 0xC0000183L)+#endif++#ifndef STATUS_INVALID_DEVICE_STATE+# define STATUS_INVALID_DEVICE_STATE ((NTSTATUS) 0xC0000184L)+#endif++#ifndef STATUS_IO_DEVICE_ERROR+# define STATUS_IO_DEVICE_ERROR ((NTSTATUS) 0xC0000185L)+#endif++#ifndef STATUS_DEVICE_PROTOCOL_ERROR+# define STATUS_DEVICE_PROTOCOL_ERROR ((NTSTATUS) 0xC0000186L)+#endif++#ifndef STATUS_BACKUP_CONTROLLER+# define STATUS_BACKUP_CONTROLLER ((NTSTATUS) 0xC0000187L)+#endif++#ifndef STATUS_LOG_FILE_FULL+# define STATUS_LOG_FILE_FULL ((NTSTATUS) 0xC0000188L)+#endif++#ifndef STATUS_TOO_LATE+# define STATUS_TOO_LATE ((NTSTATUS) 0xC0000189L)+#endif++#ifndef STATUS_NO_TRUST_LSA_SECRET+# define STATUS_NO_TRUST_LSA_SECRET ((NTSTATUS) 0xC000018AL)+#endif++#ifndef STATUS_NO_TRUST_SAM_ACCOUNT+# define STATUS_NO_TRUST_SAM_ACCOUNT ((NTSTATUS) 0xC000018BL)+#endif++#ifndef STATUS_TRUSTED_DOMAIN_FAILURE+# define STATUS_TRUSTED_DOMAIN_FAILURE ((NTSTATUS) 0xC000018CL)+#endif++#ifndef STATUS_TRUSTED_RELATIONSHIP_FAILURE+# define STATUS_TRUSTED_RELATIONSHIP_FAILURE ((NTSTATUS) 0xC000018DL)+#endif++#ifndef STATUS_EVENTLOG_FILE_CORRUPT+# define STATUS_EVENTLOG_FILE_CORRUPT ((NTSTATUS) 0xC000018EL)+#endif++#ifndef STATUS_EVENTLOG_CANT_START+# define STATUS_EVENTLOG_CANT_START ((NTSTATUS) 0xC000018FL)+#endif++#ifndef STATUS_TRUST_FAILURE+# define STATUS_TRUST_FAILURE ((NTSTATUS) 0xC0000190L)+#endif++#ifndef STATUS_MUTANT_LIMIT_EXCEEDED+# define STATUS_MUTANT_LIMIT_EXCEEDED ((NTSTATUS) 0xC0000191L)+#endif++#ifndef STATUS_NETLOGON_NOT_STARTED+# define STATUS_NETLOGON_NOT_STARTED ((NTSTATUS) 0xC0000192L)+#endif++#ifndef STATUS_ACCOUNT_EXPIRED+# define STATUS_ACCOUNT_EXPIRED ((NTSTATUS) 0xC0000193L)+#endif++#ifndef STATUS_POSSIBLE_DEADLOCK+# define STATUS_POSSIBLE_DEADLOCK ((NTSTATUS) 0xC0000194L)+#endif++#ifndef STATUS_NETWORK_CREDENTIAL_CONFLICT+# define STATUS_NETWORK_CREDENTIAL_CONFLICT ((NTSTATUS) 0xC0000195L)+#endif++#ifndef STATUS_REMOTE_SESSION_LIMIT+# define STATUS_REMOTE_SESSION_LIMIT ((NTSTATUS) 0xC0000196L)+#endif++#ifndef STATUS_EVENTLOG_FILE_CHANGED+# define STATUS_EVENTLOG_FILE_CHANGED ((NTSTATUS) 0xC0000197L)+#endif++#ifndef STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT+# define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT ((NTSTATUS) 0xC0000198L)+#endif++#ifndef STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT+# define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT ((NTSTATUS) 0xC0000199L)+#endif++#ifndef STATUS_NOLOGON_SERVER_TRUST_ACCOUNT+# define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT ((NTSTATUS) 0xC000019AL)+#endif++#ifndef STATUS_DOMAIN_TRUST_INCONSISTENT+# define STATUS_DOMAIN_TRUST_INCONSISTENT ((NTSTATUS) 0xC000019BL)+#endif++#ifndef STATUS_FS_DRIVER_REQUIRED+# define STATUS_FS_DRIVER_REQUIRED ((NTSTATUS) 0xC000019CL)+#endif++#ifndef STATUS_IMAGE_ALREADY_LOADED_AS_DLL+# define STATUS_IMAGE_ALREADY_LOADED_AS_DLL ((NTSTATUS) 0xC000019DL)+#endif++#ifndef STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING+# define STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING ((NTSTATUS) 0xC000019EL)+#endif++#ifndef STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME+# define STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME ((NTSTATUS) 0xC000019FL)+#endif++#ifndef STATUS_SECURITY_STREAM_IS_INCONSISTENT+# define STATUS_SECURITY_STREAM_IS_INCONSISTENT ((NTSTATUS) 0xC00001A0L)+#endif++#ifndef STATUS_INVALID_LOCK_RANGE+# define STATUS_INVALID_LOCK_RANGE ((NTSTATUS) 0xC00001A1L)+#endif++#ifndef STATUS_INVALID_ACE_CONDITION+# define STATUS_INVALID_ACE_CONDITION ((NTSTATUS) 0xC00001A2L)+#endif++#ifndef STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT+# define STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT ((NTSTATUS) 0xC00001A3L)+#endif++#ifndef STATUS_NOTIFICATION_GUID_ALREADY_DEFINED+# define STATUS_NOTIFICATION_GUID_ALREADY_DEFINED ((NTSTATUS) 0xC00001A4L)+#endif++#ifndef STATUS_NETWORK_OPEN_RESTRICTION+# define STATUS_NETWORK_OPEN_RESTRICTION ((NTSTATUS) 0xC0000201L)+#endif++#ifndef STATUS_NO_USER_SESSION_KEY+# define STATUS_NO_USER_SESSION_KEY ((NTSTATUS) 0xC0000202L)+#endif++#ifndef STATUS_USER_SESSION_DELETED+# define STATUS_USER_SESSION_DELETED ((NTSTATUS) 0xC0000203L)+#endif++#ifndef STATUS_RESOURCE_LANG_NOT_FOUND+# define STATUS_RESOURCE_LANG_NOT_FOUND ((NTSTATUS) 0xC0000204L)+#endif++#ifndef STATUS_INSUFF_SERVER_RESOURCES+# define STATUS_INSUFF_SERVER_RESOURCES ((NTSTATUS) 0xC0000205L)+#endif++#ifndef STATUS_INVALID_BUFFER_SIZE+# define STATUS_INVALID_BUFFER_SIZE ((NTSTATUS) 0xC0000206L)+#endif++#ifndef STATUS_INVALID_ADDRESS_COMPONENT+# define STATUS_INVALID_ADDRESS_COMPONENT ((NTSTATUS) 0xC0000207L)+#endif++#ifndef STATUS_INVALID_ADDRESS_WILDCARD+# define STATUS_INVALID_ADDRESS_WILDCARD ((NTSTATUS) 0xC0000208L)+#endif++#ifndef STATUS_TOO_MANY_ADDRESSES+# define STATUS_TOO_MANY_ADDRESSES ((NTSTATUS) 0xC0000209L)+#endif++#ifndef STATUS_ADDRESS_ALREADY_EXISTS+# define STATUS_ADDRESS_ALREADY_EXISTS ((NTSTATUS) 0xC000020AL)+#endif++#ifndef STATUS_ADDRESS_CLOSED+# define STATUS_ADDRESS_CLOSED ((NTSTATUS) 0xC000020BL)+#endif++#ifndef STATUS_CONNECTION_DISCONNECTED+# define STATUS_CONNECTION_DISCONNECTED ((NTSTATUS) 0xC000020CL)+#endif++#ifndef STATUS_CONNECTION_RESET+# define STATUS_CONNECTION_RESET ((NTSTATUS) 0xC000020DL)+#endif++#ifndef STATUS_TOO_MANY_NODES+# define STATUS_TOO_MANY_NODES ((NTSTATUS) 0xC000020EL)+#endif++#ifndef STATUS_TRANSACTION_ABORTED+# define STATUS_TRANSACTION_ABORTED ((NTSTATUS) 0xC000020FL)+#endif++#ifndef STATUS_TRANSACTION_TIMED_OUT+# define STATUS_TRANSACTION_TIMED_OUT ((NTSTATUS) 0xC0000210L)+#endif++#ifndef STATUS_TRANSACTION_NO_RELEASE+# define STATUS_TRANSACTION_NO_RELEASE ((NTSTATUS) 0xC0000211L)+#endif++#ifndef STATUS_TRANSACTION_NO_MATCH+# define STATUS_TRANSACTION_NO_MATCH ((NTSTATUS) 0xC0000212L)+#endif++#ifndef STATUS_TRANSACTION_RESPONDED+# define STATUS_TRANSACTION_RESPONDED ((NTSTATUS) 0xC0000213L)+#endif++#ifndef STATUS_TRANSACTION_INVALID_ID+# define STATUS_TRANSACTION_INVALID_ID ((NTSTATUS) 0xC0000214L)+#endif++#ifndef STATUS_TRANSACTION_INVALID_TYPE+# define STATUS_TRANSACTION_INVALID_TYPE ((NTSTATUS) 0xC0000215L)+#endif++#ifndef STATUS_NOT_SERVER_SESSION+# define STATUS_NOT_SERVER_SESSION ((NTSTATUS) 0xC0000216L)+#endif++#ifndef STATUS_NOT_CLIENT_SESSION+# define STATUS_NOT_CLIENT_SESSION ((NTSTATUS) 0xC0000217L)+#endif++#ifndef STATUS_CANNOT_LOAD_REGISTRY_FILE+# define STATUS_CANNOT_LOAD_REGISTRY_FILE ((NTSTATUS) 0xC0000218L)+#endif++#ifndef STATUS_DEBUG_ATTACH_FAILED+# define STATUS_DEBUG_ATTACH_FAILED ((NTSTATUS) 0xC0000219L)+#endif++#ifndef STATUS_SYSTEM_PROCESS_TERMINATED+# define STATUS_SYSTEM_PROCESS_TERMINATED ((NTSTATUS) 0xC000021AL)+#endif++#ifndef STATUS_DATA_NOT_ACCEPTED+# define STATUS_DATA_NOT_ACCEPTED ((NTSTATUS) 0xC000021BL)+#endif++#ifndef STATUS_NO_BROWSER_SERVERS_FOUND+# define STATUS_NO_BROWSER_SERVERS_FOUND ((NTSTATUS) 0xC000021CL)+#endif++#ifndef STATUS_VDM_HARD_ERROR+# define STATUS_VDM_HARD_ERROR ((NTSTATUS) 0xC000021DL)+#endif++#ifndef STATUS_DRIVER_CANCEL_TIMEOUT+# define STATUS_DRIVER_CANCEL_TIMEOUT ((NTSTATUS) 0xC000021EL)+#endif++#ifndef STATUS_REPLY_MESSAGE_MISMATCH+# define STATUS_REPLY_MESSAGE_MISMATCH ((NTSTATUS) 0xC000021FL)+#endif++#ifndef STATUS_MAPPED_ALIGNMENT+# define STATUS_MAPPED_ALIGNMENT ((NTSTATUS) 0xC0000220L)+#endif++#ifndef STATUS_IMAGE_CHECKSUM_MISMATCH+# define STATUS_IMAGE_CHECKSUM_MISMATCH ((NTSTATUS) 0xC0000221L)+#endif++#ifndef STATUS_LOST_WRITEBEHIND_DATA+# define STATUS_LOST_WRITEBEHIND_DATA ((NTSTATUS) 0xC0000222L)+#endif++#ifndef STATUS_CLIENT_SERVER_PARAMETERS_INVALID+# define STATUS_CLIENT_SERVER_PARAMETERS_INVALID ((NTSTATUS) 0xC0000223L)+#endif++#ifndef STATUS_PASSWORD_MUST_CHANGE+# define STATUS_PASSWORD_MUST_CHANGE ((NTSTATUS) 0xC0000224L)+#endif++#ifndef STATUS_NOT_FOUND+# define STATUS_NOT_FOUND ((NTSTATUS) 0xC0000225L)+#endif++#ifndef STATUS_NOT_TINY_STREAM+# define STATUS_NOT_TINY_STREAM ((NTSTATUS) 0xC0000226L)+#endif++#ifndef STATUS_RECOVERY_FAILURE+# define STATUS_RECOVERY_FAILURE ((NTSTATUS) 0xC0000227L)+#endif++#ifndef STATUS_STACK_OVERFLOW_READ+# define STATUS_STACK_OVERFLOW_READ ((NTSTATUS) 0xC0000228L)+#endif++#ifndef STATUS_FAIL_CHECK+# define STATUS_FAIL_CHECK ((NTSTATUS) 0xC0000229L)+#endif++#ifndef STATUS_DUPLICATE_OBJECTID+# define STATUS_DUPLICATE_OBJECTID ((NTSTATUS) 0xC000022AL)+#endif++#ifndef STATUS_OBJECTID_EXISTS+# define STATUS_OBJECTID_EXISTS ((NTSTATUS) 0xC000022BL)+#endif++#ifndef STATUS_CONVERT_TO_LARGE+# define STATUS_CONVERT_TO_LARGE ((NTSTATUS) 0xC000022CL)+#endif++#ifndef STATUS_RETRY+# define STATUS_RETRY ((NTSTATUS) 0xC000022DL)+#endif++#ifndef STATUS_FOUND_OUT_OF_SCOPE+# define STATUS_FOUND_OUT_OF_SCOPE ((NTSTATUS) 0xC000022EL)+#endif++#ifndef STATUS_ALLOCATE_BUCKET+# define STATUS_ALLOCATE_BUCKET ((NTSTATUS) 0xC000022FL)+#endif++#ifndef STATUS_PROPSET_NOT_FOUND+# define STATUS_PROPSET_NOT_FOUND ((NTSTATUS) 0xC0000230L)+#endif++#ifndef STATUS_MARSHALL_OVERFLOW+# define STATUS_MARSHALL_OVERFLOW ((NTSTATUS) 0xC0000231L)+#endif++#ifndef STATUS_INVALID_VARIANT+# define STATUS_INVALID_VARIANT ((NTSTATUS) 0xC0000232L)+#endif++#ifndef STATUS_DOMAIN_CONTROLLER_NOT_FOUND+# define STATUS_DOMAIN_CONTROLLER_NOT_FOUND ((NTSTATUS) 0xC0000233L)+#endif++#ifndef STATUS_ACCOUNT_LOCKED_OUT+# define STATUS_ACCOUNT_LOCKED_OUT ((NTSTATUS) 0xC0000234L)+#endif++#ifndef STATUS_HANDLE_NOT_CLOSABLE+# define STATUS_HANDLE_NOT_CLOSABLE ((NTSTATUS) 0xC0000235L)+#endif++#ifndef STATUS_CONNECTION_REFUSED+# define STATUS_CONNECTION_REFUSED ((NTSTATUS) 0xC0000236L)+#endif++#ifndef STATUS_GRACEFUL_DISCONNECT+# define STATUS_GRACEFUL_DISCONNECT ((NTSTATUS) 0xC0000237L)+#endif++#ifndef STATUS_ADDRESS_ALREADY_ASSOCIATED+# define STATUS_ADDRESS_ALREADY_ASSOCIATED ((NTSTATUS) 0xC0000238L)+#endif++#ifndef STATUS_ADDRESS_NOT_ASSOCIATED+# define STATUS_ADDRESS_NOT_ASSOCIATED ((NTSTATUS) 0xC0000239L)+#endif++#ifndef STATUS_CONNECTION_INVALID+# define STATUS_CONNECTION_INVALID ((NTSTATUS) 0xC000023AL)+#endif++#ifndef STATUS_CONNECTION_ACTIVE+# define STATUS_CONNECTION_ACTIVE ((NTSTATUS) 0xC000023BL)+#endif++#ifndef STATUS_NETWORK_UNREACHABLE+# define STATUS_NETWORK_UNREACHABLE ((NTSTATUS) 0xC000023CL)+#endif++#ifndef STATUS_HOST_UNREACHABLE+# define STATUS_HOST_UNREACHABLE ((NTSTATUS) 0xC000023DL)+#endif++#ifndef STATUS_PROTOCOL_UNREACHABLE+# define STATUS_PROTOCOL_UNREACHABLE ((NTSTATUS) 0xC000023EL)+#endif++#ifndef STATUS_PORT_UNREACHABLE+# define STATUS_PORT_UNREACHABLE ((NTSTATUS) 0xC000023FL)+#endif++#ifndef STATUS_REQUEST_ABORTED+# define STATUS_REQUEST_ABORTED ((NTSTATUS) 0xC0000240L)+#endif++#ifndef STATUS_CONNECTION_ABORTED+# define STATUS_CONNECTION_ABORTED ((NTSTATUS) 0xC0000241L)+#endif++#ifndef STATUS_BAD_COMPRESSION_BUFFER+# define STATUS_BAD_COMPRESSION_BUFFER ((NTSTATUS) 0xC0000242L)+#endif++#ifndef STATUS_USER_MAPPED_FILE+# define STATUS_USER_MAPPED_FILE ((NTSTATUS) 0xC0000243L)+#endif++#ifndef STATUS_AUDIT_FAILED+# define STATUS_AUDIT_FAILED ((NTSTATUS) 0xC0000244L)+#endif++#ifndef STATUS_TIMER_RESOLUTION_NOT_SET+# define STATUS_TIMER_RESOLUTION_NOT_SET ((NTSTATUS) 0xC0000245L)+#endif++#ifndef STATUS_CONNECTION_COUNT_LIMIT+# define STATUS_CONNECTION_COUNT_LIMIT ((NTSTATUS) 0xC0000246L)+#endif++#ifndef STATUS_LOGIN_TIME_RESTRICTION+# define STATUS_LOGIN_TIME_RESTRICTION ((NTSTATUS) 0xC0000247L)+#endif++#ifndef STATUS_LOGIN_WKSTA_RESTRICTION+# define STATUS_LOGIN_WKSTA_RESTRICTION ((NTSTATUS) 0xC0000248L)+#endif++#ifndef STATUS_IMAGE_MP_UP_MISMATCH+# define STATUS_IMAGE_MP_UP_MISMATCH ((NTSTATUS) 0xC0000249L)+#endif++#ifndef STATUS_INSUFFICIENT_LOGON_INFO+# define STATUS_INSUFFICIENT_LOGON_INFO ((NTSTATUS) 0xC0000250L)+#endif++#ifndef STATUS_BAD_DLL_ENTRYPOINT+# define STATUS_BAD_DLL_ENTRYPOINT ((NTSTATUS) 0xC0000251L)+#endif++#ifndef STATUS_BAD_SERVICE_ENTRYPOINT+# define STATUS_BAD_SERVICE_ENTRYPOINT ((NTSTATUS) 0xC0000252L)+#endif++#ifndef STATUS_LPC_REPLY_LOST+# define STATUS_LPC_REPLY_LOST ((NTSTATUS) 0xC0000253L)+#endif++#ifndef STATUS_IP_ADDRESS_CONFLICT1+# define STATUS_IP_ADDRESS_CONFLICT1 ((NTSTATUS) 0xC0000254L)+#endif++#ifndef STATUS_IP_ADDRESS_CONFLICT2+# define STATUS_IP_ADDRESS_CONFLICT2 ((NTSTATUS) 0xC0000255L)+#endif++#ifndef STATUS_REGISTRY_QUOTA_LIMIT+# define STATUS_REGISTRY_QUOTA_LIMIT ((NTSTATUS) 0xC0000256L)+#endif++#ifndef STATUS_PATH_NOT_COVERED+# define STATUS_PATH_NOT_COVERED ((NTSTATUS) 0xC0000257L)+#endif++#ifndef STATUS_NO_CALLBACK_ACTIVE+# define STATUS_NO_CALLBACK_ACTIVE ((NTSTATUS) 0xC0000258L)+#endif++#ifndef STATUS_LICENSE_QUOTA_EXCEEDED+# define STATUS_LICENSE_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000259L)+#endif++#ifndef STATUS_PWD_TOO_SHORT+# define STATUS_PWD_TOO_SHORT ((NTSTATUS) 0xC000025AL)+#endif++#ifndef STATUS_PWD_TOO_RECENT+# define STATUS_PWD_TOO_RECENT ((NTSTATUS) 0xC000025BL)+#endif++#ifndef STATUS_PWD_HISTORY_CONFLICT+# define STATUS_PWD_HISTORY_CONFLICT ((NTSTATUS) 0xC000025CL)+#endif++#ifndef STATUS_PLUGPLAY_NO_DEVICE+# define STATUS_PLUGPLAY_NO_DEVICE ((NTSTATUS) 0xC000025EL)+#endif++#ifndef STATUS_UNSUPPORTED_COMPRESSION+# define STATUS_UNSUPPORTED_COMPRESSION ((NTSTATUS) 0xC000025FL)+#endif++#ifndef STATUS_INVALID_HW_PROFILE+# define STATUS_INVALID_HW_PROFILE ((NTSTATUS) 0xC0000260L)+#endif++#ifndef STATUS_INVALID_PLUGPLAY_DEVICE_PATH+# define STATUS_INVALID_PLUGPLAY_DEVICE_PATH ((NTSTATUS) 0xC0000261L)+#endif++#ifndef STATUS_DRIVER_ORDINAL_NOT_FOUND+# define STATUS_DRIVER_ORDINAL_NOT_FOUND ((NTSTATUS) 0xC0000262L)+#endif++#ifndef STATUS_DRIVER_ENTRYPOINT_NOT_FOUND+# define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xC0000263L)+#endif++#ifndef STATUS_RESOURCE_NOT_OWNED+# define STATUS_RESOURCE_NOT_OWNED ((NTSTATUS) 0xC0000264L)+#endif++#ifndef STATUS_TOO_MANY_LINKS+# define STATUS_TOO_MANY_LINKS ((NTSTATUS) 0xC0000265L)+#endif++#ifndef STATUS_QUOTA_LIST_INCONSISTENT+# define STATUS_QUOTA_LIST_INCONSISTENT ((NTSTATUS) 0xC0000266L)+#endif++#ifndef STATUS_FILE_IS_OFFLINE+# define STATUS_FILE_IS_OFFLINE ((NTSTATUS) 0xC0000267L)+#endif++#ifndef STATUS_EVALUATION_EXPIRATION+# define STATUS_EVALUATION_EXPIRATION ((NTSTATUS) 0xC0000268L)+#endif++#ifndef STATUS_ILLEGAL_DLL_RELOCATION+# define STATUS_ILLEGAL_DLL_RELOCATION ((NTSTATUS) 0xC0000269L)+#endif++#ifndef STATUS_LICENSE_VIOLATION+# define STATUS_LICENSE_VIOLATION ((NTSTATUS) 0xC000026AL)+#endif++#ifndef STATUS_DLL_INIT_FAILED_LOGOFF+# define STATUS_DLL_INIT_FAILED_LOGOFF ((NTSTATUS) 0xC000026BL)+#endif++#ifndef STATUS_DRIVER_UNABLE_TO_LOAD+# define STATUS_DRIVER_UNABLE_TO_LOAD ((NTSTATUS) 0xC000026CL)+#endif++#ifndef STATUS_DFS_UNAVAILABLE+# define STATUS_DFS_UNAVAILABLE ((NTSTATUS) 0xC000026DL)+#endif++#ifndef STATUS_VOLUME_DISMOUNTED+# define STATUS_VOLUME_DISMOUNTED ((NTSTATUS) 0xC000026EL)+#endif++#ifndef STATUS_WX86_INTERNAL_ERROR+# define STATUS_WX86_INTERNAL_ERROR ((NTSTATUS) 0xC000026FL)+#endif++#ifndef STATUS_WX86_FLOAT_STACK_CHECK+# define STATUS_WX86_FLOAT_STACK_CHECK ((NTSTATUS) 0xC0000270L)+#endif++#ifndef STATUS_VALIDATE_CONTINUE+# define STATUS_VALIDATE_CONTINUE ((NTSTATUS) 0xC0000271L)+#endif++#ifndef STATUS_NO_MATCH+# define STATUS_NO_MATCH ((NTSTATUS) 0xC0000272L)+#endif++#ifndef STATUS_NO_MORE_MATCHES+# define STATUS_NO_MORE_MATCHES ((NTSTATUS) 0xC0000273L)+#endif++#ifndef STATUS_NOT_A_REPARSE_POINT+# define STATUS_NOT_A_REPARSE_POINT ((NTSTATUS) 0xC0000275L)+#endif++#ifndef STATUS_IO_REPARSE_TAG_INVALID+# define STATUS_IO_REPARSE_TAG_INVALID ((NTSTATUS) 0xC0000276L)+#endif++#ifndef STATUS_IO_REPARSE_TAG_MISMATCH+# define STATUS_IO_REPARSE_TAG_MISMATCH ((NTSTATUS) 0xC0000277L)+#endif++#ifndef STATUS_IO_REPARSE_DATA_INVALID+# define STATUS_IO_REPARSE_DATA_INVALID ((NTSTATUS) 0xC0000278L)+#endif++#ifndef STATUS_IO_REPARSE_TAG_NOT_HANDLED+# define STATUS_IO_REPARSE_TAG_NOT_HANDLED ((NTSTATUS) 0xC0000279L)+#endif++#ifndef STATUS_REPARSE_POINT_NOT_RESOLVED+# define STATUS_REPARSE_POINT_NOT_RESOLVED ((NTSTATUS) 0xC0000280L)+#endif++#ifndef STATUS_DIRECTORY_IS_A_REPARSE_POINT+# define STATUS_DIRECTORY_IS_A_REPARSE_POINT ((NTSTATUS) 0xC0000281L)+#endif++#ifndef STATUS_RANGE_LIST_CONFLICT+# define STATUS_RANGE_LIST_CONFLICT ((NTSTATUS) 0xC0000282L)+#endif++#ifndef STATUS_SOURCE_ELEMENT_EMPTY+# define STATUS_SOURCE_ELEMENT_EMPTY ((NTSTATUS) 0xC0000283L)+#endif++#ifndef STATUS_DESTINATION_ELEMENT_FULL+# define STATUS_DESTINATION_ELEMENT_FULL ((NTSTATUS) 0xC0000284L)+#endif++#ifndef STATUS_ILLEGAL_ELEMENT_ADDRESS+# define STATUS_ILLEGAL_ELEMENT_ADDRESS ((NTSTATUS) 0xC0000285L)+#endif++#ifndef STATUS_MAGAZINE_NOT_PRESENT+# define STATUS_MAGAZINE_NOT_PRESENT ((NTSTATUS) 0xC0000286L)+#endif++#ifndef STATUS_REINITIALIZATION_NEEDED+# define STATUS_REINITIALIZATION_NEEDED ((NTSTATUS) 0xC0000287L)+#endif++#ifndef STATUS_DEVICE_REQUIRES_CLEANING+# define STATUS_DEVICE_REQUIRES_CLEANING ((NTSTATUS) 0x80000288L)+#endif++#ifndef STATUS_DEVICE_DOOR_OPEN+# define STATUS_DEVICE_DOOR_OPEN ((NTSTATUS) 0x80000289L)+#endif++#ifndef STATUS_ENCRYPTION_FAILED+# define STATUS_ENCRYPTION_FAILED ((NTSTATUS) 0xC000028AL)+#endif++#ifndef STATUS_DECRYPTION_FAILED+# define STATUS_DECRYPTION_FAILED ((NTSTATUS) 0xC000028BL)+#endif++#ifndef STATUS_RANGE_NOT_FOUND+# define STATUS_RANGE_NOT_FOUND ((NTSTATUS) 0xC000028CL)+#endif++#ifndef STATUS_NO_RECOVERY_POLICY+# define STATUS_NO_RECOVERY_POLICY ((NTSTATUS) 0xC000028DL)+#endif++#ifndef STATUS_NO_EFS+# define STATUS_NO_EFS ((NTSTATUS) 0xC000028EL)+#endif++#ifndef STATUS_WRONG_EFS+# define STATUS_WRONG_EFS ((NTSTATUS) 0xC000028FL)+#endif++#ifndef STATUS_NO_USER_KEYS+# define STATUS_NO_USER_KEYS ((NTSTATUS) 0xC0000290L)+#endif++#ifndef STATUS_FILE_NOT_ENCRYPTED+# define STATUS_FILE_NOT_ENCRYPTED ((NTSTATUS) 0xC0000291L)+#endif++#ifndef STATUS_NOT_EXPORT_FORMAT+# define STATUS_NOT_EXPORT_FORMAT ((NTSTATUS) 0xC0000292L)+#endif++#ifndef STATUS_FILE_ENCRYPTED+# define STATUS_FILE_ENCRYPTED ((NTSTATUS) 0xC0000293L)+#endif++#ifndef STATUS_WAKE_SYSTEM+# define STATUS_WAKE_SYSTEM ((NTSTATUS) 0x40000294L)+#endif++#ifndef STATUS_WMI_GUID_NOT_FOUND+# define STATUS_WMI_GUID_NOT_FOUND ((NTSTATUS) 0xC0000295L)+#endif++#ifndef STATUS_WMI_INSTANCE_NOT_FOUND+# define STATUS_WMI_INSTANCE_NOT_FOUND ((NTSTATUS) 0xC0000296L)+#endif++#ifndef STATUS_WMI_ITEMID_NOT_FOUND+# define STATUS_WMI_ITEMID_NOT_FOUND ((NTSTATUS) 0xC0000297L)+#endif++#ifndef STATUS_WMI_TRY_AGAIN+# define STATUS_WMI_TRY_AGAIN ((NTSTATUS) 0xC0000298L)+#endif++#ifndef STATUS_SHARED_POLICY+# define STATUS_SHARED_POLICY ((NTSTATUS) 0xC0000299L)+#endif++#ifndef STATUS_POLICY_OBJECT_NOT_FOUND+# define STATUS_POLICY_OBJECT_NOT_FOUND ((NTSTATUS) 0xC000029AL)+#endif++#ifndef STATUS_POLICY_ONLY_IN_DS+# define STATUS_POLICY_ONLY_IN_DS ((NTSTATUS) 0xC000029BL)+#endif++#ifndef STATUS_VOLUME_NOT_UPGRADED+# define STATUS_VOLUME_NOT_UPGRADED ((NTSTATUS) 0xC000029CL)+#endif++#ifndef STATUS_REMOTE_STORAGE_NOT_ACTIVE+# define STATUS_REMOTE_STORAGE_NOT_ACTIVE ((NTSTATUS) 0xC000029DL)+#endif++#ifndef STATUS_REMOTE_STORAGE_MEDIA_ERROR+# define STATUS_REMOTE_STORAGE_MEDIA_ERROR ((NTSTATUS) 0xC000029EL)+#endif++#ifndef STATUS_NO_TRACKING_SERVICE+# define STATUS_NO_TRACKING_SERVICE ((NTSTATUS) 0xC000029FL)+#endif++#ifndef STATUS_SERVER_SID_MISMATCH+# define STATUS_SERVER_SID_MISMATCH ((NTSTATUS) 0xC00002A0L)+#endif++#ifndef STATUS_DS_NO_ATTRIBUTE_OR_VALUE+# define STATUS_DS_NO_ATTRIBUTE_OR_VALUE ((NTSTATUS) 0xC00002A1L)+#endif++#ifndef STATUS_DS_INVALID_ATTRIBUTE_SYNTAX+# define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX ((NTSTATUS) 0xC00002A2L)+#endif++#ifndef STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED+# define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED ((NTSTATUS) 0xC00002A3L)+#endif++#ifndef STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS+# define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS ((NTSTATUS) 0xC00002A4L)+#endif++#ifndef STATUS_DS_BUSY+# define STATUS_DS_BUSY ((NTSTATUS) 0xC00002A5L)+#endif++#ifndef STATUS_DS_UNAVAILABLE+# define STATUS_DS_UNAVAILABLE ((NTSTATUS) 0xC00002A6L)+#endif++#ifndef STATUS_DS_NO_RIDS_ALLOCATED+# define STATUS_DS_NO_RIDS_ALLOCATED ((NTSTATUS) 0xC00002A7L)+#endif++#ifndef STATUS_DS_NO_MORE_RIDS+# define STATUS_DS_NO_MORE_RIDS ((NTSTATUS) 0xC00002A8L)+#endif++#ifndef STATUS_DS_INCORRECT_ROLE_OWNER+# define STATUS_DS_INCORRECT_ROLE_OWNER ((NTSTATUS) 0xC00002A9L)+#endif++#ifndef STATUS_DS_RIDMGR_INIT_ERROR+# define STATUS_DS_RIDMGR_INIT_ERROR ((NTSTATUS) 0xC00002AAL)+#endif++#ifndef STATUS_DS_OBJ_CLASS_VIOLATION+# define STATUS_DS_OBJ_CLASS_VIOLATION ((NTSTATUS) 0xC00002ABL)+#endif++#ifndef STATUS_DS_CANT_ON_NON_LEAF+# define STATUS_DS_CANT_ON_NON_LEAF ((NTSTATUS) 0xC00002ACL)+#endif++#ifndef STATUS_DS_CANT_ON_RDN+# define STATUS_DS_CANT_ON_RDN ((NTSTATUS) 0xC00002ADL)+#endif++#ifndef STATUS_DS_CANT_MOD_OBJ_CLASS+# define STATUS_DS_CANT_MOD_OBJ_CLASS ((NTSTATUS) 0xC00002AEL)+#endif++#ifndef STATUS_DS_CROSS_DOM_MOVE_FAILED+# define STATUS_DS_CROSS_DOM_MOVE_FAILED ((NTSTATUS) 0xC00002AFL)+#endif++#ifndef STATUS_DS_GC_NOT_AVAILABLE+# define STATUS_DS_GC_NOT_AVAILABLE ((NTSTATUS) 0xC00002B0L)+#endif++#ifndef STATUS_DIRECTORY_SERVICE_REQUIRED+# define STATUS_DIRECTORY_SERVICE_REQUIRED ((NTSTATUS) 0xC00002B1L)+#endif++#ifndef STATUS_REPARSE_ATTRIBUTE_CONFLICT+# define STATUS_REPARSE_ATTRIBUTE_CONFLICT ((NTSTATUS) 0xC00002B2L)+#endif++#ifndef STATUS_CANT_ENABLE_DENY_ONLY+# define STATUS_CANT_ENABLE_DENY_ONLY ((NTSTATUS) 0xC00002B3L)+#endif++#ifndef STATUS_FLOAT_MULTIPLE_FAULTS+# define STATUS_FLOAT_MULTIPLE_FAULTS ((NTSTATUS) 0xC00002B4L)+#endif++#ifndef STATUS_FLOAT_MULTIPLE_TRAPS+# define STATUS_FLOAT_MULTIPLE_TRAPS ((NTSTATUS) 0xC00002B5L)+#endif++#ifndef STATUS_DEVICE_REMOVED+# define STATUS_DEVICE_REMOVED ((NTSTATUS) 0xC00002B6L)+#endif++#ifndef STATUS_JOURNAL_DELETE_IN_PROGRESS+# define STATUS_JOURNAL_DELETE_IN_PROGRESS ((NTSTATUS) 0xC00002B7L)+#endif++#ifndef STATUS_JOURNAL_NOT_ACTIVE+# define STATUS_JOURNAL_NOT_ACTIVE ((NTSTATUS) 0xC00002B8L)+#endif++#ifndef STATUS_NOINTERFACE+# define STATUS_NOINTERFACE ((NTSTATUS) 0xC00002B9L)+#endif++#ifndef STATUS_DS_ADMIN_LIMIT_EXCEEDED+# define STATUS_DS_ADMIN_LIMIT_EXCEEDED ((NTSTATUS) 0xC00002C1L)+#endif++#ifndef STATUS_DRIVER_FAILED_SLEEP+# define STATUS_DRIVER_FAILED_SLEEP ((NTSTATUS) 0xC00002C2L)+#endif++#ifndef STATUS_MUTUAL_AUTHENTICATION_FAILED+# define STATUS_MUTUAL_AUTHENTICATION_FAILED ((NTSTATUS) 0xC00002C3L)+#endif++#ifndef STATUS_CORRUPT_SYSTEM_FILE+# define STATUS_CORRUPT_SYSTEM_FILE ((NTSTATUS) 0xC00002C4L)+#endif++#ifndef STATUS_DATATYPE_MISALIGNMENT_ERROR+# define STATUS_DATATYPE_MISALIGNMENT_ERROR ((NTSTATUS) 0xC00002C5L)+#endif++#ifndef STATUS_WMI_READ_ONLY+# define STATUS_WMI_READ_ONLY ((NTSTATUS) 0xC00002C6L)+#endif++#ifndef STATUS_WMI_SET_FAILURE+# define STATUS_WMI_SET_FAILURE ((NTSTATUS) 0xC00002C7L)+#endif++#ifndef STATUS_COMMITMENT_MINIMUM+# define STATUS_COMMITMENT_MINIMUM ((NTSTATUS) 0xC00002C8L)+#endif++#ifndef STATUS_REG_NAT_CONSUMPTION+# define STATUS_REG_NAT_CONSUMPTION ((NTSTATUS) 0xC00002C9L)+#endif++#ifndef STATUS_TRANSPORT_FULL+# define STATUS_TRANSPORT_FULL ((NTSTATUS) 0xC00002CAL)+#endif++#ifndef STATUS_DS_SAM_INIT_FAILURE+# define STATUS_DS_SAM_INIT_FAILURE ((NTSTATUS) 0xC00002CBL)+#endif++#ifndef STATUS_ONLY_IF_CONNECTED+# define STATUS_ONLY_IF_CONNECTED ((NTSTATUS) 0xC00002CCL)+#endif++#ifndef STATUS_DS_SENSITIVE_GROUP_VIOLATION+# define STATUS_DS_SENSITIVE_GROUP_VIOLATION ((NTSTATUS) 0xC00002CDL)+#endif++#ifndef STATUS_PNP_RESTART_ENUMERATION+# define STATUS_PNP_RESTART_ENUMERATION ((NTSTATUS) 0xC00002CEL)+#endif++#ifndef STATUS_JOURNAL_ENTRY_DELETED+# define STATUS_JOURNAL_ENTRY_DELETED ((NTSTATUS) 0xC00002CFL)+#endif++#ifndef STATUS_DS_CANT_MOD_PRIMARYGROUPID+# define STATUS_DS_CANT_MOD_PRIMARYGROUPID ((NTSTATUS) 0xC00002D0L)+#endif++#ifndef STATUS_SYSTEM_IMAGE_BAD_SIGNATURE+# define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE ((NTSTATUS) 0xC00002D1L)+#endif++#ifndef STATUS_PNP_REBOOT_REQUIRED+# define STATUS_PNP_REBOOT_REQUIRED ((NTSTATUS) 0xC00002D2L)+#endif++#ifndef STATUS_POWER_STATE_INVALID+# define STATUS_POWER_STATE_INVALID ((NTSTATUS) 0xC00002D3L)+#endif++#ifndef STATUS_DS_INVALID_GROUP_TYPE+# define STATUS_DS_INVALID_GROUP_TYPE ((NTSTATUS) 0xC00002D4L)+#endif++#ifndef STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN+# define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN ((NTSTATUS) 0xC00002D5L)+#endif++#ifndef STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN+# define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN ((NTSTATUS) 0xC00002D6L)+#endif++#ifndef STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER+# define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS) 0xC00002D7L)+#endif++#ifndef STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER+# define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS) 0xC00002D8L)+#endif++#ifndef STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER+# define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS) 0xC00002D9L)+#endif++#ifndef STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER+# define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER ((NTSTATUS) 0xC00002DAL)+#endif++#ifndef STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER+# define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER ((NTSTATUS) 0xC00002DBL)+#endif++#ifndef STATUS_DS_HAVE_PRIMARY_MEMBERS+# define STATUS_DS_HAVE_PRIMARY_MEMBERS ((NTSTATUS) 0xC00002DCL)+#endif++#ifndef STATUS_WMI_NOT_SUPPORTED+# define STATUS_WMI_NOT_SUPPORTED ((NTSTATUS) 0xC00002DDL)+#endif++#ifndef STATUS_INSUFFICIENT_POWER+# define STATUS_INSUFFICIENT_POWER ((NTSTATUS) 0xC00002DEL)+#endif++#ifndef STATUS_SAM_NEED_BOOTKEY_PASSWORD+# define STATUS_SAM_NEED_BOOTKEY_PASSWORD ((NTSTATUS) 0xC00002DFL)+#endif++#ifndef STATUS_SAM_NEED_BOOTKEY_FLOPPY+# define STATUS_SAM_NEED_BOOTKEY_FLOPPY ((NTSTATUS) 0xC00002E0L)+#endif++#ifndef STATUS_DS_CANT_START+# define STATUS_DS_CANT_START ((NTSTATUS) 0xC00002E1L)+#endif++#ifndef STATUS_DS_INIT_FAILURE+# define STATUS_DS_INIT_FAILURE ((NTSTATUS) 0xC00002E2L)+#endif++#ifndef STATUS_SAM_INIT_FAILURE+# define STATUS_SAM_INIT_FAILURE ((NTSTATUS) 0xC00002E3L)+#endif++#ifndef STATUS_DS_GC_REQUIRED+# define STATUS_DS_GC_REQUIRED ((NTSTATUS) 0xC00002E4L)+#endif++#ifndef STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY+# define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY ((NTSTATUS) 0xC00002E5L)+#endif++#ifndef STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS+# define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS ((NTSTATUS) 0xC00002E6L)+#endif++#ifndef STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED+# define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED ((NTSTATUS) 0xC00002E7L)+#endif++#ifndef STATUS_MULTIPLE_FAULT_VIOLATION+# define STATUS_MULTIPLE_FAULT_VIOLATION ((NTSTATUS) 0xC00002E8L)+#endif++#ifndef STATUS_CURRENT_DOMAIN_NOT_ALLOWED+# define STATUS_CURRENT_DOMAIN_NOT_ALLOWED ((NTSTATUS) 0xC00002E9L)+#endif++#ifndef STATUS_CANNOT_MAKE+# define STATUS_CANNOT_MAKE ((NTSTATUS) 0xC00002EAL)+#endif++#ifndef STATUS_SYSTEM_SHUTDOWN+# define STATUS_SYSTEM_SHUTDOWN ((NTSTATUS) 0xC00002EBL)+#endif++#ifndef STATUS_DS_INIT_FAILURE_CONSOLE+# define STATUS_DS_INIT_FAILURE_CONSOLE ((NTSTATUS) 0xC00002ECL)+#endif++#ifndef STATUS_DS_SAM_INIT_FAILURE_CONSOLE+# define STATUS_DS_SAM_INIT_FAILURE_CONSOLE ((NTSTATUS) 0xC00002EDL)+#endif++#ifndef STATUS_UNFINISHED_CONTEXT_DELETED+# define STATUS_UNFINISHED_CONTEXT_DELETED ((NTSTATUS) 0xC00002EEL)+#endif++#ifndef STATUS_NO_TGT_REPLY+# define STATUS_NO_TGT_REPLY ((NTSTATUS) 0xC00002EFL)+#endif++#ifndef STATUS_OBJECTID_NOT_FOUND+# define STATUS_OBJECTID_NOT_FOUND ((NTSTATUS) 0xC00002F0L)+#endif++#ifndef STATUS_NO_IP_ADDRESSES+# define STATUS_NO_IP_ADDRESSES ((NTSTATUS) 0xC00002F1L)+#endif++#ifndef STATUS_WRONG_CREDENTIAL_HANDLE+# define STATUS_WRONG_CREDENTIAL_HANDLE ((NTSTATUS) 0xC00002F2L)+#endif++#ifndef STATUS_CRYPTO_SYSTEM_INVALID+# define STATUS_CRYPTO_SYSTEM_INVALID ((NTSTATUS) 0xC00002F3L)+#endif++#ifndef STATUS_MAX_REFERRALS_EXCEEDED+# define STATUS_MAX_REFERRALS_EXCEEDED ((NTSTATUS) 0xC00002F4L)+#endif++#ifndef STATUS_MUST_BE_KDC+# define STATUS_MUST_BE_KDC ((NTSTATUS) 0xC00002F5L)+#endif++#ifndef STATUS_STRONG_CRYPTO_NOT_SUPPORTED+# define STATUS_STRONG_CRYPTO_NOT_SUPPORTED ((NTSTATUS) 0xC00002F6L)+#endif++#ifndef STATUS_TOO_MANY_PRINCIPALS+# define STATUS_TOO_MANY_PRINCIPALS ((NTSTATUS) 0xC00002F7L)+#endif++#ifndef STATUS_NO_PA_DATA+# define STATUS_NO_PA_DATA ((NTSTATUS) 0xC00002F8L)+#endif++#ifndef STATUS_PKINIT_NAME_MISMATCH+# define STATUS_PKINIT_NAME_MISMATCH ((NTSTATUS) 0xC00002F9L)+#endif++#ifndef STATUS_SMARTCARD_LOGON_REQUIRED+# define STATUS_SMARTCARD_LOGON_REQUIRED ((NTSTATUS) 0xC00002FAL)+#endif++#ifndef STATUS_KDC_INVALID_REQUEST+# define STATUS_KDC_INVALID_REQUEST ((NTSTATUS) 0xC00002FBL)+#endif++#ifndef STATUS_KDC_UNABLE_TO_REFER+# define STATUS_KDC_UNABLE_TO_REFER ((NTSTATUS) 0xC00002FCL)+#endif++#ifndef STATUS_KDC_UNKNOWN_ETYPE+# define STATUS_KDC_UNKNOWN_ETYPE ((NTSTATUS) 0xC00002FDL)+#endif++#ifndef STATUS_SHUTDOWN_IN_PROGRESS+# define STATUS_SHUTDOWN_IN_PROGRESS ((NTSTATUS) 0xC00002FEL)+#endif++#ifndef STATUS_SERVER_SHUTDOWN_IN_PROGRESS+# define STATUS_SERVER_SHUTDOWN_IN_PROGRESS ((NTSTATUS) 0xC00002FFL)+#endif++#ifndef STATUS_NOT_SUPPORTED_ON_SBS+# define STATUS_NOT_SUPPORTED_ON_SBS ((NTSTATUS) 0xC0000300L)+#endif++#ifndef STATUS_WMI_GUID_DISCONNECTED+# define STATUS_WMI_GUID_DISCONNECTED ((NTSTATUS) 0xC0000301L)+#endif++#ifndef STATUS_WMI_ALREADY_DISABLED+# define STATUS_WMI_ALREADY_DISABLED ((NTSTATUS) 0xC0000302L)+#endif++#ifndef STATUS_WMI_ALREADY_ENABLED+# define STATUS_WMI_ALREADY_ENABLED ((NTSTATUS) 0xC0000303L)+#endif++#ifndef STATUS_MFT_TOO_FRAGMENTED+# define STATUS_MFT_TOO_FRAGMENTED ((NTSTATUS) 0xC0000304L)+#endif++#ifndef STATUS_COPY_PROTECTION_FAILURE+# define STATUS_COPY_PROTECTION_FAILURE ((NTSTATUS) 0xC0000305L)+#endif++#ifndef STATUS_CSS_AUTHENTICATION_FAILURE+# define STATUS_CSS_AUTHENTICATION_FAILURE ((NTSTATUS) 0xC0000306L)+#endif++#ifndef STATUS_CSS_KEY_NOT_PRESENT+# define STATUS_CSS_KEY_NOT_PRESENT ((NTSTATUS) 0xC0000307L)+#endif++#ifndef STATUS_CSS_KEY_NOT_ESTABLISHED+# define STATUS_CSS_KEY_NOT_ESTABLISHED ((NTSTATUS) 0xC0000308L)+#endif++#ifndef STATUS_CSS_SCRAMBLED_SECTOR+# define STATUS_CSS_SCRAMBLED_SECTOR ((NTSTATUS) 0xC0000309L)+#endif++#ifndef STATUS_CSS_REGION_MISMATCH+# define STATUS_CSS_REGION_MISMATCH ((NTSTATUS) 0xC000030AL)+#endif++#ifndef STATUS_CSS_RESETS_EXHAUSTED+# define STATUS_CSS_RESETS_EXHAUSTED ((NTSTATUS) 0xC000030BL)+#endif++#ifndef STATUS_PKINIT_FAILURE+# define STATUS_PKINIT_FAILURE ((NTSTATUS) 0xC0000320L)+#endif++#ifndef STATUS_SMARTCARD_SUBSYSTEM_FAILURE+# define STATUS_SMARTCARD_SUBSYSTEM_FAILURE ((NTSTATUS) 0xC0000321L)+#endif++#ifndef STATUS_NO_KERB_KEY+# define STATUS_NO_KERB_KEY ((NTSTATUS) 0xC0000322L)+#endif++#ifndef STATUS_HOST_DOWN+# define STATUS_HOST_DOWN ((NTSTATUS) 0xC0000350L)+#endif++#ifndef STATUS_UNSUPPORTED_PREAUTH+# define STATUS_UNSUPPORTED_PREAUTH ((NTSTATUS) 0xC0000351L)+#endif++#ifndef STATUS_EFS_ALG_BLOB_TOO_BIG+# define STATUS_EFS_ALG_BLOB_TOO_BIG ((NTSTATUS) 0xC0000352L)+#endif++#ifndef STATUS_PORT_NOT_SET+# define STATUS_PORT_NOT_SET ((NTSTATUS) 0xC0000353L)+#endif++#ifndef STATUS_DEBUGGER_INACTIVE+# define STATUS_DEBUGGER_INACTIVE ((NTSTATUS) 0xC0000354L)+#endif++#ifndef STATUS_DS_VERSION_CHECK_FAILURE+# define STATUS_DS_VERSION_CHECK_FAILURE ((NTSTATUS) 0xC0000355L)+#endif++#ifndef STATUS_AUDITING_DISABLED+# define STATUS_AUDITING_DISABLED ((NTSTATUS) 0xC0000356L)+#endif++#ifndef STATUS_PRENT4_MACHINE_ACCOUNT+# define STATUS_PRENT4_MACHINE_ACCOUNT ((NTSTATUS) 0xC0000357L)+#endif++#ifndef STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER+# define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS) 0xC0000358L)+#endif++#ifndef STATUS_INVALID_IMAGE_WIN_32+# define STATUS_INVALID_IMAGE_WIN_32 ((NTSTATUS) 0xC0000359L)+#endif++#ifndef STATUS_INVALID_IMAGE_WIN_64+# define STATUS_INVALID_IMAGE_WIN_64 ((NTSTATUS) 0xC000035AL)+#endif++#ifndef STATUS_BAD_BINDINGS+# define STATUS_BAD_BINDINGS ((NTSTATUS) 0xC000035BL)+#endif++#ifndef STATUS_NETWORK_SESSION_EXPIRED+# define STATUS_NETWORK_SESSION_EXPIRED ((NTSTATUS) 0xC000035CL)+#endif++#ifndef STATUS_APPHELP_BLOCK+# define STATUS_APPHELP_BLOCK ((NTSTATUS) 0xC000035DL)+#endif++#ifndef STATUS_ALL_SIDS_FILTERED+# define STATUS_ALL_SIDS_FILTERED ((NTSTATUS) 0xC000035EL)+#endif++#ifndef STATUS_NOT_SAFE_MODE_DRIVER+# define STATUS_NOT_SAFE_MODE_DRIVER ((NTSTATUS) 0xC000035FL)+#endif++#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT+# define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT ((NTSTATUS) 0xC0000361L)+#endif++#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_PATH+# define STATUS_ACCESS_DISABLED_BY_POLICY_PATH ((NTSTATUS) 0xC0000362L)+#endif++#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER+# define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER ((NTSTATUS) 0xC0000363L)+#endif++#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_OTHER+# define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ((NTSTATUS) 0xC0000364L)+#endif++#ifndef STATUS_FAILED_DRIVER_ENTRY+# define STATUS_FAILED_DRIVER_ENTRY ((NTSTATUS) 0xC0000365L)+#endif++#ifndef STATUS_DEVICE_ENUMERATION_ERROR+# define STATUS_DEVICE_ENUMERATION_ERROR ((NTSTATUS) 0xC0000366L)+#endif++#ifndef STATUS_MOUNT_POINT_NOT_RESOLVED+# define STATUS_MOUNT_POINT_NOT_RESOLVED ((NTSTATUS) 0xC0000368L)+#endif++#ifndef STATUS_INVALID_DEVICE_OBJECT_PARAMETER+# define STATUS_INVALID_DEVICE_OBJECT_PARAMETER ((NTSTATUS) 0xC0000369L)+#endif++#ifndef STATUS_MCA_OCCURED+# define STATUS_MCA_OCCURED ((NTSTATUS) 0xC000036AL)+#endif++#ifndef STATUS_DRIVER_BLOCKED_CRITICAL+# define STATUS_DRIVER_BLOCKED_CRITICAL ((NTSTATUS) 0xC000036BL)+#endif++#ifndef STATUS_DRIVER_BLOCKED+# define STATUS_DRIVER_BLOCKED ((NTSTATUS) 0xC000036CL)+#endif++#ifndef STATUS_DRIVER_DATABASE_ERROR+# define STATUS_DRIVER_DATABASE_ERROR ((NTSTATUS) 0xC000036DL)+#endif++#ifndef STATUS_SYSTEM_HIVE_TOO_LARGE+# define STATUS_SYSTEM_HIVE_TOO_LARGE ((NTSTATUS) 0xC000036EL)+#endif++#ifndef STATUS_INVALID_IMPORT_OF_NON_DLL+# define STATUS_INVALID_IMPORT_OF_NON_DLL ((NTSTATUS) 0xC000036FL)+#endif++#ifndef STATUS_DS_SHUTTING_DOWN+# define STATUS_DS_SHUTTING_DOWN ((NTSTATUS) 0x40000370L)+#endif++#ifndef STATUS_NO_SECRETS+# define STATUS_NO_SECRETS ((NTSTATUS) 0xC0000371L)+#endif++#ifndef STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY+# define STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY ((NTSTATUS) 0xC0000372L)+#endif++#ifndef STATUS_FAILED_STACK_SWITCH+# define STATUS_FAILED_STACK_SWITCH ((NTSTATUS) 0xC0000373L)+#endif++#ifndef STATUS_HEAP_CORRUPTION+# define STATUS_HEAP_CORRUPTION ((NTSTATUS) 0xC0000374L)+#endif++#ifndef STATUS_SMARTCARD_WRONG_PIN+# define STATUS_SMARTCARD_WRONG_PIN ((NTSTATUS) 0xC0000380L)+#endif++#ifndef STATUS_SMARTCARD_CARD_BLOCKED+# define STATUS_SMARTCARD_CARD_BLOCKED ((NTSTATUS) 0xC0000381L)+#endif++#ifndef STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED+# define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED ((NTSTATUS) 0xC0000382L)+#endif++#ifndef STATUS_SMARTCARD_NO_CARD+# define STATUS_SMARTCARD_NO_CARD ((NTSTATUS) 0xC0000383L)+#endif++#ifndef STATUS_SMARTCARD_NO_KEY_CONTAINER+# define STATUS_SMARTCARD_NO_KEY_CONTAINER ((NTSTATUS) 0xC0000384L)+#endif++#ifndef STATUS_SMARTCARD_NO_CERTIFICATE+# define STATUS_SMARTCARD_NO_CERTIFICATE ((NTSTATUS) 0xC0000385L)+#endif++#ifndef STATUS_SMARTCARD_NO_KEYSET+# define STATUS_SMARTCARD_NO_KEYSET ((NTSTATUS) 0xC0000386L)+#endif++#ifndef STATUS_SMARTCARD_IO_ERROR+# define STATUS_SMARTCARD_IO_ERROR ((NTSTATUS) 0xC0000387L)+#endif++#ifndef STATUS_DOWNGRADE_DETECTED+# define STATUS_DOWNGRADE_DETECTED ((NTSTATUS) 0xC0000388L)+#endif++#ifndef STATUS_SMARTCARD_CERT_REVOKED+# define STATUS_SMARTCARD_CERT_REVOKED ((NTSTATUS) 0xC0000389L)+#endif++#ifndef STATUS_ISSUING_CA_UNTRUSTED+# define STATUS_ISSUING_CA_UNTRUSTED ((NTSTATUS) 0xC000038AL)+#endif++#ifndef STATUS_REVOCATION_OFFLINE_C+# define STATUS_REVOCATION_OFFLINE_C ((NTSTATUS) 0xC000038BL)+#endif++#ifndef STATUS_PKINIT_CLIENT_FAILURE+# define STATUS_PKINIT_CLIENT_FAILURE ((NTSTATUS) 0xC000038CL)+#endif++#ifndef STATUS_SMARTCARD_CERT_EXPIRED+# define STATUS_SMARTCARD_CERT_EXPIRED ((NTSTATUS) 0xC000038DL)+#endif++#ifndef STATUS_DRIVER_FAILED_PRIOR_UNLOAD+# define STATUS_DRIVER_FAILED_PRIOR_UNLOAD ((NTSTATUS) 0xC000038EL)+#endif++#ifndef STATUS_SMARTCARD_SILENT_CONTEXT+# define STATUS_SMARTCARD_SILENT_CONTEXT ((NTSTATUS) 0xC000038FL)+#endif++#ifndef STATUS_PER_USER_TRUST_QUOTA_EXCEEDED+# define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000401L)+#endif++#ifndef STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED+# define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000402L)+#endif++#ifndef STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED+# define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000403L)+#endif++#ifndef STATUS_DS_NAME_NOT_UNIQUE+# define STATUS_DS_NAME_NOT_UNIQUE ((NTSTATUS) 0xC0000404L)+#endif++#ifndef STATUS_DS_DUPLICATE_ID_FOUND+# define STATUS_DS_DUPLICATE_ID_FOUND ((NTSTATUS) 0xC0000405L)+#endif++#ifndef STATUS_DS_GROUP_CONVERSION_ERROR+# define STATUS_DS_GROUP_CONVERSION_ERROR ((NTSTATUS) 0xC0000406L)+#endif++#ifndef STATUS_VOLSNAP_PREPARE_HIBERNATE+# define STATUS_VOLSNAP_PREPARE_HIBERNATE ((NTSTATUS) 0xC0000407L)+#endif++#ifndef STATUS_USER2USER_REQUIRED+# define STATUS_USER2USER_REQUIRED ((NTSTATUS) 0xC0000408L)+#endif++#ifndef STATUS_STACK_BUFFER_OVERRUN+# define STATUS_STACK_BUFFER_OVERRUN ((NTSTATUS) 0xC0000409L)+#endif++#ifndef STATUS_NO_S4U_PROT_SUPPORT+# define STATUS_NO_S4U_PROT_SUPPORT ((NTSTATUS) 0xC000040AL)+#endif++#ifndef STATUS_CROSSREALM_DELEGATION_FAILURE+# define STATUS_CROSSREALM_DELEGATION_FAILURE ((NTSTATUS) 0xC000040BL)+#endif++#ifndef STATUS_REVOCATION_OFFLINE_KDC+# define STATUS_REVOCATION_OFFLINE_KDC ((NTSTATUS) 0xC000040CL)+#endif++#ifndef STATUS_ISSUING_CA_UNTRUSTED_KDC+# define STATUS_ISSUING_CA_UNTRUSTED_KDC ((NTSTATUS) 0xC000040DL)+#endif++#ifndef STATUS_KDC_CERT_EXPIRED+# define STATUS_KDC_CERT_EXPIRED ((NTSTATUS) 0xC000040EL)+#endif++#ifndef STATUS_KDC_CERT_REVOKED+# define STATUS_KDC_CERT_REVOKED ((NTSTATUS) 0xC000040FL)+#endif++#ifndef STATUS_PARAMETER_QUOTA_EXCEEDED+# define STATUS_PARAMETER_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000410L)+#endif++#ifndef STATUS_HIBERNATION_FAILURE+# define STATUS_HIBERNATION_FAILURE ((NTSTATUS) 0xC0000411L)+#endif++#ifndef STATUS_DELAY_LOAD_FAILED+# define STATUS_DELAY_LOAD_FAILED ((NTSTATUS) 0xC0000412L)+#endif++#ifndef STATUS_AUTHENTICATION_FIREWALL_FAILED+# define STATUS_AUTHENTICATION_FIREWALL_FAILED ((NTSTATUS) 0xC0000413L)+#endif++#ifndef STATUS_VDM_DISALLOWED+# define STATUS_VDM_DISALLOWED ((NTSTATUS) 0xC0000414L)+#endif++#ifndef STATUS_HUNG_DISPLAY_DRIVER_THREAD+# define STATUS_HUNG_DISPLAY_DRIVER_THREAD ((NTSTATUS) 0xC0000415L)+#endif++#ifndef STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE+# define STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE ((NTSTATUS) 0xC0000416L)+#endif++#ifndef STATUS_INVALID_CRUNTIME_PARAMETER+# define STATUS_INVALID_CRUNTIME_PARAMETER ((NTSTATUS) 0xC0000417L)+#endif++#ifndef STATUS_NTLM_BLOCKED+# define STATUS_NTLM_BLOCKED ((NTSTATUS) 0xC0000418L)+#endif++#ifndef STATUS_DS_SRC_SID_EXISTS_IN_FOREST+# define STATUS_DS_SRC_SID_EXISTS_IN_FOREST ((NTSTATUS) 0xC0000419L)+#endif++#ifndef STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST+# define STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST ((NTSTATUS) 0xC000041AL)+#endif++#ifndef STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST+# define STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST ((NTSTATUS) 0xC000041BL)+#endif++#ifndef STATUS_INVALID_USER_PRINCIPAL_NAME+# define STATUS_INVALID_USER_PRINCIPAL_NAME ((NTSTATUS) 0xC000041CL)+#endif++#ifndef STATUS_FATAL_USER_CALLBACK_EXCEPTION+# define STATUS_FATAL_USER_CALLBACK_EXCEPTION ((NTSTATUS) 0xC000041DL)+#endif++#ifndef STATUS_ASSERTION_FAILURE+# define STATUS_ASSERTION_FAILURE ((NTSTATUS) 0xC0000420L)+#endif++#ifndef STATUS_VERIFIER_STOP+# define STATUS_VERIFIER_STOP ((NTSTATUS) 0xC0000421L)+#endif++#ifndef STATUS_CALLBACK_POP_STACK+# define STATUS_CALLBACK_POP_STACK ((NTSTATUS) 0xC0000423L)+#endif++#ifndef STATUS_INCOMPATIBLE_DRIVER_BLOCKED+# define STATUS_INCOMPATIBLE_DRIVER_BLOCKED ((NTSTATUS) 0xC0000424L)+#endif++#ifndef STATUS_HIVE_UNLOADED+# define STATUS_HIVE_UNLOADED ((NTSTATUS) 0xC0000425L)+#endif++#ifndef STATUS_COMPRESSION_DISABLED+# define STATUS_COMPRESSION_DISABLED ((NTSTATUS) 0xC0000426L)+#endif++#ifndef STATUS_FILE_SYSTEM_LIMITATION+# define STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS) 0xC0000427L)+#endif++#ifndef STATUS_INVALID_IMAGE_HASH+# define STATUS_INVALID_IMAGE_HASH ((NTSTATUS) 0xC0000428L)+#endif++#ifndef STATUS_NOT_CAPABLE+# define STATUS_NOT_CAPABLE ((NTSTATUS) 0xC0000429L)+#endif++#ifndef STATUS_REQUEST_OUT_OF_SEQUENCE+# define STATUS_REQUEST_OUT_OF_SEQUENCE ((NTSTATUS) 0xC000042AL)+#endif++#ifndef STATUS_IMPLEMENTATION_LIMIT+# define STATUS_IMPLEMENTATION_LIMIT ((NTSTATUS) 0xC000042BL)+#endif++#ifndef STATUS_ELEVATION_REQUIRED+# define STATUS_ELEVATION_REQUIRED ((NTSTATUS) 0xC000042CL)+#endif++#ifndef STATUS_NO_SECURITY_CONTEXT+# define STATUS_NO_SECURITY_CONTEXT ((NTSTATUS) 0xC000042DL)+#endif++#ifndef STATUS_PKU2U_CERT_FAILURE+# define STATUS_PKU2U_CERT_FAILURE ((NTSTATUS) 0xC000042FL)+#endif++#ifndef STATUS_BEYOND_VDL+# define STATUS_BEYOND_VDL ((NTSTATUS) 0xC0000432L)+#endif++#ifndef STATUS_ENCOUNTERED_WRITE_IN_PROGRESS+# define STATUS_ENCOUNTERED_WRITE_IN_PROGRESS ((NTSTATUS) 0xC0000433L)+#endif++#ifndef STATUS_PTE_CHANGED+# define STATUS_PTE_CHANGED ((NTSTATUS) 0xC0000434L)+#endif++#ifndef STATUS_PURGE_FAILED+# define STATUS_PURGE_FAILED ((NTSTATUS) 0xC0000435L)+#endif++#ifndef STATUS_CRED_REQUIRES_CONFIRMATION+# define STATUS_CRED_REQUIRES_CONFIRMATION ((NTSTATUS) 0xC0000440L)+#endif++#ifndef STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE+# define STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE ((NTSTATUS) 0xC0000441L)+#endif++#ifndef STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER+# define STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER ((NTSTATUS) 0xC0000442L)+#endif++#ifndef STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE+# define STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE ((NTSTATUS) 0xC0000443L)+#endif++#ifndef STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE+# define STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE ((NTSTATUS) 0xC0000444L)+#endif++#ifndef STATUS_CS_ENCRYPTION_FILE_NOT_CSE+# define STATUS_CS_ENCRYPTION_FILE_NOT_CSE ((NTSTATUS) 0xC0000445L)+#endif++#ifndef STATUS_INVALID_LABEL+# define STATUS_INVALID_LABEL ((NTSTATUS) 0xC0000446L)+#endif++#ifndef STATUS_DRIVER_PROCESS_TERMINATED+# define STATUS_DRIVER_PROCESS_TERMINATED ((NTSTATUS) 0xC0000450L)+#endif++#ifndef STATUS_AMBIGUOUS_SYSTEM_DEVICE+# define STATUS_AMBIGUOUS_SYSTEM_DEVICE ((NTSTATUS) 0xC0000451L)+#endif++#ifndef STATUS_SYSTEM_DEVICE_NOT_FOUND+# define STATUS_SYSTEM_DEVICE_NOT_FOUND ((NTSTATUS) 0xC0000452L)+#endif++#ifndef STATUS_RESTART_BOOT_APPLICATION+# define STATUS_RESTART_BOOT_APPLICATION ((NTSTATUS) 0xC0000453L)+#endif++#ifndef STATUS_INSUFFICIENT_NVRAM_RESOURCES+# define STATUS_INSUFFICIENT_NVRAM_RESOURCES ((NTSTATUS) 0xC0000454L)+#endif++#ifndef STATUS_INVALID_TASK_NAME+# define STATUS_INVALID_TASK_NAME ((NTSTATUS) 0xC0000500L)+#endif++#ifndef STATUS_INVALID_TASK_INDEX+# define STATUS_INVALID_TASK_INDEX ((NTSTATUS) 0xC0000501L)+#endif++#ifndef STATUS_THREAD_ALREADY_IN_TASK+# define STATUS_THREAD_ALREADY_IN_TASK ((NTSTATUS) 0xC0000502L)+#endif++#ifndef STATUS_CALLBACK_BYPASS+# define STATUS_CALLBACK_BYPASS ((NTSTATUS) 0xC0000503L)+#endif++#ifndef STATUS_FAIL_FAST_EXCEPTION+# define STATUS_FAIL_FAST_EXCEPTION ((NTSTATUS) 0xC0000602L)+#endif++#ifndef STATUS_IMAGE_CERT_REVOKED+# define STATUS_IMAGE_CERT_REVOKED ((NTSTATUS) 0xC0000603L)+#endif++#ifndef STATUS_PORT_CLOSED+# define STATUS_PORT_CLOSED ((NTSTATUS) 0xC0000700L)+#endif++#ifndef STATUS_MESSAGE_LOST+# define STATUS_MESSAGE_LOST ((NTSTATUS) 0xC0000701L)+#endif++#ifndef STATUS_INVALID_MESSAGE+# define STATUS_INVALID_MESSAGE ((NTSTATUS) 0xC0000702L)+#endif++#ifndef STATUS_REQUEST_CANCELED+# define STATUS_REQUEST_CANCELED ((NTSTATUS) 0xC0000703L)+#endif++#ifndef STATUS_RECURSIVE_DISPATCH+# define STATUS_RECURSIVE_DISPATCH ((NTSTATUS) 0xC0000704L)+#endif++#ifndef STATUS_LPC_RECEIVE_BUFFER_EXPECTED+# define STATUS_LPC_RECEIVE_BUFFER_EXPECTED ((NTSTATUS) 0xC0000705L)+#endif++#ifndef STATUS_LPC_INVALID_CONNECTION_USAGE+# define STATUS_LPC_INVALID_CONNECTION_USAGE ((NTSTATUS) 0xC0000706L)+#endif++#ifndef STATUS_LPC_REQUESTS_NOT_ALLOWED+# define STATUS_LPC_REQUESTS_NOT_ALLOWED ((NTSTATUS) 0xC0000707L)+#endif++#ifndef STATUS_RESOURCE_IN_USE+# define STATUS_RESOURCE_IN_USE ((NTSTATUS) 0xC0000708L)+#endif++#ifndef STATUS_HARDWARE_MEMORY_ERROR+# define STATUS_HARDWARE_MEMORY_ERROR ((NTSTATUS) 0xC0000709L)+#endif++#ifndef STATUS_THREADPOOL_HANDLE_EXCEPTION+# define STATUS_THREADPOOL_HANDLE_EXCEPTION ((NTSTATUS) 0xC000070AL)+#endif++#ifndef STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED+# define STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070BL)+#endif++#ifndef STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED+# define STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070CL)+#endif++#ifndef STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED+# define STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070DL)+#endif++#ifndef STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED+# define STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070EL)+#endif++#ifndef STATUS_THREADPOOL_RELEASED_DURING_OPERATION+# define STATUS_THREADPOOL_RELEASED_DURING_OPERATION ((NTSTATUS) 0xC000070FL)+#endif++#ifndef STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING+# define STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING ((NTSTATUS) 0xC0000710L)+#endif++#ifndef STATUS_APC_RETURNED_WHILE_IMPERSONATING+# define STATUS_APC_RETURNED_WHILE_IMPERSONATING ((NTSTATUS) 0xC0000711L)+#endif++#ifndef STATUS_PROCESS_IS_PROTECTED+# define STATUS_PROCESS_IS_PROTECTED ((NTSTATUS) 0xC0000712L)+#endif++#ifndef STATUS_MCA_EXCEPTION+# define STATUS_MCA_EXCEPTION ((NTSTATUS) 0xC0000713L)+#endif++#ifndef STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE+# define STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE ((NTSTATUS) 0xC0000714L)+#endif++#ifndef STATUS_SYMLINK_CLASS_DISABLED+# define STATUS_SYMLINK_CLASS_DISABLED ((NTSTATUS) 0xC0000715L)+#endif++#ifndef STATUS_INVALID_IDN_NORMALIZATION+# define STATUS_INVALID_IDN_NORMALIZATION ((NTSTATUS) 0xC0000716L)+#endif++#ifndef STATUS_NO_UNICODE_TRANSLATION+# define STATUS_NO_UNICODE_TRANSLATION ((NTSTATUS) 0xC0000717L)+#endif++#ifndef STATUS_ALREADY_REGISTERED+# define STATUS_ALREADY_REGISTERED ((NTSTATUS) 0xC0000718L)+#endif++#ifndef STATUS_CONTEXT_MISMATCH+# define STATUS_CONTEXT_MISMATCH ((NTSTATUS) 0xC0000719L)+#endif++#ifndef STATUS_PORT_ALREADY_HAS_COMPLETION_LIST+# define STATUS_PORT_ALREADY_HAS_COMPLETION_LIST ((NTSTATUS) 0xC000071AL)+#endif++#ifndef STATUS_CALLBACK_RETURNED_THREAD_PRIORITY+# define STATUS_CALLBACK_RETURNED_THREAD_PRIORITY ((NTSTATUS) 0xC000071BL)+#endif++#ifndef STATUS_INVALID_THREAD+# define STATUS_INVALID_THREAD ((NTSTATUS) 0xC000071CL)+#endif++#ifndef STATUS_CALLBACK_RETURNED_TRANSACTION+# define STATUS_CALLBACK_RETURNED_TRANSACTION ((NTSTATUS) 0xC000071DL)+#endif++#ifndef STATUS_CALLBACK_RETURNED_LDR_LOCK+# define STATUS_CALLBACK_RETURNED_LDR_LOCK ((NTSTATUS) 0xC000071EL)+#endif++#ifndef STATUS_CALLBACK_RETURNED_LANG+# define STATUS_CALLBACK_RETURNED_LANG ((NTSTATUS) 0xC000071FL)+#endif++#ifndef STATUS_CALLBACK_RETURNED_PRI_BACK+# define STATUS_CALLBACK_RETURNED_PRI_BACK ((NTSTATUS) 0xC0000720L)+#endif++#ifndef STATUS_CALLBACK_RETURNED_THREAD_AFFINITY+# define STATUS_CALLBACK_RETURNED_THREAD_AFFINITY ((NTSTATUS) 0xC0000721L)+#endif++#ifndef STATUS_DISK_REPAIR_DISABLED+# define STATUS_DISK_REPAIR_DISABLED ((NTSTATUS) 0xC0000800L)+#endif++#ifndef STATUS_DS_DOMAIN_RENAME_IN_PROGRESS+# define STATUS_DS_DOMAIN_RENAME_IN_PROGRESS ((NTSTATUS) 0xC0000801L)+#endif++#ifndef STATUS_DISK_QUOTA_EXCEEDED+# define STATUS_DISK_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000802L)+#endif++#ifndef STATUS_DATA_LOST_REPAIR+# define STATUS_DATA_LOST_REPAIR ((NTSTATUS) 0x80000803L)+#endif++#ifndef STATUS_CONTENT_BLOCKED+# define STATUS_CONTENT_BLOCKED ((NTSTATUS) 0xC0000804L)+#endif++#ifndef STATUS_BAD_CLUSTERS+# define STATUS_BAD_CLUSTERS ((NTSTATUS) 0xC0000805L)+#endif++#ifndef STATUS_VOLUME_DIRTY+# define STATUS_VOLUME_DIRTY ((NTSTATUS) 0xC0000806L)+#endif++#ifndef STATUS_FILE_CHECKED_OUT+# define STATUS_FILE_CHECKED_OUT ((NTSTATUS) 0xC0000901L)+#endif++#ifndef STATUS_CHECKOUT_REQUIRED+# define STATUS_CHECKOUT_REQUIRED ((NTSTATUS) 0xC0000902L)+#endif++#ifndef STATUS_BAD_FILE_TYPE+# define STATUS_BAD_FILE_TYPE ((NTSTATUS) 0xC0000903L)+#endif++#ifndef STATUS_FILE_TOO_LARGE+# define STATUS_FILE_TOO_LARGE ((NTSTATUS) 0xC0000904L)+#endif++#ifndef STATUS_FORMS_AUTH_REQUIRED+# define STATUS_FORMS_AUTH_REQUIRED ((NTSTATUS) 0xC0000905L)+#endif++#ifndef STATUS_VIRUS_INFECTED+# define STATUS_VIRUS_INFECTED ((NTSTATUS) 0xC0000906L)+#endif++#ifndef STATUS_VIRUS_DELETED+# define STATUS_VIRUS_DELETED ((NTSTATUS) 0xC0000907L)+#endif++#ifndef STATUS_BAD_MCFG_TABLE+# define STATUS_BAD_MCFG_TABLE ((NTSTATUS) 0xC0000908L)+#endif++#ifndef STATUS_CANNOT_BREAK_OPLOCK+# define STATUS_CANNOT_BREAK_OPLOCK ((NTSTATUS) 0xC0000909L)+#endif++#ifndef STATUS_WOW_ASSERTION+# define STATUS_WOW_ASSERTION ((NTSTATUS) 0xC0009898L)+#endif++#ifndef STATUS_INVALID_SIGNATURE+# define STATUS_INVALID_SIGNATURE ((NTSTATUS) 0xC000A000L)+#endif++#ifndef STATUS_HMAC_NOT_SUPPORTED+# define STATUS_HMAC_NOT_SUPPORTED ((NTSTATUS) 0xC000A001L)+#endif++#ifndef STATUS_AUTH_TAG_MISMATCH+# define STATUS_AUTH_TAG_MISMATCH ((NTSTATUS) 0xC000A002L)+#endif++#ifndef STATUS_IPSEC_QUEUE_OVERFLOW+# define STATUS_IPSEC_QUEUE_OVERFLOW ((NTSTATUS) 0xC000A010L)+#endif++#ifndef STATUS_ND_QUEUE_OVERFLOW+# define STATUS_ND_QUEUE_OVERFLOW ((NTSTATUS) 0xC000A011L)+#endif++#ifndef STATUS_HOPLIMIT_EXCEEDED+# define STATUS_HOPLIMIT_EXCEEDED ((NTSTATUS) 0xC000A012L)+#endif++#ifndef STATUS_PROTOCOL_NOT_SUPPORTED+# define STATUS_PROTOCOL_NOT_SUPPORTED ((NTSTATUS) 0xC000A013L)+#endif++#ifndef STATUS_FASTPATH_REJECTED+# define STATUS_FASTPATH_REJECTED ((NTSTATUS) 0xC000A014L)+#endif++#ifndef STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED+# define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED ((NTSTATUS) 0xC000A080L)+#endif++#ifndef STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR+# define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR ((NTSTATUS) 0xC000A081L)+#endif++#ifndef STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR+# define STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR ((NTSTATUS) 0xC000A082L)+#endif++#ifndef STATUS_XML_PARSE_ERROR+# define STATUS_XML_PARSE_ERROR ((NTSTATUS) 0xC000A083L)+#endif++#ifndef STATUS_XMLDSIG_ERROR+# define STATUS_XMLDSIG_ERROR ((NTSTATUS) 0xC000A084L)+#endif++#ifndef STATUS_WRONG_COMPARTMENT+# define STATUS_WRONG_COMPARTMENT ((NTSTATUS) 0xC000A085L)+#endif++#ifndef STATUS_AUTHIP_FAILURE+# define STATUS_AUTHIP_FAILURE ((NTSTATUS) 0xC000A086L)+#endif++#ifndef STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS+# define STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS ((NTSTATUS) 0xC000A087L)+#endif++#ifndef STATUS_DS_OID_NOT_FOUND+# define STATUS_DS_OID_NOT_FOUND ((NTSTATUS) 0xC000A088L)+#endif++#ifndef STATUS_HASH_NOT_SUPPORTED+# define STATUS_HASH_NOT_SUPPORTED ((NTSTATUS) 0xC000A100L)+#endif++#ifndef STATUS_HASH_NOT_PRESENT+# define STATUS_HASH_NOT_PRESENT ((NTSTATUS) 0xC000A101L)+#endif++/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the DDK+ * got it wrong! */+#ifdef NTSTATUS_FROM_WIN32+# undef NTSTATUS_FROM_WIN32+#endif+#define NTSTATUS_FROM_WIN32(error) ((NTSTATUS) (error) <= 0 ? \+        ((NTSTATUS) (error)) : ((NTSTATUS) (((error) & 0x0000FFFF) | \+        (FACILITY_NTWIN32 << 16) | ERROR_SEVERITY_WARNING)))++#ifndef JOB_OBJECT_LIMIT_PROCESS_MEMORY+# define JOB_OBJECT_LIMIT_PROCESS_MEMORY             0x00000100+#endif+#ifndef JOB_OBJECT_LIMIT_JOB_MEMORY+# define JOB_OBJECT_LIMIT_JOB_MEMORY                 0x00000200+#endif+#ifndef JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION+# define JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION 0x00000400+#endif+#ifndef JOB_OBJECT_LIMIT_BREAKAWAY_OK+# define JOB_OBJECT_LIMIT_BREAKAWAY_OK               0x00000800+#endif+#ifndef JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK+# define JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK        0x00001000+#endif+#ifndef JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE+# define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE          0x00002000+#endif++#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE+# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x00000002+#endif++/* from winternl.h */+#if !defined(__UNICODE_STRING_DEFINED) && defined(__MINGW32_)+#define __UNICODE_STRING_DEFINED+#endif+typedef struct _UNICODE_STRING {+  USHORT Length;+  USHORT MaximumLength;+  PWSTR  Buffer;+} UNICODE_STRING, *PUNICODE_STRING;++typedef const UNICODE_STRING *PCUNICODE_STRING;++/* from ntifs.h */+#ifndef DEVICE_TYPE+# define DEVICE_TYPE DWORD+#endif++/* MinGW already has a definition for REPARSE_DATA_BUFFER, but mingw-w64 does+ * not.+ */+#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)+  typedef struct _REPARSE_DATA_BUFFER {+    ULONG  ReparseTag;+    USHORT ReparseDataLength;+    USHORT Reserved;+    union {+      struct {+        USHORT SubstituteNameOffset;+        USHORT SubstituteNameLength;+        USHORT PrintNameOffset;+        USHORT PrintNameLength;+        ULONG Flags;+        WCHAR PathBuffer[1];+      } SymbolicLinkReparseBuffer;+      struct {+        USHORT SubstituteNameOffset;+        USHORT SubstituteNameLength;+        USHORT PrintNameOffset;+        USHORT PrintNameLength;+        WCHAR PathBuffer[1];+      } MountPointReparseBuffer;+      struct {+        UCHAR  DataBuffer[1];+      } GenericReparseBuffer;+    };+  } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;+#endif++typedef struct _IO_STATUS_BLOCK {+  union {+    NTSTATUS Status;+    PVOID Pointer;+  };+  ULONG_PTR Information;+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;++typedef enum _FILE_INFORMATION_CLASS {+  FileDirectoryInformation = 1,+  FileFullDirectoryInformation,+  FileBothDirectoryInformation,+  FileBasicInformation,+  FileStandardInformation,+  FileInternalInformation,+  FileEaInformation,+  FileAccessInformation,+  FileNameInformation,+  FileRenameInformation,+  FileLinkInformation,+  FileNamesInformation,+  FileDispositionInformation,+  FilePositionInformation,+  FileFullEaInformation,+  FileModeInformation,+  FileAlignmentInformation,+  FileAllInformation,+  FileAllocationInformation,+  FileEndOfFileInformation,+  FileAlternateNameInformation,+  FileStreamInformation,+  FilePipeInformation,+  FilePipeLocalInformation,+  FilePipeRemoteInformation,+  FileMailslotQueryInformation,+  FileMailslotSetInformation,+  FileCompressionInformation,+  FileObjectIdInformation,+  FileCompletionInformation,+  FileMoveClusterInformation,+  FileQuotaInformation,+  FileReparsePointInformation,+  FileNetworkOpenInformation,+  FileAttributeTagInformation,+  FileTrackingInformation,+  FileIdBothDirectoryInformation,+  FileIdFullDirectoryInformation,+  FileValidDataLengthInformation,+  FileShortNameInformation,+  FileIoCompletionNotificationInformation,+  FileIoStatusBlockRangeInformation,+  FileIoPriorityHintInformation,+  FileSfioReserveInformation,+  FileSfioVolumeInformation,+  FileHardLinkInformation,+  FileProcessIdsUsingFileInformation,+  FileNormalizedNameInformation,+  FileNetworkPhysicalNameInformation,+  FileIdGlobalTxDirectoryInformation,+  FileIsRemoteDeviceInformation,+  FileAttributeCacheInformation,+  FileNumaNodeInformation,+  FileStandardLinkInformation,+  FileRemoteProtocolInformation,+  FileMaximumInformation+} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;++typedef struct _FILE_DIRECTORY_INFORMATION {+  ULONG NextEntryOffset;+  ULONG FileIndex;+  LARGE_INTEGER CreationTime;+  LARGE_INTEGER LastAccessTime;+  LARGE_INTEGER LastWriteTime;+  LARGE_INTEGER ChangeTime;+  LARGE_INTEGER EndOfFile;+  LARGE_INTEGER AllocationSize;+  ULONG FileAttributes;+  ULONG FileNameLength;+  WCHAR FileName[1];+} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;++typedef struct _FILE_BOTH_DIR_INFORMATION {+  ULONG NextEntryOffset;+  ULONG FileIndex;+  LARGE_INTEGER CreationTime;+  LARGE_INTEGER LastAccessTime;+  LARGE_INTEGER LastWriteTime;+  LARGE_INTEGER ChangeTime;+  LARGE_INTEGER EndOfFile;+  LARGE_INTEGER AllocationSize;+  ULONG FileAttributes;+  ULONG FileNameLength;+  ULONG EaSize;+  CCHAR ShortNameLength;+  WCHAR ShortName[12];+  WCHAR FileName[1];+} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;++typedef struct _FILE_BASIC_INFORMATION {+  LARGE_INTEGER CreationTime;+  LARGE_INTEGER LastAccessTime;+  LARGE_INTEGER LastWriteTime;+  LARGE_INTEGER ChangeTime;+  DWORD FileAttributes;+} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;++typedef struct _FILE_STANDARD_INFORMATION {+  LARGE_INTEGER AllocationSize;+  LARGE_INTEGER EndOfFile;+  ULONG         NumberOfLinks;+  BOOLEAN       DeletePending;+  BOOLEAN       Directory;+} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;++typedef struct _FILE_INTERNAL_INFORMATION {+  LARGE_INTEGER IndexNumber;+} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;++typedef struct _FILE_EA_INFORMATION {+  ULONG EaSize;+} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;++typedef struct _FILE_ACCESS_INFORMATION {+  ACCESS_MASK AccessFlags;+} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;++typedef struct _FILE_POSITION_INFORMATION {+  LARGE_INTEGER CurrentByteOffset;+} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;++typedef struct _FILE_MODE_INFORMATION {+  ULONG Mode;+} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;++typedef struct _FILE_ALIGNMENT_INFORMATION {+  ULONG AlignmentRequirement;+} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION;++typedef struct _FILE_NAME_INFORMATION {+  ULONG FileNameLength;+  WCHAR FileName[1];+} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;++typedef struct _FILE_END_OF_FILE_INFORMATION {+  LARGE_INTEGER  EndOfFile;+} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION;++typedef struct _FILE_ALL_INFORMATION {+  FILE_BASIC_INFORMATION     BasicInformation;+  FILE_STANDARD_INFORMATION  StandardInformation;+  FILE_INTERNAL_INFORMATION  InternalInformation;+  FILE_EA_INFORMATION        EaInformation;+  FILE_ACCESS_INFORMATION    AccessInformation;+  FILE_POSITION_INFORMATION  PositionInformation;+  FILE_MODE_INFORMATION      ModeInformation;+  FILE_ALIGNMENT_INFORMATION AlignmentInformation;+  FILE_NAME_INFORMATION      NameInformation;+} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;++typedef struct _FILE_DISPOSITION_INFORMATION {+  BOOLEAN DeleteFile;+} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION;++typedef struct _FILE_PIPE_LOCAL_INFORMATION {+  ULONG NamedPipeType;+  ULONG NamedPipeConfiguration;+  ULONG MaximumInstances;+  ULONG CurrentInstances;+  ULONG InboundQuota;+  ULONG ReadDataAvailable;+  ULONG OutboundQuota;+  ULONG WriteQuotaAvailable;+  ULONG NamedPipeState;+  ULONG NamedPipeEnd;+} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;++#define FILE_SYNCHRONOUS_IO_ALERT               0x00000010+#define FILE_SYNCHRONOUS_IO_NONALERT            0x00000020++typedef enum _FS_INFORMATION_CLASS {+  FileFsVolumeInformation       = 1,+  FileFsLabelInformation        = 2,+  FileFsSizeInformation         = 3,+  FileFsDeviceInformation       = 4,+  FileFsAttributeInformation    = 5,+  FileFsControlInformation      = 6,+  FileFsFullSizeInformation     = 7,+  FileFsObjectIdInformation     = 8,+  FileFsDriverPathInformation   = 9,+  FileFsVolumeFlagsInformation  = 10,+  FileFsSectorSizeInformation   = 11+} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;++typedef struct _FILE_FS_VOLUME_INFORMATION {+  LARGE_INTEGER VolumeCreationTime;+  ULONG         VolumeSerialNumber;+  ULONG         VolumeLabelLength;+  BOOLEAN       SupportsObjects;+  WCHAR         VolumeLabel[1];+} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION;++typedef struct _FILE_FS_LABEL_INFORMATION {+  ULONG VolumeLabelLength;+  WCHAR VolumeLabel[1];+} FILE_FS_LABEL_INFORMATION, *PFILE_FS_LABEL_INFORMATION;++typedef struct _FILE_FS_SIZE_INFORMATION {+  LARGE_INTEGER TotalAllocationUnits;+  LARGE_INTEGER AvailableAllocationUnits;+  ULONG         SectorsPerAllocationUnit;+  ULONG         BytesPerSector;+} FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION;++typedef struct _FILE_FS_DEVICE_INFORMATION {+  DEVICE_TYPE DeviceType;+  ULONG       Characteristics;+} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION;++typedef struct _FILE_FS_ATTRIBUTE_INFORMATION {+  ULONG FileSystemAttributes;+  LONG  MaximumComponentNameLength;+  ULONG FileSystemNameLength;+  WCHAR FileSystemName[1];+} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;++typedef struct _FILE_FS_CONTROL_INFORMATION {+  LARGE_INTEGER FreeSpaceStartFiltering;+  LARGE_INTEGER FreeSpaceThreshold;+  LARGE_INTEGER FreeSpaceStopFiltering;+  LARGE_INTEGER DefaultQuotaThreshold;+  LARGE_INTEGER DefaultQuotaLimit;+  ULONG         FileSystemControlFlags;+} FILE_FS_CONTROL_INFORMATION, *PFILE_FS_CONTROL_INFORMATION;++typedef struct _FILE_FS_FULL_SIZE_INFORMATION {+  LARGE_INTEGER TotalAllocationUnits;+  LARGE_INTEGER CallerAvailableAllocationUnits;+  LARGE_INTEGER ActualAvailableAllocationUnits;+  ULONG         SectorsPerAllocationUnit;+  ULONG         BytesPerSector;+} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;++typedef struct _FILE_FS_OBJECTID_INFORMATION {+  UCHAR ObjectId[16];+  UCHAR ExtendedInfo[48];+} FILE_FS_OBJECTID_INFORMATION, *PFILE_FS_OBJECTID_INFORMATION;++typedef struct _FILE_FS_DRIVER_PATH_INFORMATION {+  BOOLEAN DriverInPath;+  ULONG   DriverNameLength;+  WCHAR   DriverName[1];+} FILE_FS_DRIVER_PATH_INFORMATION, *PFILE_FS_DRIVER_PATH_INFORMATION;++typedef struct _FILE_FS_VOLUME_FLAGS_INFORMATION {+  ULONG Flags;+} FILE_FS_VOLUME_FLAGS_INFORMATION, *PFILE_FS_VOLUME_FLAGS_INFORMATION;++typedef struct _FILE_FS_SECTOR_SIZE_INFORMATION {+  ULONG LogicalBytesPerSector;+  ULONG PhysicalBytesPerSectorForAtomicity;+  ULONG PhysicalBytesPerSectorForPerformance;+  ULONG FileSystemEffectivePhysicalBytesPerSectorForAtomicity;+  ULONG Flags;+  ULONG ByteOffsetForSectorAlignment;+  ULONG ByteOffsetForPartitionAlignment;+} FILE_FS_SECTOR_SIZE_INFORMATION, *PFILE_FS_SECTOR_SIZE_INFORMATION;++typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {+    LARGE_INTEGER IdleTime;+    LARGE_INTEGER KernelTime;+    LARGE_INTEGER UserTime;+    LARGE_INTEGER DpcTime;+    LARGE_INTEGER InterruptTime;+    ULONG InterruptCount;+} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;++#ifndef SystemProcessorPerformanceInformation+# define SystemProcessorPerformanceInformation 8+#endif++#ifndef FILE_DEVICE_FILE_SYSTEM+# define FILE_DEVICE_FILE_SYSTEM 0x00000009+#endif++#ifndef FILE_DEVICE_NETWORK+# define FILE_DEVICE_NETWORK 0x00000012+#endif++#ifndef METHOD_BUFFERED+# define METHOD_BUFFERED 0+#endif++#ifndef METHOD_IN_DIRECT+# define METHOD_IN_DIRECT 1+#endif++#ifndef METHOD_OUT_DIRECT+# define METHOD_OUT_DIRECT 2+#endif++#ifndef METHOD_NEITHER+#define METHOD_NEITHER 3+#endif++#ifndef METHOD_DIRECT_TO_HARDWARE+# define METHOD_DIRECT_TO_HARDWARE METHOD_IN_DIRECT+#endif++#ifndef METHOD_DIRECT_FROM_HARDWARE+# define METHOD_DIRECT_FROM_HARDWARE METHOD_OUT_DIRECT+#endif++#ifndef FILE_ANY_ACCESS+# define FILE_ANY_ACCESS 0+#endif++#ifndef FILE_SPECIAL_ACCESS+# define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS)+#endif++#ifndef FILE_READ_ACCESS+# define FILE_READ_ACCESS 0x0001+#endif++#ifndef FILE_WRITE_ACCESS+# define FILE_WRITE_ACCESS 0x0002+#endif++#ifndef CTL_CODE+# define CTL_CODE(device_type, function, method, access)                      \+    (((device_type) << 16) | ((access) << 14) | ((function) << 2) | (method))+#endif++#ifndef FSCTL_SET_REPARSE_POINT+# define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM,            \+                                          41,                                 \+                                          METHOD_BUFFERED,                    \+                                          FILE_SPECIAL_ACCESS)+#endif++#ifndef FSCTL_GET_REPARSE_POINT+# define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM,            \+                                          42,                                 \+                                          METHOD_BUFFERED,                    \+                                          FILE_ANY_ACCESS)+#endif++#ifndef FSCTL_DELETE_REPARSE_POINT+# define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM,         \+                                             43,                              \+                                             METHOD_BUFFERED,                 \+                                             FILE_SPECIAL_ACCESS)+#endif++#ifndef IO_REPARSE_TAG_SYMLINK+# define IO_REPARSE_TAG_SYMLINK (0xA000000CL)+#endif++typedef VOID (NTAPI *PIO_APC_ROUTINE)+             (PVOID ApcContext,+              PIO_STATUS_BLOCK IoStatusBlock,+              ULONG Reserved);++typedef NTSTATUS (NTAPI *sRtlGetVersion)+                 (PRTL_OSVERSIONINFOW lpVersionInformation);++typedef ULONG (NTAPI *sRtlNtStatusToDosError)+              (NTSTATUS Status);++typedef NTSTATUS (NTAPI *sNtDeviceIoControlFile)+                 (HANDLE FileHandle,+                  HANDLE Event,+                  PIO_APC_ROUTINE ApcRoutine,+                  PVOID ApcContext,+                  PIO_STATUS_BLOCK IoStatusBlock,+                  ULONG IoControlCode,+                  PVOID InputBuffer,+                  ULONG InputBufferLength,+                  PVOID OutputBuffer,+                  ULONG OutputBufferLength);++typedef NTSTATUS (NTAPI *sNtQueryInformationFile)+                 (HANDLE FileHandle,+                  PIO_STATUS_BLOCK IoStatusBlock,+                  PVOID FileInformation,+                  ULONG Length,+                  FILE_INFORMATION_CLASS FileInformationClass);++typedef NTSTATUS (NTAPI *sNtSetInformationFile)+                 (HANDLE FileHandle,+                  PIO_STATUS_BLOCK IoStatusBlock,+                  PVOID FileInformation,+                  ULONG Length,+                  FILE_INFORMATION_CLASS FileInformationClass);++typedef NTSTATUS (NTAPI *sNtQueryVolumeInformationFile)+                 (HANDLE FileHandle,+                  PIO_STATUS_BLOCK IoStatusBlock,+                  PVOID FsInformation,+                  ULONG Length,+                  FS_INFORMATION_CLASS FsInformationClass);++typedef NTSTATUS (NTAPI *sNtQuerySystemInformation)+                 (UINT SystemInformationClass,+                  PVOID SystemInformation,+                  ULONG SystemInformationLength,+                  PULONG ReturnLength);++typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile)+                 (HANDLE FileHandle,+                  HANDLE Event,+                  PIO_APC_ROUTINE ApcRoutine,+                  PVOID ApcContext,+                  PIO_STATUS_BLOCK IoStatusBlock,+                  PVOID FileInformation,+                  ULONG Length,+                  FILE_INFORMATION_CLASS FileInformationClass,+                  BOOLEAN ReturnSingleEntry,+                  PUNICODE_STRING FileName,+                  BOOLEAN RestartScan+                );++/*+ * Kernel32 headers+ */+#ifndef FILE_SKIP_COMPLETION_PORT_ON_SUCCESS+# define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 0x1+#endif++#ifndef FILE_SKIP_SET_EVENT_ON_HANDLE+# define FILE_SKIP_SET_EVENT_ON_HANDLE 0x2+#endif++#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY+# define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1+#endif++#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)+  typedef struct _OVERLAPPED_ENTRY {+      ULONG_PTR lpCompletionKey;+      LPOVERLAPPED lpOverlapped;+      ULONG_PTR Internal;+      DWORD dwNumberOfBytesTransferred;+  } OVERLAPPED_ENTRY, *LPOVERLAPPED_ENTRY;+#endif++/* from wincon.h */+#ifndef ENABLE_INSERT_MODE+# define ENABLE_INSERT_MODE 0x20+#endif++#ifndef ENABLE_QUICK_EDIT_MODE+# define ENABLE_QUICK_EDIT_MODE 0x40+#endif++#ifndef ENABLE_EXTENDED_FLAGS+# define ENABLE_EXTENDED_FLAGS 0x80+#endif++/* from winerror.h */+#ifndef ERROR_ELEVATION_REQUIRED+# define ERROR_ELEVATION_REQUIRED 740+#endif++#ifndef ERROR_SYMLINK_NOT_SUPPORTED+# define ERROR_SYMLINK_NOT_SUPPORTED 1464+#endif++#ifndef ERROR_MUI_FILE_NOT_FOUND+# define ERROR_MUI_FILE_NOT_FOUND 15100+#endif++#ifndef ERROR_MUI_INVALID_FILE+# define ERROR_MUI_INVALID_FILE 15101+#endif++#ifndef ERROR_MUI_INVALID_RC_CONFIG+# define ERROR_MUI_INVALID_RC_CONFIG 15102+#endif++#ifndef ERROR_MUI_INVALID_LOCALE_NAME+# define ERROR_MUI_INVALID_LOCALE_NAME 15103+#endif++#ifndef ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME+# define ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME 15104+#endif++#ifndef ERROR_MUI_FILE_NOT_LOADED+# define ERROR_MUI_FILE_NOT_LOADED 15105+#endif++typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx)+             (HANDLE CompletionPort,+              LPOVERLAPPED_ENTRY lpCompletionPortEntries,+              ULONG ulCount,+              PULONG ulNumEntriesRemoved,+              DWORD dwMilliseconds,+              BOOL fAlertable);++/* from powerbase.h */+#ifndef DEVICE_NOTIFY_CALLBACK+# define DEVICE_NOTIFY_CALLBACK 2+#endif++#ifndef PBT_APMRESUMEAUTOMATIC+# define PBT_APMRESUMEAUTOMATIC 18+#endif++#ifndef PBT_APMRESUMESUSPEND+# define PBT_APMRESUMESUSPEND 7+#endif++typedef ULONG CALLBACK _DEVICE_NOTIFY_CALLBACK_ROUTINE(+  PVOID Context,+  ULONG Type,+  PVOID Setting+);+typedef _DEVICE_NOTIFY_CALLBACK_ROUTINE* _PDEVICE_NOTIFY_CALLBACK_ROUTINE;++typedef struct _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS {+  _PDEVICE_NOTIFY_CALLBACK_ROUTINE Callback;+  PVOID Context;+} _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS, *_PDEVICE_NOTIFY_SUBSCRIBE_PARAMETERS;++typedef PVOID _HPOWERNOTIFY;+typedef _HPOWERNOTIFY *_PHPOWERNOTIFY;++typedef DWORD (WINAPI *sPowerRegisterSuspendResumeNotification)+              (DWORD         Flags,+               HANDLE        Recipient,+               _PHPOWERNOTIFY RegistrationHandle);++/* from Winuser.h */+typedef VOID (CALLBACK* WINEVENTPROC)+             (HWINEVENTHOOK hWinEventHook,+              DWORD         event,+              HWND          hwnd,+              LONG          idObject,+              LONG          idChild,+              DWORD         idEventThread,+              DWORD         dwmsEventTime);++typedef HWINEVENTHOOK (WINAPI *sSetWinEventHook)+                      (UINT         eventMin,+                       UINT         eventMax,+                       HMODULE      hmodWinEventProc,+                       WINEVENTPROC lpfnWinEventProc,+                       DWORD        idProcess,+                       DWORD        idThread,+                       UINT         dwflags);+++/* Ntdll function pointers */+extern sRtlGetVersion pRtlGetVersion;+extern sRtlNtStatusToDosError pRtlNtStatusToDosError;+extern sNtDeviceIoControlFile pNtDeviceIoControlFile;+extern sNtQueryInformationFile pNtQueryInformationFile;+extern sNtSetInformationFile pNtSetInformationFile;+extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;+extern sNtQueryDirectoryFile pNtQueryDirectoryFile;+extern sNtQuerySystemInformation pNtQuerySystemInformation;++/* Kernel32 function pointers */+extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;++/* Powrprof.dll function pointer */+extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;++/* User32.dll function pointer */+extern sSetWinEventHook pSetWinEventHook;++#endif /* UV_WIN_WINAPI_H_ */
+ third_party/libuv/src/win/winsock.c view
@@ -0,0 +1,591 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#include <assert.h>+#include <stdlib.h>++#include "uv.h"+#include "internal.h"+++/* Whether there are any non-IFS LSPs stacked on TCP */+int uv_tcp_non_ifs_lsp_ipv4;+int uv_tcp_non_ifs_lsp_ipv6;++/* Ip address used to bind to any port at any interface */+struct sockaddr_in uv_addr_ip4_any_;+struct sockaddr_in6 uv_addr_ip6_any_;+++/*+ * Retrieves the pointer to a winsock extension function.+ */+static BOOL uv_get_extension_function(SOCKET socket, GUID guid,+    void **target) {+  int result;+  DWORD bytes;++  result = WSAIoctl(socket,+                    SIO_GET_EXTENSION_FUNCTION_POINTER,+                    &guid,+                    sizeof(guid),+                    (void*)target,+                    sizeof(*target),+                    &bytes,+                    NULL,+                    NULL);++  if (result == SOCKET_ERROR) {+    *target = NULL;+    return FALSE;+  } else {+    return TRUE;+  }+}+++BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target) {+  const GUID wsaid_acceptex = WSAID_ACCEPTEX;+  return uv_get_extension_function(socket, wsaid_acceptex, (void**)target);+}+++BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target) {+  const GUID wsaid_connectex = WSAID_CONNECTEX;+  return uv_get_extension_function(socket, wsaid_connectex, (void**)target);+}+++static int error_means_no_support(DWORD error) {+  return error == WSAEPROTONOSUPPORT || error == WSAESOCKTNOSUPPORT ||+         error == WSAEPFNOSUPPORT || error == WSAEAFNOSUPPORT;+}+++void uv_winsock_init(void) {+  WSADATA wsa_data;+  int errorno;+  SOCKET dummy;+  WSAPROTOCOL_INFOW protocol_info;+  int opt_len;++  /* Initialize winsock */+  errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);+  if (errorno != 0) {+    uv_fatal_error(errorno, "WSAStartup");+  }++  /* Set implicit binding address used by connectEx */+  if (uv_ip4_addr("0.0.0.0", 0, &uv_addr_ip4_any_)) {+    abort();+  }++  if (uv_ip6_addr("::", 0, &uv_addr_ip6_any_)) {+    abort();+  }++  /* Detect non-IFS LSPs */+  dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);++  if (dummy != INVALID_SOCKET) {+    opt_len = (int) sizeof protocol_info;+    if (getsockopt(dummy,+                   SOL_SOCKET,+                   SO_PROTOCOL_INFOW,+                   (char*) &protocol_info,+                   &opt_len) == SOCKET_ERROR)+      uv_fatal_error(WSAGetLastError(), "getsockopt");++    if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES))+      uv_tcp_non_ifs_lsp_ipv4 = 1;++    if (closesocket(dummy) == SOCKET_ERROR)+      uv_fatal_error(WSAGetLastError(), "closesocket");++  } else if (!error_means_no_support(WSAGetLastError())) {+    /* Any error other than "socket type not supported" is fatal. */+    uv_fatal_error(WSAGetLastError(), "socket");+  }++  /* Detect IPV6 support and non-IFS LSPs */+  dummy = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP);++  if (dummy != INVALID_SOCKET) {+    opt_len = (int) sizeof protocol_info;+    if (getsockopt(dummy,+                   SOL_SOCKET,+                   SO_PROTOCOL_INFOW,+                   (char*) &protocol_info,+                   &opt_len) == SOCKET_ERROR)+      uv_fatal_error(WSAGetLastError(), "getsockopt");++    if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES))+      uv_tcp_non_ifs_lsp_ipv6 = 1;++    if (closesocket(dummy) == SOCKET_ERROR)+      uv_fatal_error(WSAGetLastError(), "closesocket");++  } else if (!error_means_no_support(WSAGetLastError())) {+    /* Any error other than "socket type not supported" is fatal. */+    uv_fatal_error(WSAGetLastError(), "socket");+  }+}+++int uv_ntstatus_to_winsock_error(NTSTATUS status) {+  switch (status) {+    case STATUS_SUCCESS:+      return ERROR_SUCCESS;++    case STATUS_PENDING:+      return ERROR_IO_PENDING;++    case STATUS_INVALID_HANDLE:+    case STATUS_OBJECT_TYPE_MISMATCH:+      return WSAENOTSOCK;++    case STATUS_INSUFFICIENT_RESOURCES:+    case STATUS_PAGEFILE_QUOTA:+    case STATUS_COMMITMENT_LIMIT:+    case STATUS_WORKING_SET_QUOTA:+    case STATUS_NO_MEMORY:+    case STATUS_QUOTA_EXCEEDED:+    case STATUS_TOO_MANY_PAGING_FILES:+    case STATUS_REMOTE_RESOURCES:+      return WSAENOBUFS;++    case STATUS_TOO_MANY_ADDRESSES:+    case STATUS_SHARING_VIOLATION:+    case STATUS_ADDRESS_ALREADY_EXISTS:+      return WSAEADDRINUSE;++    case STATUS_LINK_TIMEOUT:+    case STATUS_IO_TIMEOUT:+    case STATUS_TIMEOUT:+      return WSAETIMEDOUT;++    case STATUS_GRACEFUL_DISCONNECT:+      return WSAEDISCON;++    case STATUS_REMOTE_DISCONNECT:+    case STATUS_CONNECTION_RESET:+    case STATUS_LINK_FAILED:+    case STATUS_CONNECTION_DISCONNECTED:+    case STATUS_PORT_UNREACHABLE:+    case STATUS_HOPLIMIT_EXCEEDED:+      return WSAECONNRESET;++    case STATUS_LOCAL_DISCONNECT:+    case STATUS_TRANSACTION_ABORTED:+    case STATUS_CONNECTION_ABORTED:+      return WSAECONNABORTED;++    case STATUS_BAD_NETWORK_PATH:+    case STATUS_NETWORK_UNREACHABLE:+    case STATUS_PROTOCOL_UNREACHABLE:+      return WSAENETUNREACH;++    case STATUS_HOST_UNREACHABLE:+      return WSAEHOSTUNREACH;++    case STATUS_CANCELLED:+    case STATUS_REQUEST_ABORTED:+      return WSAEINTR;++    case STATUS_BUFFER_OVERFLOW:+    case STATUS_INVALID_BUFFER_SIZE:+      return WSAEMSGSIZE;++    case STATUS_BUFFER_TOO_SMALL:+    case STATUS_ACCESS_VIOLATION:+      return WSAEFAULT;++    case STATUS_DEVICE_NOT_READY:+    case STATUS_REQUEST_NOT_ACCEPTED:+      return WSAEWOULDBLOCK;++    case STATUS_INVALID_NETWORK_RESPONSE:+    case STATUS_NETWORK_BUSY:+    case STATUS_NO_SUCH_DEVICE:+    case STATUS_NO_SUCH_FILE:+    case STATUS_OBJECT_PATH_NOT_FOUND:+    case STATUS_OBJECT_NAME_NOT_FOUND:+    case STATUS_UNEXPECTED_NETWORK_ERROR:+      return WSAENETDOWN;++    case STATUS_INVALID_CONNECTION:+      return WSAENOTCONN;++    case STATUS_REMOTE_NOT_LISTENING:+    case STATUS_CONNECTION_REFUSED:+      return WSAECONNREFUSED;++    case STATUS_PIPE_DISCONNECTED:+      return WSAESHUTDOWN;++    case STATUS_CONFLICTING_ADDRESSES:+    case STATUS_INVALID_ADDRESS:+    case STATUS_INVALID_ADDRESS_COMPONENT:+      return WSAEADDRNOTAVAIL;++    case STATUS_NOT_SUPPORTED:+    case STATUS_NOT_IMPLEMENTED:+      return WSAEOPNOTSUPP;++    case STATUS_ACCESS_DENIED:+      return WSAEACCES;++    default:+      if ((status & (FACILITY_NTWIN32 << 16)) == (FACILITY_NTWIN32 << 16) &&+          (status & (ERROR_SEVERITY_ERROR | ERROR_SEVERITY_WARNING))) {+        /* It's a windows error that has been previously mapped to an ntstatus+         * code. */+        return (DWORD) (status & 0xffff);+      } else {+        /* The default fallback for unmappable ntstatus codes. */+        return WSAEINVAL;+      }+  }+}+++/*+ * This function provides a workaround for a bug in the winsock implementation+ * of WSARecv. The problem is that when SetFileCompletionNotificationModes is+ * used to avoid IOCP notifications of completed reads, WSARecv does not+ * reliably indicate whether we can expect a completion package to be posted+ * when the receive buffer is smaller than the received datagram.+ *+ * However it is desirable to use SetFileCompletionNotificationModes because+ * it yields a massive performance increase.+ *+ * This function provides a workaround for that bug, but it only works for the+ * specific case that we need it for. E.g. it assumes that the "avoid iocp"+ * bit has been set, and supports only overlapped operation. It also requires+ * the user to use the default msafd driver, doesn't work when other LSPs are+ * stacked on top of it.+ */+int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers,+    DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped,+    LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) {+  NTSTATUS status;+  void* apc_context;+  IO_STATUS_BLOCK* iosb = (IO_STATUS_BLOCK*) &overlapped->Internal;+  AFD_RECV_INFO info;+  DWORD error;++  if (overlapped == NULL || completion_routine != NULL) {+    WSASetLastError(WSAEINVAL);+    return SOCKET_ERROR;+  }++  info.BufferArray = buffers;+  info.BufferCount = buffer_count;+  info.AfdFlags = AFD_OVERLAPPED;+  info.TdiFlags = TDI_RECEIVE_NORMAL;++  if (*flags & MSG_PEEK) {+    info.TdiFlags |= TDI_RECEIVE_PEEK;+  }++  if (*flags & MSG_PARTIAL) {+    info.TdiFlags |= TDI_RECEIVE_PARTIAL;+  }++  if (!((intptr_t) overlapped->hEvent & 1)) {+    apc_context = (void*) overlapped;+  } else {+    apc_context = NULL;+  }++  iosb->Status = STATUS_PENDING;+  iosb->Pointer = 0;++  status = pNtDeviceIoControlFile((HANDLE) socket,+                                  overlapped->hEvent,+                                  NULL,+                                  apc_context,+                                  iosb,+                                  IOCTL_AFD_RECEIVE,+                                  &info,+                                  sizeof(info),+                                  NULL,+                                  0);++  *flags = 0;+  *bytes = (DWORD) iosb->Information;++  switch (status) {+    case STATUS_SUCCESS:+      error = ERROR_SUCCESS;+      break;++    case STATUS_PENDING:+      error = WSA_IO_PENDING;+      break;++    case STATUS_BUFFER_OVERFLOW:+      error = WSAEMSGSIZE;+      break;++    case STATUS_RECEIVE_EXPEDITED:+      error = ERROR_SUCCESS;+      *flags = MSG_OOB;+      break;++    case STATUS_RECEIVE_PARTIAL_EXPEDITED:+      error = ERROR_SUCCESS;+      *flags = MSG_PARTIAL | MSG_OOB;+      break;++    case STATUS_RECEIVE_PARTIAL:+      error = ERROR_SUCCESS;+      *flags = MSG_PARTIAL;+      break;++    default:+      error = uv_ntstatus_to_winsock_error(status);+      break;+  }++  WSASetLastError(error);++  if (error == ERROR_SUCCESS) {+    return 0;+  } else {+    return SOCKET_ERROR;+  }+}+++/* See description of uv_wsarecv_workaround. */+int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,+    DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr,+    int* addr_len, WSAOVERLAPPED *overlapped,+    LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) {+  NTSTATUS status;+  void* apc_context;+  IO_STATUS_BLOCK* iosb = (IO_STATUS_BLOCK*) &overlapped->Internal;+  AFD_RECV_DATAGRAM_INFO info;+  DWORD error;++  if (overlapped == NULL || addr == NULL || addr_len == NULL ||+      completion_routine != NULL) {+    WSASetLastError(WSAEINVAL);+    return SOCKET_ERROR;+  }++  info.BufferArray = buffers;+  info.BufferCount = buffer_count;+  info.AfdFlags = AFD_OVERLAPPED;+  info.TdiFlags = TDI_RECEIVE_NORMAL;+  info.Address = addr;+  info.AddressLength = addr_len;++  if (*flags & MSG_PEEK) {+    info.TdiFlags |= TDI_RECEIVE_PEEK;+  }++  if (*flags & MSG_PARTIAL) {+    info.TdiFlags |= TDI_RECEIVE_PARTIAL;+  }++  if (!((intptr_t) overlapped->hEvent & 1)) {+    apc_context = (void*) overlapped;+  } else {+    apc_context = NULL;+  }++  iosb->Status = STATUS_PENDING;+  iosb->Pointer = 0;++  status = pNtDeviceIoControlFile((HANDLE) socket,+                                  overlapped->hEvent,+                                  NULL,+                                  apc_context,+                                  iosb,+                                  IOCTL_AFD_RECEIVE_DATAGRAM,+                                  &info,+                                  sizeof(info),+                                  NULL,+                                  0);++  *flags = 0;+  *bytes = (DWORD) iosb->Information;++  switch (status) {+    case STATUS_SUCCESS:+      error = ERROR_SUCCESS;+      break;++    case STATUS_PENDING:+      error = WSA_IO_PENDING;+      break;++    case STATUS_BUFFER_OVERFLOW:+      error = WSAEMSGSIZE;+      break;++    case STATUS_RECEIVE_EXPEDITED:+      error = ERROR_SUCCESS;+      *flags = MSG_OOB;+      break;++    case STATUS_RECEIVE_PARTIAL_EXPEDITED:+      error = ERROR_SUCCESS;+      *flags = MSG_PARTIAL | MSG_OOB;+      break;++    case STATUS_RECEIVE_PARTIAL:+      error = ERROR_SUCCESS;+      *flags = MSG_PARTIAL;+      break;++    default:+      error = uv_ntstatus_to_winsock_error(status);+      break;+  }++  WSASetLastError(error);++  if (error == ERROR_SUCCESS) {+    return 0;+  } else {+    return SOCKET_ERROR;+  }+}+++int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,+    AFD_POLL_INFO* info_out, OVERLAPPED* overlapped) {+  IO_STATUS_BLOCK iosb;+  IO_STATUS_BLOCK* iosb_ptr;+  HANDLE event = NULL;+  void* apc_context;+  NTSTATUS status;+  DWORD error;++  if (overlapped != NULL) {+    /* Overlapped operation. */+    iosb_ptr = (IO_STATUS_BLOCK*) &overlapped->Internal;+    event = overlapped->hEvent;++    /* Do not report iocp completion if hEvent is tagged. */+    if ((uintptr_t) event & 1) {+      event = (HANDLE)((uintptr_t) event & ~(uintptr_t) 1);+      apc_context = NULL;+    } else {+      apc_context = overlapped;+    }++  } else {+    /* Blocking operation. */+    iosb_ptr = &iosb;+    event = CreateEvent(NULL, FALSE, FALSE, NULL);+    if (event == NULL) {+      return SOCKET_ERROR;+    }+    apc_context = NULL;+  }++  iosb_ptr->Status = STATUS_PENDING;+  status = pNtDeviceIoControlFile((HANDLE) socket,+                                  event,+                                  NULL,+                                  apc_context,+                                  iosb_ptr,+                                  IOCTL_AFD_POLL,+                                  info_in,+                                  sizeof *info_in,+                                  info_out,+                                  sizeof *info_out);++  if (overlapped == NULL) {+    /* If this is a blocking operation, wait for the event to become signaled,+     * and then grab the real status from the io status block. */+    if (status == STATUS_PENDING) {+      DWORD r = WaitForSingleObject(event, INFINITE);++      if (r == WAIT_FAILED) {+        DWORD saved_error = GetLastError();+        CloseHandle(event);+        WSASetLastError(saved_error);+        return SOCKET_ERROR;+      }++      status = iosb.Status;+    }++    CloseHandle(event);+  }++  switch (status) {+    case STATUS_SUCCESS:+      error = ERROR_SUCCESS;+      break;++    case STATUS_PENDING:+      error = WSA_IO_PENDING;+      break;++    default:+      error = uv_ntstatus_to_winsock_error(status);+      break;+  }++  WSASetLastError(error);++  if (error == ERROR_SUCCESS) {+    return 0;+  } else {+    return SOCKET_ERROR;+  }+}++int uv__convert_to_localhost_if_unspecified(const struct sockaddr* addr,+                                            struct sockaddr_storage* storage) {+  struct sockaddr_in* dest4;+  struct sockaddr_in6* dest6;++  if (addr == NULL)+    return UV_EINVAL;++  switch (addr->sa_family) {+  case AF_INET:+    dest4 = (struct sockaddr_in*) storage;+    memcpy(dest4, addr, sizeof(*dest4));+    if (dest4->sin_addr.s_addr == 0)+      dest4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);+    return 0;+  case AF_INET6:+    dest6 = (struct sockaddr_in6*) storage;+    memcpy(dest6, addr, sizeof(*dest6));+    if (memcmp(&dest6->sin6_addr,+               &uv_addr_ip6_any_.sin6_addr,+               sizeof(uv_addr_ip6_any_.sin6_addr)) == 0) {+      struct in6_addr init_sin6_addr = IN6ADDR_LOOPBACK_INIT;+      dest6->sin6_addr = init_sin6_addr;+    }+    return 0;+  default:+    return UV_EINVAL;+  }+}
+ third_party/libuv/src/win/winsock.h view
@@ -0,0 +1,193 @@+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to+ * deal in the Software without restriction, including without limitation the+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+ * sell copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+ * IN THE SOFTWARE.+ */++#ifndef UV_WIN_WINSOCK_H_+#define UV_WIN_WINSOCK_H_++#include <winsock2.h>+#include <iptypes.h>+#include <mswsock.h>+#include <ws2tcpip.h>+#include <windows.h>++#include "winapi.h"+++/*+ * MinGW is missing these too+ */+#ifndef SO_UPDATE_CONNECT_CONTEXT+# define SO_UPDATE_CONNECT_CONTEXT 0x7010+#endif++#ifndef TCP_KEEPALIVE+# define TCP_KEEPALIVE 3+#endif++#ifndef IPV6_V6ONLY+# define IPV6_V6ONLY 27+#endif++#ifndef IPV6_HOPLIMIT+# define IPV6_HOPLIMIT 21+#endif++#ifndef SIO_BASE_HANDLE+# define SIO_BASE_HANDLE 0x48000022+#endif++/*+ * TDI defines that are only in the DDK.+ * We only need receive flags so far.+ */+#ifndef TDI_RECEIVE_NORMAL+  #define TDI_RECEIVE_BROADCAST           0x00000004+  #define TDI_RECEIVE_MULTICAST           0x00000008+  #define TDI_RECEIVE_PARTIAL             0x00000010+  #define TDI_RECEIVE_NORMAL              0x00000020+  #define TDI_RECEIVE_EXPEDITED           0x00000040+  #define TDI_RECEIVE_PEEK                0x00000080+  #define TDI_RECEIVE_NO_RESPONSE_EXP     0x00000100+  #define TDI_RECEIVE_COPY_LOOKAHEAD      0x00000200+  #define TDI_RECEIVE_ENTIRE_MESSAGE      0x00000400+  #define TDI_RECEIVE_AT_DISPATCH_LEVEL   0x00000800+  #define TDI_RECEIVE_CONTROL_INFO        0x00001000+  #define TDI_RECEIVE_FORCE_INDICATION    0x00002000+  #define TDI_RECEIVE_NO_PUSH             0x00004000+#endif++/*+ * The "Auxiliary Function Driver" is the windows kernel-mode driver that does+ * TCP, UDP etc. Winsock is just a layer that dispatches requests to it.+ * Having these definitions allows us to bypass winsock and make an AFD kernel+ * call directly, avoiding a bug in winsock's recvfrom implementation.+ */++#define AFD_NO_FAST_IO   0x00000001+#define AFD_OVERLAPPED   0x00000002+#define AFD_IMMEDIATE    0x00000004++#define AFD_POLL_RECEIVE_BIT            0+#define AFD_POLL_RECEIVE                (1 << AFD_POLL_RECEIVE_BIT)+#define AFD_POLL_RECEIVE_EXPEDITED_BIT  1+#define AFD_POLL_RECEIVE_EXPEDITED      (1 << AFD_POLL_RECEIVE_EXPEDITED_BIT)+#define AFD_POLL_SEND_BIT               2+#define AFD_POLL_SEND                   (1 << AFD_POLL_SEND_BIT)+#define AFD_POLL_DISCONNECT_BIT         3+#define AFD_POLL_DISCONNECT             (1 << AFD_POLL_DISCONNECT_BIT)+#define AFD_POLL_ABORT_BIT              4+#define AFD_POLL_ABORT                  (1 << AFD_POLL_ABORT_BIT)+#define AFD_POLL_LOCAL_CLOSE_BIT        5+#define AFD_POLL_LOCAL_CLOSE            (1 << AFD_POLL_LOCAL_CLOSE_BIT)+#define AFD_POLL_CONNECT_BIT            6+#define AFD_POLL_CONNECT                (1 << AFD_POLL_CONNECT_BIT)+#define AFD_POLL_ACCEPT_BIT             7+#define AFD_POLL_ACCEPT                 (1 << AFD_POLL_ACCEPT_BIT)+#define AFD_POLL_CONNECT_FAIL_BIT       8+#define AFD_POLL_CONNECT_FAIL           (1 << AFD_POLL_CONNECT_FAIL_BIT)+#define AFD_POLL_QOS_BIT                9+#define AFD_POLL_QOS                    (1 << AFD_POLL_QOS_BIT)+#define AFD_POLL_GROUP_QOS_BIT          10+#define AFD_POLL_GROUP_QOS              (1 << AFD_POLL_GROUP_QOS_BIT)++#define AFD_NUM_POLL_EVENTS             11+#define AFD_POLL_ALL                    ((1 << AFD_NUM_POLL_EVENTS) - 1)++typedef struct _AFD_RECV_DATAGRAM_INFO {+    LPWSABUF BufferArray;+    ULONG BufferCount;+    ULONG AfdFlags;+    ULONG TdiFlags;+    struct sockaddr* Address;+    int* AddressLength;+} AFD_RECV_DATAGRAM_INFO, *PAFD_RECV_DATAGRAM_INFO;++typedef struct _AFD_RECV_INFO {+    LPWSABUF BufferArray;+    ULONG BufferCount;+    ULONG AfdFlags;+    ULONG TdiFlags;+} AFD_RECV_INFO, *PAFD_RECV_INFO;+++#define _AFD_CONTROL_CODE(operation, method) \+    ((FSCTL_AFD_BASE) << 12 | (operation << 2) | method)++#define FSCTL_AFD_BASE FILE_DEVICE_NETWORK++#define AFD_RECEIVE            5+#define AFD_RECEIVE_DATAGRAM   6+#define AFD_POLL               9++#define IOCTL_AFD_RECEIVE \+    _AFD_CONTROL_CODE(AFD_RECEIVE, METHOD_NEITHER)++#define IOCTL_AFD_RECEIVE_DATAGRAM \+    _AFD_CONTROL_CODE(AFD_RECEIVE_DATAGRAM, METHOD_NEITHER)++#define IOCTL_AFD_POLL \+    _AFD_CONTROL_CODE(AFD_POLL, METHOD_BUFFERED)++#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)+typedef struct _IP_ADAPTER_UNICAST_ADDRESS_XP {+  /* FIXME: __C89_NAMELESS was removed */+  /* __C89_NAMELESS */ union {+    ULONGLONG Alignment;+    /* __C89_NAMELESS */ struct {+      ULONG Length;+      DWORD Flags;+    };+  };+  struct _IP_ADAPTER_UNICAST_ADDRESS_XP *Next;+  SOCKET_ADDRESS Address;+  IP_PREFIX_ORIGIN PrefixOrigin;+  IP_SUFFIX_ORIGIN SuffixOrigin;+  IP_DAD_STATE DadState;+  ULONG ValidLifetime;+  ULONG PreferredLifetime;+  ULONG LeaseLifetime;+} IP_ADAPTER_UNICAST_ADDRESS_XP,*PIP_ADAPTER_UNICAST_ADDRESS_XP;++typedef struct _IP_ADAPTER_UNICAST_ADDRESS_LH {+  union {+    ULONGLONG Alignment;+    struct {+      ULONG Length;+      DWORD Flags;+    };+  };+  struct _IP_ADAPTER_UNICAST_ADDRESS_LH *Next;+  SOCKET_ADDRESS Address;+  IP_PREFIX_ORIGIN PrefixOrigin;+  IP_SUFFIX_ORIGIN SuffixOrigin;+  IP_DAD_STATE DadState;+  ULONG ValidLifetime;+  ULONG PreferredLifetime;+  ULONG LeaseLifetime;+  UINT8 OnLinkPrefixLength;+} IP_ADAPTER_UNICAST_ADDRESS_LH,*PIP_ADAPTER_UNICAST_ADDRESS_LH;++#endif++int uv__convert_to_localhost_if_unspecified(const struct sockaddr* addr,+                                            struct sockaddr_storage* storage);++#endif /* UV_WIN_WINSOCK_H_ */
+ third_party/utf8rewind/include/utf8rewind/utf8rewind.h view
@@ -0,0 +1,1870 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _UTF8REWIND_H_
+#define _UTF8REWIND_H_
+
+/*!
+	\file
+	\brief Public interface for UTF-8 functions.
+
+	`utf8rewind` is a system library written in C designed to extend the default
+	string handling functions with support for UTF-8 encoded text.
+*/
+
+/*!
+	\defgroup public Public interface
+	The public interface for the library.
+
+	\defgroup version Version information
+	Macros used to identify the version of the library.
+
+	\defgroup global-config Global configuration
+	Defines used for determining the global configuration of the system and your
+	application.
+
+	\defgroup errors Error codes
+	Values returned by functions on error.
+
+	\defgroup locales Locales
+	Values used by functions that change behavior based on the input locale.
+
+	\defgroup normalization Normalization flags
+	Flags used as input for #utf8normalize and the result of #utf8isnormalized.
+
+	\defgroup category Category flags
+	Flags to be used with #utf8iscategory, to check whether code points in a
+	string are part of that category.
+
+	\defgroup types Types
+	Custom type definitions used throughout the library.
+*/
+
+#include <locale.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <wchar.h>
+
+/*!
+	\addtogroup version
+	\{
+*/
+
+/*!
+	\def UTF8_VERSION_MAKE
+	\brief Macro for creating a version number from a major, minor and bugfix
+	number.
+*/
+#define UTF8_VERSION_MAKE(_major, _minor, _bugfix) \
+	((_major) * 10000) + ((_minor) * 100) + (_bugfix)
+
+/*!
+	\def UTF8_VERSION_MAJOR
+	\brief The major version number of this release.
+*/
+#define UTF8_VERSION_MAJOR   1
+
+/*!
+	\def UTF8_VERSION_MINOR
+	\brief The minor version number of this release.
+*/
+#define UTF8_VERSION_MINOR   5
+
+/*!
+	\def UTF8_VERSION_BUGFIX
+	\brief The bugfix version number of this release.
+*/
+#define UTF8_VERSION_BUGFIX  1
+
+/*!
+	\def UTF8_VERSION
+	\brief The version number as an integer.
+*/
+#define UTF8_VERSION \
+	UTF8_VERSION_MAKE(UTF8_VERSION_MAJOR, UTF8_VERSION_MINOR, UTF8_VERSION_BUGFIX)
+
+/*!
+	\def UTF8_VERSION_STRING
+	\brief The verion number as a string.
+*/
+#define UTF8_VERSION_STRING  "1.5.1"
+
+/*!
+	\def UTF8_VERSION_GUARD
+	\brief Check if feature is supported by the current release.
+*/
+#define UTF8_VERSION_GUARD(_major, _minor, _bugfix) \
+	(UTF8_VERSION >= UTF8_VERSION_MAKE(_major, _minor, _bugfix))
+
+/*!
+	\}
+*/
+
+/*!
+	\addtogroup errors
+	\{
+*/
+
+/*!
+	\def UTF8_ERR_NONE
+	\brief No errors.
+*/
+#define UTF8_ERR_NONE                           (0)
+
+/*!
+	\def UTF8_ERR_INVALID_DATA
+	\brief Input data is invalid.
+*/
+#define UTF8_ERR_INVALID_DATA                   (-1)
+
+/*!
+	\def UTF8_ERR_INVALID_FLAG
+	\brief Input flag is invalid.
+*/
+#define UTF8_ERR_INVALID_FLAG                   (-2)
+
+/*!
+	\def UTF8_ERR_NOT_ENOUGH_SPACE
+	\brief Not enough space in buffer to store result.
+*/
+#define UTF8_ERR_NOT_ENOUGH_SPACE               (-3)
+
+/*!
+	\def UTF8_ERR_OVERLAPPING_PARAMETERS
+	\brief Input and output buffers overlap in memory.
+*/
+#define UTF8_ERR_OVERLAPPING_PARAMETERS         (-4)
+
+/*!
+	\def UTF8_ERR_INVALID_LOCALE
+	\brief Invalid locale specified.
+*/
+#define UTF8_ERR_INVALID_LOCALE                 (-5)
+
+/*!
+	\}
+*/
+
+/*!
+	\addtogroup locales
+	\{
+*/
+
+/*!
+	\def UTF8_LOCALE_DEFAULT
+	\brief Used for text unaffected by changes in locale.
+*/
+#define UTF8_LOCALE_DEFAULT                     0
+
+/*!
+	\def UTF8_LOCALE_LITHUANIAN
+	\brief Changes behavior of the case mapping implementation when processing
+	specific code points. For more information, see here:
+	ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
+*/
+#define UTF8_LOCALE_LITHUANIAN                  1
+
+/*!
+	\def UTF8_LOCALE_TURKISH_AND_AZERI_LATIN
+	\brief Changes behavior of the case mapping implementation when processing
+	specific code points. For more information, see here:
+	ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
+*/
+#define UTF8_LOCALE_TURKISH_AND_AZERI_LATIN     2
+
+/*!
+	\def UTF8_LOCALE_MAXIMUM
+	\brief Terminal value for locales. Valid locales do not exceed this value.
+*/
+#define UTF8_LOCALE_MAXIMUM                     3
+
+/*!
+	\}
+*/
+
+/*!
+	\addtogroup normalization
+	\{
+*/
+
+/*!
+	\def UTF8_NORMALIZE_COMPOSE
+	\brief Normalize input to Normalization Form C (NFC).
+*/
+#define UTF8_NORMALIZE_COMPOSE                  0x00000001
+
+/*!
+	\def UTF8_NORMALIZE_DECOMPOSE
+	\brief Normalize input to Normalization Form D (NFD).
+*/
+#define UTF8_NORMALIZE_DECOMPOSE                0x00000002
+
+/*!
+	\def UTF8_NORMALIZE_COMPATIBILITY
+	\brief Changes Normalization Form from NFC to NFKC or from NFD to NFKD.
+*/
+#define UTF8_NORMALIZE_COMPATIBILITY            0x00000004
+
+/*!
+	\def UTF8_NORMALIZATION_RESULT_YES
+	\brief Text is stable and does not need to be normalized.
+*/
+#define UTF8_NORMALIZATION_RESULT_YES           (0)
+
+/*!
+	\def UTF8_NORMALIZATION_RESULT_MAYBE
+	\brief Text is unstable, but normalization may be skipped.
+*/
+#define UTF8_NORMALIZATION_RESULT_MAYBE         (1)
+
+/*!
+	\def UTF8_NORMALIZATION_RESULT_NO
+	\brief Text is unstable and must be normalized.
+*/
+#define UTF8_NORMALIZATION_RESULT_NO            (2)
+
+/*!
+	\}
+*/
+
+/*!
+	\addtogroup category
+	\{
+*/
+
+/*!
+	\def UTF8_CATEGORY_LETTER_UPPERCASE
+	\brief Uppercase letter code points, Lu in the Unicode database.
+*/
+#define UTF8_CATEGORY_LETTER_UPPERCASE          0x00000001
+
+/*!
+	\def UTF8_CATEGORY_LETTER_LOWERCASE
+	\brief Lowercase letter code points, Ll in the Unicode database.
+*/
+#define UTF8_CATEGORY_LETTER_LOWERCASE          0x00000002
+
+/*!
+	\def UTF8_CATEGORY_LETTER_TITLECASE
+	\brief Titlecase letter code points, Lt in the Unicode database.
+*/
+#define UTF8_CATEGORY_LETTER_TITLECASE          0x00000004
+
+/*!
+	\def UTF8_CATEGORY_LETTER_MODIFIER
+	\brief Modifier letter code points, Lm in the Unicode database.
+*/
+#define UTF8_CATEGORY_LETTER_MODIFIER           0x00000008
+
+/*!
+	\def UTF8_CATEGORY_LETTER_OTHER
+	\brief Other letter code points, Lo in the Unicode database.
+*/
+#define UTF8_CATEGORY_LETTER_OTHER              0x00000010
+
+/*!
+	\def UTF8_CATEGORY_LETTER
+	\brief Combined flag for all letter categories.
+*/
+#define UTF8_CATEGORY_LETTER \
+	(UTF8_CATEGORY_LETTER_UPPERCASE | UTF8_CATEGORY_LETTER_LOWERCASE | \
+	UTF8_CATEGORY_LETTER_TITLECASE | UTF8_CATEGORY_LETTER_MODIFIER | \
+	UTF8_CATEGORY_LETTER_OTHER)
+
+/*!
+	\def UTF8_CATEGORY_CASE_MAPPED
+	\brief Combined flag for all letter categories with case mapping.
+*/
+#define UTF8_CATEGORY_CASE_MAPPED \
+	(UTF8_CATEGORY_LETTER_UPPERCASE | UTF8_CATEGORY_LETTER_LOWERCASE | \
+	UTF8_CATEGORY_LETTER_TITLECASE)
+
+/*!
+	\def UTF8_CATEGORY_MARK_NON_SPACING
+	\brief Non-spacing mark code points, Mn in the Unicode database.
+*/
+#define UTF8_CATEGORY_MARK_NON_SPACING          0x00000020
+
+/*!
+	\def UTF8_CATEGORY_MARK_SPACING
+	\brief Spacing mark code points, Mc in the Unicode database.
+*/
+#define UTF8_CATEGORY_MARK_SPACING              0x00000040
+
+/*!
+	\def UTF8_CATEGORY_MARK_ENCLOSING
+	\brief Enclosing mark code points, Me in the Unicode database.
+*/
+#define UTF8_CATEGORY_MARK_ENCLOSING            0x00000080
+
+/*!
+	\def UTF8_CATEGORY_MARK
+	\brief Combined flag for all mark categories.
+*/
+#define UTF8_CATEGORY_MARK \
+	(UTF8_CATEGORY_MARK_NON_SPACING | UTF8_CATEGORY_MARK_SPACING | \
+	UTF8_CATEGORY_MARK_ENCLOSING)
+
+/*!
+	\def UTF8_CATEGORY_NUMBER_DECIMAL
+	\brief Decimal number code points, Nd in the Unicode database.
+*/
+#define UTF8_CATEGORY_NUMBER_DECIMAL            0x00000100
+
+/*!
+	\def UTF8_CATEGORY_NUMBER_LETTER
+	\brief Letter number code points, Nl in the Unicode database.
+*/
+#define UTF8_CATEGORY_NUMBER_LETTER             0x00000200
+
+/*!
+	\def UTF8_CATEGORY_NUMBER_OTHER
+	\brief Other number code points, No in the Unicode database.
+*/
+#define UTF8_CATEGORY_NUMBER_OTHER              0x00000400
+
+/*!
+	\def UTF8_CATEGORY_NUMBER
+	\brief Combined flag for all number categories.
+*/
+#define UTF8_CATEGORY_NUMBER \
+	(UTF8_CATEGORY_NUMBER_DECIMAL | UTF8_CATEGORY_NUMBER_LETTER | \
+	UTF8_CATEGORY_NUMBER_OTHER)
+
+/*!
+	\def UTF8_CATEGORY_PUNCTUATION_CONNECTOR
+	\brief Connector punctuation category, Pc in the Unicode database.
+*/
+#define UTF8_CATEGORY_PUNCTUATION_CONNECTOR     0x00000800
+
+/*!
+	\def UTF8_CATEGORY_PUNCTUATION_DASH
+	\brief Dash punctuation category, Pd in the Unicode database.
+*/
+#define UTF8_CATEGORY_PUNCTUATION_DASH          0x00001000
+
+/*!
+	\def UTF8_CATEGORY_PUNCTUATION_OPEN
+	\brief Open punctuation category, Ps in the Unicode database.
+*/
+#define UTF8_CATEGORY_PUNCTUATION_OPEN          0x00002000
+
+/*!
+	\def UTF8_CATEGORY_PUNCTUATION_CLOSE
+	\brief Close punctuation category, Pe in the Unicode database.
+*/
+#define UTF8_CATEGORY_PUNCTUATION_CLOSE         0x00004000
+
+/*!
+	\def UTF8_CATEGORY_PUNCTUATION_INITIAL
+	\brief Initial punctuation category, Pi in the Unicode database.
+*/
+#define UTF8_CATEGORY_PUNCTUATION_INITIAL       0x00008000
+
+/*!
+	\def UTF8_CATEGORY_PUNCTUATION_FINAL
+	\brief Final punctuation category, Pf in the Unicode database.
+*/
+#define UTF8_CATEGORY_PUNCTUATION_FINAL         0x00010000
+
+/*!
+	\def UTF8_CATEGORY_PUNCTUATION_OTHER
+	\brief Other punctuation category, Po in the Unicode database.
+*/
+#define UTF8_CATEGORY_PUNCTUATION_OTHER         0x00020000
+
+/*!
+	\def UTF8_CATEGORY_PUNCTUATION
+	\brief Combined flag for all punctuation categories.
+*/
+#define UTF8_CATEGORY_PUNCTUATION \
+	(UTF8_CATEGORY_PUNCTUATION_CONNECTOR | UTF8_CATEGORY_PUNCTUATION_DASH | \
+	UTF8_CATEGORY_PUNCTUATION_OPEN | UTF8_CATEGORY_PUNCTUATION_CLOSE | \
+	UTF8_CATEGORY_PUNCTUATION_INITIAL | UTF8_CATEGORY_PUNCTUATION_FINAL | \
+	UTF8_CATEGORY_PUNCTUATION_OTHER)
+
+/*!
+	\def UTF8_CATEGORY_SYMBOL_MATH
+	\brief Math symbol category, Sm in the Unicode database.
+*/
+#define UTF8_CATEGORY_SYMBOL_MATH               0x00040000
+
+/*!
+	\def UTF8_CATEGORY_SYMBOL_CURRENCY
+	\brief Currency symbol category, Sc in the Unicode database.
+*/
+#define UTF8_CATEGORY_SYMBOL_CURRENCY           0x00080000
+
+/*!
+	\def UTF8_CATEGORY_SYMBOL_MODIFIER
+	\brief Modifier symbol category, Sk in the Unicode database.
+*/
+#define UTF8_CATEGORY_SYMBOL_MODIFIER           0x00100000
+
+/*!
+	\def UTF8_CATEGORY_SYMBOL_OTHER
+	\brief Other symbol category, So in the Unicode database.
+*/
+#define UTF8_CATEGORY_SYMBOL_OTHER              0x00200000
+
+/*!
+	\def UTF8_CATEGORY_SYMBOL
+	\brief Combined flag for all symbol categories.
+*/
+#define UTF8_CATEGORY_SYMBOL \
+	(UTF8_CATEGORY_SYMBOL_MATH | UTF8_CATEGORY_SYMBOL_CURRENCY | \
+	UTF8_CATEGORY_SYMBOL_MODIFIER | UTF8_CATEGORY_SYMBOL_OTHER)
+
+/*!
+	\def UTF8_CATEGORY_SEPARATOR_SPACE
+	\brief Space separator category, Zs in the Unicode database.
+*/
+#define UTF8_CATEGORY_SEPARATOR_SPACE           0x00400000
+
+/*!
+	\def UTF8_CATEGORY_SEPARATOR_LINE
+	\brief Line separator category, Zl in the Unicode database.
+*/
+#define UTF8_CATEGORY_SEPARATOR_LINE            0x00800000
+
+/*!
+	\def UTF8_CATEGORY_SEPARATOR_PARAGRAPH
+	\brief Paragraph separator category, Zp in the Unicode database.
+*/
+#define UTF8_CATEGORY_SEPARATOR_PARAGRAPH       0x01000000
+
+/*!
+	\def UTF8_CATEGORY_SEPARATOR
+	\brief Combined flag for all separator categories.
+*/
+#define UTF8_CATEGORY_SEPARATOR \
+	(UTF8_CATEGORY_SEPARATOR_SPACE | UTF8_CATEGORY_SEPARATOR_LINE | \
+	UTF8_CATEGORY_SEPARATOR_PARAGRAPH)
+
+/*!
+	\def UTF8_CATEGORY_CONTROL
+	\brief Control category, Cc in the Unicode database.
+*/
+#define UTF8_CATEGORY_CONTROL                   0x02000000
+
+/*!
+	\def UTF8_CATEGORY_FORMAT
+	\brief Format category, Cf in the Unicode database.
+*/
+#define UTF8_CATEGORY_FORMAT                    0x04000000
+
+/*!
+	\def UTF8_CATEGORY_SURROGATE
+	\brief Surrogate category, Cs in the Unicode database.
+*/
+#define UTF8_CATEGORY_SURROGATE                 0x08000000
+
+/*!
+	\def UTF8_CATEGORY_PRIVATE_USE
+	\brief Private use category, Co in the Unicode database.
+*/
+#define UTF8_CATEGORY_PRIVATE_USE               0x10000000
+
+/*!
+	\def UTF8_CATEGORY_UNASSIGNED
+	\brief Unassigned category, Cn in the Unicode database.
+*/
+#define UTF8_CATEGORY_UNASSIGNED                0x20000000
+
+/*!
+	\def UTF8_CATEGORY_COMPATIBILITY
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	functions, not found in the Unicode database.
+*/
+#define UTF8_CATEGORY_COMPATIBILITY             0x40000000
+
+/*!
+	\def UTF8_CATEGORY_IGNORE_GRAPHEME_CLUSTER
+	\brief Flag used for checking only the general category of code points at
+	the start of a grapheme cluster.
+*/
+#define UTF8_CATEGORY_IGNORE_GRAPHEME_CLUSTER   0x80000000
+
+/*!
+	\def UTF8_CATEGORY_ISCNTRL
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	`iscntrl` function.
+*/
+#define UTF8_CATEGORY_ISCNTRL \
+	(UTF8_CATEGORY_COMPATIBILITY | \
+	UTF8_CATEGORY_CONTROL)
+
+/*!
+	\def UTF8_CATEGORY_ISPRINT
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	`isprint` function.
+*/
+#define UTF8_CATEGORY_ISPRINT \
+	(UTF8_CATEGORY_COMPATIBILITY | \
+	UTF8_CATEGORY_LETTER | UTF8_CATEGORY_NUMBER | \
+	UTF8_CATEGORY_PUNCTUATION | UTF8_CATEGORY_SYMBOL | \
+	UTF8_CATEGORY_SEPARATOR)
+
+/*!
+	\def UTF8_CATEGORY_ISSPACE
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	`isspace` function.
+*/
+#define UTF8_CATEGORY_ISSPACE \
+	(UTF8_CATEGORY_COMPATIBILITY | \
+	UTF8_CATEGORY_SEPARATOR_SPACE)
+
+/*!
+	\def UTF8_CATEGORY_ISBLANK
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	`isblank` function.
+*/
+#define UTF8_CATEGORY_ISBLANK \
+	(UTF8_CATEGORY_COMPATIBILITY | \
+	UTF8_CATEGORY_SEPARATOR_SPACE | UTF8_CATEGORY_PRIVATE_USE)
+
+/*!
+	\def UTF8_CATEGORY_ISGRAPH
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	`isgraph` function.
+*/
+#define UTF8_CATEGORY_ISGRAPH \
+	(UTF8_CATEGORY_COMPATIBILITY | \
+	UTF8_CATEGORY_LETTER | UTF8_CATEGORY_NUMBER | \
+	UTF8_CATEGORY_PUNCTUATION | UTF8_CATEGORY_SYMBOL)
+
+/*!
+	\def UTF8_CATEGORY_ISPUNCT
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	`ispunct` function.
+*/
+#define UTF8_CATEGORY_ISPUNCT \
+	(UTF8_CATEGORY_COMPATIBILITY | \
+	UTF8_CATEGORY_PUNCTUATION | UTF8_CATEGORY_SYMBOL)
+
+/*!
+	\def UTF8_CATEGORY_ISALNUM
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	`isalnum` function.
+*/
+#define UTF8_CATEGORY_ISALNUM \
+	(UTF8_CATEGORY_COMPATIBILITY | \
+	UTF8_CATEGORY_LETTER | UTF8_CATEGORY_NUMBER)
+
+/*!
+	\def UTF8_CATEGORY_ISALPHA
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	`isalpha` function.
+*/
+#define UTF8_CATEGORY_ISALPHA \
+	(UTF8_CATEGORY_COMPATIBILITY | \
+	UTF8_CATEGORY_LETTER)
+
+/*!
+	\def UTF8_CATEGORY_ISUPPER
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	`isupper` function.
+*/
+#define UTF8_CATEGORY_ISUPPER \
+	(UTF8_CATEGORY_COMPATIBILITY | \
+	UTF8_CATEGORY_LETTER_UPPERCASE)
+
+/*!
+	\def UTF8_CATEGORY_ISLOWER
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	`islower` function.
+*/
+#define UTF8_CATEGORY_ISLOWER \
+	(UTF8_CATEGORY_COMPATIBILITY | \
+	UTF8_CATEGORY_LETTER_LOWERCASE)
+
+/*!
+	\def UTF8_CATEGORY_ISDIGIT
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	`isdigit` function.
+*/
+#define UTF8_CATEGORY_ISDIGIT \
+	(UTF8_CATEGORY_COMPATIBILITY | \
+	UTF8_CATEGORY_NUMBER)
+
+/*!
+	\def UTF8_CATEGORY_ISXDIGIT
+	\brief Flag used for maintaining backwards compatibility with POSIX
+	`isxdigit` function.
+*/
+#define UTF8_CATEGORY_ISXDIGIT \
+	(UTF8_CATEGORY_COMPATIBILITY | \
+	UTF8_CATEGORY_NUMBER | UTF8_CATEGORY_PRIVATE_USE)
+
+/*!
+	\}
+*/
+
+/*!
+	\addtogroup global-config
+	\{
+*/
+
+/*!
+	\def UTF8_WCHAR_SIZE
+	\brief Specifies the size of the `wchar_t` type. On Windows this is two
+	bytes, on POSIX systems it is four. If not specified on the command line,
+	the compiler tries to automatically determine the size of the `wchar_t` type
+	based on the environment.
+*/
+
+#ifndef UTF8_WCHAR_SIZE
+	#if (__SIZEOF_WCHAR_T__ == 4) || (WCHAR_MAX > UINT16_MAX) || (__WCHAR_MAX__ > UINT16_MAX)
+		#define UTF8_WCHAR_SIZE (4)
+	#else
+		#define UTF8_WCHAR_SIZE (2)
+	#endif
+#endif
+
+#if (UTF8_WCHAR_SIZE == 4)
+	/*!
+		\def UTF8_WCHAR_UTF32
+		\brief The `wchar_t` type is treated as UTF-32 (four byte fixed
+		encoding).
+	*/
+	#define UTF8_WCHAR_UTF32 (1)
+#elif (UTF8_WCHAR_SIZE == 2)
+	/*!
+		\def UTF8_WCHAR_UTF16
+		\brief The `wchar_t` type is treated as UTF-16 (two byte variable
+		length encoding).
+	*/
+	#define UTF8_WCHAR_UTF16 (1)
+#else
+	#error Invalid size for wchar_t type.
+#endif
+
+/*!
+	\def UTF8_API
+	\brief Calling convention for public functions.
+*/
+
+#ifndef UTF8_API
+	#ifdef __cplusplus
+		#define UTF8_API extern "C"
+	#else
+		#define UTF8_API
+	#endif
+#endif
+
+/*!
+	\}
+*/
+
+/*!
+	\addtogroup types
+	\{
+*/
+
+/*!
+	\var utf16_t
+	\brief UTF-16 encoded code point.
+*/
+typedef uint16_t utf16_t;
+
+/*!
+	\var unicode_t
+	\brief UTF-32 encoded code point.
+*/
+typedef uint32_t unicode_t;
+
+/*!
+	\}
+*/
+
+/*!
+	\addtogroup public
+	\{
+*/
+
+/*!
+	\brief Get the length in code points of a UTF-8 encoded string.
+
+	Example:
+
+	\code{.c}
+		uint8_t CheckPassword(const char* password)
+		{
+			size_t length = utf8len(password);
+			return (length == utf8len("hunter2"));
+		}
+	\endcode
+
+	\param[in]  text  UTF-8 encoded string.
+
+	\return Length in code points.
+*/
+UTF8_API size_t utf8len(const char* text);
+
+/*!
+	\brief Convert a UTF-16 encoded string to a UTF-8 encoded string.
+
+	\note This function should only be called directly if you are positive that
+	you are working with UTF-16 encoded text. If you're working with wide
+	strings, take a look at #widetoutf8 instead.
+
+	Example:
+
+	\code{.c}
+		uint8_t Player_SetNameUtf16(const utf16_t* name, size_t nameSize)
+		{
+			char buffer[256];
+			size_t buffer_size = 255;
+			size_t converted_size;
+			int32_t errors;
+
+			if ((converted_size = utf16toutf8(name, nameSize, buffer, buffer_size, &errors)) == 0 ||
+				errors != UTF8_ERR_NONE)
+			{
+				return 0;
+			}
+			buffer[converted_size] = 0;
+
+			return Player_SetName(converted_name);
+		}
+	\endcode
+
+	\param[in]   input       UTF-16 encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[out]  target      Output buffer for the result, can be NULL.
+	\param[in]   targetSize  Size of the output buffer in bytes.
+	\param[out]  errors      Output for errors.
+
+	\return Amount of bytes needed for storing output.
+
+	\retval #UTF8_ERR_NONE                    No errors.
+	\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.
+	\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.
+	\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.
+
+	\sa utf32toutf8
+	\sa widetoutf8
+*/
+UTF8_API size_t utf16toutf8(const utf16_t* input, size_t inputSize, char* target, size_t targetSize, int32_t* errors);
+
+/*!
+	\brief Convert a UTF-32 encoded string to a UTF-8 encoded string.
+
+	\note This function should only be called directly if you are positive that
+	you are working with UTF-32 encoded text. If you're working with wide
+	strings, take a look at #widetoutf8 instead.
+
+	Example:
+
+	\code{.c}
+		uint8_t Database_ExecuteQuery_Unicode(const unicode_t* query, size_t querySize)
+		{
+			char* converted = NULL;
+			size_t converted_size;
+			uint8_t result = 0;
+			int32_t errors;
+
+			if ((converted_size = utf32toutf8(query, querySize, NULL, 0, &errors)) == 0 ||
+				errors != UTF8_ERR_NONE)
+			{
+				goto cleanup;
+			}
+
+			converted = (char*)malloc(converted_size + 1);
+			utf32toutf8(query, querySize, converted, converted_size, NULL);
+			converted[converted_size] = 0;
+
+			result = Database_ExecuteQuery(converted);
+
+		cleanup:
+			if (converted != NULL)
+			{
+				free(converted);
+				converted = 0;
+			}
+
+			return result;
+		}
+	\endcode
+
+	\param[in]   input       UTF-32 encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[out]  target      Output buffer for the result, can be NULL.
+	\param[in]   targetSize  Size of the output buffer in bytes.
+	\param[out]  errors      Output for errors.
+
+	\return Amount of bytes needed for storing output.
+
+	\retval #UTF8_ERR_NONE                    No errors.
+	\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.
+	\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.
+	\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.
+
+	\sa utf16toutf8
+	\sa widetoutf8
+*/
+UTF8_API size_t utf32toutf8(const unicode_t* input, size_t inputSize, char* target, size_t targetSize, int32_t* errors);
+
+/*!
+	\brief Convert a wide string to a UTF-8 encoded string.
+
+	Depending on the platform, wide strings are either UTF-16 or UTF-32 encoded.
+	This function takes a wide string as input and automatically calls the
+	correct conversion function.
+	
+	This allows for a cross-platform treatment of wide text and is preferable to
+	using the UTF-16 or UTF-32 versions directly.
+
+	Example:
+
+	\code{.c}
+		texture_t Texture_Load_Wide(const wchar_t* input)
+		{
+			char* converted = NULL;
+			size_t converted_size;
+			size_t input_size = wcslen(input) * sizeof(wchar_t);
+			texture_t result = NULL;
+			int32_t errors;
+
+			if ((converted_size = widetoutf8(input, input_size, NULL, 0, &errors)) == 0 ||
+				errors != UTF8_ERR_NONE)
+			{
+				goto cleanup;
+			}
+
+			converted = (char*)malloc(converted_size + 1);
+			widetoutf8(input, input_size, converted, converted_size, NULL);
+			converted[converted_size / sizeof(wchar_t)] = 0;
+
+			result = Texture_Load(converted);
+
+		cleanup:
+			if (converted != NULL)
+			{
+				free(converted);
+				converted = NULL;
+			}
+
+			return result;
+		}
+	\endcode
+
+	\param[in]   input       Wide-encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[out]  target      Output buffer for the result, can be NULL.
+	\param[in]   targetSize  Size of the output buffer in bytes.
+	\param[out]  errors      Output for errors.
+
+	\return Amount of bytes needed for storing output.
+
+	\retval #UTF8_ERR_NONE                    No errors.
+	\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.
+	\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.
+	\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.
+
+	\sa utf8towide
+	\sa utf16toutf8
+	\sa utf32toutf8
+*/
+UTF8_API size_t widetoutf8(const wchar_t* input, size_t inputSize, char* target, size_t targetSize, int32_t* errors);
+
+/*!
+	\brief Convert a UTF-8 encoded string to a UTF-16 encoded string.
+
+	\note This function should only be called directly if you are positive that
+	you *must* convert to UTF-16, independent of platform. If you're working
+	with wide strings, take a look at #utf8towide instead.
+
+	Erroneous byte sequences such as missing or illegal bytes or overlong
+	encoding of code points (e.g. using five bytes to encode a sequence that
+	can be represented by two bytes) are converted to the replacement
+	character U+FFFD.
+
+	Code points outside the Basic Multilingual Plane (BMP) will be converted to
+	surrogate pairs, which use four bytes instead of two.
+
+	Example:
+
+	\code{.c}
+		void Font_DrawText(int x, int y, const char* text)
+		{
+			utf16_t buffer[256];
+			size_t buffer_size = 255 * sizeof(utf16_t);
+			int32_t errors;
+			
+			size_t converted_size = utf8toutf16(text, strlen(text), buffer, buffer_size, &errors);
+			if (converted_size > 0 &&
+				errors == UTF8_ERR_NONE)
+			{
+				Legacy_DrawText(g_FontCurrent, x, y, (unsigned short*)buffer, converted_size / sizeof(utf16_t));
+			}
+		}
+	\endcode
+
+	\param[in]   input       UTF-8 encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[out]  target      Output buffer for the result, can be NULL.
+	\param[in]   targetSize  Size of the output buffer in bytes.
+	\param[out]  errors      Output for errors.
+
+	\return Amount of bytes needed for storing output.
+
+	\retval #UTF8_ERR_NONE                    No errors.
+	\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.
+	\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.
+	\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.
+
+	\sa utf8towide
+	\sa utf8toutf32
+*/
+UTF8_API size_t utf8toutf16(const char* input, size_t inputSize, utf16_t* target, size_t targetSize, int32_t* errors);
+
+/*!
+	\brief Convert a UTF-8 encoded string to a UTF-32 encoded string.
+
+	\note This function should only be called directly if you are positive that
+	you *must* convert to UTF-32, independent of platform. If you're working
+	with wide strings, take a look at #utf8towide instead.
+
+	Erroneous byte sequences such as missing or illegal bytes or overlong
+	encoding of code points (e.g. using five bytes to encode a sequence that
+	can be represented by two bytes) are converted to the replacement
+	character U+FFFD.
+
+	Example:
+
+	\code{.c}
+		void TextField_AddCharacter(const char* encoded)
+		{
+			unicode_t code_point = 0;
+			int32_t errors;
+
+			utf8toutf32(encoded, strlen(encoded), &code_point, sizeof(unicode_t), &errors);
+			if (errors == UTF8_ERR_NONE)
+			{
+				TextField_AddCodePoint(code_point);
+			}
+		}
+	\endcode
+
+	\param[in]   input       UTF-8 encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[out]  target      Output buffer for the result, can be NULL.
+	\param[in]   targetSize  Size of the output buffer in bytes.
+	\param[out]  errors      Output for errors.
+
+	\return Amount of bytes needed for storing output.
+
+	\retval #UTF8_ERR_NONE                    No errors.
+	\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.
+	\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.
+	\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.
+
+	\sa utf8towide
+	\sa utf8toutf16
+*/
+UTF8_API size_t utf8toutf32(const char* input, size_t inputSize, unicode_t* target, size_t targetSize, int32_t* errors);
+
+/*!
+	\brief Convert a UTF-8 encoded string to a wide string.
+
+	Depending on the platform, wide strings are either UTF-16 or UTF-32 encoded.
+	This function takes a UTF-8 encoded string as input and automatically calls
+	the correct conversion function.
+
+	This allows for a cross-platform treatment of wide text and is preferable to
+	using the UTF-16 or UTF-32 versions directly.
+
+	Erroneous byte sequences such as missing or illegal bytes or overlong
+	encoding of code points (e.g. using five bytes to encode a sequence that
+	can be represented by two bytes) are converted to the replacement
+	character U+FFFD.
+
+	\note Code points outside the Basic Multilingual Plane (BMP) are converted
+	to surrogate pairs when using UTF-16. This means that strings containing
+	characters outside the BMP converted on a platform with UTF-32 wide strings
+	are *not* compatible with platforms with UTF-16 wide strings.
+
+	\par Hence, it is preferable to store all data as UTF-8 and only convert to
+	wide strings when required by a third-party interface.
+
+	Example:
+
+	\code{.c}
+		void Window_SetTitle(void* windowHandle, const char* text)
+		{
+			size_t input_size = strlen(text);
+			wchar_t* converted = NULL;
+			size_t converted_size;
+			int32_t errors;
+
+			converted_size = utf8towide(text, input_size, NULL, 0, &errors);
+			if (converted_size == 0 ||
+				errors != UTF8_ERR_NONE)
+			{
+				goto cleanup;
+			}
+
+			converted = (wchar_t*)malloc(converted_size + sizeof(wchar_t));
+			utf8towide(text, input_size, converted, converted_size, NULL);
+			converted[converted_size / sizeof(wchar_t)] = 0;
+
+			SetWindowTextW((HWND)windowHandle, converted);
+
+		cleanup:
+			if (converted != NULL)
+			{
+				free(converted);
+				converted = NULL;
+			}
+		}
+	\endcode
+
+	\param[in]   input       UTF-8 encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[out]  target      Output buffer for the result, can be NULL.
+	\param[in]   targetSize  Size of the output buffer in bytes.
+	\param[out]  errors      Output for errors.
+
+	\return Amount of bytes needed for storing output.
+
+	\retval #UTF8_ERR_NONE                    No errors.
+	\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.
+	\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.
+	\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.
+
+	\sa widetoutf8
+	\sa utf8toutf16
+	\sa utf8toutf32
+*/
+UTF8_API size_t utf8towide(const char* input, size_t inputSize, wchar_t* target, size_t targetSize, int32_t* errors);
+
+/*!
+	\brief Seek into a UTF-8 encoded string.
+
+	Working with UTF-8 encoded strings can be tricky due to the nature of the
+	variable-length encoding. Because one character no longer equals one byte,
+	it can be difficult to skip around in a UTF-8 encoded string without
+	decoding the code points.
+
+	This function provides an interface similar to `fseek` in order to enable
+	skipping to another part of the string.
+
+	\note `textStart` must come before `text` in memory when seeking from the
+	current or end position.
+
+	Example:
+
+	\code{.c}
+		const char* text = "Press \xE0\x80\x13 to continue.";
+		const char fixed[1024];
+		const char* commandStart;
+		const char* commandEnd;
+
+		memset(fixed, 0, sizeof(fixed));
+
+		commandStart = strstr(text, "\xE0\x80\x13");
+		if (commandStart == 0)
+		{
+			return 0;
+		}
+
+		strncpy(fixed, text, commandStart - text);
+		strcat(fixed, "ENTER");
+
+		commandEnd = utf8seek(commandStart, strlen(commandStart), text, 1, SEEK_CUR);
+		if (commandEnd != commandStart)
+		{
+			strcat(fixed, commandEnd);
+		}
+	\endcode
+
+	\param[in]  text       Input string.
+	\param[in]  textSize   Size of the complete input string in bytes, starting from `textStart`.
+	\param[in]  textStart  Start of input string.
+	\param[in]  offset     Requested offset in code points.
+	\param[in]  direction  Direction to seek in.
+	\arg `SEEK_SET` Offset is from the start of the string.
+	\arg `SEEK_CUR` Offset is from the current position of the string.
+	\arg `SEEK_END` Offset is from the end of the string.
+
+	\return Pointer to offset string or no change on error.
+
+	\sa utf8iscategory
+*/
+UTF8_API const char* utf8seek(const char* text, size_t textSize, const char* textStart, off_t offset, int direction);
+
+/*!
+	\brief Returns the environment's locale as an enum value.
+
+	This function retrieves the (thread-local) environment locale as an enum
+	value in the \ref locales "list of locales". This value can be used with
+	functions in this library that change behavior on certain inputs, depending
+	on the specified locale.
+
+	Unfortunately, no cross-platform way of setting and retrieving the system
+	locale is available without adding dependencies to the library. Please refer
+	to your operating system's manual to determine how to setup the system
+	locale on your target system.
+
+	\warning This function should not be used as a replacement for platform-
+	specific methods for retrieving the locale. Its intended usage is to
+	"guess" the desired locale by looking at the system locale.
+
+	Example:
+
+	\code{.c}
+		uint8_t Employee_PrintNames(const char** names, size_t nameCount)
+		{
+			size_t locale = utf8envlocale();
+			char buffer[256];
+			size_t buffer_size = 255;
+			int32_t errors;
+			size_t i;
+
+			for (i = 0; i < nameCount; ++i)
+			{
+				size_t buffer_filled;
+
+				memset(buffer, 0, buffer_size);
+
+				if ((buffer_filled = utf8toupper(names[i], strlen(names[i]), buffer, buffer_size, locale, &errors)) == 0 ||
+					errors != UTF8_ERR_NONE)
+				{
+					return 0;
+				}
+
+				Log_Print(buffer, buffer_filled);
+			}
+
+			return 1;
+		}
+	\endcode
+
+	\return A specific \ref locales "locale" or #UTF8_LOCALE_DEFAULT.
+
+	\sa utf8toupper
+	\sa utf8tolower
+	\sa utf8totitle
+	\sa utf8casefold
+*/
+UTF8_API size_t utf8envlocale();
+
+/*!
+	\brief Convert UTF-8 encoded text to uppercase.
+
+	This function allows conversion of UTF-8 encoded strings to uppercase
+	without first changing the encoding to UTF-32. Conversion is fully compliant
+	with the Unicode 7.0 standard.
+
+	Although most code points can be converted in-place, there are notable
+	exceptions. For example, U+00DF (LATIN SMALL LETTER SHARP S) maps to
+	"U+0053 U+0053" (LATIN CAPITAL LETTER S and LATIN CAPITAL LETTER S) when
+	converted to uppercase. Therefor, it is advised to first determine the size
+	in bytes of the output by calling the function with a NULL output buffer.
+
+	Only a handful of scripts make a distinction between upper and lowercase.
+	In addition to modern scripts, such as Latin, Greek, Armenian and Cyrillic,
+	a few historic or archaic scripts have case. The vast majority of scripts
+	do not have case distinctions.
+
+	\note Case mapping is not reversible. That is, `toUpper(toLower(x))
+	!= toLower(toUpper(x))`.
+
+	\warning Certain code points (or combinations of code points) apply rules
+	based on the locale. For more information about these exceptional
+	code points, please refer to the Unicode standard:
+	ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
+	
+
+	Example:
+
+	\code{.c}
+		void Button_Draw(int32_t x, int32_t y, const char* text)
+		{
+			size_t input_size = strlen(text);
+			char* converted = NULL;
+			size_t converted_size;
+			int32_t text_box_width, text_box_height;
+			int32_t errors;
+
+			if ((utf8toupper(text, input_size, NULL, 0, UTF8_LOCALE_DEFAULT, &errors)) == 0 ||
+				errors != UTF8_ERR_NONE)
+			{
+				goto cleanup;
+			}
+
+			converted = (char*)malloc(converted_size + 1);
+
+			if (converted == NULL ||
+				utf8toupper(text, input_size, converted, converted_size, UTF8_LOCALE_DEFAULT, &errors) == 0 ||
+				errors != UTF8_ERR_NONE)
+			{
+				goto cleanup;
+			}
+
+			converted[converted_size] = 0;
+
+			Font_GetTextDimensions(converted, &text_box_width, &text_box_height);
+
+			Draw_BoxFilled(x - 4, y - 4, text_box_width + 8, text_box_height + 8, 0x088A08);
+			Draw_BoxOutline(x - 4, y - 4, text_box_width + 8, text_box_height + 8, 0xA9F5A9);
+			Font_DrawText(x + 2, y + 1, converted, 0x000000);
+			Font_DrawText(x, y, converted, 0xFFFFFF);
+
+		cleanup:
+			if (converted != NULL)
+			{
+				free(converted);
+				converted = NULL;
+			}
+		}
+	\endcode
+
+	\param[in]   input       UTF-8 encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[out]  target      Output buffer for the result, can be NULL.
+	\param[in]   targetSize  Size of the output buffer in bytes.
+	\param[in]   locale      Enables locale-specific behavior in the implementation. \ref locales "List of valid locales."
+	\param[out]  errors      Output for errors.
+
+	\return Amount of bytes needed to contain output.
+
+	\retval #UTF8_ERR_NONE                    No errors.
+	\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.
+	\retval #UTF8_ERR_INVALID_LOCALE          Invalid locale specified.
+	\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.
+	\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.
+
+	\sa utf8tolower
+	\sa utf8totitle
+	\sa utf8casefold
+*/
+UTF8_API size_t utf8toupper(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors);
+
+/*!
+	\brief Convert UTF-8 encoded text to lowercase.
+
+	This function allows conversion of UTF-8 encoded strings to lowercase
+	without first changing the encoding to UTF-32. Conversion is fully compliant
+	with the Unicode 7.0 standard.
+
+	Although most code points can be converted to lowercase in-place, there are
+	notable exceptions. For example, U+0130 (LATIN CAPITAL LETTER I WITH DOT
+	ABOVE) maps to "U+0069 U+0307" (LATIN SMALL LETTER I and COMBINING DOT
+	ABOVE) when converted to lowercase. Therefor, it is advised to first
+	determine the size in bytes of the output by calling the function with a
+	NULL output buffer.
+
+	Only a handful of scripts make a distinction between upper- and lowercase.
+	In addition to modern scripts, such as Latin, Greek, Armenian and Cyrillic,
+	a few historic or archaic scripts have case. The vast majority of scripts do
+	not have case distinctions.
+
+	\note Case mapping is not reversible. That is, `toUpper(toLower(x))
+	!= toLower(toUpper(x))`.
+
+	\warning Certain code points (or combinations of code points) apply rules
+	based on the locale. For more information about these exceptional
+	code points, please refer to the Unicode standard:
+	ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
+
+	Example:
+
+	\code{.c}
+		author_t* Author_ByName(const char* name)
+		{
+			author_t* result = NULL;
+			size_t name_size = strlen(name);
+			char* converted = NULL;
+			size_t converted_size;
+			int32_t errors;
+			size_t i;
+			
+			if ((converted_size = utf8tolower(name, name_size, NULL, 0, UTF8_LOCALE_DEFAULT, &errors)) == 0 ||
+				errors != UTF8_ERR_NONE)
+			{
+				goto cleanup;
+			}
+
+			converted = (char*)malloc(converted_size + 1);
+
+			if (converted == NULL ||
+				utf8tolower(name, name_size, converted, converted_size, UTF8_LOCALE_DEFAULT, &errors) == 0 ||
+				errors != UTF8_ERR_NONE)
+			{
+				goto cleanup;
+			}
+
+			converted[converted_size] = 0;
+			
+			for (i = 0; i < g_AuthorCount; ++i)
+			{
+				if (!strcmp(g_Author[i].name, converted))
+				{
+					result = &g_Author[i];
+					break;
+				}
+			}
+		
+		cleanup:
+			if (converted != NULL)
+			{
+				free(converted);
+				converted = NULL;
+			}
+			return result;
+		}
+	\endcode
+
+	\param[in]   input       UTF-8 encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[out]  target      Output buffer for the result, can be NULL.
+	\param[in]   targetSize  Size of the output buffer in bytes.
+	\param[in]   locale      Enables locale-specific behavior in the implementation. \ref locales "List of valid locales."
+	\param[out]  errors      Output for errors.
+
+	\return Amount of bytes needed for storing output.
+
+	\retval #UTF8_ERR_NONE                    No errors.
+	\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.
+	\retval #UTF8_ERR_INVALID_LOCALE          Invalid locale specified.
+	\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.
+	\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.
+
+	\sa utf8toupper
+	\sa utf8totitle
+	\sa utf8casefold
+*/
+UTF8_API size_t utf8tolower(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors);
+
+/*!
+	\brief Convert UTF-8 encoded text to titlecase.
+
+	This function allows conversion of UTF-8 encoded strings to titlecase
+	without first changing the encoding to UTF-32. Conversion is fully compliant
+	with the Unicode 7.0 standard.
+
+	Titlecase requires a bit more explanation than uppercase and lowercase,
+	because it is not a common text transformation. Titlecase uses uppercase
+	for the first letter of each word and lowercase for the rest. Words are
+	defined as "collections of code points with general category Lu, Ll, Lt, Lm
+	or Lo according to the Unicode database".
+
+	Effectively, any type of punctuation can break up a word, even if this is
+	not grammatically valid. This happens because the titlecasing algorithm
+	does not and cannot take grammar rules into account.
+
+	Text                                 | Titlecase
+	-------------------------------------|-------------------------------------
+	The running man                      | The Running Man
+	NATO Alliance                        | Nato Alliance
+	You're amazing at building libraries | You'Re Amazing At Building Libraries
+	
+	Although most code points can be converted to titlecase in-place, there are
+	notable exceptions. For example, U+00DF (LATIN SMALL LETTER SHARP S) maps to
+	"U+0053 U+0073" (LATIN CAPITAL LETTER S and LATIN SMALL LETTER S) when
+	converted to titlecase. Therefor, it is advised to first determine the size
+	in bytes of the output by calling the function with a NULL output buffer.
+
+	Only a handful of scripts make a distinction between upper- and lowercase.
+	In addition to modern scripts, such as Latin, Greek, Armenian and Cyrillic,
+	a few historic or archaic scripts have case. The vast majority of scripts
+	do not have case distinctions.
+
+	\note Case mapping is not reversible. That is, `toUpper(toLower(x))
+	!= toLower(toUpper(x))`.
+
+	\warning Certain code points (or combinations of code points) apply rules
+	based on the locale. For more information about these exceptional
+	code points, please refer to the Unicode standard:
+	ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
+
+	Example:
+
+	\code{.c}
+		void Book_SetTitle(book_t* book, const char* title)
+		{
+			size_t converted_size;
+			int32_t errors;
+			size_t i;
+
+			if ((converted_size = utf8totitle(title, strlen(title), book->title, sizeof(book->title) - 1, UTF8_LOCALE_DEFAULT, &errors)) == 0 ||
+				errors != UTF8_ERR_NONE)
+			{
+				memset(book->title, 0, sizeof(book->title));
+
+				return;
+			}
+			book->title[converted_size] = 0;
+		}
+	\endcode
+
+	\param[in]   input       UTF-8 encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[out]  target      Output buffer for the result, can be NULL.
+	\param[in]   targetSize  Size of the output buffer in bytes.
+	\param[in]   locale      Enables locale-specific behavior in the implementation. \ref locales "List of valid locales."
+	\param[out]  errors      Output for errors.
+
+	\return Amount of bytes needed for storing output.
+
+	\retval #UTF8_ERR_NONE                    No errors.
+	\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.
+	\retval #UTF8_ERR_INVALID_LOCALE          Invalid locale specified.
+	\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.
+	\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.
+
+	\sa utf8tolower
+	\sa utf8toupper
+	\sa utf8casefold
+*/
+UTF8_API size_t utf8totitle(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors);
+
+/*!
+	\brief Remove case distinction from UTF-8 encoded text.
+
+	Case folding is the process of eliminating differences between code points
+	concerning case mapping. It is most commonly used for comparing strings in a
+	case-insensitive manner. Conversion is fully compliant with the Unicode 7.0
+	standard.
+
+	Although similar to lowercasing text, there are significant differences.
+	For one, case folding does _not_ take locale into account when converting.
+	In some cases, case folding can be up to 20% faster than lowercasing the
+	same text, but the result cannot be treated as correct lowercased text.
+
+	Only two locale-specific exception are made when case folding text.
+	In Turkish, U+0049 LATIN CAPITAL LETTER I maps to U+0131 LATIN SMALL LETTER
+	DOTLESS I and U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE maps to U+0069
+	LATIN SMALL LETTER I.
+
+	Although most code points can be case folded in-place, there are notable
+	exceptions. For example, U+0130 (LATIN CAPITAL LETTER I WITH DOT ABOVE) maps
+	to "U+0069 U+0307" (LATIN SMALL LETTER I and COMBINING DOT ABOVE) when
+	converted to lowercase. Therefor, it is advised to first determine the size
+	in bytes of the output by calling the function with a NULL output buffer.
+
+	Only a handful of scripts make a distinction between upper- and lowercase.
+	In addition to modern scripts, such as Latin, Greek, Armenian and Cyrillic,
+	a few historic or archaic scripts have case. The vast majority of scripts
+	do not have case distinctions.
+
+	Example:
+
+	\code{.c}
+		int32_t Command_ParseCommand(const char* argument)
+		{
+			char* buffer = NULL;
+			size_t buffer_size = 0;
+			int32_t errors;
+			int32_t result = 0;
+
+			if ((buffer_size = utf8casefold(argument, strlen(argument), NULL, 0, UTF8_LOCALE_DEFAULT, &errors)) == 0 ||
+				errors != UTF8_ERR_NONE)
+			{
+				result = -1;
+
+				goto cleanup;
+			}
+
+			buffer = (char*)malloc(buffer_size);
+
+			if (buffer == NULL ||
+				utf8casefold(argument, strlen(argument), buffer, buffer_size, UTF8_LOCALE_DEFAULT, &errors) == 0 ||
+				errors != UTF8_ERR_NONE)
+			{
+				result = -1;
+
+				goto cleanup;
+			}
+
+			if (!strncmp(buffer, "-username", strlen("-username")))
+			{
+				result = eCommand_Username;
+			}
+			else if (
+				!strncmp(buffer, "-password", strlen("-password")))
+			{
+				result = eCommand_Password;
+			}
+			else if (
+				!strncmp(buffer, "-message", strlen("-message")))
+			{
+				result = eCommand_Message;
+			}
+
+		cleanup:
+			if (buffer != NULL)
+			{
+				free(buffer);
+				buffer = NULL;
+			}
+
+			return result;
+		}
+	\endcode
+
+	\param[in]   input       UTF-8 encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[out]  target      Output buffer for the result, can be NULL.
+	\param[in]   targetSize  Size of the output buffer in bytes.
+	\param[in]   locale      Enables locale-specific behavior in the implementation. \ref locales "List of valid locales."
+	\param[out]  errors      Output for errors.
+
+	\return Amount of bytes needed for storing output.
+
+	\retval #UTF8_ERR_NONE                    No errors.
+	\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.
+	\retval #UTF8_ERR_INVALID_LOCALE          Invalid locale specified.
+	\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.
+	\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.
+
+	\sa utf8tolower
+	\sa utf8toupper
+	\sa utf8totitle
+*/
+UTF8_API size_t utf8casefold(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors);
+
+/*!
+	\brief Check if a string is stable in the specified Unicode Normalization
+	Form.
+
+	This function can be used as a preprocessing step, before attempting to
+	normalize a string. Normalization is a very expensive process, it is often
+	cheaper to first determine if the string is unstable in the requested
+	normalization form.
+
+	The result of the check will be YES if the string is stable and MAYBE or NO
+	if it is unstable. If the result is MAYBE, the string does not necessarily
+	have to be normalized.
+
+	If the result is unstable, the offset parameter is set to the offset for the
+	first unstable code point. If the string is stable, the offset is equivalent
+	to the length of the string in bytes.
+
+	You must specify the desired Unicode Normalization Form by using a
+	combination of flags:
+
+	Unicode                      | Flags
+	---------------------------- | ---------------------------------------------------------
+	Normalization Form C (NFC)   | #UTF8_NORMALIZE_COMPOSE
+	Normalization Form KC (NFKC) | #UTF8_NORMALIZE_COMPOSE + #UTF8_NORMALIZE_COMPATIBILITY
+	Normalization Form D (NFD)   | #UTF8_NORMALIZE_DECOMPOSE
+	Normalization Form KD (NFKD) | #UTF8_NORMALIZE_DECOMPOSE + #UTF8_NORMALIZE_COMPATIBILITY
+
+	For more information, please review [Unicode Standard Annex #15 - Unicode
+	Normalization Forms](http://www.unicode.org/reports/tr15/).
+
+	Example:
+
+	\code{.c}
+		uint8_t Text_InspectComposed(const char* text)
+		{
+			const char* src = text;
+			size_t src_size = strlen(text);
+			size_t offset;
+			size_t total_offset;
+
+			if (utf8isnormalized(src, src_size, UTF8_NORMALIZE_COMPOSE, &offset) == UTF8_NORMALIZATION_RESULT_YES)
+			{
+				printf("Clean!\n");
+
+				return 1;
+			}
+
+			total_offset = offset;
+
+			do
+			{
+				const char* next;
+
+				printf("Unstable at byte %d\n", total_offset);
+
+				next = utf8seek(src, text, 1, SEEK_CUR);
+				if (next == src)
+				{
+					break;
+				}
+
+				total_offset += offset;
+
+				src = next;
+				src_size -= next - src;
+			}
+			while (utf8isnormalized(src, src_size, UTF8_NORMALIZE_COMPOSE, &offset) != UTF8_NORMALIZATION_RESULT_YES);
+
+			return 0;
+		}
+	\endcode
+
+	\param[in]   input       UTF-8 encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[in]   flags       Desired normalization form. Must be a combination of \ref normalization "normalization flags".
+	\param[out]  offset      Offset to first unstable code point or length of input in bytes if stable.
+
+	\retval #UTF8_NORMALIZATION_RESULT_YES    Input is stable and does not have to be normalized.
+	\retval #UTF8_NORMALIZATION_RESULT_MAYBE  Input is unstable, but normalization may be skipped.
+	\retval #UTF8_NORMALIZATION_RESULT_NO     Input is unstable and must be normalized.
+
+	\sa utf8normalize
+*/
+UTF8_API uint8_t utf8isnormalized(const char* input, size_t inputSize, size_t flags, size_t* offset);
+
+/*!
+	\brief Normalize a string to the specified Unicode Normalization Form.
+
+	The Unicode standard defines two standards for equivalence between
+	characters: canonical and compatibility equivalence. Canonically equivalent
+	characters and sequence represent the same abstract character and must be
+	rendered with the same appearance and behavior. Compatibility equivalent
+	characters have a weaker equivalence and may be rendered differently.
+
+	Unicode Normalization Forms are formally defined standards that can be used
+	to test whether any two strings of characters are equivalent to each other.
+	This equivalence may be canonical or compatibility.
+
+	The algorithm puts all combining marks into a specified order and uses the
+	rules for decomposition and composition to transform the string into one of
+	four Unicode Normalization Forms. A binary comparison can then be used to
+	determine equivalence.
+
+	These are the Unicode Normalization Forms:
+
+	Form                         | Description
+	---------------------------- | ---------------------------------------------
+	Normalization Form D (NFD)   | Canonical decomposition
+	Normalization Form C (NFC)   | Canonical decomposition, followed by canonical composition
+	Normalization Form KD (NFKD) | Compatibility decomposition
+	Normalization Form KC (NFKC) | Compatibility decomposition, followed by canonical composition
+
+	`utf8normalize` can be used to transform text into one of these forms. You
+	must specify the desired Unicode Normalization Form by using a combination
+	of flags:
+
+	Form                          | Flags
+	----------------------------- | ---------------------------------------------------------
+	Normalization Form D (NFD)    | #UTF8_NORMALIZE_DECOMPOSE
+	Normalization Form C (NFC)    | #UTF8_NORMALIZE_COMPOSE
+	Normalization Form KD (NFKD)  | #UTF8_NORMALIZE_DECOMPOSE + #UTF8_NORMALIZE_COMPATIBILITY
+	Normalization Form KC (NFKC)  | #UTF8_NORMALIZE_COMPOSE + #UTF8_NORMALIZE_COMPATIBILITY
+
+	For more information, please review [Unicode Standard Annex #15 - Unicode
+	Normalization Forms](http://www.unicode.org/reports/tr15/).
+
+	\note Unnormalized text is rare in the wild. As an example, *all* text
+	found on the Internet as HTML source code must be encoded as NFC, as
+	specified by the W3C.
+
+	Example:
+
+	\code{.c}
+		void Font_RenderTextNormalized(const char* input)
+		{
+			const char* src = NULL;
+			const char* src_start;
+			size_t src_size;
+			char* converted = NULL;
+			size_t converted_size = 0;
+			size_t input_size = strlen(input);
+
+			if (utf8isnormalized(input, input_size, UTF8_NORMALIZE_COMPOSE, NULL) != UTF8_NORMALIZATION_RESULT_YES)
+			{
+				int32_t errors;
+
+				converted_size = utf8normalize(input, input_size, NULL, 0, UTF8_NORMALIZE_COMPOSE, &errors);
+				if (converted_size > 0 &&
+					errors == UTF8_ERR_NONE)
+				{
+					converted = (char*)malloc(converted_size + 1);
+					utf8normalize(input, input_size, converted, converted_size, UTF8_NORMALIZE_COMPOSE, NULL);
+					converted[converted_size] = 0;
+
+					src = (const char*)converted;
+					src_size = converted_size;
+				}
+			}
+
+			if (src == NULL)
+			{
+				src = (const char*)input;
+				src_size = input_size;
+			}
+
+			src_start = src;
+
+			while (src_size > 0)
+			{
+				const char* next;
+				int32_t errors;
+
+				next = utf8seek(src, src_size, src_start, 1, SEEK_CUR);
+				if (next == src)
+				{
+					break;
+				}
+
+				unicode_t code_point;
+				utf8toutf32(src, (size_t)(next - src), &code_point, sizeof(unicode_t), &errors);
+				if (errors != UTF8_ERR_NONE)
+				{
+					break;
+				}
+
+				Font_RenderCodePoint(code_point);
+
+				src_size -= next - src;
+				src = next;
+			}
+
+			if (converted != NULL)
+			{
+				free(converted);
+				converted = NULL;
+			}
+		}
+	\endcode
+
+	\param[in]   input       UTF-8 encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[out]  target      Output buffer for the result, can be NULL.
+	\param[in]   targetSize  Size of the output buffer in bytes.
+	\param[in]   flags       Desired normalization form. Must be a combination of #UTF8_NORMALIZE_COMPOSE, #UTF8_NORMALIZE_DECOMPOSE and #UTF8_NORMALIZE_COMPATIBILITY.
+	\param[out]  errors      Output for errors.
+
+	\return Amount of bytes needed for storing output.
+
+	\retval #UTF8_ERR_NONE                    No errors.
+	\retval #UTF8_ERR_INVALID_FLAG            Invalid combination of flags was specified.
+	\retval #UTF8_ERR_INVALID_DATA            Failed to decode data.
+	\retval #UTF8_ERR_OVERLAPPING_PARAMETERS  Input and output buffers overlap in memory.
+	\retval #UTF8_ERR_NOT_ENOUGH_SPACE        Target buffer size is insufficient for result.
+
+	\sa utf8isnormalized
+*/
+UTF8_API size_t utf8normalize(const char* input, size_t inputSize, char* target, size_t targetSize, size_t flags, int32_t* errors);
+
+/*!
+	\brief Check if the input string conforms to the category specified by the
+	flags.
+
+	This function can be used to check if the code points in a string are part
+	of a category. Valid flags are members of the
+	\ref category "list of categories". The category for a code point is
+	defined as part of the entry in UnicodeData.txt, the data file for the
+	Unicode code point database.
+
+	\note The function is _greedy_. This means it will try to match as many
+	code points with the matching category flags as possible and return the
+	offset in the input in bytes. If this is undesired behavior, use `utf8seek`
+	to seek in the input first before matching it with the category flags.
+
+	By default, the function will treat grapheme clusters as a single code
+	point. This means that the following string:
+
+	Code point | Canonical combining class | General category      | Name
+	---------- | ------------------------- | --------------------- | ----------------------
+	U+0045     | 0                         | Lu (Uppercase letter) | LATIN CAPITAL LETTER E
+	U+0300     | 230                       | Mn (Non-spacing mark) | COMBINING GRAVE ACCENT
+
+	Will match with #UTF8_CATEGORY_LETTER_UPPERCASE in its entirety, because
+	the COMBINING GRAVE ACCENT is treated as part of the grapheme cluster. This
+	is useful when e.g. creating a text parser, because you do not have to
+	normalize the text first.
+
+	If this is undesired behavior, specify the
+	#UTF8_CATEGORY_IGNORE_GRAPHEME_CLUSTER flag.
+
+	\warning In order to maintain backwards compatibility with POSIX functions
+	like `isdigit` and `isspace`, compatibility flags have been provided. Note,
+	however, that the result is only guaranteed to be correct for code points
+	in the Basic Latin range, between U+0000 and 0+007F. Combining a
+	compatibility flag with a regular category flag will result in undefined
+	behavior.
+
+	Example:
+
+	\code{.c}
+		const char* Parser_NextIdentifier(char** output, size_t* outputSize, const char* input, size_t inputSize)
+		{
+			const char* src = input;
+			size_t src_size = inputSize;
+			size_t whitespace_size;
+			size_t identifier_size;
+	
+			whitespace_size = utf8iscategory(src, src_size, UTF8_CATEGORY_SEPARATOR_SPACE);
+			if (whitespace_size == 0)
+			{
+				whitespace_size = utf8iscategory(src, src_size, UTF8_CATEGORY_ISSPACE);
+			}
+
+			if (whitespace_size > 0)
+			{
+				if (whitespace_size >= src_size)
+				{
+					return src + src_size;
+				}
+
+				src += whitespace_size;
+				src_size -= whitespace_size;
+			}
+
+			identifier_size = utf8iscategory(src, src_size, UTF8_CATEGORY_LETTER | UTF8_CATEGORY_PUNCTUATION_CONNECTOR | UTF8_CATEGORY_PUNCTUATION_DASH);
+			if (identifier_size == 0)
+			{
+				return src;
+			}
+
+			*output = (char*)malloc(identifier_size + 1);
+			memcpy(*output, src, identifier_size);
+			(*output)[identifier_size] = 0;
+			*outputSize = identifier_size;
+
+			if (identifier_size >= src_size)
+			{
+				return src + src_size;
+			}
+
+			return src + identifier_size;
+		}
+	\endcode
+
+	\param[in]   input       UTF-8 encoded string.
+	\param[in]   inputSize   Size of the input in bytes.
+	\param[in]   flags       Requested category. Must be a combination of \ref category "category flags" or a single compatibility flag.
+
+	\return Number of bytes in the input that conform to the specified category flags.
+
+	\sa utf8seek
+*/
+UTF8_API size_t utf8iscategory(const char* input, size_t inputSize, size_t flags);
+
+/*!
+	\}
+*/
+
+#endif /* _UTF8REWIND_H_ */
+ third_party/utf8rewind/source/internal/base.h view
@@ -0,0 +1,120 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _UTF8REWIND_INTERNAL_BASE_H_
+#define _UTF8REWIND_INTERNAL_BASE_H_
+
+/*!
+	\file
+	\brief Base header for internal interface.
+
+	\cond INTERNAL
+*/
+
+#include "utf8rewind.h"
+
+#if defined(__GNUC__) && !defined(COMPILER_ICC)
+	#define UTF8_UNUSED(_parameter) _parameter __attribute__ ((unused))
+#else
+	#define UTF8_UNUSED(_parameter) _parameter
+#endif
+
+#define UTF8_SET_ERROR(_error) \
+	if (errors != 0) { *errors = UTF8_ERR_ ## _error; }
+
+/* Validates input before transforming */
+/* Check for parameter overlap using the separating axis theorem */
+
+#define UTF8_VALIDATE_PARAMETERS_CHAR(_inputType, _result) \
+	if (input == 0) { \
+		UTF8_SET_ERROR(INVALID_DATA); \
+		return _result; \
+	} \
+	else if (inputSize < sizeof(_inputType)) { \
+		if (target != 0) { \
+			if (targetSize < 3) { \
+				UTF8_SET_ERROR(NOT_ENOUGH_SPACE); \
+				return _result; \
+			} \
+			memcpy(target, REPLACEMENT_CHARACTER_STRING, REPLACEMENT_CHARACTER_STRING_LENGTH); \
+		} \
+		UTF8_SET_ERROR(INVALID_DATA); \
+		return _result + REPLACEMENT_CHARACTER_STRING_LENGTH; \
+	} \
+	if (target != 0 && targetSize == 0) { \
+		UTF8_SET_ERROR(NOT_ENOUGH_SPACE); \
+		return _result; \
+	} \
+	if ((char*)input == target) { \
+		UTF8_SET_ERROR(OVERLAPPING_PARAMETERS); \
+		return _result; \
+	} \
+	{ \
+		char* input_center = (char*)input + (inputSize / 2); \
+		char* target_center = target + (targetSize / 2); \
+		size_t delta = (size_t)((input_center > target_center) ? (input_center - target_center) : (target_center - input_center)); \
+		if (delta < (inputSize + targetSize) / 2) { \
+			UTF8_SET_ERROR(OVERLAPPING_PARAMETERS); \
+			return _result; \
+		} \
+	}
+
+#define UTF8_VALIDATE_PARAMETERS(_inputType, _outputType, _result) \
+	if (input == 0) { \
+		UTF8_SET_ERROR(INVALID_DATA); \
+		return _result; \
+	} \
+	else if (inputSize < sizeof(_inputType)) { \
+		if (target != 0) { \
+			if (targetSize < sizeof(_outputType)) { \
+				UTF8_SET_ERROR(NOT_ENOUGH_SPACE); \
+				return _result; \
+			} \
+			*target = REPLACEMENT_CHARACTER; \
+		} \
+		UTF8_SET_ERROR(INVALID_DATA); \
+		return _result + sizeof(_outputType); \
+	} \
+	if (target != 0 && targetSize < sizeof(_outputType)) { \
+		UTF8_SET_ERROR(NOT_ENOUGH_SPACE); \
+		return _result; \
+	} \
+	if ((char*)input == (char*)target) { \
+		UTF8_SET_ERROR(OVERLAPPING_PARAMETERS); \
+		return _result; \
+	} \
+	{ \
+		char* input_center = (char*)input + (inputSize / 2); \
+		char* target_center = (char*)target + (targetSize / 2); \
+		size_t delta = (size_t)((input_center > target_center) ? (input_center - target_center) : (target_center - input_center)); \
+		if (delta < (inputSize + targetSize) / 2) { \
+			UTF8_SET_ERROR(OVERLAPPING_PARAMETERS); \
+			return _result; \
+		} \
+	}
+
+/*! \endcond */
+
+#endif /* _UTF8REWIND_INTERNAL_BASE_H_ */
+ third_party/utf8rewind/source/internal/casemapping.c view
@@ -0,0 +1,648 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "casemapping.h"
+
+#include "base.h"
+#include "codepoint.h"
+#include "database.h"
+#include "streaming.h"
+
+static const char basic_latin_lowercase_table[58] = {
+	/* LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z */
+	0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,
+	0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+	0x79, 0x7A,
+
+	0x5B, /* LEFT SQUARE BRACKET */
+	0x5C, /* REVERSE SOLIDUS */
+	0x5D, /* RIGHT SQUARE BRACKET */
+	0x5E, /* CIRCUMFLEX ACCENT */
+	0x5F, /* LOW LINE */
+	0x60, /* GRAVE ACCENT */
+
+	/* LATIN SMALL LETTER A - LATIN SMALL LETTER Z */
+	0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,
+	0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+	0x79, 0x7A
+};
+
+static const char basic_latin_uppercase_table[58] = {
+	/* LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z */
+	0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
+	0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+	0x59, 0x5A,
+
+	0x5B, /* LEFT SQUARE BRACKET */
+	0x5C, /* REVERSE SOLIDUS */
+	0x5D, /* RIGHT SQUARE BRACKET */
+	0x5E, /* CIRCUMFLEX ACCENT */
+	0x5F, /* LOW LINE */
+	0x60, /* GRAVE ACCENT */
+
+	/* LATIN SMALL LETTER A - LATIN SMALL LETTER Z */
+	0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
+	0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+	0x59, 0x5A
+};
+
+uint8_t casemapping_initialize(
+	CaseMappingState* state,
+	const char* input, size_t inputSize,
+	char* target, size_t targetSize,
+	const uint32_t* propertyIndex1, const uint32_t* propertyIndex2, const uint32_t* propertyData,
+	uint8_t quickCheck, size_t locale,
+	int32_t* errors)
+{
+	memset(state, 0, sizeof(CaseMappingState));
+
+	if (locale >= UTF8_LOCALE_MAXIMUM)
+	{
+		UTF8_SET_ERROR(INVALID_LOCALE);
+
+		return 0;
+	}
+
+	state->src = input;
+	state->src_size = inputSize;
+	state->dst = target;
+	state->dst_size = targetSize;
+	state->property_index1 = propertyIndex1;
+	state->property_index2 = propertyIndex2;
+	state->property_data = propertyData;
+	state->quickcheck_flags = quickCheck;
+	state->locale = locale;
+
+	return 1;
+}
+
+size_t casemapping_execute(CaseMappingState* state, int32_t* errors)
+{
+	uint8_t qc_casemapped = 0;
+	uint8_t bytes_needed = 0;
+	const char* resolved = 0;
+	StreamState stream;
+	uint8_t i;
+
+	/* Read next code point */
+
+	state->last_code_point_size = codepoint_read(state->src, state->src_size, &state->last_code_point);
+	if (state->last_code_point_size == 0)
+	{
+		goto invaliddata;
+	}
+
+	/* Check for invalid characters */
+
+	if (state->last_code_point == REPLACEMENT_CHARACTER)
+	{
+		/* Get code point properties */
+
+		state->last_canonical_combining_class = CCC_NOT_REORDERED;
+		state->last_general_category = UTF8_CATEGORY_SYMBOL_OTHER;
+
+		resolved = REPLACEMENT_CHARACTER_STRING;
+		bytes_needed = REPLACEMENT_CHARACTER_STRING_LENGTH;
+
+		goto writeresolved;
+	}
+
+	if (state->locale == UTF8_LOCALE_TURKISH_AND_AZERI_LATIN)
+	{
+		/*
+			Code point General Category does not need to be modified, because
+			all mappings result in the same General Category
+		*/
+
+		if (state->property_data == LowercaseDataPtr)
+		{
+			if (state->last_code_point == CP_LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE)
+			{
+				state->last_code_point = CP_LATIN_SMALL_LETTER_I;
+
+				resolved = "i";
+				bytes_needed = 1;
+			}
+			else if (
+				state->last_code_point == CP_LATIN_CAPITAL_LETTER_I)
+			{
+				if (state->src_size == 0)
+				{
+					/* Early-out for easy case */
+
+					state->last_code_point = CP_LATIN_SMALL_LETTER_DOTLESS_I;
+
+					resolved = "\xC4\xB1";
+					bytes_needed = 2;
+				}
+				else
+				{
+					uint8_t found = 0;
+
+					/* Initialize stream and read the next sequence */
+
+					if (!stream_initialize(&stream, state->src, state->src_size) ||
+						!stream_read(&stream, QuickCheckNFCIndexPtr, QuickCheckNFCDataPtr))
+					{
+						goto writeregular;
+					}
+
+					/* Erase COMBINING DOT ABOVE from sequence */
+
+					for (i = stream.current - 1; i > 0; --i)
+					{
+						if (stream.codepoint[i] == CP_COMBINING_DOT_ABOVE)
+						{
+							stream.canonical_combining_class[i] = CCC_INVALID;
+
+							found++;
+						}
+					}
+
+					/* Stabilize sequence and write to output */
+
+					if (!stream.stable ||
+						found > 0)
+					{
+						stream_reorder(&stream);
+
+						stream.current -= found;
+					}
+
+					stream.codepoint[0] = (found > 0) ? CP_LATIN_SMALL_LETTER_I : CP_LATIN_SMALL_LETTER_DOTLESS_I;
+
+					goto writestream;
+				}
+			}
+		}
+		else
+		{
+			if (state->last_code_point == CP_LATIN_SMALL_LETTER_I)
+			{
+				state->last_code_point = CP_LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE;
+
+				resolved = "\xC4\xB0";
+				bytes_needed = 2;
+			}
+			else if (
+				state->last_code_point == CP_LATIN_SMALL_LETTER_DOTLESS_I)
+			{
+				state->last_code_point = CP_LATIN_CAPITAL_LETTER_I;
+
+				resolved = "I";
+				bytes_needed = 1;
+			}
+		}
+
+		/* Check if mapping succeeded */
+
+		if (resolved != 0)
+		{
+			/* Code point properties */
+
+			state->last_general_category = UTF8_CATEGORY_LETTER;
+
+			goto writeresolved;
+		}
+	}
+	else if (
+		state->locale == UTF8_LOCALE_LITHUANIAN)
+	{
+		if (state->property_data == LowercaseDataPtr)
+		{
+			unicode_t cp_additional_accent = 0;
+			uint8_t write_soft_dot = 1;
+
+			switch (state->last_code_point)
+			{
+
+			case CP_LATIN_CAPITAL_LETTER_I:
+				state->last_code_point = CP_LATIN_SMALL_LETTER_I;
+				break;
+
+			case CP_LATIN_CAPITAL_LETTER_J:
+				state->last_code_point = CP_LATIN_SMALL_LETTER_J;
+				break;
+
+			case CP_LATIN_CAPITAL_LETTER_I_WITH_OGONEK:
+				state->last_code_point = CP_LATIN_SMALL_LETTER_I_WITH_OGONEK;
+				break;
+
+			case CP_LATIN_CAPITAL_LETTER_I_WITH_GRAVE:
+				state->last_code_point = CP_LATIN_SMALL_LETTER_I;
+				cp_additional_accent = CP_COMBINING_GRAVE_ACCENT;
+				break;
+
+			case CP_LATIN_CAPITAL_LETTER_I_WITH_ACUTE:
+				state->last_code_point = CP_LATIN_SMALL_LETTER_I;
+				cp_additional_accent = CP_COMBINING_ACUTE_ACCENT;
+				break;
+
+			case CP_LATIN_CAPITAL_LETTER_I_WITH_TILDE:
+				state->last_code_point = CP_LATIN_SMALL_LETTER_I;
+				cp_additional_accent = CP_COMBINING_TILDE_ACCENT;
+				break;
+
+			default:
+				goto writeregular;
+
+			}
+
+			/* Initialize stream and read the next sequence */
+
+			if (!stream_initialize(&stream, state->src, state->src_size) ||
+				!stream_read(&stream, QuickCheckNFCIndexPtr, QuickCheckNFCDataPtr))
+			{
+				goto writeregular;
+			}
+
+			/* Assign the lowercase code point to the start of the stream */
+
+			stream.codepoint[0] = state->last_code_point;
+
+			/* Check if COMBINING DOT ABOVE is not yet present */ 
+
+			for (i = stream.current - 1; i > 0; --i)
+			{
+				if (stream.codepoint[i] == CP_COMBINING_DOT_ABOVE)
+				{
+					write_soft_dot = 0;
+
+					break;
+				}
+			}
+
+			/* Stabilize the sequence */
+
+			if (!stream.stable)
+			{
+				stream_reorder(&stream);
+
+				stream.stable = 1;
+			}
+
+			/* Write COMBINING DOT ABOVE */
+
+			if (write_soft_dot &&
+				stream.current < STREAM_BUFFER_MAX)
+			{
+				/* Ensure the COMBINING DOT ABOVE comes before other accents with the same CCC */
+
+				if (stream.canonical_combining_class[stream.current - 1] == CCC_ABOVE)
+				{
+					unicode_t cp_swap = stream.codepoint[stream.current - 1];
+					stream.codepoint[stream.current - 1] = CP_COMBINING_DOT_ABOVE;
+					stream.codepoint[stream.current] = cp_swap;
+				}
+				else
+				{
+					stream.codepoint[stream.current] = CP_COMBINING_DOT_ABOVE;
+				}
+
+				stream.canonical_combining_class[stream.current] = CCC_ABOVE;
+
+				/* Check if sequence has become unstable */
+
+				stream.stable = stream.canonical_combining_class[stream.current - 1] <= CCC_ABOVE;
+
+				stream.current++;
+			}
+
+			/* Write additional accent */
+
+			if (cp_additional_accent != 0 &&
+				stream.current < STREAM_BUFFER_MAX)
+			{
+				/* Additional accents are always of the upper variety */
+
+				stream.codepoint[stream.current] = cp_additional_accent;
+				stream.canonical_combining_class[stream.current] = CCC_ABOVE;
+
+				/* Check if sequence has become unstable */
+
+				if (stream.stable &&
+					stream.canonical_combining_class[stream.current] < stream.canonical_combining_class[stream.current - 1])
+				{
+					stream.stable = 0;
+				}
+
+				stream.current++;
+			}
+
+			/* Stabilize the sequence */
+
+			if (!stream.stable)
+			{
+				stream_reorder(&stream);
+			}
+		}
+		else
+		{
+			uint8_t erase_count = 0;
+
+			switch (state->last_code_point)
+			{
+
+			case CP_LATIN_SMALL_LETTER_I:
+				state->last_code_point = CP_LATIN_CAPITAL_LETTER_I;
+				break;
+
+			case CP_LATIN_SMALL_LETTER_J:
+				state->last_code_point = CP_LATIN_CAPITAL_LETTER_J;
+				break;
+
+			case CP_LATIN_SMALL_LETTER_I_WITH_OGONEK:
+				state->last_code_point = CP_LATIN_CAPITAL_LETTER_I_WITH_OGONEK;
+				break;
+
+			default:
+				goto writeregular;
+
+			}
+
+			/* Initialize stream and read the next sequence */
+
+			if (!stream_initialize(&stream, state->src, state->src_size) ||
+				!stream_read(&stream, QuickCheckNFCIndexPtr, QuickCheckNFCDataPtr))
+			{
+				goto writeregular;
+			}
+
+			/* Assign the uppercase code point to the start of the stream */
+
+			stream.codepoint[0] = state->last_code_point;
+
+			/* Remove COMBINING DOT ABOVE from sequence */
+
+			for (i = 1; i < stream.current; ++i)
+			{
+				if (stream.codepoint[i] == CP_COMBINING_DOT_ABOVE)
+				{
+					stream.canonical_combining_class[i] = CCC_INVALID;
+					erase_count++;
+				}
+			}
+
+			/* Stabilize the sequence */
+
+			if (!stream.stable ||
+				erase_count > 0)
+			{
+				stream_reorder(&stream);
+
+				stream.current -= erase_count;
+			}
+		}
+
+		goto writestream;
+	}
+
+writeregular:
+	/* Get code point properties */
+
+	state->last_canonical_combining_class = PROPERTY_GET_CCC(state->last_code_point);
+	state->last_general_category = PROPERTY_GET_GC(state->last_code_point);
+
+	/* Move source cursor */
+
+	if (state->src_size >= state->last_code_point_size)
+	{
+		state->src += state->last_code_point_size;
+		state->src_size -= state->last_code_point_size;
+	}
+	else
+	{
+		state->src_size = 0;
+	}
+
+	/* Write to output */
+
+	if (state->last_code_point_size == 1)
+	{
+		/* Write Basic Latin to output buffer*/
+
+		if (state->dst != 0)
+		{
+			if (state->dst_size < 1)
+			{
+				goto outofspace;
+			}
+
+			/*
+				Uppercase letters are U+0041 ('A') to U+005A ('Z')
+				Lowercase letters are U+0061 ('a') to U+007A ('z')
+			*/
+
+			if (state->last_code_point >= 0x41 &&
+				state->last_code_point <= 0x7A)
+			{
+				if (state->property_data == LowercaseDataPtr)
+				{
+					*state->dst = basic_latin_lowercase_table[state->last_code_point - 0x41];
+				}
+				else
+				{
+					*state->dst = basic_latin_uppercase_table[state->last_code_point - 0x41];
+				}
+			}
+			else
+			{
+				/* All other code points in Basic Latin are unaffected by case mapping */
+
+				*state->dst = (char)state->last_code_point;
+			}
+
+			state->dst++;
+			state->dst_size--;
+		}
+
+		bytes_needed = 1;
+	}
+	else
+	{
+		if (state->property_data == LowercaseDataPtr &&
+			state->last_code_point == CP_GREEK_CAPITAL_LETTER_SIGMA)
+		{
+			/*
+				If the final letter of a word (defined as "a collection of code
+				points with the General Category 'Letter'") is a GREEK CAPITAL
+				LETTER SIGMA and more than one code point was processed, the
+				lowercase version is U+03C2 GREEK SMALL LETTER FINAL SIGMA
+				instead of U+03C3 GREEK SMALL LETTER SIGMA.
+			*/
+
+			/* At least one code point should have been read */
+
+			uint8_t should_convert = state->total_bytes_needed > 0;
+
+			if (state->src_size > 0)
+			{
+				unicode_t peeked = 0;
+				const char* peeked_src = state->src;
+				size_t peeked_src_size = state->src_size;
+
+				while (1)
+				{
+					uint8_t peeked_read = 0;
+
+					/* Peek next code point */
+
+					if ((peeked_read = codepoint_read(peeked_src, peeked_src_size, &peeked)) == 0 ||
+						peeked_src_size < peeked_read)
+					{
+						should_convert = 1;
+
+						break;
+					}
+
+					/* Convert if the "word" has ended */
+
+					if (PROPERTY_GET_CCC(peeked) == CCC_NOT_REORDERED)
+					{
+						should_convert = (PROPERTY_GET_GC(peeked) & UTF8_CATEGORY_LETTER) == 0;
+
+						break;
+					}
+
+					peeked_src += peeked_read;
+					peeked_src_size -= peeked_read;
+				}
+			}
+
+			/* Write the converted code point to the output buffer */
+
+			bytes_needed = 2;
+
+			if (state->dst != 0)
+			{
+				if (state->dst_size < bytes_needed)
+				{
+					goto outofspace;
+				}
+
+				memcpy(state->dst, should_convert ? "\xCF\x82" : "\xCF\x83", bytes_needed);
+
+				state->dst += bytes_needed;
+				state->dst_size -= bytes_needed;
+			}
+
+			return bytes_needed;
+		}
+
+		/* Check if the code point is case mapped */
+
+		qc_casemapped = PROPERTY_GET_CM(state->last_code_point);
+		if ((qc_casemapped & state->quickcheck_flags) != 0)
+		{
+			/* Attempt to resolve the case mapping */
+
+			resolved = database_querydecomposition(state->last_code_point, state->property_index1, state->property_index2, state->property_data, &bytes_needed);
+			if (resolved != 0)
+			{
+				/* Code point properties */
+
+				state->last_general_category = UTF8_CATEGORY_LETTER;
+
+				goto writeresolvedonly;
+			}
+		}
+
+		/* Write code point unchanged to output */
+
+		bytes_needed = codepoint_write(state->last_code_point, &state->dst, &state->dst_size);
+		if (bytes_needed == 0)
+		{
+			goto outofspace;
+		}
+	}
+
+	return bytes_needed;
+
+writeresolved:
+	/* Move source cursor */
+
+	if (state->src_size >= state->last_code_point_size)
+	{
+		state->src += state->last_code_point_size;
+		state->src_size -= state->last_code_point_size;
+	}
+	else
+	{
+		state->src_size = 0;
+	}
+
+writeresolvedonly:
+	/* Write resolved string to output */
+
+	if (state->dst != 0)
+	{
+		if (state->dst_size < bytes_needed)
+		{
+			goto outofspace;
+		}
+
+		memcpy(state->dst, resolved, bytes_needed);
+
+		state->dst += bytes_needed;
+		state->dst_size -= bytes_needed;
+	}
+
+	return bytes_needed;
+
+writestream:
+	/* Get code point properties */
+
+	state->last_code_point = stream.codepoint[stream.current - 1];
+	state->last_canonical_combining_class = stream.canonical_combining_class[stream.current - 1];
+	state->last_general_category = PROPERTY_GET_GC(stream.codepoint[0]);
+
+	/* Move source cursor */
+
+	state->src = stream.src;
+	state->src_size = stream.src_size;
+
+	/* Write result to the output buffer */
+
+	if (!stream_write(&stream, &state->dst, &state->dst_size, &bytes_needed))
+	{
+		goto outofspace;
+	}
+
+	return bytes_needed;
+
+invaliddata:
+	UTF8_SET_ERROR(INVALID_DATA);
+
+	state->src_size = 0;
+
+	return 0;
+
+outofspace:
+	UTF8_SET_ERROR(NOT_ENOUGH_SPACE);
+
+	state->src_size = 0;
+
+	return 0;
+}
+ third_party/utf8rewind/source/internal/casemapping.h view
@@ -0,0 +1,67 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _UTF8REWIND_INTERNAL_CASEMAPPING_H_
+#define _UTF8REWIND_INTERNAL_CASEMAPPING_H_
+
+/*!
+	\file
+	\brief Case mapping interface.
+
+	\cond INTERNAL
+*/
+
+#include "utf8rewind.h"
+
+typedef struct {
+	const char* src;
+	char* dst;
+	size_t src_size;
+	size_t dst_size;
+	size_t total_bytes_needed;
+	unicode_t last_code_point;
+	size_t locale;
+	const uint32_t* property_index1;
+	const uint32_t* property_index2;
+	const uint32_t* property_data;
+	uint32_t last_general_category;
+	uint8_t last_code_point_size;
+	uint8_t last_canonical_combining_class;
+	uint8_t quickcheck_flags;
+} CaseMappingState;
+
+uint8_t casemapping_initialize(
+	CaseMappingState* state,
+	const char* input, size_t inputSize,
+	char* target, size_t targetSize,
+	const uint32_t* propertyIndex1, const uint32_t* propertyIndex2, const uint32_t* propertyData,
+	uint8_t quickCheck, size_t locale,
+	int32_t* errors);
+
+size_t casemapping_execute(CaseMappingState* state, int32_t* errors);
+
+/*! \endcond */
+
+#endif /* _UTF8REWIND_INTERNAL_CASEMAPPING_H_ */
+ third_party/utf8rewind/source/internal/codepoint.c view
@@ -0,0 +1,272 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "codepoint.h"
+
+const uint8_t codepoint_decoded_length[256] = {
+	/* Basic Latin */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x00 - 0x07 */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x08 - 0x0F */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x10 - 0x17 */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x18 - 0x1F */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x20 - 0x27 */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x28 - 0x2F */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x30 - 0x37 */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x38 - 0x3F */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x47 */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x48 - 0x4F */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x57 */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x58 - 0x5F */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x67 */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x68 - 0x6F */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x77 */
+	1, 1, 1, 1, 1, 1, 1, 1, /* 0x78 - 0x7F */
+
+	/* Malformed continuation byte */
+	0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x87 */
+	0, 0, 0, 0, 0, 0, 0, 0, /* 0x88 - 0x8F */
+	0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x97 */
+	0, 0, 0, 0, 0, 0, 0, 0, /* 0x98 - 0x9F */
+	0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xA7 */
+	0, 0, 0, 0, 0, 0, 0, 0, /* 0xA8 - 0xAF */
+	0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xB7 */
+	0, 0, 0, 0, 0, 0, 0, 0, /* 0xB8 - 0xBF */
+
+	/* Two bytes */
+	2, 2, 2, 2, 2, 2, 2, 2, /* 0xC0 - 0xC7 */
+	2, 2, 2, 2, 2, 2, 2, 2, /* 0xC8 - 0xCF */
+	2, 2, 2, 2, 2, 2, 2, 2, /* 0xD0 - 0xD7 */
+	2, 2, 2, 2, 2, 2, 2, 2, /* 0xD8 - 0xDF */
+
+	/* Three bytes */
+	3, 3, 3, 3, 3, 3, 3, 3, /* 0xE0 - 0xE7 */
+	3, 3, 3, 3, 3, 3, 3, 3, /* 0xE8 - 0xEF */
+
+	/* Four bytes */
+	4, 4, 4, 4, 4, 4, 4, 4, /* 0xF0 - 0xF7 */
+
+	/* Five bytes */
+	5, 5, 5, 5,             /* 0xF8 - 0xFB */
+
+	/* Six bytes */
+	6, 6,                   /* 0xFC - 0xFD */
+
+	/* Invalid */
+	7, 7                    /* 0xFE - 0xFF */
+};
+
+uint8_t codepoint_write(unicode_t encoded, char** target, size_t* targetSize)
+{
+	uint8_t encoded_length;
+
+	/* Determine encoded length of code point */
+
+	if (encoded <= MAX_BASIC_LATIN)
+	{
+		encoded_length = 1;
+	}
+	else if (
+		encoded <= 0x7FF)
+	{
+		encoded_length = 2;
+	}
+	else if (
+		encoded <= MAX_BASIC_MULTILINGUAL_PLANE)
+	{
+		encoded_length = 3;
+	}
+	else if (
+		encoded > MAX_LEGAL_UNICODE)
+	{
+		encoded = REPLACEMENT_CHARACTER;
+		encoded_length = REPLACEMENT_CHARACTER_STRING_LENGTH;
+	}
+	else
+	{
+		encoded_length = 4;
+	}
+
+	/* Write to target */
+
+	if (*target != 0)
+	{
+		char* dst;
+
+		if (*targetSize < encoded_length)
+		{
+			return 0;
+		}
+
+		dst = *target;
+
+		switch (encoded_length)
+		{
+
+		case 1:
+			*dst++ = (char)encoded;
+			break;
+
+		case 2:
+			*dst++ = (char)(encoded >>   6)         | 0xC0;
+			*dst++ = (char)(encoded         & 0x3F) | 0x80;
+			break;
+
+		case 3:
+			*dst++ = (char)(encoded  >> 12)         | 0xE0;
+			*dst++ = (char)((encoded >>  6) & 0x3F) | 0x80;
+			*dst++ = (char)(encoded         & 0x3F) | 0x80;
+			break;
+
+		case 4:
+			*dst++ = (char)(encoded  >> 18)         | 0xF0;
+			*dst++ = (char)((encoded >> 12) & 0x3F) | 0x80;
+			*dst++ = (char)((encoded >>  6) & 0x3F) | 0x80;
+			*dst++ = (char)(encoded         & 0x3F) | 0x80;
+			break;
+
+		default:
+			break;
+
+		}
+
+		*target += encoded_length;
+		*targetSize -= encoded_length;
+	}
+
+	return encoded_length;
+}
+
+uint8_t codepoint_read(const char* input, size_t inputSize, unicode_t* decoded)
+{
+	const uint8_t* src = (const uint8_t*)input;
+
+	if (input == 0 ||
+		inputSize == 0)
+	{
+		/* Invalid data */
+
+		return 0;
+	}
+
+	if (*src <= MAX_BASIC_LATIN)
+	{
+		/* Basic Latin */
+
+		*decoded = (unicode_t)*src;
+
+		return 1;
+	}
+	else
+	{
+		/* Multi-byte sequence */
+
+		static const uint8_t SequenceMask[7] = {
+			0x00, 0x7F, 0x1F, 0x0F,
+			0x07, 0x03, 0x01
+		};
+		static const unicode_t SequenceMinimum[7] = {
+			0x0000, 0x0000, 0x0080, 0x0800,
+			0x10000, MAX_LEGAL_UNICODE, MAX_LEGAL_UNICODE
+		};
+
+		size_t src_size = inputSize;
+		uint8_t src_index;
+
+		/* Length of sequence is determined by first byte */
+
+		uint8_t decoded_length = codepoint_decoded_length[*src];
+		if (decoded_length < 1 ||
+			decoded_length > 6)
+		{
+			/* Not a multi-byte sequence starter */
+
+			*decoded = REPLACEMENT_CHARACTER;
+			decoded_length = 1;
+		}
+		else if (decoded_length > 4)
+		{
+			/* Always an overlong sequence */
+
+			*decoded = REPLACEMENT_CHARACTER;
+
+			/* All bytes in the sequence must be processed */
+
+			for (src_index = 1; src_index < decoded_length; ++src_index)
+			{
+				src++;
+
+				/* Check if next byte is valid */
+
+				if (src_size == 0 ||               /* Not enough data */
+					(*src < 0x80 || *src > 0xBF))  /* Not a continuation byte */
+				{
+					return src_index;
+				}
+
+				src_size--;
+			}
+		}
+		else
+		{
+			/* Use mask to strip value from first byte */
+
+			*decoded = (unicode_t)(*src & SequenceMask[decoded_length]);
+
+			/* All bytes in the sequence must be processed */
+
+			for (src_index = 1; src_index < decoded_length; ++src_index)
+			{
+				src++;
+
+				/* Check if next byte is valid */
+
+				if (src_size == 0 ||               /* Not enough data */
+					(*src < 0x80 || *src > 0xBF))  /* Not a continuation byte */
+				{
+					*decoded = REPLACEMENT_CHARACTER;
+
+					return src_index;
+				}
+
+				src_size--;
+
+				/* Add value of continuation byte to codepoint */
+
+				*decoded = (*decoded << 6) | (*src & 0x3F);
+			}
+
+			/* Check for overlong sequences and surrogate pairs */
+
+			if (*decoded < SequenceMinimum[decoded_length] ||
+				*decoded > MAX_LEGAL_UNICODE ||
+				(*decoded >= SURROGATE_HIGH_START && *decoded <= SURROGATE_LOW_END))
+			{
+				*decoded = REPLACEMENT_CHARACTER;
+			}
+		}
+
+		return decoded_length;
+	}
+}
+ third_party/utf8rewind/source/internal/codepoint.h view
@@ -0,0 +1,291 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _UTF8REWIND_INTERNAL_CODEPOINT_H_
+#define _UTF8REWIND_INTERNAL_CODEPOINT_H_
+
+/*!
+	\file
+	\brief Codepoint interface.
+
+	\cond INTERNAL
+*/
+
+#include "utf8rewind.h"
+
+/*!
+	\addtogroup internal Internal functions and definitions
+	\{
+*/
+
+/*!
+	\def MAX_BASIC_LATIN
+	\brief The last codepoint part of Basic Latin (U+0000 - U+007F).
+*/
+#define MAX_BASIC_LATIN                      0x007F
+
+/*!
+	\def MAX_LATIN_1
+	\brief The last codepoint part of Latin-1 Supplement (U+0080 - U+00FF).
+*/
+#define MAX_LATIN_1                          0x00FF
+
+/*!
+	\def MAX_BASIC_MULTILINGUAL_PLANE
+	\brief The last legal codepoint in the Basic Multilingual Plane (BMP).
+*/
+#define MAX_BASIC_MULTILINGUAL_PLANE         0xFFFF
+
+/*!
+	\def MAX_LEGAL_UNICODE
+	\brief The last legal codepoint in Unicode.
+*/
+#define MAX_LEGAL_UNICODE                    0x10FFFF
+
+/*!
+	\def REPLACEMENT_CHARACTER
+	\brief The codepoint used to replace illegal codepoints.
+*/
+#define REPLACEMENT_CHARACTER                0xFFFD
+
+/*!
+	\def REPLACEMENT_CHARACTER_STRING
+	\brief The replacement character as a UTF-8 encoded string.
+*/
+#define REPLACEMENT_CHARACTER_STRING         "\xEF\xBF\xBD"
+
+/*!
+	\def REPLACEMENT_CHARACTER_STRING_LENGTH
+	\brief Length of the UTF-8 encoded string of the replacment character.
+*/
+#define REPLACEMENT_CHARACTER_STRING_LENGTH  3
+
+/*!
+	\def SURROGATE_HIGH_START
+	\brief The minimum codepoint for the high member of a surrogate pair.
+*/
+#define SURROGATE_HIGH_START                 0xD800
+
+/*!
+	\def SURROGATE_HIGH_END
+	\brief The maximum codepoint for the high member of a surrogate pair.
+*/
+#define SURROGATE_HIGH_END                   0xDBFF
+
+/*!
+	\def SURROGATE_LOW_START
+	\brief The minimum codepoint for the low member of a surrogate pair.
+*/
+#define SURROGATE_LOW_START                  0xDC00
+
+/*!
+	\def SURROGATE_LOW_END
+	\brief The maximum codepoint for the low member of a surrogate pair.
+*/
+#define SURROGATE_LOW_END                    0xDFFF
+
+/*!
+	\def HANGUL_JAMO_FIRST
+	\brief The first codepoint part of the Hangul Jamo block.
+*/
+#define HANGUL_JAMO_FIRST                    0x1100
+
+/*!
+	\def HANGUL_JAMO_LAST
+	\brief The last codepoint part of the Hangul Jamo block.
+*/
+#define HANGUL_JAMO_LAST                     0x11FF
+
+/*!
+	\def HANGUL_L_FIRST
+	\brief The first codepoint part of the Hangul Jamo L section used for
+	normalization.
+*/
+#define HANGUL_L_FIRST                       0x1100
+
+/*!
+	\def HANGUL_L_LAST
+	\brief The last codepoint part of the Hangul Jamo L section used for
+	normalization.
+*/
+#define HANGUL_L_LAST                        0x1112
+
+/*!
+	\def HANGUL_L_COUNT
+	\brief The number of codepoints in the Hangul Jamo L section.
+*/
+#define HANGUL_L_COUNT                       19
+
+/*!
+	\def HANGUL_V_FIRST
+	\brief The first codepoint part of the Hangul Jamo V section used for
+	normalization.
+*/
+#define HANGUL_V_FIRST                       0x1161
+
+/*!
+	\def HANGUL_V_LAST
+	\brief The last codepoint part of the Hangul Jamo V section used for
+	normalization.
+*/
+#define HANGUL_V_LAST                        0x1175
+
+/*!
+	\def HANGUL_V_COUNT
+	\brief The number of codepoints in the Hangul Jamo V section.
+*/
+#define HANGUL_V_COUNT                       21
+
+/*!
+	\def HANGUL_T_FIRST
+	\brief The first codepoint part of the Hangul Jamo T section used for
+	normalization.
+*/
+#define HANGUL_T_FIRST                       0x11A7
+
+/*!
+	\def HANGUL_T_LAST
+	\brief The last codepoint part of the Hangul Jamo V section used for
+	normalization.
+*/
+#define HANGUL_T_LAST                        0x11C2
+
+/*!
+	\def HANGUL_T_COUNT
+	\brief The number of codepoints in the Hangul Jamo T section.
+*/
+#define HANGUL_T_COUNT                       28
+
+/*!
+	\def HANGUL_N_COUNT
+	\brief Number of codepoints part of the Hangul Jamo V and T sections.
+*/
+#define HANGUL_N_COUNT                       588 /* VCount * TCount */
+
+/*!
+	\def HANGUL_S_FIRST
+	\brief The first codepoint in the Hangul Syllables block.
+*/
+#define HANGUL_S_FIRST                       0xAC00
+
+/*!
+	\def HANGUL_S_LAST
+	\brief The last codepoint in the Hangul Syllables block.
+*/
+#define HANGUL_S_LAST                        0xD7A3
+
+/*!
+	\def HANGUL_S_COUNT
+	\brief The number of codepoints in the Hangul Syllables block.
+*/
+#define HANGUL_S_COUNT                       11172 /* LCount * NCount */
+
+#define CP_LATIN_CAPITAL_LETTER_I                 0x0049
+#define CP_LATIN_CAPITAL_LETTER_J                 0x004A
+#define CP_LATIN_SMALL_LETTER_I                   0x0069
+#define CP_LATIN_SMALL_LETTER_J                   0x006A
+#define CP_LATIN_CAPITAL_LETTER_I_WITH_GRAVE      0x00CC
+#define CP_LATIN_CAPITAL_LETTER_I_WITH_ACUTE      0x00CD
+#define CP_LATIN_CAPITAL_LETTER_I_WITH_TILDE      0x0128
+#define CP_LATIN_CAPITAL_LETTER_I_WITH_OGONEK     0x012E
+#define CP_LATIN_SMALL_LETTER_I_WITH_OGONEK       0x012F
+#define CP_LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE  0x0130
+#define CP_LATIN_SMALL_LETTER_DOTLESS_I           0x0131
+#define CP_COMBINING_GRAVE_ACCENT                 0x0300
+#define CP_COMBINING_ACUTE_ACCENT                 0x0301
+#define CP_COMBINING_TILDE_ACCENT                 0x0303
+#define CP_COMBINING_DOT_ABOVE                    0x0307
+#define CP_COMBINING_GREEK_YPOGEGRAMMENI          0x0345
+#define CP_COMBINING_GRAPHEME_JOINER              0x034F
+#define CP_GREEK_CAPITAL_LETTER_SIGMA             0x03A3
+
+#define CCC_NOT_REORDERED                         0
+#define CCC_OVERLAY                               1
+#define CCC_NUKTA                                 7
+#define CCC_KANA_VOICING                          8
+#define CCC_VIRAMA                                9
+#define CCC_FIXED_POSITION_START                  10
+#define CCC_FIXED_POSITION_END                    199
+#define CCC_ATTACHED_BELOW_LEFT                   200
+#define CCC_ATTACHED_BELOW                        202
+#define CCC_ATTACHED_BOTTOM_RIGHT                 204
+#define CCC_ATTACHED_LEFT                         208
+#define CCC_ATTACHED_RIGHT                        210
+#define CCC_ATTACHED_TOP_LEFT                     212
+#define CCC_ATTACHED_ABOVE                        214
+#define CCC_ATTACHED_ABOVE_RIGHT                  216
+#define CCC_BELOW_LEFT                            218
+#define CCC_BELOW                                 220
+#define CCC_BELOW_RIGHT                           222
+#define CCC_LEFT                                  224
+#define CCC_RIGHT                                 226
+#define CCC_ABOVE_LEFT                            228
+#define CCC_ABOVE                                 230
+#define CCC_ABOVE_RIGHT                           232
+#define CCC_DOUBLE_BELOW                          233
+#define CCC_DOUBLE_ABOVE                          234
+#define CCC_IOTA_SUBSCRIPT                        240
+#define CCC_INVALID                               255
+
+/*!
+	\brief Get the number of bytes used for encoding a code point.
+
+	\param[in]  byte  Encoded byte
+
+	\return Number of bytes needed for decoding or 0 if input is illegal.
+*/
+extern const uint8_t codepoint_decoded_length[256];
+
+/*!
+	\brief Write Unicode code point to UTF-8 encoded string.
+
+	Target buffer and size is modified by encoded size.
+
+	\param[in]      encoded     Unicode code point
+	\param[in,out]  target      Target buffer
+	\param[in,out]  targetSize  Size of output buffer in bytes
+
+	\return Bytes needed for encoding or 0 on error.
+*/
+uint8_t codepoint_write(unicode_t encoded, char** target, size_t* targetSize);
+
+/*!
+	\brief Read Unicode code point from UTF-8 encoded string.
+
+	\param[in]   input      Input buffer
+	\param[in]   inputSize  Size of input buffer in bytes
+	\param[out]  decoded    Unicode codepoint
+
+	\return Bytes read from string or 0 on error.
+*/
+uint8_t codepoint_read(const char* input, size_t inputSize, unicode_t* decoded);
+
+/*!
+	\}
+*/
+
+/*! \endcond */
+
+#endif /* _UTF8REWIND_INTERNAL_CODEPOINT_H_ */
+ third_party/utf8rewind/source/internal/composition.c view
@@ -0,0 +1,336 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "composition.h"
+
+#include "codepoint.h"
+#include "database.h"
+
+uint8_t compose_initialize(ComposeState* state, StreamState* input, StreamState* output, uint8_t compatibility)
+{
+	memset(state, 0, sizeof(ComposeState));
+
+	/* Ensure streams are valid */
+
+	if (input == 0 ||
+		output == 0)
+	{
+		return 0;
+	}
+
+	/* Set up streams */
+
+	state->input = input;
+
+	state->output = output;
+	memset(state->output, 0, sizeof(StreamState));
+
+	/* Set up codepoint quickcheck property */
+
+	if (compatibility == 1)
+	{
+		state->qc_index = QuickCheckNFKCIndexPtr;
+		state->qc_data = QuickCheckNFKCDataPtr;
+	}
+	else
+	{
+		state->qc_index = QuickCheckNFCIndexPtr;
+		state->qc_data = QuickCheckNFCDataPtr;
+	}
+
+	return 1;
+}
+
+uint8_t compose_readcodepoint(ComposeState* state, uint8_t index)
+{
+	if (state->input->index == state->input->current &&
+		!stream_read(state->input, state->qc_index, state->qc_data))
+	{
+		/* End of data */
+
+		return 0;
+	}
+
+	/* Get next codepoint from sequence */
+
+	state->output->codepoint[index]                  = state->input->codepoint[state->input->index];
+	state->output->quick_check[index]                = state->input->quick_check[state->input->index];
+	state->output->canonical_combining_class[index]  = state->input->canonical_combining_class[state->input->index];
+
+	state->input->index++;
+	state->output->current++;
+
+	return 1;
+}
+
+uint8_t compose_execute(ComposeState* state)
+{
+	uint8_t output_index;
+	uint8_t cursor_current;
+	uint8_t cursor_next;
+
+	/* Check if input is available */
+
+	if (state->input == 0)
+	{
+		return 0;
+	}
+
+	/* Reset output */
+
+	state->output->current = 0;
+
+	/* Read first codepoint */
+
+	if (!compose_readcodepoint(state, 0))
+	{
+		return 0;
+	}
+
+	for (output_index = 0; output_index < state->output->current; ++output_index)
+	{
+		/* Ensure current codepoint is a starter */
+
+		cursor_current = output_index;
+
+		while (state->output->canonical_combining_class[cursor_current] != CCC_NOT_REORDERED)
+		{
+			cursor_current++;
+
+			if (cursor_current == state->output->current &&
+				!compose_readcodepoint(state, cursor_current))
+			{
+				/* Only non-starters left */
+
+				return 1;
+			}
+		}
+
+		/* Get next codepoint */
+
+		cursor_next = cursor_current + 1;
+
+		while (
+			cursor_next < state->output->current ||
+			compose_readcodepoint(state, cursor_next))
+		{
+			/*
+				Two codepoints can be composed if the current codepoint is a starter
+				and the next codepoint isn't blocked by a previous codepoint.
+			*/
+
+			if (state->output->canonical_combining_class[cursor_next] > state->output->canonical_combining_class[cursor_next - 1] || /* Can be composed based on CCC */
+				/* Quick check value can override composition block by previous codepoint */
+				(state->output->quick_check[cursor_next] != QuickCheckResult_Yes && state->output->canonical_combining_class[cursor_next - 1] == CCC_NOT_REORDERED))
+			{
+				unicode_t composed = 0;
+
+				/*
+					Hangul composition
+
+					Algorithm adapted from Unicode Technical Report #15:
+					http://www.unicode.org/reports/tr15/tr15-18.html#Hangul
+				*/
+
+				if (state->output->codepoint[cursor_current] >= HANGUL_L_FIRST &&
+					state->output->codepoint[cursor_current] <= HANGUL_L_LAST)
+				{
+					/* Check for Hangul LV pair */ 
+
+					if (state->output->codepoint[cursor_next] >= HANGUL_V_FIRST &&
+						state->output->codepoint[cursor_next] <= HANGUL_V_LAST)
+					{
+						unicode_t l_index = state->output->codepoint[cursor_current] - HANGUL_L_FIRST;
+						unicode_t v_index = state->output->codepoint[cursor_next] - HANGUL_V_FIRST;
+
+						composed = HANGUL_S_FIRST + (((l_index * HANGUL_V_COUNT) + v_index) * HANGUL_T_COUNT);
+					}
+				}
+				else if (
+					state->output->codepoint[cursor_current] >= HANGUL_S_FIRST &&
+					state->output->codepoint[cursor_current] <= HANGUL_S_LAST)
+				{
+					/* Check for Hangul LV and T pair */ 
+
+					if (state->output->codepoint[cursor_next] >= HANGUL_T_FIRST &&
+						state->output->codepoint[cursor_next] <= HANGUL_T_LAST)
+					{
+						unicode_t t_index = state->output->codepoint[cursor_next] - HANGUL_T_FIRST;
+
+						composed = state->output->codepoint[cursor_current] + t_index;
+					}
+				}
+				else
+				{
+					/* Attempt to compose codepoints using the database */
+
+					composed = database_querycomposition(
+						state->output->codepoint[cursor_current],
+						state->output->codepoint[cursor_next]);
+				}
+
+				/* Check if composition succeeded */
+
+				if (composed != 0)
+				{
+					/*
+						When we successfully compose two codepoints, the second must be removed
+						from the sequence. The way this is accomplished is by marking the cell
+						empty with a NUL codepoint.
+
+						Decomposed:
+
+						codepoint   U+0044 U+0307 U+0031
+						    index        0      1      2
+
+						Composed:
+
+						codepoint   U+1E0A U+0000 U+0031
+						    index        0      1      2
+
+						If the second codepoint was at the end of the sequence, the output 
+						sequence is shortened by one.
+					*/
+
+					/* Add composition to output */
+
+					state->output->codepoint[cursor_current]                  = composed;
+					state->output->quick_check[cursor_current]                = PROPERTY_GET(state->qc_index, state->qc_data, composed);
+					state->output->canonical_combining_class[cursor_current]  = PROPERTY_GET_CCC(composed);
+
+					/* Clear next codepoint from output */
+
+					state->output->codepoint[cursor_next]                  = 0;
+					state->output->quick_check[cursor_next]                = QuickCheckResult_Yes;
+					state->output->canonical_combining_class[cursor_next]  = CCC_NOT_REORDERED;
+
+					if (cursor_next == state->output->current - 1)
+					{
+						/* Next codepoint was at end of output */
+
+						state->output->current--;
+					}
+
+					/* Reset cursor to current output index */
+
+					cursor_current = output_index;
+					cursor_next = output_index;
+				}
+			}
+			else if (
+				state->output->canonical_combining_class[cursor_next] == CCC_NOT_REORDERED)
+			{
+				/* Attempt to compose starters, but do not read from the next sequence */
+
+				break;
+			}
+
+			/* Evaluate next codepoint */
+
+			cursor_next++;
+		}
+
+		/* Fill up "holes" left by composing codepoints not at the end of the sequence */
+
+		if (state->output->current > 1)
+		{
+			uint8_t write_index = 0;
+			uint8_t read_index = 1;
+
+			/*
+				We want to move valid codepoints to the left as much as possible in order to fill up
+				holes left by the composition process. 
+
+				Note that the process does not clear unused codepoints at the end, this is a small
+				optimization in order to avoid unnecessary clears. The length member is adjusted to
+				the new size.
+				
+				Before reordering:
+
+				codepoint   A  B  0  0  0  D
+				    index   0  1  2  3  4  5
+				   length                  6
+
+				After reordering:
+
+				codepoint   A  B  D  0  0  D
+				    index   0  1  2  3  4  5
+				   length         3
+			*/
+
+			/* Evaluate all codepoints in output sequence */
+
+			while (write_index < state->output->current)
+			{
+				/* Check if read cursor is on an empty cell */
+
+				if (read_index < state->output->current &&
+					state->output->codepoint[read_index] == 0)
+				{
+					/* Skip all empty cells */
+
+					while (
+						read_index < state->output->current &&
+						state->output->codepoint[read_index] == 0)
+					{
+						read_index++;
+					}
+
+					if (read_index == state->output->current)
+					{
+						/* Reached end of data */
+
+						break;
+					}
+
+					/* Copy cell at read cursor to write cursor */
+
+					state->output->codepoint[write_index]                  = state->output->codepoint[read_index];
+					state->output->quick_check[write_index]                = state->output->quick_check[read_index];
+					state->output->canonical_combining_class[write_index]  = state->output->canonical_combining_class[read_index];
+				}
+
+				/* Move cursors */
+
+				write_index++;
+				read_index++;
+			}
+
+			/* Adjust length of output sequence */
+
+			state->output->current = write_index;
+		}
+		else
+		{
+			/* Evaluated all sequences in output */
+
+			state->input = 0;
+
+			break;
+		}
+	}
+
+	return 1;
+}
+ third_party/utf8rewind/source/internal/composition.h view
@@ -0,0 +1,54 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _UTF8REWIND_INTERNAL_COMPOSITION_H_
+#define _UTF8REWIND_INTERNAL_COMPOSITION_H_
+
+/*!
+	\file
+	\brief Composition interface.
+
+	\cond INTERNAL
+*/
+
+#include "utf8rewind.h"
+#include "streaming.h"
+
+typedef struct {
+	StreamState* input;
+	StreamState* output;
+	const size_t* qc_index;
+	const uint8_t* qc_data;
+} ComposeState;
+
+uint8_t compose_initialize(ComposeState* state, StreamState* input, StreamState* output, uint8_t compatibility);
+
+uint8_t compose_readcodepoint(ComposeState* state, uint8_t index);
+
+uint8_t compose_execute(ComposeState* state);
+
+/*! \endcond */
+
+#endif /* _UTF8REWIND_INTERNAL_COMPOSITION_H_ */
+ third_party/utf8rewind/source/internal/database.c view
@@ -0,0 +1,113 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "database.h"
+
+#include "../unicodedatabase.h"
+#include "codepoint.h"
+
+#define DECOMPOSE_INDEX1_SHIFT (12)
+#define DECOMPOSE_INDEX2_SHIFT (5)
+
+static const unicode_t DECOMPOSE_INDEX1_MASK = MAX_LEGAL_UNICODE;
+static const unicode_t DECOMPOSE_INDEX2_MASK = (1 << DECOMPOSE_INDEX1_SHIFT) - 1;
+static const unicode_t DECOMPOSE_DATA_MASK = (1 << DECOMPOSE_INDEX2_SHIFT) - 1;
+
+const char* database_querydecomposition(unicode_t codepoint, const uint32_t* index1Array, const uint32_t* index2Array, const uint32_t* dataArray, uint8_t* length)
+{
+	uint32_t index;
+	uint32_t data;
+
+	index = index1Array[codepoint >> DECOMPOSE_INDEX1_SHIFT];
+	index = index2Array[index + ((codepoint & DECOMPOSE_INDEX2_MASK) >> DECOMPOSE_INDEX2_SHIFT)];
+	index = index + (codepoint & DECOMPOSE_DATA_MASK);
+
+	if (index == 0 ||
+		(data = dataArray[index]) == 0)
+	{
+		*length = 0;
+
+		return 0;
+	}
+
+	*length = (uint8_t)((data & 0xFF000000) >> 24);
+
+	return CompressedStringData + (data & 0x00FFFFFF);
+}
+
+unicode_t database_querycomposition(unicode_t left, unicode_t right)
+{
+	uint64_t key = ((uint64_t)left << 32) + (uint64_t)right;
+	size_t offset_start = 0;
+	size_t offset_end = UnicodeCompositionRecordCount - 1;
+	size_t offset_pivot;
+	size_t i;
+
+	if (key < UnicodeCompositionRecordPtr[offset_start].key ||
+		key > UnicodeCompositionRecordPtr[offset_end].key)
+	{
+		return 0;
+	}
+
+	do
+	{
+		offset_pivot = offset_start + ((offset_end - offset_start) / 2);
+
+		if (key == UnicodeCompositionRecordPtr[offset_start].key)
+		{
+			return UnicodeCompositionRecordPtr[offset_start].value;
+		}
+		else if (key == UnicodeCompositionRecordPtr[offset_end].key)
+		{
+			return UnicodeCompositionRecordPtr[offset_end].value;
+		}
+		else if (key == UnicodeCompositionRecordPtr[offset_pivot].key)
+		{
+			return UnicodeCompositionRecordPtr[offset_pivot].value;
+		}
+		else
+		{
+			if (key > UnicodeCompositionRecordPtr[offset_pivot].key)
+			{
+				offset_start = offset_pivot;
+			}
+			else
+			{
+				offset_end = offset_pivot;
+			}
+		}
+	}
+	while (offset_end - offset_start > 32);
+
+	for (i = offset_start; i <= offset_end; ++i)
+	{
+		if (key == UnicodeCompositionRecordPtr[i].key)
+		{
+			return UnicodeCompositionRecordPtr[i].value;
+		}
+	}
+
+	return 0;
+}
+ third_party/utf8rewind/source/internal/database.h view
@@ -0,0 +1,91 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _UTF8REWIND_INTERNAL_DATABASE_H_
+#define _UTF8REWIND_INTERNAL_DATABASE_H_
+
+/*!
+	\file
+	\brief Database interface.
+
+	\cond INTERNAL
+*/
+
+#include "utf8rewind.h"
+
+#include "../unicodedatabase.h"
+
+enum QuickCheckCaseMapped
+{
+	QuickCheckCaseMapped_Uppercase = 0x01,
+	QuickCheckCaseMapped_Lowercase = 0x02,
+	QuickCheckCaseMapped_Titlecase = 0x04,
+	QuickCheckCaseMapped_Casefolded = 0x08,
+};
+
+enum QuickCheckResult
+{
+	QuickCheckResult_Yes,
+	QuickCheckResult_Maybe,
+	QuickCheckResult_No,
+};
+
+#define PROPERTY_INDEX_SHIFT (5)
+
+static const unicode_t PROPERTY_DATA_MASK = (1 << PROPERTY_INDEX_SHIFT) - 1;
+
+#define PROPERTY_GET(_indexArray, _dataArray, _cp) \
+	(_dataArray)[ \
+		(_indexArray)[(_cp) >> PROPERTY_INDEX_SHIFT] + \
+		((_cp) & PROPERTY_DATA_MASK)]
+
+#define PROPERTY_GET_GC(_cp) \
+	PROPERTY_GET(GeneralCategoryIndexPtr, GeneralCategoryDataPtr, _cp)
+
+#define PROPERTY_GET_CCC(_cp) \
+	PROPERTY_GET(CanonicalCombiningClassIndexPtr, CanonicalCombiningClassDataPtr, _cp)
+
+#define PROPERTY_GET_CM(_cp) \
+	PROPERTY_GET(QuickCheckCaseMappedIndexPtr, QuickCheckCaseMappedDataPtr, _cp)
+
+#define PROPERTY_GET_NFC(_cp) \
+	PROPERTY_GET(QuickCheckNFCIndexPtr, QuickCheckNFCDataPtr, _cp)
+
+#define PROPERTY_GET_NFD(_cp) \
+	PROPERTY_GET(QuickCheckNFDIndexPtr, QuickCheckNFDDataPtr, _cp)
+
+#define PROPERTY_GET_NFKC(_cp) \
+	PROPERTY_GET(QuickCheckNFKCIndexPtr, QuickCheckNFKCDataPtr, _cp)
+
+#define PROPERTY_GET_NFKD(_cp) \
+	PROPERTY_GET(QuickCheckNFKDIndexPtr, QuickCheckNFKDDataPtr, _cp)
+
+const char* database_querydecomposition(unicode_t codepoint, const uint32_t* index1Array, const uint32_t* index2Array, const uint32_t* dataArray, uint8_t* length);
+
+unicode_t database_querycomposition(unicode_t left, unicode_t right);
+
+/*! \endcond */
+
+#endif /* _UTF8REWIND_INTERNAL_DATABASE_H_ */
+ third_party/utf8rewind/source/internal/decomposition.c view
@@ -0,0 +1,339 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "decomposition.h"
+
+#include "codepoint.h"
+#include "database.h"
+
+uint8_t decompose_initialize(
+	DecomposeState* state,
+	StreamState* input, StreamState* output,
+	uint8_t compatibility)
+{
+	memset(state, 0, sizeof(DecomposeState));
+
+	/* Ensure streams are valid */
+
+	if (input == 0 ||
+		output == 0)
+	{
+		return 0;
+	}
+
+	/* Set up streams */
+
+	state->input = input;
+
+	state->output = output;
+	memset(state->output, 0, sizeof(StreamState));
+
+	/* Set up codepoint quickcheck property */
+
+	if (compatibility == 1)
+	{
+		state->property_index1 = NFKDIndex1Ptr;
+		state->property_index2 = NFKDIndex2Ptr;
+		state->property_data = NFKDDataPtr;
+
+		state->qc_index = QuickCheckNFKDIndexPtr;
+		state->qc_data = QuickCheckNFKDDataPtr;
+	}
+	else
+	{
+		state->property_index1 = NFDIndex1Ptr;
+		state->property_index2 = NFDIndex2Ptr;
+		state->property_data = NFDDataPtr;
+
+		state->qc_index = QuickCheckNFDIndexPtr;
+		state->qc_data = QuickCheckNFDDataPtr;
+	}
+
+	return 1;
+}
+
+uint8_t decompose_execute(DecomposeState* state)
+{
+	unicode_t* src_codepoint;
+	unicode_t* dst_codepoint;
+	uint8_t* dst_canonical_combining_class;
+	uint8_t* dst_quick_check;
+	uint8_t uncached = 1;
+
+	/* Check if input is valid */
+
+	if (state->input == 0)
+	{
+		return 0;
+	}
+
+	/* Set up output */
+
+	state->output->current = 0;
+	state->output->index = 0;
+	state->output->stable = 1;
+
+	dst_codepoint = state->output->codepoint;
+	dst_canonical_combining_class = state->output->canonical_combining_class;
+	dst_quick_check = state->output->quick_check;
+
+	/* Check cache for stored sequences */
+
+	if (state->cache_current < state->cache_filled)
+	{
+		/* Read from cache */
+
+		while (state->cache_current < state->cache_filled)
+		{
+			if (state->output->current > 0 &&
+				state->cache_canonical_combining_class[state->cache_current] == CCC_NOT_REORDERED)
+			{
+				/* Sequence ends on next non-starter or end of data */
+
+				break;
+			}
+
+			*dst_codepoint++ = state->cache_codepoint[state->cache_current];
+			*dst_canonical_combining_class++ = state->cache_canonical_combining_class[state->cache_current];
+			*dst_quick_check++ = QuickCheckResult_Yes;
+
+			state->output->current++;
+			state->cache_current++;
+		}
+
+		/* Check if cache has been emptied */
+
+		if (state->cache_current == state->cache_filled)
+		{
+			state->cache_current = 0;
+			state->cache_filled = 0;
+		}
+
+		/* Check for additional input */
+
+		if (state->input->index == state->input->current)
+		{
+			/* Don't compare canonical combining classes, output will always be stable */
+
+			return state->output->current;
+		}
+	}
+
+	/* Read next sequence from input */
+
+	if (state->input->index == state->input->current &&
+		!stream_read(state->input, state->qc_index, state->qc_data))
+	{
+		/* End of data */
+
+		state->input = 0;
+
+		return 0;
+	}
+
+	/* Read from source */
+
+	src_codepoint = state->input->codepoint + state->input->index;
+
+	while (state->input->index < state->input->current)
+	{
+		if (*src_codepoint <= MAX_BASIC_LATIN)
+		{
+			/* Basic Latin codepoints are already decomposed */
+
+			if (uncached)
+			{
+				*dst_codepoint++ = *src_codepoint;
+				*dst_canonical_combining_class++ = CCC_NOT_REORDERED;
+				*dst_quick_check++ = QuickCheckResult_Yes;
+
+				state->output->current++;
+			}
+			else
+			{
+				state->cache_codepoint[state->cache_filled] = *src_codepoint;
+				state->cache_canonical_combining_class[state->cache_filled] = CCC_NOT_REORDERED;
+
+				state->cache_filled++;
+			}
+		}
+		else if (
+			*src_codepoint >= HANGUL_S_FIRST &&
+			*src_codepoint <= HANGUL_S_LAST)
+		{
+			/*
+				Hangul decomposition
+
+				Algorithm adapted from Unicode Technical Report #15:
+				http://www.unicode.org/reports/tr15/tr15-18.html#Hangul
+			*/
+
+			unicode_t s_index = *src_codepoint - HANGUL_S_FIRST;
+
+			if (uncached)
+			{
+				*dst_codepoint++ = HANGUL_L_FIRST + (s_index / HANGUL_N_COUNT);
+				*dst_canonical_combining_class++ = CCC_NOT_REORDERED;
+				*dst_quick_check++ = QuickCheckResult_Yes;
+
+				state->output->current++;
+			}
+			else
+			{
+				state->cache_codepoint[state->cache_filled] = HANGUL_L_FIRST + (s_index / HANGUL_N_COUNT);
+				state->cache_canonical_combining_class[state->cache_filled] = CCC_NOT_REORDERED;
+
+				state->cache_filled++;
+			}
+
+			/* Store subsequent non-starters in cache */
+
+			uncached = 0;
+
+			state->cache_codepoint[state->cache_filled] = HANGUL_V_FIRST + (s_index % HANGUL_N_COUNT) / HANGUL_T_COUNT;
+			state->cache_canonical_combining_class[state->cache_filled] = CCC_NOT_REORDERED;
+
+			state->cache_filled++;
+
+			if ((s_index % HANGUL_T_COUNT) != 0)
+			{
+				state->cache_codepoint[state->cache_filled] = HANGUL_T_FIRST + (s_index % HANGUL_T_COUNT);
+				state->cache_canonical_combining_class[state->cache_filled] = CCC_NOT_REORDERED;
+
+				state->cache_filled++;
+			}
+		}
+		else
+		{
+			/* Use quick check to skip stable codepoints */
+
+			unicode_t decoded_codepoint = *src_codepoint;
+			uint8_t decoded_quick_check = PROPERTY_GET(state->qc_index, state->qc_data, decoded_codepoint);
+			uint8_t decoded_canonical_combining_class;
+			uint8_t decoded_size;
+
+			if (decoded_quick_check != QuickCheckResult_Yes)
+			{
+				/* Check database for decomposition */
+
+				uint8_t src_size;
+				const char* src = database_querydecomposition(
+					decoded_codepoint,
+					state->property_index1, state->property_index2, state->property_data,
+					&src_size);
+
+				while (src_size > 0)
+				{
+					/* Decode current codepoint */
+
+					decoded_size = codepoint_read(src, src_size, &decoded_codepoint);
+					if (decoded_size == 0)
+					{
+						break;
+					}
+
+					decoded_canonical_combining_class = PROPERTY_GET_CCC(decoded_codepoint);
+
+					/* Check for end of sequence */
+
+					if (uncached &&
+						state->output->current > 0 &&
+						decoded_canonical_combining_class == CCC_NOT_REORDERED)
+					{
+						uncached = 0;
+					}
+
+					if (uncached)
+					{
+						/* Write codepoint to output */
+
+						*dst_codepoint++ = decoded_codepoint;
+						*dst_canonical_combining_class++ = decoded_canonical_combining_class;
+						*dst_quick_check++ = QuickCheckResult_Yes;
+
+						state->output->current++;
+					}
+					else
+					{
+						/* Store in cache */
+
+						state->cache_codepoint[state->cache_filled] = decoded_codepoint;
+						state->cache_canonical_combining_class[state->cache_filled] = decoded_canonical_combining_class;
+
+						state->cache_filled++;
+					}
+
+					src += decoded_size;
+					src_size -= decoded_size;
+				}
+			}
+			else
+			{
+				decoded_canonical_combining_class = PROPERTY_GET_CCC(decoded_codepoint);
+
+				if (uncached)
+				{
+					/* Write codepoint to output */
+
+					*dst_codepoint++ = decoded_codepoint;
+					*dst_canonical_combining_class++ = decoded_canonical_combining_class;
+					*dst_quick_check++ = decoded_quick_check;
+
+					state->output->current++;
+				}
+				else
+				{
+					/* Store in cache */
+
+					state->cache_codepoint[state->cache_filled] = decoded_codepoint;
+					state->cache_canonical_combining_class[state->cache_filled] = decoded_canonical_combining_class;
+
+					state->cache_filled++;
+				}
+			}
+		}
+
+		src_codepoint++;
+		state->input->index++;
+	}
+
+	if (state->output->current > 1)
+	{
+		/* Check if output is stable by comparing canonical combining classes */
+
+		uint8_t i;
+		for (i = 1; i < state->output->current; ++i)
+		{
+			if (state->output->canonical_combining_class[i] < state->output->canonical_combining_class[i - 1])
+			{
+				state->output->stable = 0;
+
+				break;
+			}
+		}
+	}
+
+	return state->output->current;
+}
+ third_party/utf8rewind/source/internal/decomposition.h view
@@ -0,0 +1,59 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _UTF8REWIND_INTERNAL_DECOMPOSITION_H_
+#define _UTF8REWIND_INTERNAL_DECOMPOSITION_H_
+
+/*!
+	\file
+	\brief Decomposition interface.
+
+	\cond INTERNAL
+*/
+
+#include "utf8rewind.h"
+#include "streaming.h"
+
+typedef struct {
+	StreamState* input;
+	StreamState* output;
+	const size_t* qc_index;
+	const uint8_t* qc_data;
+	const uint32_t* property_index1;
+	const uint32_t* property_index2;
+	const uint32_t* property_data;
+	unicode_t cache_codepoint[STREAM_BUFFER_MAX];
+	uint8_t cache_canonical_combining_class[STREAM_BUFFER_MAX];
+	uint8_t cache_current;
+	uint8_t cache_filled;
+} DecomposeState;
+
+uint8_t decompose_initialize(DecomposeState* state, StreamState* input, StreamState* output, uint8_t compatibility);
+
+uint8_t decompose_execute(DecomposeState* state);
+
+/*! \endcond */
+
+#endif /* _UTF8REWIND_INTERNAL_DECOMPOSITION_H_ */
+ third_party/utf8rewind/source/internal/seeking.c view
@@ -0,0 +1,187 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "seeking.h"
+
+#include "codepoint.h"
+
+const char* seeking_forward(const char* input, const char* inputEnd, size_t inputSize, off_t offset)
+{
+	if (inputEnd <= input ||  /* Swapped parameters */
+		offset <= 0 ||        /* Invalid offset */
+		inputSize == 0)       /* Nothing to do */
+	{
+		return input;
+	}
+	else if (
+		offset >= (off_t)inputSize)  /* Out of bounds */
+	{
+		return inputEnd;
+	}
+
+	do
+	{
+		/* Get decoded length of next sequence */
+
+		uint8_t codepoint_length = codepoint_decoded_length[(uint8_t)*input];
+
+		if (codepoint_length > 1 &&
+			codepoint_length < 7)
+		{
+			/* Check all bytes of multi-byte sequence */
+
+			uint8_t i;
+
+			for (i = 0; i < codepoint_length; ++i)
+			{
+				/* Next byte of sequence */
+
+				input++;
+
+				if (input == inputEnd ||                             /* End of data */
+					codepoint_decoded_length[(uint8_t)*input] != 0)  /* Not a continuation byte */
+				{
+					break;
+				}
+			}
+		}
+		else
+		{
+			/* Skip to next sequence */
+
+			input++;
+		}
+	}
+	while (input < inputEnd &&
+		--offset > 0);
+
+	return input;
+}
+
+const char* seeking_rewind(const char* inputStart, const char* input, size_t inputSize, off_t offset)
+{
+	const char* marker;
+	const char* marker_valid;
+
+	if (inputStart >= input ||  /* Swapped parameters */
+		offset >= 0)            /* Invalid offset */
+	{
+		return input;
+	}
+	else if (
+		-offset >= (off_t)inputSize)  /* Out of bounds */
+	{
+		return inputStart;
+	}
+
+	/* Set up the marker */
+
+	marker = input - 1;
+	marker_valid = marker;
+
+	do
+	{
+		/* Move the cursor */
+
+		input--;
+
+		/* Move the marker until we encounter a valid sequence */
+
+		while (marker_valid == input)
+		{
+			uint8_t codepoint_length = codepoint_decoded_length[(uint8_t)*marker];
+
+			if (codepoint_length == 1 ||  /* Basic Latin */
+				codepoint_length == 7)    /* Illegal byte */
+			{
+				marker_valid = marker;
+
+				break;
+			}
+			else if (
+				codepoint_length > 1)
+			{
+				if (marker == inputStart &&
+					/* Not overlong */
+					marker_valid - inputStart == codepoint_length - 1)
+				{
+					/* Last sequence */
+
+					return marker;
+				}
+				else
+				{
+					/* Multi-byte sequence */
+
+					marker_valid = marker + codepoint_length - 1;
+
+					break;
+				}
+			}
+			else if (
+				marker <= inputStart)
+			{
+				/* Continuation bytes only */
+
+				marker_valid = marker;
+
+				break;
+			}
+			else
+			{
+				/* Move marker to next byte */
+
+				marker--;
+			}
+		}
+
+		/* Read the next part of a sequence */
+
+		if (input <= marker_valid)
+		{
+			if (marker == inputStart)
+			{
+				/* Last sequence */
+
+				return marker;
+			}
+			else
+			{
+				/* Move the cursor to the start of the sequence */
+
+				input = marker;
+
+				/* Reset the marker on the next byte */
+
+				marker--;
+				marker_valid = marker;
+			}
+		}
+	}
+	while (input >= inputStart &&
+		++offset < 0);
+
+	return input;
+}
+ third_party/utf8rewind/source/internal/seeking.h view
@@ -0,0 +1,44 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _UTF8REWIND_INTERNAL_SEEKING_H_
+#define _UTF8REWIND_INTERNAL_SEEKING_H_
+
+/*!
+	\file
+	\brief Seeking interface.
+
+	\cond INTERNAL
+*/
+
+#include "utf8rewind.h"
+
+const char* seeking_forward(const char* input, const char* inputEnd, size_t inputSize, off_t offset);
+
+const char* seeking_rewind(const char* inputStart, const char* input, size_t inputSize, off_t offset);
+
+/*! \endcond */
+
+#endif /* _UTF8REWIND_INTERNAL_SEEKING_H_ */
+ third_party/utf8rewind/source/internal/streaming.c view
@@ -0,0 +1,236 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "streaming.h"
+
+#include "codepoint.h"
+#include "database.h"
+
+uint8_t stream_initialize(StreamState* state, const char* input, size_t inputSize)
+{
+	memset(state, 0, sizeof(StreamState));
+
+	if (input == 0 ||
+		inputSize == 0)
+	{
+		return 0;
+	}
+
+	state->src = input;
+	state->src_size = inputSize;
+
+	state->stable = 1;
+
+	return 1;
+}
+
+uint8_t stream_read(StreamState* state, const size_t* propertyIndex, const uint8_t* propertyData)
+{
+	/* Ensure input is available */
+
+	if (state->src_size == 0 ||
+		propertyIndex == 0 ||
+		propertyData == 0)
+	{
+		return 0;
+	}
+
+	/* Reset sequence after the first pass */
+
+	if (state->filled > 0)
+	{
+		/* Check for end of data */
+
+		if (state->filled == state->current &&
+			state->src_size <= state->last_length)
+		{
+			state->src_size = 0;
+
+			state->index = 0;
+			state->current = 0;
+			state->filled = 0;
+
+			return 0;
+		}
+
+		/* Copy last peeked codepoint to new sequence */
+
+		state->codepoint[0]                  = state->codepoint[state->filled - 1];
+		state->canonical_combining_class[0]  = state->canonical_combining_class[state->filled - 1];
+		state->quick_check[0]                = state->quick_check[state->filled - 1];
+
+		/* New sequence always starts as stable */
+
+		state->stable = 1;
+
+		/* Reset buffer members */
+
+		state->index = 0;
+		state->current = 1;
+		state->filled = 1;
+	}
+
+	/* Read codepoints */
+
+	while (state->filled < STREAM_SAFE_MAX)
+	{
+		/* Move the input cursor after peeking */
+
+		if (state->last_length > 0)
+		{
+			if (state->src_size <= state->last_length)
+			{
+				state->src += state->src_size;
+				state->src_size = 0;
+
+				break;
+			}
+
+			state->src += state->last_length;
+			state->src_size -= state->last_length;
+		}
+
+		/* Peek the next codepoint */
+
+		state->last_length = codepoint_read(state->src, state->src_size, &state->codepoint[state->filled]);
+		state->quick_check[state->filled] = PROPERTY_GET(propertyIndex, propertyData, state->codepoint[state->filled]);
+		state->canonical_combining_class[state->filled] = PROPERTY_GET_CCC(state->codepoint[state->filled]);
+
+		state->filled++;
+
+		if (state->current > 0)
+		{
+			/* Sequences end on the next starter and can consist of only non-starters */
+
+			if (state->canonical_combining_class[state->current] == 0)
+			{
+				break;
+			}
+
+			/* Check if sequence is unstable by comparing canonical combining classes */
+
+			if (state->stable &&
+				state->canonical_combining_class[state->current] < state->canonical_combining_class[state->current - 1])
+			{
+				state->stable = 0;
+			}
+		}
+
+		state->current++;
+	}
+
+	if (state->filled == STREAM_SAFE_MAX)
+	{
+		/* Insert COMBINING GRAPHEME JOINER into output */
+
+		state->codepoint[state->filled]                  = CP_COMBINING_GRAPHEME_JOINER;
+		state->quick_check[state->filled]                = QuickCheckResult_Yes;
+		state->canonical_combining_class[state->filled]  = CCC_NOT_REORDERED;
+
+		state->filled++;
+	}
+
+	return 1;
+}
+
+uint8_t stream_write(StreamState* state, char** output, size_t* outputSize, uint8_t* bytesWritten)
+{
+	uint8_t i;
+
+	if (state->current == 0)
+	{
+		/* Nothing to write */
+
+		*bytesWritten = 0;
+
+		return 1;
+	}
+
+	/* Encode code points as UTF-8 */
+
+	for (i = 0; i < state->current; ++i)
+	{
+		uint8_t encoded_size = codepoint_write(state->codepoint[i], output, outputSize);
+		if (encoded_size == 0)
+		{
+			/* Not enough space */
+
+			return 0;
+		}
+
+		*bytesWritten += encoded_size;
+	}
+
+	return 1;
+}
+
+uint8_t stream_reorder(StreamState* state)
+{
+	uint8_t i;
+	uint8_t dirty = 1;
+
+	if (state->current == 0)
+	{
+		/* Nothing to do */
+
+		return 0;
+	}
+
+	/* Reorder codepoints until the entire sequence is table */
+
+	do
+	{
+		dirty = 0;
+
+		for (i = 1; i < state->current; i++)
+		{
+			/* Sort codepoints by canonical combining class, smallest to largest */
+
+			if (state->canonical_combining_class[i] < state->canonical_combining_class[i - 1])
+			{
+				unicode_t swap_cp;
+				uint8_t swap_qc;
+				uint8_t swap_ccc;
+
+				swap_cp = state->codepoint[i];
+				state->codepoint[i] = state->codepoint[i - 1];
+				state->codepoint[i - 1] = swap_cp;
+
+				swap_qc = state->quick_check[i];
+				state->quick_check[i] = state->quick_check[i - 1];
+				state->quick_check[i - 1] = swap_qc;
+
+				swap_ccc = state->canonical_combining_class[i];
+				state->canonical_combining_class[i] = state->canonical_combining_class[i - 1];
+				state->canonical_combining_class[i - 1] = swap_ccc;
+
+				dirty = 1;
+			}
+		}
+	}
+	while (dirty == 1);
+
+	return 1;
+}
+ third_party/utf8rewind/source/internal/streaming.h view
@@ -0,0 +1,84 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _UTF8REWIND_INTERNAL_STREAMING_H_
+#define _UTF8REWIND_INTERNAL_STREAMING_H_
+
+/*!
+	\file
+	\brief Streaming interface.
+
+	\cond INTERNAL
+*/
+
+#include "utf8rewind.h"
+
+/*
+	UAX15-D4. Stream-Safe Text Process
+		
+	This is the process of producing a Unicode string in Stream-Safe Text Format by processing that string
+	from start to finish, inserting U+034F COMBINING GRAPHEME JOINER (CGJ) within long sequences of
+	non-starters. The exact position of the inserted CGJs are determined according to the following algorithm,
+	which describes the generation of an output string from an input string:
+
+	* If the input string is empty, return an empty output string.
+	* Set nonStarterCount to zero.
+	* For each code point C in the input string:
+		* Produce the NFKD decomposition S.
+		* If nonStarterCount plus the number of initial non-starters in S is greater than 30, append a CGJ to
+			the output string and set the nonStarterCount to zero.
+		* Append C to the output string.
+		* If there are no starters in S, increment nonStarterCount by the number of code points in S; otherwise,
+			set nonStarterCount to the number of trailing non-starters in S (which may be zero).
+	* Return the output string.
+*/
+
+#define STREAM_SAFE_MAX 30
+#define STREAM_BUFFER_MAX 32
+
+typedef struct {
+	const char* src;
+	size_t src_size;
+	uint8_t index;
+	uint8_t current;
+	uint8_t filled;
+	uint8_t stable;
+	uint8_t last_length;
+	unicode_t codepoint[STREAM_BUFFER_MAX];
+	uint8_t quick_check[STREAM_BUFFER_MAX];
+	uint8_t canonical_combining_class[STREAM_BUFFER_MAX];
+} StreamState;
+
+uint8_t stream_initialize(StreamState* state, const char* input, size_t inputSize);
+
+uint8_t stream_read(StreamState* state, const size_t* propertyIndex, const uint8_t* propertyData);
+
+uint8_t stream_write(StreamState* state, char** output, size_t* outputSize, uint8_t* bytesWritten);
+
+uint8_t stream_reorder(StreamState* state);
+
+/*! \endcond */
+
+#endif /* _UTF8REWIND_INTERNAL_STREAMING_H_ */
+ third_party/utf8rewind/source/unicodedatabase.c view
@@ -0,0 +1,11739 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	DO NOT MODIFY, AUTO-GENERATED
+
+	Generated on:
+		2016-02-01T14:10:25
+
+	Command line:
+		tools\converter\unicodedata.py
+*/
+
+#include "unicodedatabase.h"
+
+const size_t GeneralCategoryIndex[34816] = {
+	0, 32, 64, 96, 0, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 224, 480, 512, 544, 576, 608, 640, 672, 704, 704, 704, 736, 768, 800, 832, 864,
+	896, 928, 527, 224, 960, 224, 992, 224, 224, 1024, 1056, 1088, 1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1280, 1280, 1376, 1408, 1440, 1472, 1504, 1280, 1280, 1536, 1568, 1600,
+	1632, 1664, 1696, 1728, 1727, 1760, 1727, 1792, 1824, 1856, 1888, 1920, 1952, 1984, 2016, 2048, 2080, 2112, 2144, 2176, 2208, 2240, 2272, 2304, 2336, 2368, 2400, 2432, 2464, 2496, 2528, 2560,
+	2592, 2624, 2656, 2688, 2720, 2752, 2784, 2816, 2720, 2848, 2880, 2912, 2944, 2976, 3008, 3040, 3072, 3104, 3136, 1727, 3168, 3200, 3232, 1727, 3264, 3296, 3328, 3360, 3392, 3424, 3456, 1727,
+	1280, 3488, 3520, 3552, 3584, 893, 3616, 3648, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 3680, 1280, 3712, 3744, 3776, 1280, 3808, 1280, 3840, 3872, 3904, 1280, 1280, 3936,
+	3968, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 4000, 4032, 1280, 1280, 4064, 4096, 4128, 4160, 4192, 1280, 4224, 4256, 4288,
+	4320, 1280, 4352, 4384, 1280, 4416, 1280, 4448, 4480, 4512, 4544, 4576, 1280, 4608, 4640, 4672, 4704, 1280, 4736, 4768, 4800, 4832, 1727, 1727, 4864, 4896, 4928, 4960, 4992, 5024, 1280, 5056,
+	1280, 5088, 5120, 5152, 1727, 1727, 5184, 5216, 527, 5248, 5280, 5312, 597, 5260, 704, 5344, 224, 224, 224, 224, 5376, 224, 224, 224, 5408, 5440, 5472, 5504, 5536, 5568, 5600, 5632,
+	5664, 5696, 5728, 5760, 5792, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112, 6144, 6176, 6164, 6164, 6164, 6164, 6164, 6164, 6164, 6208, 6240, 4670, 6272, 6304, 6336, 6368, 6400,
+	4670, 6432, 6464, 6496, 6528, 4670, 4670, 6560, 4670, 4670, 4670, 4670, 4670, 6592, 6093, 6624, 4670, 4670, 4670, 6656, 4670, 4670, 4670, 4670, 4670, 4670, 4670, 6688, 6720, 4670, 6752, 6784,
+	4670, 4670, 4670, 4670, 4670, 4670, 4670, 4670, 6164, 6164, 6164, 6164, 6816, 6164, 6848, 6880, 6164, 6164, 6164, 6164, 6164, 6164, 6164, 6164, 4670, 6912, 6944, 6976, 7008, 7040, 7072, 1727,
+	893, 7104, 7136, 7168, 224, 224, 224, 7200, 527, 7232, 1280, 7264, 7296, 7328, 7328, 704, 7360, 7392, 7424, 1727, 7456, 4670, 4670, 7488, 4670, 4670, 4670, 4670, 4670, 4670, 7520, 7552,
+	7584, 7616, 3336, 1280, 7648, 3968, 1280, 7680, 4427, 7712, 1280, 1280, 7744, 1200, 4670, 7776, 7808, 7840, 7872, 4670, 7840, 7904, 4670, 7808, 4670, 4670, 4670, 4670, 4670, 4670, 4670, 4670,
+	7936, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 7968, 4670, 4670, 7936, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 8000, 1727,
+	8032, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280,
+	1280, 1280, 1280, 1280, 8064, 4670, 8096, 8128, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 8160, 8192, 224, 8224, 8256, 1280, 1280, 8288, 8320, 8352, 224, 8384, 8416, 8448, 1727, 8480,
+	8512, 8544, 1280, 8576, 8608, 8640, 8672, 8704, 1568, 8736, 8768, 8800, 1824, 8832, 8864, 8896, 1280, 8928, 8960, 8992, 1280, 9024, 9056, 9088, 9120, 9152, 9184, 9216, 1727, 1727, 1280, 9248,
+	7936, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 9280, 9312, 9344,
+	9376, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 9408, 9376, 1727, 1727, 9440,
+	9376, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 9440,
+	9472, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 9504, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 9536, 1280, 1280, 9568, 1727, 9600, 9632, 9664, 1280, 1280, 9696, 9728, 1280,
+	1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 9760, 1744, 1280, 9792, 1280, 9824, 9856, 9888, 9920, 9952, 9984, 1280, 1280, 1280, 10016, 10048, 10080, 10112, 10144, 5146, 4480, 10176, 10208,
+	10240, 10272, 10304, 1727, 1280, 1280, 1280, 1200, 10336, 10368, 6016, 10400, 10432, 10464, 10496, 10528, 1727, 1727, 1727, 1727, 8800, 1280, 10560, 10592, 1280, 10624, 10656, 10688, 10720, 1280, 10752, 1727,
+	893, 10784, 10816, 1280, 4560, 10848, 1727, 1727, 1280, 10880, 1280, 10912, 1727, 1727, 1727, 1727, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 7296, 9810, 10944, 1727, 1727, 1727, 1727,
+	10976, 11008, 11040, 11072, 4480, 11104, 1727, 1727, 11136, 11168, 1727, 1727, 1280, 11200, 1727, 1727, 11232, 11264, 11296, 11328, 11360, 1727, 11392, 11424, 1280, 11456, 11488, 11520, 11552, 11584, 1727, 1727,
+	1280, 1280, 11616, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 11648, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	11680, 11712, 11744, 11776, 4992, 11808, 11840, 11872, 11904, 11936, 11968, 12000, 4992, 12032, 12064, 12096, 12128, 12160, 1727, 1727, 1727, 1744, 12192, 12224, 2336, 12256, 12288, 12320, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1280, 12352, 12384, 1727, 1727, 1727, 1727, 1727, 1280, 12416, 12448, 1727, 1280, 12480, 12512, 1727, 1280, 12544, 10848, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 893, 527, 12576, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1280, 11856, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 11856, 1727, 1727, 1727,
+	6016, 6016, 6016, 12608, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280,
+	1280, 12640, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 11856, 4480, 12672, 1727, 1727, 1744, 12704, 1280, 12736, 12768, 12800, 12832, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1280, 1280, 12864, 12896, 12928, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	12960, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1280, 1280, 1280, 12992, 13024, 13056, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	4670, 4670, 4670, 4670, 4670, 4670, 4670, 7520, 4670, 6989, 4670, 13088, 13120, 13152, 13184, 1727, 4670, 4670, 13216, 1727, 1727, 1727, 1727, 1727, 4670, 4670, 8080, 13248, 1727, 1727, 1727, 1727,
+	13280, 13312, 13344, 13324, 13376, 13408, 13440, 13472, 13504, 13536, 13568, 13600, 13632, 13280, 13664, 13696, 13324, 13304, 13728, 13760, 13792, 13824, 13856, 13888, 13920, 13952, 13984, 14016, 14048, 14080, 14112, 14144,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1280, 1280, 1280, 1280, 1280, 1280, 14176, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 14208, 14240, 14272, 14304, 14336, 14368, 1727, 14400, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	4670, 14432, 4670, 4670, 14464, 14496, 14528, 7520, 14560, 14592, 4670, 14432, 14624, 1727, 1727, 14656, 14688, 14720, 14752, 1727, 1727, 1727, 1727, 1727, 4670, 14784, 4670, 14816, 4670, 4670, 14848, 14880,
+	4670, 4670, 4670, 4670, 4670, 4670, 4670, 7808, 4670, 4670, 14912, 7456, 4670, 14944, 4670, 4670, 4670, 4670, 6993, 4670, 4670, 4670, 14976, 15008, 4670, 4670, 4670, 15040, 4670, 4670, 14630, 1727,
+	14432, 4670, 15072, 4670, 15104, 15136, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	7936, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 7990, 1727, 7936, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 15168, 7936, 1727, 1727, 1727, 1727, 1727,
+	15200, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 4560, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	15232, 15264, 15264, 15264, 1727, 1727, 1727, 1727, 704, 704, 704, 704, 704, 704, 704, 15296, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	9472, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 15328,
+	9472, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727,
+	1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 15360,
+};
+const size_t* GeneralCategoryIndexPtr = GeneralCategoryIndex;
+
+const uint32_t GeneralCategoryData[15392] = {
+	0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000, 0x2000000,
+	0x400000, 0x20000, 0x20000, 0x20000, 0x80000, 0x20000, 0x20000, 0x20000, 0x2000, 0x4000, 0x20000, 0x40000, 0x20000, 0x1000, 0x20000, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x40000, 0x40000, 0x40000, 0x20000,
+	0x20000, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2000, 0x20000, 0x4000, 0x100000, 0x800,
+	0x100000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x2000, 0x40000, 0x4000, 0x40000, 0x2000000,
+	0x400000, 0x20000, 0x80000, 0x80000, 0x80000, 0x80000, 0x200000, 0x20000, 0x100000, 0x200000, 0x10, 0x8000, 0x40000, 0x4000000, 0x200000, 0x100000, 0x200000, 0x40000, 0x400, 0x400, 0x100000, 0x02, 0x20000, 0x20000, 0x100000, 0x400, 0x10, 0x10000, 0x400, 0x400, 0x400, 0x20000,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40000, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
+	0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02,
+	0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x10, 0x01, 0x02, 0x02, 0x02,
+	0x10, 0x10, 0x10, 0x10, 0x01, 0x04, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02,
+	0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x100000, 0x100000, 0x100000, 0x100000, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000,
+	0x08, 0x08, 0x08, 0x08, 0x08, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x08, 0x100000, 0x08, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x02, 0x01, 0x02, 0x08, 0x100000, 0x01, 0x02, 0x00, 0x00, 0x08, 0x02, 0x02, 0x02, 0x20000, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x100000, 0x100000, 0x01, 0x20000, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x40000, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x01, 0x02, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x20, 0x80, 0x80, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
+	0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x08, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000,
+	0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x20000, 0x1000, 0x00, 0x00, 0x200000, 0x200000, 0x80000, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1000, 0x20,
+	0x20000, 0x20, 0x20, 0x20000, 0x20, 0x20, 0x20000, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x40000, 0x40000, 0x40000, 0x20000, 0x20000, 0x80000, 0x20000, 0x20000, 0x200000, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x4000000, 0x00, 0x20000, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x20000, 0x20000, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4000000, 0x200000, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x08, 0x08, 0x20, 0x20, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x10, 0x200000, 0x200000, 0x10,
+	0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x4000000, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x08, 0x08, 0x200000, 0x20000, 0x20000, 0x20000, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x08, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x08, 0x20, 0x20, 0x20, 0x08, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20000, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x20, 0x10, 0x40, 0x40,
+	0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x20, 0x40, 0x40, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x20, 0x20, 0x20000, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x20, 0x40, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x10, 0x40, 0x40,
+	0x40, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10,
+	0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x80000, 0x80000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x80000, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x20, 0x20, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x00, 0x40, 0x40,
+	0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20, 0x20, 0x10, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x20, 0x20, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x10, 0x40, 0x40,
+	0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x40, 0x00, 0x40, 0x40, 0x20, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x80000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x20, 0x40, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x10, 0x40, 0x20,
+	0x40, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10,
+	0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x200000, 0x10, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x20, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,
+	0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40,
+	0x20, 0x40, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x20, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x80000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x40, 0x40, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20,
+	0x20, 0x40, 0x40, 0x40, 0x40, 0x00, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000,
+	0x00, 0x20, 0x40, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x10, 0x40, 0x20,
+	0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x20, 0x40, 0x40, 0x00, 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+	0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x40, 0x40,
+	0x40, 0x20, 0x20, 0x20, 0x20, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x200000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x00, 0x00, 0x40, 0x40, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x40, 0x40, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x80000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x08, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x200000, 0x200000, 0x200000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x200000, 0x20000, 0x200000, 0x200000, 0x200000, 0x20, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x20, 0x200000, 0x20, 0x200000, 0x20, 0x2000, 0x4000, 0x2000, 0x4000, 0x40, 0x40,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x200000, 0x200000, 0x200000, 0x200000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x10,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20,
+	0x20, 0x10, 0x40, 0x40, 0x40, 0x10, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x20, 0x40, 0x40, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x10, 0x40, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x40, 0x40, 0x40, 0x20, 0x200000, 0x200000,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x08, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,
+	0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x20,
+	0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x1000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x400000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x2000, 0x4000, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x20000, 0x200, 0x200, 0x200, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40,
+	0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x08, 0x20000, 0x20000, 0x20000, 0x80000, 0x10, 0x20, 0x00, 0x00,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x1000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20, 0x20, 0x20, 0x4000000, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,
+	0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+	0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x400, 0x00, 0x00, 0x00, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x20, 0x00, 0x00, 0x20000, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00,
+	0x20, 0x40, 0x20, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x08, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x80, 0x00,
+	0x20, 0x20, 0x20, 0x20, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x40, 0x40, 0x40,
+	0x40, 0x40, 0x20, 0x40, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000,
+	0x20000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00,
+	0x20, 0x20, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x40, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x20, 0x20, 0x40, 0x40, 0x40, 0x20, 0x40, 0x20, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x20000, 0x20000,
+	0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20000, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x20, 0x10, 0x10, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x04, 0x100000, 0x02, 0x100000,
+	0x100000, 0x100000, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x04, 0x100000, 0x100000, 0x100000, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x100000, 0x100000, 0x100000,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x100000, 0x100000, 0x100000, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x04, 0x100000, 0x100000, 0x00,
+	0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x20000, 0x20000, 0x8000, 0x10000, 0x2000, 0x8000, 0x8000, 0x10000, 0x2000, 0x8000,
+	0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x800000, 0x1000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x400000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x8000, 0x10000, 0x20000, 0x20000, 0x20000, 0x20000, 0x800,
+	0x800, 0x20000, 0x20000, 0x20000, 0x40000, 0x2000, 0x4000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x40000, 0x20000, 0x800, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x400000,
+	0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x00, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x400, 0x08, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x08,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+	0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x80000, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x80, 0x80, 0x80,
+	0x80, 0x20, 0x80, 0x80, 0x80, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x01, 0x200000, 0x200000, 0x200000, 0x200000, 0x01, 0x200000, 0x200000, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x200000, 0x01, 0x200000, 0x200000, 0x40000, 0x01, 0x01, 0x01, 0x01, 0x01, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x01, 0x200000, 0x01, 0x200000, 0x01, 0x200000, 0x01, 0x01, 0x01, 0x01, 0x200000, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x10, 0x10, 0x10, 0x10, 0x02, 0x200000, 0x200000, 0x02, 0x02, 0x01, 0x01,
+	0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x01, 0x02, 0x02, 0x02, 0x02, 0x200000, 0x40000, 0x200000, 0x200000, 0x02, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200,
+	0x200, 0x200, 0x200, 0x01, 0x02, 0x200, 0x200, 0x200, 0x200, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x40000, 0x200000, 0x200000, 0x40000, 0x200000, 0x200000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x200000, 0x200000, 0x40000, 0x200000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,
+	0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x2000, 0x4000, 0x2000, 0x4000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x40000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x2000, 0x4000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,
+	0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000,
+	0x40000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,
+	0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,
+	0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,
+	0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x2000, 0x4000, 0x40000, 0x40000, 0x40000, 0x40000,
+	0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x2000, 0x4000, 0x40000, 0x40000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000,
+	0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x200000, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x08, 0x08, 0x01, 0x01,
+	0x01, 0x02, 0x01, 0x02, 0x02, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x01, 0x02, 0x01, 0x02, 0x20, 0x20, 0x20, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x400, 0x20000, 0x20000,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,
+	0x20000, 0x20000, 0x8000, 0x10000, 0x8000, 0x10000, 0x20000, 0x20000, 0x20000, 0x8000, 0x10000, 0x20000, 0x8000, 0x10000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x1000, 0x20000, 0x20000, 0x1000, 0x20000, 0x8000, 0x10000, 0x20000, 0x20000,
+	0x8000, 0x10000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x08, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x1000, 0x1000, 0x20000, 0x20000, 0x20000, 0x20000,
+	0x1000, 0x20000, 0x2000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00,
+	0x400000, 0x20000, 0x20000, 0x20000, 0x200000, 0x08, 0x10, 0x200, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x200000, 0x200000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x1000, 0x2000, 0x4000, 0x4000,
+	0x200000, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x1000, 0x08, 0x08, 0x08, 0x08, 0x08, 0x200000, 0x200000, 0x200, 0x200, 0x200, 0x08, 0x10, 0x20000, 0x200000, 0x200000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x100000, 0x100000, 0x08, 0x08, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x08, 0x08, 0x08, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x200000, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x20000, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x20000, 0x20000, 0x20000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x10, 0x20, 0x80, 0x80, 0x80, 0x20000, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x08,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x08, 0x08, 0x00, 0x20,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	0x100000, 0x100000, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x02,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x08, 0x100000, 0x100000, 0x01, 0x02, 0x01, 0x02, 0x00, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
+	0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x08, 0x02, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x40, 0x40, 0x20, 0x20, 0x40, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x80000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x40, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+	0x40, 0x40, 0x40, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x20000, 0x10, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x20000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x40, 0x40, 0x40,
+	0x40, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x08, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x200000, 0x200000, 0x200000, 0x10, 0x40, 0x20, 0x40, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x20, 0x20, 0x20, 0x10, 0x10, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20,
+	0x10, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x20000, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x20, 0x20, 0x40, 0x40, 0x20000, 0x20000, 0x10, 0x08, 0x08, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x100000, 0x08, 0x08, 0x08, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x40, 0x40, 0x20, 0x40, 0x40, 0x20, 0x40, 0x40, 0x20000, 0x40, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+	0x8000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8000000,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8000000,
+	0x10000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10000000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00,
+	0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000,
+	0x100000, 0x100000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x4000, 0x2000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x80000, 0x200000, 0x00, 0x00,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x2000, 0x4000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20000, 0x1000, 0x1000, 0x800, 0x800, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000,
+	0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x20000, 0x20000, 0x2000, 0x4000, 0x20000, 0x20000, 0x20000, 0x20000, 0x800, 0x800, 0x800, 0x20000, 0x20000, 0x20000, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x1000, 0x2000, 0x4000, 0x2000, 0x4000, 0x2000, 0x4000, 0x20000,
+	0x20000, 0x20000, 0x40000, 0x1000, 0x40000, 0x40000, 0x40000, 0x00, 0x20000, 0x80000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x4000000,
+	0x00, 0x20000, 0x20000, 0x20000, 0x80000, 0x20000, 0x20000, 0x20000, 0x2000, 0x4000, 0x20000, 0x40000, 0x20000, 0x1000, 0x20000, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x40000, 0x40000, 0x40000, 0x20000,
+	0x20000, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2000, 0x20000, 0x4000, 0x100000, 0x800,
+	0x100000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x2000, 0x40000, 0x4000, 0x40000, 0x2000,
+	0x4000, 0x20000, 0x2000, 0x4000, 0x20000, 0x20000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
+	0x80000, 0x80000, 0x40000, 0x100000, 0x200000, 0x80000, 0x80000, 0x00, 0x200000, 0x40000, 0x40000, 0x40000, 0x40000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4000000, 0x4000000, 0x4000000, 0x200000, 0x200000, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
+	0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x400, 0x400, 0x200000, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x20, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00,
+	0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x200, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x200, 0x200, 0x200, 0x200, 0x200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x20000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x200000, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,
+	0x10, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x400, 0x400, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x400, 0x400, 0x400,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x200000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00,
+	0x40, 0x20, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x20000, 0x20000, 0x4000000, 0x20000, 0x20000,
+	0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
+	0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20000, 0x20000, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40,
+	0x40, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x40, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20,
+	0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x10, 0x40, 0x40,
+	0x20, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x40, 0x40, 0x40, 0x40, 0x20,
+	0x20, 0x40, 0x20, 0x20, 0x10, 0x10, 0x20000, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x40, 0x20,
+	0x20, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x40, 0x20,
+	0x20, 0x20000, 0x20000, 0x20000, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x20, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+	0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x00, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x08, 0x08, 0x08, 0x08, 0x20000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x400, 0x400, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+	0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x200000, 0x20, 0x20, 0x20000,
+	0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x40, 0x40, 0x20, 0x20, 0x20, 0x200000, 0x200000, 0x200000, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x200000, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00,
+	0x200000, 0x200000, 0x20, 0x20, 0x20, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01,
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40000, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40000, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x40000, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10,
+	0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40000, 0x40000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+	0x00, 0x4000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10000000, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10000000, 0x00, 0x00,
+};
+const uint32_t* GeneralCategoryDataPtr = GeneralCategoryData;
+
+const size_t CanonicalCombiningClassIndex[34816] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 64, 96, 128, 0, 0, 0, 0,
+	0, 0, 0, 0, 160, 0, 0, 0, 0, 0, 0, 0, 192, 224, 256, 0, 288, 0, 320, 352, 0, 0, 384, 416, 448, 480, 512, 0, 0, 0, 0, 544,
+	576, 608, 640, 0, 0, 0, 0, 672, 0, 704, 736, 0, 0, 704, 768, 0, 0, 704, 800, 0, 0, 704, 832, 0, 0, 704, 864, 0, 0, 0, 896, 0,
+	0, 0, 928, 0, 0, 704, 960, 0, 0, 0, 992, 0, 0, 0, 1024, 0, 0, 1056, 1088, 0, 0, 1120, 1152, 0, 1184, 1216, 0, 1248, 1280, 0, 1312, 0,
+	0, 1344, 0, 0, 1376, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1408, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1440, 1440, 0, 0, 0, 0, 1472, 0,
+	0, 0, 0, 0, 0, 1504, 0, 0, 0, 1536, 0, 0, 0, 0, 0, 0, 1568, 0, 0, 1600, 0, 1632, 0, 0, 0, 1664, 777, 1696, 0, 1728, 0, 1760,
+	0, 1792, 0, 0, 0, 0, 1824, 1856, 0, 0, 0, 0, 0, 0, 1888, 1920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 1952, 1984, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 1422, 0, 0, 0, 782, 0, 0, 0, 1905, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 2016, 0, 0, 2048, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2080, 2112, 0, 0, 2144, 0, 0, 0, 0, 0, 0, 0, 0,
+	1454, 0, 0, 0, 0, 0, 777, 2176, 0, 2208, 2240, 0, 0, 2272, 781, 0, 0, 0, 0, 0, 0, 2304, 2336, 951, 0, 0, 0, 0, 0, 0, 0, 2368,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2400, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2432, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2464, 0, 0, 0, 0, 0, 0, 0, 429, 0, 0, 0, 2496, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2528, 2560, 0, 0, 0, 0, 0, 2592, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 1454, 782, 0, 2624, 0, 0, 2656, 2688, 0, 2720, 0, 0, 781, 0, 0, 2752, 0, 0, 0, 0, 0, 2784, 0, 704, 2816, 2848, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 2880, 0, 0, 0, 0, 0, 0, 782, 2739, 0, 0, 782, 0, 0, 0, 2912, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2944, 0, 2976, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 3008, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3040, 3072, 3104, 0, 0, 0, 0, 2654, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 3136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const size_t* CanonicalCombiningClassIndexPtr = CanonicalCombiningClassIndex;
+
+const uint8_t CanonicalCombiningClassData[3168] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE8, 0xDC, 0xDC, 0xDC, 0xDC, 0xE8, 0xD8, 0xDC, 0xDC, 0xDC, 0xDC,
+	0xDC, 0xCA, 0xCA, 0xDC, 0xDC, 0xDC, 0xDC, 0xCA, 0xCA, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0x01, 0x01, 0x01, 0x01, 0x01, 0xDC, 0xDC, 0xDC, 0xDC, 0xE6, 0xE6, 0xE6,
+	0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xF0, 0xE6, 0xDC, 0xDC, 0xDC, 0xE6, 0xE6, 0xE6, 0xDC, 0xDC, 0x00, 0xE6, 0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0xDC, 0xE6, 0xE8, 0xDC, 0xDC, 0xE6, 0xE9, 0xEA, 0xEA, 0xE9,
+	0xEA, 0xEA, 0xE9, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xE6, 0xDE, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6,
+	0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xDE, 0xE4, 0xE6, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x00, 0x17,
+	0x00, 0x18, 0x19, 0x00, 0xE6, 0xDC, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x1E, 0x1F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0xE6, 0xE6, 0xDC, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xDC,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0xE6,
+	0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 0x00, 0x00, 0xE6, 0xE6, 0x00, 0xDC, 0xE6, 0xE6, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xDC, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0xE6, 0xDC, 0xDC, 0xE6, 0xDC, 0xE6,
+	0xE6, 0xE6, 0xDC, 0xE6, 0xDC, 0xE6, 0xDC, 0xE6, 0xDC, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+	0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0xE6, 0xE6, 0xE6, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0x1B, 0x1C, 0x1D, 0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xDC, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xE6, 0xDC, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x67, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x6B, 0x6B, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x7A, 0x7A, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0xDC, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x82, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00,
+	0x82, 0x00, 0xE6, 0xE6, 0x09, 0x00, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xE6, 0xDC, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0xDC,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xE6, 0xE6, 0xDC, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0x00, 0x01, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0xDC,
+	0xE6, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 0xE6, 0xEA, 0xD6, 0xDC, 0xCA, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+	0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0xDC, 0xE6, 0xDC,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0x01, 0x01, 0xE6, 0xE6, 0xE6, 0xE6, 0x01, 0x01, 0x01, 0xE6, 0xE6, 0x00, 0x00, 0x00,
+	0x00, 0xE6, 0x00, 0x00, 0x00, 0x01, 0x01, 0xE6, 0xDC, 0xE6, 0x01, 0x01, 0xDC, 0xDC, 0xDC, 0xDC, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDA, 0xE4, 0xE8, 0xDE, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x00, 0xE6, 0xE6, 0xDC, 0x00, 0x00, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6,
+	0x00, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00,
+	0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x01, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x09,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0xD8, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0xE2, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+	0xDC, 0xDC, 0xDC, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+const uint8_t* CanonicalCombiningClassDataPtr = CanonicalCombiningClassData;
+
+const size_t QuickCheckCaseMappedIndex[34816] = {
+	0, 0, 32, 64, 0, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 192, 448, 480, 512, 544, 0, 0, 0, 0, 0, 576, 608, 640, 672, 704, 736,
+	768, 800, 832, 192, 864, 192, 896, 192, 192, 928, 960, 992, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 765, 1056, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1088, 0, 0, 0, 0, 192, 192, 192, 192, 1120, 192, 192, 192, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 1408, 1440, 1472, 1504, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 1536, 1472, 1568, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	765, 1600, 1632, 1664, 192, 192, 192, 1696, 816, 1728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 1760, 1792, 0, 0, 0, 0, 1824, 192, 1856, 1888, 1920, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1952, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 1984, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	765, 2016, 2048, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 765, 816, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const size_t* QuickCheckCaseMappedIndexPtr = QuickCheckCaseMappedIndex;
+
+const uint8_t QuickCheckCaseMappedData[2080] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0D,
+	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A,
+	0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0D, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0D,
+	0x05, 0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x05, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x00, 0x0A, 0x0A, 0x05, 0x0A,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x0A, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x00, 0x00, 0x0A, 0x05, 0x00, 0x05,
+	0x00, 0x00, 0x00, 0x00, 0x0E, 0x0B, 0x05, 0x0E, 0x0B, 0x05, 0x0E, 0x0B, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x05, 0x0A, 0x05,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0D, 0x0E, 0x0B, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,
+	0x0A, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x05, 0x0A, 0x0A, 0x05,
+	0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x05, 0x05, 0x00, 0x05, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00,
+	0x05, 0x05, 0x00, 0x05, 0x00, 0x05, 0x05, 0x00, 0x05, 0x05, 0x00, 0x05, 0x05, 0x00, 0x00, 0x05, 0x00, 0x05, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+	0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x05, 0x05, 0x05, 0x00, 0x0A,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x0A, 0x0A, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x0A, 0x0D, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
+	0x0A, 0x0A, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x0D, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+	0x05, 0x05, 0x0D, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0A, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0D, 0x0D, 0x05, 0x05, 0x0A, 0x0D, 0x00, 0x0A, 0x05, 0x0A, 0x0A, 0x05, 0x00, 0x0A, 0x0A, 0x0A,
+	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
+	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+	0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,
+	0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
+	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x0A, 0x00,
+	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00,
+	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
+	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x0D, 0x05, 0x0D, 0x05, 0x0D, 0x05, 0x0D, 0x05, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A,
+	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00,
+	0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
+	0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x05, 0x05, 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x0D, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x00, 0x0D, 0x00,
+	0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x0D, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x00, 0x00, 0x00, 0x05, 0x05, 0x0D, 0x0D, 0x00, 0x00, 0x0D, 0x0D, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00,
+	0x05, 0x05, 0x0D, 0x0D, 0x0D, 0x05, 0x0D, 0x0D, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x0D, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+	0x00, 0x00, 0x00, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
+	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00,
+	0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x0A, 0x05, 0x00, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0A,
+	0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x05,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x00, 0x00, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,
+	0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+const uint8_t* QuickCheckCaseMappedDataPtr = QuickCheckCaseMappedData;
+
+const size_t QuickCheckNFCIndex[34816] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 64, 96, 128, 160, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 256, 0, 0, 288, 320, 0, 0, 352, 384, 0, 0, 0, 0, 0, 0, 288, 416, 0, 0, 288, 448, 0,
+	0, 0, 480, 0, 0, 0, 512, 0, 0, 288, 544, 0, 0, 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 608, 640, 672, 704, 0, 0,
+	0, 736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 768, 0, 800, 211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 832, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 864, 0, 896, 928, 960,
+	286, 0, 0, 0, 0, 0, 0, 0, 0, 992, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1024, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1056, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 1088, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1152, 1184, 1120, 1216, 1120, 1120, 1248, 0, 1280, 1312, 1344, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 1376, 0, 0, 0, 1408, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 288, 1440, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 1472, 0, 0, 0, 0, 0, 0, 0, 1448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1504, 1536, 0, 253, 167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1568, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const size_t* QuickCheckNFCIndexPtr = QuickCheckNFCIndex;
+
+const uint8_t QuickCheckNFCData[1600] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,
+	0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+};
+const uint8_t* QuickCheckNFCDataPtr = QuickCheckNFCData;
+
+const size_t QuickCheckNFDIndex[34816] = {
+	0, 0, 0, 0, 0, 0, 32, 64, 96, 128, 160, 192, 0, 224, 256, 288, 320, 352, 0, 0, 0, 0, 0, 0, 0, 0, 384, 416, 448, 480, 512, 0,
+	544, 576, 608, 640, 0, 0, 672, 704, 0, 0, 0, 0, 0, 0, 0, 0, 0, 736, 0, 0, 0, 0, 768, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 800, 832, 0, 0, 0, 864, 0, 0, 896, 928, 0, 0, 0, 0, 0, 0, 0, 960, 0, 992, 0, 1024, 0,
+	0, 0, 1056, 0, 0, 0, 1088, 0, 0, 0, 1024, 0, 0, 0, 1120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1152, 1184, 1216, 1248, 0, 0,
+	0, 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1312, 1344, 1376, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 312, 312, 312, 312, 1408, 312, 312, 1440, 1472, 312, 1504, 1536, 312, 1568, 1600, 1632,
+	1664, 0, 0, 0, 0, 0, 0, 0, 0, 1696, 0, 0, 1728, 1760, 1792, 0, 1824, 1856, 1888, 1920, 1952, 1984, 0, 2016, 0, 2048, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2080, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 2112, 2144, 2176, 2208, 2240, 2272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,
+	312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,
+	312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,
+	312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,
+	312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,
+	312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,
+	312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,
+	312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,
+	312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,
+	312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,
+	312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 2304, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 312, 312, 312, 312, 312, 312, 312, 312, 2336, 2368, 312, 2400, 312, 312, 1440, 0, 2432, 2464, 2496, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 2528, 2560, 0, 0, 0, 2592, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2624, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 2656, 0, 0, 0, 0, 0, 0, 0, 2688, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1775, 2720, 0, 2752, 820, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, 2784, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const size_t* QuickCheckNFDIndexPtr = QuickCheckNFDIndex;
+
+const uint8_t QuickCheckNFDData[2816] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,
+	0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,
+	0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,
+	0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,
+	0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+};
+const uint8_t* QuickCheckNFDDataPtr = QuickCheckNFDData;
+
+const size_t QuickCheckNFKCIndex[34816] = {
+	0, 0, 0, 0, 0, 32, 0, 0, 0, 64, 96, 128, 0, 0, 160, 192, 0, 0, 0, 0, 0, 224, 256, 288, 320, 352, 384, 416, 448, 0, 480, 512,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 544, 0, 0, 0, 0, 0, 576, 608, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 640, 672, 0, 0, 704, 736, 0, 0, 768, 800, 0, 0, 0, 0, 0, 0, 704, 832, 0, 0, 704, 864, 0,
+	0, 0, 896, 0, 0, 0, 928, 0, 0, 704, 960, 0, 0, 0, 992, 0, 0, 1024, 0, 0, 0, 1024, 1056, 0, 1088, 0, 1120, 1152, 1184, 1216, 0, 0,
+	0, 1248, 0, 0, 0, 0, 0, 1280, 0, 0, 0, 1312, 0, 1344, 595, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1376, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 1408, 1440, 1472, 669, 1504, 0, 0, 0, 0, 0, 0, 1536, 0, 0, 0, 0, 0, 0, 1568, 0, 1600, 1632, 1664,
+	1696, 1728, 1760, 1792, 1824, 97, 0, 0, 1856, 1888, 1920, 1504, 1034, 0, 0, 0, 0, 1952, 0, 0, 0, 0, 0, 0, 0, 1984, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 1504, 1504, 1504, 1504, 2016, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1229, 0, 0, 2048, 0, 0, 2080, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 2112, 0, 0, 0, 0, 0, 0, 0, 2144, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 1024, 1504, 1504, 1504, 1504, 1504, 1504, 2176, 0,
+	105, 2208, 0, 0, 2240, 0, 0, 249, 0, 2272, 1504, 1504, 2304, 0, 0, 0, 2336, 1504, 2368, 2400, 1504, 1504, 1504, 2432, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2464, 0, 0, 0, 0, 0, 0, 2496, 0, 0, 0, 1969,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 2528, 2560, 1504, 2592, 1504, 1504, 2624, 0, 2656, 2688, 2720, 1504, 1504, 2752, 2784, 1504,
+	1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 2289, 2160, 1504, 2816, 1504, 696, 2848, 2880, 2160, 2912, 2944, 1504, 1504, 1504, 2976, 1503, 1504, 1504, 1504, 1504, 2432, 3008, 3040,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 3072, 0, 0, 0, 3104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 704, 3136, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 3168, 0, 0, 0, 0, 0, 0, 0, 1008, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3200, 288, 0, 669, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1504, 1504, 3232, 1504, 3264, 3296, 3328, 1504, 3360, 3392, 3424, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 3456, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 3488, 1504,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3520, 3552, 3584, 3616, 3648, 3680, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 3712, 2416, 3744, 3776, 3808, 0, 0, 0, 3840, 3872, 3904, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 2289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const size_t* QuickCheckNFKCIndexPtr = QuickCheckNFKCIndex;
+
+const uint8_t QuickCheckNFKCData[3936] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,
+	0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,
+	0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+const uint8_t* QuickCheckNFKCDataPtr = QuickCheckNFKCData;
+
+const size_t QuickCheckNFKDIndex[34816] = {
+	0, 0, 0, 0, 0, 32, 64, 96, 128, 160, 192, 224, 0, 256, 288, 320, 352, 384, 0, 0, 0, 416, 448, 480, 0, 0, 512, 544, 576, 608, 640, 672,
+	704, 736, 768, 800, 0, 0, 832, 864, 0, 0, 0, 0, 896, 0, 0, 0, 0, 478, 0, 928, 0, 0, 960, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 992, 1024, 0, 0, 0, 1056, 0, 0, 1088, 1120, 0, 0, 0, 0, 0, 0, 0, 1152, 0, 1184, 0, 1216, 0,
+	0, 0, 1248, 0, 0, 0, 1280, 0, 0, 0, 1216, 0, 0, 0, 1312, 0, 0, 1344, 0, 0, 0, 1376, 1408, 0, 1440, 0, 1472, 1504, 1536, 1568, 0, 0,
+	0, 897, 0, 0, 0, 0, 0, 1600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1632, 1664, 1696, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 1728, 1760, 1792, 1824, 344, 0, 0, 344, 344, 344, 344, 1775, 344, 344, 232, 1856, 344, 1888, 1920, 344, 1952, 1984, 2016,
+	2048, 2080, 2112, 2144, 2176, 2208, 0, 0, 2240, 2272, 2304, 344, 2336, 1438, 2368, 0, 2400, 2432, 2464, 2496, 2528, 2560, 0, 2592, 0, 2624, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 344, 344, 344, 344, 2656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1581, 0, 0, 2688, 0, 0, 2720, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 2752, 0, 0, 0, 0, 0, 0, 0, 746, 0, 0, 0, 0, 0, 0, 0, 0, 441, 0, 0, 2784, 344, 344, 344, 344, 344, 344, 2816, 0,
+	440, 2848, 2880, 2912, 2944, 2976, 3008, 3040, 0, 3072, 344, 344, 3104, 0, 0, 0, 1919, 344, 3136, 1919, 344, 344, 344, 1919, 344, 344, 344, 344, 344, 344, 344, 344,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3168, 0, 0, 0, 0, 0, 0, 963, 0, 0, 0, 3200,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 404, 0, 0, 0, 0, 0,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 400, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 344, 344, 344, 344, 344, 344, 344, 344, 3232, 3264, 344, 3296, 344, 344, 232, 0, 3328, 3360, 3392, 344, 344, 3424, 273, 344,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 3089, 3456, 344, 326, 344, 3434, 3488, 3520, 3552, 3584, 3616, 344, 344, 344, 3648, 3397, 344, 344, 344, 344, 1919, 3680, 3712,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 3744, 2205, 0, 0, 0, 3776, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3808, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 3840, 0, 0, 0, 0, 0, 0, 0, 3198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3442, 480, 0, 3872, 440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	344, 344, 1952, 344, 3904, 3936, 3968, 344, 4000, 4032, 4064, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 4096, 344, 344, 344, 344, 344, 344, 344, 344, 4128, 344,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4160, 4192, 4224, 4256, 4288, 4320, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 4352, 4384, 3152, 4416, 963, 0, 0, 0, 4448, 4480, 4512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 3089, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+const size_t* QuickCheckNFKDIndexPtr = QuickCheckNFKDIndex;
+
+const uint8_t QuickCheckNFKDData[4544] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,
+	0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,
+	0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,
+	0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,
+	0x00, 0x02, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+const uint8_t* QuickCheckNFKDDataPtr = QuickCheckNFKDData;
+
+const uint32_t NFDIndex1[272] = {
+	0, 128, 256, 384, 512, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 640,
+	392, 768, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 896, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 1024,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+	392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
+};
+const uint32_t* NFDIndex1Ptr = NFDIndex1;
+
+const uint32_t NFDIndex2[1152] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0x0, 0xE0, 0x100, 0x120,
+	0x140, 0x160, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x180, 0x1A0, 0x1C0, 0x1E0, 0x200, 0x0,
+	0x220, 0x240, 0x260, 0x280, 0x0, 0x0, 0x2A0, 0x2C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x2E0, 0x0, 0x0, 0x0, 0x0, 0x300, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x320, 0x340, 0x0, 0x0, 0x0, 0x360, 0x0,
+	0x0, 0x380, 0x3A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3C0, 0x0, 0x3E0, 0x0, 0x400, 0x0,
+	0x0, 0x0, 0x420, 0x0, 0x0, 0x0, 0x440, 0x0, 0x0, 0x0, 0x460, 0x0, 0x0, 0x0, 0x480, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4A0, 0x4C0, 0x4E0, 0x500, 0x0, 0x0,
+	0x0, 0x520, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x540, 0x560, 0x580, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x5A0, 0x5C0, 0x5E0, 0x600, 0x620, 0x640, 0x660, 0x680, 0x6A0, 0x6C0, 0x6E0, 0x700, 0x720, 0x740, 0x760, 0x780,
+	0x7A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7C0, 0x0, 0x0, 0x7E0, 0x800, 0x820, 0x0,
+	0x840, 0x860, 0x880, 0x8A0, 0x8C0, 0x8E0, 0x0, 0x900, 0x0, 0x920, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x940, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x960, 0x980, 0x9A0, 0x9C0, 0x9E0, 0xA00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xA20, 0xA40, 0xA60, 0xA80, 0xAA0, 0xAC0, 0xAE0, 0xB00,
+	0xB20, 0xB40, 0xB60, 0xB80, 0xBA0, 0xBC0, 0xBE0, 0x0, 0xC00, 0xC20, 0xC40, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0xC60, 0xC80, 0x0, 0x0, 0x0, 0xCA0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xCC0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0xCE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xD00, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xD20, 0xD40, 0x0, 0xD60, 0xD80, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0xDA0, 0xDC0, 0xDE0, 0xE00, 0xE20, 0xE40, 0xE60, 0xE80, 0xEA0, 0xEC0, 0xEE0, 0xF00, 0xF20, 0xF40, 0xF60, 0xF80,
+	0xFA0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+};
+const uint32_t* NFDIndex2Ptr = NFDIndex2;
+
+const uint32_t NFDData[4032] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3000000, 0x3000003, 0x3000006, 0x3000009, 0x300000C, 0x300000F, 0x0, 0x3000012, 0x3000015, 0x3000018, 0x300001B, 0x300001E, 0x3000021, 0x3000024, 0x3000027, 0x300002A,
+	0x0, 0x300002D, 0x3000030, 0x3000033, 0x3000036, 0x3000039, 0x300003C, 0x0, 0x0, 0x300003F, 0x3000042, 0x3000045, 0x3000048, 0x300004B, 0x0, 0x0,
+	0x300004E, 0x3000051, 0x3000054, 0x3000057, 0x300005A, 0x300005D, 0x0, 0x3000060, 0x3000063, 0x3000066, 0x3000069, 0x300006C, 0x300006F, 0x3000072, 0x3000075, 0x3000078,
+	0x0, 0x300007B, 0x300007E, 0x3000081, 0x3000084, 0x3000087, 0x300008A, 0x0, 0x0, 0x300008D, 0x3000090, 0x3000093, 0x3000096, 0x3000099, 0x0, 0x300009C,
+	0x300009F, 0x30000A2, 0x30000A5, 0x30000A8, 0x30000AB, 0x30000AE, 0x30000B1, 0x30000B4, 0x30000B7, 0x30000BA, 0x30000BD, 0x30000C0, 0x30000C3, 0x30000C6, 0x30000C9, 0x30000CC,
+	0x0, 0x0, 0x30000CF, 0x30000D2, 0x30000D5, 0x30000D8, 0x30000DB, 0x30000DE, 0x30000E1, 0x30000E4, 0x30000E7, 0x30000EA, 0x30000ED, 0x30000F0, 0x30000F3, 0x30000F6,
+	0x30000F9, 0x30000FC, 0x30000FF, 0x3000102, 0x3000105, 0x3000108, 0x0, 0x0, 0x300010B, 0x300010E, 0x3000111, 0x3000114, 0x3000117, 0x300011A, 0x300011D, 0x3000120,
+	0x3000123, 0x0, 0x0, 0x0, 0x3000126, 0x3000129, 0x300012C, 0x300012F, 0x0, 0x3000132, 0x3000135, 0x3000138, 0x300013B, 0x300013E, 0x3000141, 0x0,
+	0x0, 0x0, 0x0, 0x3000144, 0x3000147, 0x300014A, 0x300014D, 0x3000150, 0x3000153, 0x0, 0x0, 0x0, 0x3000156, 0x3000159, 0x300015C, 0x300015F,
+	0x3000162, 0x3000165, 0x0, 0x0, 0x3000168, 0x300016B, 0x300016E, 0x3000171, 0x3000174, 0x3000177, 0x300017A, 0x300017D, 0x3000180, 0x3000183, 0x3000186, 0x3000189,
+	0x300018C, 0x300018F, 0x3000192, 0x3000195, 0x3000198, 0x300019B, 0x0, 0x0, 0x300019E, 0x30001A1, 0x30001A4, 0x30001A7, 0x30001AA, 0x30001AD, 0x30001B0, 0x30001B3,
+	0x30001B6, 0x30001B9, 0x30001BC, 0x30001BF, 0x30001C2, 0x30001C5, 0x30001C8, 0x30001CB, 0x30001CE, 0x30001D1, 0x30001D4, 0x30001D7, 0x30001DA, 0x30001DD, 0x30001E0, 0x0,
+	0x30001E3, 0x30001E6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30001E9,
+	0x30001EC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30001EF, 0x30001F2, 0x30001F5,
+	0x30001F8, 0x30001FB, 0x30001FE, 0x3000201, 0x3000204, 0x5000207, 0x500020C, 0x5000211, 0x5000216, 0x500021B, 0x5000220, 0x5000225, 0x500022A, 0x0, 0x500022F, 0x5000234,
+	0x5000239, 0x500023E, 0x4000243, 0x4000247, 0x0, 0x0, 0x300024B, 0x300024E, 0x3000251, 0x3000254, 0x3000257, 0x300025A, 0x500025D, 0x5000262, 0x4000267, 0x400026B,
+	0x300026F, 0x0, 0x0, 0x0, 0x3000272, 0x3000275, 0x0, 0x0, 0x3000278, 0x300027B, 0x500027E, 0x5000283, 0x4000288, 0x400028C, 0x4000290, 0x4000294,
+	0x3000298, 0x300029B, 0x300029E, 0x30002A1, 0x30002A4, 0x30002A7, 0x30002AA, 0x30002AD, 0x30002B0, 0x30002B3, 0x30002B6, 0x30002B9, 0x30002BC, 0x30002BF, 0x30002C2, 0x30002C5,
+	0x30002C8, 0x30002CB, 0x30002CE, 0x30002D1, 0x30002D4, 0x30002D7, 0x30002DA, 0x30002DD, 0x30002E0, 0x30002E3, 0x30002E6, 0x30002E9, 0x0, 0x0, 0x30002EC, 0x30002EF,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3000239, 0x300023E, 0x30002F2, 0x30002F5, 0x50002F8, 0x50002FD, 0x5000302, 0x5000307, 0x300030C, 0x300030F,
+	0x5000312, 0x5000317, 0x300031C, 0x300031F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2000001, 0x2000004, 0x0, 0x2000322, 0x4000212, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x2000324, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000326, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x4000327, 0x400032B, 0x200032F, 0x4000331, 0x4000335, 0x4000339, 0x0, 0x400033D, 0x0, 0x4000341, 0x4000345,
+	0x6000349, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400034F, 0x4000353, 0x4000357, 0x400035B, 0x400035F, 0x4000363,
+	0x6000367, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000349, 0x4000367, 0x400036D, 0x4000371, 0x4000375, 0x0,
+	0x0, 0x0, 0x0, 0x4000379, 0x400037D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4000381, 0x4000385, 0x0, 0x4000389, 0x0, 0x0, 0x0, 0x400038D, 0x0, 0x0, 0x0, 0x0, 0x4000391, 0x4000395, 0x4000399, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400039D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40003A1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x40003A5, 0x40003A9, 0x0, 0x40003AD, 0x0, 0x0, 0x0, 0x40003B1, 0x0, 0x0, 0x0, 0x0, 0x40003B5, 0x40003B9, 0x40003BD, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40003C1, 0x40003C5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x40003C9, 0x40003CD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x40003D1, 0x40003D5, 0x40003D9, 0x40003DD, 0x0, 0x0, 0x40003E1, 0x40003E5, 0x0, 0x0, 0x40003E9, 0x40003ED, 0x40003F1, 0x40003F5, 0x40003F9, 0x40003FD,
+	0x0, 0x0, 0x4000401, 0x4000405, 0x4000409, 0x400040D, 0x4000411, 0x4000415, 0x0, 0x0, 0x4000419, 0x400041D, 0x4000421, 0x4000425, 0x4000429, 0x400042D,
+	0x4000431, 0x4000435, 0x4000439, 0x400043D, 0x4000441, 0x4000445, 0x0, 0x0, 0x4000449, 0x400044D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x4000451, 0x4000455, 0x4000459, 0x400045D, 0x4000461, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4000465, 0x0, 0x4000469, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x400046D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000471, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x6000477, 0x0, 0x0, 0x600047D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000483, 0x6000489, 0x600048F, 0x6000495, 0x600049B, 0x60004A1, 0x60004A7, 0x60004AD,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004B3, 0x60004B9, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004BF, 0x60004C5, 0x0, 0x60004CB,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x60004D1, 0x0, 0x0, 0x60004D7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004DD, 0x60004E3, 0x60004E9, 0x0, 0x0, 0x60004EF, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004F5, 0x0, 0x0, 0x60004FB, 0x6000501, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000507, 0x600050D, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x6000513, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000519, 0x600051F, 0x6000525, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600052B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6000531, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000537, 0x600053D, 0x0, 0x6000543, 0x9000549, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000552, 0x6000558, 0x600055E, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000564, 0x0, 0x600056A, 0x9000570, 0x6000579, 0x0,
+	0x0, 0x0, 0x0, 0x600057F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000585, 0x0, 0x0,
+	0x0, 0x0, 0x600058B, 0x0, 0x0, 0x0, 0x0, 0x6000591, 0x0, 0x0, 0x0, 0x0, 0x6000597, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600059D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x60005A3, 0x0, 0x60005A9, 0x60005AF, 0x0, 0x60005B5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x60005BB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x60005C1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005C7, 0x0, 0x0,
+	0x0, 0x0, 0x60005CD, 0x0, 0x0, 0x0, 0x0, 0x60005D3, 0x0, 0x0, 0x0, 0x0, 0x60005D9, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005DF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005E5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005EB, 0x0, 0x60005F1, 0x0, 0x60005F7, 0x0, 0x60005FD, 0x0, 0x6000603, 0x0,
+	0x0, 0x0, 0x6000609, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600060F, 0x0, 0x6000615, 0x0, 0x0,
+	0x600061B, 0x6000621, 0x0, 0x6000627, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300062D, 0x3000630, 0x3000633, 0x3000636, 0x3000639, 0x300063C, 0x300063F, 0x3000642, 0x5000645, 0x500064A, 0x300064F, 0x3000652, 0x3000655, 0x3000658, 0x300065B, 0x300065E,
+	0x3000661, 0x3000664, 0x3000667, 0x300066A, 0x500066D, 0x5000672, 0x5000677, 0x500067C, 0x3000681, 0x3000684, 0x3000687, 0x300068A, 0x500068D, 0x5000692, 0x3000697, 0x300069A,
+	0x300069D, 0x30006A0, 0x30006A3, 0x30006A6, 0x30006A9, 0x30006AC, 0x30006AF, 0x30006B2, 0x30006B5, 0x30006B8, 0x30006BB, 0x30006BE, 0x30006C1, 0x30006C4, 0x50006C7, 0x50006CC,
+	0x30006D1, 0x30006D4, 0x30006D7, 0x30006DA, 0x30006DD, 0x30006E0, 0x30006E3, 0x30006E6, 0x50006E9, 0x50006EE, 0x30006F3, 0x30006F6, 0x30006F9, 0x30006FC, 0x30006FF, 0x3000702,
+	0x3000705, 0x3000708, 0x300070B, 0x300070E, 0x3000711, 0x3000714, 0x3000717, 0x300071A, 0x300071D, 0x3000720, 0x3000723, 0x3000726, 0x5000729, 0x500072E, 0x5000733, 0x5000738,
+	0x500073D, 0x5000742, 0x5000747, 0x500074C, 0x3000751, 0x3000754, 0x3000757, 0x300075A, 0x300075D, 0x3000760, 0x3000763, 0x3000766, 0x5000769, 0x500076E, 0x3000773, 0x3000776,
+	0x3000779, 0x300077C, 0x300077F, 0x3000782, 0x5000785, 0x500078A, 0x500078F, 0x5000794, 0x5000799, 0x500079E, 0x30007A3, 0x30007A6, 0x30007A9, 0x30007AC, 0x30007AF, 0x30007B2,
+	0x30007B5, 0x30007B8, 0x30007BB, 0x30007BE, 0x30007C1, 0x30007C4, 0x30007C7, 0x30007CA, 0x50007CD, 0x50007D2, 0x50007D7, 0x50007DC, 0x30007E1, 0x30007E4, 0x30007E7, 0x30007EA,
+	0x30007ED, 0x30007F0, 0x30007F3, 0x30007F6, 0x30007F9, 0x30007FC, 0x30007FF, 0x3000802, 0x3000805, 0x3000808, 0x300080B, 0x300080E, 0x3000811, 0x3000814, 0x3000817, 0x300081A,
+	0x300081D, 0x3000820, 0x3000823, 0x3000826, 0x3000829, 0x300082C, 0x300082F, 0x3000832, 0x3000835, 0x3000838, 0x0, 0x400083B, 0x0, 0x0, 0x0, 0x0,
+	0x300083F, 0x3000842, 0x3000845, 0x3000848, 0x500084B, 0x5000850, 0x5000855, 0x500085A, 0x500085F, 0x5000864, 0x5000869, 0x500086E, 0x5000873, 0x5000878, 0x500087D, 0x5000882,
+	0x5000887, 0x500088C, 0x5000891, 0x5000896, 0x500089B, 0x50008A0, 0x50008A5, 0x50008AA, 0x30008AF, 0x30008B2, 0x30008B5, 0x30008B8, 0x30008BB, 0x30008BE, 0x50008C1, 0x50008C6,
+	0x50008CB, 0x50008D0, 0x50008D5, 0x50008DA, 0x50008DF, 0x50008E4, 0x50008E9, 0x50008EE, 0x30008F3, 0x30008F6, 0x30008F9, 0x30008FC, 0x30008FF, 0x3000902, 0x3000905, 0x3000908,
+	0x500090B, 0x5000910, 0x5000915, 0x500091A, 0x500091F, 0x5000924, 0x5000929, 0x500092E, 0x5000933, 0x5000938, 0x500093D, 0x5000942, 0x5000947, 0x500094C, 0x5000951, 0x5000956,
+	0x500095B, 0x5000960, 0x5000965, 0x500096A, 0x300096F, 0x3000972, 0x3000975, 0x3000978, 0x500097B, 0x5000980, 0x5000985, 0x500098A, 0x500098F, 0x5000994, 0x5000999, 0x500099E,
+	0x50009A3, 0x50009A8, 0x30009AD, 0x30009B0, 0x30009B3, 0x30009B6, 0x30009B9, 0x30009BC, 0x30009BF, 0x30009C2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x40009C5, 0x40009C9, 0x60009CD, 0x60009D3, 0x60009D9, 0x60009DF, 0x60009E5, 0x60009EB, 0x40009F1, 0x40009F5, 0x60009F9, 0x60009FF, 0x6000A05, 0x6000A0B, 0x6000A11, 0x6000A17,
+	0x4000A1D, 0x4000A21, 0x6000A25, 0x6000A2B, 0x6000A31, 0x6000A37, 0x0, 0x0, 0x4000A3D, 0x4000A41, 0x6000A45, 0x6000A4B, 0x6000A51, 0x6000A57, 0x0, 0x0,
+	0x4000A5D, 0x4000A61, 0x6000A65, 0x6000A6B, 0x6000A71, 0x6000A77, 0x6000A7D, 0x6000A83, 0x4000A89, 0x4000A8D, 0x6000A91, 0x6000A97, 0x6000A9D, 0x6000AA3, 0x6000AA9, 0x6000AAF,
+	0x4000AB5, 0x4000AB9, 0x6000ABD, 0x6000AC3, 0x6000AC9, 0x6000ACF, 0x6000AD5, 0x6000ADB, 0x4000AE1, 0x4000AE5, 0x6000AE9, 0x6000AEF, 0x6000AF5, 0x6000AFB, 0x6000B01, 0x6000B07,
+	0x4000B0D, 0x4000B11, 0x6000B15, 0x6000B1B, 0x6000B21, 0x6000B27, 0x0, 0x0, 0x4000B2D, 0x4000B31, 0x6000B35, 0x6000B3B, 0x6000B41, 0x6000B47, 0x0, 0x0,
+	0x4000B4D, 0x4000B51, 0x6000B55, 0x6000B5B, 0x6000B61, 0x6000B67, 0x6000B6D, 0x6000B73, 0x0, 0x4000B79, 0x0, 0x6000B7D, 0x0, 0x6000B83, 0x0, 0x6000B89,
+	0x4000B8F, 0x4000B93, 0x6000B97, 0x6000B9D, 0x6000BA3, 0x6000BA9, 0x6000BAF, 0x6000BB5, 0x4000BBB, 0x4000BBF, 0x6000BC3, 0x6000BC9, 0x6000BCF, 0x6000BD5, 0x6000BDB, 0x6000BE1,
+	0x4000BE7, 0x4000357, 0x4000BEB, 0x400035B, 0x4000BEF, 0x400035F, 0x4000BF3, 0x4000363, 0x4000BF7, 0x400036D, 0x4000BFB, 0x4000371, 0x4000BFF, 0x4000375, 0x0, 0x0,
+	0x6000C03, 0x6000C09, 0x8000C0F, 0x8000C17, 0x8000C1F, 0x8000C27, 0x8000C2F, 0x8000C37, 0x6000C3F, 0x6000C45, 0x8000C4B, 0x8000C53, 0x8000C5B, 0x8000C63, 0x8000C6B, 0x8000C73,
+	0x6000C7B, 0x6000C81, 0x8000C87, 0x8000C8F, 0x8000C97, 0x8000C9F, 0x8000CA7, 0x8000CAF, 0x6000CB7, 0x6000CBD, 0x8000CC3, 0x8000CCB, 0x8000CD3, 0x8000CDB, 0x8000CE3, 0x8000CEB,
+	0x6000CF3, 0x6000CF9, 0x8000CFF, 0x8000D07, 0x8000D0F, 0x8000D17, 0x8000D1F, 0x8000D27, 0x6000D2F, 0x6000D35, 0x8000D3B, 0x8000D43, 0x8000D4B, 0x8000D53, 0x8000D5B, 0x8000D63,
+	0x4000D6B, 0x4000D6F, 0x6000D73, 0x4000D79, 0x6000D7D, 0x0, 0x4000D83, 0x6000D87, 0x4000D8D, 0x4000D91, 0x4000D95, 0x400032B, 0x4000D99, 0x0, 0x2000349, 0x0,
+	0x0, 0x4000D9D, 0x6000DA1, 0x4000DA7, 0x6000DAB, 0x0, 0x4000DB1, 0x6000DB5, 0x4000DBB, 0x4000331, 0x4000DBF, 0x4000335, 0x4000DC3, 0x5000DC7, 0x5000DCC, 0x5000DD1,
+	0x4000DD6, 0x4000DDA, 0x6000DDE, 0x6000349, 0x0, 0x0, 0x4000DE4, 0x6000DE8, 0x4000DEE, 0x4000DF2, 0x4000DF6, 0x4000339, 0x0, 0x5000DFA, 0x5000DFF, 0x5000E04,
+	0x4000E09, 0x4000E0D, 0x6000E11, 0x6000367, 0x4000E17, 0x4000E1B, 0x4000E1F, 0x6000E23, 0x4000E29, 0x4000E2D, 0x4000E31, 0x4000341, 0x4000E35, 0x4000E39, 0x4000327, 0x1000E3D,
+	0x0, 0x0, 0x6000E3E, 0x4000E44, 0x6000E48, 0x0, 0x4000E4E, 0x6000E52, 0x4000E58, 0x400033D, 0x4000E5C, 0x4000345, 0x4000E60, 0x2000E64, 0x0, 0x0,
+	0x3000E66, 0x3000E69, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000345, 0x0, 0x0, 0x0, 0x100012C, 0x300000F, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000E6C, 0x5000E71, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000E76, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000E7B, 0x5000E80, 0x5000E85,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x5000E8A, 0x0, 0x0, 0x0, 0x0, 0x5000E8F, 0x0, 0x0, 0x5000E94, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x5000E99, 0x0, 0x5000E9E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x5000EA3, 0x0, 0x0, 0x5000EA8, 0x0, 0x0, 0x5000EAD, 0x0, 0x5000EB2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3000EB7, 0x0, 0x5000EBA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000EBF, 0x3000EC4, 0x3000EC7,
+	0x5000ECA, 0x5000ECF, 0x0, 0x0, 0x5000ED4, 0x5000ED9, 0x0, 0x0, 0x5000EDE, 0x5000EE3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x5000EE8, 0x5000EED, 0x0, 0x0, 0x5000EF2, 0x5000EF7, 0x0, 0x0, 0x5000EFC, 0x5000F01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000F06, 0x5000F0B, 0x5000F10, 0x5000F15,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x5000F1A, 0x5000F1F, 0x5000F24, 0x5000F29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000F2E, 0x5000F33, 0x5000F38, 0x5000F3D, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3000F42, 0x3000F45, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000F48, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000F4D, 0x0, 0x6000F53, 0x0,
+	0x6000F59, 0x0, 0x6000F5F, 0x0, 0x6000F65, 0x0, 0x6000F6B, 0x0, 0x6000F71, 0x0, 0x6000F77, 0x0, 0x6000F7D, 0x0, 0x6000F83, 0x0,
+	0x6000F89, 0x0, 0x6000F8F, 0x0, 0x0, 0x6000F95, 0x0, 0x6000F9B, 0x0, 0x6000FA1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6000FA7, 0x6000FAD, 0x0, 0x6000FB3, 0x6000FB9, 0x0, 0x6000FBF, 0x6000FC5, 0x0, 0x6000FCB, 0x6000FD1, 0x0, 0x6000FD7, 0x6000FDD, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x6000FE3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000FE9, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000FEF, 0x0, 0x6000FF5, 0x0,
+	0x6000FFB, 0x0, 0x6001001, 0x0, 0x6001007, 0x0, 0x600100D, 0x0, 0x6001013, 0x0, 0x6001019, 0x0, 0x600101F, 0x0, 0x6001025, 0x0,
+	0x600102B, 0x0, 0x6001031, 0x0, 0x0, 0x6001037, 0x0, 0x600103D, 0x0, 0x6001043, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6001049, 0x600104F, 0x0, 0x6001055, 0x600105B, 0x0, 0x6001061, 0x6001067, 0x0, 0x600106D, 0x6001073, 0x0, 0x6001079, 0x600107F, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x6001085, 0x0, 0x0, 0x600108B, 0x6001091, 0x6001097, 0x600109D, 0x0, 0x0, 0x0, 0x60010A3, 0x0,
+	0x30010A9, 0x30010AC, 0x30010AF, 0x30010B2, 0x30010B5, 0x30010B8, 0x30010BB, 0x30010BE, 0x30010BE, 0x30010C1, 0x30010C4, 0x30010C7, 0x30010CA, 0x30010CD, 0x30010D0, 0x30010D3,
+	0x30010D6, 0x30010D9, 0x30010DC, 0x30010DF, 0x30010E2, 0x30010E5, 0x30010E8, 0x30010EB, 0x30010EE, 0x30010F1, 0x30010F4, 0x30010F7, 0x30010FA, 0x30010FD, 0x3001100, 0x3001103,
+	0x3001106, 0x3001109, 0x300110C, 0x300110F, 0x3001112, 0x3001115, 0x3001118, 0x300111B, 0x300111E, 0x3001121, 0x3001124, 0x3001127, 0x300112A, 0x300112D, 0x3001130, 0x3001133,
+	0x3001136, 0x3001139, 0x300113C, 0x300113F, 0x3001142, 0x3001145, 0x3001148, 0x300114B, 0x300114E, 0x3001151, 0x3001154, 0x3001157, 0x300115A, 0x300115D, 0x3001160, 0x3001163,
+	0x3001166, 0x3001169, 0x300116C, 0x300116F, 0x3001172, 0x3001175, 0x3001178, 0x300117B, 0x300117E, 0x3001181, 0x3001184, 0x3001187, 0x300118A, 0x300118D, 0x3001190, 0x3001193,
+	0x3001196, 0x3001199, 0x300119C, 0x300119F, 0x30011A2, 0x30011A5, 0x30011A8, 0x30011AB, 0x30011AE, 0x30011B1, 0x30011B4, 0x30011B7, 0x30010E2, 0x30011BA, 0x30011BD, 0x30011C0,
+	0x30011C3, 0x30011C6, 0x30011C9, 0x30011CC, 0x30011CF, 0x30011D2, 0x30011D5, 0x30011D8, 0x30011DB, 0x30011DE, 0x30011E1, 0x30011E4, 0x30011E7, 0x30011EA, 0x30011ED, 0x30011F0,
+	0x30011F3, 0x30011F6, 0x30011F9, 0x30011FC, 0x30011FF, 0x3001202, 0x3001205, 0x3001208, 0x300120B, 0x300120E, 0x3001211, 0x3001214, 0x3001217, 0x300121A, 0x300121D, 0x3001220,
+	0x3001223, 0x3001226, 0x3001229, 0x300122C, 0x300122F, 0x3001232, 0x3001235, 0x3001238, 0x300123B, 0x300123E, 0x3001241, 0x3001244, 0x3001247, 0x300124A, 0x300124D, 0x3001250,
+	0x3001253, 0x3001256, 0x3001259, 0x300125C, 0x300125F, 0x3001262, 0x3001265, 0x3001268, 0x300126B, 0x300126E, 0x3001271, 0x3001274, 0x3001277, 0x300127A, 0x300127D, 0x3001280,
+	0x3001283, 0x30011F0, 0x3001286, 0x3001289, 0x300128C, 0x300128F, 0x3001292, 0x3001295, 0x3001298, 0x300129B, 0x30011C0, 0x300129E, 0x30012A1, 0x30012A4, 0x30012A7, 0x30012AA,
+	0x30012AD, 0x30012B0, 0x30012B3, 0x30012B6, 0x30012B9, 0x30012BC, 0x30012BF, 0x30012C2, 0x30012C5, 0x30012C8, 0x30012CB, 0x30012CE, 0x30012D1, 0x30012D4, 0x30012D7, 0x30010E2,
+	0x30012DA, 0x30012DD, 0x30012E0, 0x30012E3, 0x30012E6, 0x30012E9, 0x30012EC, 0x30012EF, 0x30012F2, 0x30012F5, 0x30012F8, 0x30012FB, 0x30012FE, 0x3001301, 0x3001304, 0x3001307,
+	0x300130A, 0x300130D, 0x3001310, 0x3001313, 0x3001316, 0x3001319, 0x300131C, 0x300131F, 0x3001322, 0x3001325, 0x3001328, 0x30011C6, 0x300132B, 0x300132E, 0x3001331, 0x3001334,
+	0x3001337, 0x300133A, 0x300133D, 0x3001340, 0x3001343, 0x3001346, 0x3001349, 0x300134C, 0x300134F, 0x3001352, 0x3001355, 0x3001358, 0x300135B, 0x300135E, 0x3001361, 0x3001364,
+	0x3001367, 0x300136A, 0x300136D, 0x3001370, 0x3001373, 0x3001376, 0x3001379, 0x300137C, 0x300137F, 0x3001382, 0x3001385, 0x3001388, 0x300138B, 0x300138E, 0x3001391, 0x3001394,
+	0x3001397, 0x300139A, 0x300139D, 0x30013A0, 0x30013A3, 0x30013A6, 0x30013A9, 0x30013AC, 0x30013AF, 0x30013B2, 0x30013B5, 0x30013B8, 0x30013BB, 0x30013BE, 0x0, 0x0,
+	0x30013C1, 0x0, 0x30013C4, 0x0, 0x0, 0x30013C7, 0x30013CA, 0x30013CD, 0x30013D0, 0x30013D3, 0x30013D6, 0x30013D9, 0x30013DC, 0x30013DF, 0x30013E2, 0x0,
+	0x30013E5, 0x0, 0x30013E8, 0x0, 0x0, 0x30013EB, 0x30013EE, 0x0, 0x0, 0x0, 0x30013F1, 0x30013F4, 0x30013F7, 0x30013FA, 0x30013FD, 0x3001400,
+	0x3001403, 0x3001406, 0x3001409, 0x300140C, 0x300140F, 0x3001412, 0x3001415, 0x3001418, 0x300141B, 0x300141E, 0x3001421, 0x3001424, 0x3001427, 0x300142A, 0x300142D, 0x3001430,
+	0x3001433, 0x3001436, 0x3001439, 0x300143C, 0x300143F, 0x3001442, 0x3001445, 0x3001448, 0x300144B, 0x300144E, 0x3001451, 0x3001454, 0x3001457, 0x300145A, 0x300145D, 0x3001460,
+	0x3001463, 0x3001466, 0x3001469, 0x300146C, 0x300146F, 0x3001472, 0x3001475, 0x3001265, 0x3001478, 0x300147B, 0x300147E, 0x3001481, 0x3001484, 0x3001487, 0x3001487, 0x300148A,
+	0x300148D, 0x3001490, 0x3001493, 0x3001496, 0x3001499, 0x300149C, 0x300149F, 0x30013EB, 0x30014A2, 0x30014A5, 0x30014A8, 0x30014AB, 0x40014AE, 0x30014B2, 0x0, 0x0,
+	0x30014B5, 0x30014B8, 0x30014BB, 0x30014BE, 0x30014C1, 0x30014C4, 0x30014C7, 0x30014CA, 0x3001415, 0x30014CD, 0x30014D0, 0x30014D3, 0x30013C1, 0x30014D6, 0x30014D9, 0x30014DC,
+	0x30014DF, 0x30014E2, 0x30014E5, 0x30014E8, 0x30014EB, 0x30014EE, 0x30014F1, 0x30014F4, 0x30014F7, 0x3001430, 0x30014FA, 0x3001433, 0x30014FD, 0x3001500, 0x3001503, 0x3001506,
+	0x3001509, 0x30013C4, 0x3001121, 0x300150C, 0x300150F, 0x3001512, 0x30011F3, 0x30012F8, 0x3001515, 0x3001518, 0x3001448, 0x300151B, 0x300144B, 0x300151E, 0x3001521, 0x3001524,
+	0x30013CA, 0x3001527, 0x300152A, 0x300152D, 0x3001530, 0x3001533, 0x30013CD, 0x3001536, 0x3001539, 0x300153C, 0x300153F, 0x3001542, 0x3001545, 0x3001475, 0x3001548, 0x300154B,
+	0x3001265, 0x300154E, 0x3001481, 0x3001551, 0x3001554, 0x3001557, 0x300155A, 0x300155D, 0x3001490, 0x3001560, 0x30013E8, 0x3001563, 0x3001493, 0x30011BA, 0x3001566, 0x3001496,
+	0x3001569, 0x300149C, 0x300156C, 0x300156F, 0x3001572, 0x3001575, 0x3001578, 0x30014A2, 0x30013DC, 0x300157B, 0x30014A5, 0x300157E, 0x30014A8, 0x3001581, 0x30010BE, 0x4001584,
+	0x4001588, 0x400158C, 0x3001590, 0x3001593, 0x3001596, 0x4001599, 0x400159D, 0x40015A1, 0x30015A5, 0x30015A8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40015AB, 0x0, 0x40015AF,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40015B3, 0x40015B7, 0x60015BB, 0x60015C1, 0x40015C7, 0x40015CB,
+	0x40015CF, 0x40015D3, 0x40015D7, 0x40015DB, 0x40015DF, 0x40015E3, 0x40015E7, 0x0, 0x40015EB, 0x40015EF, 0x40015F3, 0x40015F7, 0x40015FB, 0x0, 0x40015FF, 0x0,
+	0x4001603, 0x4001607, 0x0, 0x400160B, 0x400160F, 0x0, 0x4001613, 0x4001617, 0x400161B, 0x40015BB, 0x400161F, 0x4001623, 0x4001627, 0x400162B, 0x400162F, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001633, 0x0, 0x800163B, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001643, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800164B, 0x8001653,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800165B, 0x8001663, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800166B, 0x8001673, 0x0, 0x800167B, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001683, 0x800168B, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001693, 0x800169B,
+	0xC0016A3, 0xC0016AF, 0xC0016BB, 0xC0016C7, 0xC0016D3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80016DF, 0x80016E7, 0xC0016EF, 0xC0016FB, 0xC001707,
+	0xC001713, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300171F, 0x3001722, 0x3001725, 0x4001728, 0x300172C, 0x3001403, 0x300172F, 0x3001732, 0x3001735, 0x3001738, 0x3001406, 0x300173B, 0x300173E, 0x4001741, 0x3001409, 0x3001745,
+	0x3001748, 0x300174B, 0x400174E, 0x3001752, 0x3001755, 0x3001758, 0x400175B, 0x300175F, 0x3001762, 0x3001765, 0x3001768, 0x30014B8, 0x400176B, 0x300176F, 0x3001772, 0x3001775,
+	0x3001778, 0x300177B, 0x300177E, 0x3001781, 0x3001784, 0x30014C7, 0x300140C, 0x300140F, 0x30014CA, 0x3001787, 0x300178A, 0x30011CC, 0x300178D, 0x3001412, 0x3001790, 0x3001793,
+	0x3001796, 0x3001799, 0x3001799, 0x3001799, 0x400179C, 0x30017A0, 0x30017A3, 0x30017A6, 0x40017A9, 0x30017AD, 0x30017B0, 0x30017B3, 0x30017B6, 0x30017B9, 0x30017BC, 0x30017BF,
+	0x30017C2, 0x30017C5, 0x30017C8, 0x30017CB, 0x30017CE, 0x30017D1, 0x30017D1, 0x30014D0, 0x30017D4, 0x30017D7, 0x30017DA, 0x30017DD, 0x3001418, 0x30017E0, 0x30017E3, 0x30017E6,
+	0x3001397, 0x30017E9, 0x30017EC, 0x30017EF, 0x30017F2, 0x30017F5, 0x30017F8, 0x30017FB, 0x30017FE, 0x4001801, 0x3001805, 0x3001808, 0x300180B, 0x300180E, 0x3001811, 0x3001814,
+	0x4001817, 0x400181B, 0x300181F, 0x3001822, 0x3001825, 0x3001828, 0x300182B, 0x300182E, 0x3001831, 0x3001834, 0x3001837, 0x3001837, 0x400183A, 0x300183E, 0x3001841, 0x30011C0,
+	0x3001844, 0x4001847, 0x300184B, 0x300184E, 0x3001851, 0x3001854, 0x3001857, 0x300185A, 0x3001427, 0x300185D, 0x3001860, 0x4001863, 0x3001867, 0x400186A, 0x300186E, 0x3001871,
+	0x3001874, 0x3001877, 0x300187A, 0x300187D, 0x3001880, 0x3001883, 0x3001886, 0x3001889, 0x300188C, 0x400188F, 0x3001893, 0x3001896, 0x3001899, 0x300189C, 0x300111E, 0x400189F,
+	0x30018A3, 0x40018A6, 0x40018A6, 0x30018AA, 0x30018AD, 0x30018AD, 0x30018B0, 0x40018B3, 0x40018B7, 0x30018BB, 0x30018BE, 0x30018C1, 0x30018C4, 0x30018C7, 0x30018CA, 0x30018CD,
+	0x30018D0, 0x30018D3, 0x30018D6, 0x300142A, 0x40018D9, 0x30018DD, 0x30018E0, 0x30018E3, 0x30014F4, 0x30018E3, 0x30018E6, 0x3001430, 0x30018E9, 0x30018EC, 0x30018EF, 0x30018F2,
+	0x3001433, 0x30010CD, 0x30018F5, 0x30018F8, 0x30018FB, 0x30018FE, 0x3001901, 0x3001904, 0x4001907, 0x300190B, 0x300190E, 0x3001911, 0x3001914, 0x3001917, 0x400191A, 0x300191E,
+	0x3001921, 0x3001924, 0x3001927, 0x300192A, 0x300192D, 0x3001930, 0x3001933, 0x3001936, 0x3001436, 0x3001939, 0x400193C, 0x3001940, 0x3001943, 0x3001946, 0x3001949, 0x300143C,
+	0x300194C, 0x300194F, 0x3001952, 0x3001955, 0x3001958, 0x300195B, 0x300195E, 0x3001961, 0x3001121, 0x300150C, 0x3001964, 0x3001967, 0x300196A, 0x400196D, 0x3001971, 0x3001974,
+	0x3001977, 0x300197A, 0x300143F, 0x400197D, 0x3001981, 0x3001984, 0x3001987, 0x3001590, 0x300198A, 0x300198D, 0x3001990, 0x3001993, 0x4001996, 0x300199A, 0x300199D, 0x30019A0,
+	0x40019A3, 0x30019A7, 0x30019AA, 0x30019AD, 0x30019B0, 0x30011F3, 0x30019B3, 0x40019B6, 0x40019BA, 0x40019BE, 0x30019C2, 0x40019C5, 0x30019C9, 0x30019CC, 0x30019CF, 0x30019D2,
+	0x30019D5, 0x3001442, 0x30012F8, 0x30019D8, 0x30019DB, 0x30019DE, 0x40019E1, 0x30019E5, 0x30019E8, 0x30019EB, 0x30019EE, 0x3001518, 0x30019F1, 0x40019F4, 0x30019F8, 0x30019FB,
+	0x40019FE, 0x4001A02, 0x3001A06, 0x3001A09, 0x300151B, 0x3001A0C, 0x3001A0F, 0x3001A12, 0x3001A15, 0x3001A18, 0x3001A1B, 0x4001A1E, 0x3001A22, 0x4001A25, 0x3001A29, 0x4001A2C,
+	0x3001A30, 0x3001521, 0x3001A33, 0x4001A36, 0x3001A3A, 0x3001A3D, 0x4001A40, 0x4001A44, 0x3001A48, 0x3001A4B, 0x3001A4E, 0x3001A51, 0x3001A54, 0x3001A54, 0x3001A57, 0x3001A5A,
+	0x3001527, 0x3001A5D, 0x3001A60, 0x3001A63, 0x3001A66, 0x4001A69, 0x3001A6D, 0x4001A70, 0x30011C9, 0x4001A74, 0x3001A78, 0x4001A7B, 0x4001A7F, 0x4001A83, 0x3001A87, 0x3001A8A,
+	0x3001539, 0x4001A8D, 0x4001A91, 0x4001A95, 0x4001A99, 0x3001A9D, 0x3001AA0, 0x3001AA0, 0x300153C, 0x3001596, 0x3001AA3, 0x3001AA6, 0x3001AA9, 0x4001AAC, 0x3001AB0, 0x3001157,
+	0x3001542, 0x3001AB3, 0x4001AB6, 0x3001463, 0x4001ABA, 0x4001ABE, 0x30013D9, 0x3001AC2, 0x3001AC5, 0x300146F, 0x3001AC8, 0x3001ACB, 0x4001ACE, 0x4001AD2, 0x4001AD2, 0x3001AD6,
+	0x3001AD9, 0x4001ADC, 0x3001AE0, 0x3001AE3, 0x3001AE6, 0x4001AE9, 0x3001AED, 0x3001AF0, 0x3001AF3, 0x3001AF6, 0x3001AF9, 0x4001AFC, 0x3001B00, 0x3001B03, 0x3001B06, 0x3001B09,
+	0x3001B0C, 0x3001B0F, 0x4001B12, 0x4001B16, 0x3001B1A, 0x4001B1D, 0x3001B21, 0x4001B24, 0x3001B28, 0x3001B2B, 0x3001481, 0x4001B2E, 0x4001B32, 0x3001B36, 0x4001B39, 0x3001B3D,
+	0x4001B40, 0x3001B44, 0x3001B47, 0x3001B4A, 0x3001B4D, 0x3001B50, 0x3001B53, 0x4001B56, 0x4001B5A, 0x4001B5E, 0x4001B62, 0x30018AA, 0x3001B66, 0x3001B69, 0x3001B6C, 0x3001B6F,
+	0x3001B72, 0x3001B75, 0x3001B78, 0x3001B7B, 0x3001B7E, 0x3001B81, 0x3001B84, 0x4001B87, 0x30011FF, 0x3001B8B, 0x3001B8E, 0x3001B91, 0x3001B94, 0x3001B97, 0x3001B9A, 0x300148A,
+	0x3001B9D, 0x3001BA0, 0x3001BA3, 0x3001BA6, 0x4001BA9, 0x4001BAD, 0x4001BB1, 0x3001BB5, 0x3001BB8, 0x3001BBB, 0x3001BBE, 0x4001BC1, 0x3001BC5, 0x4001BC8, 0x3001BCC, 0x3001BCF,
+	0x4001BD2, 0x4001BD6, 0x3001BDA, 0x3001BDD, 0x3001148, 0x3001BE0, 0x3001BE3, 0x3001BE6, 0x3001BE9, 0x3001BEC, 0x3001BEF, 0x3001557, 0x3001BF2, 0x3001BF5, 0x3001BF8, 0x3001BFB,
+	0x3001BFE, 0x3001C01, 0x3001C04, 0x3001C07, 0x3001C0A, 0x4001C0D, 0x3001C11, 0x3001C14, 0x3001C17, 0x3001C1A, 0x3001C1D, 0x4001C20, 0x4001C24, 0x3001C28, 0x3001C2B, 0x3001C2E,
+	0x3001566, 0x3001569, 0x3001C31, 0x4001C34, 0x3001C38, 0x3001C3B, 0x3001C3E, 0x3001C41, 0x4001C44, 0x4001C48, 0x3001C4C, 0x3001C4F, 0x3001C52, 0x4001C55, 0x3001C59, 0x300156C,
+	0x4001C5C, 0x4001C60, 0x3001C64, 0x3001C67, 0x3001C6A, 0x4001C6D, 0x3001C71, 0x3001C74, 0x3001C77, 0x3001C7A, 0x3001C7D, 0x3001C80, 0x3001C83, 0x4001C86, 0x3001C8A, 0x3001C8D,
+	0x3001C90, 0x4001C93, 0x3001C97, 0x3001C9A, 0x3001C9D, 0x3001CA0, 0x4001CA3, 0x4001CA7, 0x3001CAB, 0x3001CAE, 0x3001CB1, 0x4001CB4, 0x3001CB8, 0x4001CBB, 0x300157E, 0x300157E,
+	0x3001CBF, 0x4001CC2, 0x3001CC6, 0x3001CC9, 0x3001CCC, 0x3001CCF, 0x3001CD2, 0x3001CD5, 0x3001CD8, 0x4001CDB, 0x3001581, 0x3001CDF, 0x3001CE2, 0x3001CE5, 0x3001CE8, 0x3001CEB,
+	0x4001CEE, 0x3001CF2, 0x4001CF5, 0x4001CF9, 0x4001CFD, 0x3001D01, 0x3001D04, 0x3001D07, 0x3001D0A, 0x3001D0D, 0x3001D10, 0x3001D13, 0x3001D16, 0x4001D19, 0x0, 0x0,
+};
+const uint32_t* NFDDataPtr = NFDData;
+
+const uint32_t NFKDIndex1[272] = {
+	0, 128, 256, 384, 512, 416, 416, 416, 416, 416, 640, 416, 416, 416, 416, 768,
+	416, 896, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 1024, 1152, 1280,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 1408,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+	416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416, 416,
+};
+const uint32_t* NFKDIndex1Ptr = NFKDIndex1;
+
+const uint32_t NFKDIndex2[1536] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0, 0x0, 0x100, 0x120, 0x140,
+	0x160, 0x180, 0x0, 0x0, 0x0, 0x1A0, 0x1C0, 0x1E0, 0x0, 0x0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0,
+	0x2C0, 0x2E0, 0x300, 0x320, 0x0, 0x0, 0x340, 0x360, 0x0, 0x0, 0x0, 0x0, 0x380, 0x0, 0x0, 0x0,
+	0x0, 0x3A0, 0x0, 0x3C0, 0x0, 0x0, 0x3E0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400, 0x420, 0x0, 0x0, 0x0, 0x440, 0x0,
+	0x0, 0x460, 0x480, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4A0, 0x0, 0x4C0, 0x0, 0x4E0, 0x0,
+	0x0, 0x0, 0x500, 0x0, 0x0, 0x0, 0x520, 0x0, 0x0, 0x0, 0x540, 0x0, 0x0, 0x0, 0x560, 0x0,
+	0x0, 0x580, 0x0, 0x0, 0x0, 0x5A0, 0x5C0, 0x0, 0x5E0, 0x0, 0x600, 0x620, 0x640, 0x660, 0x0, 0x0,
+	0x0, 0x680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6C0, 0x6E0, 0x700, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x720, 0x740, 0x760, 0x780, 0x7A0, 0x0, 0x0,
+	0x7C0, 0x7E0, 0x800, 0x820, 0x840, 0x860, 0x880, 0x8A0, 0x8C0, 0x8E0, 0x900, 0x920, 0x940, 0x960, 0x980, 0x9A0,
+	0x9C0, 0x9E0, 0xA00, 0xA20, 0xA40, 0xA60, 0x0, 0x0, 0xA80, 0xAA0, 0xAC0, 0xAE0, 0xB00, 0xB20, 0xB40, 0x0,
+	0xB60, 0xB80, 0xBA0, 0xBC0, 0xBE0, 0xC00, 0x0, 0xC20, 0x0, 0xC40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0xC60, 0xC80, 0xCA0, 0xCC0, 0xCE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0xD00, 0x0, 0x0, 0xD20, 0x0, 0x0, 0xD40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0xD60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xD80, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0xDA0, 0x0, 0x0, 0xDC0, 0xDE0, 0xE00, 0xE20, 0xE40, 0xE60, 0xE80, 0xEA0, 0x0,
+	0xEC0, 0xEE0, 0xF00, 0xF20, 0xF40, 0xF60, 0xF80, 0xFA0, 0x0, 0xFC0, 0xFE0, 0x1000, 0x1020, 0x0, 0x0, 0x0,
+	0x1040, 0x1060, 0x1080, 0x10A0, 0x10C0, 0x10E0, 0x1100, 0x1120, 0x1140, 0x1160, 0x1180, 0x11A0, 0x11C0, 0x11E0, 0x1200, 0x1220,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x1240, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1260, 0x0, 0x0, 0x0, 0x1280,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12A0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12C0, 0x12E0, 0x1300, 0x1320, 0x1340, 0x1360, 0x1380, 0x13A0,
+	0x13C0, 0x13E0, 0x1400, 0x1420, 0x1440, 0x1460, 0x1480, 0x0, 0x14A0, 0x14C0, 0x14E0, 0x1500, 0x1520, 0x1540, 0x1560, 0x1580,
+	0x15A0, 0x15C0, 0x15E0, 0x1600, 0x1620, 0x1640, 0x1660, 0x1680, 0x16A0, 0x16C0, 0x16E0, 0x1700, 0x1720, 0x1740, 0x1760, 0x1780,
+	0x17A0, 0x17C0, 0x17E0, 0x1800, 0x1820, 0x1840, 0x1860, 0x1880, 0x18A0, 0x18C0, 0x18E0, 0x1900, 0x1920, 0x1940, 0x1960, 0x1980,
+	0x0, 0x0, 0x0, 0x0, 0x19A0, 0x19C0, 0x0, 0x0, 0x0, 0x19E0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1A00, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x1A20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1A40, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1A60, 0x1A80, 0x0, 0x1AA0, 0x1AC0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0xCB6, 0x1AE0, 0x1B00, 0x1AEC, 0x1B20, 0x1B40, 0x1B60, 0xCC6, 0x1B80, 0x1BA0, 0x1BC0, 0x1AE8, 0xCCA, 0xCB6, 0x1AE0, 0xCC2,
+	0x1AEC, 0x1BE0, 0xCBA, 0x1AE4, 0xCC6, 0x1C00, 0x1C20, 0x1C40, 0x1C26, 0x1C0C, 0x1C2C, 0x1C12, 0x1C32, 0x1C18, 0x1C60, 0x1C80,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1CA0, 0x1CC0, 0x1CE0, 0x1D00, 0x1D20, 0x1D40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1D60, 0x1D80, 0x1DA0, 0x1DC0, 0x1DE0, 0x0, 0x0, 0x0,
+	0x1E00, 0x1E20, 0x1E40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1E60, 0x1E80, 0x1EA0, 0x1EC0, 0x1EE0, 0x1F00, 0x1F20, 0x1F40, 0x1F60, 0x1F80, 0x1FA0, 0x1FC0, 0x1FE0, 0x2000, 0x2020, 0x2040,
+	0x2060, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+};
+const uint32_t* NFKDIndex2Ptr = NFKDIndex2;
+
+const uint32_t NFKDData[8320] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1001D1D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001D1E, 0x0, 0x100004E, 0x0, 0x0, 0x0, 0x0, 0x3001D21,
+	0x0, 0x0, 0x1001D24, 0x1001D25, 0x3001D26, 0x2001D29, 0x0, 0x0, 0x3001D2B, 0x1001D2E, 0x100007E, 0x0, 0x5001D2F, 0x5001D34, 0x5001D39, 0x0,
+	0x3000000, 0x3000003, 0x3000006, 0x3000009, 0x300000C, 0x300000F, 0x0, 0x3000012, 0x3000015, 0x3000018, 0x300001B, 0x300001E, 0x3000021, 0x3000024, 0x3000027, 0x300002A,
+	0x0, 0x300002D, 0x3000030, 0x3000033, 0x3000036, 0x3000039, 0x300003C, 0x0, 0x0, 0x300003F, 0x3000042, 0x3000045, 0x3000048, 0x300004B, 0x0, 0x0,
+	0x300004E, 0x3000051, 0x3000054, 0x3000057, 0x300005A, 0x300005D, 0x0, 0x3000060, 0x3000063, 0x3000066, 0x3000069, 0x300006C, 0x300006F, 0x3000072, 0x3000075, 0x3000078,
+	0x0, 0x300007B, 0x300007E, 0x3000081, 0x3000084, 0x3000087, 0x300008A, 0x0, 0x0, 0x300008D, 0x3000090, 0x3000093, 0x3000096, 0x3000099, 0x0, 0x300009C,
+	0x300009F, 0x30000A2, 0x30000A5, 0x30000A8, 0x30000AB, 0x30000AE, 0x30000B1, 0x30000B4, 0x30000B7, 0x30000BA, 0x30000BD, 0x30000C0, 0x30000C3, 0x30000C6, 0x30000C9, 0x30000CC,
+	0x0, 0x0, 0x30000CF, 0x30000D2, 0x30000D5, 0x30000D8, 0x30000DB, 0x30000DE, 0x30000E1, 0x30000E4, 0x30000E7, 0x30000EA, 0x30000ED, 0x30000F0, 0x30000F3, 0x30000F6,
+	0x30000F9, 0x30000FC, 0x30000FF, 0x3000102, 0x3000105, 0x3000108, 0x0, 0x0, 0x300010B, 0x300010E, 0x3000111, 0x3000114, 0x3000117, 0x300011A, 0x300011D, 0x3000120,
+	0x3000123, 0x0, 0x2001D3E, 0x2001D40, 0x3000126, 0x3000129, 0x300012C, 0x300012F, 0x0, 0x3000132, 0x3000135, 0x3000138, 0x300013B, 0x300013E, 0x3000141, 0x3001D42,
+	0x3001D45, 0x0, 0x0, 0x3000144, 0x3000147, 0x300014A, 0x300014D, 0x3000150, 0x3000153, 0x3001D48, 0x0, 0x0, 0x3000156, 0x3000159, 0x300015C, 0x300015F,
+	0x3000162, 0x3000165, 0x0, 0x0, 0x3000168, 0x300016B, 0x300016E, 0x3000171, 0x3000174, 0x3000177, 0x300017A, 0x300017D, 0x3000180, 0x3000183, 0x3000186, 0x3000189,
+	0x300018C, 0x300018F, 0x3000192, 0x3000195, 0x3000198, 0x300019B, 0x0, 0x0, 0x300019E, 0x30001A1, 0x30001A4, 0x30001A7, 0x30001AA, 0x30001AD, 0x30001B0, 0x30001B3,
+	0x30001B6, 0x30001B9, 0x30001BC, 0x30001BF, 0x30001C2, 0x30001C5, 0x30001C8, 0x30001CB, 0x30001CE, 0x30001D1, 0x30001D4, 0x30001D7, 0x30001DA, 0x30001DD, 0x30001E0, 0x100017D,
+	0x30001E3, 0x30001E6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30001E9,
+	0x30001EC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x4001D4B, 0x4001D4F, 0x4001D53, 0x2001D57, 0x2001D59, 0x2001D5B, 0x2001D5D, 0x2001D5F, 0x2001D61, 0x30001EF, 0x30001F2, 0x30001F5,
+	0x30001F8, 0x30001FB, 0x30001FE, 0x3000201, 0x3000204, 0x5000207, 0x500020C, 0x5000211, 0x5000216, 0x500021B, 0x5000220, 0x5000225, 0x500022A, 0x0, 0x500022F, 0x5000234,
+	0x5000239, 0x500023E, 0x4000243, 0x4000247, 0x0, 0x0, 0x300024B, 0x300024E, 0x3000251, 0x3000254, 0x3000257, 0x300025A, 0x500025D, 0x5000262, 0x4000267, 0x400026B,
+	0x300026F, 0x2001D4B, 0x2001D4F, 0x2001D53, 0x3000272, 0x3000275, 0x0, 0x0, 0x3000278, 0x300027B, 0x500027E, 0x5000283, 0x4000288, 0x400028C, 0x4000290, 0x4000294,
+	0x3000298, 0x300029B, 0x300029E, 0x30002A1, 0x30002A4, 0x30002A7, 0x30002AA, 0x30002AD, 0x30002B0, 0x30002B3, 0x30002B6, 0x30002B9, 0x30002BC, 0x30002BF, 0x30002C2, 0x30002C5,
+	0x30002C8, 0x30002CB, 0x30002CE, 0x30002D1, 0x30002D4, 0x30002D7, 0x30002DA, 0x30002DD, 0x30002E0, 0x30002E3, 0x30002E6, 0x30002E9, 0x0, 0x0, 0x30002EC, 0x30002EF,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3000239, 0x300023E, 0x30002F2, 0x30002F5, 0x50002F8, 0x50002FD, 0x5000302, 0x5000307, 0x300030C, 0x300030F,
+	0x5000312, 0x5000317, 0x300031C, 0x300031F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1000108, 0x2001D63, 0x1000129, 0x100016B, 0x2001D65, 0x2001D67, 0x2001D69, 0x10001C5, 0x1000099, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001D6B, 0x3001D6E, 0x3001D71, 0x3001D74, 0x3001D77, 0x3001D7A, 0x0, 0x0,
+	0x2001D7D, 0x1000135, 0x100017D, 0x100080E, 0x2001D7F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2000001, 0x2000004, 0x0, 0x2000322, 0x4000212, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x2000324, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001D81, 0x0, 0x0, 0x0, 0x1000326, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x3001D26, 0x5001D84, 0x400032B, 0x200032F, 0x4000331, 0x4000335, 0x4000339, 0x0, 0x400033D, 0x0, 0x4000341, 0x4000345,
+	0x6000349, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400034F, 0x4000353, 0x4000357, 0x400035B, 0x400035F, 0x4000363,
+	0x6000367, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000349, 0x4000367, 0x400036D, 0x4000371, 0x4000375, 0x0,
+	0x2001D89, 0x2001D8B, 0x2000341, 0x4000341, 0x4000353, 0x2001D8D, 0x2001D8F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2001D91, 0x2000E17, 0x2001D93, 0x0, 0x2001D95, 0x200035B, 0x0, 0x0, 0x0, 0x2001D97, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4000381, 0x4000385, 0x0, 0x4000389, 0x0, 0x0, 0x0, 0x400038D, 0x0, 0x0, 0x0, 0x0, 0x4000391, 0x4000395, 0x4000399, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400039D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40003A1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x40003A5, 0x40003A9, 0x0, 0x40003AD, 0x0, 0x0, 0x0, 0x40003B1, 0x0, 0x0, 0x0, 0x0, 0x40003B5, 0x40003B9, 0x40003BD, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40003C1, 0x40003C5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x40003C9, 0x40003CD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x40003D1, 0x40003D5, 0x40003D9, 0x40003DD, 0x0, 0x0, 0x40003E1, 0x40003E5, 0x0, 0x0, 0x40003E9, 0x40003ED, 0x40003F1, 0x40003F5, 0x40003F9, 0x40003FD,
+	0x0, 0x0, 0x4000401, 0x4000405, 0x4000409, 0x400040D, 0x4000411, 0x4000415, 0x0, 0x0, 0x4000419, 0x400041D, 0x4000421, 0x4000425, 0x4000429, 0x400042D,
+	0x4000431, 0x4000435, 0x4000439, 0x400043D, 0x4000441, 0x4000445, 0x0, 0x0, 0x4000449, 0x400044D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4001D99, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x4000451, 0x4000455, 0x4000459, 0x400045D, 0x4000461, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x4001D9D, 0x4001DA1, 0x4001DA5, 0x4001DA9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4000465, 0x0, 0x4000469, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x400046D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000471, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x6000477, 0x0, 0x0, 0x600047D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000483, 0x6000489, 0x600048F, 0x6000495, 0x600049B, 0x60004A1, 0x60004A7, 0x60004AD,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004B3, 0x60004B9, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004BF, 0x60004C5, 0x0, 0x60004CB,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x60004D1, 0x0, 0x0, 0x60004D7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004DD, 0x60004E3, 0x60004E9, 0x0, 0x0, 0x60004EF, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60004F5, 0x0, 0x0, 0x60004FB, 0x6000501, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000507, 0x600050D, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x6000513, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000519, 0x600051F, 0x6000525, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600052B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6000531, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000537, 0x600053D, 0x0, 0x6000543, 0x9001DAD, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000552, 0x6000558, 0x600055E, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000564, 0x0, 0x600056A, 0x9001DB6, 0x6000579, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x6001DBF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x6001DC5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6001DCB, 0x6001DD1, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001DD7, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x600057F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000585, 0x0, 0x0,
+	0x0, 0x0, 0x600058B, 0x0, 0x0, 0x0, 0x0, 0x6000591, 0x0, 0x0, 0x0, 0x0, 0x6000597, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600059D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x60005A3, 0x0, 0x60005A9, 0x60005AF, 0x9001DDA, 0x60005B5, 0x9001DE3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x60005BB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x60005C1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005C7, 0x0, 0x0,
+	0x0, 0x0, 0x60005CD, 0x0, 0x0, 0x0, 0x0, 0x60005D3, 0x0, 0x0, 0x0, 0x0, 0x60005D9, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005DF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005E5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001DEC, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60005EB, 0x0, 0x60005F1, 0x0, 0x60005F7, 0x0, 0x60005FD, 0x0, 0x6000603, 0x0,
+	0x0, 0x0, 0x6000609, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x600060F, 0x0, 0x6000615, 0x0, 0x0,
+	0x600061B, 0x6000621, 0x0, 0x6000627, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000000, 0x2000243, 0x1000633, 0x0,
+	0x10000C9, 0x1000015, 0x2001DEF, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x0, 0x1000030, 0x2001DF1, 0x1000751, 0x1000168,
+	0x1000192, 0x100003F, 0x10001C2, 0x100004E, 0x2001DF3, 0x2001DF5, 0x3001DF7, 0x1000636, 0x10000CC, 0x1000063, 0x2001DFA, 0x2001DFC, 0x2001DFE, 0x10000F0, 0x0, 0x100012F,
+	0x1000702, 0x2001E00, 0x100007E, 0x2001E02, 0x3001E04, 0x3001E07, 0x1000754, 0x1000195, 0x100008D, 0x3001E0A, 0x2001E0D, 0x10007E4, 0x3001E0F, 0x2001D89, 0x2001E12, 0x2001E14,
+	0x2001D8D, 0x2001E16, 0x100006F, 0x100016B, 0x100008D, 0x10007E4, 0x2001D89, 0x2001E12, 0x2000E17, 0x2001D8D, 0x2001E16, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2001E18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2001E1A, 0x1000060, 0x2001E1C, 0x2001E1E, 0x2001DFE,
+	0x100069A, 0x2001E20, 0x2001E22, 0x2001E24, 0x2001E26, 0x2001E28, 0x2001E2A, 0x3001E2C, 0x2001E2F, 0x2001E31, 0x3001E33, 0x2001E36, 0x2001E38, 0x2001E3A, 0x2001E3C, 0x2001E3E,
+	0x2001E40, 0x2001E42, 0x2001E44, 0x2001E46, 0x2001E48, 0x2001E4A, 0x2001E4C, 0x2001E4E, 0x3001E50, 0x2001E53, 0x2001E55, 0x10001D4, 0x2001E57, 0x2001E59, 0x200026B, 0x2001D8B,
+	0x300062D, 0x3000630, 0x3000633, 0x3000636, 0x3000639, 0x300063C, 0x300063F, 0x3000642, 0x5000645, 0x500064A, 0x300064F, 0x3000652, 0x3000655, 0x3000658, 0x300065B, 0x300065E,
+	0x3000661, 0x3000664, 0x3000667, 0x300066A, 0x500066D, 0x5000672, 0x5000677, 0x500067C, 0x3000681, 0x3000684, 0x3000687, 0x300068A, 0x500068D, 0x5000692, 0x3000697, 0x300069A,
+	0x300069D, 0x30006A0, 0x30006A3, 0x30006A6, 0x30006A9, 0x30006AC, 0x30006AF, 0x30006B2, 0x30006B5, 0x30006B8, 0x30006BB, 0x30006BE, 0x30006C1, 0x30006C4, 0x50006C7, 0x50006CC,
+	0x30006D1, 0x30006D4, 0x30006D7, 0x30006DA, 0x30006DD, 0x30006E0, 0x30006E3, 0x30006E6, 0x50006E9, 0x50006EE, 0x30006F3, 0x30006F6, 0x30006F9, 0x30006FC, 0x30006FF, 0x3000702,
+	0x3000705, 0x3000708, 0x300070B, 0x300070E, 0x3000711, 0x3000714, 0x3000717, 0x300071A, 0x300071D, 0x3000720, 0x3000723, 0x3000726, 0x5000729, 0x500072E, 0x5000733, 0x5000738,
+	0x500073D, 0x5000742, 0x5000747, 0x500074C, 0x3000751, 0x3000754, 0x3000757, 0x300075A, 0x300075D, 0x3000760, 0x3000763, 0x3000766, 0x5000769, 0x500076E, 0x3000773, 0x3000776,
+	0x3000779, 0x300077C, 0x300077F, 0x3000782, 0x5000785, 0x500078A, 0x500078F, 0x5000794, 0x5000799, 0x500079E, 0x30007A3, 0x30007A6, 0x30007A9, 0x30007AC, 0x30007AF, 0x30007B2,
+	0x30007B5, 0x30007B8, 0x30007BB, 0x30007BE, 0x30007C1, 0x30007C4, 0x30007C7, 0x30007CA, 0x50007CD, 0x50007D2, 0x50007D7, 0x50007DC, 0x30007E1, 0x30007E4, 0x30007E7, 0x30007EA,
+	0x30007ED, 0x30007F0, 0x30007F3, 0x30007F6, 0x30007F9, 0x30007FC, 0x30007FF, 0x3000802, 0x3000805, 0x3000808, 0x300080B, 0x300080E, 0x3000811, 0x3000814, 0x3000817, 0x300081A,
+	0x300081D, 0x3000820, 0x3000823, 0x3000826, 0x3000829, 0x300082C, 0x300082F, 0x3000832, 0x3000835, 0x3000838, 0x3001E5B, 0x300077C, 0x0, 0x0, 0x0, 0x0,
+	0x300083F, 0x3000842, 0x3000845, 0x3000848, 0x500084B, 0x5000850, 0x5000855, 0x500085A, 0x500085F, 0x5000864, 0x5000869, 0x500086E, 0x5000873, 0x5000878, 0x500087D, 0x5000882,
+	0x5000887, 0x500088C, 0x5000891, 0x5000896, 0x500089B, 0x50008A0, 0x50008A5, 0x50008AA, 0x30008AF, 0x30008B2, 0x30008B5, 0x30008B8, 0x30008BB, 0x30008BE, 0x50008C1, 0x50008C6,
+	0x50008CB, 0x50008D0, 0x50008D5, 0x50008DA, 0x50008DF, 0x50008E4, 0x50008E9, 0x50008EE, 0x30008F3, 0x30008F6, 0x30008F9, 0x30008FC, 0x30008FF, 0x3000902, 0x3000905, 0x3000908,
+	0x500090B, 0x5000910, 0x5000915, 0x500091A, 0x500091F, 0x5000924, 0x5000929, 0x500092E, 0x5000933, 0x5000938, 0x500093D, 0x5000942, 0x5000947, 0x500094C, 0x5000951, 0x5000956,
+	0x500095B, 0x5000960, 0x5000965, 0x500096A, 0x300096F, 0x3000972, 0x3000975, 0x3000978, 0x500097B, 0x5000980, 0x5000985, 0x500098A, 0x500098F, 0x5000994, 0x5000999, 0x500099E,
+	0x50009A3, 0x50009A8, 0x30009AD, 0x30009B0, 0x30009B3, 0x30009B6, 0x30009B9, 0x30009BC, 0x30009BF, 0x30009C2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x40009C5, 0x40009C9, 0x60009CD, 0x60009D3, 0x60009D9, 0x60009DF, 0x60009E5, 0x60009EB, 0x40009F1, 0x40009F5, 0x60009F9, 0x60009FF, 0x6000A05, 0x6000A0B, 0x6000A11, 0x6000A17,
+	0x4000A1D, 0x4000A21, 0x6000A25, 0x6000A2B, 0x6000A31, 0x6000A37, 0x0, 0x0, 0x4000A3D, 0x4000A41, 0x6000A45, 0x6000A4B, 0x6000A51, 0x6000A57, 0x0, 0x0,
+	0x4000A5D, 0x4000A61, 0x6000A65, 0x6000A6B, 0x6000A71, 0x6000A77, 0x6000A7D, 0x6000A83, 0x4000A89, 0x4000A8D, 0x6000A91, 0x6000A97, 0x6000A9D, 0x6000AA3, 0x6000AA9, 0x6000AAF,
+	0x4000AB5, 0x4000AB9, 0x6000ABD, 0x6000AC3, 0x6000AC9, 0x6000ACF, 0x6000AD5, 0x6000ADB, 0x4000AE1, 0x4000AE5, 0x6000AE9, 0x6000AEF, 0x6000AF5, 0x6000AFB, 0x6000B01, 0x6000B07,
+	0x4000B0D, 0x4000B11, 0x6000B15, 0x6000B1B, 0x6000B21, 0x6000B27, 0x0, 0x0, 0x4000B2D, 0x4000B31, 0x6000B35, 0x6000B3B, 0x6000B41, 0x6000B47, 0x0, 0x0,
+	0x4000B4D, 0x4000B51, 0x6000B55, 0x6000B5B, 0x6000B61, 0x6000B67, 0x6000B6D, 0x6000B73, 0x0, 0x4000B79, 0x0, 0x6001E5E, 0x0, 0x6000B83, 0x0, 0x6000B89,
+	0x4000B8F, 0x4000B93, 0x6000B97, 0x6000B9D, 0x6000BA3, 0x6000BA9, 0x6000BAF, 0x6000BB5, 0x4000BBB, 0x4000BBF, 0x6000BC3, 0x6000BC9, 0x6000BCF, 0x6000BD5, 0x6000BDB, 0x6000BE1,
+	0x4000BE7, 0x4000357, 0x4000BEB, 0x400035B, 0x4000BEF, 0x400035F, 0x4000BF3, 0x4000363, 0x4000BF7, 0x400036D, 0x4000BFB, 0x4000371, 0x4000BFF, 0x4000375, 0x0, 0x0,
+	0x6000C03, 0x6000C09, 0x8000C0F, 0x8000C17, 0x8000C1F, 0x8000C27, 0x8000C2F, 0x8000C37, 0x6000C3F, 0x6000C45, 0x8000C4B, 0x8000C53, 0x8000C5B, 0x8000C63, 0x8000C6B, 0x8000C73,
+	0x6000C7B, 0x6000C81, 0x8000C87, 0x8000C8F, 0x8000C97, 0x8000C9F, 0x8000CA7, 0x8000CAF, 0x6000CB7, 0x6000CBD, 0x8000CC3, 0x8000CCB, 0x8000CD3, 0x8000CDB, 0x8000CE3, 0x8000CEB,
+	0x6000CF3, 0x6000CF9, 0x8000CFF, 0x8000D07, 0x8000D0F, 0x8000D17, 0x8000D1F, 0x8000D27, 0x6000D2F, 0x6000D35, 0x8000D3B, 0x8000D43, 0x8000D4B, 0x8000D53, 0x8000D5B, 0x8000D63,
+	0x4000D6B, 0x4000D6F, 0x6000D73, 0x4000D79, 0x6000D7D, 0x0, 0x4000D83, 0x6001E64, 0x4000D8D, 0x4000D91, 0x4000D95, 0x400032B, 0x4000D99, 0x3001E6A, 0x2000349, 0x3001E6A,
+	0x3001E6D, 0x5001E70, 0x6000DA1, 0x4000DA7, 0x6000DAB, 0x0, 0x4000DB1, 0x6001E75, 0x4000DBB, 0x4000331, 0x4000DBF, 0x4000335, 0x4000DC3, 0x5001E7B, 0x5001E80, 0x5001E85,
+	0x4000DD6, 0x4000DDA, 0x6000DDE, 0x6000349, 0x0, 0x0, 0x4000DE4, 0x6000DE8, 0x4000DEE, 0x4000DF2, 0x4000DF6, 0x4000339, 0x0, 0x5001E8A, 0x5001E8F, 0x5001E94,
+	0x4000E09, 0x4000E0D, 0x6000E11, 0x6000367, 0x4000E17, 0x4000E1B, 0x4000E1F, 0x6000E23, 0x4000E29, 0x4000E2D, 0x4000E31, 0x4000341, 0x4000E35, 0x5001E99, 0x5001D84, 0x1000E3D,
+	0x0, 0x0, 0x6000E3E, 0x4000E44, 0x6000E48, 0x0, 0x4000E4E, 0x6001E9E, 0x4000E58, 0x400033D, 0x4000E5C, 0x4000345, 0x4000E60, 0x3001D26, 0x3001E8A, 0x0,
+	0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x1001D1D, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3001EA4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001EA7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x1001EAA, 0x2001EAB, 0x3001EAA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1001D1D,
+	0x0, 0x0, 0x0, 0x6001EAD, 0x9001EB3, 0x0, 0x6001EBC, 0x9001EC2, 0x0, 0x0, 0x0, 0x0, 0x2001ECB, 0x0, 0x3001ECD, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2001ED0, 0x2001ED2, 0x2001ED4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC001EAD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1001D1D,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1001ED6, 0x100006F, 0x0, 0x0, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x1001EDC, 0x3001EDD, 0x1000EB7, 0x1001EE0, 0x1001EE1, 0x100007B,
+	0x1001ED6, 0x1001D2E, 0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x1001EDC, 0x3001EDD, 0x1000EB7, 0x1001EE0, 0x1001EE1, 0x0,
+	0x100004E, 0x1000063, 0x100007E, 0x100080E, 0x2001DFA, 0x1000108, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x1000754, 0x100017D, 0x1000195, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2001EE2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3001EE4, 0x3001EE7, 0x1000012, 0x3001EEA, 0x0, 0x3001EED, 0x3001EF0, 0x2001EF3, 0x0, 0x3001EF5, 0x10000F0, 0x1000105, 0x1000105, 0x1000105, 0x1000108, 0x2001EF8,
+	0x1000021, 0x1000021, 0x1000132, 0x1000135, 0x0, 0x100002D, 0x2001EFA, 0x0, 0x0, 0x1000751, 0x1001EFC, 0x1000168, 0x1000168, 0x1000168, 0x0, 0x0,
+	0x2001EFD, 0x3001EFF, 0x2001F02, 0x0, 0x10001D1, 0x0, 0x2000345, 0x0, 0x10001D1, 0x0, 0x100012C, 0x300000F, 0x1000633, 0x1000012, 0x0, 0x1000063,
+	0x1000015, 0x1000697, 0x0, 0x10006FF, 0x100007E, 0x20015C7, 0x20015D3, 0x20015D7, 0x20015DB, 0x100006F, 0x0, 0x3001F04, 0x2001D8F, 0x2001E12, 0x2001F07, 0x2001F09,
+	0x3001F0B, 0x0, 0x0, 0x0, 0x0, 0x10000C9, 0x10000CC, 0x1000063, 0x100006F, 0x1000129, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x5001F0E, 0x5001F13, 0x6001F18, 0x5001F1E, 0x5001F23, 0x5001F28, 0x5001F2D, 0x5001F32, 0x5001F37, 0x5001F3C, 0x5001F41, 0x5001F46, 0x5001F4B, 0x5001F50, 0x5001F55, 0x4001D34,
+	0x1000021, 0x2001F5A, 0x3001F5C, 0x2001F5F, 0x10007E1, 0x2001F61, 0x3001F63, 0x4001F66, 0x2001F6A, 0x100080B, 0x2001F6C, 0x3001F6E, 0x1000132, 0x1000012, 0x10000C9, 0x10006FF,
+	0x100006F, 0x2001F71, 0x3001F73, 0x2001F76, 0x10007E4, 0x2001F78, 0x3001F7A, 0x4001F7D, 0x2001F81, 0x100080E, 0x2001F83, 0x3001F85, 0x1000135, 0x1000060, 0x10000CC, 0x1000702,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5001F88, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000E6C, 0x5000E71, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000E76, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000E7B, 0x5000E80, 0x5000E85,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x5000E8A, 0x0, 0x0, 0x0, 0x0, 0x5000E8F, 0x0, 0x0, 0x5000E94, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x5000E99, 0x0, 0x5000E9E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6001F8D, 0x9001F93, 0x0, 0x6001F9C,
+	0x9001FA2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x5000EA3, 0x0, 0x0, 0x5000EA8, 0x0, 0x0, 0x5000EAD, 0x0, 0x5000EB2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3000EB7, 0x0, 0x5000EBA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000EBF, 0x3000EC4, 0x3000EC7,
+	0x5000ECA, 0x5000ECF, 0x0, 0x0, 0x5000ED4, 0x5000ED9, 0x0, 0x0, 0x5000EDE, 0x5000EE3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x5000EE8, 0x5000EED, 0x0, 0x0, 0x5000EF2, 0x5000EF7, 0x0, 0x0, 0x5000EFC, 0x5000F01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000F06, 0x5000F0B, 0x5000F10, 0x5000F15,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x5000F1A, 0x5000F1F, 0x5000F24, 0x5000F29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000F2E, 0x5000F33, 0x5000F38, 0x5000F3D, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3000F42, 0x3000F45, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1001D2E, 0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x2001F1C, 0x2001D2E, 0x2001FAB, 0x2001FAD, 0x2001FAF, 0x2001FB1, 0x2001FB3,
+	0x2001FB5, 0x2001FB7, 0x2001FB9, 0x2001FBB, 0x3001FBD, 0x3001FC0, 0x3001FC3, 0x3001FC6, 0x3001FC9, 0x3001FCC, 0x3001FCF, 0x3001FD2, 0x3001FD5, 0x4001FD8, 0x4001FDC, 0x4001FE0,
+	0x4001FE4, 0x4001FE8, 0x4001FEC, 0x4001FF0, 0x4001FF4, 0x4001FF8, 0x4001FFC, 0x4002000, 0x2002004, 0x2002006, 0x2002008, 0x200200A, 0x200200C, 0x200200E, 0x2002010, 0x2002012,
+	0x2002014, 0x3002016, 0x3002019, 0x300201C, 0x300201F, 0x3002022, 0x3002025, 0x3002028, 0x300202B, 0x300202E, 0x3002031, 0x3002034, 0x3002037, 0x300203A, 0x300203D, 0x3002040,
+	0x3002043, 0x3002046, 0x3002049, 0x300204C, 0x300204F, 0x3002052, 0x3002055, 0x3002058, 0x300205B, 0x300205E, 0x3002061, 0x3002064, 0x3002067, 0x300206A, 0x300206D, 0x3002070,
+	0x3002073, 0x3002076, 0x3002079, 0x300207C, 0x300207F, 0x3002082, 0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126,
+	0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030, 0x1000751, 0x1001EFC, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1,
+	0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E, 0x1000754,
+	0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1001ED6, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC001F8D, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x3002085, 0x2002088, 0x3002087, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5000F48, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000129, 0x10007E1, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300208A,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300208D,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3002090, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3002093, 0x3002096, 0x3002099, 0x300209C, 0x300209F, 0x30020A2, 0x30020A5, 0x30020A8, 0x30020AB, 0x30020AE, 0x30020B1, 0x30020B4, 0x30020B7, 0x30020BA, 0x30020BD, 0x30020C0,
+	0x300176F, 0x30020C3, 0x3001241, 0x30020C6, 0x30020C9, 0x30020CC, 0x30020CF, 0x30020D2, 0x30020D5, 0x30020D8, 0x30020DB, 0x30020DE, 0x30020E1, 0x30020E4, 0x30020E7, 0x30020EA,
+	0x30020ED, 0x30020F0, 0x30020F3, 0x30020F6, 0x30020F9, 0x3001226, 0x30020FC, 0x30020FF, 0x3002102, 0x3002105, 0x3001854, 0x3002108, 0x3001427, 0x300210B, 0x300210E, 0x3002111,
+	0x3002114, 0x3002117, 0x300211A, 0x300211D, 0x3002120, 0x3002123, 0x30018A3, 0x3002126, 0x3002129, 0x300212C, 0x300212F, 0x3002132, 0x3002135, 0x3002138, 0x300213B, 0x300213E,
+	0x3002141, 0x3002144, 0x3002147, 0x300214A, 0x300214D, 0x3002150, 0x3002153, 0x3002156, 0x3002159, 0x300215C, 0x300215F, 0x3002162, 0x3002165, 0x3001512, 0x3002168, 0x300216B,
+	0x300216E, 0x3002171, 0x3002174, 0x3002177, 0x300217A, 0x300217D, 0x3002180, 0x3002183, 0x3002186, 0x3002189, 0x300218C, 0x300218F, 0x3002192, 0x3002195, 0x3002198, 0x300219B,
+	0x300219E, 0x30021A1, 0x30021A4, 0x30021A7, 0x30021AA, 0x30021AD, 0x30021B0, 0x30021B3, 0x30021B6, 0x30021B9, 0x30021BC, 0x30021BF, 0x30021C2, 0x30021C5, 0x30021C8, 0x30021CB,
+	0x30021CE, 0x30021D1, 0x30021D4, 0x30021D7, 0x300137C, 0x30021DA, 0x30021DD, 0x30021E0, 0x30021E3, 0x30021E6, 0x30021E9, 0x30013E2, 0x3001142, 0x30021EC, 0x30021EF, 0x30021F2,
+	0x30021F5, 0x30021F8, 0x30021FB, 0x30021FE, 0x3002201, 0x3002204, 0x3002207, 0x300220A, 0x300220D, 0x3002210, 0x3002213, 0x3002216, 0x3002219, 0x300221C, 0x300221F, 0x30013AF,
+	0x3001C0A, 0x3002222, 0x30013B5, 0x3002225, 0x3002228, 0x300222B, 0x300222E, 0x3001C31, 0x3002231, 0x3002234, 0x3002237, 0x300223A, 0x300223D, 0x3002240, 0x30010AF, 0x3002243,
+	0x30011F6, 0x3002246, 0x3002249, 0x300224C, 0x300224F, 0x3001352, 0x30010C4, 0x3002252, 0x3002255, 0x3002258, 0x300225B, 0x300225E, 0x3002261, 0x3002264, 0x3002267, 0x300226A,
+	0x300226D, 0x3002270, 0x3002273, 0x3002276, 0x3002279, 0x300227C, 0x300227F, 0x3002282, 0x3002285, 0x3002288, 0x300228B, 0x300228E, 0x3002291, 0x3002294, 0x3002297, 0x300229A,
+	0x300229D, 0x30022A0, 0x30022A3, 0x30022A6, 0x30022A9, 0x3001166, 0x30022AC, 0x3001D01, 0x30022AF, 0x30022B2, 0x30022B5, 0x3001D07, 0x30022B8, 0x30022BB, 0x30022BE, 0x30022C1,
+	0x3001D16, 0x30022C4, 0x30022C7, 0x30012E6, 0x30010BE, 0x30022CA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1001D1D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30022CD, 0x0, 0x30020D2, 0x30022D0, 0x30022D3, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000F4D, 0x0, 0x6000F53, 0x0,
+	0x6000F59, 0x0, 0x6000F5F, 0x0, 0x6000F65, 0x0, 0x6000F6B, 0x0, 0x6000F71, 0x0, 0x6000F77, 0x0, 0x6000F7D, 0x0, 0x6000F83, 0x0,
+	0x6000F89, 0x0, 0x6000F8F, 0x0, 0x0, 0x6000F95, 0x0, 0x6000F9B, 0x0, 0x6000FA1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6000FA7, 0x6000FAD, 0x0, 0x6000FB3, 0x6000FB9, 0x0, 0x6000FBF, 0x6000FC5, 0x0, 0x6000FCB, 0x6000FD1, 0x0, 0x6000FD7, 0x6000FDD, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x6000FE3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40022D6, 0x40022DA, 0x0, 0x6000FE9, 0x60022DE,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6000FEF, 0x0, 0x6000FF5, 0x0,
+	0x6000FFB, 0x0, 0x6001001, 0x0, 0x6001007, 0x0, 0x600100D, 0x0, 0x6001013, 0x0, 0x6001019, 0x0, 0x600101F, 0x0, 0x6001025, 0x0,
+	0x600102B, 0x0, 0x6001031, 0x0, 0x0, 0x6001037, 0x0, 0x600103D, 0x0, 0x6001043, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6001049, 0x600104F, 0x0, 0x6001055, 0x600105B, 0x0, 0x6001061, 0x6001067, 0x0, 0x600106D, 0x6001073, 0x0, 0x6001079, 0x600107F, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x6001085, 0x0, 0x0, 0x600108B, 0x6001091, 0x6001097, 0x600109D, 0x0, 0x0, 0x0, 0x60010A3, 0x60022E4,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x30022EA, 0x30022ED, 0x30022F0, 0x30022F3, 0x30022F6, 0x30022F9, 0x30022FC, 0x30022FF, 0x3002302, 0x3002305, 0x3002308, 0x300230B, 0x300230E, 0x3002311, 0x3002314,
+	0x3002317, 0x300231A, 0x300231D, 0x3002320, 0x3002323, 0x3002326, 0x3002329, 0x300232C, 0x300232F, 0x3002332, 0x3002335, 0x3002338, 0x300233B, 0x300233E, 0x3002341, 0x3002344,
+	0x3002347, 0x300234A, 0x300234D, 0x3002350, 0x3002353, 0x3002356, 0x3002359, 0x300235C, 0x300235F, 0x3002362, 0x3002365, 0x3002368, 0x300236B, 0x300236E, 0x3002371, 0x3002374,
+	0x3002377, 0x300237A, 0x300237D, 0x3002380, 0x3002383, 0x3002386, 0x3002389, 0x300238C, 0x300238F, 0x3002392, 0x3002395, 0x3002398, 0x300239B, 0x300239E, 0x30023A1, 0x30023A4,
+	0x30023A7, 0x30023AA, 0x30023AD, 0x30023B0, 0x30023B3, 0x30023B6, 0x30023B9, 0x30023BC, 0x30023BF, 0x30023C2, 0x30023C5, 0x30023C8, 0x30023CB, 0x30023CE, 0x30023D1, 0x30023D4,
+	0x30023D7, 0x30023DA, 0x30023DD, 0x30023E0, 0x30023E3, 0x30023E6, 0x30023E9, 0x30023EC, 0x30023EF, 0x30023F2, 0x30023F5, 0x30023F8, 0x30023FB, 0x30023FE, 0x3002401, 0x0,
+	0x0, 0x0, 0x3002093, 0x30020A5, 0x3002404, 0x3002407, 0x300240A, 0x300240D, 0x3002410, 0x3002413, 0x300209F, 0x3002416, 0x3002419, 0x300241C, 0x300241F, 0x30020AB,
+	0x5002422, 0x5002427, 0x500242C, 0x5002431, 0x5002436, 0x500243B, 0x5002440, 0x5002445, 0x500244A, 0x500244F, 0x5002454, 0x5002459, 0x500245E, 0x5002463, 0x8002468, 0x8002470,
+	0x8002478, 0x8002480, 0x8002488, 0x8002490, 0x8002498, 0x80024A0, 0x80024A8, 0x80024B0, 0x80024B8, 0x80024C0, 0x80024C8, 0x80024D0, 0x80024D8, 0x110024E0, 0xE0024F1, 0x0,
+	0x50024FF, 0x5002504, 0x5002509, 0x500250E, 0x5002513, 0x5002518, 0x500251D, 0x5002522, 0x5002527, 0x500252C, 0x5002531, 0x5002536, 0x500253B, 0x5002540, 0x5002545, 0x500254A,
+	0x500254F, 0x5002554, 0x5002559, 0x500255E, 0x5002563, 0x5002568, 0x500256D, 0x5002572, 0x5002577, 0x500257C, 0x5002581, 0x5002586, 0x500258B, 0x5002590, 0x5002595, 0x500259A,
+	0x500259F, 0x50025A4, 0x50025A9, 0x50025AE, 0x30025B3, 0x30025B6, 0x3002147, 0x30025B9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30025BC, 0x2001FAC, 0x20025BF, 0x2001D24, 0x20025C1, 0x20025C3, 0x20025C5, 0x20025C7, 0x20025C9, 0x20025CB, 0x20025CD, 0x2001F27, 0x2001F22, 0x20025CF, 0x20025D1, 0x20025D3,
+	0x30022EA, 0x30022F3, 0x30022FC, 0x3002302, 0x300231A, 0x300231D, 0x3002326, 0x300232C, 0x300232F, 0x3002335, 0x3002338, 0x300233B, 0x300233E, 0x3002341, 0x6002469, 0x6002471,
+	0x6002479, 0x6002481, 0x6002489, 0x6002491, 0x6002499, 0x60024A1, 0x60024A9, 0x60024B1, 0x60024B9, 0x60024C1, 0x60024C9, 0x6002341, 0xF0025D5, 0xC0025E4, 0x60025F0, 0x0,
+	0x3002093, 0x30020A5, 0x3002404, 0x3002407, 0x3002514, 0x300130D, 0x300251E, 0x30020B4, 0x3002528, 0x30020D2, 0x300215C, 0x300217D, 0x300217A, 0x300215F, 0x30010C4, 0x30020EA,
+	0x3002156, 0x3002555, 0x300255A, 0x3001457, 0x3002564, 0x3002569, 0x300256E, 0x3001466, 0x3002578, 0x30025F6, 0x30025F9, 0x3001226, 0x30025FC, 0x30025FF, 0x3002602, 0x3002605,
+	0x3002608, 0x30025A5, 0x300260B, 0x300260E, 0x300240A, 0x300240D, 0x3002410, 0x3002611, 0x3002614, 0x3002617, 0x300261A, 0x3002587, 0x300258C, 0x3002591, 0x3002596, 0x300259B,
+	0x300261D, 0x2002620, 0x2002622, 0x2002624, 0x2002626, 0x2002628, 0x2001D33, 0x20025C2, 0x20025D2, 0x200262A, 0x200262C, 0x200262E, 0x2002630, 0x2002632, 0x2002634, 0x2002636,
+	0x4002638, 0x400263C, 0x4002640, 0x4002644, 0x4002648, 0x400264C, 0x4002650, 0x4002654, 0x4002658, 0x500265C, 0x5002661, 0x5002666, 0x200266B, 0x300266D, 0x2002670, 0x3002672,
+	0x3002675, 0x3002678, 0x3001085, 0x300267B, 0x300267E, 0x3000FEF, 0x3000FF5, 0x3000FFB, 0x3001001, 0x3001007, 0x300100D, 0x3001013, 0x3001019, 0x300101F, 0x3001025, 0x300102B,
+	0x3001031, 0x3001037, 0x300103D, 0x3001043, 0x3002681, 0x3002684, 0x3002687, 0x300268A, 0x300268D, 0x3001049, 0x3001055, 0x3001061, 0x300106D, 0x3001079, 0x3002690, 0x3002693,
+	0x3002696, 0x3002699, 0x300269C, 0x300269F, 0x30026A2, 0x30026A5, 0x30026A8, 0x30026AB, 0x30026AE, 0x30026B1, 0x30026B4, 0x300108B, 0x3001091, 0x3001097, 0x300109D, 0x0,
+	0xF0026B7, 0xC0026C6, 0xF0026D2, 0x90026E1, 0xF0026EA, 0x90026F9, 0x9002702, 0x1200270B, 0xC00271D, 0x9002729, 0x9002732, 0x900273B, 0xC002744, 0xC002750, 0xC00275C, 0xC002768,
+	0xC002774, 0xC002780, 0xC00278C, 0x12002798, 0x60027AA, 0x120027B0, 0x120027C2, 0xF0027D4, 0xC0027B6, 0x120027E3, 0x120027F5, 0xC002807, 0x9002813, 0x900281C, 0xC002825, 0xC002831,
+	0xF00283D, 0xF00284C, 0x900285B, 0x9002864, 0xC00286D, 0x9002879, 0x9002882, 0x60027EF, 0x600288B, 0x9002891, 0x900289A, 0x120028A3, 0xC0028B5, 0xF0028C1, 0x120028D0, 0xC0028E2,
+	0x90028EE, 0x90028F7, 0x12002900, 0xC002912, 0x1200291E, 0x9002930, 0xF002939, 0x9002948, 0xC002951, 0x900295D, 0xC002966, 0xF002972, 0xC002981, 0xF00298D, 0xC00299C, 0x60029A8,
+	0xF0029AE, 0x90029BD, 0x90029C6, 0xC0029CF, 0x90029DB, 0x90029E4, 0x90029ED, 0xF0029F6, 0xC002A05, 0x6002A11, 0x12002A17, 0x9002A29, 0xF002A32, 0xC0027C8, 0xC002A41, 0x9002A4D,
+	0x9002A56, 0xC002A5F, 0x6002A6B, 0xC002A71, 0xF002A7D, 0x6002A8C, 0x12002A92, 0x90027DA, 0x4002AA4, 0x4002AA8, 0x4002AAC, 0x4002AB0, 0x4002AB4, 0x4002AB8, 0x4002ABC, 0x4002AC0,
+	0x4002AC4, 0x4002AC8, 0x5002ACC, 0x5002AD1, 0x5002AD6, 0x5002ADB, 0x5002AE0, 0x5002AE5, 0x5002AEA, 0x5002AEF, 0x5002AF4, 0x5002AF9, 0x5002AFE, 0x5002B03, 0x5002B08, 0x5002B0D,
+	0x5002B12, 0x3002B17, 0x2002B1A, 0x2002B1C, 0x3002B1E, 0x2002B21, 0x2002B23, 0x2002B25, 0x3002B27, 0x3002B2A, 0x2002B2D, 0x6002B2F, 0x6002B35, 0x6002B3B, 0x6002B41, 0xC002B47,
+	0x2002B53, 0x2002B55, 0x3002B57, 0x2002B5A, 0x2002B5C, 0x2002B5E, 0x2002B60, 0x2002B62, 0x3002B64, 0x4002B67, 0x2002B6B, 0x2002B6D, 0x3002B6F, 0x3002B72, 0x2002B75, 0x2002B77,
+	0x2002B79, 0x3002B7B, 0x3002B7E, 0x3002B81, 0x3002B84, 0x3002B87, 0x2002B8A, 0x2002B8C, 0x2002B8E, 0x2002B90, 0x2002B92, 0x3002B94, 0x2002B97, 0x2002B99, 0x2002B9B, 0x3002B9D,
+	0x3002BA0, 0x2002B28, 0x3002BA3, 0x3002BA6, 0x3002BA9, 0x2002B2B, 0x3002BAC, 0x5002BAF, 0x6002BB4, 0x2002B18, 0x3002BBA, 0x3002BBD, 0x3002BC0, 0x3002BC3, 0x7002BC6, 0x8002BCD,
+	0x2002BD5, 0x2002BD7, 0x3002BD9, 0x2002BDC, 0x2002BDE, 0x2002BE0, 0x3002BE2, 0x2002BE5, 0x2002BE7, 0x2002BE9, 0x2002BEB, 0x2002BED, 0x3002BEF, 0x2002BF2, 0x2002BF4, 0x2002BF6,
+	0x3002BF8, 0x3002BFB, 0x4002BFE, 0x2002C02, 0x2002C04, 0x2002B24, 0x6002C06, 0x3002C0C, 0x2002C0F, 0x2002C11, 0x2002C13, 0x2002C15, 0x2002C17, 0x2002C19, 0x2002C1B, 0x2002C1D,
+	0x2002B89, 0x2002C1F, 0x3002C21, 0x2002C24, 0x2002C26, 0x3002C28, 0x3002C2B, 0x2002C2E, 0x4002C30, 0x3002C34, 0x2002C37, 0x2002BCC, 0x2002C39, 0x2002C3B, 0x5002C3D, 0x5002C42,
+	0x4002C47, 0x4002C4B, 0x4002C4F, 0x4002C53, 0x4002C57, 0x4002C5B, 0x4002C5F, 0x4002C63, 0x4002C67, 0x5002C6B, 0x5002C70, 0x5002C75, 0x5002C7A, 0x5002C7F, 0x5002C84, 0x5002C89,
+	0x5002C8E, 0x5002C93, 0x5002C98, 0x5002C9D, 0x5002CA2, 0x5002CA7, 0x5002CAC, 0x5002CB1, 0x5002CB6, 0x5002CBB, 0x5002CC0, 0x5002CC5, 0x5002CCA, 0x5002CCF, 0x5002CD4, 0x3002CD9,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2002CDC, 0x2002CDE, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3002CE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2002CE3, 0x2002CE5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3002CE7, 0x3002CEA, 0x2002CED, 0x3002CEF,
+	0x30010A9, 0x30010AC, 0x30010AF, 0x30010B2, 0x30010B5, 0x30010B8, 0x30010BB, 0x30010BE, 0x30010BE, 0x30010C1, 0x30010C4, 0x30010C7, 0x30010CA, 0x30010CD, 0x30010D0, 0x30010D3,
+	0x30010D6, 0x30010D9, 0x30010DC, 0x30010DF, 0x30010E2, 0x30010E5, 0x30010E8, 0x30010EB, 0x30010EE, 0x30010F1, 0x30010F4, 0x30010F7, 0x30010FA, 0x30010FD, 0x3001100, 0x3001103,
+	0x3001106, 0x3001109, 0x300110C, 0x300110F, 0x3001112, 0x3001115, 0x3001118, 0x300111B, 0x300111E, 0x3001121, 0x3001124, 0x3001127, 0x300112A, 0x300112D, 0x3001130, 0x3001133,
+	0x3001136, 0x3001139, 0x300113C, 0x300113F, 0x3001142, 0x3001145, 0x3001148, 0x300114B, 0x300114E, 0x3001151, 0x3001154, 0x3001157, 0x300115A, 0x300115D, 0x3001160, 0x3001163,
+	0x3001166, 0x3001169, 0x300116C, 0x300116F, 0x3001172, 0x3001175, 0x3001178, 0x300117B, 0x300117E, 0x3001181, 0x3001184, 0x3001187, 0x300118A, 0x300118D, 0x3001190, 0x3001193,
+	0x3001196, 0x3001199, 0x300119C, 0x300119F, 0x30011A2, 0x30011A5, 0x30011A8, 0x30011AB, 0x30011AE, 0x30011B1, 0x30011B4, 0x30011B7, 0x30010E2, 0x30011BA, 0x30011BD, 0x30011C0,
+	0x30011C3, 0x30011C6, 0x30011C9, 0x30011CC, 0x30011CF, 0x30011D2, 0x30011D5, 0x30011D8, 0x30011DB, 0x30011DE, 0x30011E1, 0x30011E4, 0x30011E7, 0x30011EA, 0x30011ED, 0x30011F0,
+	0x30011F3, 0x30011F6, 0x30011F9, 0x30011FC, 0x30011FF, 0x3001202, 0x3001205, 0x3001208, 0x300120B, 0x300120E, 0x3001211, 0x3001214, 0x3001217, 0x300121A, 0x300121D, 0x3001220,
+	0x3001223, 0x3001226, 0x3001229, 0x300122C, 0x300122F, 0x3001232, 0x3001235, 0x3001238, 0x300123B, 0x300123E, 0x3001241, 0x3001244, 0x3001247, 0x300124A, 0x300124D, 0x3001250,
+	0x3001253, 0x3001256, 0x3001259, 0x300125C, 0x300125F, 0x3001262, 0x3001265, 0x3001268, 0x300126B, 0x300126E, 0x3001271, 0x3001274, 0x3001277, 0x300127A, 0x300127D, 0x3001280,
+	0x3001283, 0x30011F0, 0x3001286, 0x3001289, 0x300128C, 0x300128F, 0x3001292, 0x3001295, 0x3001298, 0x300129B, 0x30011C0, 0x300129E, 0x30012A1, 0x30012A4, 0x30012A7, 0x30012AA,
+	0x30012AD, 0x30012B0, 0x30012B3, 0x30012B6, 0x30012B9, 0x30012BC, 0x30012BF, 0x30012C2, 0x30012C5, 0x30012C8, 0x30012CB, 0x30012CE, 0x30012D1, 0x30012D4, 0x30012D7, 0x30010E2,
+	0x30012DA, 0x30012DD, 0x30012E0, 0x30012E3, 0x30012E6, 0x30012E9, 0x30012EC, 0x30012EF, 0x30012F2, 0x30012F5, 0x30012F8, 0x30012FB, 0x30012FE, 0x3001301, 0x3001304, 0x3001307,
+	0x300130A, 0x300130D, 0x3001310, 0x3001313, 0x3001316, 0x3001319, 0x300131C, 0x300131F, 0x3001322, 0x3001325, 0x3001328, 0x30011C6, 0x300132B, 0x300132E, 0x3001331, 0x3001334,
+	0x3001337, 0x300133A, 0x300133D, 0x3001340, 0x3001343, 0x3001346, 0x3001349, 0x300134C, 0x300134F, 0x3001352, 0x3001355, 0x3001358, 0x300135B, 0x300135E, 0x3001361, 0x3001364,
+	0x3001367, 0x300136A, 0x300136D, 0x3001370, 0x3001373, 0x3001376, 0x3001379, 0x300137C, 0x300137F, 0x3001382, 0x3001385, 0x3001388, 0x300138B, 0x300138E, 0x3001391, 0x3001394,
+	0x3001397, 0x300139A, 0x300139D, 0x30013A0, 0x30013A3, 0x30013A6, 0x30013A9, 0x30013AC, 0x30013AF, 0x30013B2, 0x30013B5, 0x30013B8, 0x30013BB, 0x30013BE, 0x0, 0x0,
+	0x30013C1, 0x0, 0x30013C4, 0x0, 0x0, 0x30013C7, 0x30013CA, 0x30013CD, 0x30013D0, 0x30013D3, 0x30013D6, 0x30013D9, 0x30013DC, 0x30013DF, 0x30013E2, 0x0,
+	0x30013E5, 0x0, 0x30013E8, 0x0, 0x0, 0x30013EB, 0x30013EE, 0x0, 0x0, 0x0, 0x30013F1, 0x30013F4, 0x30013F7, 0x30013FA, 0x30013FD, 0x3001400,
+	0x3001403, 0x3001406, 0x3001409, 0x300140C, 0x300140F, 0x3001412, 0x3001415, 0x3001418, 0x300141B, 0x300141E, 0x3001421, 0x3001424, 0x3001427, 0x300142A, 0x300142D, 0x3001430,
+	0x3001433, 0x3001436, 0x3001439, 0x300143C, 0x300143F, 0x3001442, 0x3001445, 0x3001448, 0x300144B, 0x300144E, 0x3001451, 0x3001454, 0x3001457, 0x300145A, 0x300145D, 0x3001460,
+	0x3001463, 0x3001466, 0x3001469, 0x300146C, 0x300146F, 0x3001472, 0x3001475, 0x3001265, 0x3001478, 0x300147B, 0x300147E, 0x3001481, 0x3001484, 0x3001487, 0x3001487, 0x300148A,
+	0x300148D, 0x3001490, 0x3001493, 0x3001496, 0x3001499, 0x300149C, 0x300149F, 0x30013EB, 0x30014A2, 0x30014A5, 0x30014A8, 0x30014AB, 0x40014AE, 0x30014B2, 0x0, 0x0,
+	0x30014B5, 0x30014B8, 0x30014BB, 0x30014BE, 0x30014C1, 0x30014C4, 0x30014C7, 0x30014CA, 0x3001415, 0x30014CD, 0x30014D0, 0x30014D3, 0x30013C1, 0x30014D6, 0x30014D9, 0x30014DC,
+	0x30014DF, 0x30014E2, 0x30014E5, 0x30014E8, 0x30014EB, 0x30014EE, 0x30014F1, 0x30014F4, 0x30014F7, 0x3001430, 0x30014FA, 0x3001433, 0x30014FD, 0x3001500, 0x3001503, 0x3001506,
+	0x3001509, 0x30013C4, 0x3001121, 0x300150C, 0x300150F, 0x3001512, 0x30011F3, 0x30012F8, 0x3001515, 0x3001518, 0x3001448, 0x300151B, 0x300144B, 0x300151E, 0x3001521, 0x3001524,
+	0x30013CA, 0x3001527, 0x300152A, 0x300152D, 0x3001530, 0x3001533, 0x30013CD, 0x3001536, 0x3001539, 0x300153C, 0x300153F, 0x3001542, 0x3001545, 0x3001475, 0x3001548, 0x300154B,
+	0x3001265, 0x300154E, 0x3001481, 0x3001551, 0x3001554, 0x3001557, 0x300155A, 0x300155D, 0x3001490, 0x3001560, 0x30013E8, 0x3001563, 0x3001493, 0x30011BA, 0x3001566, 0x3001496,
+	0x3001569, 0x300149C, 0x300156C, 0x300156F, 0x3001572, 0x3001575, 0x3001578, 0x30014A2, 0x30013DC, 0x300157B, 0x30014A5, 0x300157E, 0x30014A8, 0x3001581, 0x30010BE, 0x4001584,
+	0x4001588, 0x400158C, 0x3001590, 0x3001593, 0x3001596, 0x4001599, 0x400159D, 0x40015A1, 0x30015A5, 0x30015A8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2002CF2, 0x2002CF4, 0x2002CF6, 0x3002CF8, 0x3002CFB, 0x2002CFE, 0x2002CFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x4002D00, 0x4002D04, 0x4002D08, 0x4002D0C, 0x4002D10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40015AB, 0x0, 0x40015AF,
+	0x2002D14, 0x20015C7, 0x20015DB, 0x20015DF, 0x20015F7, 0x20015FB, 0x2002D16, 0x200161B, 0x200161F, 0x1001EDC, 0x40015B3, 0x40015B7, 0x60015BB, 0x60015C1, 0x40015C7, 0x40015CB,
+	0x40015CF, 0x40015D3, 0x40015D7, 0x40015DB, 0x40015DF, 0x40015E3, 0x40015E7, 0x0, 0x40015EB, 0x40015EF, 0x40015F3, 0x40015F7, 0x40015FB, 0x0, 0x40015FF, 0x0,
+	0x4001603, 0x4001607, 0x0, 0x400160B, 0x400160F, 0x0, 0x4001613, 0x4001617, 0x400161B, 0x40015BB, 0x400161F, 0x4001623, 0x4001627, 0x400162B, 0x400162F, 0x4002D18,
+	0x2002D1C, 0x2002D1C, 0x2002D1E, 0x2002D1E, 0x2002D1E, 0x2002D1E, 0x2002D20, 0x2002D20, 0x2002D20, 0x2002D20, 0x2002D22, 0x2002D22, 0x2002D22, 0x2002D22, 0x2002D24, 0x2002D24,
+	0x2002D24, 0x2002D24, 0x2002D26, 0x2002D26, 0x2002D26, 0x2002D26, 0x2002D28, 0x2002D28, 0x2002D28, 0x2002D28, 0x2002D2A, 0x2002D2A, 0x2002D2A, 0x2002D2A, 0x2002D2C, 0x2002D2C,
+	0x2002D2C, 0x2002D2C, 0x2002D2E, 0x2002D2E, 0x2002D2E, 0x2002D2E, 0x2002D30, 0x2002D30, 0x2002D30, 0x2002D30, 0x2002D32, 0x2002D32, 0x2002D32, 0x2002D32, 0x2002D34, 0x2002D34,
+	0x2002D34, 0x2002D34, 0x2002D36, 0x2002D36, 0x2002D38, 0x2002D38, 0x2002D3A, 0x2002D3A, 0x2002D3C, 0x2002D3C, 0x2002D3E, 0x2002D3E, 0x2002D40, 0x2002D40, 0x2002D42, 0x2002D42,
+	0x2002D42, 0x2002D42, 0x2002D44, 0x2002D44, 0x2002D44, 0x2002D44, 0x2002D46, 0x2002D46, 0x2002D46, 0x2002D46, 0x2002D48, 0x2002D48, 0x2002D48, 0x2002D48, 0x2002D4A, 0x2002D4A,
+	0x2002D4C, 0x2002D4C, 0x2002D4C, 0x2002D4C, 0x4000465, 0x4000465, 0x2000469, 0x2000469, 0x2000469, 0x2000469, 0x2002D4E, 0x2002D4E, 0x2002D4E, 0x2002D4E, 0x200046D, 0x200046D,
+	0x400046D, 0x400046D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x2002D50, 0x2002D50, 0x2002D50, 0x2002D50, 0x2001DA5, 0x2001DA5, 0x2002D52, 0x2002D52, 0x2002D54, 0x2002D54, 0x4001DA5, 0x2002D56, 0x2002D56,
+	0x2002D58, 0x2002D58, 0x2002D5A, 0x2002D5A, 0x2002D5C, 0x2002D5C, 0x2002D5C, 0x2002D5C, 0x2002D5E, 0x2002D5E, 0x6002D60, 0x6002D60, 0x6000461, 0x6000461, 0x6002D66, 0x6002D66,
+	0x6002D6C, 0x6002D6C, 0x6002D72, 0x6002D72, 0x6002D78, 0x6002D78, 0x6002D7E, 0x6002D7E, 0x6002D7E, 0x6002D84, 0x6002D84, 0x6002D84, 0x2002D8A, 0x2002D8A, 0x2002D8A, 0x2002D8A,
+	0x6002D8C, 0x6002D92, 0x6002D98, 0x6002D84, 0x6002D9E, 0x4002DA4, 0x4002DA8, 0x4002DAC, 0x4002DB0, 0x4002DB4, 0x4002DB8, 0x4002DBC, 0x4002DC0, 0x4002DC4, 0x4002DC8, 0x4002DCC,
+	0x4002DD0, 0x4002DD4, 0x4002DD8, 0x4002DDC, 0x4002DE0, 0x4002DE4, 0x4002DE8, 0x4002DE6, 0x4002DEC, 0x4002DF0, 0x4002DF4, 0x4002DF8, 0x4002DFC, 0x4002E00, 0x4002E04, 0x4002E08,
+	0x4002E0C, 0x4002E10, 0x4002E14, 0x4002E18, 0x4002E1C, 0x4002E20, 0x4002E24, 0x4002E28, 0x4002E2C, 0x4002E30, 0x4002E34, 0x4002E38, 0x4002E3C, 0x4002E40, 0x4002E44, 0x4002E48,
+	0x4002E4C, 0x4002E50, 0x4002E54, 0x4002E58, 0x4002E5C, 0x4002E60, 0x4002E64, 0x4002E68, 0x4002E6C, 0x4002E70, 0x4002E74, 0x4002E78, 0x4002E7C, 0x4002E80, 0x4002E84, 0x4002E88,
+	0x4002E8C, 0x4002E90, 0x4002E94, 0x4002E98, 0x4002E9C, 0x4002EA0, 0x4002DEA, 0x4002DEE, 0x4002EA4, 0x4002EA8, 0x4002D9C, 0x4002EAC, 0x4002EB0, 0x4002EB4, 0x4002EB8, 0x4002EBC,
+	0x4002EC0, 0x4002EC4, 0x4002EC8, 0x4002ECC, 0x4002ED0, 0x4002DE2, 0x4002ED4, 0x4002ED8, 0x4002E9E, 0x4002EDC, 0x4002ED2, 0x4002EE0, 0x4002EE4, 0x4002EE8, 0x5002EEC, 0x5002EF1,
+	0x5002EF6, 0x5002EFB, 0x5002F00, 0x5002F05, 0x6002F0A, 0x6002F10, 0x6002D98, 0x6002F16, 0x6002D84, 0x6002D9E, 0x4002F1C, 0x4002F20, 0x4002DB0, 0x4002F24, 0x4002DB4, 0x4002DB8,
+	0x4002F28, 0x4002F2C, 0x4002DC8, 0x4002F30, 0x4002DCC, 0x4002DD0, 0x4002F34, 0x4002F38, 0x4002DD8, 0x4002F3C, 0x4002DDC, 0x4002DE0, 0x4002E50, 0x4002E54, 0x4002E60, 0x4002E64,
+	0x4002E68, 0x4002E78, 0x4002E7C, 0x4002E80, 0x4002E84, 0x4002E94, 0x4002E98, 0x4002E9C, 0x4002F40, 0x4002EA4, 0x4002F44, 0x4002F48, 0x4002EB8, 0x4002F4C, 0x4002EBC, 0x4002EC0,
+	0x4002EE8, 0x4002F50, 0x4002F54, 0x4002E9E, 0x4002F58, 0x4002EDC, 0x4002ED2, 0x6002D8C, 0x6002D92, 0x6002F5C, 0x6002D98, 0x6002F62, 0x4002DA4, 0x4002DA8, 0x4002DAC, 0x4002DB0,
+	0x4002F68, 0x4002DBC, 0x4002DC0, 0x4002DC4, 0x4002DC8, 0x4002F6C, 0x4002DD8, 0x4002DE4, 0x4002DE8, 0x4002DE6, 0x4002DEC, 0x4002DF0, 0x4002DF8, 0x4002DFC, 0x4002E00, 0x4002E04,
+	0x4002E08, 0x4002E0C, 0x4002F70, 0x4002E10, 0x4002E14, 0x4002E18, 0x4002E1C, 0x4002E20, 0x4002E24, 0x4002E2C, 0x4002E30, 0x4002E34, 0x4002E38, 0x4002E3C, 0x4002E40, 0x4002E44,
+	0x4002E48, 0x4002E4C, 0x4002E58, 0x4002E5C, 0x4002E6C, 0x4002E70, 0x4002E74, 0x4002E78, 0x4002E7C, 0x4002E88, 0x4002E8C, 0x4002E90, 0x4002E94, 0x4002F74, 0x4002EA0, 0x4002DEA,
+	0x4002DEE, 0x4002EA4, 0x4002EAC, 0x4002EB0, 0x4002EB4, 0x4002EB8, 0x4002F78, 0x4002EC4, 0x4002EC8, 0x4002F7C, 0x4002DE2, 0x4002F80, 0x4002ED8, 0x4002E9E, 0x4002EC2, 0x6002D98,
+	0x6002F62, 0x4002DB0, 0x4002F68, 0x4002DC8, 0x4002F6C, 0x4002DD8, 0x4002F84, 0x4002E08, 0x4002F88, 0x4002F8C, 0x4002F90, 0x4002E78, 0x4002E7C, 0x4002E94, 0x4002EB8, 0x4002F78,
+	0x4002E9E, 0x4002EC2, 0x6002F94, 0x6002F9A, 0x6002FA0, 0x4002FA6, 0x4002FAA, 0x4002FAE, 0x4002FB2, 0x4002FB6, 0x4002FBA, 0x4002FBE, 0x4002FC2, 0x4002FC6, 0x4002FCA, 0x4002FCE,
+	0x4002D96, 0x4002FD2, 0x4002D90, 0x4002FD6, 0x4002EDA, 0x4002FDA, 0x4002FDE, 0x4002FE2, 0x4002FE6, 0x4002FEA, 0x4002FEE, 0x4002FF2, 0x4002F8C, 0x4002FF6, 0x4002FFA, 0x4002FFE,
+	0x4003002, 0x4002FA6, 0x4002FAA, 0x4002FAE, 0x4002FB2, 0x4002FB6, 0x4002FBA, 0x4002FBE, 0x4002FC2, 0x4002FC6, 0x4002FCA, 0x4002FCE, 0x4002D96, 0x4002FD2, 0x4002D90, 0x4002FD6,
+	0x4002EDA, 0x4002FDA, 0x4002FDE, 0x4002FE2, 0x4002FE6, 0x4002FEA, 0x4002FEE, 0x4002FF2, 0x4002F8C, 0x4002FF6, 0x4002FFA, 0x4002FFE, 0x4003002, 0x4002FEA, 0x4002FEE, 0x4002FF2,
+	0x4002F8C, 0x4002F88, 0x4002F90, 0x4002E28, 0x4002DFC, 0x4002E00, 0x4002E04, 0x4002FEA, 0x4002FEE, 0x4002FF2, 0x4002E28, 0x4002E2C, 0x4003006, 0x4003006, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x600300A, 0x6003010, 0x6003010, 0x6003016, 0x600301C, 0x6003022, 0x6003028, 0x600302E, 0x6002DE8, 0x6002DE8, 0x6003034, 0x600303A, 0x6003040, 0x6003046, 0x600304C, 0x6003052,
+	0x6003052, 0x6003058, 0x600305E, 0x600305E, 0x6003064, 0x6003064, 0x600306A, 0x6003070, 0x6003070, 0x6003076, 0x600307C, 0x600307C, 0x6003082, 0x6003082, 0x6003088, 0x600308E,
+	0x600308E, 0x6003094, 0x6003094, 0x600309A, 0x60030A0, 0x60030A6, 0x60030AC, 0x60030AC, 0x60030B2, 0x60030B8, 0x60030BE, 0x60030C4, 0x60030CA, 0x60030CA, 0x60030D0, 0x60030D6,
+	0x60030DC, 0x60030E2, 0x60030E8, 0x60030EE, 0x60030EE, 0x60030F4, 0x60030F4, 0x60030FA, 0x60030FA, 0x6003100, 0x6002DEA, 0x6003106, 0x600310C, 0x6002EA0, 0x6002DEE, 0x6003112,
+	0x0, 0x0, 0x6003118, 0x600311E, 0x6003124, 0x600312A, 0x6003130, 0x6003136, 0x6003136, 0x600313C, 0x6003142, 0x6003148, 0x600314E, 0x600314E, 0x6003154, 0x600315A,
+	0x6003160, 0x6003166, 0x600316C, 0x6003172, 0x6003178, 0x600317E, 0x6003184, 0x600318A, 0x6003190, 0x6003196, 0x600319C, 0x60031A2, 0x60031A8, 0x60031AE, 0x60031B4, 0x60031BA,
+	0x60031C0, 0x60031C6, 0x60031CC, 0x60031D2, 0x60030D0, 0x60030DC, 0x60031D8, 0x60031DE, 0x60031E4, 0x60031EA, 0x60031F0, 0x60031F6, 0x60031F0, 0x60031E4, 0x60031FC, 0x6003202,
+	0x6003208, 0x600320E, 0x6003214, 0x60031F6, 0x60030A6, 0x600306A, 0x600321A, 0x6003220, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6003226, 0x600322C, 0x8003232, 0x800323A, 0x8003242, 0x800324A, 0x8003252, 0x800325A, 0x8003262, 0x600326A, 0x21003270, 0xF003291, 0x80032A0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x10032A8, 0x30032A9, 0x30032AC, 0x1002085, 0x1000326, 0x1001ECB, 0x1001ED0, 0x30032AF, 0x30032B2, 0x3001EAA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2001EAA, 0x30032B5, 0x30032B8, 0x10032BB, 0x10032BB, 0x1001EE0, 0x1001EE1, 0x10032BC, 0x10032BD, 0x30032BE, 0x30032C1, 0x30032C4, 0x30032C7, 0x30032CA, 0x30032CD, 0x3000F42,
+	0x3000F45, 0x30032D0, 0x30032D3, 0x30032D6, 0x30032D9, 0x0, 0x0, 0x10032DC, 0x10032DD, 0x3001ECD, 0x3001ECD, 0x3001ECD, 0x3001ECD, 0x10032BB, 0x10032BB, 0x10032BB,
+	0x10032A8, 0x30032A9, 0x1001EAA, 0x0, 0x1000326, 0x1002085, 0x1001ED0, 0x1001ECB, 0x30032B5, 0x1001EE0, 0x1001EE1, 0x10032BC, 0x10032BD, 0x30032BE, 0x30032C1, 0x10032DE,
+	0x10032DF, 0x10032E0, 0x1001EDC, 0x10032E1, 0x1000EC4, 0x1000EC7, 0x1000EB7, 0x0, 0x10032E2, 0x10032E3, 0x10032E4, 0x10032E5, 0x0, 0x0, 0x0, 0x0,
+	0x30032E6, 0x40032E9, 0x3002EEC, 0x0, 0x3002EF1, 0x0, 0x3002EF6, 0x4002F94, 0x3002EFB, 0x4002F9A, 0x3002F00, 0x4002FA0, 0x3002F05, 0x40032ED, 0x30032F1, 0x40032F4,
+	0x20032F8, 0x4000451, 0x4000451, 0x4000455, 0x4000455, 0x4000459, 0x4000459, 0x400045D, 0x400045D, 0x4000461, 0x4000461, 0x4000461, 0x4000461, 0x2000451, 0x2000451, 0x2002DA4,
+	0x2002DA4, 0x2002DA4, 0x2002DA4, 0x20032FA, 0x20032FA, 0x2002DBC, 0x2002DBC, 0x2002DBC, 0x2002DBC, 0x2002DD4, 0x2002DD4, 0x2002DD4, 0x2002DD4, 0x2002D90, 0x2002D90, 0x2002D90,
+	0x2002D90, 0x2002D96, 0x2002D96, 0x2002D96, 0x2002D96, 0x2002DAE, 0x2002DAE, 0x2002DAE, 0x2002DAE, 0x2003248, 0x2003248, 0x2002EE0, 0x2002EE0, 0x2002EE4, 0x2002EE4, 0x2002F14,
+	0x2002F14, 0x2002DFC, 0x2002DFC, 0x2002DFC, 0x2002DFC, 0x2002F8C, 0x2002F8C, 0x2002F8C, 0x2002F8C, 0x2002E0C, 0x2002E0C, 0x2002E0C, 0x2002E0C, 0x2002E14, 0x2002E14, 0x2002E14,
+	0x2002E14, 0x2002E24, 0x2002E24, 0x2002E24, 0x2002E24, 0x2002E2C, 0x2002E2C, 0x2002E2C, 0x2002E2C, 0x2002E30, 0x2002E30, 0x2002E30, 0x2002E30, 0x2002E38, 0x2002E38, 0x2002E38,
+	0x2002E38, 0x2002E40, 0x2002E40, 0x2002E40, 0x2002E40, 0x2002E58, 0x2002E58, 0x2002E58, 0x2002E58, 0x2002E68, 0x2002E68, 0x2002E68, 0x2002E68, 0x2002E7A, 0x2002E7A, 0x2002E7A,
+	0x2002E7A, 0x2002D9C, 0x2002D9C, 0x2002D9C, 0x2002D9C, 0x2002EAC, 0x2002EAC, 0x2002EAC, 0x2002EAC, 0x2002EC4, 0x2002EC4, 0x2002EC4, 0x2002EC4, 0x2000459, 0x2000459, 0x2002D5E,
+	0x2002D5E, 0x2000461, 0x2000461, 0x2000461, 0x2000461, 0x60032FC, 0x60032FC, 0x6003302, 0x6003302, 0x6003308, 0x6003308, 0x4003298, 0x4003298, 0x0, 0x0, 0x0,
+	0x0, 0x1001ECB, 0x100330E, 0x10032DE, 0x10032E3, 0x10032E4, 0x10032DF, 0x100330F, 0x1001EE0, 0x1001EE1, 0x10032E0, 0x1001EDC, 0x10032A8, 0x10032E1, 0x1001EAA, 0x1001EE5,
+	0x1001ED6, 0x1001D2E, 0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x1002085, 0x1000326, 0x1000EC4, 0x1000EB7, 0x1000EC7, 0x1001ED0,
+	0x10032E5, 0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030,
+	0x1000751, 0x1001EFC, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x10032DC, 0x10032E2, 0x10032DD, 0x1003310, 0x10032BB,
+	0x1000E3D, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E,
+	0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x10032BC, 0x1003311, 0x10032BD, 0x1003312, 0x3003313,
+	0x3003316, 0x30032AC, 0x30032D0, 0x30032D3, 0x30032A9, 0x3003319, 0x300109D, 0x30026CF, 0x3002915, 0x300331C, 0x300292A, 0x3002705, 0x300331F, 0x300278F, 0x30029FF, 0x300274A,
+	0x30026C0, 0x3002675, 0x3002678, 0x3001085, 0x300267B, 0x300267E, 0x3000FEF, 0x3000FF5, 0x3000FFB, 0x3001001, 0x3001007, 0x300100D, 0x3001013, 0x3001019, 0x300101F, 0x3001025,
+	0x300102B, 0x3001031, 0x3001037, 0x300103D, 0x3001043, 0x3002681, 0x3002684, 0x3002687, 0x300268A, 0x300268D, 0x3001049, 0x3001055, 0x3001061, 0x300106D, 0x3001079, 0x3002690,
+	0x3002693, 0x3002696, 0x3002699, 0x300269C, 0x300269F, 0x30026A2, 0x30026A5, 0x30026A8, 0x30026AB, 0x30026AE, 0x30026B1, 0x30026B4, 0x300108B, 0x30026D5, 0x3000F50, 0x3000FB0,
+	0x3002383, 0x30022EA, 0x30022ED, 0x30022F0, 0x30022F3, 0x30022F6, 0x30022F9, 0x30022FC, 0x30022FF, 0x3002302, 0x3002305, 0x3002308, 0x300230B, 0x300230E, 0x3002311, 0x3002314,
+	0x3002317, 0x300231A, 0x300231D, 0x3002320, 0x3002323, 0x3002326, 0x3002329, 0x300232C, 0x300232F, 0x3002332, 0x3002335, 0x3002338, 0x300233B, 0x300233E, 0x3002341, 0x0,
+	0x0, 0x0, 0x3002344, 0x3002347, 0x300234A, 0x300234D, 0x3002350, 0x3002353, 0x0, 0x0, 0x3002356, 0x3002359, 0x300235C, 0x300235F, 0x3002362, 0x3002365,
+	0x0, 0x0, 0x3002368, 0x300236B, 0x300236E, 0x3002371, 0x3002374, 0x3002377, 0x0, 0x0, 0x300237A, 0x300237D, 0x3002380, 0x0, 0x0, 0x0,
+	0x2003322, 0x2003324, 0x2003326, 0x3001D21, 0x2003328, 0x200332A, 0x300332C, 0x0, 0x300332F, 0x3000E6C, 0x3003332, 0x3000E71, 0x3003335, 0x3003338, 0x300333B, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001633, 0x0, 0x800163B, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001643, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800164B, 0x8001653,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800165B, 0x8001663, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800166B, 0x8001673, 0x0, 0x800167B, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001683, 0x800168B, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8001693, 0x800169B,
+	0xC00333E, 0xC0016AF, 0xC0016BB, 0xC0016C7, 0xC0016D3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80016DF, 0x80016E7, 0xC0016EF, 0xC0016FB, 0xC001707,
+	0xC001713, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E, 0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4,
+	0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132,
+	0x10006FF, 0x100002D, 0x1000030, 0x1000751, 0x1001EFC, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x100004E, 0x1000636,
+	0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x0, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E, 0x1000754, 0x1002068, 0x100016B,
+	0x100004B, 0x10001D1, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B,
+	0x100007E, 0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1000000, 0x0, 0x1000012, 0x10000C9,
+	0x0, 0x0, 0x10000ED, 0x0, 0x0, 0x1000126, 0x100012C, 0x0, 0x0, 0x100002D, 0x1000030, 0x1000751, 0x1001EFC, 0x0, 0x100017A, 0x1000192,
+	0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x0, 0x100069A, 0x0, 0x1000108, 0x100006F, 0x1000129,
+	0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x0, 0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4,
+	0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030, 0x1000751,
+	0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1000000, 0x1000633, 0x0, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x0, 0x0, 0x1000126, 0x100012C, 0x1000132,
+	0x10006FF, 0x100002D, 0x1000030, 0x1000751, 0x1001EFC, 0x0, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x0, 0x100004E, 0x1000636,
+	0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E, 0x1000754, 0x1002068, 0x100016B,
+	0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1000000, 0x1000633, 0x0, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x0,
+	0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x0, 0x1000030, 0x0, 0x0, 0x0, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B,
+	0x100004B, 0x0, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B,
+	0x100004B, 0x10001D1, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B,
+	0x100007E, 0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1000000, 0x1000633, 0x1000012, 0x10000C9,
+	0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x200334A, 0x200334C, 0x0, 0x0, 0x200032B, 0x200334E, 0x2001F07, 0x2003350, 0x2000331, 0x2003352, 0x2000335, 0x2001D95,
+	0x2000339, 0x2003354, 0x2003356, 0x2003358, 0x200335A, 0x200335C, 0x200033D, 0x2001F09, 0x2000E35, 0x2001D95, 0x2001D97, 0x200335E, 0x2000341, 0x2003360, 0x2003362, 0x2003364,
+	0x2000345, 0x3003366, 0x2000357, 0x2001D89, 0x2001E12, 0x2001E14, 0x200035B, 0x2003369, 0x200035F, 0x2001D8B, 0x2000349, 0x2001D91, 0x200336B, 0x2001D29, 0x200336D, 0x200336F,
+	0x200036D, 0x2001D8F, 0x2000E17, 0x2001D93, 0x2003371, 0x2003373, 0x2000367, 0x2001D8D, 0x2001E16, 0x2003375, 0x2000375, 0x3003377, 0x200035B, 0x2001D8B, 0x2001D91, 0x2001D8D,
+	0x2000E17, 0x2001D8F, 0x200032B, 0x200334E, 0x2001F07, 0x2003350, 0x2000331, 0x2003352, 0x2000335, 0x2001D95, 0x2000339, 0x2003354, 0x2003356, 0x2003358, 0x200335A, 0x200335C,
+	0x200033D, 0x2001F09, 0x2000E35, 0x2001D95, 0x2001D97, 0x200335E, 0x2000341, 0x2003360, 0x2003362, 0x2003364, 0x2000345, 0x3003366, 0x2000357, 0x2001D89, 0x2001E12, 0x2001E14,
+	0x2001E16, 0x2003375, 0x2000375, 0x3003377, 0x200035B, 0x2001D8B, 0x2001D91, 0x2001D8D, 0x2000E17, 0x2001D8F, 0x200337A, 0x200337C, 0x0, 0x0, 0x1001ED6, 0x1001D2E,
+	0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x1001ED6, 0x1001D2E, 0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9,
+	0x1001EDA, 0x1001EDB, 0x1001ED6, 0x1001D2E, 0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x1001ED6, 0x1001D2E, 0x1001D24, 0x1001D25,
+	0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB, 0x1001ED6, 0x1001D2E, 0x1001D24, 0x1001D25, 0x1001D33, 0x1001ED7, 0x1001ED8, 0x1001ED9, 0x1001EDA, 0x1001EDB,
+	0x2000451, 0x2002DA4, 0x2002D90, 0x2003248, 0x0, 0x2000459, 0x2002F14, 0x2002D96, 0x2002E24, 0x2000461, 0x2002E68, 0x2002E7A, 0x2002D9C, 0x2002EAC, 0x2002DFC, 0x2002E30,
+	0x2002E40, 0x2002E0C, 0x2002E58, 0x2002EE4, 0x2002F8C, 0x2002DBC, 0x2002DD4, 0x2002DAE, 0x2002EE0, 0x2002E14, 0x2002E2C, 0x2002E38, 0x200337E, 0x2002D4A, 0x2003380, 0x2003382,
+	0x0, 0x2002DA4, 0x2002D90, 0x0, 0x2002EC4, 0x0, 0x0, 0x2002D96, 0x0, 0x2000461, 0x2002E68, 0x2002E7A, 0x2002D9C, 0x2002EAC, 0x2002DFC, 0x2002E30,
+	0x2002E40, 0x2002E0C, 0x2002E58, 0x0, 0x2002F8C, 0x2002DBC, 0x2002DD4, 0x2002DAE, 0x0, 0x2002E14, 0x0, 0x2002E38, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x2002D90, 0x0, 0x0, 0x0, 0x0, 0x2002D96, 0x0, 0x2000461, 0x0, 0x2002E7A, 0x0, 0x2002EAC, 0x2002DFC, 0x2002E30,
+	0x0, 0x2002E0C, 0x2002E58, 0x0, 0x2002F8C, 0x0, 0x0, 0x2002DAE, 0x0, 0x2002E14, 0x0, 0x2002E38, 0x0, 0x2002D4A, 0x0, 0x2003382,
+	0x0, 0x2002DA4, 0x2002D90, 0x0, 0x2002EC4, 0x0, 0x0, 0x2002D96, 0x2002E24, 0x2000461, 0x2002E68, 0x0, 0x2002D9C, 0x2002EAC, 0x2002DFC, 0x2002E30,
+	0x2002E40, 0x2002E0C, 0x2002E58, 0x0, 0x2002F8C, 0x2002DBC, 0x2002DD4, 0x2002DAE, 0x0, 0x2002E14, 0x2002E2C, 0x2002E38, 0x200337E, 0x0, 0x2003380, 0x0,
+	0x2000451, 0x2002DA4, 0x2002D90, 0x2003248, 0x2002EC4, 0x2000459, 0x2002F14, 0x2002D96, 0x2002E24, 0x2000461, 0x0, 0x2002E7A, 0x2002D9C, 0x2002EAC, 0x2002DFC, 0x2002E30,
+	0x2002E40, 0x2002E0C, 0x2002E58, 0x2002EE4, 0x2002F8C, 0x2002DBC, 0x2002DD4, 0x2002DAE, 0x2002EE0, 0x2002E14, 0x2002E2C, 0x2002E38, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x2002DA4, 0x2002D90, 0x2003248, 0x0, 0x2000459, 0x2002F14, 0x2002D96, 0x2002E24, 0x2000461, 0x0, 0x2002E7A, 0x2002D9C, 0x2002EAC, 0x2002DFC, 0x2002E30,
+	0x2002E40, 0x2002E0C, 0x2002E58, 0x2002EE4, 0x2002F8C, 0x2002DBC, 0x2002DD4, 0x2002DAE, 0x2002EE0, 0x2002E14, 0x2002E2C, 0x2002E38, 0x0, 0x0, 0x0, 0x0,
+	0x2002017, 0x2003384, 0x2003386, 0x2003388, 0x200338A, 0x200338C, 0x200338E, 0x2003390, 0x2003392, 0x2003394, 0x2003396, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003398, 0x300339B, 0x300339E, 0x30033A1, 0x30033A4, 0x30033A7, 0x30033AA, 0x30033AD, 0x30033B0, 0x30033B3, 0x30033B6, 0x30033B9, 0x30033BC, 0x30033BF, 0x30033C2, 0x30033C5,
+	0x30033C8, 0x30033CB, 0x30033CE, 0x30033D1, 0x30033D4, 0x30033D7, 0x30033DA, 0x30033DD, 0x30033E0, 0x30033E3, 0x70033E6, 0x1000012, 0x1000168, 0x20033ED, 0x20033EF, 0x0,
+	0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030, 0x1000751,
+	0x1001EFC, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x20033F1, 0x2002BE9, 0x20033F3, 0x20033F5, 0x30033F7, 0x20033FA,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20033FC, 0x20033FE, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2003400, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6003402, 0x6003408, 0x300100D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300213E, 0x300340E, 0x3003411, 0x600103D, 0x30020A5, 0x300180E, 0x3003414, 0x300241C, 0x3003417, 0x300341A, 0x300341D, 0x30012D7, 0x3003420, 0x3003423, 0x3001758, 0x3003426,
+	0x3003429, 0x300342C, 0x30021A7, 0x300342F, 0x3003432, 0x3003435, 0x3003438, 0x300343B, 0x300343E, 0x3002093, 0x3002404, 0x3003441, 0x3002611, 0x300240D, 0x3002614, 0x3003444,
+	0x300223A, 0x3003447, 0x300344A, 0x300344D, 0x3003450, 0x3003453, 0x300255A, 0x300215C, 0x3003456, 0x300177E, 0x3003459, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x900345C, 0x9003465, 0x900346E, 0x9003477, 0x9003480, 0x9003489, 0x9003492, 0x900349B, 0x90034A4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30034AD, 0x30034B0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300171F, 0x3001722, 0x3001725, 0x4001728, 0x300172C, 0x3001403, 0x300172F, 0x3001732, 0x3001735, 0x3001738, 0x3001406, 0x300173B, 0x300173E, 0x4001741, 0x3001409, 0x3001745,
+	0x3001748, 0x300174B, 0x400174E, 0x3001752, 0x3001755, 0x3001758, 0x400175B, 0x300175F, 0x3001762, 0x3001765, 0x3001768, 0x30014B8, 0x400176B, 0x300176F, 0x3001772, 0x3001775,
+	0x3001778, 0x300177B, 0x300177E, 0x3001781, 0x3001784, 0x30014C7, 0x300140C, 0x300140F, 0x30014CA, 0x3001787, 0x300178A, 0x30011CC, 0x300178D, 0x3001412, 0x3001790, 0x3001793,
+	0x3001796, 0x3001799, 0x3001799, 0x3001799, 0x400179C, 0x30017A0, 0x30017A3, 0x30017A6, 0x40017A9, 0x30017AD, 0x30017B0, 0x30017B3, 0x30017B6, 0x30017B9, 0x30017BC, 0x30017BF,
+	0x30017C2, 0x30017C5, 0x30017C8, 0x30017CB, 0x30017CE, 0x30017D1, 0x30017D1, 0x30014D0, 0x30017D4, 0x30017D7, 0x30017DA, 0x30017DD, 0x3001418, 0x30017E0, 0x30017E3, 0x30017E6,
+	0x3001397, 0x30017E9, 0x30017EC, 0x30017EF, 0x30017F2, 0x30017F5, 0x30017F8, 0x30017FB, 0x30017FE, 0x4001801, 0x3001805, 0x3001808, 0x300180B, 0x300180E, 0x3001811, 0x3001814,
+	0x4001817, 0x400181B, 0x300181F, 0x3001822, 0x3001825, 0x3001828, 0x300182B, 0x300182E, 0x3001831, 0x3001834, 0x3001837, 0x3001837, 0x400183A, 0x300183E, 0x3001841, 0x30011C0,
+	0x3001844, 0x4001847, 0x300184B, 0x300184E, 0x3001851, 0x3001854, 0x3001857, 0x300185A, 0x3001427, 0x300185D, 0x3001860, 0x4001863, 0x3001867, 0x400186A, 0x300186E, 0x3001871,
+	0x3001874, 0x3001877, 0x300187A, 0x300187D, 0x3001880, 0x3001883, 0x3001886, 0x3001889, 0x300188C, 0x400188F, 0x3001893, 0x3001896, 0x3001899, 0x300189C, 0x300111E, 0x400189F,
+	0x30018A3, 0x40018A6, 0x40018A6, 0x30018AA, 0x30018AD, 0x30018AD, 0x30018B0, 0x40018B3, 0x40018B7, 0x30018BB, 0x30018BE, 0x30018C1, 0x30018C4, 0x30018C7, 0x30018CA, 0x30018CD,
+	0x30018D0, 0x30018D3, 0x30018D6, 0x300142A, 0x40018D9, 0x30018DD, 0x30018E0, 0x30018E3, 0x30014F4, 0x30018E3, 0x30018E6, 0x3001430, 0x30018E9, 0x30018EC, 0x30018EF, 0x30018F2,
+	0x3001433, 0x30010CD, 0x30018F5, 0x30018F8, 0x30018FB, 0x30018FE, 0x3001901, 0x3001904, 0x4001907, 0x300190B, 0x300190E, 0x3001911, 0x3001914, 0x3001917, 0x400191A, 0x300191E,
+	0x3001921, 0x3001924, 0x3001927, 0x300192A, 0x300192D, 0x3001930, 0x3001933, 0x3001936, 0x3001436, 0x3001939, 0x400193C, 0x3001940, 0x3001943, 0x3001946, 0x3001949, 0x300143C,
+	0x300194C, 0x300194F, 0x3001952, 0x3001955, 0x3001958, 0x300195B, 0x300195E, 0x3001961, 0x3001121, 0x300150C, 0x3001964, 0x3001967, 0x300196A, 0x400196D, 0x3001971, 0x3001974,
+	0x3001977, 0x300197A, 0x300143F, 0x400197D, 0x3001981, 0x3001984, 0x3001987, 0x3001590, 0x300198A, 0x300198D, 0x3001990, 0x3001993, 0x4001996, 0x300199A, 0x300199D, 0x30019A0,
+	0x40019A3, 0x30019A7, 0x30019AA, 0x30019AD, 0x30019B0, 0x30011F3, 0x30019B3, 0x40019B6, 0x40019BA, 0x40019BE, 0x30019C2, 0x40019C5, 0x30019C9, 0x30019CC, 0x30019CF, 0x30019D2,
+	0x30019D5, 0x3001442, 0x30012F8, 0x30019D8, 0x30019DB, 0x30019DE, 0x40019E1, 0x30019E5, 0x30019E8, 0x30019EB, 0x30019EE, 0x3001518, 0x30019F1, 0x40019F4, 0x30019F8, 0x30019FB,
+	0x40019FE, 0x4001A02, 0x3001A06, 0x3001A09, 0x300151B, 0x3001A0C, 0x3001A0F, 0x3001A12, 0x3001A15, 0x3001A18, 0x3001A1B, 0x4001A1E, 0x3001A22, 0x4001A25, 0x3001A29, 0x4001A2C,
+	0x3001A30, 0x3001521, 0x3001A33, 0x4001A36, 0x3001A3A, 0x3001A3D, 0x4001A40, 0x4001A44, 0x3001A48, 0x3001A4B, 0x3001A4E, 0x3001A51, 0x3001A54, 0x3001A54, 0x3001A57, 0x3001A5A,
+	0x3001527, 0x3001A5D, 0x3001A60, 0x3001A63, 0x3001A66, 0x4001A69, 0x3001A6D, 0x4001A70, 0x30011C9, 0x4001A74, 0x3001A78, 0x4001A7B, 0x4001A7F, 0x4001A83, 0x3001A87, 0x3001A8A,
+	0x3001539, 0x4001A8D, 0x4001A91, 0x4001A95, 0x4001A99, 0x3001A9D, 0x3001AA0, 0x3001AA0, 0x300153C, 0x3001596, 0x3001AA3, 0x3001AA6, 0x3001AA9, 0x4001AAC, 0x3001AB0, 0x3001157,
+	0x3001542, 0x3001AB3, 0x4001AB6, 0x3001463, 0x4001ABA, 0x4001ABE, 0x30013D9, 0x3001AC2, 0x3001AC5, 0x300146F, 0x3001AC8, 0x3001ACB, 0x4001ACE, 0x4001AD2, 0x4001AD2, 0x3001AD6,
+	0x3001AD9, 0x4001ADC, 0x3001AE0, 0x3001AE3, 0x3001AE6, 0x4001AE9, 0x3001AED, 0x3001AF0, 0x3001AF3, 0x3001AF6, 0x3001AF9, 0x4001AFC, 0x3001B00, 0x3001B03, 0x3001B06, 0x3001B09,
+	0x3001B0C, 0x3001B0F, 0x4001B12, 0x4001B16, 0x3001B1A, 0x4001B1D, 0x3001B21, 0x4001B24, 0x3001B28, 0x3001B2B, 0x3001481, 0x4001B2E, 0x4001B32, 0x3001B36, 0x4001B39, 0x3001B3D,
+	0x4001B40, 0x3001B44, 0x3001B47, 0x3001B4A, 0x3001B4D, 0x3001B50, 0x3001B53, 0x4001B56, 0x4001B5A, 0x4001B5E, 0x4001B62, 0x30018AA, 0x3001B66, 0x3001B69, 0x3001B6C, 0x3001B6F,
+	0x3001B72, 0x3001B75, 0x3001B78, 0x3001B7B, 0x3001B7E, 0x3001B81, 0x3001B84, 0x4001B87, 0x30011FF, 0x3001B8B, 0x3001B8E, 0x3001B91, 0x3001B94, 0x3001B97, 0x3001B9A, 0x300148A,
+	0x3001B9D, 0x3001BA0, 0x3001BA3, 0x3001BA6, 0x4001BA9, 0x4001BAD, 0x4001BB1, 0x3001BB5, 0x3001BB8, 0x3001BBB, 0x3001BBE, 0x4001BC1, 0x3001BC5, 0x4001BC8, 0x3001BCC, 0x3001BCF,
+	0x4001BD2, 0x4001BD6, 0x3001BDA, 0x3001BDD, 0x3001148, 0x3001BE0, 0x3001BE3, 0x3001BE6, 0x3001BE9, 0x3001BEC, 0x3001BEF, 0x3001557, 0x3001BF2, 0x3001BF5, 0x3001BF8, 0x3001BFB,
+	0x3001BFE, 0x3001C01, 0x3001C04, 0x3001C07, 0x3001C0A, 0x4001C0D, 0x3001C11, 0x3001C14, 0x3001C17, 0x3001C1A, 0x3001C1D, 0x4001C20, 0x4001C24, 0x3001C28, 0x3001C2B, 0x3001C2E,
+	0x3001566, 0x3001569, 0x3001C31, 0x4001C34, 0x3001C38, 0x3001C3B, 0x3001C3E, 0x3001C41, 0x4001C44, 0x4001C48, 0x3001C4C, 0x3001C4F, 0x3001C52, 0x4001C55, 0x3001C59, 0x300156C,
+	0x4001C5C, 0x4001C60, 0x3001C64, 0x3001C67, 0x3001C6A, 0x4001C6D, 0x3001C71, 0x3001C74, 0x3001C77, 0x3001C7A, 0x3001C7D, 0x3001C80, 0x3001C83, 0x4001C86, 0x3001C8A, 0x3001C8D,
+	0x3001C90, 0x4001C93, 0x3001C97, 0x3001C9A, 0x3001C9D, 0x3001CA0, 0x4001CA3, 0x4001CA7, 0x3001CAB, 0x3001CAE, 0x3001CB1, 0x4001CB4, 0x3001CB8, 0x4001CBB, 0x300157E, 0x300157E,
+	0x3001CBF, 0x4001CC2, 0x3001CC6, 0x3001CC9, 0x3001CCC, 0x3001CCF, 0x3001CD2, 0x3001CD5, 0x3001CD8, 0x4001CDB, 0x3001581, 0x3001CDF, 0x3001CE2, 0x3001CE5, 0x3001CE8, 0x3001CEB,
+	0x4001CEE, 0x3001CF2, 0x4001CF5, 0x4001CF9, 0x4001CFD, 0x3001D01, 0x3001D04, 0x3001D07, 0x3001D0A, 0x3001D0D, 0x3001D10, 0x3001D13, 0x3001D16, 0x4001D19, 0x0, 0x0,
+};
+const uint32_t* NFKDDataPtr = NFKDData;
+
+const uint32_t UppercaseIndex1[272] = {
+	0, 128, 256, 45, 45, 45, 45, 45, 45, 45, 384, 45, 45, 45, 45, 512,
+	640, 768, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+};
+const uint32_t* UppercaseIndex1Ptr = UppercaseIndex1;
+
+const uint32_t UppercaseIndex2[896] = {
+	0x0, 0x0, 0x0, 0x20, 0x0, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0, 0x100, 0x120, 0x140, 0x160, 0x180,
+	0x1A0, 0x1C0, 0x1E0, 0x200, 0x220, 0x0, 0x0, 0x0, 0x0, 0x0, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
+	0x0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0x400, 0x0, 0x420, 0x440, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x460, 0x0, 0x0, 0x0, 0x0,
+	0x480, 0x4A0, 0x4C0, 0x4E0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5A0, 0x5C0, 0x5E0, 0x600, 0x620, 0x640, 0x660,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x680, 0x6A0, 0x6C0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6E0, 0x700, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x720, 0x740, 0x760, 0x780, 0x7A0, 0x7C0, 0x7E0, 0x800, 0x820, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x840, 0x860, 0x880, 0x0, 0x0, 0x0, 0x0, 0x8A0, 0x8C0, 0x8E0, 0x900, 0x920, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x940, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x960, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x980, 0x9A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+};
+const uint32_t* UppercaseIndex2Ptr = UppercaseIndex2;
+
+const uint32_t UppercaseData[2528] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030,
+	0x1000751, 0x1001EFC, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x2003358, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20033F5,
+	0x20034B3, 0x20034B5, 0x20034B7, 0x20034B9, 0x20034BB, 0x20034BD, 0x2000243, 0x20034BF, 0x20034C1, 0x20034C3, 0x20034C5, 0x20034C7, 0x20034C9, 0x20034CB, 0x20034CD, 0x20034CF,
+	0x20034D1, 0x20034D3, 0x20034D5, 0x20034D7, 0x20034D9, 0x20034DB, 0x20034DD, 0x0, 0x2000290, 0x20034DF, 0x20034E1, 0x20034E3, 0x20034E5, 0x20034E7, 0x20034E9, 0x20034EB,
+	0x0, 0x20034ED, 0x0, 0x20034EF, 0x0, 0x20034F1, 0x0, 0x20034F3, 0x0, 0x20034F5, 0x0, 0x20034F7, 0x0, 0x20034F9, 0x0, 0x20034FB,
+	0x0, 0x20034FD, 0x0, 0x20034FF, 0x0, 0x2003501, 0x0, 0x2003503, 0x0, 0x2003505, 0x0, 0x2003507, 0x0, 0x2003509, 0x0, 0x200350B,
+	0x0, 0x200350D, 0x0, 0x200350F, 0x0, 0x2003511, 0x0, 0x2002CE3, 0x0, 0x2003513, 0x0, 0x2003515, 0x0, 0x2003517, 0x0, 0x2003519,
+	0x0, 0x1000021, 0x0, 0x200351B, 0x0, 0x200351D, 0x0, 0x200351F, 0x0, 0x0, 0x2003521, 0x0, 0x2003523, 0x0, 0x2003525, 0x0,
+	0x2003527, 0x0, 0x2003529, 0x0, 0x200352B, 0x0, 0x200352D, 0x0, 0x200352F, 0x3003531, 0x0, 0x2003534, 0x0, 0x2003536, 0x0, 0x2003538,
+	0x0, 0x200353A, 0x0, 0x200353C, 0x0, 0x200353E, 0x0, 0x2003540, 0x0, 0x2003542, 0x0, 0x2003544, 0x0, 0x2003546, 0x0, 0x2003548,
+	0x0, 0x200354A, 0x0, 0x200354C, 0x0, 0x200354E, 0x0, 0x2003550, 0x0, 0x2003552, 0x0, 0x2003554, 0x0, 0x2003556, 0x0, 0x2003558,
+	0x0, 0x200355A, 0x0, 0x200355C, 0x0, 0x200355E, 0x0, 0x2003560, 0x0, 0x0, 0x2003562, 0x0, 0x2003564, 0x0, 0x2003566, 0x100017A,
+	0x2003568, 0x0, 0x0, 0x200356A, 0x0, 0x200356C, 0x0, 0x0, 0x200356E, 0x0, 0x0, 0x0, 0x2003570, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x2003572, 0x0, 0x0, 0x2003574, 0x0, 0x0, 0x0, 0x2003576, 0x2003578, 0x0, 0x0, 0x0, 0x200357A, 0x0,
+	0x0, 0x200357C, 0x0, 0x200357E, 0x0, 0x2003580, 0x0, 0x0, 0x2003582, 0x0, 0x0, 0x0, 0x0, 0x2003584, 0x0, 0x0,
+	0x2003586, 0x0, 0x0, 0x0, 0x2003588, 0x0, 0x200358A, 0x0, 0x0, 0x200358C, 0x0, 0x0, 0x0, 0x200358E, 0x0, 0x2003590,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x2003592, 0x2003592, 0x0, 0x2003594, 0x2003594, 0x0, 0x2003596, 0x2003596, 0x0, 0x2003598, 0x0,
+	0x200359A, 0x0, 0x200359C, 0x0, 0x200359E, 0x0, 0x20035A0, 0x0, 0x20035A2, 0x0, 0x20035A4, 0x0, 0x20035A6, 0x2001DEF, 0x0, 0x20035A8,
+	0x0, 0x20035AA, 0x0, 0x20035AC, 0x0, 0x20035AE, 0x0, 0x20035B0, 0x0, 0x20035B2, 0x0, 0x20035B4, 0x0, 0x20035B6, 0x0, 0x20035B8,
+	0x30035BA, 0x0, 0x20035BD, 0x20035BD, 0x0, 0x20035BF, 0x0, 0x0, 0x0, 0x20035C1, 0x0, 0x20035C3, 0x0, 0x20035C5, 0x0, 0x20035C7,
+	0x0, 0x20035C9, 0x0, 0x20035CB, 0x0, 0x20035CD, 0x0, 0x20035CF, 0x0, 0x20035D1, 0x0, 0x20035D3, 0x0, 0x20035D5, 0x0, 0x20035D7,
+	0x0, 0x20035D9, 0x0, 0x20035DB, 0x0, 0x20035DD, 0x0, 0x20035DF, 0x0, 0x20035E1, 0x0, 0x20035E3, 0x0, 0x20035E5, 0x0, 0x20035E7,
+	0x0, 0x0, 0x0, 0x2001DF1, 0x0, 0x20035E9, 0x0, 0x20035EB, 0x0, 0x20035ED, 0x0, 0x20035EF, 0x0, 0x20035F1, 0x0, 0x20035F3,
+	0x0, 0x20035F5, 0x0, 0x20035F7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20035F9, 0x0, 0x0, 0x30035FB,
+	0x30035FE, 0x0, 0x2003601, 0x0, 0x0, 0x0, 0x0, 0x2003603, 0x0, 0x2003605, 0x0, 0x2003607, 0x0, 0x2003609, 0x0, 0x200360B,
+	0x300360D, 0x3003610, 0x3003613, 0x2003616, 0x2003618, 0x0, 0x200361A, 0x200361C, 0x0, 0x200361E, 0x0, 0x2001EF3, 0x3003620, 0x0, 0x0, 0x0,
+	0x2003623, 0x3003625, 0x0, 0x2003628, 0x0, 0x300362A, 0x300362D, 0x0, 0x2003630, 0x2003632, 0x0, 0x3003634, 0x3003637, 0x0, 0x0, 0x200363A,
+	0x0, 0x300363C, 0x200363F, 0x0, 0x0, 0x2003641, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003643, 0x0, 0x0,
+	0x2003646, 0x0, 0x0, 0x2003648, 0x0, 0x0, 0x0, 0x300364A, 0x200364D, 0x200364F, 0x2003651, 0x2003653, 0x2003655, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x2000267, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003657, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x2000339, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x200365A, 0x0, 0x200365C, 0x0, 0x0, 0x0, 0x200365E, 0x0, 0x0, 0x0, 0x2003660, 0x2003662, 0x2003664, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6003666, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200366C, 0x200366E, 0x2003670, 0x2003672,
+	0x6003674, 0x200032B, 0x200334E, 0x2001F07, 0x2003350, 0x2000331, 0x2003352, 0x2000335, 0x2001D95, 0x2000339, 0x2003354, 0x2003356, 0x2003358, 0x200335A, 0x200335C, 0x200033D,
+	0x2001F09, 0x2000E35, 0x2001D97, 0x2001D97, 0x200335E, 0x2000341, 0x2003360, 0x2003362, 0x2003364, 0x2000345, 0x200367A, 0x200367C, 0x200367E, 0x2003680, 0x2003682, 0x0,
+	0x200334E, 0x2001D95, 0x0, 0x0, 0x0, 0x2003360, 0x2001F09, 0x2003684, 0x0, 0x2003686, 0x0, 0x2003688, 0x0, 0x200337A, 0x0, 0x200368A,
+	0x0, 0x200368C, 0x0, 0x200368E, 0x0, 0x2003690, 0x0, 0x2003692, 0x0, 0x2003694, 0x0, 0x2003696, 0x0, 0x2003698, 0x0, 0x200369A,
+	0x2003354, 0x2000E35, 0x200369C, 0x200369E, 0x0, 0x2000331, 0x0, 0x0, 0x20036A0, 0x0, 0x0, 0x20036A2, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x20003D1, 0x20036A4, 0x20036A6, 0x2000389, 0x20036A8, 0x2000381, 0x20003C9, 0x20003F9, 0x2000395, 0x20036AA, 0x2000391, 0x20036AC, 0x20036AE, 0x20036B0, 0x2000411, 0x20036B2,
+	0x20036B4, 0x20036B6, 0x20036B8, 0x2000399, 0x20036BA, 0x20036BC, 0x20036BE, 0x2000441, 0x20036C0, 0x20036C2, 0x20036C4, 0x2000449, 0x20036C6, 0x2000421, 0x20036C8, 0x20036CA,
+	0x20036CC, 0x20036CE, 0x20036D0, 0x20036D2, 0x20036D4, 0x20036D6, 0x200038D, 0x20036D8, 0x20036DA, 0x20036DC, 0x20036DE, 0x20036E0, 0x20036E2, 0x20036E4, 0x20036E6, 0x20036E8,
+	0x0, 0x20036EA, 0x0, 0x20036EC, 0x0, 0x20036EE, 0x0, 0x20036F0, 0x0, 0x20036F2, 0x0, 0x20036F4, 0x0, 0x20036F6, 0x0, 0x20036F8,
+	0x0, 0x20036FA, 0x0, 0x20036FC, 0x0, 0x20003C1, 0x0, 0x20036FE, 0x0, 0x2003700, 0x0, 0x2003702, 0x0, 0x2003704, 0x0, 0x2003706,
+	0x0, 0x2003708, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200370A, 0x0, 0x200370C, 0x0, 0x200370E,
+	0x0, 0x2003710, 0x0, 0x2003712, 0x0, 0x2003714, 0x0, 0x2003716, 0x0, 0x2003718, 0x0, 0x200371A, 0x0, 0x200371C, 0x0, 0x200371E,
+	0x0, 0x2003720, 0x0, 0x2003722, 0x0, 0x2003724, 0x0, 0x2003726, 0x0, 0x2003728, 0x0, 0x200372A, 0x0, 0x200372C, 0x0, 0x200372E,
+	0x0, 0x2003730, 0x0, 0x2003732, 0x0, 0x2003734, 0x0, 0x2003736, 0x0, 0x2003738, 0x0, 0x200373A, 0x0, 0x200373C, 0x0, 0x200373E,
+	0x0, 0x0, 0x2003740, 0x0, 0x2003742, 0x0, 0x2003744, 0x0, 0x2003746, 0x0, 0x2003748, 0x0, 0x200374A, 0x0, 0x200374C, 0x200374E,
+	0x0, 0x2003750, 0x0, 0x2003752, 0x0, 0x2003754, 0x0, 0x2003756, 0x0, 0x20003E9, 0x0, 0x2003758, 0x0, 0x200375A, 0x0, 0x200375C,
+	0x0, 0x200375E, 0x0, 0x2003760, 0x0, 0x2003762, 0x0, 0x2003764, 0x0, 0x2000419, 0x0, 0x2003766, 0x0, 0x2003768, 0x0, 0x200376A,
+	0x0, 0x200376C, 0x0, 0x200376E, 0x0, 0x2003770, 0x0, 0x2003772, 0x0, 0x2003774, 0x0, 0x2003776, 0x0, 0x2003778, 0x0, 0x200377A,
+	0x0, 0x200377C, 0x0, 0x200377E, 0x0, 0x2003780, 0x0, 0x2003782, 0x0, 0x2003784, 0x0, 0x2003786, 0x0, 0x2003788, 0x0, 0x200378A,
+	0x0, 0x200378C, 0x0, 0x200378E, 0x0, 0x2003790, 0x0, 0x2003792, 0x0, 0x2003794, 0x0, 0x2003796, 0x0, 0x2003798, 0x0, 0x200379A,
+	0x0, 0x200379C, 0x0, 0x200379E, 0x0, 0x20037A0, 0x0, 0x20037A2, 0x0, 0x20037A4, 0x0, 0x20037A6, 0x0, 0x20037A8, 0x0, 0x20037AA,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x20037AC, 0x20037AE, 0x20037B0, 0x20037B2, 0x20037B4, 0x20037B6, 0x20037B8, 0x20037BA, 0x20037BC, 0x20037BE, 0x20037C0, 0x20037C2, 0x20037C4, 0x20037C6, 0x20037C8,
+	0x20037CA, 0x20037CC, 0x20037CE, 0x20037D0, 0x20037D2, 0x20037D4, 0x20037D6, 0x20037D8, 0x20037DA, 0x20037DC, 0x20037DE, 0x20037E0, 0x20037E2, 0x20037E4, 0x20037E6, 0x20037E8,
+	0x20037EA, 0x20037EC, 0x20037EE, 0x20037F0, 0x20037F2, 0x20037F4, 0x20037F6, 0x40037F8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30037FC, 0x0, 0x0, 0x0, 0x30037FF, 0x0, 0x0,
+	0x0, 0x3003802, 0x0, 0x3003805, 0x0, 0x3003808, 0x0, 0x300380B, 0x0, 0x300380E, 0x0, 0x3003811, 0x0, 0x3003814, 0x0, 0x3003817,
+	0x0, 0x300381A, 0x0, 0x300381D, 0x0, 0x3003820, 0x0, 0x3003823, 0x0, 0x3003826, 0x0, 0x3003829, 0x0, 0x300382C, 0x0, 0x300382F,
+	0x0, 0x3003832, 0x0, 0x3003835, 0x0, 0x3003838, 0x0, 0x300383B, 0x0, 0x300383E, 0x0, 0x3003841, 0x0, 0x3003844, 0x0, 0x3003847,
+	0x0, 0x300384A, 0x0, 0x300384D, 0x0, 0x3003850, 0x0, 0x3003853, 0x0, 0x3003856, 0x0, 0x3003859, 0x0, 0x300385C, 0x0, 0x300385F,
+	0x0, 0x3003862, 0x0, 0x3003865, 0x0, 0x3003868, 0x0, 0x300386B, 0x0, 0x300386E, 0x0, 0x3003871, 0x0, 0x3003874, 0x0, 0x3003877,
+	0x0, 0x300387A, 0x0, 0x300387D, 0x0, 0x3003880, 0x0, 0x3003883, 0x0, 0x3003886, 0x0, 0x3003889, 0x0, 0x300388C, 0x0, 0x300388F,
+	0x0, 0x3003892, 0x0, 0x3003895, 0x0, 0x3003898, 0x0, 0x300389B, 0x0, 0x300389E, 0x0, 0x30038A1, 0x0, 0x30038A4, 0x0, 0x30038A7,
+	0x0, 0x30038AA, 0x0, 0x30038AD, 0x0, 0x30038B0, 0x0, 0x30038B3, 0x0, 0x30038B6, 0x0, 0x30038B9, 0x0, 0x30038BC, 0x0, 0x30038BF,
+	0x0, 0x30038C2, 0x0, 0x30038C5, 0x0, 0x30038C8, 0x0, 0x30038CB, 0x0, 0x30038CE, 0x0, 0x30038D1, 0x0, 0x30038D4, 0x0, 0x30038D7,
+	0x0, 0x30038DA, 0x0, 0x30038DD, 0x0, 0x30038E0, 0x30038E3, 0x30038E6, 0x30038E9, 0x30038EC, 0x30038EF, 0x3003892, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x30038F2, 0x0, 0x30038F5, 0x0, 0x30038F8, 0x0, 0x30038FB, 0x0, 0x30038FE, 0x0, 0x3003901, 0x0, 0x3003904, 0x0, 0x3003907,
+	0x0, 0x300390A, 0x0, 0x300390D, 0x0, 0x3003910, 0x0, 0x3003913, 0x0, 0x3003916, 0x0, 0x3003919, 0x0, 0x300391C, 0x0, 0x300391F,
+	0x0, 0x3003922, 0x0, 0x3003925, 0x0, 0x3003928, 0x0, 0x300392B, 0x0, 0x300392E, 0x0, 0x3003931, 0x0, 0x3003934, 0x0, 0x3003937,
+	0x0, 0x300393A, 0x0, 0x300393D, 0x0, 0x3003940, 0x0, 0x3003943, 0x0, 0x3003946, 0x0, 0x3003949, 0x0, 0x300394C, 0x0, 0x300394F,
+	0x0, 0x3003952, 0x0, 0x3003955, 0x0, 0x3003958, 0x0, 0x300395B, 0x0, 0x300395E, 0x0, 0x3003961, 0x0, 0x3003964, 0x0, 0x3003967,
+	0x0, 0x300396A, 0x0, 0x300396D, 0x0, 0x3003970, 0x0, 0x3003973, 0x0, 0x3003976, 0x0, 0x3003979, 0x0, 0x300397C, 0x0, 0x300397F,
+	0x3003982, 0x3003985, 0x3003988, 0x300398B, 0x300398E, 0x3003991, 0x3003994, 0x3003997, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300399A, 0x300399D, 0x30039A0, 0x30039A3, 0x30039A6, 0x30039A9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30039AC, 0x30039AF, 0x30039B2, 0x30039B5, 0x30039B8, 0x30039BB, 0x30039BE, 0x30039C1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30039C4, 0x30039C7, 0x30039CA, 0x30039CD, 0x30039D0, 0x30039D3, 0x30039D6, 0x30039D9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30039DC, 0x30039DF, 0x30039E2, 0x30039E5, 0x30039E8, 0x30039EB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x40039EE, 0x30039F2, 0x60039F5, 0x30039FB, 0x60039FE, 0x3003A04, 0x6003A07, 0x3003A0D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003A10, 0x3003A13, 0x3003A16, 0x3003A19, 0x3003A1C, 0x3003A1F, 0x3003A22, 0x3003A25, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003A28, 0x3003A2B, 0x3003A2E, 0x3003A31, 0x3003A34, 0x3003A37, 0x3003A3A, 0x3003A3D, 0x3003A40, 0x3003A43, 0x3003A46, 0x3003A49, 0x3003A4C, 0x3003A4F, 0x0, 0x0,
+	0x5003A52, 0x5003A57, 0x5003A5C, 0x5003A61, 0x5003A66, 0x5003A6B, 0x5003A70, 0x5003A75, 0x5003A52, 0x5003A57, 0x5003A5C, 0x5003A61, 0x5003A66, 0x5003A6B, 0x5003A70, 0x5003A75,
+	0x5003A7A, 0x5003A7F, 0x5003A84, 0x5003A89, 0x5003A8E, 0x5003A93, 0x5003A98, 0x5003A9D, 0x5003A7A, 0x5003A7F, 0x5003A84, 0x5003A89, 0x5003A8E, 0x5003A93, 0x5003A98, 0x5003A9D,
+	0x5003AA2, 0x5003AA7, 0x5003AAC, 0x5003AB1, 0x5003AB6, 0x5003ABB, 0x5003AC0, 0x5003AC5, 0x5003AA2, 0x5003AA7, 0x5003AAC, 0x5003AB1, 0x5003AB6, 0x5003ABB, 0x5003AC0, 0x5003AC5,
+	0x3003ACA, 0x3003ACD, 0x5003AD0, 0x4003AD5, 0x4003AD9, 0x0, 0x4003ADD, 0x6003AE1, 0x0, 0x0, 0x0, 0x0, 0x4003AD5, 0x0, 0x2000339, 0x0,
+	0x0, 0x0, 0x5003AE7, 0x4003AEC, 0x4003AF0, 0x0, 0x4003AF4, 0x6003AF8, 0x0, 0x0, 0x0, 0x0, 0x4003AEC, 0x0, 0x0, 0x0,
+	0x3003AFE, 0x3003B01, 0x6003B04, 0x6003666, 0x0, 0x0, 0x4003B0A, 0x6003B0E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003B14, 0x3003B17, 0x6003B1A, 0x6003674, 0x4003B20, 0x3003B24, 0x4003B27, 0x6003B2B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x5003B31, 0x4003B36, 0x4003B3A, 0x0, 0x4003B3E, 0x6003B42, 0x0, 0x0, 0x0, 0x0, 0x4003B36, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003B48, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003B4B, 0x3003B4E, 0x3003B51, 0x3003B54, 0x3003B57, 0x3003B5A, 0x3003B5D, 0x3003B60, 0x3003B63, 0x3003B66, 0x3003B69, 0x3003B6C, 0x3003B6F, 0x3003B72, 0x3003B75, 0x3003B78,
+	0x0, 0x0, 0x0, 0x0, 0x3003B7B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003B7E, 0x3003B81, 0x3003B84, 0x3003B87, 0x3003B8A, 0x3003B8D, 0x3003B90, 0x3003B93, 0x3003B96, 0x3003B99, 0x3003B9C, 0x3003B9F, 0x3003BA2, 0x3003BA5, 0x3003BA8, 0x3003BAB,
+	0x3003BAE, 0x3003BB1, 0x3003BB4, 0x3003BB7, 0x3003BBA, 0x3003BBD, 0x3003BC0, 0x3003BC3, 0x3003BC6, 0x3003BC9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003BCC, 0x3003BCF, 0x3003BD2, 0x3003BD5, 0x3003BD8, 0x3003BDB, 0x3003BDE, 0x3003BE1, 0x3003BE4, 0x3003BE7, 0x3003BEA, 0x3003BED, 0x3003BF0, 0x3003BF3, 0x3003BF6, 0x3003BF9,
+	0x3003BFC, 0x3003BFF, 0x3003C02, 0x3003C05, 0x3003C08, 0x3003C0B, 0x3003C0E, 0x3003C11, 0x3003C14, 0x3003C17, 0x3003C1A, 0x3003C1D, 0x3003C20, 0x3003C23, 0x3003C26, 0x3003C29,
+	0x3003C2C, 0x3003C2F, 0x3003C32, 0x3003C35, 0x3003C38, 0x3003C3B, 0x3003C3E, 0x3003C41, 0x3003C44, 0x3003C47, 0x3003C4A, 0x3003C4D, 0x3003C50, 0x3003C53, 0x3003C56, 0x0,
+	0x0, 0x3003C59, 0x0, 0x0, 0x0, 0x2003C5C, 0x2003C5E, 0x0, 0x3003C60, 0x0, 0x3003C63, 0x0, 0x3003C66, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3003C69, 0x0, 0x0, 0x3003C6C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003C6F, 0x0, 0x3003C72, 0x0, 0x3003C75, 0x0, 0x3003C78, 0x0, 0x3003C7B, 0x0, 0x3003C7E, 0x0, 0x3003C81, 0x0, 0x3003C84,
+	0x0, 0x3003C87, 0x0, 0x3003C8A, 0x0, 0x3003C8D, 0x0, 0x3003C90, 0x0, 0x3003C93, 0x0, 0x3003C96, 0x0, 0x3003C99, 0x0, 0x3003C9C,
+	0x0, 0x3003C9F, 0x0, 0x3003CA2, 0x0, 0x3003CA5, 0x0, 0x3003CA8, 0x0, 0x3003CAB, 0x0, 0x3003CAE, 0x0, 0x3003CB1, 0x0, 0x3003CB4,
+	0x0, 0x3003CB7, 0x0, 0x3003CBA, 0x0, 0x3003CBD, 0x0, 0x3003CC0, 0x0, 0x3003CC3, 0x0, 0x3003CC6, 0x0, 0x3003CC9, 0x0, 0x3003CCC,
+	0x0, 0x3003CCF, 0x0, 0x3003CD2, 0x0, 0x3003CD5, 0x0, 0x3003CD8, 0x0, 0x3003CDB, 0x0, 0x3003CDE, 0x0, 0x3003CE1, 0x0, 0x3003CE4,
+	0x0, 0x3003CE7, 0x0, 0x3003CEA, 0x0, 0x3003CED, 0x0, 0x3003CF0, 0x0, 0x3003CF3, 0x0, 0x3003CF6, 0x0, 0x3003CF9, 0x0, 0x3003CFC,
+	0x0, 0x3003CFF, 0x0, 0x3003D02, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003D05, 0x0, 0x3003D08, 0x0,
+	0x0, 0x0, 0x0, 0x3003D0B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003D0E, 0x3003D11, 0x3003D14, 0x3003D17, 0x3003D1A, 0x3003D1D, 0x3003D20, 0x3003D23, 0x3003D26, 0x3003D29, 0x3003D2C, 0x3003D2F, 0x3003D32, 0x3003D35, 0x3003D38, 0x3003D3B,
+	0x3003D3E, 0x3003D41, 0x3003D44, 0x3003D47, 0x3003D4A, 0x3003D4D, 0x3003D50, 0x3003D53, 0x3003D56, 0x3003D59, 0x3003D5C, 0x3003D5F, 0x3003D62, 0x3003D65, 0x3003D68, 0x3003D6B,
+	0x3003D6E, 0x3003D71, 0x3003D74, 0x3003D77, 0x3003D7A, 0x3003D7D, 0x0, 0x3003D80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003D83, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003D86, 0x0, 0x3003D89, 0x0, 0x3003D8C, 0x0, 0x3003D8F, 0x0, 0x3003D92, 0x0, 0x3003D95, 0x0, 0x3003D98, 0x0, 0x3003D9B,
+	0x0, 0x3003D9E, 0x0, 0x3003DA1, 0x0, 0x3003DA4, 0x0, 0x3003DA7, 0x0, 0x3003DAA, 0x0, 0x3003DAD, 0x0, 0x3003DB0, 0x0, 0x3003DB3,
+	0x0, 0x3003DB6, 0x0, 0x3003DB9, 0x0, 0x3003DBC, 0x0, 0x3003DBF, 0x0, 0x3003DC2, 0x0, 0x3003DC5, 0x0, 0x3003DC8, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003DCB, 0x0, 0x3003DCE, 0x0, 0x3003DD1, 0x0, 0x3003DD4, 0x0, 0x3003DD7, 0x0, 0x3003DDA, 0x0, 0x3003DDD, 0x0, 0x3003DE0,
+	0x0, 0x3003DE3, 0x0, 0x3003DE6, 0x0, 0x3003DE9, 0x0, 0x3003DEC, 0x0, 0x3003DEF, 0x0, 0x3003DF2, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3003DF5, 0x0, 0x3003DF8, 0x0, 0x3003DFB, 0x0, 0x3003DFE, 0x0, 0x3003E01, 0x0, 0x3003E04, 0x0, 0x3003E07,
+	0x0, 0x0, 0x0, 0x3003E0A, 0x0, 0x3003E0D, 0x0, 0x3003E10, 0x0, 0x3003E13, 0x0, 0x3003E16, 0x0, 0x3003E19, 0x0, 0x3003E1C,
+	0x0, 0x3003E1F, 0x0, 0x3003E22, 0x0, 0x3003E25, 0x0, 0x3003E28, 0x0, 0x3003E2B, 0x0, 0x3003E2E, 0x0, 0x3003E31, 0x0, 0x3003E34,
+	0x0, 0x3003E37, 0x0, 0x3003E3A, 0x0, 0x3003E3D, 0x0, 0x3003E40, 0x0, 0x3003E43, 0x0, 0x3003E46, 0x0, 0x3003E49, 0x0, 0x3003E4C,
+	0x0, 0x3003E4F, 0x0, 0x3003E52, 0x0, 0x3003E55, 0x0, 0x3003E58, 0x0, 0x3003E5B, 0x0, 0x3003E5E, 0x0, 0x3003E61, 0x0, 0x3003E64,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003E67, 0x0, 0x3003E6A, 0x0, 0x0, 0x3003E6D,
+	0x0, 0x3003E70, 0x0, 0x3003E73, 0x0, 0x3003E76, 0x0, 0x3003E79, 0x0, 0x0, 0x0, 0x0, 0x3003E7C, 0x0, 0x0, 0x0,
+	0x0, 0x3003E7F, 0x0, 0x3003E82, 0x0, 0x0, 0x0, 0x3003E85, 0x0, 0x3003E88, 0x0, 0x3003E8B, 0x0, 0x3003E8E, 0x0, 0x3003E91,
+	0x0, 0x3003E94, 0x0, 0x3003E97, 0x0, 0x3003E9A, 0x0, 0x3003E9D, 0x0, 0x3003EA0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2003EA3, 0x2003EA5, 0x2003EA7, 0x3003EA9, 0x3003EAC, 0x2003EAF, 0x2003EAF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x4003EB1, 0x4003EB5, 0x4003EB9, 0x4003EBD, 0x4003EC1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003EC5, 0x3003EC8, 0x3003ECB, 0x3003ECE, 0x3003ED1, 0x3003ED4, 0x3003ED7, 0x3003EDA, 0x3003EDD, 0x3003EE0, 0x3003EE3, 0x3003EE6, 0x3003EE9, 0x3003EEC, 0x3003EEF,
+	0x3003EF2, 0x3003EF5, 0x3003EF8, 0x3003EFB, 0x3003EFE, 0x3003F01, 0x3003F04, 0x3003F07, 0x3003F0A, 0x3003F0D, 0x3003F10, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4003F13, 0x4003F17, 0x4003F1B, 0x4003F1F, 0x4003F23, 0x4003F27, 0x4003F2B, 0x4003F2F,
+	0x4003F33, 0x4003F37, 0x4003F3B, 0x4003F3F, 0x4003F43, 0x4003F47, 0x4003F4B, 0x4003F4F, 0x4003F53, 0x4003F57, 0x4003F5B, 0x4003F5F, 0x4003F63, 0x4003F67, 0x4003F6B, 0x4003F6F,
+	0x4003F73, 0x4003F77, 0x4003F7B, 0x4003F7F, 0x4003F83, 0x4003F87, 0x4003F8B, 0x4003F8F, 0x4003F93, 0x4003F97, 0x4003F9B, 0x4003F9F, 0x4003FA3, 0x4003FA7, 0x4003FAB, 0x4003FAF,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4003FB3, 0x4003FB7, 0x4003FBB, 0x4003FBF, 0x4003FC3, 0x4003FC7, 0x4003FCB, 0x4003FCF, 0x4003FD3, 0x4003FD7, 0x4003FDB, 0x4003FDF, 0x4003FE3, 0x4003FE7, 0x4003FEB, 0x4003FEF,
+	0x4003FF3, 0x4003FF7, 0x4003FFB, 0x4003FFF, 0x4004003, 0x4004007, 0x400400B, 0x400400F, 0x4004013, 0x4004017, 0x400401B, 0x400401F, 0x4004023, 0x4004027, 0x400402B, 0x400402F,
+};
+const uint32_t* UppercaseDataPtr = UppercaseData;
+
+const uint32_t LowercaseIndex1[272] = {
+	0, 128, 256, 384, 360, 360, 360, 360, 360, 360, 512, 360, 360, 360, 360, 640,
+	768, 896, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+};
+const uint32_t* LowercaseIndex1Ptr = LowercaseIndex1;
+
+const uint32_t LowercaseIndex2[1024] = {
+	0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x40, 0x0, 0x60, 0x80, 0xA0, 0xC0, 0xE0, 0x100, 0x120, 0x140,
+	0x160, 0x180, 0x1A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C0, 0x1E0, 0x200, 0x220, 0x240,
+	0x260, 0x280, 0x0, 0x2A0, 0x2C0, 0x2E0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x3A0, 0x3C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3E0, 0x400, 0x420, 0x440, 0x460, 0x480, 0x4A0, 0x4C0, 0x4E0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5A0, 0x5C0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5E0, 0x0, 0x600, 0x620, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x640, 0x660, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x680, 0x6A0, 0x0, 0x6C0, 0x6E0, 0x700, 0x720, 0x740, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x760, 0x780, 0x7A0, 0x0, 0x0, 0x0, 0x0, 0x7C0, 0x7E0, 0x800, 0x820, 0x840, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x860, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x880, 0x8A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x8C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+};
+const uint32_t* LowercaseIndex2Ptr = LowercaseIndex2;
+
+const uint32_t LowercaseData[2272] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E,
+	0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2004033, 0x2004035, 0x2004037, 0x2004039, 0x200403B, 0x200403D, 0x2000247, 0x200403F, 0x2004041, 0x2004043, 0x2004045, 0x2004047, 0x2004049, 0x200404B, 0x200404D, 0x200404F,
+	0x2001E1E, 0x2004051, 0x2004053, 0x2004055, 0x2004057, 0x2004059, 0x200405B, 0x0, 0x2000294, 0x200405D, 0x200405F, 0x2004061, 0x2004063, 0x2004065, 0x2004067, 0x0,
+	0x2004069, 0x0, 0x200406B, 0x0, 0x200406D, 0x0, 0x200406F, 0x0, 0x2004071, 0x0, 0x2004073, 0x0, 0x2004075, 0x0, 0x2004077, 0x0,
+	0x2004079, 0x0, 0x200407B, 0x0, 0x200407D, 0x0, 0x200407F, 0x0, 0x2004081, 0x0, 0x2004083, 0x0, 0x2004085, 0x0, 0x2004087, 0x0,
+	0x2004089, 0x0, 0x200408B, 0x0, 0x200408D, 0x0, 0x2001EF8, 0x0, 0x200408F, 0x0, 0x2004091, 0x0, 0x2004093, 0x0, 0x2004095, 0x0,
+	0x3004097, 0x0, 0x200409A, 0x0, 0x200409C, 0x0, 0x200409E, 0x0, 0x0, 0x20040A0, 0x0, 0x20040A2, 0x0, 0x20040A4, 0x0, 0x20040A6,
+	0x0, 0x20040A8, 0x0, 0x20040AA, 0x0, 0x20040AC, 0x0, 0x20040AE, 0x0, 0x0, 0x2001E00, 0x0, 0x20040B0, 0x0, 0x20040B2, 0x0,
+	0x20040B4, 0x0, 0x2002CE5, 0x0, 0x20040B6, 0x0, 0x20040B8, 0x0, 0x20040BA, 0x0, 0x20040BC, 0x0, 0x20040BE, 0x0, 0x20040C0, 0x0,
+	0x20040C2, 0x0, 0x20040C4, 0x0, 0x20040C6, 0x0, 0x20040C8, 0x0, 0x20040CA, 0x0, 0x20040CC, 0x0, 0x20040CE, 0x0, 0x20040D0, 0x0,
+	0x20040D2, 0x0, 0x20040D4, 0x0, 0x20040D6, 0x0, 0x20040D8, 0x0, 0x20040DA, 0x20040DC, 0x0, 0x20040DE, 0x0, 0x20040E0, 0x0, 0x0,
+	0x0, 0x20040E2, 0x20040E4, 0x0, 0x20040E6, 0x0, 0x2001E02, 0x20040E8, 0x0, 0x20040EA, 0x20040EC, 0x20040EE, 0x0, 0x0, 0x20040F0, 0x2001DFA,
+	0x2001DFC, 0x20040F2, 0x0, 0x20040F4, 0x2001D7D, 0x0, 0x2001E28, 0x2001E26, 0x20040F6, 0x0, 0x0, 0x0, 0x2001E0D, 0x2001E3C, 0x0, 0x2001E42,
+	0x20040F8, 0x0, 0x20040FA, 0x0, 0x20040FC, 0x0, 0x20040FE, 0x2004100, 0x0, 0x2001E48, 0x0, 0x0, 0x2004102, 0x0, 0x2004104, 0x2004106,
+	0x0, 0x2001E4E, 0x2001E53, 0x2004108, 0x0, 0x200410A, 0x0, 0x200026B, 0x200410C, 0x0, 0x0, 0x0, 0x200410E, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x2004110, 0x2004110, 0x0, 0x2004112, 0x2004112, 0x0, 0x2004114, 0x2004114, 0x0, 0x2004116, 0x0, 0x2004118,
+	0x0, 0x200411A, 0x0, 0x200411C, 0x0, 0x200411E, 0x0, 0x2004120, 0x0, 0x2004122, 0x0, 0x2004124, 0x0, 0x0, 0x2004126, 0x0,
+	0x2004128, 0x0, 0x200412A, 0x0, 0x200412C, 0x0, 0x200412E, 0x0, 0x2004130, 0x0, 0x2004132, 0x0, 0x2004134, 0x0, 0x2004136, 0x0,
+	0x0, 0x2004138, 0x2004138, 0x0, 0x200413A, 0x0, 0x200413C, 0x200413E, 0x2004140, 0x0, 0x2004142, 0x0, 0x2004144, 0x0, 0x2004146, 0x0,
+	0x2004148, 0x0, 0x200414A, 0x0, 0x200414C, 0x0, 0x200414E, 0x0, 0x2004150, 0x0, 0x2004152, 0x0, 0x2004154, 0x0, 0x2004156, 0x0,
+	0x2004158, 0x0, 0x200415A, 0x0, 0x200415C, 0x0, 0x200415E, 0x0, 0x2004160, 0x0, 0x2004162, 0x0, 0x2004164, 0x0, 0x2004166, 0x0,
+	0x2004168, 0x0, 0x200416A, 0x0, 0x200416C, 0x0, 0x200416E, 0x0, 0x2004170, 0x0, 0x2004172, 0x0, 0x2004174, 0x0, 0x2004176, 0x0,
+	0x2004178, 0x0, 0x200417A, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300417C, 0x200417F, 0x0, 0x2004181, 0x3004183, 0x0,
+	0x0, 0x2004186, 0x0, 0x2004188, 0x2001E4C, 0x2001E55, 0x200418A, 0x0, 0x200418C, 0x0, 0x200418E, 0x0, 0x2004190, 0x0, 0x2004192, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2004194, 0x0, 0x2004196, 0x0, 0x0, 0x0, 0x2004198, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200419A,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200419C, 0x0, 0x200419E, 0x20041A0, 0x20041A2, 0x0, 0x20041A4, 0x0, 0x20041A6, 0x20041A8,
+	0x0, 0x2000357, 0x2001D89, 0x2001E12, 0x2001E14, 0x200035B, 0x2003369, 0x200035F, 0x2001D8B, 0x2000349, 0x2001D91, 0x200336B, 0x2001D29, 0x200336D, 0x200336F, 0x200036D,
+	0x2001D8F, 0x2000E17, 0x0, 0x2003371, 0x2003373, 0x2000367, 0x2001D8D, 0x2001E16, 0x2003375, 0x2000375, 0x20041AA, 0x20041AC, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20041AE,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20041B0, 0x0, 0x20041B2, 0x0, 0x200337C, 0x0, 0x20041B4, 0x0,
+	0x20041B6, 0x0, 0x20041B8, 0x0, 0x20041BA, 0x0, 0x20041BC, 0x0, 0x20041BE, 0x0, 0x20041C0, 0x0, 0x20041C2, 0x0, 0x20041C4, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x2001D8B, 0x0, 0x0, 0x20041C6, 0x0, 0x20041C8, 0x20041CA, 0x0, 0x0, 0x20041CC, 0x20041CE, 0x20041D0,
+	0x20041D2, 0x20041D4, 0x20041D6, 0x20041D8, 0x20041DA, 0x20041DC, 0x20003B1, 0x20041DE, 0x20041E0, 0x20041E2, 0x20041E4, 0x20041E6, 0x20041E8, 0x20041EA, 0x20041EC, 0x20041EE,
+	0x20003D5, 0x20041F0, 0x20041F2, 0x20003AD, 0x20041F4, 0x20003A5, 0x20003CD, 0x20003FD, 0x20003A1, 0x20041F6, 0x20003B5, 0x20041F8, 0x20041FA, 0x2001E18, 0x2000415, 0x20041FC,
+	0x20041FE, 0x2004200, 0x2004202, 0x20003BD, 0x2004204, 0x2004206, 0x2004208, 0x2000445, 0x200420A, 0x200420C, 0x2002CDC, 0x200044D, 0x2002CDE, 0x2000425, 0x200420E, 0x2004210,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2004212, 0x0, 0x2004214, 0x0, 0x2004216, 0x0, 0x2004218, 0x0, 0x200421A, 0x0, 0x200421C, 0x0, 0x200421E, 0x0, 0x2004220, 0x0,
+	0x2004222, 0x0, 0x2004224, 0x0, 0x20003C5, 0x0, 0x2004226, 0x0, 0x2004228, 0x0, 0x200422A, 0x0, 0x200422C, 0x0, 0x200422E, 0x0,
+	0x2004230, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004232, 0x0, 0x2004234, 0x0, 0x2004236, 0x0,
+	0x2004238, 0x0, 0x200423A, 0x0, 0x200423C, 0x0, 0x200423E, 0x0, 0x2004240, 0x0, 0x2004242, 0x0, 0x2004244, 0x0, 0x2004246, 0x0,
+	0x2004248, 0x0, 0x200424A, 0x0, 0x200424C, 0x0, 0x200424E, 0x0, 0x2004250, 0x0, 0x2004252, 0x0, 0x2004254, 0x0, 0x2004256, 0x0,
+	0x2004258, 0x0, 0x200425A, 0x0, 0x200425C, 0x0, 0x200425E, 0x0, 0x2004260, 0x0, 0x2004262, 0x0, 0x2004264, 0x0, 0x2004266, 0x0,
+	0x2004268, 0x200426A, 0x0, 0x200426C, 0x0, 0x200426E, 0x0, 0x2004270, 0x0, 0x2004272, 0x0, 0x2004274, 0x0, 0x2004276, 0x0, 0x0,
+	0x2004278, 0x0, 0x200427A, 0x0, 0x200427C, 0x0, 0x200427E, 0x0, 0x20003ED, 0x0, 0x2004280, 0x0, 0x2004282, 0x0, 0x2004284, 0x0,
+	0x2004286, 0x0, 0x2004288, 0x0, 0x200428A, 0x0, 0x200428C, 0x0, 0x200041D, 0x0, 0x200428E, 0x0, 0x2004290, 0x0, 0x2004292, 0x0,
+	0x2004294, 0x0, 0x2004296, 0x0, 0x2004298, 0x0, 0x200429A, 0x0, 0x200429C, 0x0, 0x200429E, 0x0, 0x20042A0, 0x0, 0x20042A2, 0x0,
+	0x20042A4, 0x0, 0x20042A6, 0x0, 0x20042A8, 0x0, 0x20042AA, 0x0, 0x20042AC, 0x0, 0x20042AE, 0x0, 0x20042B0, 0x0, 0x20042B2, 0x0,
+	0x20042B4, 0x0, 0x20042B6, 0x0, 0x20042B8, 0x0, 0x20042BA, 0x0, 0x20042BC, 0x0, 0x20042BE, 0x0, 0x20042C0, 0x0, 0x20042C2, 0x0,
+	0x20042C4, 0x0, 0x20042C6, 0x0, 0x20042C8, 0x0, 0x20042CA, 0x0, 0x20042CC, 0x0, 0x20042CE, 0x0, 0x20042D0, 0x0, 0x20042D2, 0x0,
+	0x0, 0x20042D4, 0x20042D6, 0x20042D8, 0x20042DA, 0x2001D99, 0x20042DC, 0x20042DE, 0x20042E0, 0x20042E2, 0x20042E4, 0x2002D0A, 0x20042E6, 0x2002D12, 0x20042E8, 0x20042EA,
+	0x20042EC, 0x20042EE, 0x20042F0, 0x20042F2, 0x2002D00, 0x20042F4, 0x2002D02, 0x20042F6, 0x20042F8, 0x20042FA, 0x20042FC, 0x20042FE, 0x2004300, 0x2004302, 0x2002D0C, 0x2004304,
+	0x2004306, 0x2004308, 0x2001D9B, 0x200430A, 0x200430C, 0x200430E, 0x2004310, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004312, 0x3004315, 0x3004318, 0x300431B, 0x300431E, 0x3004321, 0x3004324, 0x3004327, 0x300432A, 0x300432D, 0x3004330, 0x3004333, 0x3004336, 0x3004339, 0x300433C, 0x300433F,
+	0x3004342, 0x3004345, 0x3004348, 0x300434B, 0x300434E, 0x3004351, 0x3004354, 0x3004357, 0x300435A, 0x300435D, 0x3004360, 0x3004363, 0x3004366, 0x3004369, 0x300436C, 0x300436F,
+	0x3004372, 0x3004375, 0x3004378, 0x300437B, 0x300437E, 0x3004381, 0x0, 0x3004384, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004387, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300438A, 0x0, 0x300438D, 0x0, 0x3004390, 0x0, 0x3004393, 0x0, 0x3004396, 0x0, 0x3004399, 0x0, 0x300439C, 0x0, 0x300439F, 0x0,
+	0x30043A2, 0x0, 0x30043A5, 0x0, 0x30043A8, 0x0, 0x30043AB, 0x0, 0x30043AE, 0x0, 0x30043B1, 0x0, 0x30043B4, 0x0, 0x30043B7, 0x0,
+	0x30043BA, 0x0, 0x30043BD, 0x0, 0x30043C0, 0x0, 0x30043C3, 0x0, 0x30043C6, 0x0, 0x30043C9, 0x0, 0x30043CC, 0x0, 0x30043CF, 0x0,
+	0x30043D2, 0x0, 0x30043D5, 0x0, 0x30043D8, 0x0, 0x30043DB, 0x0, 0x30043DE, 0x0, 0x30043E1, 0x0, 0x30043E4, 0x0, 0x30043E7, 0x0,
+	0x30043EA, 0x0, 0x30043ED, 0x0, 0x30043F0, 0x0, 0x30043F3, 0x0, 0x30043F6, 0x0, 0x30043F9, 0x0, 0x30043FC, 0x0, 0x30043FF, 0x0,
+	0x3004402, 0x0, 0x3004405, 0x0, 0x3004408, 0x0, 0x300440B, 0x0, 0x300440E, 0x0, 0x3004411, 0x0, 0x3004414, 0x0, 0x3004417, 0x0,
+	0x300441A, 0x0, 0x300441D, 0x0, 0x3004420, 0x0, 0x3004423, 0x0, 0x3004426, 0x0, 0x3004429, 0x0, 0x300442C, 0x0, 0x300442F, 0x0,
+	0x3004432, 0x0, 0x3004435, 0x0, 0x3004438, 0x0, 0x300443B, 0x0, 0x300443E, 0x0, 0x3004441, 0x0, 0x3004444, 0x0, 0x3004447, 0x0,
+	0x300444A, 0x0, 0x300444D, 0x0, 0x3004450, 0x0, 0x3004453, 0x0, 0x3004456, 0x0, 0x3004459, 0x0, 0x300445C, 0x0, 0x300445F, 0x0,
+	0x3004462, 0x0, 0x3004465, 0x0, 0x3004468, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200446B, 0x0,
+	0x300446D, 0x0, 0x3004470, 0x0, 0x3004473, 0x0, 0x3004476, 0x0, 0x3004479, 0x0, 0x300447C, 0x0, 0x300447F, 0x0, 0x3004482, 0x0,
+	0x3004485, 0x0, 0x3004488, 0x0, 0x300448B, 0x0, 0x300448E, 0x0, 0x3004491, 0x0, 0x3004494, 0x0, 0x3004497, 0x0, 0x300449A, 0x0,
+	0x300449D, 0x0, 0x30044A0, 0x0, 0x30044A3, 0x0, 0x30044A6, 0x0, 0x30044A9, 0x0, 0x30044AC, 0x0, 0x30044AF, 0x0, 0x30044B2, 0x0,
+	0x30044B5, 0x0, 0x30044B8, 0x0, 0x30044BB, 0x0, 0x30044BE, 0x0, 0x30044C1, 0x0, 0x30044C4, 0x0, 0x30044C7, 0x0, 0x30044CA, 0x0,
+	0x30044CD, 0x0, 0x30044D0, 0x0, 0x30044D3, 0x0, 0x30044D6, 0x0, 0x30044D9, 0x0, 0x30044DC, 0x0, 0x30044DF, 0x0, 0x30044E2, 0x0,
+	0x30044E5, 0x0, 0x30044E8, 0x0, 0x30044EB, 0x0, 0x30044EE, 0x0, 0x30044F1, 0x0, 0x30044F4, 0x0, 0x30044F7, 0x0, 0x30044FA, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30044FD, 0x3004500, 0x3004503, 0x3004506, 0x3004509, 0x300450C, 0x300450F, 0x3004512,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004515, 0x3004518, 0x300451B, 0x300451E, 0x3004521, 0x3004524, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004527, 0x300452A, 0x300452D, 0x3004530, 0x3004533, 0x3004536, 0x3004539, 0x300453C,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300453F, 0x3004542, 0x3004545, 0x3004548, 0x300454B, 0x300454E, 0x3004551, 0x3004554,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004557, 0x300455A, 0x300455D, 0x3004560, 0x3004563, 0x3004566, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004569, 0x0, 0x300456C, 0x0, 0x300456F, 0x0, 0x3004572,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004575, 0x3004578, 0x300457B, 0x300457E, 0x3004581, 0x3004584, 0x3004587, 0x300458A,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300458D, 0x3004590, 0x3004593, 0x3004596, 0x3004599, 0x300459C, 0x300459F, 0x30045A2,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045A5, 0x30045A8, 0x30045AB, 0x30045AE, 0x30045B1, 0x30045B4, 0x30045B7, 0x30045BA,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045BD, 0x30045C0, 0x30045C3, 0x30045C6, 0x30045C9, 0x30045CC, 0x30045CF, 0x30045D2,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045D5, 0x30045D8, 0x30045DB, 0x30045DE, 0x30045E1, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045E4, 0x30045E7, 0x30045EA, 0x30045ED, 0x30045F0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045F3, 0x30045F6, 0x30045F9, 0x30045FC, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045FF, 0x3004602, 0x3004605, 0x3004608, 0x300460B, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300460E, 0x3004611, 0x3004614, 0x3004617, 0x300461A, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000375, 0x0, 0x0, 0x0, 0x100012F, 0x200403D, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x300461D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004620, 0x3004623, 0x3004626, 0x3004629, 0x300462C, 0x300462F, 0x3004632, 0x3004635, 0x3004638, 0x300463B, 0x300463E, 0x3004641, 0x3004644, 0x3004647, 0x300464A, 0x300464D,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3004650, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004653, 0x3004656, 0x3004659, 0x300465C, 0x300465F, 0x3004662, 0x3004665, 0x3004668, 0x300466B, 0x300466E,
+	0x3004671, 0x3004674, 0x3004677, 0x300467A, 0x300467D, 0x3004680, 0x3004683, 0x3004686, 0x3004689, 0x300468C, 0x300468F, 0x3004692, 0x3004695, 0x3004698, 0x300469B, 0x300469E,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30046A1, 0x30046A4, 0x30046A7, 0x30046AA, 0x30046AD, 0x30046B0, 0x30046B3, 0x30046B6, 0x30046B9, 0x30046BC, 0x30046BF, 0x30046C2, 0x30046C5, 0x30046C8, 0x30046CB, 0x30046CE,
+	0x30046D1, 0x30046D4, 0x30046D7, 0x30046DA, 0x30046DD, 0x30046E0, 0x30046E3, 0x30046E6, 0x30046E9, 0x30046EC, 0x30046EF, 0x30046F2, 0x30046F5, 0x30046F8, 0x30046FB, 0x30046FE,
+	0x3004701, 0x3004704, 0x3004707, 0x300470A, 0x300470D, 0x3004710, 0x3004713, 0x3004716, 0x3004719, 0x300471C, 0x300471F, 0x3004722, 0x3004725, 0x3004728, 0x300472B, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300472E, 0x0, 0x2002CED, 0x3004731, 0x2004734, 0x0, 0x0, 0x3004736, 0x0, 0x3004739, 0x0, 0x300473C, 0x0, 0x2001DF5, 0x2001E38, 0x2001DF3,
+	0x2001E1A, 0x0, 0x300473F, 0x0, 0x0, 0x3004742, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004745, 0x2004747,
+	0x3004749, 0x0, 0x300474C, 0x0, 0x300474F, 0x0, 0x3004752, 0x0, 0x3004755, 0x0, 0x3004758, 0x0, 0x300475B, 0x0, 0x300475E, 0x0,
+	0x3004761, 0x0, 0x3004764, 0x0, 0x3004767, 0x0, 0x300476A, 0x0, 0x300476D, 0x0, 0x3004770, 0x0, 0x3004773, 0x0, 0x3004776, 0x0,
+	0x3004779, 0x0, 0x300477C, 0x0, 0x300477F, 0x0, 0x3004782, 0x0, 0x3004785, 0x0, 0x3004788, 0x0, 0x300478B, 0x0, 0x300478E, 0x0,
+	0x3004791, 0x0, 0x3004794, 0x0, 0x3004797, 0x0, 0x300479A, 0x0, 0x300479D, 0x0, 0x30047A0, 0x0, 0x30047A3, 0x0, 0x30047A6, 0x0,
+	0x30047A9, 0x0, 0x30047AC, 0x0, 0x30047AF, 0x0, 0x30047B2, 0x0, 0x30047B5, 0x0, 0x30047B8, 0x0, 0x30047BB, 0x0, 0x30047BE, 0x0,
+	0x30047C1, 0x0, 0x30047C4, 0x0, 0x30047C7, 0x0, 0x30047CA, 0x0, 0x30047CD, 0x0, 0x30047D0, 0x0, 0x30047D3, 0x0, 0x30047D6, 0x0,
+	0x30047D9, 0x0, 0x30047DC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30047DF, 0x0, 0x30047E2, 0x0, 0x0,
+	0x0, 0x0, 0x30047E5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30047E8, 0x0, 0x30047EB, 0x0, 0x30047EE, 0x0, 0x30047F1, 0x0, 0x30047F4, 0x0, 0x30047F7, 0x0, 0x30047FA, 0x0, 0x30047FD, 0x0,
+	0x3004800, 0x0, 0x3004803, 0x0, 0x3004806, 0x0, 0x3004809, 0x0, 0x300480C, 0x0, 0x300480F, 0x0, 0x3004812, 0x0, 0x3004815, 0x0,
+	0x3004818, 0x0, 0x300481B, 0x0, 0x300481E, 0x0, 0x3004821, 0x0, 0x3004824, 0x0, 0x3004827, 0x0, 0x300482A, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300482D, 0x0, 0x3004830, 0x0, 0x3004833, 0x0, 0x3004836, 0x0, 0x3004839, 0x0, 0x300483C, 0x0, 0x300483F, 0x0, 0x3004842, 0x0,
+	0x3004845, 0x0, 0x3004848, 0x0, 0x300484B, 0x0, 0x300484E, 0x0, 0x3004851, 0x0, 0x3004854, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x3004857, 0x0, 0x300485A, 0x0, 0x3002CE7, 0x0, 0x300485D, 0x0, 0x3004860, 0x0, 0x3004863, 0x0, 0x3004866, 0x0,
+	0x0, 0x0, 0x3004869, 0x0, 0x300486C, 0x0, 0x300486F, 0x0, 0x3004872, 0x0, 0x3004875, 0x0, 0x3004878, 0x0, 0x300487B, 0x0,
+	0x300487E, 0x0, 0x3004881, 0x0, 0x3004884, 0x0, 0x3004887, 0x0, 0x300488A, 0x0, 0x300488D, 0x0, 0x3004890, 0x0, 0x3004893, 0x0,
+	0x3004896, 0x0, 0x3004899, 0x0, 0x300489C, 0x0, 0x300489F, 0x0, 0x30048A2, 0x0, 0x30048A5, 0x0, 0x30048A8, 0x0, 0x30048AB, 0x0,
+	0x30048AE, 0x0, 0x30048B1, 0x0, 0x30048B4, 0x0, 0x30048B7, 0x0, 0x30048BA, 0x0, 0x30048BD, 0x0, 0x30048C0, 0x0, 0x3002CE0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30048C3, 0x0, 0x30048C6, 0x0, 0x30048C9, 0x30048CC, 0x0,
+	0x30048CF, 0x0, 0x30048D2, 0x0, 0x30048D5, 0x0, 0x30048D8, 0x0, 0x0, 0x0, 0x0, 0x30048DB, 0x0, 0x2001E24, 0x0, 0x0,
+	0x30048DE, 0x0, 0x30048E1, 0x0, 0x0, 0x0, 0x30048E4, 0x0, 0x30048E7, 0x0, 0x30048EA, 0x0, 0x30048ED, 0x0, 0x30048F0, 0x0,
+	0x30048F3, 0x0, 0x30048F6, 0x0, 0x30048F9, 0x0, 0x30048FC, 0x0, 0x30048FF, 0x0, 0x2001D63, 0x2001DFE, 0x2001E22, 0x2004902, 0x0, 0x0,
+	0x2004904, 0x2004906, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3004908, 0x300490B, 0x300490E, 0x3004911, 0x3004914, 0x3004917, 0x300491A, 0x300491D, 0x3004920, 0x3004923, 0x3004926, 0x3004929, 0x300492C, 0x300492F, 0x3004932,
+	0x3004935, 0x3004938, 0x300493B, 0x300493E, 0x3004941, 0x3004944, 0x3004947, 0x300494A, 0x300494D, 0x3004950, 0x3004953, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4004956, 0x400495A, 0x400495E, 0x4004962, 0x4004966, 0x400496A, 0x400496E, 0x4004972, 0x4004976, 0x400497A, 0x400497E, 0x4004982, 0x4004986, 0x400498A, 0x400498E, 0x4004992,
+	0x4004996, 0x400499A, 0x400499E, 0x40049A2, 0x40049A6, 0x40049AA, 0x40049AE, 0x40049B2, 0x40049B6, 0x40049BA, 0x40049BE, 0x40049C2, 0x40049C6, 0x40049CA, 0x40049CE, 0x40049D2,
+	0x40049D6, 0x40049DA, 0x40049DE, 0x40049E2, 0x40049E6, 0x40049EA, 0x40049EE, 0x40049F2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x40049F6, 0x40049FA, 0x40049FE, 0x4004A02, 0x4004A06, 0x4004A0A, 0x4004A0E, 0x4004A12, 0x4004A16, 0x4004A1A, 0x4004A1E, 0x4004A22, 0x4004A26, 0x4004A2A, 0x4004A2E, 0x4004A32,
+	0x4004A36, 0x4004A3A, 0x4004A3E, 0x4004A42, 0x4004A46, 0x4004A4A, 0x4004A4E, 0x4004A52, 0x4004A56, 0x4004A5A, 0x4004A5E, 0x4004A62, 0x4004A66, 0x4004A6A, 0x4004A6E, 0x4004A72,
+};
+const uint32_t* LowercaseDataPtr = LowercaseData;
+
+const uint32_t TitlecaseIndex1[272] = {
+	0, 128, 256, 45, 45, 45, 45, 45, 45, 45, 384, 45, 45, 45, 45, 512,
+	640, 768, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+	45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+};
+const uint32_t* TitlecaseIndex1Ptr = TitlecaseIndex1;
+
+const uint32_t TitlecaseIndex2[896] = {
+	0x0, 0x0, 0x0, 0x20, 0x0, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0, 0x100, 0x120, 0x140, 0x160, 0x180,
+	0x1A0, 0x1C0, 0x1E0, 0x200, 0x220, 0x0, 0x0, 0x0, 0x0, 0x0, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
+	0x0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0x400, 0x0, 0x420, 0x440, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x460, 0x0, 0x0, 0x0, 0x0,
+	0x480, 0x4A0, 0x4C0, 0x4E0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5A0, 0x5C0, 0x5E0, 0x600, 0x620, 0x640, 0x660,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x680, 0x6A0, 0x6C0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6E0, 0x700, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x720, 0x740, 0x760, 0x780, 0x7A0, 0x7C0, 0x7E0, 0x800, 0x820, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x840, 0x860, 0x880, 0x0, 0x0, 0x0, 0x0, 0x8A0, 0x8C0, 0x8E0, 0x900, 0x920, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x940, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x960, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x980, 0x9A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+};
+const uint32_t* TitlecaseIndex2Ptr = TitlecaseIndex2;
+
+const uint32_t TitlecaseData[2528] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030,
+	0x1000751, 0x1001EFC, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x2003358, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004A76,
+	0x20034B3, 0x20034B5, 0x20034B7, 0x20034B9, 0x20034BB, 0x20034BD, 0x2000243, 0x20034BF, 0x20034C1, 0x20034C3, 0x20034C5, 0x20034C7, 0x20034C9, 0x20034CB, 0x20034CD, 0x20034CF,
+	0x20034D1, 0x20034D3, 0x20034D5, 0x20034D7, 0x20034D9, 0x20034DB, 0x20034DD, 0x0, 0x2000290, 0x20034DF, 0x20034E1, 0x20034E3, 0x20034E5, 0x20034E7, 0x20034E9, 0x20034EB,
+	0x0, 0x20034ED, 0x0, 0x20034EF, 0x0, 0x20034F1, 0x0, 0x20034F3, 0x0, 0x20034F5, 0x0, 0x20034F7, 0x0, 0x20034F9, 0x0, 0x20034FB,
+	0x0, 0x20034FD, 0x0, 0x20034FF, 0x0, 0x2003501, 0x0, 0x2003503, 0x0, 0x2003505, 0x0, 0x2003507, 0x0, 0x2003509, 0x0, 0x200350B,
+	0x0, 0x200350D, 0x0, 0x200350F, 0x0, 0x2003511, 0x0, 0x2002CE3, 0x0, 0x2003513, 0x0, 0x2003515, 0x0, 0x2003517, 0x0, 0x2003519,
+	0x0, 0x1000021, 0x0, 0x200351B, 0x0, 0x200351D, 0x0, 0x200351F, 0x0, 0x0, 0x2003521, 0x0, 0x2003523, 0x0, 0x2003525, 0x0,
+	0x2003527, 0x0, 0x2003529, 0x0, 0x200352B, 0x0, 0x200352D, 0x0, 0x200352F, 0x3003531, 0x0, 0x2003534, 0x0, 0x2003536, 0x0, 0x2003538,
+	0x0, 0x200353A, 0x0, 0x200353C, 0x0, 0x200353E, 0x0, 0x2003540, 0x0, 0x2003542, 0x0, 0x2003544, 0x0, 0x2003546, 0x0, 0x2003548,
+	0x0, 0x200354A, 0x0, 0x200354C, 0x0, 0x200354E, 0x0, 0x2003550, 0x0, 0x2003552, 0x0, 0x2003554, 0x0, 0x2003556, 0x0, 0x2003558,
+	0x0, 0x200355A, 0x0, 0x200355C, 0x0, 0x200355E, 0x0, 0x2003560, 0x0, 0x0, 0x2003562, 0x0, 0x2003564, 0x0, 0x2003566, 0x100017A,
+	0x2003568, 0x0, 0x0, 0x200356A, 0x0, 0x200356C, 0x0, 0x0, 0x200356E, 0x0, 0x0, 0x0, 0x2003570, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x2003572, 0x0, 0x0, 0x2003574, 0x0, 0x0, 0x0, 0x2003576, 0x2003578, 0x0, 0x0, 0x0, 0x200357A, 0x0,
+	0x0, 0x200357C, 0x0, 0x200357E, 0x0, 0x2003580, 0x0, 0x0, 0x2003582, 0x0, 0x0, 0x0, 0x0, 0x2003584, 0x0, 0x0,
+	0x2003586, 0x0, 0x0, 0x0, 0x2003588, 0x0, 0x200358A, 0x0, 0x0, 0x200358C, 0x0, 0x0, 0x0, 0x200358E, 0x0, 0x2003590,
+	0x0, 0x0, 0x0, 0x0, 0x2004A78, 0x0, 0x2004A78, 0x2004A7A, 0x0, 0x2004A7A, 0x2004A7C, 0x0, 0x2004A7C, 0x0, 0x2003598, 0x0,
+	0x200359A, 0x0, 0x200359C, 0x0, 0x200359E, 0x0, 0x20035A0, 0x0, 0x20035A2, 0x0, 0x20035A4, 0x0, 0x20035A6, 0x2001DEF, 0x0, 0x20035A8,
+	0x0, 0x20035AA, 0x0, 0x20035AC, 0x0, 0x20035AE, 0x0, 0x20035B0, 0x0, 0x20035B2, 0x0, 0x20035B4, 0x0, 0x20035B6, 0x0, 0x20035B8,
+	0x30035BA, 0x2004A7E, 0x0, 0x2004A7E, 0x0, 0x20035BF, 0x0, 0x0, 0x0, 0x20035C1, 0x0, 0x20035C3, 0x0, 0x20035C5, 0x0, 0x20035C7,
+	0x0, 0x20035C9, 0x0, 0x20035CB, 0x0, 0x20035CD, 0x0, 0x20035CF, 0x0, 0x20035D1, 0x0, 0x20035D3, 0x0, 0x20035D5, 0x0, 0x20035D7,
+	0x0, 0x20035D9, 0x0, 0x20035DB, 0x0, 0x20035DD, 0x0, 0x20035DF, 0x0, 0x20035E1, 0x0, 0x20035E3, 0x0, 0x20035E5, 0x0, 0x20035E7,
+	0x0, 0x0, 0x0, 0x2001DF1, 0x0, 0x20035E9, 0x0, 0x20035EB, 0x0, 0x20035ED, 0x0, 0x20035EF, 0x0, 0x20035F1, 0x0, 0x20035F3,
+	0x0, 0x20035F5, 0x0, 0x20035F7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20035F9, 0x0, 0x0, 0x30035FB,
+	0x30035FE, 0x0, 0x2003601, 0x0, 0x0, 0x0, 0x0, 0x2003603, 0x0, 0x2003605, 0x0, 0x2003607, 0x0, 0x2003609, 0x0, 0x200360B,
+	0x300360D, 0x3003610, 0x3003613, 0x2003616, 0x2003618, 0x0, 0x200361A, 0x200361C, 0x0, 0x200361E, 0x0, 0x2001EF3, 0x3003620, 0x0, 0x0, 0x0,
+	0x2003623, 0x3003625, 0x0, 0x2003628, 0x0, 0x300362A, 0x300362D, 0x0, 0x2003630, 0x2003632, 0x0, 0x3003634, 0x3003637, 0x0, 0x0, 0x200363A,
+	0x0, 0x300363C, 0x200363F, 0x0, 0x0, 0x2003641, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003643, 0x0, 0x0,
+	0x2003646, 0x0, 0x0, 0x2003648, 0x0, 0x0, 0x0, 0x300364A, 0x200364D, 0x200364F, 0x2003651, 0x2003653, 0x2003655, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x2000267, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003657, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x2000339, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x200365A, 0x0, 0x200365C, 0x0, 0x0, 0x0, 0x200365E, 0x0, 0x0, 0x0, 0x2003660, 0x2003662, 0x2003664, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6003666, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200366C, 0x200366E, 0x2003670, 0x2003672,
+	0x6003674, 0x200032B, 0x200334E, 0x2001F07, 0x2003350, 0x2000331, 0x2003352, 0x2000335, 0x2001D95, 0x2000339, 0x2003354, 0x2003356, 0x2003358, 0x200335A, 0x200335C, 0x200033D,
+	0x2001F09, 0x2000E35, 0x2001D97, 0x2001D97, 0x200335E, 0x2000341, 0x2003360, 0x2003362, 0x2003364, 0x2000345, 0x200367A, 0x200367C, 0x200367E, 0x2003680, 0x2003682, 0x0,
+	0x200334E, 0x2001D95, 0x0, 0x0, 0x0, 0x2003360, 0x2001F09, 0x2003684, 0x0, 0x2003686, 0x0, 0x2003688, 0x0, 0x200337A, 0x0, 0x200368A,
+	0x0, 0x200368C, 0x0, 0x200368E, 0x0, 0x2003690, 0x0, 0x2003692, 0x0, 0x2003694, 0x0, 0x2003696, 0x0, 0x2003698, 0x0, 0x200369A,
+	0x2003354, 0x2000E35, 0x200369C, 0x200369E, 0x0, 0x2000331, 0x0, 0x0, 0x20036A0, 0x0, 0x0, 0x20036A2, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x20003D1, 0x20036A4, 0x20036A6, 0x2000389, 0x20036A8, 0x2000381, 0x20003C9, 0x20003F9, 0x2000395, 0x20036AA, 0x2000391, 0x20036AC, 0x20036AE, 0x20036B0, 0x2000411, 0x20036B2,
+	0x20036B4, 0x20036B6, 0x20036B8, 0x2000399, 0x20036BA, 0x20036BC, 0x20036BE, 0x2000441, 0x20036C0, 0x20036C2, 0x20036C4, 0x2000449, 0x20036C6, 0x2000421, 0x20036C8, 0x20036CA,
+	0x20036CC, 0x20036CE, 0x20036D0, 0x20036D2, 0x20036D4, 0x20036D6, 0x200038D, 0x20036D8, 0x20036DA, 0x20036DC, 0x20036DE, 0x20036E0, 0x20036E2, 0x20036E4, 0x20036E6, 0x20036E8,
+	0x0, 0x20036EA, 0x0, 0x20036EC, 0x0, 0x20036EE, 0x0, 0x20036F0, 0x0, 0x20036F2, 0x0, 0x20036F4, 0x0, 0x20036F6, 0x0, 0x20036F8,
+	0x0, 0x20036FA, 0x0, 0x20036FC, 0x0, 0x20003C1, 0x0, 0x20036FE, 0x0, 0x2003700, 0x0, 0x2003702, 0x0, 0x2003704, 0x0, 0x2003706,
+	0x0, 0x2003708, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200370A, 0x0, 0x200370C, 0x0, 0x200370E,
+	0x0, 0x2003710, 0x0, 0x2003712, 0x0, 0x2003714, 0x0, 0x2003716, 0x0, 0x2003718, 0x0, 0x200371A, 0x0, 0x200371C, 0x0, 0x200371E,
+	0x0, 0x2003720, 0x0, 0x2003722, 0x0, 0x2003724, 0x0, 0x2003726, 0x0, 0x2003728, 0x0, 0x200372A, 0x0, 0x200372C, 0x0, 0x200372E,
+	0x0, 0x2003730, 0x0, 0x2003732, 0x0, 0x2003734, 0x0, 0x2003736, 0x0, 0x2003738, 0x0, 0x200373A, 0x0, 0x200373C, 0x0, 0x200373E,
+	0x0, 0x0, 0x2003740, 0x0, 0x2003742, 0x0, 0x2003744, 0x0, 0x2003746, 0x0, 0x2003748, 0x0, 0x200374A, 0x0, 0x200374C, 0x200374E,
+	0x0, 0x2003750, 0x0, 0x2003752, 0x0, 0x2003754, 0x0, 0x2003756, 0x0, 0x20003E9, 0x0, 0x2003758, 0x0, 0x200375A, 0x0, 0x200375C,
+	0x0, 0x200375E, 0x0, 0x2003760, 0x0, 0x2003762, 0x0, 0x2003764, 0x0, 0x2000419, 0x0, 0x2003766, 0x0, 0x2003768, 0x0, 0x200376A,
+	0x0, 0x200376C, 0x0, 0x200376E, 0x0, 0x2003770, 0x0, 0x2003772, 0x0, 0x2003774, 0x0, 0x2003776, 0x0, 0x2003778, 0x0, 0x200377A,
+	0x0, 0x200377C, 0x0, 0x200377E, 0x0, 0x2003780, 0x0, 0x2003782, 0x0, 0x2003784, 0x0, 0x2003786, 0x0, 0x2003788, 0x0, 0x200378A,
+	0x0, 0x200378C, 0x0, 0x200378E, 0x0, 0x2003790, 0x0, 0x2003792, 0x0, 0x2003794, 0x0, 0x2003796, 0x0, 0x2003798, 0x0, 0x200379A,
+	0x0, 0x200379C, 0x0, 0x200379E, 0x0, 0x20037A0, 0x0, 0x20037A2, 0x0, 0x20037A4, 0x0, 0x20037A6, 0x0, 0x20037A8, 0x0, 0x20037AA,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x20037AC, 0x20037AE, 0x20037B0, 0x20037B2, 0x20037B4, 0x20037B6, 0x20037B8, 0x20037BA, 0x20037BC, 0x20037BE, 0x20037C0, 0x20037C2, 0x20037C4, 0x20037C6, 0x20037C8,
+	0x20037CA, 0x20037CC, 0x20037CE, 0x20037D0, 0x20037D2, 0x20037D4, 0x20037D6, 0x20037D8, 0x20037DA, 0x20037DC, 0x20037DE, 0x20037E0, 0x20037E2, 0x20037E4, 0x20037E6, 0x20037E8,
+	0x20037EA, 0x20037EC, 0x20037EE, 0x20037F0, 0x20037F2, 0x20037F4, 0x20037F6, 0x4004A80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30037FC, 0x0, 0x0, 0x0, 0x30037FF, 0x0, 0x0,
+	0x0, 0x3003802, 0x0, 0x3003805, 0x0, 0x3003808, 0x0, 0x300380B, 0x0, 0x300380E, 0x0, 0x3003811, 0x0, 0x3003814, 0x0, 0x3003817,
+	0x0, 0x300381A, 0x0, 0x300381D, 0x0, 0x3003820, 0x0, 0x3003823, 0x0, 0x3003826, 0x0, 0x3003829, 0x0, 0x300382C, 0x0, 0x300382F,
+	0x0, 0x3003832, 0x0, 0x3003835, 0x0, 0x3003838, 0x0, 0x300383B, 0x0, 0x300383E, 0x0, 0x3003841, 0x0, 0x3003844, 0x0, 0x3003847,
+	0x0, 0x300384A, 0x0, 0x300384D, 0x0, 0x3003850, 0x0, 0x3003853, 0x0, 0x3003856, 0x0, 0x3003859, 0x0, 0x300385C, 0x0, 0x300385F,
+	0x0, 0x3003862, 0x0, 0x3003865, 0x0, 0x3003868, 0x0, 0x300386B, 0x0, 0x300386E, 0x0, 0x3003871, 0x0, 0x3003874, 0x0, 0x3003877,
+	0x0, 0x300387A, 0x0, 0x300387D, 0x0, 0x3003880, 0x0, 0x3003883, 0x0, 0x3003886, 0x0, 0x3003889, 0x0, 0x300388C, 0x0, 0x300388F,
+	0x0, 0x3003892, 0x0, 0x3003895, 0x0, 0x3003898, 0x0, 0x300389B, 0x0, 0x300389E, 0x0, 0x30038A1, 0x0, 0x30038A4, 0x0, 0x30038A7,
+	0x0, 0x30038AA, 0x0, 0x30038AD, 0x0, 0x30038B0, 0x0, 0x30038B3, 0x0, 0x30038B6, 0x0, 0x30038B9, 0x0, 0x30038BC, 0x0, 0x30038BF,
+	0x0, 0x30038C2, 0x0, 0x30038C5, 0x0, 0x30038C8, 0x0, 0x30038CB, 0x0, 0x30038CE, 0x0, 0x30038D1, 0x0, 0x30038D4, 0x0, 0x30038D7,
+	0x0, 0x30038DA, 0x0, 0x30038DD, 0x0, 0x30038E0, 0x30038E3, 0x30038E6, 0x30038E9, 0x30038EC, 0x30038EF, 0x3003892, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x30038F2, 0x0, 0x30038F5, 0x0, 0x30038F8, 0x0, 0x30038FB, 0x0, 0x30038FE, 0x0, 0x3003901, 0x0, 0x3003904, 0x0, 0x3003907,
+	0x0, 0x300390A, 0x0, 0x300390D, 0x0, 0x3003910, 0x0, 0x3003913, 0x0, 0x3003916, 0x0, 0x3003919, 0x0, 0x300391C, 0x0, 0x300391F,
+	0x0, 0x3003922, 0x0, 0x3003925, 0x0, 0x3003928, 0x0, 0x300392B, 0x0, 0x300392E, 0x0, 0x3003931, 0x0, 0x3003934, 0x0, 0x3003937,
+	0x0, 0x300393A, 0x0, 0x300393D, 0x0, 0x3003940, 0x0, 0x3003943, 0x0, 0x3003946, 0x0, 0x3003949, 0x0, 0x300394C, 0x0, 0x300394F,
+	0x0, 0x3003952, 0x0, 0x3003955, 0x0, 0x3003958, 0x0, 0x300395B, 0x0, 0x300395E, 0x0, 0x3003961, 0x0, 0x3003964, 0x0, 0x3003967,
+	0x0, 0x300396A, 0x0, 0x300396D, 0x0, 0x3003970, 0x0, 0x3003973, 0x0, 0x3003976, 0x0, 0x3003979, 0x0, 0x300397C, 0x0, 0x300397F,
+	0x3003982, 0x3003985, 0x3003988, 0x300398B, 0x300398E, 0x3003991, 0x3003994, 0x3003997, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300399A, 0x300399D, 0x30039A0, 0x30039A3, 0x30039A6, 0x30039A9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30039AC, 0x30039AF, 0x30039B2, 0x30039B5, 0x30039B8, 0x30039BB, 0x30039BE, 0x30039C1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30039C4, 0x30039C7, 0x30039CA, 0x30039CD, 0x30039D0, 0x30039D3, 0x30039D6, 0x30039D9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30039DC, 0x30039DF, 0x30039E2, 0x30039E5, 0x30039E8, 0x30039EB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x40039EE, 0x30039F2, 0x60039F5, 0x30039FB, 0x60039FE, 0x3003A04, 0x6003A07, 0x3003A0D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003A10, 0x3003A13, 0x3003A16, 0x3003A19, 0x3003A1C, 0x3003A1F, 0x3003A22, 0x3003A25, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003A28, 0x3003A2B, 0x3003A2E, 0x3003A31, 0x3003A34, 0x3003A37, 0x3003A3A, 0x3003A3D, 0x3003A40, 0x3003A43, 0x3003A46, 0x3003A49, 0x3003A4C, 0x3003A4F, 0x0, 0x0,
+	0x3004A84, 0x3004A87, 0x3004A8A, 0x3004A8D, 0x3004A90, 0x3004A93, 0x3004A96, 0x3004A99, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004A9C, 0x3004A9F, 0x3004AA2, 0x3004AA5, 0x3004AA8, 0x3004AAB, 0x3004AAE, 0x3004AB1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004AB4, 0x3004AB7, 0x3004ABA, 0x3004ABD, 0x3004AC0, 0x3004AC3, 0x3004AC6, 0x3004AC9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003ACA, 0x3003ACD, 0x5004ACC, 0x3004AD1, 0x4004AD4, 0x0, 0x4003ADD, 0x6004AD8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000339, 0x0,
+	0x0, 0x0, 0x5004ADE, 0x3004AE3, 0x4004AE6, 0x0, 0x4003AF4, 0x6004AEA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003AFE, 0x3003B01, 0x6003B04, 0x6003666, 0x0, 0x0, 0x4003B0A, 0x6003B0E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003B14, 0x3003B17, 0x6003B1A, 0x6003674, 0x4003B20, 0x3003B24, 0x4003B27, 0x6003B2B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x5004AF0, 0x3004AF5, 0x4004AF8, 0x0, 0x4003B3E, 0x6004AFC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003B48, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003B4B, 0x3003B4E, 0x3003B51, 0x3003B54, 0x3003B57, 0x3003B5A, 0x3003B5D, 0x3003B60, 0x3003B63, 0x3003B66, 0x3003B69, 0x3003B6C, 0x3003B6F, 0x3003B72, 0x3003B75, 0x3003B78,
+	0x0, 0x0, 0x0, 0x0, 0x3003B7B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003B7E, 0x3003B81, 0x3003B84, 0x3003B87, 0x3003B8A, 0x3003B8D, 0x3003B90, 0x3003B93, 0x3003B96, 0x3003B99, 0x3003B9C, 0x3003B9F, 0x3003BA2, 0x3003BA5, 0x3003BA8, 0x3003BAB,
+	0x3003BAE, 0x3003BB1, 0x3003BB4, 0x3003BB7, 0x3003BBA, 0x3003BBD, 0x3003BC0, 0x3003BC3, 0x3003BC6, 0x3003BC9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003BCC, 0x3003BCF, 0x3003BD2, 0x3003BD5, 0x3003BD8, 0x3003BDB, 0x3003BDE, 0x3003BE1, 0x3003BE4, 0x3003BE7, 0x3003BEA, 0x3003BED, 0x3003BF0, 0x3003BF3, 0x3003BF6, 0x3003BF9,
+	0x3003BFC, 0x3003BFF, 0x3003C02, 0x3003C05, 0x3003C08, 0x3003C0B, 0x3003C0E, 0x3003C11, 0x3003C14, 0x3003C17, 0x3003C1A, 0x3003C1D, 0x3003C20, 0x3003C23, 0x3003C26, 0x3003C29,
+	0x3003C2C, 0x3003C2F, 0x3003C32, 0x3003C35, 0x3003C38, 0x3003C3B, 0x3003C3E, 0x3003C41, 0x3003C44, 0x3003C47, 0x3003C4A, 0x3003C4D, 0x3003C50, 0x3003C53, 0x3003C56, 0x0,
+	0x0, 0x3003C59, 0x0, 0x0, 0x0, 0x2003C5C, 0x2003C5E, 0x0, 0x3003C60, 0x0, 0x3003C63, 0x0, 0x3003C66, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3003C69, 0x0, 0x0, 0x3003C6C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003C6F, 0x0, 0x3003C72, 0x0, 0x3003C75, 0x0, 0x3003C78, 0x0, 0x3003C7B, 0x0, 0x3003C7E, 0x0, 0x3003C81, 0x0, 0x3003C84,
+	0x0, 0x3003C87, 0x0, 0x3003C8A, 0x0, 0x3003C8D, 0x0, 0x3003C90, 0x0, 0x3003C93, 0x0, 0x3003C96, 0x0, 0x3003C99, 0x0, 0x3003C9C,
+	0x0, 0x3003C9F, 0x0, 0x3003CA2, 0x0, 0x3003CA5, 0x0, 0x3003CA8, 0x0, 0x3003CAB, 0x0, 0x3003CAE, 0x0, 0x3003CB1, 0x0, 0x3003CB4,
+	0x0, 0x3003CB7, 0x0, 0x3003CBA, 0x0, 0x3003CBD, 0x0, 0x3003CC0, 0x0, 0x3003CC3, 0x0, 0x3003CC6, 0x0, 0x3003CC9, 0x0, 0x3003CCC,
+	0x0, 0x3003CCF, 0x0, 0x3003CD2, 0x0, 0x3003CD5, 0x0, 0x3003CD8, 0x0, 0x3003CDB, 0x0, 0x3003CDE, 0x0, 0x3003CE1, 0x0, 0x3003CE4,
+	0x0, 0x3003CE7, 0x0, 0x3003CEA, 0x0, 0x3003CED, 0x0, 0x3003CF0, 0x0, 0x3003CF3, 0x0, 0x3003CF6, 0x0, 0x3003CF9, 0x0, 0x3003CFC,
+	0x0, 0x3003CFF, 0x0, 0x3003D02, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003D05, 0x0, 0x3003D08, 0x0,
+	0x0, 0x0, 0x0, 0x3003D0B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003D0E, 0x3003D11, 0x3003D14, 0x3003D17, 0x3003D1A, 0x3003D1D, 0x3003D20, 0x3003D23, 0x3003D26, 0x3003D29, 0x3003D2C, 0x3003D2F, 0x3003D32, 0x3003D35, 0x3003D38, 0x3003D3B,
+	0x3003D3E, 0x3003D41, 0x3003D44, 0x3003D47, 0x3003D4A, 0x3003D4D, 0x3003D50, 0x3003D53, 0x3003D56, 0x3003D59, 0x3003D5C, 0x3003D5F, 0x3003D62, 0x3003D65, 0x3003D68, 0x3003D6B,
+	0x3003D6E, 0x3003D71, 0x3003D74, 0x3003D77, 0x3003D7A, 0x3003D7D, 0x0, 0x3003D80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003D83, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003D86, 0x0, 0x3003D89, 0x0, 0x3003D8C, 0x0, 0x3003D8F, 0x0, 0x3003D92, 0x0, 0x3003D95, 0x0, 0x3003D98, 0x0, 0x3003D9B,
+	0x0, 0x3003D9E, 0x0, 0x3003DA1, 0x0, 0x3003DA4, 0x0, 0x3003DA7, 0x0, 0x3003DAA, 0x0, 0x3003DAD, 0x0, 0x3003DB0, 0x0, 0x3003DB3,
+	0x0, 0x3003DB6, 0x0, 0x3003DB9, 0x0, 0x3003DBC, 0x0, 0x3003DBF, 0x0, 0x3003DC2, 0x0, 0x3003DC5, 0x0, 0x3003DC8, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003DCB, 0x0, 0x3003DCE, 0x0, 0x3003DD1, 0x0, 0x3003DD4, 0x0, 0x3003DD7, 0x0, 0x3003DDA, 0x0, 0x3003DDD, 0x0, 0x3003DE0,
+	0x0, 0x3003DE3, 0x0, 0x3003DE6, 0x0, 0x3003DE9, 0x0, 0x3003DEC, 0x0, 0x3003DEF, 0x0, 0x3003DF2, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3003DF5, 0x0, 0x3003DF8, 0x0, 0x3003DFB, 0x0, 0x3003DFE, 0x0, 0x3003E01, 0x0, 0x3003E04, 0x0, 0x3003E07,
+	0x0, 0x0, 0x0, 0x3003E0A, 0x0, 0x3003E0D, 0x0, 0x3003E10, 0x0, 0x3003E13, 0x0, 0x3003E16, 0x0, 0x3003E19, 0x0, 0x3003E1C,
+	0x0, 0x3003E1F, 0x0, 0x3003E22, 0x0, 0x3003E25, 0x0, 0x3003E28, 0x0, 0x3003E2B, 0x0, 0x3003E2E, 0x0, 0x3003E31, 0x0, 0x3003E34,
+	0x0, 0x3003E37, 0x0, 0x3003E3A, 0x0, 0x3003E3D, 0x0, 0x3003E40, 0x0, 0x3003E43, 0x0, 0x3003E46, 0x0, 0x3003E49, 0x0, 0x3003E4C,
+	0x0, 0x3003E4F, 0x0, 0x3003E52, 0x0, 0x3003E55, 0x0, 0x3003E58, 0x0, 0x3003E5B, 0x0, 0x3003E5E, 0x0, 0x3003E61, 0x0, 0x3003E64,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003E67, 0x0, 0x3003E6A, 0x0, 0x0, 0x3003E6D,
+	0x0, 0x3003E70, 0x0, 0x3003E73, 0x0, 0x3003E76, 0x0, 0x3003E79, 0x0, 0x0, 0x0, 0x0, 0x3003E7C, 0x0, 0x0, 0x0,
+	0x0, 0x3003E7F, 0x0, 0x3003E82, 0x0, 0x0, 0x0, 0x3003E85, 0x0, 0x3003E88, 0x0, 0x3003E8B, 0x0, 0x3003E8E, 0x0, 0x3003E91,
+	0x0, 0x3003E94, 0x0, 0x3003E97, 0x0, 0x3003E9A, 0x0, 0x3003E9D, 0x0, 0x3003EA0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2004B02, 0x2004B04, 0x2004B06, 0x3004B08, 0x3004B0B, 0x2004B0E, 0x2004B0E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x4004B10, 0x4004B14, 0x4004B18, 0x4004B1C, 0x4004B20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003EC5, 0x3003EC8, 0x3003ECB, 0x3003ECE, 0x3003ED1, 0x3003ED4, 0x3003ED7, 0x3003EDA, 0x3003EDD, 0x3003EE0, 0x3003EE3, 0x3003EE6, 0x3003EE9, 0x3003EEC, 0x3003EEF,
+	0x3003EF2, 0x3003EF5, 0x3003EF8, 0x3003EFB, 0x3003EFE, 0x3003F01, 0x3003F04, 0x3003F07, 0x3003F0A, 0x3003F0D, 0x3003F10, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4003F13, 0x4003F17, 0x4003F1B, 0x4003F1F, 0x4003F23, 0x4003F27, 0x4003F2B, 0x4003F2F,
+	0x4003F33, 0x4003F37, 0x4003F3B, 0x4003F3F, 0x4003F43, 0x4003F47, 0x4003F4B, 0x4003F4F, 0x4003F53, 0x4003F57, 0x4003F5B, 0x4003F5F, 0x4003F63, 0x4003F67, 0x4003F6B, 0x4003F6F,
+	0x4003F73, 0x4003F77, 0x4003F7B, 0x4003F7F, 0x4003F83, 0x4003F87, 0x4003F8B, 0x4003F8F, 0x4003F93, 0x4003F97, 0x4003F9B, 0x4003F9F, 0x4003FA3, 0x4003FA7, 0x4003FAB, 0x4003FAF,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4003FB3, 0x4003FB7, 0x4003FBB, 0x4003FBF, 0x4003FC3, 0x4003FC7, 0x4003FCB, 0x4003FCF, 0x4003FD3, 0x4003FD7, 0x4003FDB, 0x4003FDF, 0x4003FE3, 0x4003FE7, 0x4003FEB, 0x4003FEF,
+	0x4003FF3, 0x4003FF7, 0x4003FFB, 0x4003FFF, 0x4004003, 0x4004007, 0x400400B, 0x400400F, 0x4004013, 0x4004017, 0x400401B, 0x400401F, 0x4004023, 0x4004027, 0x400402B, 0x400402F,
+};
+const uint32_t* TitlecaseDataPtr = TitlecaseData;
+
+const uint32_t CaseFoldingIndex1[272] = {
+	0, 128, 256, 384, 360, 360, 360, 360, 360, 360, 512, 360, 360, 360, 360, 640,
+	768, 896, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+};
+const uint32_t* CaseFoldingIndex1Ptr = CaseFoldingIndex1;
+
+const uint32_t CaseFoldingIndex2[1024] = {
+	0x0, 0x0, 0x20, 0x0, 0x0, 0x40, 0x60, 0x0, 0x80, 0xA0, 0xC0, 0xE0, 0x100, 0x120, 0x140, 0x160,
+	0x180, 0x1A0, 0x1C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1E0, 0x200, 0x220, 0x240, 0x260, 0x280,
+	0x2A0, 0x2C0, 0x0, 0x2E0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x0, 0x3E0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x400, 0x420, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x440, 0x460, 0x480, 0x4A0, 0x4C0, 0x4E0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5A0, 0x5C0, 0x5E0, 0x600, 0x620,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x640, 0x0, 0x660, 0x680, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x6A0, 0x6C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6E0, 0x700, 0x0, 0x720, 0x740, 0x760, 0x780, 0x7A0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x7C0, 0x7E0, 0x800, 0x0, 0x0, 0x0, 0x0, 0x820, 0x840, 0x860, 0x880, 0x8A0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8E0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x900, 0x920, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x940, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+};
+const uint32_t* CaseFoldingIndex2Ptr = CaseFoldingIndex2;
+
+const uint32_t CaseFoldingData[2400] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E,
+	0x1000754, 0x1002068, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x2001D29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2004033, 0x2004035, 0x2004037, 0x2004039, 0x200403B, 0x200403D, 0x2000247, 0x200403F, 0x2004041, 0x2004043, 0x2004045, 0x2004047, 0x2004049, 0x200404B, 0x200404D, 0x200404F,
+	0x2001E1E, 0x2004051, 0x2004053, 0x2004055, 0x2004057, 0x2004059, 0x200405B, 0x0, 0x2000294, 0x200405D, 0x200405F, 0x2004061, 0x2004063, 0x2004065, 0x2004067, 0x2004B24,
+	0x2004069, 0x0, 0x200406B, 0x0, 0x200406D, 0x0, 0x200406F, 0x0, 0x2004071, 0x0, 0x2004073, 0x0, 0x2004075, 0x0, 0x2004077, 0x0,
+	0x2004079, 0x0, 0x200407B, 0x0, 0x200407D, 0x0, 0x200407F, 0x0, 0x2004081, 0x0, 0x2004083, 0x0, 0x2004085, 0x0, 0x2004087, 0x0,
+	0x2004089, 0x0, 0x200408B, 0x0, 0x200408D, 0x0, 0x2001EF8, 0x0, 0x200408F, 0x0, 0x2004091, 0x0, 0x2004093, 0x0, 0x2004095, 0x0,
+	0x3004097, 0x0, 0x200409A, 0x0, 0x200409C, 0x0, 0x200409E, 0x0, 0x0, 0x20040A0, 0x0, 0x20040A2, 0x0, 0x20040A4, 0x0, 0x20040A6,
+	0x0, 0x20040A8, 0x0, 0x20040AA, 0x0, 0x20040AC, 0x0, 0x20040AE, 0x0, 0x3001D48, 0x2001E00, 0x0, 0x20040B0, 0x0, 0x20040B2, 0x0,
+	0x20040B4, 0x0, 0x2002CE5, 0x0, 0x20040B6, 0x0, 0x20040B8, 0x0, 0x20040BA, 0x0, 0x20040BC, 0x0, 0x20040BE, 0x0, 0x20040C0, 0x0,
+	0x20040C2, 0x0, 0x20040C4, 0x0, 0x20040C6, 0x0, 0x20040C8, 0x0, 0x20040CA, 0x0, 0x20040CC, 0x0, 0x20040CE, 0x0, 0x20040D0, 0x0,
+	0x20040D2, 0x0, 0x20040D4, 0x0, 0x20040D6, 0x0, 0x20040D8, 0x0, 0x20040DA, 0x20040DC, 0x0, 0x20040DE, 0x0, 0x20040E0, 0x0, 0x100017D,
+	0x0, 0x20040E2, 0x20040E4, 0x0, 0x20040E6, 0x0, 0x2001E02, 0x20040E8, 0x0, 0x20040EA, 0x20040EC, 0x20040EE, 0x0, 0x0, 0x20040F0, 0x2001DFA,
+	0x2001DFC, 0x20040F2, 0x0, 0x20040F4, 0x2001D7D, 0x0, 0x2001E28, 0x2001E26, 0x20040F6, 0x0, 0x0, 0x0, 0x2001E0D, 0x2001E3C, 0x0, 0x2001E42,
+	0x20040F8, 0x0, 0x20040FA, 0x0, 0x20040FC, 0x0, 0x20040FE, 0x2004100, 0x0, 0x2001E48, 0x0, 0x0, 0x2004102, 0x0, 0x2004104, 0x2004106,
+	0x0, 0x2001E4E, 0x2001E53, 0x2004108, 0x0, 0x200410A, 0x0, 0x200026B, 0x200410C, 0x0, 0x0, 0x0, 0x200410E, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x2004110, 0x2004110, 0x0, 0x2004112, 0x2004112, 0x0, 0x2004114, 0x2004114, 0x0, 0x2004116, 0x0, 0x2004118,
+	0x0, 0x200411A, 0x0, 0x200411C, 0x0, 0x200411E, 0x0, 0x2004120, 0x0, 0x2004122, 0x0, 0x2004124, 0x0, 0x0, 0x2004126, 0x0,
+	0x2004128, 0x0, 0x200412A, 0x0, 0x200412C, 0x0, 0x200412E, 0x0, 0x2004130, 0x0, 0x2004132, 0x0, 0x2004134, 0x0, 0x2004136, 0x0,
+	0x300026F, 0x2004138, 0x2004138, 0x0, 0x200413A, 0x0, 0x200413C, 0x200413E, 0x2004140, 0x0, 0x2004142, 0x0, 0x2004144, 0x0, 0x2004146, 0x0,
+	0x2004148, 0x0, 0x200414A, 0x0, 0x200414C, 0x0, 0x200414E, 0x0, 0x2004150, 0x0, 0x2004152, 0x0, 0x2004154, 0x0, 0x2004156, 0x0,
+	0x2004158, 0x0, 0x200415A, 0x0, 0x200415C, 0x0, 0x200415E, 0x0, 0x2004160, 0x0, 0x2004162, 0x0, 0x2004164, 0x0, 0x2004166, 0x0,
+	0x2004168, 0x0, 0x200416A, 0x0, 0x200416C, 0x0, 0x200416E, 0x0, 0x2004170, 0x0, 0x2004172, 0x0, 0x2004174, 0x0, 0x2004176, 0x0,
+	0x2004178, 0x0, 0x200417A, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300417C, 0x200417F, 0x0, 0x2004181, 0x3004183, 0x0,
+	0x0, 0x2004186, 0x0, 0x2004188, 0x2001E4C, 0x2001E55, 0x200418A, 0x0, 0x200418C, 0x0, 0x200418E, 0x0, 0x2004190, 0x0, 0x2004192, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x2000349, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2004194, 0x0, 0x2004196, 0x0, 0x0, 0x0, 0x2004198, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200419A,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200419C, 0x0, 0x200419E, 0x20041A0, 0x20041A2, 0x0, 0x20041A4, 0x0, 0x20041A6, 0x20041A8,
+	0x6000349, 0x2000357, 0x2001D89, 0x2001E12, 0x2001E14, 0x200035B, 0x2003369, 0x200035F, 0x2001D8B, 0x2000349, 0x2001D91, 0x200336B, 0x2001D29, 0x200336D, 0x200336F, 0x200036D,
+	0x2001D8F, 0x2000E17, 0x0, 0x2003371, 0x2003373, 0x2000367, 0x2001D8D, 0x2001E16, 0x2003375, 0x2000375, 0x20041AA, 0x20041AC, 0x0, 0x0, 0x0, 0x0,
+	0x6000367, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x2003371, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20041AE,
+	0x2001D89, 0x2001D8B, 0x0, 0x0, 0x0, 0x2001D8D, 0x2001D8F, 0x0, 0x20041B0, 0x0, 0x20041B2, 0x0, 0x200337C, 0x0, 0x20041B4, 0x0,
+	0x20041B6, 0x0, 0x20041B8, 0x0, 0x20041BA, 0x0, 0x20041BC, 0x0, 0x20041BE, 0x0, 0x20041C0, 0x0, 0x20041C2, 0x0, 0x20041C4, 0x0,
+	0x2001D91, 0x2000E17, 0x0, 0x0, 0x2001D8B, 0x200035B, 0x0, 0x20041C6, 0x0, 0x20041C8, 0x20041CA, 0x0, 0x0, 0x20041CC, 0x20041CE, 0x20041D0,
+	0x20041D2, 0x20041D4, 0x20041D6, 0x20041D8, 0x20041DA, 0x20041DC, 0x20003B1, 0x20041DE, 0x20041E0, 0x20041E2, 0x20041E4, 0x20041E6, 0x20041E8, 0x20041EA, 0x20041EC, 0x20041EE,
+	0x20003D5, 0x20041F0, 0x20041F2, 0x20003AD, 0x20041F4, 0x20003A5, 0x20003CD, 0x20003FD, 0x20003A1, 0x20041F6, 0x20003B5, 0x20041F8, 0x20041FA, 0x2001E18, 0x2000415, 0x20041FC,
+	0x20041FE, 0x2004200, 0x2004202, 0x20003BD, 0x2004204, 0x2004206, 0x2004208, 0x2000445, 0x200420A, 0x200420C, 0x2002CDC, 0x200044D, 0x2002CDE, 0x2000425, 0x200420E, 0x2004210,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2004212, 0x0, 0x2004214, 0x0, 0x2004216, 0x0, 0x2004218, 0x0, 0x200421A, 0x0, 0x200421C, 0x0, 0x200421E, 0x0, 0x2004220, 0x0,
+	0x2004222, 0x0, 0x2004224, 0x0, 0x20003C5, 0x0, 0x2004226, 0x0, 0x2004228, 0x0, 0x200422A, 0x0, 0x200422C, 0x0, 0x200422E, 0x0,
+	0x2004230, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004232, 0x0, 0x2004234, 0x0, 0x2004236, 0x0,
+	0x2004238, 0x0, 0x200423A, 0x0, 0x200423C, 0x0, 0x200423E, 0x0, 0x2004240, 0x0, 0x2004242, 0x0, 0x2004244, 0x0, 0x2004246, 0x0,
+	0x2004248, 0x0, 0x200424A, 0x0, 0x200424C, 0x0, 0x200424E, 0x0, 0x2004250, 0x0, 0x2004252, 0x0, 0x2004254, 0x0, 0x2004256, 0x0,
+	0x2004258, 0x0, 0x200425A, 0x0, 0x200425C, 0x0, 0x200425E, 0x0, 0x2004260, 0x0, 0x2004262, 0x0, 0x2004264, 0x0, 0x2004266, 0x0,
+	0x2004268, 0x200426A, 0x0, 0x200426C, 0x0, 0x200426E, 0x0, 0x2004270, 0x0, 0x2004272, 0x0, 0x2004274, 0x0, 0x2004276, 0x0, 0x0,
+	0x2004278, 0x0, 0x200427A, 0x0, 0x200427C, 0x0, 0x200427E, 0x0, 0x20003ED, 0x0, 0x2004280, 0x0, 0x2004282, 0x0, 0x2004284, 0x0,
+	0x2004286, 0x0, 0x2004288, 0x0, 0x200428A, 0x0, 0x200428C, 0x0, 0x200041D, 0x0, 0x200428E, 0x0, 0x2004290, 0x0, 0x2004292, 0x0,
+	0x2004294, 0x0, 0x2004296, 0x0, 0x2004298, 0x0, 0x200429A, 0x0, 0x200429C, 0x0, 0x200429E, 0x0, 0x20042A0, 0x0, 0x20042A2, 0x0,
+	0x20042A4, 0x0, 0x20042A6, 0x0, 0x20042A8, 0x0, 0x20042AA, 0x0, 0x20042AC, 0x0, 0x20042AE, 0x0, 0x20042B0, 0x0, 0x20042B2, 0x0,
+	0x20042B4, 0x0, 0x20042B6, 0x0, 0x20042B8, 0x0, 0x20042BA, 0x0, 0x20042BC, 0x0, 0x20042BE, 0x0, 0x20042C0, 0x0, 0x20042C2, 0x0,
+	0x20042C4, 0x0, 0x20042C6, 0x0, 0x20042C8, 0x0, 0x20042CA, 0x0, 0x20042CC, 0x0, 0x20042CE, 0x0, 0x20042D0, 0x0, 0x20042D2, 0x0,
+	0x0, 0x20042D4, 0x20042D6, 0x20042D8, 0x20042DA, 0x2001D99, 0x20042DC, 0x20042DE, 0x20042E0, 0x20042E2, 0x20042E4, 0x2002D0A, 0x20042E6, 0x2002D12, 0x20042E8, 0x20042EA,
+	0x20042EC, 0x20042EE, 0x20042F0, 0x20042F2, 0x2002D00, 0x20042F4, 0x2002D02, 0x20042F6, 0x20042F8, 0x20042FA, 0x20042FC, 0x20042FE, 0x2004300, 0x2004302, 0x2002D0C, 0x2004304,
+	0x2004306, 0x2004308, 0x2001D9B, 0x200430A, 0x200430C, 0x200430E, 0x2004310, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4001D99, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004312, 0x3004315, 0x3004318, 0x300431B, 0x300431E, 0x3004321, 0x3004324, 0x3004327, 0x300432A, 0x300432D, 0x3004330, 0x3004333, 0x3004336, 0x3004339, 0x300433C, 0x300433F,
+	0x3004342, 0x3004345, 0x3004348, 0x300434B, 0x300434E, 0x3004351, 0x3004354, 0x3004357, 0x300435A, 0x300435D, 0x3004360, 0x3004363, 0x3004366, 0x3004369, 0x300436C, 0x300436F,
+	0x3004372, 0x3004375, 0x3004378, 0x300437B, 0x300437E, 0x3004381, 0x0, 0x3004384, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004387, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300438A, 0x0, 0x300438D, 0x0, 0x3004390, 0x0, 0x3004393, 0x0, 0x3004396, 0x0, 0x3004399, 0x0, 0x300439C, 0x0, 0x300439F, 0x0,
+	0x30043A2, 0x0, 0x30043A5, 0x0, 0x30043A8, 0x0, 0x30043AB, 0x0, 0x30043AE, 0x0, 0x30043B1, 0x0, 0x30043B4, 0x0, 0x30043B7, 0x0,
+	0x30043BA, 0x0, 0x30043BD, 0x0, 0x30043C0, 0x0, 0x30043C3, 0x0, 0x30043C6, 0x0, 0x30043C9, 0x0, 0x30043CC, 0x0, 0x30043CF, 0x0,
+	0x30043D2, 0x0, 0x30043D5, 0x0, 0x30043D8, 0x0, 0x30043DB, 0x0, 0x30043DE, 0x0, 0x30043E1, 0x0, 0x30043E4, 0x0, 0x30043E7, 0x0,
+	0x30043EA, 0x0, 0x30043ED, 0x0, 0x30043F0, 0x0, 0x30043F3, 0x0, 0x30043F6, 0x0, 0x30043F9, 0x0, 0x30043FC, 0x0, 0x30043FF, 0x0,
+	0x3004402, 0x0, 0x3004405, 0x0, 0x3004408, 0x0, 0x300440B, 0x0, 0x300440E, 0x0, 0x3004411, 0x0, 0x3004414, 0x0, 0x3004417, 0x0,
+	0x300441A, 0x0, 0x300441D, 0x0, 0x3004420, 0x0, 0x3004423, 0x0, 0x3004426, 0x0, 0x3004429, 0x0, 0x300442C, 0x0, 0x300442F, 0x0,
+	0x3004432, 0x0, 0x3004435, 0x0, 0x3004438, 0x0, 0x300443B, 0x0, 0x300443E, 0x0, 0x3004441, 0x0, 0x3004444, 0x0, 0x3004447, 0x0,
+	0x300444A, 0x0, 0x300444D, 0x0, 0x3004450, 0x0, 0x3004453, 0x0, 0x3004456, 0x0, 0x3004459, 0x0, 0x300445C, 0x0, 0x300445F, 0x0,
+	0x3004462, 0x0, 0x3004465, 0x0, 0x3004468, 0x0, 0x300082F, 0x3000832, 0x3000835, 0x3000838, 0x3001E5B, 0x300441A, 0x0, 0x0, 0x2004B24, 0x0,
+	0x300446D, 0x0, 0x3004470, 0x0, 0x3004473, 0x0, 0x3004476, 0x0, 0x3004479, 0x0, 0x300447C, 0x0, 0x300447F, 0x0, 0x3004482, 0x0,
+	0x3004485, 0x0, 0x3004488, 0x0, 0x300448B, 0x0, 0x300448E, 0x0, 0x3004491, 0x0, 0x3004494, 0x0, 0x3004497, 0x0, 0x300449A, 0x0,
+	0x300449D, 0x0, 0x30044A0, 0x0, 0x30044A3, 0x0, 0x30044A6, 0x0, 0x30044A9, 0x0, 0x30044AC, 0x0, 0x30044AF, 0x0, 0x30044B2, 0x0,
+	0x30044B5, 0x0, 0x30044B8, 0x0, 0x30044BB, 0x0, 0x30044BE, 0x0, 0x30044C1, 0x0, 0x30044C4, 0x0, 0x30044C7, 0x0, 0x30044CA, 0x0,
+	0x30044CD, 0x0, 0x30044D0, 0x0, 0x30044D3, 0x0, 0x30044D6, 0x0, 0x30044D9, 0x0, 0x30044DC, 0x0, 0x30044DF, 0x0, 0x30044E2, 0x0,
+	0x30044E5, 0x0, 0x30044E8, 0x0, 0x30044EB, 0x0, 0x30044EE, 0x0, 0x30044F1, 0x0, 0x30044F4, 0x0, 0x30044F7, 0x0, 0x30044FA, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30044FD, 0x3004500, 0x3004503, 0x3004506, 0x3004509, 0x300450C, 0x300450F, 0x3004512,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004515, 0x3004518, 0x300451B, 0x300451E, 0x3004521, 0x3004524, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004527, 0x300452A, 0x300452D, 0x3004530, 0x3004533, 0x3004536, 0x3004539, 0x300453C,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300453F, 0x3004542, 0x3004545, 0x3004548, 0x300454B, 0x300454E, 0x3004551, 0x3004554,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004557, 0x300455A, 0x300455D, 0x3004560, 0x3004563, 0x3004566, 0x0, 0x0,
+	0x4000B4D, 0x0, 0x6000B55, 0x0, 0x6000B61, 0x0, 0x6000B6D, 0x0, 0x0, 0x3004569, 0x0, 0x300456C, 0x0, 0x300456F, 0x0, 0x3004572,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004575, 0x3004578, 0x300457B, 0x300457E, 0x3004581, 0x3004584, 0x3004587, 0x300458A,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x5004B26, 0x5004B2B, 0x5004B30, 0x5004B35, 0x5004B3A, 0x5004B3F, 0x5004B44, 0x5004B49, 0x5004B26, 0x5004B2B, 0x5004B30, 0x5004B35, 0x5004B3A, 0x5004B3F, 0x5004B44, 0x5004B49,
+	0x5004B4E, 0x5004B53, 0x5004B58, 0x5004B5D, 0x5004B62, 0x5004B67, 0x5004B6C, 0x5004B71, 0x5004B4E, 0x5004B53, 0x5004B58, 0x5004B5D, 0x5004B62, 0x5004B67, 0x5004B6C, 0x5004B71,
+	0x5004B76, 0x5004B7B, 0x5004B80, 0x5004B85, 0x5004B8A, 0x5004B8F, 0x5004B94, 0x5004B99, 0x5004B76, 0x5004B7B, 0x5004B80, 0x5004B85, 0x5004B8A, 0x5004B8F, 0x5004B94, 0x5004B99,
+	0x0, 0x0, 0x5004B9E, 0x4004BA3, 0x4004BA7, 0x0, 0x4000D83, 0x6004BAB, 0x30045D5, 0x30045D8, 0x30045DB, 0x30045DE, 0x4004BA3, 0x0, 0x2000349, 0x0,
+	0x0, 0x0, 0x5004BB1, 0x4004BB6, 0x4004BBA, 0x0, 0x4000DB1, 0x6004BBE, 0x30045E4, 0x30045E7, 0x30045EA, 0x30045ED, 0x4004BB6, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x6000DDE, 0x6000349, 0x0, 0x0, 0x4000DE4, 0x6000DE8, 0x30045F3, 0x30045F6, 0x30045F9, 0x30045FC, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x6000E11, 0x6000367, 0x4000E17, 0x0, 0x4000E1F, 0x6000E23, 0x30045FF, 0x3004602, 0x3004605, 0x3004608, 0x300460B, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x5004BC4, 0x4004BC9, 0x4004BCD, 0x0, 0x4000E4E, 0x6004BD1, 0x300460E, 0x3004611, 0x3004614, 0x3004617, 0x4004BC9, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000375, 0x0, 0x0, 0x0, 0x100012F, 0x200403D, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x300461D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004620, 0x3004623, 0x3004626, 0x3004629, 0x300462C, 0x300462F, 0x3004632, 0x3004635, 0x3004638, 0x300463B, 0x300463E, 0x3004641, 0x3004644, 0x3004647, 0x300464A, 0x300464D,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3004650, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004653, 0x3004656, 0x3004659, 0x300465C, 0x300465F, 0x3004662, 0x3004665, 0x3004668, 0x300466B, 0x300466E,
+	0x3004671, 0x3004674, 0x3004677, 0x300467A, 0x300467D, 0x3004680, 0x3004683, 0x3004686, 0x3004689, 0x300468C, 0x300468F, 0x3004692, 0x3004695, 0x3004698, 0x300469B, 0x300469E,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30046A1, 0x30046A4, 0x30046A7, 0x30046AA, 0x30046AD, 0x30046B0, 0x30046B3, 0x30046B6, 0x30046B9, 0x30046BC, 0x30046BF, 0x30046C2, 0x30046C5, 0x30046C8, 0x30046CB, 0x30046CE,
+	0x30046D1, 0x30046D4, 0x30046D7, 0x30046DA, 0x30046DD, 0x30046E0, 0x30046E3, 0x30046E6, 0x30046E9, 0x30046EC, 0x30046EF, 0x30046F2, 0x30046F5, 0x30046F8, 0x30046FB, 0x30046FE,
+	0x3004701, 0x3004704, 0x3004707, 0x300470A, 0x300470D, 0x3004710, 0x3004713, 0x3004716, 0x3004719, 0x300471C, 0x300471F, 0x3004722, 0x3004725, 0x3004728, 0x300472B, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300472E, 0x0, 0x2002CED, 0x3004731, 0x2004734, 0x0, 0x0, 0x3004736, 0x0, 0x3004739, 0x0, 0x300473C, 0x0, 0x2001DF5, 0x2001E38, 0x2001DF3,
+	0x2001E1A, 0x0, 0x300473F, 0x0, 0x0, 0x3004742, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004745, 0x2004747,
+	0x3004749, 0x0, 0x300474C, 0x0, 0x300474F, 0x0, 0x3004752, 0x0, 0x3004755, 0x0, 0x3004758, 0x0, 0x300475B, 0x0, 0x300475E, 0x0,
+	0x3004761, 0x0, 0x3004764, 0x0, 0x3004767, 0x0, 0x300476A, 0x0, 0x300476D, 0x0, 0x3004770, 0x0, 0x3004773, 0x0, 0x3004776, 0x0,
+	0x3004779, 0x0, 0x300477C, 0x0, 0x300477F, 0x0, 0x3004782, 0x0, 0x3004785, 0x0, 0x3004788, 0x0, 0x300478B, 0x0, 0x300478E, 0x0,
+	0x3004791, 0x0, 0x3004794, 0x0, 0x3004797, 0x0, 0x300479A, 0x0, 0x300479D, 0x0, 0x30047A0, 0x0, 0x30047A3, 0x0, 0x30047A6, 0x0,
+	0x30047A9, 0x0, 0x30047AC, 0x0, 0x30047AF, 0x0, 0x30047B2, 0x0, 0x30047B5, 0x0, 0x30047B8, 0x0, 0x30047BB, 0x0, 0x30047BE, 0x0,
+	0x30047C1, 0x0, 0x30047C4, 0x0, 0x30047C7, 0x0, 0x30047CA, 0x0, 0x30047CD, 0x0, 0x30047D0, 0x0, 0x30047D3, 0x0, 0x30047D6, 0x0,
+	0x30047D9, 0x0, 0x30047DC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30047DF, 0x0, 0x30047E2, 0x0, 0x0,
+	0x0, 0x0, 0x30047E5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30047E8, 0x0, 0x30047EB, 0x0, 0x30047EE, 0x0, 0x30047F1, 0x0, 0x30047F4, 0x0, 0x30047F7, 0x0, 0x30047FA, 0x0, 0x30047FD, 0x0,
+	0x3004800, 0x0, 0x3004803, 0x0, 0x3004806, 0x0, 0x3004809, 0x0, 0x300480C, 0x0, 0x300480F, 0x0, 0x3004812, 0x0, 0x3004815, 0x0,
+	0x3004818, 0x0, 0x300481B, 0x0, 0x300481E, 0x0, 0x3004821, 0x0, 0x3004824, 0x0, 0x3004827, 0x0, 0x300482A, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300482D, 0x0, 0x3004830, 0x0, 0x3004833, 0x0, 0x3004836, 0x0, 0x3004839, 0x0, 0x300483C, 0x0, 0x300483F, 0x0, 0x3004842, 0x0,
+	0x3004845, 0x0, 0x3004848, 0x0, 0x300484B, 0x0, 0x300484E, 0x0, 0x3004851, 0x0, 0x3004854, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x3004857, 0x0, 0x300485A, 0x0, 0x3002CE7, 0x0, 0x300485D, 0x0, 0x3004860, 0x0, 0x3004863, 0x0, 0x3004866, 0x0,
+	0x0, 0x0, 0x3004869, 0x0, 0x300486C, 0x0, 0x300486F, 0x0, 0x3004872, 0x0, 0x3004875, 0x0, 0x3004878, 0x0, 0x300487B, 0x0,
+	0x300487E, 0x0, 0x3004881, 0x0, 0x3004884, 0x0, 0x3004887, 0x0, 0x300488A, 0x0, 0x300488D, 0x0, 0x3004890, 0x0, 0x3004893, 0x0,
+	0x3004896, 0x0, 0x3004899, 0x0, 0x300489C, 0x0, 0x300489F, 0x0, 0x30048A2, 0x0, 0x30048A5, 0x0, 0x30048A8, 0x0, 0x30048AB, 0x0,
+	0x30048AE, 0x0, 0x30048B1, 0x0, 0x30048B4, 0x0, 0x30048B7, 0x0, 0x30048BA, 0x0, 0x30048BD, 0x0, 0x30048C0, 0x0, 0x3002CE0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30048C3, 0x0, 0x30048C6, 0x0, 0x30048C9, 0x30048CC, 0x0,
+	0x30048CF, 0x0, 0x30048D2, 0x0, 0x30048D5, 0x0, 0x30048D8, 0x0, 0x0, 0x0, 0x0, 0x30048DB, 0x0, 0x2001E24, 0x0, 0x0,
+	0x30048DE, 0x0, 0x30048E1, 0x0, 0x0, 0x0, 0x30048E4, 0x0, 0x30048E7, 0x0, 0x30048EA, 0x0, 0x30048ED, 0x0, 0x30048F0, 0x0,
+	0x30048F3, 0x0, 0x30048F6, 0x0, 0x30048F9, 0x0, 0x30048FC, 0x0, 0x30048FF, 0x0, 0x2001D63, 0x2001DFE, 0x2001E22, 0x2004902, 0x0, 0x0,
+	0x2004904, 0x2004906, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2002CF2, 0x2002CF4, 0x2002CF6, 0x3002CF8, 0x3002CFB, 0x2002CFE, 0x2002CFE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x4002D00, 0x4002D04, 0x4002D08, 0x4002D0C, 0x4002D10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3004908, 0x300490B, 0x300490E, 0x3004911, 0x3004914, 0x3004917, 0x300491A, 0x300491D, 0x3004920, 0x3004923, 0x3004926, 0x3004929, 0x300492C, 0x300492F, 0x3004932,
+	0x3004935, 0x3004938, 0x300493B, 0x300493E, 0x3004941, 0x3004944, 0x3004947, 0x300494A, 0x300494D, 0x3004950, 0x3004953, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4004956, 0x400495A, 0x400495E, 0x4004962, 0x4004966, 0x400496A, 0x400496E, 0x4004972, 0x4004976, 0x400497A, 0x400497E, 0x4004982, 0x4004986, 0x400498A, 0x400498E, 0x4004992,
+	0x4004996, 0x400499A, 0x400499E, 0x40049A2, 0x40049A6, 0x40049AA, 0x40049AE, 0x40049B2, 0x40049B6, 0x40049BA, 0x40049BE, 0x40049C2, 0x40049C6, 0x40049CA, 0x40049CE, 0x40049D2,
+	0x40049D6, 0x40049DA, 0x40049DE, 0x40049E2, 0x40049E6, 0x40049EA, 0x40049EE, 0x40049F2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x40049F6, 0x40049FA, 0x40049FE, 0x4004A02, 0x4004A06, 0x4004A0A, 0x4004A0E, 0x4004A12, 0x4004A16, 0x4004A1A, 0x4004A1E, 0x4004A22, 0x4004A26, 0x4004A2A, 0x4004A2E, 0x4004A32,
+	0x4004A36, 0x4004A3A, 0x4004A3E, 0x4004A42, 0x4004A46, 0x4004A4A, 0x4004A4E, 0x4004A52, 0x4004A56, 0x4004A5A, 0x4004A5E, 0x4004A62, 0x4004A66, 0x4004A6A, 0x4004A6E, 0x4004A72,
+};
+const uint32_t* CaseFoldingDataPtr = CaseFoldingData;
+
+const size_t UnicodeCompositionRecordCount = 940;
+const CompositionRecord UnicodeCompositionRecord[940] = {
+	{ 0x3c00000338, 0x226e }, { 0x3d00000338, 0x2260 }, { 0x3e00000338, 0x226f }, { 0x4100000300, 0xc0 },
+	{ 0x4100000301, 0xc1 }, { 0x4100000302, 0xc2 }, { 0x4100000303, 0xc3 }, { 0x4100000304, 0x100 },
+	{ 0x4100000306, 0x102 }, { 0x4100000307, 0x226 }, { 0x4100000308, 0xc4 }, { 0x4100000309, 0x1ea2 },
+	{ 0x410000030a, 0xc5 }, { 0x410000030c, 0x1cd }, { 0x410000030f, 0x200 }, { 0x4100000311, 0x202 },
+	{ 0x4100000323, 0x1ea0 }, { 0x4100000325, 0x1e00 }, { 0x4100000328, 0x104 }, { 0x4200000307, 0x1e02 },
+	{ 0x4200000323, 0x1e04 }, { 0x4200000331, 0x1e06 }, { 0x4300000301, 0x106 }, { 0x4300000302, 0x108 },
+	{ 0x4300000307, 0x10a }, { 0x430000030c, 0x10c }, { 0x4300000327, 0xc7 }, { 0x4400000307, 0x1e0a },
+	{ 0x440000030c, 0x10e }, { 0x4400000323, 0x1e0c }, { 0x4400000327, 0x1e10 }, { 0x440000032d, 0x1e12 },
+	{ 0x4400000331, 0x1e0e }, { 0x4500000300, 0xc8 }, { 0x4500000301, 0xc9 }, { 0x4500000302, 0xca },
+	{ 0x4500000303, 0x1ebc }, { 0x4500000304, 0x112 }, { 0x4500000306, 0x114 }, { 0x4500000307, 0x116 },
+	{ 0x4500000308, 0xcb }, { 0x4500000309, 0x1eba }, { 0x450000030c, 0x11a }, { 0x450000030f, 0x204 },
+	{ 0x4500000311, 0x206 }, { 0x4500000323, 0x1eb8 }, { 0x4500000327, 0x228 }, { 0x4500000328, 0x118 },
+	{ 0x450000032d, 0x1e18 }, { 0x4500000330, 0x1e1a }, { 0x4600000307, 0x1e1e }, { 0x4700000301, 0x1f4 },
+	{ 0x4700000302, 0x11c }, { 0x4700000304, 0x1e20 }, { 0x4700000306, 0x11e }, { 0x4700000307, 0x120 },
+	{ 0x470000030c, 0x1e6 }, { 0x4700000327, 0x122 }, { 0x4800000302, 0x124 }, { 0x4800000307, 0x1e22 },
+	{ 0x4800000308, 0x1e26 }, { 0x480000030c, 0x21e }, { 0x4800000323, 0x1e24 }, { 0x4800000327, 0x1e28 },
+	{ 0x480000032e, 0x1e2a }, { 0x4900000300, 0xcc }, { 0x4900000301, 0xcd }, { 0x4900000302, 0xce },
+	{ 0x4900000303, 0x128 }, { 0x4900000304, 0x12a }, { 0x4900000306, 0x12c }, { 0x4900000307, 0x130 },
+	{ 0x4900000308, 0xcf }, { 0x4900000309, 0x1ec8 }, { 0x490000030c, 0x1cf }, { 0x490000030f, 0x208 },
+	{ 0x4900000311, 0x20a }, { 0x4900000323, 0x1eca }, { 0x4900000328, 0x12e }, { 0x4900000330, 0x1e2c },
+	{ 0x4a00000302, 0x134 }, { 0x4b00000301, 0x1e30 }, { 0x4b0000030c, 0x1e8 }, { 0x4b00000323, 0x1e32 },
+	{ 0x4b00000327, 0x136 }, { 0x4b00000331, 0x1e34 }, { 0x4c00000301, 0x139 }, { 0x4c0000030c, 0x13d },
+	{ 0x4c00000323, 0x1e36 }, { 0x4c00000327, 0x13b }, { 0x4c0000032d, 0x1e3c }, { 0x4c00000331, 0x1e3a },
+	{ 0x4d00000301, 0x1e3e }, { 0x4d00000307, 0x1e40 }, { 0x4d00000323, 0x1e42 }, { 0x4e00000300, 0x1f8 },
+	{ 0x4e00000301, 0x143 }, { 0x4e00000303, 0xd1 }, { 0x4e00000307, 0x1e44 }, { 0x4e0000030c, 0x147 },
+	{ 0x4e00000323, 0x1e46 }, { 0x4e00000327, 0x145 }, { 0x4e0000032d, 0x1e4a }, { 0x4e00000331, 0x1e48 },
+	{ 0x4f00000300, 0xd2 }, { 0x4f00000301, 0xd3 }, { 0x4f00000302, 0xd4 }, { 0x4f00000303, 0xd5 },
+	{ 0x4f00000304, 0x14c }, { 0x4f00000306, 0x14e }, { 0x4f00000307, 0x22e }, { 0x4f00000308, 0xd6 },
+	{ 0x4f00000309, 0x1ece }, { 0x4f0000030b, 0x150 }, { 0x4f0000030c, 0x1d1 }, { 0x4f0000030f, 0x20c },
+	{ 0x4f00000311, 0x20e }, { 0x4f0000031b, 0x1a0 }, { 0x4f00000323, 0x1ecc }, { 0x4f00000328, 0x1ea },
+	{ 0x5000000301, 0x1e54 }, { 0x5000000307, 0x1e56 }, { 0x5200000301, 0x154 }, { 0x5200000307, 0x1e58 },
+	{ 0x520000030c, 0x158 }, { 0x520000030f, 0x210 }, { 0x5200000311, 0x212 }, { 0x5200000323, 0x1e5a },
+	{ 0x5200000327, 0x156 }, { 0x5200000331, 0x1e5e }, { 0x5300000301, 0x15a }, { 0x5300000302, 0x15c },
+	{ 0x5300000307, 0x1e60 }, { 0x530000030c, 0x160 }, { 0x5300000323, 0x1e62 }, { 0x5300000326, 0x218 },
+	{ 0x5300000327, 0x15e }, { 0x5400000307, 0x1e6a }, { 0x540000030c, 0x164 }, { 0x5400000323, 0x1e6c },
+	{ 0x5400000326, 0x21a }, { 0x5400000327, 0x162 }, { 0x540000032d, 0x1e70 }, { 0x5400000331, 0x1e6e },
+	{ 0x5500000300, 0xd9 }, { 0x5500000301, 0xda }, { 0x5500000302, 0xdb }, { 0x5500000303, 0x168 },
+	{ 0x5500000304, 0x16a }, { 0x5500000306, 0x16c }, { 0x5500000308, 0xdc }, { 0x5500000309, 0x1ee6 },
+	{ 0x550000030a, 0x16e }, { 0x550000030b, 0x170 }, { 0x550000030c, 0x1d3 }, { 0x550000030f, 0x214 },
+	{ 0x5500000311, 0x216 }, { 0x550000031b, 0x1af }, { 0x5500000323, 0x1ee4 }, { 0x5500000324, 0x1e72 },
+	{ 0x5500000328, 0x172 }, { 0x550000032d, 0x1e76 }, { 0x5500000330, 0x1e74 }, { 0x5600000303, 0x1e7c },
+	{ 0x5600000323, 0x1e7e }, { 0x5700000300, 0x1e80 }, { 0x5700000301, 0x1e82 }, { 0x5700000302, 0x174 },
+	{ 0x5700000307, 0x1e86 }, { 0x5700000308, 0x1e84 }, { 0x5700000323, 0x1e88 }, { 0x5800000307, 0x1e8a },
+	{ 0x5800000308, 0x1e8c }, { 0x5900000300, 0x1ef2 }, { 0x5900000301, 0xdd }, { 0x5900000302, 0x176 },
+	{ 0x5900000303, 0x1ef8 }, { 0x5900000304, 0x232 }, { 0x5900000307, 0x1e8e }, { 0x5900000308, 0x178 },
+	{ 0x5900000309, 0x1ef6 }, { 0x5900000323, 0x1ef4 }, { 0x5a00000301, 0x179 }, { 0x5a00000302, 0x1e90 },
+	{ 0x5a00000307, 0x17b }, { 0x5a0000030c, 0x17d }, { 0x5a00000323, 0x1e92 }, { 0x5a00000331, 0x1e94 },
+	{ 0x6100000300, 0xe0 }, { 0x6100000301, 0xe1 }, { 0x6100000302, 0xe2 }, { 0x6100000303, 0xe3 },
+	{ 0x6100000304, 0x101 }, { 0x6100000306, 0x103 }, { 0x6100000307, 0x227 }, { 0x6100000308, 0xe4 },
+	{ 0x6100000309, 0x1ea3 }, { 0x610000030a, 0xe5 }, { 0x610000030c, 0x1ce }, { 0x610000030f, 0x201 },
+	{ 0x6100000311, 0x203 }, { 0x6100000323, 0x1ea1 }, { 0x6100000325, 0x1e01 }, { 0x6100000328, 0x105 },
+	{ 0x6200000307, 0x1e03 }, { 0x6200000323, 0x1e05 }, { 0x6200000331, 0x1e07 }, { 0x6300000301, 0x107 },
+	{ 0x6300000302, 0x109 }, { 0x6300000307, 0x10b }, { 0x630000030c, 0x10d }, { 0x6300000327, 0xe7 },
+	{ 0x6400000307, 0x1e0b }, { 0x640000030c, 0x10f }, { 0x6400000323, 0x1e0d }, { 0x6400000327, 0x1e11 },
+	{ 0x640000032d, 0x1e13 }, { 0x6400000331, 0x1e0f }, { 0x6500000300, 0xe8 }, { 0x6500000301, 0xe9 },
+	{ 0x6500000302, 0xea }, { 0x6500000303, 0x1ebd }, { 0x6500000304, 0x113 }, { 0x6500000306, 0x115 },
+	{ 0x6500000307, 0x117 }, { 0x6500000308, 0xeb }, { 0x6500000309, 0x1ebb }, { 0x650000030c, 0x11b },
+	{ 0x650000030f, 0x205 }, { 0x6500000311, 0x207 }, { 0x6500000323, 0x1eb9 }, { 0x6500000327, 0x229 },
+	{ 0x6500000328, 0x119 }, { 0x650000032d, 0x1e19 }, { 0x6500000330, 0x1e1b }, { 0x6600000307, 0x1e1f },
+	{ 0x6700000301, 0x1f5 }, { 0x6700000302, 0x11d }, { 0x6700000304, 0x1e21 }, { 0x6700000306, 0x11f },
+	{ 0x6700000307, 0x121 }, { 0x670000030c, 0x1e7 }, { 0x6700000327, 0x123 }, { 0x6800000302, 0x125 },
+	{ 0x6800000307, 0x1e23 }, { 0x6800000308, 0x1e27 }, { 0x680000030c, 0x21f }, { 0x6800000323, 0x1e25 },
+	{ 0x6800000327, 0x1e29 }, { 0x680000032e, 0x1e2b }, { 0x6800000331, 0x1e96 }, { 0x6900000300, 0xec },
+	{ 0x6900000301, 0xed }, { 0x6900000302, 0xee }, { 0x6900000303, 0x129 }, { 0x6900000304, 0x12b },
+	{ 0x6900000306, 0x12d }, { 0x6900000308, 0xef }, { 0x6900000309, 0x1ec9 }, { 0x690000030c, 0x1d0 },
+	{ 0x690000030f, 0x209 }, { 0x6900000311, 0x20b }, { 0x6900000323, 0x1ecb }, { 0x6900000328, 0x12f },
+	{ 0x6900000330, 0x1e2d }, { 0x6a00000302, 0x135 }, { 0x6a0000030c, 0x1f0 }, { 0x6b00000301, 0x1e31 },
+	{ 0x6b0000030c, 0x1e9 }, { 0x6b00000323, 0x1e33 }, { 0x6b00000327, 0x137 }, { 0x6b00000331, 0x1e35 },
+	{ 0x6c00000301, 0x13a }, { 0x6c0000030c, 0x13e }, { 0x6c00000323, 0x1e37 }, { 0x6c00000327, 0x13c },
+	{ 0x6c0000032d, 0x1e3d }, { 0x6c00000331, 0x1e3b }, { 0x6d00000301, 0x1e3f }, { 0x6d00000307, 0x1e41 },
+	{ 0x6d00000323, 0x1e43 }, { 0x6e00000300, 0x1f9 }, { 0x6e00000301, 0x144 }, { 0x6e00000303, 0xf1 },
+	{ 0x6e00000307, 0x1e45 }, { 0x6e0000030c, 0x148 }, { 0x6e00000323, 0x1e47 }, { 0x6e00000327, 0x146 },
+	{ 0x6e0000032d, 0x1e4b }, { 0x6e00000331, 0x1e49 }, { 0x6f00000300, 0xf2 }, { 0x6f00000301, 0xf3 },
+	{ 0x6f00000302, 0xf4 }, { 0x6f00000303, 0xf5 }, { 0x6f00000304, 0x14d }, { 0x6f00000306, 0x14f },
+	{ 0x6f00000307, 0x22f }, { 0x6f00000308, 0xf6 }, { 0x6f00000309, 0x1ecf }, { 0x6f0000030b, 0x151 },
+	{ 0x6f0000030c, 0x1d2 }, { 0x6f0000030f, 0x20d }, { 0x6f00000311, 0x20f }, { 0x6f0000031b, 0x1a1 },
+	{ 0x6f00000323, 0x1ecd }, { 0x6f00000328, 0x1eb }, { 0x7000000301, 0x1e55 }, { 0x7000000307, 0x1e57 },
+	{ 0x7200000301, 0x155 }, { 0x7200000307, 0x1e59 }, { 0x720000030c, 0x159 }, { 0x720000030f, 0x211 },
+	{ 0x7200000311, 0x213 }, { 0x7200000323, 0x1e5b }, { 0x7200000327, 0x157 }, { 0x7200000331, 0x1e5f },
+	{ 0x7300000301, 0x15b }, { 0x7300000302, 0x15d }, { 0x7300000307, 0x1e61 }, { 0x730000030c, 0x161 },
+	{ 0x7300000323, 0x1e63 }, { 0x7300000326, 0x219 }, { 0x7300000327, 0x15f }, { 0x7400000307, 0x1e6b },
+	{ 0x7400000308, 0x1e97 }, { 0x740000030c, 0x165 }, { 0x7400000323, 0x1e6d }, { 0x7400000326, 0x21b },
+	{ 0x7400000327, 0x163 }, { 0x740000032d, 0x1e71 }, { 0x7400000331, 0x1e6f }, { 0x7500000300, 0xf9 },
+	{ 0x7500000301, 0xfa }, { 0x7500000302, 0xfb }, { 0x7500000303, 0x169 }, { 0x7500000304, 0x16b },
+	{ 0x7500000306, 0x16d }, { 0x7500000308, 0xfc }, { 0x7500000309, 0x1ee7 }, { 0x750000030a, 0x16f },
+	{ 0x750000030b, 0x171 }, { 0x750000030c, 0x1d4 }, { 0x750000030f, 0x215 }, { 0x7500000311, 0x217 },
+	{ 0x750000031b, 0x1b0 }, { 0x7500000323, 0x1ee5 }, { 0x7500000324, 0x1e73 }, { 0x7500000328, 0x173 },
+	{ 0x750000032d, 0x1e77 }, { 0x7500000330, 0x1e75 }, { 0x7600000303, 0x1e7d }, { 0x7600000323, 0x1e7f },
+	{ 0x7700000300, 0x1e81 }, { 0x7700000301, 0x1e83 }, { 0x7700000302, 0x175 }, { 0x7700000307, 0x1e87 },
+	{ 0x7700000308, 0x1e85 }, { 0x770000030a, 0x1e98 }, { 0x7700000323, 0x1e89 }, { 0x7800000307, 0x1e8b },
+	{ 0x7800000308, 0x1e8d }, { 0x7900000300, 0x1ef3 }, { 0x7900000301, 0xfd }, { 0x7900000302, 0x177 },
+	{ 0x7900000303, 0x1ef9 }, { 0x7900000304, 0x233 }, { 0x7900000307, 0x1e8f }, { 0x7900000308, 0xff },
+	{ 0x7900000309, 0x1ef7 }, { 0x790000030a, 0x1e99 }, { 0x7900000323, 0x1ef5 }, { 0x7a00000301, 0x17a },
+	{ 0x7a00000302, 0x1e91 }, { 0x7a00000307, 0x17c }, { 0x7a0000030c, 0x17e }, { 0x7a00000323, 0x1e93 },
+	{ 0x7a00000331, 0x1e95 }, { 0xa800000300, 0x1fed }, { 0xa800000301, 0x385 }, { 0xa800000342, 0x1fc1 },
+	{ 0xc200000300, 0x1ea6 }, { 0xc200000301, 0x1ea4 }, { 0xc200000303, 0x1eaa }, { 0xc200000309, 0x1ea8 },
+	{ 0xc400000304, 0x1de }, { 0xc500000301, 0x1fa }, { 0xc600000301, 0x1fc }, { 0xc600000304, 0x1e2 },
+	{ 0xc700000301, 0x1e08 }, { 0xca00000300, 0x1ec0 }, { 0xca00000301, 0x1ebe }, { 0xca00000303, 0x1ec4 },
+	{ 0xca00000309, 0x1ec2 }, { 0xcf00000301, 0x1e2e }, { 0xd400000300, 0x1ed2 }, { 0xd400000301, 0x1ed0 },
+	{ 0xd400000303, 0x1ed6 }, { 0xd400000309, 0x1ed4 }, { 0xd500000301, 0x1e4c }, { 0xd500000304, 0x22c },
+	{ 0xd500000308, 0x1e4e }, { 0xd600000304, 0x22a }, { 0xd800000301, 0x1fe }, { 0xdc00000300, 0x1db },
+	{ 0xdc00000301, 0x1d7 }, { 0xdc00000304, 0x1d5 }, { 0xdc0000030c, 0x1d9 }, { 0xe200000300, 0x1ea7 },
+	{ 0xe200000301, 0x1ea5 }, { 0xe200000303, 0x1eab }, { 0xe200000309, 0x1ea9 }, { 0xe400000304, 0x1df },
+	{ 0xe500000301, 0x1fb }, { 0xe600000301, 0x1fd }, { 0xe600000304, 0x1e3 }, { 0xe700000301, 0x1e09 },
+	{ 0xea00000300, 0x1ec1 }, { 0xea00000301, 0x1ebf }, { 0xea00000303, 0x1ec5 }, { 0xea00000309, 0x1ec3 },
+	{ 0xef00000301, 0x1e2f }, { 0xf400000300, 0x1ed3 }, { 0xf400000301, 0x1ed1 }, { 0xf400000303, 0x1ed7 },
+	{ 0xf400000309, 0x1ed5 }, { 0xf500000301, 0x1e4d }, { 0xf500000304, 0x22d }, { 0xf500000308, 0x1e4f },
+	{ 0xf600000304, 0x22b }, { 0xf800000301, 0x1ff }, { 0xfc00000300, 0x1dc }, { 0xfc00000301, 0x1d8 },
+	{ 0xfc00000304, 0x1d6 }, { 0xfc0000030c, 0x1da }, { 0x10200000300, 0x1eb0 }, { 0x10200000301, 0x1eae },
+	{ 0x10200000303, 0x1eb4 }, { 0x10200000309, 0x1eb2 }, { 0x10300000300, 0x1eb1 }, { 0x10300000301, 0x1eaf },
+	{ 0x10300000303, 0x1eb5 }, { 0x10300000309, 0x1eb3 }, { 0x11200000300, 0x1e14 }, { 0x11200000301, 0x1e16 },
+	{ 0x11300000300, 0x1e15 }, { 0x11300000301, 0x1e17 }, { 0x14c00000300, 0x1e50 }, { 0x14c00000301, 0x1e52 },
+	{ 0x14d00000300, 0x1e51 }, { 0x14d00000301, 0x1e53 }, { 0x15a00000307, 0x1e64 }, { 0x15b00000307, 0x1e65 },
+	{ 0x16000000307, 0x1e66 }, { 0x16100000307, 0x1e67 }, { 0x16800000301, 0x1e78 }, { 0x16900000301, 0x1e79 },
+	{ 0x16a00000308, 0x1e7a }, { 0x16b00000308, 0x1e7b }, { 0x17f00000307, 0x1e9b }, { 0x1a000000300, 0x1edc },
+	{ 0x1a000000301, 0x1eda }, { 0x1a000000303, 0x1ee0 }, { 0x1a000000309, 0x1ede }, { 0x1a000000323, 0x1ee2 },
+	{ 0x1a100000300, 0x1edd }, { 0x1a100000301, 0x1edb }, { 0x1a100000303, 0x1ee1 }, { 0x1a100000309, 0x1edf },
+	{ 0x1a100000323, 0x1ee3 }, { 0x1af00000300, 0x1eea }, { 0x1af00000301, 0x1ee8 }, { 0x1af00000303, 0x1eee },
+	{ 0x1af00000309, 0x1eec }, { 0x1af00000323, 0x1ef0 }, { 0x1b000000300, 0x1eeb }, { 0x1b000000301, 0x1ee9 },
+	{ 0x1b000000303, 0x1eef }, { 0x1b000000309, 0x1eed }, { 0x1b000000323, 0x1ef1 }, { 0x1b70000030c, 0x1ee },
+	{ 0x1ea00000304, 0x1ec }, { 0x1eb00000304, 0x1ed }, { 0x22600000304, 0x1e0 }, { 0x22700000304, 0x1e1 },
+	{ 0x22800000306, 0x1e1c }, { 0x22900000306, 0x1e1d }, { 0x22e00000304, 0x230 }, { 0x22f00000304, 0x231 },
+	{ 0x2920000030c, 0x1ef }, { 0x39100000300, 0x1fba }, { 0x39100000301, 0x386 }, { 0x39100000304, 0x1fb9 },
+	{ 0x39100000306, 0x1fb8 }, { 0x39100000313, 0x1f08 }, { 0x39100000314, 0x1f09 }, { 0x39100000345, 0x1fbc },
+	{ 0x39500000300, 0x1fc8 }, { 0x39500000301, 0x388 }, { 0x39500000313, 0x1f18 }, { 0x39500000314, 0x1f19 },
+	{ 0x39700000300, 0x1fca }, { 0x39700000301, 0x389 }, { 0x39700000313, 0x1f28 }, { 0x39700000314, 0x1f29 },
+	{ 0x39700000345, 0x1fcc }, { 0x39900000300, 0x1fda }, { 0x39900000301, 0x38a }, { 0x39900000304, 0x1fd9 },
+	{ 0x39900000306, 0x1fd8 }, { 0x39900000308, 0x3aa }, { 0x39900000313, 0x1f38 }, { 0x39900000314, 0x1f39 },
+	{ 0x39f00000300, 0x1ff8 }, { 0x39f00000301, 0x38c }, { 0x39f00000313, 0x1f48 }, { 0x39f00000314, 0x1f49 },
+	{ 0x3a100000314, 0x1fec }, { 0x3a500000300, 0x1fea }, { 0x3a500000301, 0x38e }, { 0x3a500000304, 0x1fe9 },
+	{ 0x3a500000306, 0x1fe8 }, { 0x3a500000308, 0x3ab }, { 0x3a500000314, 0x1f59 }, { 0x3a900000300, 0x1ffa },
+	{ 0x3a900000301, 0x38f }, { 0x3a900000313, 0x1f68 }, { 0x3a900000314, 0x1f69 }, { 0x3a900000345, 0x1ffc },
+	{ 0x3ac00000345, 0x1fb4 }, { 0x3ae00000345, 0x1fc4 }, { 0x3b100000300, 0x1f70 }, { 0x3b100000301, 0x3ac },
+	{ 0x3b100000304, 0x1fb1 }, { 0x3b100000306, 0x1fb0 }, { 0x3b100000313, 0x1f00 }, { 0x3b100000314, 0x1f01 },
+	{ 0x3b100000342, 0x1fb6 }, { 0x3b100000345, 0x1fb3 }, { 0x3b500000300, 0x1f72 }, { 0x3b500000301, 0x3ad },
+	{ 0x3b500000313, 0x1f10 }, { 0x3b500000314, 0x1f11 }, { 0x3b700000300, 0x1f74 }, { 0x3b700000301, 0x3ae },
+	{ 0x3b700000313, 0x1f20 }, { 0x3b700000314, 0x1f21 }, { 0x3b700000342, 0x1fc6 }, { 0x3b700000345, 0x1fc3 },
+	{ 0x3b900000300, 0x1f76 }, { 0x3b900000301, 0x3af }, { 0x3b900000304, 0x1fd1 }, { 0x3b900000306, 0x1fd0 },
+	{ 0x3b900000308, 0x3ca }, { 0x3b900000313, 0x1f30 }, { 0x3b900000314, 0x1f31 }, { 0x3b900000342, 0x1fd6 },
+	{ 0x3bf00000300, 0x1f78 }, { 0x3bf00000301, 0x3cc }, { 0x3bf00000313, 0x1f40 }, { 0x3bf00000314, 0x1f41 },
+	{ 0x3c100000313, 0x1fe4 }, { 0x3c100000314, 0x1fe5 }, { 0x3c500000300, 0x1f7a }, { 0x3c500000301, 0x3cd },
+	{ 0x3c500000304, 0x1fe1 }, { 0x3c500000306, 0x1fe0 }, { 0x3c500000308, 0x3cb }, { 0x3c500000313, 0x1f50 },
+	{ 0x3c500000314, 0x1f51 }, { 0x3c500000342, 0x1fe6 }, { 0x3c900000300, 0x1f7c }, { 0x3c900000301, 0x3ce },
+	{ 0x3c900000313, 0x1f60 }, { 0x3c900000314, 0x1f61 }, { 0x3c900000342, 0x1ff6 }, { 0x3c900000345, 0x1ff3 },
+	{ 0x3ca00000300, 0x1fd2 }, { 0x3ca00000301, 0x390 }, { 0x3ca00000342, 0x1fd7 }, { 0x3cb00000300, 0x1fe2 },
+	{ 0x3cb00000301, 0x3b0 }, { 0x3cb00000342, 0x1fe7 }, { 0x3ce00000345, 0x1ff4 }, { 0x3d200000301, 0x3d3 },
+	{ 0x3d200000308, 0x3d4 }, { 0x40600000308, 0x407 }, { 0x41000000306, 0x4d0 }, { 0x41000000308, 0x4d2 },
+	{ 0x41300000301, 0x403 }, { 0x41500000300, 0x400 }, { 0x41500000306, 0x4d6 }, { 0x41500000308, 0x401 },
+	{ 0x41600000306, 0x4c1 }, { 0x41600000308, 0x4dc }, { 0x41700000308, 0x4de }, { 0x41800000300, 0x40d },
+	{ 0x41800000304, 0x4e2 }, { 0x41800000306, 0x419 }, { 0x41800000308, 0x4e4 }, { 0x41a00000301, 0x40c },
+	{ 0x41e00000308, 0x4e6 }, { 0x42300000304, 0x4ee }, { 0x42300000306, 0x40e }, { 0x42300000308, 0x4f0 },
+	{ 0x4230000030b, 0x4f2 }, { 0x42700000308, 0x4f4 }, { 0x42b00000308, 0x4f8 }, { 0x42d00000308, 0x4ec },
+	{ 0x43000000306, 0x4d1 }, { 0x43000000308, 0x4d3 }, { 0x43300000301, 0x453 }, { 0x43500000300, 0x450 },
+	{ 0x43500000306, 0x4d7 }, { 0x43500000308, 0x451 }, { 0x43600000306, 0x4c2 }, { 0x43600000308, 0x4dd },
+	{ 0x43700000308, 0x4df }, { 0x43800000300, 0x45d }, { 0x43800000304, 0x4e3 }, { 0x43800000306, 0x439 },
+	{ 0x43800000308, 0x4e5 }, { 0x43a00000301, 0x45c }, { 0x43e00000308, 0x4e7 }, { 0x44300000304, 0x4ef },
+	{ 0x44300000306, 0x45e }, { 0x44300000308, 0x4f1 }, { 0x4430000030b, 0x4f3 }, { 0x44700000308, 0x4f5 },
+	{ 0x44b00000308, 0x4f9 }, { 0x44d00000308, 0x4ed }, { 0x45600000308, 0x457 }, { 0x4740000030f, 0x476 },
+	{ 0x4750000030f, 0x477 }, { 0x4d800000308, 0x4da }, { 0x4d900000308, 0x4db }, { 0x4e800000308, 0x4ea },
+	{ 0x4e900000308, 0x4eb }, { 0x62700000653, 0x622 }, { 0x62700000654, 0x623 }, { 0x62700000655, 0x625 },
+	{ 0x64800000654, 0x624 }, { 0x64a00000654, 0x626 }, { 0x6c100000654, 0x6c2 }, { 0x6d200000654, 0x6d3 },
+	{ 0x6d500000654, 0x6c0 }, { 0x9280000093c, 0x929 }, { 0x9300000093c, 0x931 }, { 0x9330000093c, 0x934 },
+	{ 0x9c7000009be, 0x9cb }, { 0x9c7000009d7, 0x9cc }, { 0xb4700000b3e, 0xb4b }, { 0xb4700000b56, 0xb48 },
+	{ 0xb4700000b57, 0xb4c }, { 0xb9200000bd7, 0xb94 }, { 0xbc600000bbe, 0xbca }, { 0xbc600000bd7, 0xbcc },
+	{ 0xbc700000bbe, 0xbcb }, { 0xc4600000c56, 0xc48 }, { 0xcbf00000cd5, 0xcc0 }, { 0xcc600000cc2, 0xcca },
+	{ 0xcc600000cd5, 0xcc7 }, { 0xcc600000cd6, 0xcc8 }, { 0xcca00000cd5, 0xccb }, { 0xd4600000d3e, 0xd4a },
+	{ 0xd4600000d57, 0xd4c }, { 0xd4700000d3e, 0xd4b }, { 0xdd900000dca, 0xdda }, { 0xdd900000dcf, 0xddc },
+	{ 0xdd900000ddf, 0xdde }, { 0xddc00000dca, 0xddd }, { 0x10250000102e, 0x1026 }, { 0x1b0500001b35, 0x1b06 },
+	{ 0x1b0700001b35, 0x1b08 }, { 0x1b0900001b35, 0x1b0a }, { 0x1b0b00001b35, 0x1b0c }, { 0x1b0d00001b35, 0x1b0e },
+	{ 0x1b1100001b35, 0x1b12 }, { 0x1b3a00001b35, 0x1b3b }, { 0x1b3c00001b35, 0x1b3d }, { 0x1b3e00001b35, 0x1b40 },
+	{ 0x1b3f00001b35, 0x1b41 }, { 0x1b4200001b35, 0x1b43 }, { 0x1e3600000304, 0x1e38 }, { 0x1e3700000304, 0x1e39 },
+	{ 0x1e5a00000304, 0x1e5c }, { 0x1e5b00000304, 0x1e5d }, { 0x1e6200000307, 0x1e68 }, { 0x1e6300000307, 0x1e69 },
+	{ 0x1ea000000302, 0x1eac }, { 0x1ea000000306, 0x1eb6 }, { 0x1ea100000302, 0x1ead }, { 0x1ea100000306, 0x1eb7 },
+	{ 0x1eb800000302, 0x1ec6 }, { 0x1eb900000302, 0x1ec7 }, { 0x1ecc00000302, 0x1ed8 }, { 0x1ecd00000302, 0x1ed9 },
+	{ 0x1f0000000300, 0x1f02 }, { 0x1f0000000301, 0x1f04 }, { 0x1f0000000342, 0x1f06 }, { 0x1f0000000345, 0x1f80 },
+	{ 0x1f0100000300, 0x1f03 }, { 0x1f0100000301, 0x1f05 }, { 0x1f0100000342, 0x1f07 }, { 0x1f0100000345, 0x1f81 },
+	{ 0x1f0200000345, 0x1f82 }, { 0x1f0300000345, 0x1f83 }, { 0x1f0400000345, 0x1f84 }, { 0x1f0500000345, 0x1f85 },
+	{ 0x1f0600000345, 0x1f86 }, { 0x1f0700000345, 0x1f87 }, { 0x1f0800000300, 0x1f0a }, { 0x1f0800000301, 0x1f0c },
+	{ 0x1f0800000342, 0x1f0e }, { 0x1f0800000345, 0x1f88 }, { 0x1f0900000300, 0x1f0b }, { 0x1f0900000301, 0x1f0d },
+	{ 0x1f0900000342, 0x1f0f }, { 0x1f0900000345, 0x1f89 }, { 0x1f0a00000345, 0x1f8a }, { 0x1f0b00000345, 0x1f8b },
+	{ 0x1f0c00000345, 0x1f8c }, { 0x1f0d00000345, 0x1f8d }, { 0x1f0e00000345, 0x1f8e }, { 0x1f0f00000345, 0x1f8f },
+	{ 0x1f1000000300, 0x1f12 }, { 0x1f1000000301, 0x1f14 }, { 0x1f1100000300, 0x1f13 }, { 0x1f1100000301, 0x1f15 },
+	{ 0x1f1800000300, 0x1f1a }, { 0x1f1800000301, 0x1f1c }, { 0x1f1900000300, 0x1f1b }, { 0x1f1900000301, 0x1f1d },
+	{ 0x1f2000000300, 0x1f22 }, { 0x1f2000000301, 0x1f24 }, { 0x1f2000000342, 0x1f26 }, { 0x1f2000000345, 0x1f90 },
+	{ 0x1f2100000300, 0x1f23 }, { 0x1f2100000301, 0x1f25 }, { 0x1f2100000342, 0x1f27 }, { 0x1f2100000345, 0x1f91 },
+	{ 0x1f2200000345, 0x1f92 }, { 0x1f2300000345, 0x1f93 }, { 0x1f2400000345, 0x1f94 }, { 0x1f2500000345, 0x1f95 },
+	{ 0x1f2600000345, 0x1f96 }, { 0x1f2700000345, 0x1f97 }, { 0x1f2800000300, 0x1f2a }, { 0x1f2800000301, 0x1f2c },
+	{ 0x1f2800000342, 0x1f2e }, { 0x1f2800000345, 0x1f98 }, { 0x1f2900000300, 0x1f2b }, { 0x1f2900000301, 0x1f2d },
+	{ 0x1f2900000342, 0x1f2f }, { 0x1f2900000345, 0x1f99 }, { 0x1f2a00000345, 0x1f9a }, { 0x1f2b00000345, 0x1f9b },
+	{ 0x1f2c00000345, 0x1f9c }, { 0x1f2d00000345, 0x1f9d }, { 0x1f2e00000345, 0x1f9e }, { 0x1f2f00000345, 0x1f9f },
+	{ 0x1f3000000300, 0x1f32 }, { 0x1f3000000301, 0x1f34 }, { 0x1f3000000342, 0x1f36 }, { 0x1f3100000300, 0x1f33 },
+	{ 0x1f3100000301, 0x1f35 }, { 0x1f3100000342, 0x1f37 }, { 0x1f3800000300, 0x1f3a }, { 0x1f3800000301, 0x1f3c },
+	{ 0x1f3800000342, 0x1f3e }, { 0x1f3900000300, 0x1f3b }, { 0x1f3900000301, 0x1f3d }, { 0x1f3900000342, 0x1f3f },
+	{ 0x1f4000000300, 0x1f42 }, { 0x1f4000000301, 0x1f44 }, { 0x1f4100000300, 0x1f43 }, { 0x1f4100000301, 0x1f45 },
+	{ 0x1f4800000300, 0x1f4a }, { 0x1f4800000301, 0x1f4c }, { 0x1f4900000300, 0x1f4b }, { 0x1f4900000301, 0x1f4d },
+	{ 0x1f5000000300, 0x1f52 }, { 0x1f5000000301, 0x1f54 }, { 0x1f5000000342, 0x1f56 }, { 0x1f5100000300, 0x1f53 },
+	{ 0x1f5100000301, 0x1f55 }, { 0x1f5100000342, 0x1f57 }, { 0x1f5900000300, 0x1f5b }, { 0x1f5900000301, 0x1f5d },
+	{ 0x1f5900000342, 0x1f5f }, { 0x1f6000000300, 0x1f62 }, { 0x1f6000000301, 0x1f64 }, { 0x1f6000000342, 0x1f66 },
+	{ 0x1f6000000345, 0x1fa0 }, { 0x1f6100000300, 0x1f63 }, { 0x1f6100000301, 0x1f65 }, { 0x1f6100000342, 0x1f67 },
+	{ 0x1f6100000345, 0x1fa1 }, { 0x1f6200000345, 0x1fa2 }, { 0x1f6300000345, 0x1fa3 }, { 0x1f6400000345, 0x1fa4 },
+	{ 0x1f6500000345, 0x1fa5 }, { 0x1f6600000345, 0x1fa6 }, { 0x1f6700000345, 0x1fa7 }, { 0x1f6800000300, 0x1f6a },
+	{ 0x1f6800000301, 0x1f6c }, { 0x1f6800000342, 0x1f6e }, { 0x1f6800000345, 0x1fa8 }, { 0x1f6900000300, 0x1f6b },
+	{ 0x1f6900000301, 0x1f6d }, { 0x1f6900000342, 0x1f6f }, { 0x1f6900000345, 0x1fa9 }, { 0x1f6a00000345, 0x1faa },
+	{ 0x1f6b00000345, 0x1fab }, { 0x1f6c00000345, 0x1fac }, { 0x1f6d00000345, 0x1fad }, { 0x1f6e00000345, 0x1fae },
+	{ 0x1f6f00000345, 0x1faf }, { 0x1f7000000345, 0x1fb2 }, { 0x1f7400000345, 0x1fc2 }, { 0x1f7c00000345, 0x1ff2 },
+	{ 0x1fb600000345, 0x1fb7 }, { 0x1fbf00000300, 0x1fcd }, { 0x1fbf00000301, 0x1fce }, { 0x1fbf00000342, 0x1fcf },
+	{ 0x1fc600000345, 0x1fc7 }, { 0x1ff600000345, 0x1ff7 }, { 0x1ffe00000300, 0x1fdd }, { 0x1ffe00000301, 0x1fde },
+	{ 0x1ffe00000342, 0x1fdf }, { 0x219000000338, 0x219a }, { 0x219200000338, 0x219b }, { 0x219400000338, 0x21ae },
+	{ 0x21d000000338, 0x21cd }, { 0x21d200000338, 0x21cf }, { 0x21d400000338, 0x21ce }, { 0x220300000338, 0x2204 },
+	{ 0x220800000338, 0x2209 }, { 0x220b00000338, 0x220c }, { 0x222300000338, 0x2224 }, { 0x222500000338, 0x2226 },
+	{ 0x223c00000338, 0x2241 }, { 0x224300000338, 0x2244 }, { 0x224500000338, 0x2247 }, { 0x224800000338, 0x2249 },
+	{ 0x224d00000338, 0x226d }, { 0x226100000338, 0x2262 }, { 0x226400000338, 0x2270 }, { 0x226500000338, 0x2271 },
+	{ 0x227200000338, 0x2274 }, { 0x227300000338, 0x2275 }, { 0x227600000338, 0x2278 }, { 0x227700000338, 0x2279 },
+	{ 0x227a00000338, 0x2280 }, { 0x227b00000338, 0x2281 }, { 0x227c00000338, 0x22e0 }, { 0x227d00000338, 0x22e1 },
+	{ 0x228200000338, 0x2284 }, { 0x228300000338, 0x2285 }, { 0x228600000338, 0x2288 }, { 0x228700000338, 0x2289 },
+	{ 0x229100000338, 0x22e2 }, { 0x229200000338, 0x22e3 }, { 0x22a200000338, 0x22ac }, { 0x22a800000338, 0x22ad },
+	{ 0x22a900000338, 0x22ae }, { 0x22ab00000338, 0x22af }, { 0x22b200000338, 0x22ea }, { 0x22b300000338, 0x22eb },
+	{ 0x22b400000338, 0x22ec }, { 0x22b500000338, 0x22ed }, { 0x304600003099, 0x3094 }, { 0x304b00003099, 0x304c },
+	{ 0x304d00003099, 0x304e }, { 0x304f00003099, 0x3050 }, { 0x305100003099, 0x3052 }, { 0x305300003099, 0x3054 },
+	{ 0x305500003099, 0x3056 }, { 0x305700003099, 0x3058 }, { 0x305900003099, 0x305a }, { 0x305b00003099, 0x305c },
+	{ 0x305d00003099, 0x305e }, { 0x305f00003099, 0x3060 }, { 0x306100003099, 0x3062 }, { 0x306400003099, 0x3065 },
+	{ 0x306600003099, 0x3067 }, { 0x306800003099, 0x3069 }, { 0x306f00003099, 0x3070 }, { 0x306f0000309a, 0x3071 },
+	{ 0x307200003099, 0x3073 }, { 0x30720000309a, 0x3074 }, { 0x307500003099, 0x3076 }, { 0x30750000309a, 0x3077 },
+	{ 0x307800003099, 0x3079 }, { 0x30780000309a, 0x307a }, { 0x307b00003099, 0x307c }, { 0x307b0000309a, 0x307d },
+	{ 0x309d00003099, 0x309e }, { 0x30a600003099, 0x30f4 }, { 0x30ab00003099, 0x30ac }, { 0x30ad00003099, 0x30ae },
+	{ 0x30af00003099, 0x30b0 }, { 0x30b100003099, 0x30b2 }, { 0x30b300003099, 0x30b4 }, { 0x30b500003099, 0x30b6 },
+	{ 0x30b700003099, 0x30b8 }, { 0x30b900003099, 0x30ba }, { 0x30bb00003099, 0x30bc }, { 0x30bd00003099, 0x30be },
+	{ 0x30bf00003099, 0x30c0 }, { 0x30c100003099, 0x30c2 }, { 0x30c400003099, 0x30c5 }, { 0x30c600003099, 0x30c7 },
+	{ 0x30c800003099, 0x30c9 }, { 0x30cf00003099, 0x30d0 }, { 0x30cf0000309a, 0x30d1 }, { 0x30d200003099, 0x30d3 },
+	{ 0x30d20000309a, 0x30d4 }, { 0x30d500003099, 0x30d6 }, { 0x30d50000309a, 0x30d7 }, { 0x30d800003099, 0x30d9 },
+	{ 0x30d80000309a, 0x30da }, { 0x30db00003099, 0x30dc }, { 0x30db0000309a, 0x30dd }, { 0x30ef00003099, 0x30f7 },
+	{ 0x30f000003099, 0x30f8 }, { 0x30f100003099, 0x30f9 }, { 0x30f200003099, 0x30fa }, { 0x30fd00003099, 0x30fe },
+	{ 0x11099000110ba, 0x1109a }, { 0x1109b000110ba, 0x1109c }, { 0x110a5000110ba, 0x110ab }, { 0x1113100011127, 0x1112e },
+	{ 0x1113200011127, 0x1112f }, { 0x113470001133e, 0x1134b }, { 0x1134700011357, 0x1134c }, { 0x114b9000114b0, 0x114bc },
+	{ 0x114b9000114ba, 0x114bb }, { 0x114b9000114bd, 0x114be }, { 0x115b8000115af, 0x115ba }, { 0x115b9000115af, 0x115bb },
+};
+const CompositionRecord* UnicodeCompositionRecordPtr = UnicodeCompositionRecord;
+
+const char* CompressedStringData = 
+	"\x41\xCC\x80\x41\xCC\x81\x41\xCC\x82\x41\xCC\x83\x41\xCC\x88\x41\xCC\x8A\x43\xCC\xA7\x45\xCC\x80\x45"
+	"\xCC\x81\x45\xCC\x82\x45\xCC\x88\x49\xCC\x80\x49\xCC\x81\x49\xCC\x82\x49\xCC\x88\x4E\xCC\x83\x4F\xCC"
+	"\x80\x4F\xCC\x81\x4F\xCC\x82\x4F\xCC\x83\x4F\xCC\x88\x55\xCC\x80\x55\xCC\x81\x55\xCC\x82\x55\xCC\x88"
+	"\x59\xCC\x81\x61\xCC\x80\x61\xCC\x81\x61\xCC\x82\x61\xCC\x83\x61\xCC\x88\x61\xCC\x8A\x63\xCC\xA7\x65"
+	"\xCC\x80\x65\xCC\x81\x65\xCC\x82\x65\xCC\x88\x69\xCC\x80\x69\xCC\x81\x69\xCC\x82\x69\xCC\x88\x6E\xCC"
+	"\x83\x6F\xCC\x80\x6F\xCC\x81\x6F\xCC\x82\x6F\xCC\x83\x6F\xCC\x88\x75\xCC\x80\x75\xCC\x81\x75\xCC\x82"
+	"\x75\xCC\x88\x79\xCC\x81\x79\xCC\x88\x41\xCC\x84\x61\xCC\x84\x41\xCC\x86\x61\xCC\x86\x41\xCC\xA8\x61"
+	"\xCC\xA8\x43\xCC\x81\x63\xCC\x81\x43\xCC\x82\x63\xCC\x82\x43\xCC\x87\x63\xCC\x87\x43\xCC\x8C\x63\xCC"
+	"\x8C\x44\xCC\x8C\x64\xCC\x8C\x45\xCC\x84\x65\xCC\x84\x45\xCC\x86\x65\xCC\x86\x45\xCC\x87\x65\xCC\x87"
+	"\x45\xCC\xA8\x65\xCC\xA8\x45\xCC\x8C\x65\xCC\x8C\x47\xCC\x82\x67\xCC\x82\x47\xCC\x86\x67\xCC\x86\x47"
+	"\xCC\x87\x67\xCC\x87\x47\xCC\xA7\x67\xCC\xA7\x48\xCC\x82\x68\xCC\x82\x49\xCC\x83\x69\xCC\x83\x49\xCC"
+	"\x84\x69\xCC\x84\x49\xCC\x86\x69\xCC\x86\x49\xCC\xA8\x69\xCC\xA8\x49\xCC\x87\x4A\xCC\x82\x6A\xCC\x82"
+	"\x4B\xCC\xA7\x6B\xCC\xA7\x4C\xCC\x81\x6C\xCC\x81\x4C\xCC\xA7\x6C\xCC\xA7\x4C\xCC\x8C\x6C\xCC\x8C\x4E"
+	"\xCC\x81\x6E\xCC\x81\x4E\xCC\xA7\x6E\xCC\xA7\x4E\xCC\x8C\x6E\xCC\x8C\x4F\xCC\x84\x6F\xCC\x84\x4F\xCC"
+	"\x86\x6F\xCC\x86\x4F\xCC\x8B\x6F\xCC\x8B\x52\xCC\x81\x72\xCC\x81\x52\xCC\xA7\x72\xCC\xA7\x52\xCC\x8C"
+	"\x72\xCC\x8C\x53\xCC\x81\x73\xCC\x81\x53\xCC\x82\x73\xCC\x82\x53\xCC\xA7\x73\xCC\xA7\x53\xCC\x8C\x73"
+	"\xCC\x8C\x54\xCC\xA7\x74\xCC\xA7\x54\xCC\x8C\x74\xCC\x8C\x55\xCC\x83\x75\xCC\x83\x55\xCC\x84\x75\xCC"
+	"\x84\x55\xCC\x86\x75\xCC\x86\x55\xCC\x8A\x75\xCC\x8A\x55\xCC\x8B\x75\xCC\x8B\x55\xCC\xA8\x75\xCC\xA8"
+	"\x57\xCC\x82\x77\xCC\x82\x59\xCC\x82\x79\xCC\x82\x59\xCC\x88\x5A\xCC\x81\x7A\xCC\x81\x5A\xCC\x87\x7A"
+	"\xCC\x87\x5A\xCC\x8C\x7A\xCC\x8C\x4F\xCC\x9B\x6F\xCC\x9B\x55\xCC\x9B\x75\xCC\x9B\x41\xCC\x8C\x61\xCC"
+	"\x8C\x49\xCC\x8C\x69\xCC\x8C\x4F\xCC\x8C\x6F\xCC\x8C\x55\xCC\x8C\x75\xCC\x8C\x55\xCC\x88\xCC\x84\x75"
+	"\xCC\x88\xCC\x84\x55\xCC\x88\xCC\x81\x75\xCC\x88\xCC\x81\x55\xCC\x88\xCC\x8C\x75\xCC\x88\xCC\x8C\x55"
+	"\xCC\x88\xCC\x80\x75\xCC\x88\xCC\x80\x41\xCC\x88\xCC\x84\x61\xCC\x88\xCC\x84\x41\xCC\x87\xCC\x84\x61"
+	"\xCC\x87\xCC\x84\xC3\x86\xCC\x84\xC3\xA6\xCC\x84\x47\xCC\x8C\x67\xCC\x8C\x4B\xCC\x8C\x6B\xCC\x8C\x4F"
+	"\xCC\xA8\x6F\xCC\xA8\x4F\xCC\xA8\xCC\x84\x6F\xCC\xA8\xCC\x84\xC6\xB7\xCC\x8C\xCA\x92\xCC\x8C\x6A\xCC"
+	"\x8C\x47\xCC\x81\x67\xCC\x81\x4E\xCC\x80\x6E\xCC\x80\x41\xCC\x8A\xCC\x81\x61\xCC\x8A\xCC\x81\xC3\x86"
+	"\xCC\x81\xC3\xA6\xCC\x81\xC3\x98\xCC\x81\xC3\xB8\xCC\x81\x41\xCC\x8F\x61\xCC\x8F\x41\xCC\x91\x61\xCC"
+	"\x91\x45\xCC\x8F\x65\xCC\x8F\x45\xCC\x91\x65\xCC\x91\x49\xCC\x8F\x69\xCC\x8F\x49\xCC\x91\x69\xCC\x91"
+	"\x4F\xCC\x8F\x6F\xCC\x8F\x4F\xCC\x91\x6F\xCC\x91\x52\xCC\x8F\x72\xCC\x8F\x52\xCC\x91\x72\xCC\x91\x55"
+	"\xCC\x8F\x75\xCC\x8F\x55\xCC\x91\x75\xCC\x91\x53\xCC\xA6\x73\xCC\xA6\x54\xCC\xA6\x74\xCC\xA6\x48\xCC"
+	"\x8C\x68\xCC\x8C\x45\xCC\xA7\x65\xCC\xA7\x4F\xCC\x88\xCC\x84\x6F\xCC\x88\xCC\x84\x4F\xCC\x83\xCC\x84"
+	"\x6F\xCC\x83\xCC\x84\x4F\xCC\x87\x6F\xCC\x87\x4F\xCC\x87\xCC\x84\x6F\xCC\x87\xCC\x84\x59\xCC\x84\x79"
+	"\xCC\x84\xCC\x93\xCA\xB9\x3B\xC2\xA8\xCC\x81\xCE\x91\xCC\x81\xC2\xB7\xCE\x95\xCC\x81\xCE\x97\xCC\x81"
+	"\xCE\x99\xCC\x81\xCE\x9F\xCC\x81\xCE\xA5\xCC\x81\xCE\xA9\xCC\x81\xCE\xB9\xCC\x88\xCC\x81\xCE\x99\xCC"
+	"\x88\xCE\xA5\xCC\x88\xCE\xB1\xCC\x81\xCE\xB5\xCC\x81\xCE\xB7\xCC\x81\xCE\xB9\xCC\x81\xCF\x85\xCC\x88"
+	"\xCC\x81\xCE\xBF\xCC\x81\xCF\x85\xCC\x81\xCF\x89\xCC\x81\xCF\x92\xCC\x81\xCF\x92\xCC\x88\xD0\x95\xCC"
+	"\x80\xD0\x95\xCC\x88\xD0\x93\xCC\x81\xD0\x86\xCC\x88\xD0\x9A\xCC\x81\xD0\x98\xCC\x80\xD0\xA3\xCC\x86"
+	"\xD0\x98\xCC\x86\xD0\xB8\xCC\x86\xD0\xB5\xCC\x80\xD0\xB5\xCC\x88\xD0\xB3\xCC\x81\xD1\x96\xCC\x88\xD0"
+	"\xBA\xCC\x81\xD0\xB8\xCC\x80\xD1\x83\xCC\x86\xD1\xB4\xCC\x8F\xD1\xB5\xCC\x8F\xD0\x96\xCC\x86\xD0\xB6"
+	"\xCC\x86\xD0\x90\xCC\x86\xD0\xB0\xCC\x86\xD0\x90\xCC\x88\xD0\xB0\xCC\x88\xD0\x95\xCC\x86\xD0\xB5\xCC"
+	"\x86\xD3\x98\xCC\x88\xD3\x99\xCC\x88\xD0\x96\xCC\x88\xD0\xB6\xCC\x88\xD0\x97\xCC\x88\xD0\xB7\xCC\x88"
+	"\xD0\x98\xCC\x84\xD0\xB8\xCC\x84\xD0\x98\xCC\x88\xD0\xB8\xCC\x88\xD0\x9E\xCC\x88\xD0\xBE\xCC\x88\xD3"
+	"\xA8\xCC\x88\xD3\xA9\xCC\x88\xD0\xAD\xCC\x88\xD1\x8D\xCC\x88\xD0\xA3\xCC\x84\xD1\x83\xCC\x84\xD0\xA3"
+	"\xCC\x88\xD1\x83\xCC\x88\xD0\xA3\xCC\x8B\xD1\x83\xCC\x8B\xD0\xA7\xCC\x88\xD1\x87\xCC\x88\xD0\xAB\xCC"
+	"\x88\xD1\x8B\xCC\x88\xD8\xA7\xD9\x93\xD8\xA7\xD9\x94\xD9\x88\xD9\x94\xD8\xA7\xD9\x95\xD9\x8A\xD9\x94"
+	"\xDB\x95\xD9\x94\xDB\x81\xD9\x94\xDB\x92\xD9\x94\xE0\xA4\xA8\xE0\xA4\xBC\xE0\xA4\xB0\xE0\xA4\xBC\xE0"
+	"\xA4\xB3\xE0\xA4\xBC\xE0\xA4\x95\xE0\xA4\xBC\xE0\xA4\x96\xE0\xA4\xBC\xE0\xA4\x97\xE0\xA4\xBC\xE0\xA4"
+	"\x9C\xE0\xA4\xBC\xE0\xA4\xA1\xE0\xA4\xBC\xE0\xA4\xA2\xE0\xA4\xBC\xE0\xA4\xAB\xE0\xA4\xBC\xE0\xA4\xAF"
+	"\xE0\xA4\xBC\xE0\xA7\x87\xE0\xA6\xBE\xE0\xA7\x87\xE0\xA7\x97\xE0\xA6\xA1\xE0\xA6\xBC\xE0\xA6\xA2\xE0"
+	"\xA6\xBC\xE0\xA6\xAF\xE0\xA6\xBC\xE0\xA8\xB2\xE0\xA8\xBC\xE0\xA8\xB8\xE0\xA8\xBC\xE0\xA8\x96\xE0\xA8"
+	"\xBC\xE0\xA8\x97\xE0\xA8\xBC\xE0\xA8\x9C\xE0\xA8\xBC\xE0\xA8\xAB\xE0\xA8\xBC\xE0\xAD\x87\xE0\xAD\x96"
+	"\xE0\xAD\x87\xE0\xAC\xBE\xE0\xAD\x87\xE0\xAD\x97\xE0\xAC\xA1\xE0\xAC\xBC\xE0\xAC\xA2\xE0\xAC\xBC\xE0"
+	"\xAE\x92\xE0\xAF\x97\xE0\xAF\x86\xE0\xAE\xBE\xE0\xAF\x87\xE0\xAE\xBE\xE0\xAF\x86\xE0\xAF\x97\xE0\xB1"
+	"\x86\xE0\xB1\x96\xE0\xB2\xBF\xE0\xB3\x95\xE0\xB3\x86\xE0\xB3\x95\xE0\xB3\x86\xE0\xB3\x96\xE0\xB3\x86"
+	"\xE0\xB3\x82\xE0\xB3\x86\xE0\xB3\x82\xE0\xB3\x95\xE0\xB5\x86\xE0\xB4\xBE\xE0\xB5\x87\xE0\xB4\xBE\xE0"
+	"\xB5\x86\xE0\xB5\x97\xE0\xB7\x99\xE0\xB7\x8A\xE0\xB7\x99\xE0\xB7\x8F\xE0\xB7\x99\xE0\xB7\x8F\xE0\xB7"
+	"\x8A\xE0\xB7\x99\xE0\xB7\x9F\xE0\xBD\x82\xE0\xBE\xB7\xE0\xBD\x8C\xE0\xBE\xB7\xE0\xBD\x91\xE0\xBE\xB7"
+	"\xE0\xBD\x96\xE0\xBE\xB7\xE0\xBD\x9B\xE0\xBE\xB7\xE0\xBD\x80\xE0\xBE\xB5\xE0\xBD\xB1\xE0\xBD\xB2\xE0"
+	"\xBD\xB1\xE0\xBD\xB4\xE0\xBE\xB2\xE0\xBE\x80\xE0\xBE\xB3\xE0\xBE\x80\xE0\xBD\xB1\xE0\xBE\x80\xE0\xBE"
+	"\x92\xE0\xBE\xB7\xE0\xBE\x9C\xE0\xBE\xB7\xE0\xBE\xA1\xE0\xBE\xB7\xE0\xBE\xA6\xE0\xBE\xB7\xE0\xBE\xAB"
+	"\xE0\xBE\xB7\xE0\xBE\x90\xE0\xBE\xB5\xE1\x80\xA5\xE1\x80\xAE\xE1\xAC\x85\xE1\xAC\xB5\xE1\xAC\x87\xE1"
+	"\xAC\xB5\xE1\xAC\x89\xE1\xAC\xB5\xE1\xAC\x8B\xE1\xAC\xB5\xE1\xAC\x8D\xE1\xAC\xB5\xE1\xAC\x91\xE1\xAC"
+	"\xB5\xE1\xAC\xBA\xE1\xAC\xB5\xE1\xAC\xBC\xE1\xAC\xB5\xE1\xAC\xBE\xE1\xAC\xB5\xE1\xAC\xBF\xE1\xAC\xB5"
+	"\xE1\xAD\x82\xE1\xAC\xB5\x41\xCC\xA5\x61\xCC\xA5\x42\xCC\x87\x62\xCC\x87\x42\xCC\xA3\x62\xCC\xA3\x42"
+	"\xCC\xB1\x62\xCC\xB1\x43\xCC\xA7\xCC\x81\x63\xCC\xA7\xCC\x81\x44\xCC\x87\x64\xCC\x87\x44\xCC\xA3\x64"
+	"\xCC\xA3\x44\xCC\xB1\x64\xCC\xB1\x44\xCC\xA7\x64\xCC\xA7\x44\xCC\xAD\x64\xCC\xAD\x45\xCC\x84\xCC\x80"
+	"\x65\xCC\x84\xCC\x80\x45\xCC\x84\xCC\x81\x65\xCC\x84\xCC\x81\x45\xCC\xAD\x65\xCC\xAD\x45\xCC\xB0\x65"
+	"\xCC\xB0\x45\xCC\xA7\xCC\x86\x65\xCC\xA7\xCC\x86\x46\xCC\x87\x66\xCC\x87\x47\xCC\x84\x67\xCC\x84\x48"
+	"\xCC\x87\x68\xCC\x87\x48\xCC\xA3\x68\xCC\xA3\x48\xCC\x88\x68\xCC\x88\x48\xCC\xA7\x68\xCC\xA7\x48\xCC"
+	"\xAE\x68\xCC\xAE\x49\xCC\xB0\x69\xCC\xB0\x49\xCC\x88\xCC\x81\x69\xCC\x88\xCC\x81\x4B\xCC\x81\x6B\xCC"
+	"\x81\x4B\xCC\xA3\x6B\xCC\xA3\x4B\xCC\xB1\x6B\xCC\xB1\x4C\xCC\xA3\x6C\xCC\xA3\x4C\xCC\xA3\xCC\x84\x6C"
+	"\xCC\xA3\xCC\x84\x4C\xCC\xB1\x6C\xCC\xB1\x4C\xCC\xAD\x6C\xCC\xAD\x4D\xCC\x81\x6D\xCC\x81\x4D\xCC\x87"
+	"\x6D\xCC\x87\x4D\xCC\xA3\x6D\xCC\xA3\x4E\xCC\x87\x6E\xCC\x87\x4E\xCC\xA3\x6E\xCC\xA3\x4E\xCC\xB1\x6E"
+	"\xCC\xB1\x4E\xCC\xAD\x6E\xCC\xAD\x4F\xCC\x83\xCC\x81\x6F\xCC\x83\xCC\x81\x4F\xCC\x83\xCC\x88\x6F\xCC"
+	"\x83\xCC\x88\x4F\xCC\x84\xCC\x80\x6F\xCC\x84\xCC\x80\x4F\xCC\x84\xCC\x81\x6F\xCC\x84\xCC\x81\x50\xCC"
+	"\x81\x70\xCC\x81\x50\xCC\x87\x70\xCC\x87\x52\xCC\x87\x72\xCC\x87\x52\xCC\xA3\x72\xCC\xA3\x52\xCC\xA3"
+	"\xCC\x84\x72\xCC\xA3\xCC\x84\x52\xCC\xB1\x72\xCC\xB1\x53\xCC\x87\x73\xCC\x87\x53\xCC\xA3\x73\xCC\xA3"
+	"\x53\xCC\x81\xCC\x87\x73\xCC\x81\xCC\x87\x53\xCC\x8C\xCC\x87\x73\xCC\x8C\xCC\x87\x53\xCC\xA3\xCC\x87"
+	"\x73\xCC\xA3\xCC\x87\x54\xCC\x87\x74\xCC\x87\x54\xCC\xA3\x74\xCC\xA3\x54\xCC\xB1\x74\xCC\xB1\x54\xCC"
+	"\xAD\x74\xCC\xAD\x55\xCC\xA4\x75\xCC\xA4\x55\xCC\xB0\x75\xCC\xB0\x55\xCC\xAD\x75\xCC\xAD\x55\xCC\x83"
+	"\xCC\x81\x75\xCC\x83\xCC\x81\x55\xCC\x84\xCC\x88\x75\xCC\x84\xCC\x88\x56\xCC\x83\x76\xCC\x83\x56\xCC"
+	"\xA3\x76\xCC\xA3\x57\xCC\x80\x77\xCC\x80\x57\xCC\x81\x77\xCC\x81\x57\xCC\x88\x77\xCC\x88\x57\xCC\x87"
+	"\x77\xCC\x87\x57\xCC\xA3\x77\xCC\xA3\x58\xCC\x87\x78\xCC\x87\x58\xCC\x88\x78\xCC\x88\x59\xCC\x87\x79"
+	"\xCC\x87\x5A\xCC\x82\x7A\xCC\x82\x5A\xCC\xA3\x7A\xCC\xA3\x5A\xCC\xB1\x7A\xCC\xB1\x68\xCC\xB1\x74\xCC"
+	"\x88\x77\xCC\x8A\x79\xCC\x8A\xC5\xBF\xCC\x87\x41\xCC\xA3\x61\xCC\xA3\x41\xCC\x89\x61\xCC\x89\x41\xCC"
+	"\x82\xCC\x81\x61\xCC\x82\xCC\x81\x41\xCC\x82\xCC\x80\x61\xCC\x82\xCC\x80\x41\xCC\x82\xCC\x89\x61\xCC"
+	"\x82\xCC\x89\x41\xCC\x82\xCC\x83\x61\xCC\x82\xCC\x83\x41\xCC\xA3\xCC\x82\x61\xCC\xA3\xCC\x82\x41\xCC"
+	"\x86\xCC\x81\x61\xCC\x86\xCC\x81\x41\xCC\x86\xCC\x80\x61\xCC\x86\xCC\x80\x41\xCC\x86\xCC\x89\x61\xCC"
+	"\x86\xCC\x89\x41\xCC\x86\xCC\x83\x61\xCC\x86\xCC\x83\x41\xCC\xA3\xCC\x86\x61\xCC\xA3\xCC\x86\x45\xCC"
+	"\xA3\x65\xCC\xA3\x45\xCC\x89\x65\xCC\x89\x45\xCC\x83\x65\xCC\x83\x45\xCC\x82\xCC\x81\x65\xCC\x82\xCC"
+	"\x81\x45\xCC\x82\xCC\x80\x65\xCC\x82\xCC\x80\x45\xCC\x82\xCC\x89\x65\xCC\x82\xCC\x89\x45\xCC\x82\xCC"
+	"\x83\x65\xCC\x82\xCC\x83\x45\xCC\xA3\xCC\x82\x65\xCC\xA3\xCC\x82\x49\xCC\x89\x69\xCC\x89\x49\xCC\xA3"
+	"\x69\xCC\xA3\x4F\xCC\xA3\x6F\xCC\xA3\x4F\xCC\x89\x6F\xCC\x89\x4F\xCC\x82\xCC\x81\x6F\xCC\x82\xCC\x81"
+	"\x4F\xCC\x82\xCC\x80\x6F\xCC\x82\xCC\x80\x4F\xCC\x82\xCC\x89\x6F\xCC\x82\xCC\x89\x4F\xCC\x82\xCC\x83"
+	"\x6F\xCC\x82\xCC\x83\x4F\xCC\xA3\xCC\x82\x6F\xCC\xA3\xCC\x82\x4F\xCC\x9B\xCC\x81\x6F\xCC\x9B\xCC\x81"
+	"\x4F\xCC\x9B\xCC\x80\x6F\xCC\x9B\xCC\x80\x4F\xCC\x9B\xCC\x89\x6F\xCC\x9B\xCC\x89\x4F\xCC\x9B\xCC\x83"
+	"\x6F\xCC\x9B\xCC\x83\x4F\xCC\x9B\xCC\xA3\x6F\xCC\x9B\xCC\xA3\x55\xCC\xA3\x75\xCC\xA3\x55\xCC\x89\x75"
+	"\xCC\x89\x55\xCC\x9B\xCC\x81\x75\xCC\x9B\xCC\x81\x55\xCC\x9B\xCC\x80\x75\xCC\x9B\xCC\x80\x55\xCC\x9B"
+	"\xCC\x89\x75\xCC\x9B\xCC\x89\x55\xCC\x9B\xCC\x83\x75\xCC\x9B\xCC\x83\x55\xCC\x9B\xCC\xA3\x75\xCC\x9B"
+	"\xCC\xA3\x59\xCC\x80\x79\xCC\x80\x59\xCC\xA3\x79\xCC\xA3\x59\xCC\x89\x79\xCC\x89\x59\xCC\x83\x79\xCC"
+	"\x83\xCE\xB1\xCC\x93\xCE\xB1\xCC\x94\xCE\xB1\xCC\x93\xCC\x80\xCE\xB1\xCC\x94\xCC\x80\xCE\xB1\xCC\x93"
+	"\xCC\x81\xCE\xB1\xCC\x94\xCC\x81\xCE\xB1\xCC\x93\xCD\x82\xCE\xB1\xCC\x94\xCD\x82\xCE\x91\xCC\x93\xCE"
+	"\x91\xCC\x94\xCE\x91\xCC\x93\xCC\x80\xCE\x91\xCC\x94\xCC\x80\xCE\x91\xCC\x93\xCC\x81\xCE\x91\xCC\x94"
+	"\xCC\x81\xCE\x91\xCC\x93\xCD\x82\xCE\x91\xCC\x94\xCD\x82\xCE\xB5\xCC\x93\xCE\xB5\xCC\x94\xCE\xB5\xCC"
+	"\x93\xCC\x80\xCE\xB5\xCC\x94\xCC\x80\xCE\xB5\xCC\x93\xCC\x81\xCE\xB5\xCC\x94\xCC\x81\xCE\x95\xCC\x93"
+	"\xCE\x95\xCC\x94\xCE\x95\xCC\x93\xCC\x80\xCE\x95\xCC\x94\xCC\x80\xCE\x95\xCC\x93\xCC\x81\xCE\x95\xCC"
+	"\x94\xCC\x81\xCE\xB7\xCC\x93\xCE\xB7\xCC\x94\xCE\xB7\xCC\x93\xCC\x80\xCE\xB7\xCC\x94\xCC\x80\xCE\xB7"
+	"\xCC\x93\xCC\x81\xCE\xB7\xCC\x94\xCC\x81\xCE\xB7\xCC\x93\xCD\x82\xCE\xB7\xCC\x94\xCD\x82\xCE\x97\xCC"
+	"\x93\xCE\x97\xCC\x94\xCE\x97\xCC\x93\xCC\x80\xCE\x97\xCC\x94\xCC\x80\xCE\x97\xCC\x93\xCC\x81\xCE\x97"
+	"\xCC\x94\xCC\x81\xCE\x97\xCC\x93\xCD\x82\xCE\x97\xCC\x94\xCD\x82\xCE\xB9\xCC\x93\xCE\xB9\xCC\x94\xCE"
+	"\xB9\xCC\x93\xCC\x80\xCE\xB9\xCC\x94\xCC\x80\xCE\xB9\xCC\x93\xCC\x81\xCE\xB9\xCC\x94\xCC\x81\xCE\xB9"
+	"\xCC\x93\xCD\x82\xCE\xB9\xCC\x94\xCD\x82\xCE\x99\xCC\x93\xCE\x99\xCC\x94\xCE\x99\xCC\x93\xCC\x80\xCE"
+	"\x99\xCC\x94\xCC\x80\xCE\x99\xCC\x93\xCC\x81\xCE\x99\xCC\x94\xCC\x81\xCE\x99\xCC\x93\xCD\x82\xCE\x99"
+	"\xCC\x94\xCD\x82\xCE\xBF\xCC\x93\xCE\xBF\xCC\x94\xCE\xBF\xCC\x93\xCC\x80\xCE\xBF\xCC\x94\xCC\x80\xCE"
+	"\xBF\xCC\x93\xCC\x81\xCE\xBF\xCC\x94\xCC\x81\xCE\x9F\xCC\x93\xCE\x9F\xCC\x94\xCE\x9F\xCC\x93\xCC\x80"
+	"\xCE\x9F\xCC\x94\xCC\x80\xCE\x9F\xCC\x93\xCC\x81\xCE\x9F\xCC\x94\xCC\x81\xCF\x85\xCC\x93\xCF\x85\xCC"
+	"\x94\xCF\x85\xCC\x93\xCC\x80\xCF\x85\xCC\x94\xCC\x80\xCF\x85\xCC\x93\xCC\x81\xCF\x85\xCC\x94\xCC\x81"
+	"\xCF\x85\xCC\x93\xCD\x82\xCF\x85\xCC\x94\xCD\x82\xCE\xA5\xCC\x94\xCE\xA5\xCC\x94\xCC\x80\xCE\xA5\xCC"
+	"\x94\xCC\x81\xCE\xA5\xCC\x94\xCD\x82\xCF\x89\xCC\x93\xCF\x89\xCC\x94\xCF\x89\xCC\x93\xCC\x80\xCF\x89"
+	"\xCC\x94\xCC\x80\xCF\x89\xCC\x93\xCC\x81\xCF\x89\xCC\x94\xCC\x81\xCF\x89\xCC\x93\xCD\x82\xCF\x89\xCC"
+	"\x94\xCD\x82\xCE\xA9\xCC\x93\xCE\xA9\xCC\x94\xCE\xA9\xCC\x93\xCC\x80\xCE\xA9\xCC\x94\xCC\x80\xCE\xA9"
+	"\xCC\x93\xCC\x81\xCE\xA9\xCC\x94\xCC\x81\xCE\xA9\xCC\x93\xCD\x82\xCE\xA9\xCC\x94\xCD\x82\xCE\xB1\xCC"
+	"\x80\xCE\xB5\xCC\x80\xCE\xB7\xCC\x80\xCE\xB9\xCC\x80\xCE\xBF\xCC\x80\xCF\x85\xCC\x80\xCF\x89\xCC\x80"
+	"\xCE\xB1\xCC\x93\xCD\x85\xCE\xB1\xCC\x94\xCD\x85\xCE\xB1\xCC\x93\xCC\x80\xCD\x85\xCE\xB1\xCC\x94\xCC"
+	"\x80\xCD\x85\xCE\xB1\xCC\x93\xCC\x81\xCD\x85\xCE\xB1\xCC\x94\xCC\x81\xCD\x85\xCE\xB1\xCC\x93\xCD\x82"
+	"\xCD\x85\xCE\xB1\xCC\x94\xCD\x82\xCD\x85\xCE\x91\xCC\x93\xCD\x85\xCE\x91\xCC\x94\xCD\x85\xCE\x91\xCC"
+	"\x93\xCC\x80\xCD\x85\xCE\x91\xCC\x94\xCC\x80\xCD\x85\xCE\x91\xCC\x93\xCC\x81\xCD\x85\xCE\x91\xCC\x94"
+	"\xCC\x81\xCD\x85\xCE\x91\xCC\x93\xCD\x82\xCD\x85\xCE\x91\xCC\x94\xCD\x82\xCD\x85\xCE\xB7\xCC\x93\xCD"
+	"\x85\xCE\xB7\xCC\x94\xCD\x85\xCE\xB7\xCC\x93\xCC\x80\xCD\x85\xCE\xB7\xCC\x94\xCC\x80\xCD\x85\xCE\xB7"
+	"\xCC\x93\xCC\x81\xCD\x85\xCE\xB7\xCC\x94\xCC\x81\xCD\x85\xCE\xB7\xCC\x93\xCD\x82\xCD\x85\xCE\xB7\xCC"
+	"\x94\xCD\x82\xCD\x85\xCE\x97\xCC\x93\xCD\x85\xCE\x97\xCC\x94\xCD\x85\xCE\x97\xCC\x93\xCC\x80\xCD\x85"
+	"\xCE\x97\xCC\x94\xCC\x80\xCD\x85\xCE\x97\xCC\x93\xCC\x81\xCD\x85\xCE\x97\xCC\x94\xCC\x81\xCD\x85\xCE"
+	"\x97\xCC\x93\xCD\x82\xCD\x85\xCE\x97\xCC\x94\xCD\x82\xCD\x85\xCF\x89\xCC\x93\xCD\x85\xCF\x89\xCC\x94"
+	"\xCD\x85\xCF\x89\xCC\x93\xCC\x80\xCD\x85\xCF\x89\xCC\x94\xCC\x80\xCD\x85\xCF\x89\xCC\x93\xCC\x81\xCD"
+	"\x85\xCF\x89\xCC\x94\xCC\x81\xCD\x85\xCF\x89\xCC\x93\xCD\x82\xCD\x85\xCF\x89\xCC\x94\xCD\x82\xCD\x85"
+	"\xCE\xA9\xCC\x93\xCD\x85\xCE\xA9\xCC\x94\xCD\x85\xCE\xA9\xCC\x93\xCC\x80\xCD\x85\xCE\xA9\xCC\x94\xCC"
+	"\x80\xCD\x85\xCE\xA9\xCC\x93\xCC\x81\xCD\x85\xCE\xA9\xCC\x94\xCC\x81\xCD\x85\xCE\xA9\xCC\x93\xCD\x82"
+	"\xCD\x85\xCE\xA9\xCC\x94\xCD\x82\xCD\x85\xCE\xB1\xCC\x86\xCE\xB1\xCC\x84\xCE\xB1\xCC\x80\xCD\x85\xCE"
+	"\xB1\xCD\x85\xCE\xB1\xCC\x81\xCD\x85\xCE\xB1\xCD\x82\xCE\xB1\xCD\x82\xCD\x85\xCE\x91\xCC\x86\xCE\x91"
+	"\xCC\x84\xCE\x91\xCC\x80\xCE\x91\xCD\x85\xC2\xA8\xCD\x82\xCE\xB7\xCC\x80\xCD\x85\xCE\xB7\xCD\x85\xCE"
+	"\xB7\xCC\x81\xCD\x85\xCE\xB7\xCD\x82\xCE\xB7\xCD\x82\xCD\x85\xCE\x95\xCC\x80\xCE\x97\xCC\x80\xCE\x97"
+	"\xCD\x85\xE1\xBE\xBF\xCC\x80\xE1\xBE\xBF\xCC\x81\xE1\xBE\xBF\xCD\x82\xCE\xB9\xCC\x86\xCE\xB9\xCC\x84"
+	"\xCE\xB9\xCC\x88\xCC\x80\xCE\xB9\xCD\x82\xCE\xB9\xCC\x88\xCD\x82\xCE\x99\xCC\x86\xCE\x99\xCC\x84\xCE"
+	"\x99\xCC\x80\xE1\xBF\xBE\xCC\x80\xE1\xBF\xBE\xCC\x81\xE1\xBF\xBE\xCD\x82\xCF\x85\xCC\x86\xCF\x85\xCC"
+	"\x84\xCF\x85\xCC\x88\xCC\x80\xCF\x81\xCC\x93\xCF\x81\xCC\x94\xCF\x85\xCD\x82\xCF\x85\xCC\x88\xCD\x82"
+	"\xCE\xA5\xCC\x86\xCE\xA5\xCC\x84\xCE\xA5\xCC\x80\xCE\xA1\xCC\x94\xC2\xA8\xCC\x80\x60\xCF\x89\xCC\x80"
+	"\xCD\x85\xCF\x89\xCD\x85\xCF\x89\xCC\x81\xCD\x85\xCF\x89\xCD\x82\xCF\x89\xCD\x82\xCD\x85\xCE\x9F\xCC"
+	"\x80\xCE\xA9\xCC\x80\xCE\xA9\xCD\x85\xC2\xB4\xE2\x80\x82\xE2\x80\x83\xE2\x86\x90\xCC\xB8\xE2\x86\x92"
+	"\xCC\xB8\xE2\x86\x94\xCC\xB8\xE2\x87\x90\xCC\xB8\xE2\x87\x94\xCC\xB8\xE2\x87\x92\xCC\xB8\xE2\x88\x83"
+	"\xCC\xB8\xE2\x88\x88\xCC\xB8\xE2\x88\x8B\xCC\xB8\xE2\x88\xA3\xCC\xB8\xE2\x88\xA5\xCC\xB8\xE2\x88\xBC"
+	"\xCC\xB8\xE2\x89\x83\xCC\xB8\xE2\x89\x85\xCC\xB8\xE2\x89\x88\xCC\xB8\x3D\xCC\xB8\xE2\x89\xA1\xCC\xB8"
+	"\xE2\x89\x8D\xCC\xB8\x3C\xCC\xB8\x3E\xCC\xB8\xE2\x89\xA4\xCC\xB8\xE2\x89\xA5\xCC\xB8\xE2\x89\xB2\xCC"
+	"\xB8\xE2\x89\xB3\xCC\xB8\xE2\x89\xB6\xCC\xB8\xE2\x89\xB7\xCC\xB8\xE2\x89\xBA\xCC\xB8\xE2\x89\xBB\xCC"
+	"\xB8\xE2\x8A\x82\xCC\xB8\xE2\x8A\x83\xCC\xB8\xE2\x8A\x86\xCC\xB8\xE2\x8A\x87\xCC\xB8\xE2\x8A\xA2\xCC"
+	"\xB8\xE2\x8A\xA8\xCC\xB8\xE2\x8A\xA9\xCC\xB8\xE2\x8A\xAB\xCC\xB8\xE2\x89\xBC\xCC\xB8\xE2\x89\xBD\xCC"
+	"\xB8\xE2\x8A\x91\xCC\xB8\xE2\x8A\x92\xCC\xB8\xE2\x8A\xB2\xCC\xB8\xE2\x8A\xB3\xCC\xB8\xE2\x8A\xB4\xCC"
+	"\xB8\xE2\x8A\xB5\xCC\xB8\xE3\x80\x88\xE3\x80\x89\xE2\xAB\x9D\xCC\xB8\xE3\x81\x8B\xE3\x82\x99\xE3\x81"
+	"\x8D\xE3\x82\x99\xE3\x81\x8F\xE3\x82\x99\xE3\x81\x91\xE3\x82\x99\xE3\x81\x93\xE3\x82\x99\xE3\x81\x95"
+	"\xE3\x82\x99\xE3\x81\x97\xE3\x82\x99\xE3\x81\x99\xE3\x82\x99\xE3\x81\x9B\xE3\x82\x99\xE3\x81\x9D\xE3"
+	"\x82\x99\xE3\x81\x9F\xE3\x82\x99\xE3\x81\xA1\xE3\x82\x99\xE3\x81\xA4\xE3\x82\x99\xE3\x81\xA6\xE3\x82"
+	"\x99\xE3\x81\xA8\xE3\x82\x99\xE3\x81\xAF\xE3\x82\x99\xE3\x81\xAF\xE3\x82\x9A\xE3\x81\xB2\xE3\x82\x99"
+	"\xE3\x81\xB2\xE3\x82\x9A\xE3\x81\xB5\xE3\x82\x99\xE3\x81\xB5\xE3\x82\x9A\xE3\x81\xB8\xE3\x82\x99\xE3"
+	"\x81\xB8\xE3\x82\x9A\xE3\x81\xBB\xE3\x82\x99\xE3\x81\xBB\xE3\x82\x9A\xE3\x81\x86\xE3\x82\x99\xE3\x82"
+	"\x9D\xE3\x82\x99\xE3\x82\xAB\xE3\x82\x99\xE3\x82\xAD\xE3\x82\x99\xE3\x82\xAF\xE3\x82\x99\xE3\x82\xB1"
+	"\xE3\x82\x99\xE3\x82\xB3\xE3\x82\x99\xE3\x82\xB5\xE3\x82\x99\xE3\x82\xB7\xE3\x82\x99\xE3\x82\xB9\xE3"
+	"\x82\x99\xE3\x82\xBB\xE3\x82\x99\xE3\x82\xBD\xE3\x82\x99\xE3\x82\xBF\xE3\x82\x99\xE3\x83\x81\xE3\x82"
+	"\x99\xE3\x83\x84\xE3\x82\x99\xE3\x83\x86\xE3\x82\x99\xE3\x83\x88\xE3\x82\x99\xE3\x83\x8F\xE3\x82\x99"
+	"\xE3\x83\x8F\xE3\x82\x9A\xE3\x83\x92\xE3\x82\x99\xE3\x83\x92\xE3\x82\x9A\xE3\x83\x95\xE3\x82\x99\xE3"
+	"\x83\x95\xE3\x82\x9A\xE3\x83\x98\xE3\x82\x99\xE3\x83\x98\xE3\x82\x9A\xE3\x83\x9B\xE3\x82\x99\xE3\x83"
+	"\x9B\xE3\x82\x9A\xE3\x82\xA6\xE3\x82\x99\xE3\x83\xAF\xE3\x82\x99\xE3\x83\xB0\xE3\x82\x99\xE3\x83\xB1"
+	"\xE3\x82\x99\xE3\x83\xB2\xE3\x82\x99\xE3\x83\xBD\xE3\x82\x99\xE8\xB1\x88\xE6\x9B\xB4\xE8\xBB\x8A\xE8"
+	"\xB3\x88\xE6\xBB\x91\xE4\xB8\xB2\xE5\x8F\xA5\xE9\xBE\x9C\xE5\xA5\x91\xE9\x87\x91\xE5\x96\x87\xE5\xA5"
+	"\x88\xE6\x87\xB6\xE7\x99\xA9\xE7\xBE\x85\xE8\x98\xBF\xE8\x9E\xBA\xE8\xA3\xB8\xE9\x82\x8F\xE6\xA8\x82"
+	"\xE6\xB4\x9B\xE7\x83\x99\xE7\x8F\x9E\xE8\x90\xBD\xE9\x85\xAA\xE9\xA7\xB1\xE4\xBA\x82\xE5\x8D\xB5\xE6"
+	"\xAC\x84\xE7\x88\x9B\xE8\x98\xAD\xE9\xB8\x9E\xE5\xB5\x90\xE6\xBF\xAB\xE8\x97\x8D\xE8\xA5\xA4\xE6\x8B"
+	"\x89\xE8\x87\x98\xE8\xA0\x9F\xE5\xBB\x8A\xE6\x9C\x97\xE6\xB5\xAA\xE7\x8B\xBC\xE9\x83\x8E\xE4\xBE\x86"
+	"\xE5\x86\xB7\xE5\x8B\x9E\xE6\x93\x84\xE6\xAB\x93\xE7\x88\x90\xE7\x9B\xA7\xE8\x80\x81\xE8\x98\x86\xE8"
+	"\x99\x9C\xE8\xB7\xAF\xE9\x9C\xB2\xE9\xAD\xAF\xE9\xB7\xBA\xE7\xA2\x8C\xE7\xA5\xBF\xE7\xB6\xA0\xE8\x8F"
+	"\x89\xE9\x8C\x84\xE9\xB9\xBF\xE8\xAB\x96\xE5\xA3\x9F\xE5\xBC\x84\xE7\xB1\xA0\xE8\x81\xBE\xE7\x89\xA2"
+	"\xE7\xA3\x8A\xE8\xB3\x82\xE9\x9B\xB7\xE5\xA3\x98\xE5\xB1\xA2\xE6\xA8\x93\xE6\xB7\x9A\xE6\xBC\x8F\xE7"
+	"\xB4\xAF\xE7\xB8\xB7\xE9\x99\x8B\xE5\x8B\x92\xE8\x82\x8B\xE5\x87\x9C\xE5\x87\x8C\xE7\xA8\x9C\xE7\xB6"
+	"\xBE\xE8\x8F\xB1\xE9\x99\xB5\xE8\xAE\x80\xE6\x8B\x8F\xE8\xAB\xBE\xE4\xB8\xB9\xE5\xAF\xA7\xE6\x80\x92"
+	"\xE7\x8E\x87\xE7\x95\xB0\xE5\x8C\x97\xE7\xA3\xBB\xE4\xBE\xBF\xE5\xBE\xA9\xE4\xB8\x8D\xE6\xB3\x8C\xE6"
+	"\x95\xB8\xE7\xB4\xA2\xE5\x8F\x83\xE5\xA1\x9E\xE7\x9C\x81\xE8\x91\x89\xE8\xAA\xAA\xE6\xAE\xBA\xE8\xBE"
+	"\xB0\xE6\xB2\x88\xE6\x8B\xBE\xE8\x8B\xA5\xE6\x8E\xA0\xE7\x95\xA5\xE4\xBA\xAE\xE5\x85\xA9\xE5\x87\x89"
+	"\xE6\xA2\x81\xE7\xB3\xA7\xE8\x89\xAF\xE8\xAB\x92\xE9\x87\x8F\xE5\x8B\xB5\xE5\x91\x82\xE5\xA5\xB3\xE5"
+	"\xBB\xAC\xE6\x97\x85\xE6\xBF\xBE\xE7\xA4\xAA\xE9\x96\xAD\xE9\xA9\xAA\xE9\xBA\x97\xE9\xBB\x8E\xE5\x8A"
+	"\x9B\xE6\x9B\x86\xE6\xAD\xB7\xE8\xBD\xA2\xE5\xB9\xB4\xE6\x86\x90\xE6\x88\x80\xE6\x92\x9A\xE6\xBC\xA3"
+	"\xE7\x85\x89\xE7\x92\x89\xE7\xA7\x8A\xE7\xB7\xB4\xE8\x81\xAF\xE8\xBC\xA6\xE8\x93\xAE\xE9\x80\xA3\xE9"
+	"\x8D\x8A\xE5\x88\x97\xE5\x8A\xA3\xE5\x92\xBD\xE7\x83\x88\xE8\xA3\x82\xE5\xBB\x89\xE5\xBF\xB5\xE6\x8D"
+	"\xBB\xE6\xAE\xAE\xE7\xB0\xBE\xE7\x8D\xB5\xE4\xBB\xA4\xE5\x9B\xB9\xE5\xB6\xBA\xE6\x80\x9C\xE7\x8E\xB2"
+	"\xE7\x91\xA9\xE7\xBE\x9A\xE8\x81\x86\xE9\x88\xB4\xE9\x9B\xB6\xE9\x9D\x88\xE9\xA0\x98\xE4\xBE\x8B\xE7"
+	"\xA6\xAE\xE9\x86\xB4\xE9\x9A\xB8\xE6\x83\xA1\xE4\xBA\x86\xE5\x83\x9A\xE5\xAF\xAE\xE5\xB0\xBF\xE6\x96"
+	"\x99\xE7\x87\x8E\xE7\x99\x82\xE8\x93\xBC\xE9\x81\xBC\xE9\xBE\x8D\xE6\x9A\x88\xE9\x98\xAE\xE5\x8A\x89"
+	"\xE6\x9D\xBB\xE6\x9F\xB3\xE6\xB5\x81\xE6\xBA\x9C\xE7\x90\x89\xE7\x95\x99\xE7\xA1\xAB\xE7\xB4\x90\xE9"
+	"\xA1\x9E\xE5\x85\xAD\xE6\x88\xAE\xE9\x99\xB8\xE5\x80\xAB\xE5\xB4\x99\xE6\xB7\xAA\xE8\xBC\xAA\xE5\xBE"
+	"\x8B\xE6\x85\x84\xE6\xA0\x97\xE9\x9A\x86\xE5\x88\xA9\xE5\x90\x8F\xE5\xB1\xA5\xE6\x98\x93\xE6\x9D\x8E"
+	"\xE6\xA2\xA8\xE6\xB3\xA5\xE7\x90\x86\xE7\x97\xA2\xE7\xBD\xB9\xE8\xA3\x8F\xE8\xA3\xA1\xE9\x87\x8C\xE9"
+	"\x9B\xA2\xE5\x8C\xBF\xE6\xBA\xBA\xE5\x90\x9D\xE7\x87\x90\xE7\x92\x98\xE8\x97\xBA\xE9\x9A\xA3\xE9\xB1"
+	"\x97\xE9\xBA\x9F\xE6\x9E\x97\xE6\xB7\x8B\xE8\x87\xA8\xE7\xAB\x8B\xE7\xAC\xA0\xE7\xB2\x92\xE7\x8B\x80"
+	"\xE7\x82\x99\xE8\xAD\x98\xE4\xBB\x80\xE8\x8C\xB6\xE5\x88\xBA\xE5\x88\x87\xE5\xBA\xA6\xE6\x8B\x93\xE7"
+	"\xB3\x96\xE5\xAE\x85\xE6\xB4\x9E\xE6\x9A\xB4\xE8\xBC\xBB\xE8\xA1\x8C\xE9\x99\x8D\xE8\xA6\x8B\xE5\xBB"
+	"\x93\xE5\x85\x80\xE5\x97\x80\xE5\xA1\x9A\xE6\x99\xB4\xE5\x87\x9E\xE7\x8C\xAA\xE7\x9B\x8A\xE7\xA4\xBC"
+	"\xE7\xA5\x9E\xE7\xA5\xA5\xE7\xA6\x8F\xE9\x9D\x96\xE7\xB2\xBE\xE7\xBE\xBD\xE8\x98\x92\xE8\xAB\xB8\xE9"
+	"\x80\xB8\xE9\x83\xBD\xE9\xA3\xAF\xE9\xA3\xBC\xE9\xA4\xA8\xE9\xB6\xB4\xE9\x83\x9E\xE9\x9A\xB7\xE4\xBE"
+	"\xAE\xE5\x83\xA7\xE5\x85\x8D\xE5\x8B\x89\xE5\x8B\xA4\xE5\x8D\x91\xE5\x96\x9D\xE5\x98\x86\xE5\x99\xA8"
+	"\xE5\xA1\x80\xE5\xA2\xA8\xE5\xB1\xA4\xE5\xB1\xAE\xE6\x82\x94\xE6\x85\xA8\xE6\x86\x8E\xE6\x87\xB2\xE6"
+	"\x95\x8F\xE6\x97\xA2\xE6\x9A\x91\xE6\xA2\x85\xE6\xB5\xB7\xE6\xB8\x9A\xE6\xBC\xA2\xE7\x85\xAE\xE7\x88"
+	"\xAB\xE7\x90\xA2\xE7\xA2\x91\xE7\xA4\xBE\xE7\xA5\x89\xE7\xA5\x88\xE7\xA5\x90\xE7\xA5\x96\xE7\xA5\x9D"
+	"\xE7\xA6\x8D\xE7\xA6\x8E\xE7\xA9\x80\xE7\xAA\x81\xE7\xAF\x80\xE7\xB8\x89\xE7\xB9\x81\xE7\xBD\xB2\xE8"
+	"\x80\x85\xE8\x87\xAD\xE8\x89\xB9\xE8\x91\x97\xE8\xA4\x90\xE8\xA6\x96\xE8\xAC\x81\xE8\xAC\xB9\xE8\xB3"
+	"\x93\xE8\xB4\x88\xE8\xBE\xB6\xE9\x9B\xA3\xE9\x9F\xBF\xE9\xA0\xBB\xE6\x81\xB5\xF0\xA4\x8B\xAE\xE8\x88"
+	"\x98\xE4\xB8\xA6\xE5\x86\xB5\xE5\x85\xA8\xE4\xBE\x80\xE5\x85\x85\xE5\x86\x80\xE5\x8B\x87\xE5\x8B\xBA"
+	"\xE5\x95\x95\xE5\x96\x99\xE5\x97\xA2\xE5\xA2\xB3\xE5\xA5\x84\xE5\xA5\x94\xE5\xA9\xA2\xE5\xAC\xA8\xE5"
+	"\xBB\x92\xE5\xBB\x99\xE5\xBD\xA9\xE5\xBE\xAD\xE6\x83\x98\xE6\x85\x8E\xE6\x84\x88\xE6\x85\xA0\xE6\x88"
+	"\xB4\xE6\x8F\x84\xE6\x90\x9C\xE6\x91\x92\xE6\x95\x96\xE6\x9C\x9B\xE6\x9D\x96\xE6\xAD\xB9\xE6\xBB\x9B"
+	"\xE6\xBB\x8B\xE7\x80\x9E\xE7\x9E\xA7\xE7\x88\xB5\xE7\x8A\xAF\xE7\x91\xB1\xE7\x94\x86\xE7\x94\xBB\xE7"
+	"\x98\x9D\xE7\x98\x9F\xE7\x9B\x9B\xE7\x9B\xB4\xE7\x9D\x8A\xE7\x9D\x80\xE7\xA3\x8C\xE7\xAA\xB1\xE7\xB1"
+	"\xBB\xE7\xB5\x9B\xE7\xBC\xBE\xE8\x8D\x92\xE8\x8F\xAF\xE8\x9D\xB9\xE8\xA5\x81\xE8\xA6\x86\xE8\xAA\xBF"
+	"\xE8\xAB\x8B\xE8\xAB\xAD\xE8\xAE\x8A\xE8\xBC\xB8\xE9\x81\xB2\xE9\x86\x99\xE9\x89\xB6\xE9\x99\xBC\xE9"
+	"\x9F\x9B\xE9\xA0\x8B\xE9\xAC\x92\xF0\xA2\xA1\x8A\xF0\xA2\xA1\x84\xF0\xA3\x8F\x95\xE3\xAE\x9D\xE4\x80"
+	"\x98\xE4\x80\xB9\xF0\xA5\x89\x89\xF0\xA5\xB3\x90\xF0\xA7\xBB\x93\xE9\xBD\x83\xE9\xBE\x8E\xD7\x99\xD6"
+	"\xB4\xD7\xB2\xD6\xB7\xD7\xA9\xD7\x81\xD7\xA9\xD7\x82\xD7\xA9\xD6\xBC\xD7\x81\xD7\xA9\xD6\xBC\xD7\x82"
+	"\xD7\x90\xD6\xB7\xD7\x90\xD6\xB8\xD7\x90\xD6\xBC\xD7\x91\xD6\xBC\xD7\x92\xD6\xBC\xD7\x93\xD6\xBC\xD7"
+	"\x94\xD6\xBC\xD7\x95\xD6\xBC\xD7\x96\xD6\xBC\xD7\x98\xD6\xBC\xD7\x99\xD6\xBC\xD7\x9A\xD6\xBC\xD7\x9B"
+	"\xD6\xBC\xD7\x9C\xD6\xBC\xD7\x9E\xD6\xBC\xD7\xA0\xD6\xBC\xD7\xA1\xD6\xBC\xD7\xA3\xD6\xBC\xD7\xA4\xD6"
+	"\xBC\xD7\xA6\xD6\xBC\xD7\xA7\xD6\xBC\xD7\xA8\xD6\xBC\xD7\xAA\xD6\xBC\xD7\x95\xD6\xB9\xD7\x91\xD6\xBF"
+	"\xD7\x9B\xD6\xBF\xD7\xA4\xD6\xBF\xF0\x91\x82\x99\xF0\x91\x82\xBA\xF0\x91\x82\x9B\xF0\x91\x82\xBA\xF0"
+	"\x91\x82\xA5\xF0\x91\x82\xBA\xF0\x91\x84\xB1\xF0\x91\x84\xA7\xF0\x91\x84\xB2\xF0\x91\x84\xA7\xF0\x91"
+	"\x8D\x87\xF0\x91\x8C\xBE\xF0\x91\x8D\x87\xF0\x91\x8D\x97\xF0\x91\x92\xB9\xF0\x91\x92\xBA\xF0\x91\x92"
+	"\xB9\xF0\x91\x92\xB0\xF0\x91\x92\xB9\xF0\x91\x92\xBD\xF0\x91\x96\xB8\xF0\x91\x96\xAF\xF0\x91\x96\xB9"
+	"\xF0\x91\x96\xAF\xF0\x9D\x85\x97\xF0\x9D\x85\xA5\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\x98\xF0"
+	"\x9D\x85\xA5\xF0\x9D\x85\xAE\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\xAF\xF0\x9D\x85\x98\xF0\x9D"
+	"\x85\xA5\xF0\x9D\x85\xB0\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\xB1\xF0\x9D\x85\x98\xF0\x9D\x85"
+	"\xA5\xF0\x9D\x85\xB2\xF0\x9D\x86\xB9\xF0\x9D\x85\xA5\xF0\x9D\x86\xBA\xF0\x9D\x85\xA5\xF0\x9D\x86\xB9"
+	"\xF0\x9D\x85\xA5\xF0\x9D\x85\xAE\xF0\x9D\x86\xBA\xF0\x9D\x85\xA5\xF0\x9D\x85\xAE\xF0\x9D\x86\xB9\xF0"
+	"\x9D\x85\xA5\xF0\x9D\x85\xAF\xF0\x9D\x86\xBA\xF0\x9D\x85\xA5\xF0\x9D\x85\xAF\xE4\xB8\xBD\xE4\xB8\xB8"
+	"\xE4\xB9\x81\xF0\xA0\x84\xA2\xE4\xBD\xA0\xE4\xBE\xBB\xE5\x80\x82\xE5\x81\xBA\xE5\x82\x99\xE5\x83\x8F"
+	"\xE3\x92\x9E\xF0\xA0\x98\xBA\xE5\x85\x94\xE5\x85\xA4\xE5\x85\xB7\xF0\xA0\x94\x9C\xE3\x92\xB9\xE5\x85"
+	"\xA7\xE5\x86\x8D\xF0\xA0\x95\x8B\xE5\x86\x97\xE5\x86\xA4\xE4\xBB\x8C\xE5\x86\xAC\xF0\xA9\x87\x9F\xE5"
+	"\x87\xB5\xE5\x88\x83\xE3\x93\x9F\xE5\x88\xBB\xE5\x89\x86\xE5\x89\xB2\xE5\x89\xB7\xE3\x94\x95\xE5\x8C"
+	"\x85\xE5\x8C\x86\xE5\x8D\x89\xE5\x8D\x9A\xE5\x8D\xB3\xE5\x8D\xBD\xE5\x8D\xBF\xF0\xA0\xA8\xAC\xE7\x81"
+	"\xB0\xE5\x8F\x8A\xE5\x8F\x9F\xF0\xA0\xAD\xA3\xE5\x8F\xAB\xE5\x8F\xB1\xE5\x90\x86\xE5\x92\x9E\xE5\x90"
+	"\xB8\xE5\x91\x88\xE5\x91\xA8\xE5\x92\xA2\xE5\x93\xB6\xE5\x94\x90\xE5\x95\x93\xE5\x95\xA3\xE5\x96\x84"
+	"\xE5\x96\xAB\xE5\x96\xB3\xE5\x97\x82\xE5\x9C\x96\xE5\x9C\x97\xE5\x99\x91\xE5\x99\xB4\xE5\xA3\xAE\xE5"
+	"\x9F\x8E\xE5\x9F\xB4\xE5\xA0\x8D\xE5\x9E\x8B\xE5\xA0\xB2\xE5\xA0\xB1\xE5\xA2\xAC\xF0\xA1\x93\xA4\xE5"
+	"\xA3\xB2\xE5\xA3\xB7\xE5\xA4\x86\xE5\xA4\x9A\xE5\xA4\xA2\xE5\xA5\xA2\xF0\xA1\x9A\xA8\xF0\xA1\x9B\xAA"
+	"\xE5\xA7\xAC\xE5\xA8\x9B\xE5\xA8\xA7\xE5\xA7\x98\xE5\xA9\xA6\xE3\x9B\xAE\xE3\x9B\xBC\xE5\xAC\x88\xE5"
+	"\xAC\xBE\xF0\xA1\xA7\x88\xE5\xAF\x83\xE5\xAF\x98\xE5\xAF\xB3\xF0\xA1\xAC\x98\xE5\xAF\xBF\xE5\xB0\x86"
+	"\xE5\xBD\x93\xE5\xB0\xA2\xE3\x9E\x81\xE5\xB1\xA0\xE5\xB3\x80\xE5\xB2\x8D\xF0\xA1\xB7\xA4\xE5\xB5\x83"
+	"\xF0\xA1\xB7\xA6\xE5\xB5\xAE\xE5\xB5\xAB\xE5\xB5\xBC\xE5\xB7\xA1\xE5\xB7\xA2\xE3\xA0\xAF\xE5\xB7\xBD"
+	"\xE5\xB8\xA8\xE5\xB8\xBD\xE5\xB9\xA9\xE3\xA1\xA2\xF0\xA2\x86\x83\xE3\xA1\xBC\xE5\xBA\xB0\xE5\xBA\xB3"
+	"\xE5\xBA\xB6\xF0\xAA\x8E\x92\xE5\xBB\xBE\xF0\xA2\x8C\xB1\xE8\x88\x81\xE5\xBC\xA2\xE3\xA3\x87\xF0\xA3"
+	"\x8A\xB8\xF0\xA6\x87\x9A\xE5\xBD\xA2\xE5\xBD\xAB\xE3\xA3\xA3\xE5\xBE\x9A\xE5\xBF\x8D\xE5\xBF\x97\xE5"
+	"\xBF\xB9\xE6\x82\x81\xE3\xA4\xBA\xE3\xA4\x9C\xF0\xA2\x9B\x94\xE6\x83\x87\xE6\x85\x88\xE6\x85\x8C\xE6"
+	"\x85\xBA\xE6\x86\xB2\xE6\x86\xA4\xE6\x86\xAF\xE6\x87\x9E\xE6\x88\x90\xE6\x88\x9B\xE6\x89\x9D\xE6\x8A"
+	"\xB1\xE6\x8B\x94\xE6\x8D\x90\xF0\xA2\xAC\x8C\xE6\x8C\xBD\xE6\x8B\xBC\xE6\x8D\xA8\xE6\x8E\x83\xE6\x8F"
+	"\xA4\xF0\xA2\xAF\xB1\xE6\x90\xA2\xE6\x8F\x85\xE6\x8E\xA9\xE3\xA8\xAE\xE6\x91\xA9\xE6\x91\xBE\xE6\x92"
+	"\x9D\xE6\x91\xB7\xE3\xA9\xAC\xE6\x95\xAC\xF0\xA3\x80\x8A\xE6\x97\xA3\xE6\x9B\xB8\xE6\x99\x89\xE3\xAC"
+	"\x99\xE3\xAC\x88\xE3\xAB\xA4\xE5\x86\x92\xE5\x86\x95\xE6\x9C\x80\xE6\x9A\x9C\xE8\x82\xAD\xE4\x8F\x99"
+	"\xE6\x9C\xA1\xE6\x9D\x9E\xE6\x9D\x93\xF0\xA3\x8F\x83\xE3\xAD\x89\xE6\x9F\xBA\xE6\x9E\x85\xE6\xA1\x92"
+	"\xF0\xA3\x91\xAD\xE6\xA2\x8E\xE6\xA0\x9F\xE6\xA4\x94\xE6\xA5\x82\xE6\xA6\xA3\xE6\xA7\xAA\xE6\xAA\xA8"
+	"\xF0\xA3\x9A\xA3\xE6\xAB\x9B\xE3\xB0\x98\xE6\xAC\xA1\xF0\xA3\xA2\xA7\xE6\xAD\x94\xE3\xB1\x8E\xE6\xAD"
+	"\xB2\xE6\xAE\x9F\xE6\xAE\xBB\xF0\xA3\xAA\x8D\xF0\xA1\xB4\x8B\xF0\xA3\xAB\xBA\xE6\xB1\x8E\xF0\xA3\xB2"
+	"\xBC\xE6\xB2\xBF\xE6\xB3\x8D\xE6\xB1\xA7\xE6\xB4\x96\xE6\xB4\xBE\xE6\xB5\xA9\xE6\xB5\xB8\xE6\xB6\x85"
+	"\xF0\xA3\xB4\x9E\xE6\xB4\xB4\xE6\xB8\xAF\xE6\xB9\xAE\xE3\xB4\xB3\xE6\xBB\x87\xF0\xA3\xBB\x91\xE6\xB7"
+	"\xB9\xE6\xBD\xAE\xF0\xA3\xBD\x9E\xF0\xA3\xBE\x8E\xE6\xBF\x86\xE7\x80\xB9\xE7\x80\x9B\xE3\xB6\x96\xE7"
+	"\x81\x8A\xE7\x81\xBD\xE7\x81\xB7\xE7\x82\xAD\xF0\xA0\x94\xA5\xE7\x85\x85\xF0\xA4\x89\xA3\xE7\x86\x9C"
+	"\xF0\xA4\x8E\xAB\xE7\x88\xA8\xE7\x89\x90\xF0\xA4\x98\x88\xE7\x8A\x80\xE7\x8A\x95\xF0\xA4\x9C\xB5\xF0"
+	"\xA4\xA0\x94\xE7\x8D\xBA\xE7\x8E\x8B\xE3\xBA\xAC\xE7\x8E\xA5\xE3\xBA\xB8\xE7\x91\x87\xE7\x91\x9C\xE7"
+	"\x92\x85\xE7\x93\x8A\xE3\xBC\x9B\xE7\x94\xA4\xF0\xA4\xB0\xB6\xE7\x94\xBE\xF0\xA4\xB2\x92\xF0\xA2\x86"
+	"\x9F\xE7\x98\x90\xF0\xA4\xBE\xA1\xF0\xA4\xBE\xB8\xF0\xA5\x81\x84\xE3\xBF\xBC\xE4\x80\x88\xF0\xA5\x83"
+	"\xB3\xF0\xA5\x83\xB2\xF0\xA5\x84\x99\xF0\xA5\x84\xB3\xE7\x9C\x9E\xE7\x9C\x9F\xE7\x9E\x8B\xE4\x81\x86"
+	"\xE4\x82\x96\xF0\xA5\x90\x9D\xE7\xA1\x8E\xE4\x83\xA3\xF0\xA5\x98\xA6\xF0\xA5\x9A\x9A\xF0\xA5\x9B\x85"
+	"\xE7\xA7\xAB\xE4\x84\xAF\xE7\xA9\x8A\xE7\xA9\x8F\xF0\xA5\xA5\xBC\xF0\xA5\xAA\xA7\xE7\xAB\xAE\xE4\x88"
+	"\x82\xF0\xA5\xAE\xAB\xE7\xAF\x86\xE7\xAF\x89\xE4\x88\xA7\xF0\xA5\xB2\x80\xE7\xB3\x92\xE4\x8A\xA0\xE7"
+	"\xB3\xA8\xE7\xB3\xA3\xE7\xB4\x80\xF0\xA5\xBE\x86\xE7\xB5\xA3\xE4\x8C\x81\xE7\xB7\x87\xE7\xB8\x82\xE7"
+	"\xB9\x85\xE4\x8C\xB4\xF0\xA6\x88\xA8\xF0\xA6\x89\x87\xE4\x8D\x99\xF0\xA6\x8B\x99\xE7\xBD\xBA\xF0\xA6"
+	"\x8C\xBE\xE7\xBE\x95\xE7\xBF\xBA\xF0\xA6\x93\x9A\xF0\xA6\x94\xA3\xE8\x81\xA0\xF0\xA6\x96\xA8\xE8\x81"
+	"\xB0\xF0\xA3\x8D\x9F\xE4\x8F\x95\xE8\x82\xB2\xE8\x84\x83\xE4\x90\x8B\xE8\x84\xBE\xE5\xAA\xB5\xF0\xA6"
+	"\x9E\xA7\xF0\xA6\x9E\xB5\xF0\xA3\x8E\x93\xF0\xA3\x8E\x9C\xE8\x88\x84\xE8\xBE\x9E\xE4\x91\xAB\xE8\x8A"
+	"\x91\xE8\x8A\x8B\xE8\x8A\x9D\xE5\x8A\xB3\xE8\x8A\xB1\xE8\x8A\xB3\xE8\x8A\xBD\xE8\x8B\xA6\xF0\xA6\xAC"
+	"\xBC\xE8\x8C\x9D\xE8\x8D\xA3\xE8\x8E\xAD\xE8\x8C\xA3\xE8\x8E\xBD\xE8\x8F\xA7\xE8\x8D\x93\xE8\x8F\x8A"
+	"\xE8\x8F\x8C\xE8\x8F\x9C\xF0\xA6\xB0\xB6\xF0\xA6\xB5\xAB\xF0\xA6\xB3\x95\xE4\x94\xAB\xE8\x93\xB1\xE8"
+	"\x93\xB3\xE8\x94\x96\xF0\xA7\x8F\x8A\xE8\x95\xA4\xF0\xA6\xBC\xAC\xE4\x95\x9D\xE4\x95\xA1\xF0\xA6\xBE"
+	"\xB1\xF0\xA7\x83\x92\xE4\x95\xAB\xE8\x99\x90\xE8\x99\xA7\xE8\x99\xA9\xE8\x9A\xA9\xE8\x9A\x88\xE8\x9C"
+	"\x8E\xE8\x9B\xA2\xE8\x9C\xA8\xE8\x9D\xAB\xE8\x9E\x86\xE4\x97\x97\xE8\x9F\xA1\xE8\xA0\x81\xE4\x97\xB9"
+	"\xE8\xA1\xA0\xE8\xA1\xA3\xF0\xA7\x99\xA7\xE8\xA3\x97\xE8\xA3\x9E\xE4\x98\xB5\xE8\xA3\xBA\xE3\x92\xBB"
+	"\xF0\xA7\xA2\xAE\xF0\xA7\xA5\xA6\xE4\x9A\xBE\xE4\x9B\x87\xE8\xAA\xA0\xE8\xB1\x95\xF0\xA7\xB2\xA8\xE8"
+	"\xB2\xAB\xE8\xB3\x81\xE8\xB4\x9B\xE8\xB5\xB7\xF0\xA7\xBC\xAF\xF0\xA0\xA0\x84\xE8\xB7\x8B\xE8\xB6\xBC"
+	"\xE8\xB7\xB0\xF0\xA0\xA3\x9E\xE8\xBB\x94\xF0\xA8\x97\x92\xF0\xA8\x97\xAD\xE9\x82\x94\xE9\x83\xB1\xE9"
+	"\x84\x91\xF0\xA8\x9C\xAE\xE9\x84\x9B\xE9\x88\xB8\xE9\x8B\x97\xE9\x8B\x98\xE9\x89\xBC\xE9\x8F\xB9\xE9"
+	"\x90\x95\xF0\xA8\xAF\xBA\xE9\x96\x8B\xE4\xA6\x95\xE9\x96\xB7\xF0\xA8\xB5\xB7\xE4\xA7\xA6\xE9\x9B\x83"
+	"\xE5\xB6\xB2\xE9\x9C\xA3\xF0\xA9\x85\x85\xF0\xA9\x88\x9A\xE4\xA9\xAE\xE4\xA9\xB6\xE9\x9F\xA0\xF0\xA9"
+	"\x90\x8A\xE4\xAA\xB2\xF0\xA9\x92\x96\xE9\xA0\xA9\xF0\xA9\x96\xB6\xE9\xA3\xA2\xE4\xAC\xB3\xE9\xA4\xA9"
+	"\xE9\xA6\xA7\xE9\xA7\x82\xE9\xA7\xBE\xE4\xAF\x8E\xF0\xA9\xAC\xB0\xE9\xB1\x80\xE9\xB3\xBD\xE4\xB3\x8E"
+	"\xE4\xB3\xAD\xE9\xB5\xA7\xF0\xAA\x83\x8E\xE4\xB3\xB8\xF0\xAA\x84\x85\xF0\xAA\x88\x8E\xF0\xAA\x8A\x91"
+	"\xE9\xBA\xBB\xE4\xB5\x96\xE9\xBB\xB9\xE9\xBB\xBE\xE9\xBC\x85\xE9\xBC\x8F\xE9\xBC\x96\xE9\xBC\xBB\xF0"
+	"\xAA\x98\x80\x20\x20\xCC\x88\x20\xCC\x84\x32\x33\x20\xCC\x81\xCE\xBC\x20\xCC\xA7\x31\x31\xE2\x81\x84"
+	"\x34\x31\xE2\x81\x84\x32\x33\xE2\x81\x84\x34\x49\x4A\x69\x6A\x4C\xC2\xB7\x6C\xC2\xB7\xCA\xBC\x6E\x44"
+	"\x5A\xCC\x8C\x44\x7A\xCC\x8C\x64\x7A\xCC\x8C\x4C\x4A\x4C\x6A\x6C\x6A\x4E\x4A\x4E\x6A\x6E\x6A\xC9\xA6"
+	"\xC9\xB9\xC9\xBB\xCA\x81\x20\xCC\x86\x20\xCC\x87\x20\xCC\x8A\x20\xCC\xA8\x20\xCC\x83\x20\xCC\x8B\xC9"
+	"\xA3\xCA\x95\x20\xCD\x85\x20\xCC\x88\xCC\x81\xCE\xB2\xCE\xB8\xCF\x86\xCF\x80\xCE\xBA\xCF\x82\xCE\x98"
+	"\xCE\xA3\xD5\xA5\xD6\x82\xD8\xA7\xD9\xB4\xD9\x88\xD9\xB4\xDB\x87\xD9\xB4\xD9\x8A\xD9\xB4\xE0\xB3\x86"
+	"\xE0\xB3\x82\xE0\xB3\x95\xE0\xB7\x99\xE0\xB7\x8F\xE0\xB7\x8A\xE0\xB9\x8D\xE0\xB8\xB2\xE0\xBB\x8D\xE0"
+	"\xBA\xB2\xE0\xBA\xAB\xE0\xBA\x99\xE0\xBA\xAB\xE0\xBA\xA1\xE0\xBC\x8B\xE0\xBE\xB2\xE0\xBD\xB1\xE0\xBE"
+	"\x80\xE0\xBE\xB3\xE0\xBD\xB1\xE0\xBE\x80\xE1\x83\x9C\xC6\x8E\xC8\xA2\xC9\x90\xC9\x91\xE1\xB4\x82\xC9"
+	"\x99\xC9\x9B\xC9\x9C\xC5\x8B\xC9\x94\xE1\xB4\x96\xE1\xB4\x97\xE1\xB4\x9D\xC9\xAF\xE1\xB4\xA5\xCE\xB3"
+	"\xCE\xB4\xCF\x87\xD0\xBD\xC9\x92\xC9\x95\xC3\xB0\xC9\x9F\xC9\xA1\xC9\xA5\xC9\xA8\xC9\xA9\xC9\xAA\xE1"
+	"\xB5\xBB\xCA\x9D\xC9\xAD\xE1\xB6\x85\xCA\x9F\xC9\xB1\xC9\xB0\xC9\xB2\xC9\xB3\xC9\xB4\xC9\xB5\xC9\xB8"
+	"\xCA\x82\xCA\x83\xC6\xAB\xCA\x89\xCA\x8A\xE1\xB4\x9C\xCA\x8B\xCA\x8C\xCA\x90\xCA\x91\x61\xCA\xBE\xCE"
+	"\xA5\xCC\x94\xCC\x80\xCE\xB1\xCD\x82\xCD\x85\x20\xCC\x93\x20\xCD\x82\x20\xCC\x88\xCD\x82\xCE\xB7\xCD"
+	"\x82\xCD\x85\x20\xCC\x93\xCC\x80\x20\xCC\x93\xCC\x81\x20\xCC\x93\xCD\x82\x20\xCC\x94\xCC\x80\x20\xCC"
+	"\x94\xCC\x81\x20\xCC\x94\xCD\x82\x20\xCC\x88\xCC\x80\xCF\x89\xCD\x82\xCD\x85\xE2\x80\x90\x20\xCC\xB3"
+	"\x2E\x2E\x2E\xE2\x80\xB2\xE2\x80\xB2\xE2\x80\xB2\xE2\x80\xB2\xE2\x80\xB2\xE2\x80\xB5\xE2\x80\xB5\xE2"
+	"\x80\xB5\xE2\x80\xB5\xE2\x80\xB5\x21\x21\x20\xCC\x85\x3F\x3F\x3F\x21\x21\x3F\x30\x35\x36\x37\x38\x39"
+	"\x2B\xE2\x88\x92\x28\x29\x52\x73\x61\x2F\x63\x61\x2F\x73\xC2\xB0\x43\x63\x2F\x6F\x63\x2F\x75\xC6\x90"
+	"\xC2\xB0\x46\xC4\xA7\x4E\x6F\x51\x53\x4D\x54\x45\x4C\x54\x4D\x46\x41\x58\xCE\x93\xCE\xA0\xE2\x88\x91"
+	"\x31\xE2\x81\x84\x37\x31\xE2\x81\x84\x39\x31\xE2\x81\x84\x31\x30\x31\xE2\x81\x84\x33\x32\xE2\x81\x84"
+	"\x33\x31\xE2\x81\x84\x35\x32\xE2\x81\x84\x35\x33\xE2\x81\x84\x35\x34\xE2\x81\x84\x35\x31\xE2\x81\x84"
+	"\x36\x35\xE2\x81\x84\x36\x31\xE2\x81\x84\x38\x33\xE2\x81\x84\x38\x35\xE2\x81\x84\x38\x37\xE2\x81\x84"
+	"\x38\x49\x49\x49\x49\x49\x49\x56\x56\x49\x56\x49\x49\x56\x49\x49\x49\x49\x58\x58\x49\x58\x49\x49\x69"
+	"\x69\x69\x69\x69\x69\x76\x76\x69\x76\x69\x69\x76\x69\x69\x69\x69\x78\x78\x69\x78\x69\x69\x30\xE2\x81"
+	"\x84\x33\xE2\x88\xAB\xE2\x88\xAB\xE2\x88\xAB\xE2\x88\xAB\xE2\x88\xAB\xE2\x88\xAE\xE2\x88\xAE\xE2\x88"
+	"\xAE\xE2\x88\xAE\xE2\x88\xAE\x31\x32\x31\x33\x31\x34\x31\x35\x31\x36\x31\x37\x31\x38\x31\x39\x32\x30"
+	"\x28\x31\x29\x28\x32\x29\x28\x33\x29\x28\x34\x29\x28\x35\x29\x28\x36\x29\x28\x37\x29\x28\x38\x29\x28"
+	"\x39\x29\x28\x31\x30\x29\x28\x31\x31\x29\x28\x31\x32\x29\x28\x31\x33\x29\x28\x31\x34\x29\x28\x31\x35"
+	"\x29\x28\x31\x36\x29\x28\x31\x37\x29\x28\x31\x38\x29\x28\x31\x39\x29\x28\x32\x30\x29\x31\x2E\x32\x2E"
+	"\x33\x2E\x34\x2E\x35\x2E\x36\x2E\x37\x2E\x38\x2E\x39\x2E\x31\x30\x2E\x31\x31\x2E\x31\x32\x2E\x31\x33"
+	"\x2E\x31\x34\x2E\x31\x35\x2E\x31\x36\x2E\x31\x37\x2E\x31\x38\x2E\x31\x39\x2E\x32\x30\x2E\x28\x61\x29"
+	"\x28\x62\x29\x28\x63\x29\x28\x64\x29\x28\x65\x29\x28\x66\x29\x28\x67\x29\x28\x68\x29\x28\x69\x29\x28"
+	"\x6A\x29\x28\x6B\x29\x28\x6C\x29\x28\x6D\x29\x28\x6E\x29\x28\x6F\x29\x28\x70\x29\x28\x71\x29\x28\x72"
+	"\x29\x28\x73\x29\x28\x74\x29\x28\x75\x29\x28\x76\x29\x28\x77\x29\x28\x78\x29\x28\x79\x29\x28\x7A\x29"
+	"\x3A\x3A\x3D\x3D\x3D\xE2\xB5\xA1\xE6\xAF\x8D\xE9\xBE\x9F\xE4\xB8\x80\xE4\xB8\xA8\xE4\xB8\xB6\xE4\xB8"
+	"\xBF\xE4\xB9\x99\xE4\xBA\x85\xE4\xBA\x8C\xE4\xBA\xA0\xE4\xBA\xBA\xE5\x84\xBF\xE5\x85\xA5\xE5\x85\xAB"
+	"\xE5\x86\x82\xE5\x86\x96\xE5\x86\xAB\xE5\x87\xA0\xE5\x88\x80\xE5\x8B\xB9\xE5\x8C\x95\xE5\x8C\x9A\xE5"
+	"\x8C\xB8\xE5\x8D\x81\xE5\x8D\x9C\xE5\x8D\xA9\xE5\x8E\x82\xE5\x8E\xB6\xE5\x8F\x88\xE5\x8F\xA3\xE5\x9B"
+	"\x97\xE5\x9C\x9F\xE5\xA3\xAB\xE5\xA4\x82\xE5\xA4\x8A\xE5\xA4\x95\xE5\xA4\xA7\xE5\xAD\x90\xE5\xAE\x80"
+	"\xE5\xAF\xB8\xE5\xB0\x8F\xE5\xB0\xB8\xE5\xB1\xB1\xE5\xB7\x9B\xE5\xB7\xA5\xE5\xB7\xB1\xE5\xB7\xBE\xE5"
+	"\xB9\xB2\xE5\xB9\xBA\xE5\xB9\xBF\xE5\xBB\xB4\xE5\xBC\x8B\xE5\xBC\x93\xE5\xBD\x90\xE5\xBD\xA1\xE5\xBD"
+	"\xB3\xE5\xBF\x83\xE6\x88\x88\xE6\x88\xB6\xE6\x89\x8B\xE6\x94\xAF\xE6\x94\xB4\xE6\x96\x87\xE6\x96\x97"
+	"\xE6\x96\xA4\xE6\x96\xB9\xE6\x97\xA0\xE6\x97\xA5\xE6\x9B\xB0\xE6\x9C\x88\xE6\x9C\xA8\xE6\xAC\xA0\xE6"
+	"\xAD\xA2\xE6\xAE\xB3\xE6\xAF\x8B\xE6\xAF\x94\xE6\xAF\x9B\xE6\xB0\x8F\xE6\xB0\x94\xE6\xB0\xB4\xE7\x81"
+	"\xAB\xE7\x88\xAA\xE7\x88\xB6\xE7\x88\xBB\xE7\x88\xBF\xE7\x89\x87\xE7\x89\x99\xE7\x89\x9B\xE7\x8A\xAC"
+	"\xE7\x8E\x84\xE7\x8E\x89\xE7\x93\x9C\xE7\x93\xA6\xE7\x94\x98\xE7\x94\x9F\xE7\x94\xA8\xE7\x94\xB0\xE7"
+	"\x96\x8B\xE7\x96\x92\xE7\x99\xB6\xE7\x99\xBD\xE7\x9A\xAE\xE7\x9A\xBF\xE7\x9B\xAE\xE7\x9F\x9B\xE7\x9F"
+	"\xA2\xE7\x9F\xB3\xE7\xA4\xBA\xE7\xA6\xB8\xE7\xA6\xBE\xE7\xA9\xB4\xE7\xAB\xB9\xE7\xB1\xB3\xE7\xB3\xB8"
+	"\xE7\xBC\xB6\xE7\xBD\x91\xE7\xBE\x8A\xE8\x80\x8C\xE8\x80\x92\xE8\x80\xB3\xE8\x81\xBF\xE8\x82\x89\xE8"
+	"\x87\xA3\xE8\x87\xAA\xE8\x87\xB3\xE8\x87\xBC\xE8\x88\x8C\xE8\x88\x9B\xE8\x88\x9F\xE8\x89\xAE\xE8\x89"
+	"\xB2\xE8\x89\xB8\xE8\x99\x8D\xE8\x99\xAB\xE8\xA1\x80\xE8\xA5\xBE\xE8\xA7\x92\xE8\xA8\x80\xE8\xB0\xB7"
+	"\xE8\xB1\x86\xE8\xB1\xB8\xE8\xB2\x9D\xE8\xB5\xA4\xE8\xB5\xB0\xE8\xB6\xB3\xE8\xBA\xAB\xE8\xBE\x9B\xE8"
+	"\xBE\xB5\xE9\x82\x91\xE9\x85\x89\xE9\x87\x86\xE9\x95\xB7\xE9\x96\x80\xE9\x98\x9C\xE9\x9A\xB6\xE9\x9A"
+	"\xB9\xE9\x9B\xA8\xE9\x9D\x91\xE9\x9D\x9E\xE9\x9D\xA2\xE9\x9D\xA9\xE9\x9F\x8B\xE9\x9F\xAD\xE9\x9F\xB3"
+	"\xE9\xA0\x81\xE9\xA2\xA8\xE9\xA3\x9B\xE9\xA3\x9F\xE9\xA6\x96\xE9\xA6\x99\xE9\xA6\xAC\xE9\xAA\xA8\xE9"
+	"\xAB\x98\xE9\xAB\x9F\xE9\xAC\xA5\xE9\xAC\xAF\xE9\xAC\xB2\xE9\xAC\xBC\xE9\xAD\x9A\xE9\xB3\xA5\xE9\xB9"
+	"\xB5\xE9\xBA\xA5\xE9\xBB\x83\xE9\xBB\x8D\xE9\xBB\x91\xE9\xBB\xBD\xE9\xBC\x8E\xE9\xBC\x93\xE9\xBC\xA0"
+	"\xE9\xBD\x8A\xE9\xBD\x92\xE9\xBE\xA0\xE3\x80\x92\xE5\x8D\x84\xE5\x8D\x85\x20\xE3\x82\x99\x20\xE3\x82"
+	"\x9A\xE3\x82\x88\xE3\x82\x8A\xE3\x82\xB3\xE3\x83\x88\xE1\x84\x80\xE1\x84\x81\xE1\x86\xAA\xE1\x84\x82"
+	"\xE1\x86\xAC\xE1\x86\xAD\xE1\x84\x83\xE1\x84\x84\xE1\x84\x85\xE1\x86\xB0\xE1\x86\xB1\xE1\x86\xB2\xE1"
+	"\x86\xB3\xE1\x86\xB4\xE1\x86\xB5\xE1\x84\x9A\xE1\x84\x86\xE1\x84\x87\xE1\x84\x88\xE1\x84\xA1\xE1\x84"
+	"\x89\xE1\x84\x8A\xE1\x84\x8B\xE1\x84\x8C\xE1\x84\x8D\xE1\x84\x8E\xE1\x84\x8F\xE1\x84\x90\xE1\x84\x91"
+	"\xE1\x84\x92\xE1\x85\xA1\xE1\x85\xA2\xE1\x85\xA3\xE1\x85\xA4\xE1\x85\xA5\xE1\x85\xA6\xE1\x85\xA7\xE1"
+	"\x85\xA8\xE1\x85\xA9\xE1\x85\xAA\xE1\x85\xAB\xE1\x85\xAC\xE1\x85\xAD\xE1\x85\xAE\xE1\x85\xAF\xE1\x85"
+	"\xB0\xE1\x85\xB1\xE1\x85\xB2\xE1\x85\xB3\xE1\x85\xB4\xE1\x85\xB5\xE1\x85\xA0\xE1\x84\x94\xE1\x84\x95"
+	"\xE1\x87\x87\xE1\x87\x88\xE1\x87\x8C\xE1\x87\x8E\xE1\x87\x93\xE1\x87\x97\xE1\x87\x99\xE1\x84\x9C\xE1"
+	"\x87\x9D\xE1\x87\x9F\xE1\x84\x9D\xE1\x84\x9E\xE1\x84\xA0\xE1\x84\xA2\xE1\x84\xA3\xE1\x84\xA7\xE1\x84"
+	"\xA9\xE1\x84\xAB\xE1\x84\xAC\xE1\x84\xAD\xE1\x84\xAE\xE1\x84\xAF\xE1\x84\xB2\xE1\x84\xB6\xE1\x85\x80"
+	"\xE1\x85\x87\xE1\x85\x8C\xE1\x87\xB1\xE1\x87\xB2\xE1\x85\x97\xE1\x85\x98\xE1\x85\x99\xE1\x86\x84\xE1"
+	"\x86\x85\xE1\x86\x88\xE1\x86\x91\xE1\x86\x92\xE1\x86\x94\xE1\x86\x9E\xE1\x86\xA1\xE4\xB8\x89\xE5\x9B"
+	"\x9B\xE4\xB8\x8A\xE4\xB8\xAD\xE4\xB8\x8B\xE7\x94\xB2\xE4\xB8\x99\xE4\xB8\x81\xE5\xA4\xA9\xE5\x9C\xB0"
+	"\x28\xE1\x84\x80\x29\x28\xE1\x84\x82\x29\x28\xE1\x84\x83\x29\x28\xE1\x84\x85\x29\x28\xE1\x84\x86\x29"
+	"\x28\xE1\x84\x87\x29\x28\xE1\x84\x89\x29\x28\xE1\x84\x8B\x29\x28\xE1\x84\x8C\x29\x28\xE1\x84\x8E\x29"
+	"\x28\xE1\x84\x8F\x29\x28\xE1\x84\x90\x29\x28\xE1\x84\x91\x29\x28\xE1\x84\x92\x29\x28\xE1\x84\x80\xE1"
+	"\x85\xA1\x29\x28\xE1\x84\x82\xE1\x85\xA1\x29\x28\xE1\x84\x83\xE1\x85\xA1\x29\x28\xE1\x84\x85\xE1\x85"
+	"\xA1\x29\x28\xE1\x84\x86\xE1\x85\xA1\x29\x28\xE1\x84\x87\xE1\x85\xA1\x29\x28\xE1\x84\x89\xE1\x85\xA1"
+	"\x29\x28\xE1\x84\x8B\xE1\x85\xA1\x29\x28\xE1\x84\x8C\xE1\x85\xA1\x29\x28\xE1\x84\x8E\xE1\x85\xA1\x29"
+	"\x28\xE1\x84\x8F\xE1\x85\xA1\x29\x28\xE1\x84\x90\xE1\x85\xA1\x29\x28\xE1\x84\x91\xE1\x85\xA1\x29\x28"
+	"\xE1\x84\x92\xE1\x85\xA1\x29\x28\xE1\x84\x8C\xE1\x85\xAE\x29\x28\xE1\x84\x8B\xE1\x85\xA9\xE1\x84\x8C"
+	"\xE1\x85\xA5\xE1\x86\xAB\x29\x28\xE1\x84\x8B\xE1\x85\xA9\xE1\x84\x92\xE1\x85\xAE\x29\x28\xE4\xB8\x80"
+	"\x29\x28\xE4\xBA\x8C\x29\x28\xE4\xB8\x89\x29\x28\xE5\x9B\x9B\x29\x28\xE4\xBA\x94\x29\x28\xE5\x85\xAD"
+	"\x29\x28\xE4\xB8\x83\x29\x28\xE5\x85\xAB\x29\x28\xE4\xB9\x9D\x29\x28\xE5\x8D\x81\x29\x28\xE6\x9C\x88"
+	"\x29\x28\xE7\x81\xAB\x29\x28\xE6\xB0\xB4\x29\x28\xE6\x9C\xA8\x29\x28\xE9\x87\x91\x29\x28\xE5\x9C\x9F"
+	"\x29\x28\xE6\x97\xA5\x29\x28\xE6\xA0\xAA\x29\x28\xE6\x9C\x89\x29\x28\xE7\xA4\xBE\x29\x28\xE5\x90\x8D"
+	"\x29\x28\xE7\x89\xB9\x29\x28\xE8\xB2\xA1\x29\x28\xE7\xA5\x9D\x29\x28\xE5\x8A\xB4\x29\x28\xE4\xBB\xA3"
+	"\x29\x28\xE5\x91\xBC\x29\x28\xE5\xAD\xA6\x29\x28\xE7\x9B\xA3\x29\x28\xE4\xBC\x81\x29\x28\xE8\xB3\x87"
+	"\x29\x28\xE5\x8D\x94\x29\x28\xE7\xA5\xAD\x29\x28\xE4\xBC\x91\x29\x28\xE8\x87\xAA\x29\x28\xE8\x87\xB3"
+	"\x29\xE5\x95\x8F\xE5\xB9\xBC\xE7\xAE\x8F\x50\x54\x45\x32\x32\x32\x34\x32\x35\x32\x36\x32\x37\x32\x38"
+	"\x32\x39\x33\x30\x33\x33\x33\x34\x33\x35\xE1\x84\x8E\xE1\x85\xA1\xE1\x86\xB7\xE1\x84\x80\xE1\x85\xA9"
+	"\xE1\x84\x8C\xE1\x85\xAE\xE1\x84\x8B\xE1\x85\xB4\xE1\x84\x8B\xE1\x85\xAE\xE7\xA7\x98\xE7\x94\xB7\xE9"
+	"\x81\xA9\xE5\x84\xAA\xE5\x8D\xB0\xE6\xB3\xA8\xE9\xA0\x85\xE5\x86\x99\xE6\xAD\xA3\xE5\xB7\xA6\xE5\x8F"
+	"\xB3\xE5\x8C\xBB\xE5\xAE\x97\xE5\xA4\x9C\x33\x36\x33\x37\x33\x38\x33\x39\x34\x30\x34\x34\x34\x35\x34"
+	"\x36\x34\x37\x34\x38\x34\x39\x35\x30\x31\xE6\x9C\x88\x32\xE6\x9C\x88\x33\xE6\x9C\x88\x34\xE6\x9C\x88"
+	"\x35\xE6\x9C\x88\x36\xE6\x9C\x88\x37\xE6\x9C\x88\x38\xE6\x9C\x88\x39\xE6\x9C\x88\x31\x30\xE6\x9C\x88"
+	"\x31\x31\xE6\x9C\x88\x31\x32\xE6\x9C\x88\x48\x67\x65\x72\x67\x65\x56\x4C\x54\x44\xE3\x82\xA2\xE3\x82"
+	"\xA4\xE3\x82\xA8\xE3\x82\xAA\xE3\x83\x8A\xE3\x83\x8B\xE3\x83\x8C\xE3\x83\x8D\xE3\x83\x8E\xE3\x83\x9E"
+	"\xE3\x83\x9F\xE3\x83\xA0\xE3\x83\xA1\xE3\x83\xA2\xE3\x83\xA4\xE3\x83\xA6\xE3\x83\xA8\xE3\x83\xA9\xE3"
+	"\x83\xAA\xE3\x83\xAB\xE3\x83\xAC\xE3\x83\xAD\xE3\x82\xA2\xE3\x83\x8F\xE3\x82\x9A\xE3\x83\xBC\xE3\x83"
+	"\x88\xE3\x82\xA2\xE3\x83\xAB\xE3\x83\x95\xE3\x82\xA1\xE3\x82\xA2\xE3\x83\xB3\xE3\x83\x98\xE3\x82\x9A"
+	"\xE3\x82\xA2\xE3\x82\xA2\xE3\x83\xBC\xE3\x83\xAB\xE3\x82\xA4\xE3\x83\x8B\xE3\x83\xB3\xE3\x82\xAF\xE3"
+	"\x82\x99\xE3\x82\xA4\xE3\x83\xB3\xE3\x83\x81\xE3\x82\xA6\xE3\x82\xA9\xE3\x83\xB3\xE3\x82\xA8\xE3\x82"
+	"\xB9\xE3\x82\xAF\xE3\x83\xBC\xE3\x83\x88\xE3\x82\x99\xE3\x82\xA8\xE3\x83\xBC\xE3\x82\xAB\xE3\x83\xBC"
+	"\xE3\x82\xAA\xE3\x83\xB3\xE3\x82\xB9\xE3\x82\xAA\xE3\x83\xBC\xE3\x83\xA0\xE3\x82\xAB\xE3\x82\xA4\xE3"
+	"\x83\xAA\xE3\x82\xAB\xE3\x83\xA9\xE3\x83\x83\xE3\x83\x88\xE3\x82\xAB\xE3\x83\xAD\xE3\x83\xAA\xE3\x83"
+	"\xBC\xE3\x82\xAB\xE3\x82\x99\xE3\x83\xAD\xE3\x83\xB3\xE3\x82\xAB\xE3\x82\x99\xE3\x83\xB3\xE3\x83\x9E"
+	"\xE3\x82\xAD\xE3\x82\x99\xE3\x82\xAB\xE3\x82\x99\xE3\x82\xAD\xE3\x82\x99\xE3\x83\x8B\xE3\x83\xBC\xE3"
+	"\x82\xAD\xE3\x83\xA5\xE3\x83\xAA\xE3\x83\xBC\xE3\x82\xAD\xE3\x82\x99\xE3\x83\xAB\xE3\x82\xBF\xE3\x82"
+	"\x99\xE3\x83\xBC\xE3\x82\xAD\xE3\x83\xAD\xE3\x82\xAD\xE3\x83\xAD\xE3\x82\xAF\xE3\x82\x99\xE3\x83\xA9"
+	"\xE3\x83\xA0\xE3\x82\xAD\xE3\x83\xAD\xE3\x83\xA1\xE3\x83\xBC\xE3\x83\x88\xE3\x83\xAB\xE3\x82\xAD\xE3"
+	"\x83\xAD\xE3\x83\xAF\xE3\x83\x83\xE3\x83\x88\xE3\x82\xAF\xE3\x82\x99\xE3\x83\xA9\xE3\x83\xA0\xE3\x83"
+	"\x88\xE3\x83\xB3\xE3\x82\xAF\xE3\x83\xAB\xE3\x82\xBB\xE3\x82\x99\xE3\x82\xA4\xE3\x83\xAD\xE3\x82\xAF"
+	"\xE3\x83\xAD\xE3\x83\xBC\xE3\x83\x8D\xE3\x82\xB1\xE3\x83\xBC\xE3\x82\xB9\xE3\x82\xB3\xE3\x83\xAB\xE3"
+	"\x83\x8A\xE3\x82\xB3\xE3\x83\xBC\xE3\x83\x9B\xE3\x82\x9A\xE3\x82\xB5\xE3\x82\xA4\xE3\x82\xAF\xE3\x83"
+	"\xAB\xE3\x82\xB5\xE3\x83\xB3\xE3\x83\x81\xE3\x83\xBC\xE3\x83\xA0\xE3\x82\xB7\xE3\x83\xAA\xE3\x83\xB3"
+	"\xE3\x82\xAF\xE3\x82\x99\xE3\x82\xBB\xE3\x83\xB3\xE3\x83\x81\xE3\x82\xBB\xE3\x83\xB3\xE3\x83\x88\xE3"
+	"\x82\xBF\xE3\x82\x99\xE3\x83\xBC\xE3\x82\xB9\xE3\x83\x86\xE3\x82\x99\xE3\x82\xB7\xE3\x83\x88\xE3\x82"
+	"\x99\xE3\x83\xAB\xE3\x83\x8A\xE3\x83\x8E\xE3\x83\x8E\xE3\x83\x83\xE3\x83\x88\xE3\x83\x8F\xE3\x82\xA4"
+	"\xE3\x83\x84\xE3\x83\x8F\xE3\x82\x9A\xE3\x83\xBC\xE3\x82\xBB\xE3\x83\xB3\xE3\x83\x88\xE3\x83\x8F\xE3"
+	"\x82\x9A\xE3\x83\xBC\xE3\x83\x84\xE3\x83\x8F\xE3\x82\x99\xE3\x83\xBC\xE3\x83\xAC\xE3\x83\xAB\xE3\x83"
+	"\x92\xE3\x82\x9A\xE3\x82\xA2\xE3\x82\xB9\xE3\x83\x88\xE3\x83\xAB\xE3\x83\x92\xE3\x82\x9A\xE3\x82\xAF"
+	"\xE3\x83\xAB\xE3\x83\x92\xE3\x82\x9A\xE3\x82\xB3\xE3\x83\x92\xE3\x82\x99\xE3\x83\xAB\xE3\x83\x95\xE3"
+	"\x82\xA1\xE3\x83\xA9\xE3\x83\x83\xE3\x83\x88\xE3\x82\x99\xE3\x83\x95\xE3\x82\xA3\xE3\x83\xBC\xE3\x83"
+	"\x88\xE3\x83\x95\xE3\x82\x99\xE3\x83\x83\xE3\x82\xB7\xE3\x82\xA7\xE3\x83\xAB\xE3\x83\x95\xE3\x83\xA9"
+	"\xE3\x83\xB3\xE3\x83\x98\xE3\x82\xAF\xE3\x82\xBF\xE3\x83\xBC\xE3\x83\xAB\xE3\x83\x98\xE3\x82\x9A\xE3"
+	"\x82\xBD\xE3\x83\x98\xE3\x82\x9A\xE3\x83\x8B\xE3\x83\x92\xE3\x83\x98\xE3\x83\xAB\xE3\x83\x84\xE3\x83"
+	"\x98\xE3\x82\x9A\xE3\x83\xB3\xE3\x82\xB9\xE3\x83\x98\xE3\x82\x9A\xE3\x83\xBC\xE3\x82\xB7\xE3\x82\x99"
+	"\xE3\x83\x98\xE3\x82\x99\xE3\x83\xBC\xE3\x82\xBF\xE3\x83\x9B\xE3\x82\x9A\xE3\x82\xA4\xE3\x83\xB3\xE3"
+	"\x83\x88\xE3\x83\x9B\xE3\x82\x99\xE3\x83\xAB\xE3\x83\x88\xE3\x83\x9B\xE3\x83\xB3\xE3\x83\x9B\xE3\x82"
+	"\x9A\xE3\x83\xB3\xE3\x83\x88\xE3\x82\x99\xE3\x83\x9B\xE3\x83\xBC\xE3\x83\xAB\xE3\x83\x9B\xE3\x83\xBC"
+	"\xE3\x83\xB3\xE3\x83\x9E\xE3\x82\xA4\xE3\x82\xAF\xE3\x83\xAD\xE3\x83\x9E\xE3\x82\xA4\xE3\x83\xAB\xE3"
+	"\x83\x9E\xE3\x83\x83\xE3\x83\x8F\xE3\x83\x9E\xE3\x83\xAB\xE3\x82\xAF\xE3\x83\x9E\xE3\x83\xB3\xE3\x82"
+	"\xB7\xE3\x83\xA7\xE3\x83\xB3\xE3\x83\x9F\xE3\x82\xAF\xE3\x83\xAD\xE3\x83\xB3\xE3\x83\x9F\xE3\x83\xAA"
+	"\xE3\x83\x9F\xE3\x83\xAA\xE3\x83\x8F\xE3\x82\x99\xE3\x83\xBC\xE3\x83\xAB\xE3\x83\xA1\xE3\x82\xAB\xE3"
+	"\x82\x99\xE3\x83\xA1\xE3\x82\xAB\xE3\x82\x99\xE3\x83\x88\xE3\x83\xB3\xE3\x83\xA4\xE3\x83\xBC\xE3\x83"
+	"\x88\xE3\x82\x99\xE3\x83\xA4\xE3\x83\xBC\xE3\x83\xAB\xE3\x83\xA6\xE3\x82\xA2\xE3\x83\xB3\xE3\x83\xAA"
+	"\xE3\x83\x83\xE3\x83\x88\xE3\x83\xAB\xE3\x83\xAA\xE3\x83\xA9\xE3\x83\xAB\xE3\x83\x92\xE3\x82\x9A\xE3"
+	"\x83\xBC\xE3\x83\xAB\xE3\x83\xBC\xE3\x83\x95\xE3\x82\x99\xE3\x83\xAB\xE3\x83\xAC\xE3\x83\xA0\xE3\x83"
+	"\xAC\xE3\x83\xB3\xE3\x83\x88\xE3\x82\xB1\xE3\x82\x99\xE3\x83\xB3\x30\xE7\x82\xB9\x31\xE7\x82\xB9\x32"
+	"\xE7\x82\xB9\x33\xE7\x82\xB9\x34\xE7\x82\xB9\x35\xE7\x82\xB9\x36\xE7\x82\xB9\x37\xE7\x82\xB9\x38\xE7"
+	"\x82\xB9\x39\xE7\x82\xB9\x31\x30\xE7\x82\xB9\x31\x31\xE7\x82\xB9\x31\x32\xE7\x82\xB9\x31\x33\xE7\x82"
+	"\xB9\x31\x34\xE7\x82\xB9\x31\x35\xE7\x82\xB9\x31\x36\xE7\x82\xB9\x31\x37\xE7\x82\xB9\x31\x38\xE7\x82"
+	"\xB9\x31\x39\xE7\x82\xB9\x32\x30\xE7\x82\xB9\x32\x31\xE7\x82\xB9\x32\x32\xE7\x82\xB9\x32\x33\xE7\x82"
+	"\xB9\x32\x34\xE7\x82\xB9\x68\x50\x61\x64\x61\x41\x55\x62\x61\x72\x6F\x56\x70\x63\x64\x6D\x64\x6D\x32"
+	"\x64\x6D\x33\x49\x55\xE5\xB9\xB3\xE6\x88\x90\xE6\x98\xAD\xE5\x92\x8C\xE5\xA4\xA7\xE6\xAD\xA3\xE6\x98"
+	"\x8E\xE6\xB2\xBB\xE6\xA0\xAA\xE5\xBC\x8F\xE4\xBC\x9A\xE7\xA4\xBE\x70\x41\x6E\x41\xCE\xBC\x41\x6D\x41"
+	"\x6B\x41\x4B\x42\x4D\x42\x47\x42\x63\x61\x6C\x6B\x63\x61\x6C\x70\x46\x6E\x46\xCE\xBC\x46\xCE\xBC\x67"
+	"\x6D\x67\x6B\x67\x48\x7A\x6B\x48\x7A\x4D\x48\x7A\x47\x48\x7A\x54\x48\x7A\xCE\xBC\x6C\x6D\x6C\x64\x6C"
+	"\x6B\x6C\x66\x6D\x6E\x6D\xCE\xBC\x6D\x6D\x6D\x63\x6D\x6B\x6D\x6D\x6D\x32\x63\x6D\x32\x6B\x6D\x32\x6D"
+	"\x6D\x33\x63\x6D\x33\x6B\x6D\x33\x6D\xE2\x88\x95\x73\x6D\xE2\x88\x95\x73\x32\x6B\x50\x61\x4D\x50\x61"
+	"\x47\x50\x61\x72\x61\x64\x72\x61\x64\xE2\x88\x95\x73\x72\x61\x64\xE2\x88\x95\x73\x32\x70\x73\x6E\x73"
+	"\xCE\xBC\x73\x6D\x73\x70\x56\x6E\x56\xCE\xBC\x56\x6D\x56\x6B\x56\x4D\x56\x70\x57\x6E\x57\xCE\xBC\x57"
+	"\x6D\x57\x6B\x57\x4D\x57\x6B\xCE\xA9\x4D\xCE\xA9\x61\x2E\x6D\x2E\x42\x71\x63\x63\x43\xE2\x88\x95\x6B"
+	"\x67\x43\x6F\x2E\x64\x42\x47\x79\x68\x61\x48\x50\x69\x6E\x4B\x4B\x4B\x4D\x6B\x74\x6C\x6E\x6C\x6F\x67"
+	"\x6C\x78\x6D\x62\x6D\x69\x6C\x6D\x6F\x6C\x50\x48\x70\x2E\x6D\x2E\x50\x50\x4D\x50\x52\x53\x76\x57\x62"
+	"\x56\xE2\x88\x95\x6D\x41\xE2\x88\x95\x6D\x31\xE6\x97\xA5\x32\xE6\x97\xA5\x33\xE6\x97\xA5\x34\xE6\x97"
+	"\xA5\x35\xE6\x97\xA5\x36\xE6\x97\xA5\x37\xE6\x97\xA5\x38\xE6\x97\xA5\x39\xE6\x97\xA5\x31\x30\xE6\x97"
+	"\xA5\x31\x31\xE6\x97\xA5\x31\x32\xE6\x97\xA5\x31\x33\xE6\x97\xA5\x31\x34\xE6\x97\xA5\x31\x35\xE6\x97"
+	"\xA5\x31\x36\xE6\x97\xA5\x31\x37\xE6\x97\xA5\x31\x38\xE6\x97\xA5\x31\x39\xE6\x97\xA5\x32\x30\xE6\x97"
+	"\xA5\x32\x31\xE6\x97\xA5\x32\x32\xE6\x97\xA5\x32\x33\xE6\x97\xA5\x32\x34\xE6\x97\xA5\x32\x35\xE6\x97"
+	"\xA5\x32\x36\xE6\x97\xA5\x32\x37\xE6\x97\xA5\x32\x38\xE6\x97\xA5\x32\x39\xE6\x97\xA5\x33\x30\xE6\x97"
+	"\xA5\x33\x31\xE6\x97\xA5\x67\x61\x6C\xD1\x8A\xD1\x8C\xEA\x9D\xAF\xC4\xA6\xC5\x93\xEA\x9C\xA7\xEA\xAC"
+	"\xB7\xC9\xAB\xEA\xAD\x92\x66\x66\x66\x69\x66\x6C\x66\x66\x69\x66\x66\x6C\x73\x74\xD5\xB4\xD5\xB6\xD5"
+	"\xB4\xD5\xA5\xD5\xB4\xD5\xAB\xD5\xBE\xD5\xB6\xD5\xB4\xD5\xAD\xD7\xA2\xD7\x9D\xD7\x90\xD7\x9C\xD9\xB1"
+	"\xD9\xBB\xD9\xBE\xDA\x80\xD9\xBA\xD9\xBF\xD9\xB9\xDA\xA4\xDA\xA6\xDA\x84\xDA\x83\xDA\x86\xDA\x87\xDA"
+	"\x8D\xDA\x8C\xDA\x8E\xDA\x88\xDA\x98\xDA\x91\xDA\xA9\xDA\xAF\xDA\xB3\xDA\xB1\xDA\xBA\xDA\xBB\xDA\xBE"
+	"\xDA\xAD\xDB\x86\xDB\x88\xDB\x8B\xDB\x85\xDB\x89\xDB\x90\xD9\x89\xD9\x8A\xD9\x94\xD8\xA7\xD9\x8A\xD9"
+	"\x94\xD9\x88\xD9\x8A\xD9\x94\xDB\x87\xD9\x8A\xD9\x94\xDB\x86\xD9\x8A\xD9\x94\xDB\x88\xD9\x8A\xD9\x94"
+	"\xDB\x90\xD9\x8A\xD9\x94\xD9\x89\xDB\x8C\xD9\x8A\xD9\x94\xD8\xAC\xD9\x8A\xD9\x94\xD8\xAD\xD9\x8A\xD9"
+	"\x94\xD9\x85\xD9\x8A\xD9\x94\xD9\x8A\xD8\xA8\xD8\xAC\xD8\xA8\xD8\xAD\xD8\xA8\xD8\xAE\xD8\xA8\xD9\x85"
+	"\xD8\xA8\xD9\x89\xD8\xA8\xD9\x8A\xD8\xAA\xD8\xAC\xD8\xAA\xD8\xAD\xD8\xAA\xD8\xAE\xD8\xAA\xD9\x85\xD8"
+	"\xAA\xD9\x89\xD8\xAA\xD9\x8A\xD8\xAB\xD8\xAC\xD8\xAB\xD9\x85\xD8\xAB\xD9\x89\xD8\xAB\xD9\x8A\xD8\xAC"
+	"\xD8\xAD\xD8\xAC\xD9\x85\xD8\xAD\xD9\x85\xD8\xAE\xD8\xAC\xD8\xAE\xD8\xAD\xD8\xAE\xD9\x85\xD8\xB3\xD8"
+	"\xAC\xD8\xB3\xD8\xAD\xD8\xB3\xD8\xAE\xD8\xB3\xD9\x85\xD8\xB5\xD8\xAD\xD8\xB5\xD9\x85\xD8\xB6\xD8\xAC"
+	"\xD8\xB6\xD8\xAD\xD8\xB6\xD8\xAE\xD8\xB6\xD9\x85\xD8\xB7\xD8\xAD\xD8\xB7\xD9\x85\xD8\xB8\xD9\x85\xD8"
+	"\xB9\xD8\xAC\xD8\xB9\xD9\x85\xD8\xBA\xD8\xAC\xD8\xBA\xD9\x85\xD9\x81\xD8\xAC\xD9\x81\xD8\xAD\xD9\x81"
+	"\xD8\xAE\xD9\x81\xD9\x85\xD9\x81\xD9\x89\xD9\x81\xD9\x8A\xD9\x82\xD8\xAD\xD9\x82\xD9\x85\xD9\x82\xD9"
+	"\x89\xD9\x82\xD9\x8A\xD9\x83\xD8\xA7\xD9\x83\xD8\xAC\xD9\x83\xD8\xAD\xD9\x83\xD8\xAE\xD9\x83\xD9\x84"
+	"\xD9\x83\xD9\x85\xD9\x83\xD9\x89\xD9\x83\xD9\x8A\xD9\x84\xD8\xAC\xD9\x84\xD8\xAD\xD9\x84\xD8\xAE\xD9"
+	"\x84\xD9\x85\xD9\x84\xD9\x89\xD9\x84\xD9\x8A\xD9\x85\xD8\xAC\xD9\x85\xD9\x85\xD9\x85\xD9\x89\xD9\x86"
+	"\xD8\xAC\xD9\x86\xD8\xAD\xD9\x86\xD8\xAE\xD9\x86\xD9\x85\xD9\x86\xD9\x89\xD9\x86\xD9\x8A\xD9\x87\xD8"
+	"\xAC\xD9\x87\xD9\x85\xD9\x87\xD9\x89\xD9\x87\xD9\x8A\xD9\x8A\xD8\xAD\xD9\x8A\xD8\xAE\xD9\x8A\xD9\x89"
+	"\xD8\xB0\xD9\xB0\xD8\xB1\xD9\xB0\xD9\x89\xD9\xB0\x20\xD9\x8C\xD9\x91\x20\xD9\x8D\xD9\x91\x20\xD9\x8E"
+	"\xD9\x91\x20\xD9\x8F\xD9\x91\x20\xD9\x90\xD9\x91\x20\xD9\x91\xD9\xB0\xD9\x8A\xD9\x94\xD8\xB1\xD9\x8A"
+	"\xD9\x94\xD8\xB2\xD9\x8A\xD9\x94\xD9\x86\xD8\xA8\xD8\xB1\xD8\xA8\xD8\xB2\xD8\xA8\xD9\x86\xD8\xAA\xD8"
+	"\xB1\xD8\xAA\xD8\xB2\xD8\xAA\xD9\x86\xD8\xAB\xD8\xB1\xD8\xAB\xD8\xB2\xD8\xAB\xD9\x86\xD9\x85\xD8\xA7"
+	"\xD9\x86\xD8\xB1\xD9\x86\xD8\xB2\xD9\x86\xD9\x86\xD9\x8A\xD8\xB1\xD9\x8A\xD8\xB2\xD9\x8A\xD9\x86\xD9"
+	"\x8A\xD9\x94\xD8\xAE\xD9\x8A\xD9\x94\xD9\x87\xD8\xA8\xD9\x87\xD8\xAA\xD9\x87\xD8\xB5\xD8\xAE\xD9\x84"
+	"\xD9\x87\xD9\x86\xD9\x87\xD9\x87\xD9\xB0\xD9\x8A\xD8\xAD\xD8\xAB\xD9\x87\xD8\xB3\xD9\x87\xD8\xB4\xD9"
+	"\x85\xD8\xB4\xD9\x87\xD9\x80\xD9\x8E\xD9\x91\xD9\x80\xD9\x8F\xD9\x91\xD9\x80\xD9\x90\xD9\x91\xD8\xB7"
+	"\xD9\x89\xD8\xB7\xD9\x8A\xD8\xB9\xD9\x89\xD8\xB9\xD9\x8A\xD8\xBA\xD9\x89\xD8\xBA\xD9\x8A\xD8\xB3\xD9"
+	"\x89\xD8\xB3\xD9\x8A\xD8\xB4\xD9\x89\xD8\xB4\xD9\x8A\xD8\xAD\xD9\x89\xD8\xAC\xD9\x89\xD8\xAE\xD9\x89"
+	"\xD8\xB5\xD9\x89\xD8\xB5\xD9\x8A\xD8\xB6\xD9\x89\xD8\xB6\xD9\x8A\xD8\xB4\xD8\xAC\xD8\xB4\xD8\xAD\xD8"
+	"\xB4\xD8\xAE\xD8\xB4\xD8\xB1\xD8\xB3\xD8\xB1\xD8\xB5\xD8\xB1\xD8\xB6\xD8\xB1\xD8\xA7\xD9\x8B\xD8\xAA"
+	"\xD8\xAC\xD9\x85\xD8\xAA\xD8\xAD\xD8\xAC\xD8\xAA\xD8\xAD\xD9\x85\xD8\xAA\xD8\xAE\xD9\x85\xD8\xAA\xD9"
+	"\x85\xD8\xAC\xD8\xAA\xD9\x85\xD8\xAD\xD8\xAA\xD9\x85\xD8\xAE\xD8\xAD\xD9\x85\xD9\x8A\xD8\xAD\xD9\x85"
+	"\xD9\x89\xD8\xB3\xD8\xAD\xD8\xAC\xD8\xB3\xD8\xAC\xD8\xAD\xD8\xB3\xD8\xAC\xD9\x89\xD8\xB3\xD9\x85\xD8"
+	"\xAD\xD8\xB3\xD9\x85\xD8\xAC\xD8\xB3\xD9\x85\xD9\x85\xD8\xB5\xD8\xAD\xD8\xAD\xD8\xB5\xD9\x85\xD9\x85"
+	"\xD8\xB4\xD8\xAD\xD9\x85\xD8\xB4\xD8\xAC\xD9\x8A\xD8\xB4\xD9\x85\xD8\xAE\xD8\xB4\xD9\x85\xD9\x85\xD8"
+	"\xB6\xD8\xAD\xD9\x89\xD8\xB6\xD8\xAE\xD9\x85\xD8\xB7\xD9\x85\xD8\xAD\xD8\xB7\xD9\x85\xD9\x85\xD8\xB7"
+	"\xD9\x85\xD9\x8A\xD8\xB9\xD8\xAC\xD9\x85\xD8\xB9\xD9\x85\xD9\x85\xD8\xB9\xD9\x85\xD9\x89\xD8\xBA\xD9"
+	"\x85\xD9\x85\xD8\xBA\xD9\x85\xD9\x8A\xD8\xBA\xD9\x85\xD9\x89\xD9\x81\xD8\xAE\xD9\x85\xD9\x82\xD9\x85"
+	"\xD8\xAD\xD9\x82\xD9\x85\xD9\x85\xD9\x84\xD8\xAD\xD9\x85\xD9\x84\xD8\xAD\xD9\x8A\xD9\x84\xD8\xAD\xD9"
+	"\x89\xD9\x84\xD8\xAC\xD8\xAC\xD9\x84\xD8\xAE\xD9\x85\xD9\x84\xD9\x85\xD8\xAD\xD9\x85\xD8\xAD\xD8\xAC"
+	"\xD9\x85\xD8\xAD\xD9\x8A\xD9\x85\xD8\xAC\xD8\xAD\xD9\x85\xD8\xAE\xD9\x85\xD9\x85\xD8\xAC\xD8\xAE\xD9"
+	"\x87\xD9\x85\xD8\xAC\xD9\x87\xD9\x85\xD9\x85\xD9\x86\xD8\xAD\xD9\x85\xD9\x86\xD8\xAD\xD9\x89\xD9\x86"
+	"\xD8\xAC\xD9\x85\xD9\x86\xD8\xAC\xD9\x89\xD9\x86\xD9\x85\xD9\x8A\xD9\x86\xD9\x85\xD9\x89\xD9\x8A\xD9"
+	"\x85\xD9\x85\xD8\xA8\xD8\xAE\xD9\x8A\xD8\xAA\xD8\xAC\xD9\x8A\xD8\xAA\xD8\xAC\xD9\x89\xD8\xAA\xD8\xAE"
+	"\xD9\x8A\xD8\xAA\xD8\xAE\xD9\x89\xD8\xAA\xD9\x85\xD9\x8A\xD8\xAA\xD9\x85\xD9\x89\xD8\xAC\xD9\x85\xD9"
+	"\x8A\xD8\xAC\xD8\xAD\xD9\x89\xD8\xAC\xD9\x85\xD9\x89\xD8\xB3\xD8\xAE\xD9\x89\xD8\xB5\xD8\xAD\xD9\x8A"
+	"\xD8\xB4\xD8\xAD\xD9\x8A\xD8\xB6\xD8\xAD\xD9\x8A\xD9\x84\xD8\xAC\xD9\x8A\xD9\x84\xD9\x85\xD9\x8A\xD9"
+	"\x8A\xD8\xAD\xD9\x8A\xD9\x8A\xD8\xAC\xD9\x8A\xD9\x8A\xD9\x85\xD9\x8A\xD9\x85\xD9\x85\xD9\x8A\xD9\x82"
+	"\xD9\x85\xD9\x8A\xD9\x86\xD8\xAD\xD9\x8A\xD8\xB9\xD9\x85\xD9\x8A\xD9\x83\xD9\x85\xD9\x8A\xD9\x86\xD8"
+	"\xAC\xD8\xAD\xD9\x85\xD8\xAE\xD9\x8A\xD9\x84\xD8\xAC\xD9\x85\xD9\x83\xD9\x85\xD9\x85\xD8\xAC\xD8\xAD"
+	"\xD9\x8A\xD8\xAD\xD8\xAC\xD9\x8A\xD9\x85\xD8\xAC\xD9\x8A\xD9\x81\xD9\x85\xD9\x8A\xD8\xA8\xD8\xAD\xD9"
+	"\x8A\xD8\xB3\xD8\xAE\xD9\x8A\xD9\x86\xD8\xAC\xD9\x8A\xD8\xB5\xD9\x84\xDB\x92\xD9\x82\xD9\x84\xDB\x92"
+	"\xD8\xA7\xD9\x84\xD9\x84\xD9\x87\xD8\xA7\xD9\x83\xD8\xA8\xD8\xB1\xD9\x85\xD8\xAD\xD9\x85\xD8\xAF\xD8"
+	"\xB5\xD9\x84\xD8\xB9\xD9\x85\xD8\xB1\xD8\xB3\xD9\x88\xD9\x84\xD8\xB9\xD9\x84\xD9\x8A\xD9\x87\xD9\x88"
+	"\xD8\xB3\xD9\x84\xD9\x85\xD8\xB5\xD9\x84\xD9\x89\xD8\xB5\xD9\x84\xD9\x89\x20\xD8\xA7\xD9\x84\xD9\x84"
+	"\xD9\x87\x20\xD8\xB9\xD9\x84\xD9\x8A\xD9\x87\x20\xD9\x88\xD8\xB3\xD9\x84\xD9\x85\xD8\xAC\xD9\x84\x20"
+	"\xD8\xAC\xD9\x84\xD8\xA7\xD9\x84\xD9\x87\xD8\xB1\xDB\x8C\xD8\xA7\xD9\x84\x2C\xE3\x80\x81\xE3\x80\x82"
+	"\xE3\x80\x96\xE3\x80\x97\xE2\x80\x94\xE2\x80\x93\x5F\x7B\x7D\xE3\x80\x94\xE3\x80\x95\xE3\x80\x90\xE3"
+	"\x80\x91\xE3\x80\x8A\xE3\x80\x8B\xE3\x80\x8C\xE3\x80\x8D\xE3\x80\x8E\xE3\x80\x8F\x5B\x5D\x23\x26\x2A"
+	"\x2D\x5C\x24\x25\x40\x20\xD9\x8B\xD9\x80\xD9\x8B\xD9\x80\xD9\x91\x20\xD9\x92\xD9\x80\xD9\x92\xD8\xA1"
+	"\xD8\xA9\xD9\x84\xD8\xA7\xD9\x93\xD9\x84\xD8\xA7\xD9\x94\xD9\x84\xD8\xA7\xD9\x95\x22\x27\x5E\x7C\x7E"
+	"\xE2\xA6\x85\xE2\xA6\x86\xE3\x83\xBB\xE3\x82\xA5\xE3\x83\xA3\xC2\xA2\xC2\xA3\xC2\xAC\xC2\xA6\xC2\xA5"
+	"\xE2\x82\xA9\xE2\x94\x82\xE2\x86\x91\xE2\x86\x93\xE2\x96\xA0\xE2\x97\x8B\xF0\x9D\x85\x98\xF0\x9D\x85"
+	"\xA5\xF0\x9D\x85\xAE\xC4\xB1\xC8\xB7\xCE\x92\xCE\x94\xCE\x96\xCE\x9A\xCE\x9B\xCE\x9C\xCE\x9D\xCE\x9E"
+	"\xCE\xA4\xCE\xA6\xCE\xA7\xCE\xA8\xE2\x88\x87\xCE\xB6\xCE\xBB\xCE\xBD\xCE\xBE\xCF\x83\xCF\x84\xCF\x88"
+	"\xE2\x88\x82\xCF\x9C\xCF\x9D\xD9\xAE\xDA\xA1\xD9\xAF\x30\x2C\x31\x2C\x32\x2C\x33\x2C\x34\x2C\x35\x2C"
+	"\x36\x2C\x37\x2C\x38\x2C\x39\x2C\x28\x41\x29\x28\x42\x29\x28\x43\x29\x28\x44\x29\x28\x45\x29\x28\x46"
+	"\x29\x28\x47\x29\x28\x48\x29\x28\x49\x29\x28\x4A\x29\x28\x4B\x29\x28\x4C\x29\x28\x4D\x29\x28\x4E\x29"
+	"\x28\x4F\x29\x28\x50\x29\x28\x51\x29\x28\x52\x29\x28\x53\x29\x28\x54\x29\x28\x55\x29\x28\x56\x29\x28"
+	"\x57\x29\x28\x58\x29\x28\x59\x29\x28\x5A\x29\xE3\x80\x94\x53\xE3\x80\x95\x43\x44\x57\x5A\x48\x56\x53"
+	"\x44\x53\x53\x50\x50\x56\x57\x43\x4D\x43\x4D\x44\x44\x4A\xE3\x81\xBB\xE3\x81\x8B\xE3\x82\xB3\xE3\x82"
+	"\xB3\xE5\xAD\x97\xE5\x8F\x8C\xE8\xA7\xA3\xE4\xBA\xA4\xE6\x98\xA0\xE7\x84\xA1\xE5\x89\x8D\xE5\xBE\x8C"
+	"\xE6\x96\xB0\xE5\x88\x9D\xE7\xB5\x82\xE8\xB2\xA9\xE5\xA3\xB0\xE5\x90\xB9\xE6\xBC\x94\xE6\x8A\x95\xE6"
+	"\x8D\x95\xE9\x81\x8A\xE6\x8C\x87\xE6\x89\x93\xE7\xA6\x81\xE7\xA9\xBA\xE5\x90\x88\xE6\xBA\x80\xE7\x94"
+	"\xB3\xE5\x96\xB6\xE3\x80\x94\xE6\x9C\xAC\xE3\x80\x95\xE3\x80\x94\xE4\xB8\x89\xE3\x80\x95\xE3\x80\x94"
+	"\xE4\xBA\x8C\xE3\x80\x95\xE3\x80\x94\xE5\xAE\x89\xE3\x80\x95\xE3\x80\x94\xE7\x82\xB9\xE3\x80\x95\xE3"
+	"\x80\x94\xE6\x89\x93\xE3\x80\x95\xE3\x80\x94\xE7\x9B\x97\xE3\x80\x95\xE3\x80\x94\xE5\x8B\x9D\xE3\x80"
+	"\x95\xE3\x80\x94\xE6\x95\x97\xE3\x80\x95\xE5\xBE\x97\xE5\x8F\xAF\xC3\x80\xC3\x81\xC3\x82\xC3\x83\xC3"
+	"\x84\xC3\x85\xC3\x87\xC3\x88\xC3\x89\xC3\x8A\xC3\x8B\xC3\x8C\xC3\x8D\xC3\x8E\xC3\x8F\xC3\x90\xC3\x91"
+	"\xC3\x92\xC3\x93\xC3\x94\xC3\x95\xC3\x96\xC3\x99\xC3\x9A\xC3\x9B\xC3\x9C\xC3\x9D\xC3\x9E\xC5\xB8\xC4"
+	"\x80\xC4\x82\xC4\x84\xC4\x86\xC4\x88\xC4\x8A\xC4\x8C\xC4\x8E\xC4\x90\xC4\x92\xC4\x94\xC4\x96\xC4\x98"
+	"\xC4\x9A\xC4\x9C\xC4\x9E\xC4\xA0\xC4\xA2\xC4\xA4\xC4\xA8\xC4\xAA\xC4\xAC\xC4\xAE\xC4\xB2\xC4\xB4\xC4"
+	"\xB6\xC4\xB9\xC4\xBB\xC4\xBD\xC4\xBF\xC5\x81\xC5\x83\xC5\x85\xC5\x87\xCA\xBC\x4E\xC5\x8A\xC5\x8C\xC5"
+	"\x8E\xC5\x90\xC5\x92\xC5\x94\xC5\x96\xC5\x98\xC5\x9A\xC5\x9C\xC5\x9E\xC5\xA0\xC5\xA2\xC5\xA4\xC5\xA6"
+	"\xC5\xA8\xC5\xAA\xC5\xAC\xC5\xAE\xC5\xB0\xC5\xB2\xC5\xB4\xC5\xB6\xC5\xB9\xC5\xBB\xC5\xBD\xC9\x83\xC6"
+	"\x82\xC6\x84\xC6\x87\xC6\x8B\xC6\x91\xC7\xB6\xC6\x98\xC8\xBD\xC8\xA0\xC6\xA0\xC6\xA2\xC6\xA4\xC6\xA7"
+	"\xC6\xAC\xC6\xAF\xC6\xB3\xC6\xB5\xC6\xB8\xC6\xBC\xC7\xB7\xC7\x84\xC7\x87\xC7\x8A\xC7\x8D\xC7\x8F\xC7"
+	"\x91\xC7\x93\xC7\x95\xC7\x97\xC7\x99\xC7\x9B\xC7\x9E\xC7\xA0\xC7\xA2\xC7\xA4\xC7\xA6\xC7\xA8\xC7\xAA"
+	"\xC7\xAC\xC7\xAE\x4A\xCC\x8C\xC7\xB1\xC7\xB4\xC7\xB8\xC7\xBA\xC7\xBC\xC7\xBE\xC8\x80\xC8\x82\xC8\x84"
+	"\xC8\x86\xC8\x88\xC8\x8A\xC8\x8C\xC8\x8E\xC8\x90\xC8\x92\xC8\x94\xC8\x96\xC8\x98\xC8\x9A\xC8\x9C\xC8"
+	"\x9E\xC8\xA4\xC8\xA6\xC8\xA8\xC8\xAA\xC8\xAC\xC8\xAE\xC8\xB0\xC8\xB2\xC8\xBB\xE2\xB1\xBE\xE2\xB1\xBF"
+	"\xC9\x81\xC9\x86\xC9\x88\xC9\x8A\xC9\x8C\xC9\x8E\xE2\xB1\xAF\xE2\xB1\xAD\xE2\xB1\xB0\xC6\x81\xC6\x86"
+	"\xC6\x89\xC6\x8A\xC6\x8F\xEA\x9E\xAB\xC6\x93\xEA\x9E\xAC\xC6\x94\xEA\x9E\x8D\xEA\x9E\xAA\xC6\x97\xC6"
+	"\x96\xE2\xB1\xA2\xEA\x9E\xAD\xC6\x9C\xE2\xB1\xAE\xC6\x9D\xC6\x9F\xE2\xB1\xA4\xC6\xA6\xC6\xA9\xEA\x9E"
+	"\xB1\xC6\xAE\xC9\x84\xC6\xB1\xC6\xB2\xC9\x85\xEA\x9E\xB0\xCD\xB0\xCD\xB2\xCD\xB6\xCF\xBD\xCF\xBE\xCF"
+	"\xBF\xCE\x99\xCC\x88\xCC\x81\xCE\x86\xCE\x88\xCE\x89\xCE\x8A\xCE\xA5\xCC\x88\xCC\x81\xCE\xAA\xCE\xAB"
+	"\xCE\x8C\xCE\x8E\xCE\x8F\xCF\x8F\xCF\x98\xCF\x9A\xCF\x9E\xCF\xA0\xCF\xA2\xCF\xA4\xCF\xA6\xCF\xA8\xCF"
+	"\xAA\xCF\xAC\xCF\xAE\xCF\xB9\xCD\xBF\xCF\xB7\xCF\xBA\xD0\x91\xD0\x92\xD0\x94\xD0\x99\xD0\x9B\xD0\x9C"
+	"\xD0\x9D\xD0\x9F\xD0\xA0\xD0\xA1\xD0\xA2\xD0\xA4\xD0\xA5\xD0\xA6\xD0\xA8\xD0\xA9\xD0\xAA\xD0\xAC\xD0"
+	"\xAE\xD0\xAF\xD0\x80\xD0\x81\xD0\x82\xD0\x83\xD0\x84\xD0\x85\xD0\x87\xD0\x88\xD0\x89\xD0\x8A\xD0\x8B"
+	"\xD0\x8C\xD0\x8D\xD0\x8E\xD0\x8F\xD1\xA0\xD1\xA2\xD1\xA4\xD1\xA6\xD1\xA8\xD1\xAA\xD1\xAC\xD1\xAE\xD1"
+	"\xB0\xD1\xB2\xD1\xB6\xD1\xB8\xD1\xBA\xD1\xBC\xD1\xBE\xD2\x80\xD2\x8A\xD2\x8C\xD2\x8E\xD2\x90\xD2\x92"
+	"\xD2\x94\xD2\x96\xD2\x98\xD2\x9A\xD2\x9C\xD2\x9E\xD2\xA0\xD2\xA2\xD2\xA4\xD2\xA6\xD2\xA8\xD2\xAA\xD2"
+	"\xAC\xD2\xAE\xD2\xB0\xD2\xB2\xD2\xB4\xD2\xB6\xD2\xB8\xD2\xBA\xD2\xBC\xD2\xBE\xD3\x81\xD3\x83\xD3\x85"
+	"\xD3\x87\xD3\x89\xD3\x8B\xD3\x8D\xD3\x80\xD3\x90\xD3\x92\xD3\x94\xD3\x96\xD3\x9A\xD3\x9C\xD3\x9E\xD3"
+	"\xA0\xD3\xA2\xD3\xA4\xD3\xA6\xD3\xAA\xD3\xAC\xD3\xAE\xD3\xB0\xD3\xB2\xD3\xB4\xD3\xB6\xD3\xB8\xD3\xBA"
+	"\xD3\xBC\xD3\xBE\xD4\x80\xD4\x82\xD4\x84\xD4\x86\xD4\x88\xD4\x8A\xD4\x8C\xD4\x8E\xD4\x90\xD4\x92\xD4"
+	"\x94\xD4\x96\xD4\x98\xD4\x9A\xD4\x9C\xD4\x9E\xD4\xA0\xD4\xA2\xD4\xA4\xD4\xA6\xD4\xA8\xD4\xAA\xD4\xAC"
+	"\xD4\xAE\xD4\xB1\xD4\xB2\xD4\xB3\xD4\xB4\xD4\xB5\xD4\xB6\xD4\xB7\xD4\xB8\xD4\xB9\xD4\xBA\xD4\xBB\xD4"
+	"\xBC\xD4\xBD\xD4\xBE\xD4\xBF\xD5\x80\xD5\x81\xD5\x82\xD5\x83\xD5\x84\xD5\x85\xD5\x86\xD5\x87\xD5\x88"
+	"\xD5\x89\xD5\x8A\xD5\x8B\xD5\x8C\xD5\x8D\xD5\x8E\xD5\x8F\xD5\x90\xD5\x91\xD5\x92\xD5\x93\xD5\x94\xD5"
+	"\x95\xD5\x96\xD4\xB5\xD5\x92\xEA\x9D\xBD\xE2\xB1\xA3\xE1\xB8\x80\xE1\xB8\x82\xE1\xB8\x84\xE1\xB8\x86"
+	"\xE1\xB8\x88\xE1\xB8\x8A\xE1\xB8\x8C\xE1\xB8\x8E\xE1\xB8\x90\xE1\xB8\x92\xE1\xB8\x94\xE1\xB8\x96\xE1"
+	"\xB8\x98\xE1\xB8\x9A\xE1\xB8\x9C\xE1\xB8\x9E\xE1\xB8\xA0\xE1\xB8\xA2\xE1\xB8\xA4\xE1\xB8\xA6\xE1\xB8"
+	"\xA8\xE1\xB8\xAA\xE1\xB8\xAC\xE1\xB8\xAE\xE1\xB8\xB0\xE1\xB8\xB2\xE1\xB8\xB4\xE1\xB8\xB6\xE1\xB8\xB8"
+	"\xE1\xB8\xBA\xE1\xB8\xBC\xE1\xB8\xBE\xE1\xB9\x80\xE1\xB9\x82\xE1\xB9\x84\xE1\xB9\x86\xE1\xB9\x88\xE1"
+	"\xB9\x8A\xE1\xB9\x8C\xE1\xB9\x8E\xE1\xB9\x90\xE1\xB9\x92\xE1\xB9\x94\xE1\xB9\x96\xE1\xB9\x98\xE1\xB9"
+	"\x9A\xE1\xB9\x9C\xE1\xB9\x9E\xE1\xB9\xA0\xE1\xB9\xA2\xE1\xB9\xA4\xE1\xB9\xA6\xE1\xB9\xA8\xE1\xB9\xAA"
+	"\xE1\xB9\xAC\xE1\xB9\xAE\xE1\xB9\xB0\xE1\xB9\xB2\xE1\xB9\xB4\xE1\xB9\xB6\xE1\xB9\xB8\xE1\xB9\xBA\xE1"
+	"\xB9\xBC\xE1\xB9\xBE\xE1\xBA\x80\xE1\xBA\x82\xE1\xBA\x84\xE1\xBA\x86\xE1\xBA\x88\xE1\xBA\x8A\xE1\xBA"
+	"\x8C\xE1\xBA\x8E\xE1\xBA\x90\xE1\xBA\x92\xE1\xBA\x94\x48\xCC\xB1\x54\xCC\x88\x57\xCC\x8A\x59\xCC\x8A"
+	"\x41\xCA\xBE\xE1\xBA\xA0\xE1\xBA\xA2\xE1\xBA\xA4\xE1\xBA\xA6\xE1\xBA\xA8\xE1\xBA\xAA\xE1\xBA\xAC\xE1"
+	"\xBA\xAE\xE1\xBA\xB0\xE1\xBA\xB2\xE1\xBA\xB4\xE1\xBA\xB6\xE1\xBA\xB8\xE1\xBA\xBA\xE1\xBA\xBC\xE1\xBA"
+	"\xBE\xE1\xBB\x80\xE1\xBB\x82\xE1\xBB\x84\xE1\xBB\x86\xE1\xBB\x88\xE1\xBB\x8A\xE1\xBB\x8C\xE1\xBB\x8E"
+	"\xE1\xBB\x90\xE1\xBB\x92\xE1\xBB\x94\xE1\xBB\x96\xE1\xBB\x98\xE1\xBB\x9A\xE1\xBB\x9C\xE1\xBB\x9E\xE1"
+	"\xBB\xA0\xE1\xBB\xA2\xE1\xBB\xA4\xE1\xBB\xA6\xE1\xBB\xA8\xE1\xBB\xAA\xE1\xBB\xAC\xE1\xBB\xAE\xE1\xBB"
+	"\xB0\xE1\xBB\xB2\xE1\xBB\xB4\xE1\xBB\xB6\xE1\xBB\xB8\xE1\xBB\xBA\xE1\xBB\xBC\xE1\xBB\xBE\xE1\xBC\x88"
+	"\xE1\xBC\x89\xE1\xBC\x8A\xE1\xBC\x8B\xE1\xBC\x8C\xE1\xBC\x8D\xE1\xBC\x8E\xE1\xBC\x8F\xE1\xBC\x98\xE1"
+	"\xBC\x99\xE1\xBC\x9A\xE1\xBC\x9B\xE1\xBC\x9C\xE1\xBC\x9D\xE1\xBC\xA8\xE1\xBC\xA9\xE1\xBC\xAA\xE1\xBC"
+	"\xAB\xE1\xBC\xAC\xE1\xBC\xAD\xE1\xBC\xAE\xE1\xBC\xAF\xE1\xBC\xB8\xE1\xBC\xB9\xE1\xBC\xBA\xE1\xBC\xBB"
+	"\xE1\xBC\xBC\xE1\xBC\xBD\xE1\xBC\xBE\xE1\xBC\xBF\xE1\xBD\x88\xE1\xBD\x89\xE1\xBD\x8A\xE1\xBD\x8B\xE1"
+	"\xBD\x8C\xE1\xBD\x8D\xCE\xA5\xCC\x93\xE1\xBD\x99\xCE\xA5\xCC\x93\xCC\x80\xE1\xBD\x9B\xCE\xA5\xCC\x93"
+	"\xCC\x81\xE1\xBD\x9D\xCE\xA5\xCC\x93\xCD\x82\xE1\xBD\x9F\xE1\xBD\xA8\xE1\xBD\xA9\xE1\xBD\xAA\xE1\xBD"
+	"\xAB\xE1\xBD\xAC\xE1\xBD\xAD\xE1\xBD\xAE\xE1\xBD\xAF\xE1\xBE\xBA\xE1\xBE\xBB\xE1\xBF\x88\xE1\xBF\x89"
+	"\xE1\xBF\x8A\xE1\xBF\x8B\xE1\xBF\x9A\xE1\xBF\x9B\xE1\xBF\xB8\xE1\xBF\xB9\xE1\xBF\xAA\xE1\xBF\xAB\xE1"
+	"\xBF\xBA\xE1\xBF\xBB\xE1\xBC\x88\xCE\x99\xE1\xBC\x89\xCE\x99\xE1\xBC\x8A\xCE\x99\xE1\xBC\x8B\xCE\x99"
+	"\xE1\xBC\x8C\xCE\x99\xE1\xBC\x8D\xCE\x99\xE1\xBC\x8E\xCE\x99\xE1\xBC\x8F\xCE\x99\xE1\xBC\xA8\xCE\x99"
+	"\xE1\xBC\xA9\xCE\x99\xE1\xBC\xAA\xCE\x99\xE1\xBC\xAB\xCE\x99\xE1\xBC\xAC\xCE\x99\xE1\xBC\xAD\xCE\x99"
+	"\xE1\xBC\xAE\xCE\x99\xE1\xBC\xAF\xCE\x99\xE1\xBD\xA8\xCE\x99\xE1\xBD\xA9\xCE\x99\xE1\xBD\xAA\xCE\x99"
+	"\xE1\xBD\xAB\xCE\x99\xE1\xBD\xAC\xCE\x99\xE1\xBD\xAD\xCE\x99\xE1\xBD\xAE\xCE\x99\xE1\xBD\xAF\xCE\x99"
+	"\xE1\xBE\xB8\xE1\xBE\xB9\xE1\xBE\xBA\xCE\x99\xCE\x91\xCE\x99\xCE\x86\xCE\x99\xCE\x91\xCD\x82\xCE\x91"
+	"\xCD\x82\xCE\x99\xE1\xBF\x8A\xCE\x99\xCE\x97\xCE\x99\xCE\x89\xCE\x99\xCE\x97\xCD\x82\xCE\x97\xCD\x82"
+	"\xCE\x99\xE1\xBF\x98\xE1\xBF\x99\xCE\x99\xCC\x88\xCC\x80\xCE\x99\xCD\x82\xCE\x99\xCC\x88\xCD\x82\xE1"
+	"\xBF\xA8\xE1\xBF\xA9\xCE\xA5\xCC\x88\xCC\x80\xCE\xA1\xCC\x93\xE1\xBF\xAC\xCE\xA5\xCD\x82\xCE\xA5\xCC"
+	"\x88\xCD\x82\xE1\xBF\xBA\xCE\x99\xCE\xA9\xCE\x99\xCE\x8F\xCE\x99\xCE\xA9\xCD\x82\xCE\xA9\xCD\x82\xCE"
+	"\x99\xE2\x84\xB2\xE2\x85\xA0\xE2\x85\xA1\xE2\x85\xA2\xE2\x85\xA3\xE2\x85\xA4\xE2\x85\xA5\xE2\x85\xA6"
+	"\xE2\x85\xA7\xE2\x85\xA8\xE2\x85\xA9\xE2\x85\xAA\xE2\x85\xAB\xE2\x85\xAC\xE2\x85\xAD\xE2\x85\xAE\xE2"
+	"\x85\xAF\xE2\x86\x83\xE2\x92\xB6\xE2\x92\xB7\xE2\x92\xB8\xE2\x92\xB9\xE2\x92\xBA\xE2\x92\xBB\xE2\x92"
+	"\xBC\xE2\x92\xBD\xE2\x92\xBE\xE2\x92\xBF\xE2\x93\x80\xE2\x93\x81\xE2\x93\x82\xE2\x93\x83\xE2\x93\x84"
+	"\xE2\x93\x85\xE2\x93\x86\xE2\x93\x87\xE2\x93\x88\xE2\x93\x89\xE2\x93\x8A\xE2\x93\x8B\xE2\x93\x8C\xE2"
+	"\x93\x8D\xE2\x93\x8E\xE2\x93\x8F\xE2\xB0\x80\xE2\xB0\x81\xE2\xB0\x82\xE2\xB0\x83\xE2\xB0\x84\xE2\xB0"
+	"\x85\xE2\xB0\x86\xE2\xB0\x87\xE2\xB0\x88\xE2\xB0\x89\xE2\xB0\x8A\xE2\xB0\x8B\xE2\xB0\x8C\xE2\xB0\x8D"
+	"\xE2\xB0\x8E\xE2\xB0\x8F\xE2\xB0\x90\xE2\xB0\x91\xE2\xB0\x92\xE2\xB0\x93\xE2\xB0\x94\xE2\xB0\x95\xE2"
+	"\xB0\x96\xE2\xB0\x97\xE2\xB0\x98\xE2\xB0\x99\xE2\xB0\x9A\xE2\xB0\x9B\xE2\xB0\x9C\xE2\xB0\x9D\xE2\xB0"
+	"\x9E\xE2\xB0\x9F\xE2\xB0\xA0\xE2\xB0\xA1\xE2\xB0\xA2\xE2\xB0\xA3\xE2\xB0\xA4\xE2\xB0\xA5\xE2\xB0\xA6"
+	"\xE2\xB0\xA7\xE2\xB0\xA8\xE2\xB0\xA9\xE2\xB0\xAA\xE2\xB0\xAB\xE2\xB0\xAC\xE2\xB0\xAD\xE2\xB0\xAE\xE2"
+	"\xB1\xA0\xC8\xBA\xC8\xBE\xE2\xB1\xA7\xE2\xB1\xA9\xE2\xB1\xAB\xE2\xB1\xB2\xE2\xB1\xB5\xE2\xB2\x80\xE2"
+	"\xB2\x82\xE2\xB2\x84\xE2\xB2\x86\xE2\xB2\x88\xE2\xB2\x8A\xE2\xB2\x8C\xE2\xB2\x8E\xE2\xB2\x90\xE2\xB2"
+	"\x92\xE2\xB2\x94\xE2\xB2\x96\xE2\xB2\x98\xE2\xB2\x9A\xE2\xB2\x9C\xE2\xB2\x9E\xE2\xB2\xA0\xE2\xB2\xA2"
+	"\xE2\xB2\xA4\xE2\xB2\xA6\xE2\xB2\xA8\xE2\xB2\xAA\xE2\xB2\xAC\xE2\xB2\xAE\xE2\xB2\xB0\xE2\xB2\xB2\xE2"
+	"\xB2\xB4\xE2\xB2\xB6\xE2\xB2\xB8\xE2\xB2\xBA\xE2\xB2\xBC\xE2\xB2\xBE\xE2\xB3\x80\xE2\xB3\x82\xE2\xB3"
+	"\x84\xE2\xB3\x86\xE2\xB3\x88\xE2\xB3\x8A\xE2\xB3\x8C\xE2\xB3\x8E\xE2\xB3\x90\xE2\xB3\x92\xE2\xB3\x94"
+	"\xE2\xB3\x96\xE2\xB3\x98\xE2\xB3\x9A\xE2\xB3\x9C\xE2\xB3\x9E\xE2\xB3\xA0\xE2\xB3\xA2\xE2\xB3\xAB\xE2"
+	"\xB3\xAD\xE2\xB3\xB2\xE1\x82\xA0\xE1\x82\xA1\xE1\x82\xA2\xE1\x82\xA3\xE1\x82\xA4\xE1\x82\xA5\xE1\x82"
+	"\xA6\xE1\x82\xA7\xE1\x82\xA8\xE1\x82\xA9\xE1\x82\xAA\xE1\x82\xAB\xE1\x82\xAC\xE1\x82\xAD\xE1\x82\xAE"
+	"\xE1\x82\xAF\xE1\x82\xB0\xE1\x82\xB1\xE1\x82\xB2\xE1\x82\xB3\xE1\x82\xB4\xE1\x82\xB5\xE1\x82\xB6\xE1"
+	"\x82\xB7\xE1\x82\xB8\xE1\x82\xB9\xE1\x82\xBA\xE1\x82\xBB\xE1\x82\xBC\xE1\x82\xBD\xE1\x82\xBE\xE1\x82"
+	"\xBF\xE1\x83\x80\xE1\x83\x81\xE1\x83\x82\xE1\x83\x83\xE1\x83\x84\xE1\x83\x85\xE1\x83\x87\xE1\x83\x8D"
+	"\xEA\x99\x80\xEA\x99\x82\xEA\x99\x84\xEA\x99\x86\xEA\x99\x88\xEA\x99\x8A\xEA\x99\x8C\xEA\x99\x8E\xEA"
+	"\x99\x90\xEA\x99\x92\xEA\x99\x94\xEA\x99\x96\xEA\x99\x98\xEA\x99\x9A\xEA\x99\x9C\xEA\x99\x9E\xEA\x99"
+	"\xA0\xEA\x99\xA2\xEA\x99\xA4\xEA\x99\xA6\xEA\x99\xA8\xEA\x99\xAA\xEA\x99\xAC\xEA\x9A\x80\xEA\x9A\x82"
+	"\xEA\x9A\x84\xEA\x9A\x86\xEA\x9A\x88\xEA\x9A\x8A\xEA\x9A\x8C\xEA\x9A\x8E\xEA\x9A\x90\xEA\x9A\x92\xEA"
+	"\x9A\x94\xEA\x9A\x96\xEA\x9A\x98\xEA\x9A\x9A\xEA\x9C\xA2\xEA\x9C\xA4\xEA\x9C\xA6\xEA\x9C\xA8\xEA\x9C"
+	"\xAA\xEA\x9C\xAC\xEA\x9C\xAE\xEA\x9C\xB2\xEA\x9C\xB4\xEA\x9C\xB6\xEA\x9C\xB8\xEA\x9C\xBA\xEA\x9C\xBC"
+	"\xEA\x9C\xBE\xEA\x9D\x80\xEA\x9D\x82\xEA\x9D\x84\xEA\x9D\x86\xEA\x9D\x88\xEA\x9D\x8A\xEA\x9D\x8C\xEA"
+	"\x9D\x8E\xEA\x9D\x90\xEA\x9D\x92\xEA\x9D\x94\xEA\x9D\x96\xEA\x9D\x98\xEA\x9D\x9A\xEA\x9D\x9C\xEA\x9D"
+	"\x9E\xEA\x9D\xA0\xEA\x9D\xA2\xEA\x9D\xA4\xEA\x9D\xA6\xEA\x9D\xA8\xEA\x9D\xAA\xEA\x9D\xAC\xEA\x9D\xAE"
+	"\xEA\x9D\xB9\xEA\x9D\xBB\xEA\x9D\xBE\xEA\x9E\x80\xEA\x9E\x82\xEA\x9E\x84\xEA\x9E\x86\xEA\x9E\x8B\xEA"
+	"\x9E\x90\xEA\x9E\x92\xEA\x9E\x96\xEA\x9E\x98\xEA\x9E\x9A\xEA\x9E\x9C\xEA\x9E\x9E\xEA\x9E\xA0\xEA\x9E"
+	"\xA2\xEA\x9E\xA4\xEA\x9E\xA6\xEA\x9E\xA8\x46\x46\x46\x49\x46\x4C\x46\x46\x49\x46\x46\x4C\x53\x54\xD5"
+	"\x84\xD5\x86\xD5\x84\xD4\xB5\xD5\x84\xD4\xBB\xD5\x8E\xD5\x86\xD5\x84\xD4\xBD\xEF\xBC\xA1\xEF\xBC\xA2"
+	"\xEF\xBC\xA3\xEF\xBC\xA4\xEF\xBC\xA5\xEF\xBC\xA6\xEF\xBC\xA7\xEF\xBC\xA8\xEF\xBC\xA9\xEF\xBC\xAA\xEF"
+	"\xBC\xAB\xEF\xBC\xAC\xEF\xBC\xAD\xEF\xBC\xAE\xEF\xBC\xAF\xEF\xBC\xB0\xEF\xBC\xB1\xEF\xBC\xB2\xEF\xBC"
+	"\xB3\xEF\xBC\xB4\xEF\xBC\xB5\xEF\xBC\xB6\xEF\xBC\xB7\xEF\xBC\xB8\xEF\xBC\xB9\xEF\xBC\xBA\xF0\x90\x90"
+	"\x80\xF0\x90\x90\x81\xF0\x90\x90\x82\xF0\x90\x90\x83\xF0\x90\x90\x84\xF0\x90\x90\x85\xF0\x90\x90\x86"
+	"\xF0\x90\x90\x87\xF0\x90\x90\x88\xF0\x90\x90\x89\xF0\x90\x90\x8A\xF0\x90\x90\x8B\xF0\x90\x90\x8C\xF0"
+	"\x90\x90\x8D\xF0\x90\x90\x8E\xF0\x90\x90\x8F\xF0\x90\x90\x90\xF0\x90\x90\x91\xF0\x90\x90\x92\xF0\x90"
+	"\x90\x93\xF0\x90\x90\x94\xF0\x90\x90\x95\xF0\x90\x90\x96\xF0\x90\x90\x97\xF0\x90\x90\x98\xF0\x90\x90"
+	"\x99\xF0\x90\x90\x9A\xF0\x90\x90\x9B\xF0\x90\x90\x9C\xF0\x90\x90\x9D\xF0\x90\x90\x9E\xF0\x90\x90\x9F"
+	"\xF0\x90\x90\xA0\xF0\x90\x90\xA1\xF0\x90\x90\xA2\xF0\x90\x90\xA3\xF0\x90\x90\xA4\xF0\x90\x90\xA5\xF0"
+	"\x90\x90\xA6\xF0\x90\x90\xA7\xF0\x91\xA2\xA0\xF0\x91\xA2\xA1\xF0\x91\xA2\xA2\xF0\x91\xA2\xA3\xF0\x91"
+	"\xA2\xA4\xF0\x91\xA2\xA5\xF0\x91\xA2\xA6\xF0\x91\xA2\xA7\xF0\x91\xA2\xA8\xF0\x91\xA2\xA9\xF0\x91\xA2"
+	"\xAA\xF0\x91\xA2\xAB\xF0\x91\xA2\xAC\xF0\x91\xA2\xAD\xF0\x91\xA2\xAE\xF0\x91\xA2\xAF\xF0\x91\xA2\xB0"
+	"\xF0\x91\xA2\xB1\xF0\x91\xA2\xB2\xF0\x91\xA2\xB3\xF0\x91\xA2\xB4\xF0\x91\xA2\xB5\xF0\x91\xA2\xB6\xF0"
+	"\x91\xA2\xB7\xF0\x91\xA2\xB8\xF0\x91\xA2\xB9\xF0\x91\xA2\xBA\xF0\x91\xA2\xBB\xF0\x91\xA2\xBC\xF0\x91"
+	"\xA2\xBD\xF0\x91\xA2\xBE\xF0\x91\xA2\xBF\xC3\xA0\xC3\xA1\xC3\xA2\xC3\xA3\xC3\xA4\xC3\xA5\xC3\xA7\xC3"
+	"\xA8\xC3\xA9\xC3\xAA\xC3\xAB\xC3\xAC\xC3\xAD\xC3\xAE\xC3\xAF\xC3\xB1\xC3\xB2\xC3\xB3\xC3\xB4\xC3\xB5"
+	"\xC3\xB6\xC3\xB9\xC3\xBA\xC3\xBB\xC3\xBC\xC3\xBD\xC3\xBE\xC4\x81\xC4\x83\xC4\x85\xC4\x87\xC4\x89\xC4"
+	"\x8B\xC4\x8D\xC4\x8F\xC4\x91\xC4\x93\xC4\x95\xC4\x97\xC4\x99\xC4\x9B\xC4\x9D\xC4\x9F\xC4\xA1\xC4\xA3"
+	"\xC4\xA5\xC4\xA9\xC4\xAB\xC4\xAD\xC4\xAF\x69\xCC\x87\xC4\xB3\xC4\xB5\xC4\xB7\xC4\xBA\xC4\xBC\xC4\xBE"
+	"\xC5\x80\xC5\x82\xC5\x84\xC5\x86\xC5\x88\xC5\x8D\xC5\x8F\xC5\x91\xC5\x95\xC5\x97\xC5\x99\xC5\x9B\xC5"
+	"\x9D\xC5\x9F\xC5\xA1\xC5\xA3\xC5\xA5\xC5\xA7\xC5\xA9\xC5\xAB\xC5\xAD\xC5\xAF\xC5\xB1\xC5\xB3\xC5\xB5"
+	"\xC5\xB7\xC3\xBF\xC5\xBA\xC5\xBC\xC5\xBE\xC9\x93\xC6\x83\xC6\x85\xC6\x88\xC9\x96\xC9\x97\xC6\x8C\xC7"
+	"\x9D\xC6\x92\xC9\xA0\xC6\x99\xC6\xA1\xC6\xA3\xC6\xA5\xCA\x80\xC6\xA8\xC6\xAD\xCA\x88\xC6\xB0\xC6\xB4"
+	"\xC6\xB6\xC6\xB9\xC6\xBD\xC7\x86\xC7\x89\xC7\x8C\xC7\x8E\xC7\x90\xC7\x92\xC7\x94\xC7\x96\xC7\x98\xC7"
+	"\x9A\xC7\x9C\xC7\x9F\xC7\xA1\xC7\xA3\xC7\xA5\xC7\xA7\xC7\xA9\xC7\xAB\xC7\xAD\xC7\xAF\xC7\xB3\xC7\xB5"
+	"\xC6\x95\xC6\xBF\xC7\xB9\xC7\xBB\xC7\xBD\xC7\xBF\xC8\x81\xC8\x83\xC8\x85\xC8\x87\xC8\x89\xC8\x8B\xC8"
+	"\x8D\xC8\x8F\xC8\x91\xC8\x93\xC8\x95\xC8\x97\xC8\x99\xC8\x9B\xC8\x9D\xC8\x9F\xC6\x9E\xC8\xA3\xC8\xA5"
+	"\xC8\xA7\xC8\xA9\xC8\xAB\xC8\xAD\xC8\xAF\xC8\xB1\xC8\xB3\xE2\xB1\xA5\xC8\xBC\xC6\x9A\xE2\xB1\xA6\xC9"
+	"\x82\xC6\x80\xC9\x87\xC9\x89\xC9\x8B\xC9\x8D\xC9\x8F\xCD\xB1\xCD\xB3\xCD\xB7\xCF\xB3\xCE\xAC\xCE\xAD"
+	"\xCE\xAE\xCE\xAF\xCF\x8C\xCF\x8D\xCF\x8E\xCF\x8A\xCF\x8B\xCF\x97\xCF\x99\xCF\x9B\xCF\x9F\xCF\xA1\xCF"
+	"\xA3\xCF\xA5\xCF\xA7\xCF\xA9\xCF\xAB\xCF\xAD\xCF\xAF\xCF\xB8\xCF\xB2\xCF\xBB\xCD\xBB\xCD\xBC\xCD\xBD"
+	"\xD1\x90\xD1\x91\xD1\x92\xD1\x93\xD1\x94\xD1\x95\xD1\x97\xD1\x98\xD1\x99\xD1\x9A\xD1\x9B\xD1\x9C\xD1"
+	"\x9D\xD1\x9E\xD1\x9F\xD0\xB1\xD0\xB2\xD0\xB4\xD0\xB9\xD0\xBB\xD0\xBC\xD0\xBF\xD1\x80\xD1\x81\xD1\x82"
+	"\xD1\x84\xD1\x85\xD1\x86\xD1\x88\xD1\x89\xD1\x8E\xD1\x8F\xD1\xA1\xD1\xA3\xD1\xA5\xD1\xA7\xD1\xA9\xD1"
+	"\xAB\xD1\xAD\xD1\xAF\xD1\xB1\xD1\xB3\xD1\xB7\xD1\xB9\xD1\xBB\xD1\xBD\xD1\xBF\xD2\x81\xD2\x8B\xD2\x8D"
+	"\xD2\x8F\xD2\x91\xD2\x93\xD2\x95\xD2\x97\xD2\x99\xD2\x9B\xD2\x9D\xD2\x9F\xD2\xA1\xD2\xA3\xD2\xA5\xD2"
+	"\xA7\xD2\xA9\xD2\xAB\xD2\xAD\xD2\xAF\xD2\xB1\xD2\xB3\xD2\xB5\xD2\xB7\xD2\xB9\xD2\xBB\xD2\xBD\xD2\xBF"
+	"\xD3\x8F\xD3\x82\xD3\x84\xD3\x86\xD3\x88\xD3\x8A\xD3\x8C\xD3\x8E\xD3\x91\xD3\x93\xD3\x95\xD3\x97\xD3"
+	"\x9B\xD3\x9D\xD3\x9F\xD3\xA1\xD3\xA3\xD3\xA5\xD3\xA7\xD3\xAB\xD3\xAD\xD3\xAF\xD3\xB1\xD3\xB3\xD3\xB5"
+	"\xD3\xB7\xD3\xB9\xD3\xBB\xD3\xBD\xD3\xBF\xD4\x81\xD4\x83\xD4\x85\xD4\x87\xD4\x89\xD4\x8B\xD4\x8D\xD4"
+	"\x8F\xD4\x91\xD4\x93\xD4\x95\xD4\x97\xD4\x99\xD4\x9B\xD4\x9D\xD4\x9F\xD4\xA1\xD4\xA3\xD4\xA5\xD4\xA7"
+	"\xD4\xA9\xD4\xAB\xD4\xAD\xD4\xAF\xD5\xA1\xD5\xA2\xD5\xA3\xD5\xA4\xD5\xA6\xD5\xA7\xD5\xA8\xD5\xA9\xD5"
+	"\xAA\xD5\xAC\xD5\xAE\xD5\xAF\xD5\xB0\xD5\xB1\xD5\xB2\xD5\xB3\xD5\xB5\xD5\xB7\xD5\xB8\xD5\xB9\xD5\xBA"
+	"\xD5\xBB\xD5\xBC\xD5\xBD\xD5\xBF\xD6\x80\xD6\x81\xD6\x83\xD6\x84\xD6\x85\xD6\x86\xE2\xB4\x80\xE2\xB4"
+	"\x81\xE2\xB4\x82\xE2\xB4\x83\xE2\xB4\x84\xE2\xB4\x85\xE2\xB4\x86\xE2\xB4\x87\xE2\xB4\x88\xE2\xB4\x89"
+	"\xE2\xB4\x8A\xE2\xB4\x8B\xE2\xB4\x8C\xE2\xB4\x8D\xE2\xB4\x8E\xE2\xB4\x8F\xE2\xB4\x90\xE2\xB4\x91\xE2"
+	"\xB4\x92\xE2\xB4\x93\xE2\xB4\x94\xE2\xB4\x95\xE2\xB4\x96\xE2\xB4\x97\xE2\xB4\x98\xE2\xB4\x99\xE2\xB4"
+	"\x9A\xE2\xB4\x9B\xE2\xB4\x9C\xE2\xB4\x9D\xE2\xB4\x9E\xE2\xB4\x9F\xE2\xB4\xA0\xE2\xB4\xA1\xE2\xB4\xA2"
+	"\xE2\xB4\xA3\xE2\xB4\xA4\xE2\xB4\xA5\xE2\xB4\xA7\xE2\xB4\xAD\xE1\xB8\x81\xE1\xB8\x83\xE1\xB8\x85\xE1"
+	"\xB8\x87\xE1\xB8\x89\xE1\xB8\x8B\xE1\xB8\x8D\xE1\xB8\x8F\xE1\xB8\x91\xE1\xB8\x93\xE1\xB8\x95\xE1\xB8"
+	"\x97\xE1\xB8\x99\xE1\xB8\x9B\xE1\xB8\x9D\xE1\xB8\x9F\xE1\xB8\xA1\xE1\xB8\xA3\xE1\xB8\xA5\xE1\xB8\xA7"
+	"\xE1\xB8\xA9\xE1\xB8\xAB\xE1\xB8\xAD\xE1\xB8\xAF\xE1\xB8\xB1\xE1\xB8\xB3\xE1\xB8\xB5\xE1\xB8\xB7\xE1"
+	"\xB8\xB9\xE1\xB8\xBB\xE1\xB8\xBD\xE1\xB8\xBF\xE1\xB9\x81\xE1\xB9\x83\xE1\xB9\x85\xE1\xB9\x87\xE1\xB9"
+	"\x89\xE1\xB9\x8B\xE1\xB9\x8D\xE1\xB9\x8F\xE1\xB9\x91\xE1\xB9\x93\xE1\xB9\x95\xE1\xB9\x97\xE1\xB9\x99"
+	"\xE1\xB9\x9B\xE1\xB9\x9D\xE1\xB9\x9F\xE1\xB9\xA1\xE1\xB9\xA3\xE1\xB9\xA5\xE1\xB9\xA7\xE1\xB9\xA9\xE1"
+	"\xB9\xAB\xE1\xB9\xAD\xE1\xB9\xAF\xE1\xB9\xB1\xE1\xB9\xB3\xE1\xB9\xB5\xE1\xB9\xB7\xE1\xB9\xB9\xE1\xB9"
+	"\xBB\xE1\xB9\xBD\xE1\xB9\xBF\xE1\xBA\x81\xE1\xBA\x83\xE1\xBA\x85\xE1\xBA\x87\xE1\xBA\x89\xE1\xBA\x8B"
+	"\xE1\xBA\x8D\xE1\xBA\x8F\xE1\xBA\x91\xE1\xBA\x93\xE1\xBA\x95\xC3\x9F\xE1\xBA\xA1\xE1\xBA\xA3\xE1\xBA"
+	"\xA5\xE1\xBA\xA7\xE1\xBA\xA9\xE1\xBA\xAB\xE1\xBA\xAD\xE1\xBA\xAF\xE1\xBA\xB1\xE1\xBA\xB3\xE1\xBA\xB5"
+	"\xE1\xBA\xB7\xE1\xBA\xB9\xE1\xBA\xBB\xE1\xBA\xBD\xE1\xBA\xBF\xE1\xBB\x81\xE1\xBB\x83\xE1\xBB\x85\xE1"
+	"\xBB\x87\xE1\xBB\x89\xE1\xBB\x8B\xE1\xBB\x8D\xE1\xBB\x8F\xE1\xBB\x91\xE1\xBB\x93\xE1\xBB\x95\xE1\xBB"
+	"\x97\xE1\xBB\x99\xE1\xBB\x9B\xE1\xBB\x9D\xE1\xBB\x9F\xE1\xBB\xA1\xE1\xBB\xA3\xE1\xBB\xA5\xE1\xBB\xA7"
+	"\xE1\xBB\xA9\xE1\xBB\xAB\xE1\xBB\xAD\xE1\xBB\xAF\xE1\xBB\xB1\xE1\xBB\xB3\xE1\xBB\xB5\xE1\xBB\xB7\xE1"
+	"\xBB\xB9\xE1\xBB\xBB\xE1\xBB\xBD\xE1\xBB\xBF\xE1\xBC\x80\xE1\xBC\x81\xE1\xBC\x82\xE1\xBC\x83\xE1\xBC"
+	"\x84\xE1\xBC\x85\xE1\xBC\x86\xE1\xBC\x87\xE1\xBC\x90\xE1\xBC\x91\xE1\xBC\x92\xE1\xBC\x93\xE1\xBC\x94"
+	"\xE1\xBC\x95\xE1\xBC\xA0\xE1\xBC\xA1\xE1\xBC\xA2\xE1\xBC\xA3\xE1\xBC\xA4\xE1\xBC\xA5\xE1\xBC\xA6\xE1"
+	"\xBC\xA7\xE1\xBC\xB0\xE1\xBC\xB1\xE1\xBC\xB2\xE1\xBC\xB3\xE1\xBC\xB4\xE1\xBC\xB5\xE1\xBC\xB6\xE1\xBC"
+	"\xB7\xE1\xBD\x80\xE1\xBD\x81\xE1\xBD\x82\xE1\xBD\x83\xE1\xBD\x84\xE1\xBD\x85\xE1\xBD\x91\xE1\xBD\x93"
+	"\xE1\xBD\x95\xE1\xBD\x97\xE1\xBD\xA0\xE1\xBD\xA1\xE1\xBD\xA2\xE1\xBD\xA3\xE1\xBD\xA4\xE1\xBD\xA5\xE1"
+	"\xBD\xA6\xE1\xBD\xA7\xE1\xBE\x80\xE1\xBE\x81\xE1\xBE\x82\xE1\xBE\x83\xE1\xBE\x84\xE1\xBE\x85\xE1\xBE"
+	"\x86\xE1\xBE\x87\xE1\xBE\x90\xE1\xBE\x91\xE1\xBE\x92\xE1\xBE\x93\xE1\xBE\x94\xE1\xBE\x95\xE1\xBE\x96"
+	"\xE1\xBE\x97\xE1\xBE\xA0\xE1\xBE\xA1\xE1\xBE\xA2\xE1\xBE\xA3\xE1\xBE\xA4\xE1\xBE\xA5\xE1\xBE\xA6\xE1"
+	"\xBE\xA7\xE1\xBE\xB0\xE1\xBE\xB1\xE1\xBD\xB0\xE1\xBD\xB1\xE1\xBE\xB3\xE1\xBD\xB2\xE1\xBD\xB3\xE1\xBD"
+	"\xB4\xE1\xBD\xB5\xE1\xBF\x83\xE1\xBF\x90\xE1\xBF\x91\xE1\xBD\xB6\xE1\xBD\xB7\xE1\xBF\xA0\xE1\xBF\xA1"
+	"\xE1\xBD\xBA\xE1\xBD\xBB\xE1\xBF\xA5\xE1\xBD\xB8\xE1\xBD\xB9\xE1\xBD\xBC\xE1\xBD\xBD\xE1\xBF\xB3\xE2"
+	"\x85\x8E\xE2\x85\xB0\xE2\x85\xB1\xE2\x85\xB2\xE2\x85\xB3\xE2\x85\xB4\xE2\x85\xB5\xE2\x85\xB6\xE2\x85"
+	"\xB7\xE2\x85\xB8\xE2\x85\xB9\xE2\x85\xBA\xE2\x85\xBB\xE2\x85\xBC\xE2\x85\xBD\xE2\x85\xBE\xE2\x85\xBF"
+	"\xE2\x86\x84\xE2\x93\x90\xE2\x93\x91\xE2\x93\x92\xE2\x93\x93\xE2\x93\x94\xE2\x93\x95\xE2\x93\x96\xE2"
+	"\x93\x97\xE2\x93\x98\xE2\x93\x99\xE2\x93\x9A\xE2\x93\x9B\xE2\x93\x9C\xE2\x93\x9D\xE2\x93\x9E\xE2\x93"
+	"\x9F\xE2\x93\xA0\xE2\x93\xA1\xE2\x93\xA2\xE2\x93\xA3\xE2\x93\xA4\xE2\x93\xA5\xE2\x93\xA6\xE2\x93\xA7"
+	"\xE2\x93\xA8\xE2\x93\xA9\xE2\xB0\xB0\xE2\xB0\xB1\xE2\xB0\xB2\xE2\xB0\xB3\xE2\xB0\xB4\xE2\xB0\xB5\xE2"
+	"\xB0\xB6\xE2\xB0\xB7\xE2\xB0\xB8\xE2\xB0\xB9\xE2\xB0\xBA\xE2\xB0\xBB\xE2\xB0\xBC\xE2\xB0\xBD\xE2\xB0"
+	"\xBE\xE2\xB0\xBF\xE2\xB1\x80\xE2\xB1\x81\xE2\xB1\x82\xE2\xB1\x83\xE2\xB1\x84\xE2\xB1\x85\xE2\xB1\x86"
+	"\xE2\xB1\x87\xE2\xB1\x88\xE2\xB1\x89\xE2\xB1\x8A\xE2\xB1\x8B\xE2\xB1\x8C\xE2\xB1\x8D\xE2\xB1\x8E\xE2"
+	"\xB1\x8F\xE2\xB1\x90\xE2\xB1\x91\xE2\xB1\x92\xE2\xB1\x93\xE2\xB1\x94\xE2\xB1\x95\xE2\xB1\x96\xE2\xB1"
+	"\x97\xE2\xB1\x98\xE2\xB1\x99\xE2\xB1\x9A\xE2\xB1\x9B\xE2\xB1\x9C\xE2\xB1\x9D\xE2\xB1\x9E\xE2\xB1\xA1"
+	"\xE1\xB5\xBD\xC9\xBD\xE2\xB1\xA8\xE2\xB1\xAA\xE2\xB1\xAC\xE2\xB1\xB3\xE2\xB1\xB6\xC8\xBF\xC9\x80\xE2"
+	"\xB2\x81\xE2\xB2\x83\xE2\xB2\x85\xE2\xB2\x87\xE2\xB2\x89\xE2\xB2\x8B\xE2\xB2\x8D\xE2\xB2\x8F\xE2\xB2"
+	"\x91\xE2\xB2\x93\xE2\xB2\x95\xE2\xB2\x97\xE2\xB2\x99\xE2\xB2\x9B\xE2\xB2\x9D\xE2\xB2\x9F\xE2\xB2\xA1"
+	"\xE2\xB2\xA3\xE2\xB2\xA5\xE2\xB2\xA7\xE2\xB2\xA9\xE2\xB2\xAB\xE2\xB2\xAD\xE2\xB2\xAF\xE2\xB2\xB1\xE2"
+	"\xB2\xB3\xE2\xB2\xB5\xE2\xB2\xB7\xE2\xB2\xB9\xE2\xB2\xBB\xE2\xB2\xBD\xE2\xB2\xBF\xE2\xB3\x81\xE2\xB3"
+	"\x83\xE2\xB3\x85\xE2\xB3\x87\xE2\xB3\x89\xE2\xB3\x8B\xE2\xB3\x8D\xE2\xB3\x8F\xE2\xB3\x91\xE2\xB3\x93"
+	"\xE2\xB3\x95\xE2\xB3\x97\xE2\xB3\x99\xE2\xB3\x9B\xE2\xB3\x9D\xE2\xB3\x9F\xE2\xB3\xA1\xE2\xB3\xA3\xE2"
+	"\xB3\xAC\xE2\xB3\xAE\xE2\xB3\xB3\xEA\x99\x81\xEA\x99\x83\xEA\x99\x85\xEA\x99\x87\xEA\x99\x89\xEA\x99"
+	"\x8B\xEA\x99\x8D\xEA\x99\x8F\xEA\x99\x91\xEA\x99\x93\xEA\x99\x95\xEA\x99\x97\xEA\x99\x99\xEA\x99\x9B"
+	"\xEA\x99\x9D\xEA\x99\x9F\xEA\x99\xA1\xEA\x99\xA3\xEA\x99\xA5\xEA\x99\xA7\xEA\x99\xA9\xEA\x99\xAB\xEA"
+	"\x99\xAD\xEA\x9A\x81\xEA\x9A\x83\xEA\x9A\x85\xEA\x9A\x87\xEA\x9A\x89\xEA\x9A\x8B\xEA\x9A\x8D\xEA\x9A"
+	"\x8F\xEA\x9A\x91\xEA\x9A\x93\xEA\x9A\x95\xEA\x9A\x97\xEA\x9A\x99\xEA\x9A\x9B\xEA\x9C\xA3\xEA\x9C\xA5"
+	"\xEA\x9C\xA9\xEA\x9C\xAB\xEA\x9C\xAD\xEA\x9C\xAF\xEA\x9C\xB3\xEA\x9C\xB5\xEA\x9C\xB7\xEA\x9C\xB9\xEA"
+	"\x9C\xBB\xEA\x9C\xBD\xEA\x9C\xBF\xEA\x9D\x81\xEA\x9D\x83\xEA\x9D\x85\xEA\x9D\x87\xEA\x9D\x89\xEA\x9D"
+	"\x8B\xEA\x9D\x8D\xEA\x9D\x8F\xEA\x9D\x91\xEA\x9D\x93\xEA\x9D\x95\xEA\x9D\x97\xEA\x9D\x99\xEA\x9D\x9B"
+	"\xEA\x9D\x9D\xEA\x9D\x9F\xEA\x9D\xA1\xEA\x9D\xA3\xEA\x9D\xA5\xEA\x9D\xA7\xEA\x9D\xA9\xEA\x9D\xAB\xEA"
+	"\x9D\xAD\xEA\x9D\xBA\xEA\x9D\xBC\xE1\xB5\xB9\xEA\x9D\xBF\xEA\x9E\x81\xEA\x9E\x83\xEA\x9E\x85\xEA\x9E"
+	"\x87\xEA\x9E\x8C\xEA\x9E\x91\xEA\x9E\x93\xEA\x9E\x97\xEA\x9E\x99\xEA\x9E\x9B\xEA\x9E\x9D\xEA\x9E\x9F"
+	"\xEA\x9E\xA1\xEA\x9E\xA3\xEA\x9E\xA5\xEA\x9E\xA7\xEA\x9E\xA9\xC9\xAC\xCA\x9E\xCA\x87\xEF\xBD\x81\xEF"
+	"\xBD\x82\xEF\xBD\x83\xEF\xBD\x84\xEF\xBD\x85\xEF\xBD\x86\xEF\xBD\x87\xEF\xBD\x88\xEF\xBD\x89\xEF\xBD"
+	"\x8A\xEF\xBD\x8B\xEF\xBD\x8C\xEF\xBD\x8D\xEF\xBD\x8E\xEF\xBD\x8F\xEF\xBD\x90\xEF\xBD\x91\xEF\xBD\x92"
+	"\xEF\xBD\x93\xEF\xBD\x94\xEF\xBD\x95\xEF\xBD\x96\xEF\xBD\x97\xEF\xBD\x98\xEF\xBD\x99\xEF\xBD\x9A\xF0"
+	"\x90\x90\xA8\xF0\x90\x90\xA9\xF0\x90\x90\xAA\xF0\x90\x90\xAB\xF0\x90\x90\xAC\xF0\x90\x90\xAD\xF0\x90"
+	"\x90\xAE\xF0\x90\x90\xAF\xF0\x90\x90\xB0\xF0\x90\x90\xB1\xF0\x90\x90\xB2\xF0\x90\x90\xB3\xF0\x90\x90"
+	"\xB4\xF0\x90\x90\xB5\xF0\x90\x90\xB6\xF0\x90\x90\xB7\xF0\x90\x90\xB8\xF0\x90\x90\xB9\xF0\x90\x90\xBA"
+	"\xF0\x90\x90\xBB\xF0\x90\x90\xBC\xF0\x90\x90\xBD\xF0\x90\x90\xBE\xF0\x90\x90\xBF\xF0\x90\x91\x80\xF0"
+	"\x90\x91\x81\xF0\x90\x91\x82\xF0\x90\x91\x83\xF0\x90\x91\x84\xF0\x90\x91\x85\xF0\x90\x91\x86\xF0\x90"
+	"\x91\x87\xF0\x90\x91\x88\xF0\x90\x91\x89\xF0\x90\x91\x8A\xF0\x90\x91\x8B\xF0\x90\x91\x8C\xF0\x90\x91"
+	"\x8D\xF0\x90\x91\x8E\xF0\x90\x91\x8F\xF0\x91\xA3\x80\xF0\x91\xA3\x81\xF0\x91\xA3\x82\xF0\x91\xA3\x83"
+	"\xF0\x91\xA3\x84\xF0\x91\xA3\x85\xF0\x91\xA3\x86\xF0\x91\xA3\x87\xF0\x91\xA3\x88\xF0\x91\xA3\x89\xF0"
+	"\x91\xA3\x8A\xF0\x91\xA3\x8B\xF0\x91\xA3\x8C\xF0\x91\xA3\x8D\xF0\x91\xA3\x8E\xF0\x91\xA3\x8F\xF0\x91"
+	"\xA3\x90\xF0\x91\xA3\x91\xF0\x91\xA3\x92\xF0\x91\xA3\x93\xF0\x91\xA3\x94\xF0\x91\xA3\x95\xF0\x91\xA3"
+	"\x96\xF0\x91\xA3\x97\xF0\x91\xA3\x98\xF0\x91\xA3\x99\xF0\x91\xA3\x9A\xF0\x91\xA3\x9B\xF0\x91\xA3\x9C"
+	"\xF0\x91\xA3\x9D\xF0\x91\xA3\x9E\xF0\x91\xA3\x9F\x53\x73\xC7\x85\xC7\x88\xC7\x8B\xC7\xB2\xD4\xB5\xD6"
+	"\x82\xE1\xBE\x88\xE1\xBE\x89\xE1\xBE\x8A\xE1\xBE\x8B\xE1\xBE\x8C\xE1\xBE\x8D\xE1\xBE\x8E\xE1\xBE\x8F"
+	"\xE1\xBE\x98\xE1\xBE\x99\xE1\xBE\x9A\xE1\xBE\x9B\xE1\xBE\x9C\xE1\xBE\x9D\xE1\xBE\x9E\xE1\xBE\x9F\xE1"
+	"\xBE\xA8\xE1\xBE\xA9\xE1\xBE\xAA\xE1\xBE\xAB\xE1\xBE\xAC\xE1\xBE\xAD\xE1\xBE\xAE\xE1\xBE\xAF\xE1\xBE"
+	"\xBA\xCD\x85\xE1\xBE\xBC\xCE\x86\xCD\x85\xCE\x91\xCD\x82\xCD\x85\xE1\xBF\x8A\xCD\x85\xE1\xBF\x8C\xCE"
+	"\x89\xCD\x85\xCE\x97\xCD\x82\xCD\x85\xE1\xBF\xBA\xCD\x85\xE1\xBF\xBC\xCE\x8F\xCD\x85\xCE\xA9\xCD\x82"
+	"\xCD\x85\x46\x66\x46\x69\x46\x6C\x46\x66\x69\x46\x66\x6C\x53\x74\xD5\x84\xD5\xB6\xD5\x84\xD5\xA5\xD5"
+	"\x84\xD5\xAB\xD5\x8E\xD5\xB6\xD5\x84\xD5\xAD\x73\x73\xE1\xBC\x80\xCE\xB9\xE1\xBC\x81\xCE\xB9\xE1\xBC"
+	"\x82\xCE\xB9\xE1\xBC\x83\xCE\xB9\xE1\xBC\x84\xCE\xB9\xE1\xBC\x85\xCE\xB9\xE1\xBC\x86\xCE\xB9\xE1\xBC"
+	"\x87\xCE\xB9\xE1\xBC\xA0\xCE\xB9\xE1\xBC\xA1\xCE\xB9\xE1\xBC\xA2\xCE\xB9\xE1\xBC\xA3\xCE\xB9\xE1\xBC"
+	"\xA4\xCE\xB9\xE1\xBC\xA5\xCE\xB9\xE1\xBC\xA6\xCE\xB9\xE1\xBC\xA7\xCE\xB9\xE1\xBD\xA0\xCE\xB9\xE1\xBD"
+	"\xA1\xCE\xB9\xE1\xBD\xA2\xCE\xB9\xE1\xBD\xA3\xCE\xB9\xE1\xBD\xA4\xCE\xB9\xE1\xBD\xA5\xCE\xB9\xE1\xBD"
+	"\xA6\xCE\xB9\xE1\xBD\xA7\xCE\xB9\xE1\xBD\xB0\xCE\xB9\xCE\xB1\xCE\xB9\xCE\xAC\xCE\xB9\xCE\xB1\xCD\x82"
+	"\xCE\xB9\xE1\xBD\xB4\xCE\xB9\xCE\xB7\xCE\xB9\xCE\xAE\xCE\xB9\xCE\xB7\xCD\x82\xCE\xB9\xE1\xBD\xBC\xCE"
+	"\xB9\xCF\x89\xCE\xB9\xCF\x8E\xCE\xB9\xCF\x89\xCD\x82\xCE\xB9"
+;
+const size_t CompressedStringDataLength = 19415;
+ third_party/utf8rewind/source/unicodedatabase.h view
@@ -0,0 +1,119 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef _UTF8REWIND_UNICODEDATABASE_H_
+#define _UTF8REWIND_UNICODEDATABASE_H_
+
+/*!
+	\file
+	\brief Unicode property database.
+
+	\cond INTERNAL
+*/
+
+#include "utf8rewind.h"
+
+typedef struct {
+	unicode_t codepoint;
+	uint32_t length_and_offset;
+} DecompositionRecord;
+
+typedef struct {
+	uint64_t key;
+	unicode_t value;
+} CompositionRecord;
+
+extern const size_t* GeneralCategoryIndexPtr;
+extern const uint32_t* GeneralCategoryDataPtr;
+
+extern const size_t* CanonicalCombiningClassIndexPtr;
+extern const uint8_t* CanonicalCombiningClassDataPtr;
+
+extern const size_t* QuickCheckCaseMappedIndexPtr;
+extern const uint8_t* QuickCheckCaseMappedDataPtr;
+
+extern const size_t* QuickCheckNFCIndexPtr;
+extern const uint8_t* QuickCheckNFCDataPtr;
+
+extern const size_t* QuickCheckNFDIndexPtr;
+extern const uint8_t* QuickCheckNFDDataPtr;
+
+extern const size_t* QuickCheckNFKCIndexPtr;
+extern const uint8_t* QuickCheckNFKCDataPtr;
+
+extern const size_t* QuickCheckNFKDIndexPtr;
+extern const uint8_t* QuickCheckNFKDDataPtr;
+
+extern const size_t UnicodeNFDRecordCount;
+extern const DecompositionRecord* UnicodeNFDRecordPtr;
+
+extern const size_t UnicodeNFKDRecordCount;
+extern const DecompositionRecord* UnicodeNFKDRecordPtr;
+
+extern const size_t UnicodeUppercaseRecordCount;
+extern const DecompositionRecord* UnicodeUppercaseRecordPtr;
+
+extern const size_t UnicodeLowercaseRecordCount;
+extern const DecompositionRecord* UnicodeLowercaseRecordPtr;
+
+extern const size_t UnicodeTitlecaseRecordCount;
+extern const DecompositionRecord* UnicodeTitlecaseRecordPtr;
+
+extern const size_t UnicodeCompositionRecordCount;
+extern const CompositionRecord* UnicodeCompositionRecordPtr;
+
+extern const uint32_t* NFDIndex1Ptr;
+extern const uint32_t* NFDIndex2Ptr;
+extern const uint32_t* NFDDataPtr;
+
+extern const uint32_t* NFKDIndex1Ptr;
+extern const uint32_t* NFKDIndex2Ptr;
+extern const uint32_t* NFKDDataPtr;
+
+extern const uint32_t* UppercaseIndex1Ptr;
+extern const uint32_t* UppercaseIndex2Ptr;
+extern const uint32_t* UppercaseDataPtr;
+
+extern const uint32_t* LowercaseIndex1Ptr;
+extern const uint32_t* LowercaseIndex2Ptr;
+extern const uint32_t* LowercaseDataPtr;
+
+extern const uint32_t* TitlecaseIndex1Ptr;
+extern const uint32_t* TitlecaseIndex2Ptr;
+extern const uint32_t* TitlecaseDataPtr;
+
+extern const uint32_t* CaseFoldingIndex1Ptr;
+extern const uint32_t* CaseFoldingIndex2Ptr;
+extern const uint32_t* CaseFoldingDataPtr;
+
+extern const char* CompressedStringData;
+extern const size_t CompressedStringDataLength;
+
+extern const char* DecompositionData;
+extern const size_t DecompositionDataLength;
+
+/*! \endcond */
+
+#endif /* _UTF8REWIND_UNICODEDATABASE_H_ */
+ third_party/utf8rewind/source/utf8rewind.c view
@@ -0,0 +1,1379 @@+/*
+	Copyright (C) 2014-2016 Quinten Lansu
+
+	Permission is hereby granted, free of charge, to any person
+	obtaining a copy of this software and associated documentation
+	files (the "Software"), to deal in the Software without
+	restriction, including without limitation the rights to use,
+	copy, modify, merge, publish, distribute, sublicense, and/or
+	sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following
+	conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+	OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "utf8rewind.h"
+
+#include "internal/base.h"
+#include "internal/casemapping.h"
+#include "internal/codepoint.h"
+#include "internal/composition.h"
+#include "internal/decomposition.h"
+#include "internal/database.h"
+#include "internal/seeking.h"
+#include "internal/streaming.h"
+
+size_t utf8len(const char* text)
+{
+	const uint8_t* src;
+	size_t src_length;
+	size_t length;
+
+	/* Validate input */
+
+	if (text == 0 ||
+		text[0] == 0)
+	{
+		return 0;
+	}
+
+	length = 0;
+
+	/* Determine length in codepoints */
+
+	src = (const uint8_t*)text;
+	src_length = strlen(text);
+
+	while (src_length > 0)
+	{
+		uint8_t src_offset = 1;
+
+		/* Check if the current byte is part of a multi-byte sequence */
+
+		uint8_t codepoint_length = codepoint_decoded_length[*src];
+		if (codepoint_length > 1)
+		{
+			/* Check every byte of the sequence */
+
+			do
+			{
+				if (src[src_offset] < 0x80 ||  /* Not a continuation byte */
+					src[src_offset] > 0xBF)    /* Start of a new sequence */
+				{
+					break;
+				}
+			}
+			while (++src_offset < codepoint_length);
+		}
+
+		/* Found a codepoint */
+
+		length++;
+
+		/* Move cursor */
+
+		if (src_offset >= src_length)
+		{
+			break;
+		}
+
+		src += src_offset;
+		src_length -= src_offset;
+	}
+
+	return length;
+}
+
+size_t utf16toutf8(const utf16_t* input, size_t inputSize, char* target, size_t targetSize, int32_t* errors)
+{
+	const utf16_t* src;
+	size_t src_size;
+	char* dst;
+	size_t dst_size;
+	size_t bytes_written = 0;
+
+	/* Validate parameters */
+
+	UTF8_VALIDATE_PARAMETERS_CHAR(utf16_t, bytes_written);
+	UTF8_SET_ERROR(NONE);
+
+	/* Setup cursors */
+
+	src = input;
+	src_size = inputSize;
+	dst = target;
+	dst_size = targetSize;
+
+	/* Loop over input */
+
+	while (src_size > 0)
+	{
+		unicode_t codepoint;
+		uint8_t encoded_size;
+
+		if (src_size < sizeof(utf16_t))
+		{
+			/* Not enough data */
+
+			goto invaliddata;
+		}
+
+		codepoint = (unicode_t)*src;
+
+		if (codepoint >= SURROGATE_HIGH_START &&
+			codepoint <= SURROGATE_LOW_END)
+		{
+			/* Decode surrogate pair */
+
+			if (codepoint > SURROGATE_HIGH_END)
+			{
+				/* Missing high surrogate codepoint */
+
+				codepoint = REPLACEMENT_CHARACTER;
+
+				UTF8_SET_ERROR(INVALID_DATA);
+			}
+			else if (
+				src_size < 2 * sizeof(utf16_t))
+			{
+				/* Not enough data */
+
+				goto invaliddata;
+			}
+			else
+			{
+				/* Read low surrogate codepoint */
+
+				if (src[1] < SURROGATE_LOW_START ||
+					src[1] > SURROGATE_LOW_END)
+				{
+					/* Missing low surrogate codepoint */
+
+					codepoint = REPLACEMENT_CHARACTER;
+
+					UTF8_SET_ERROR(INVALID_DATA);
+				}
+				else
+				{
+					/* Decode codepoint from surrogate pair */
+
+					codepoint =
+						(MAX_BASIC_MULTILINGUAL_PLANE + 1) +
+						(src[1] - SURROGATE_LOW_START) +
+						((src[0] - SURROGATE_HIGH_START) << 10);
+
+					src++;
+					src_size -= sizeof(utf16_t);
+				}
+			}
+		}
+
+		encoded_size = codepoint_write(codepoint, &dst, &dst_size);
+		if (encoded_size == 0)
+		{
+			UTF8_SET_ERROR(NOT_ENOUGH_SPACE);
+
+			return bytes_written;
+		}
+
+		bytes_written += encoded_size;
+
+		src++;
+		src_size -= sizeof(utf16_t);
+	}
+
+	return bytes_written;
+
+invaliddata:
+	if (dst != 0)
+	{
+		if (dst_size < REPLACEMENT_CHARACTER_STRING_LENGTH)
+		{
+			UTF8_SET_ERROR(NOT_ENOUGH_SPACE);
+
+			return bytes_written;
+		}
+
+		/* Write replacement codepoint to output */
+
+		memcpy(dst, REPLACEMENT_CHARACTER_STRING, REPLACEMENT_CHARACTER_STRING_LENGTH);
+	}
+
+	UTF8_SET_ERROR(INVALID_DATA);
+
+	return bytes_written + REPLACEMENT_CHARACTER_STRING_LENGTH;
+}
+
+size_t utf32toutf8(const unicode_t* input, size_t inputSize, char* target, size_t targetSize, int32_t* errors)
+{
+	const unicode_t* src;
+	size_t src_size;
+	char* dst;
+	size_t dst_size;
+	size_t bytes_written = 0;
+
+	/* Validate parameters */
+
+	UTF8_VALIDATE_PARAMETERS_CHAR(unicode_t, bytes_written);
+	UTF8_SET_ERROR(NONE);
+
+	/* Setup cursors */
+
+	src = input;
+	src_size = inputSize;
+	dst = target;
+	dst_size = targetSize;
+
+	/* Loop over input */
+
+	while (src_size > 0)
+	{
+		unicode_t codepoint;
+		uint8_t encoded_size;
+
+		if (src_size < sizeof(unicode_t))
+		{
+			/* Not enough data */
+
+			goto invaliddata;
+		}
+
+		codepoint = *src;
+
+		if (codepoint >= SURROGATE_HIGH_START &&
+			codepoint <= SURROGATE_LOW_END)
+		{
+			/* Decode surrogate pair */
+
+			if (codepoint > SURROGATE_HIGH_END) 
+			{
+				/* Missing high surrogate codepoint */
+
+				codepoint = REPLACEMENT_CHARACTER;
+
+				UTF8_SET_ERROR(INVALID_DATA);
+			}
+			else if (
+				src_size < 2 * sizeof(unicode_t))
+			{
+				/* Not enough data */
+
+				goto invaliddata;
+			}
+			else
+			{
+				/* Read low surrogate codepoint */
+
+				if (src[1] < SURROGATE_LOW_START ||
+					src[1] > SURROGATE_LOW_END)
+				{
+					/* Missing low surrogate codepoint */
+
+					codepoint = REPLACEMENT_CHARACTER;
+
+					UTF8_SET_ERROR(INVALID_DATA);
+				}
+				else
+				{
+					/* Decode codepoint from surrogate pair */
+
+					codepoint =
+						(MAX_BASIC_MULTILINGUAL_PLANE + 1) +
+						(src[1] - SURROGATE_LOW_START) +
+						((src[0] - SURROGATE_HIGH_START) << 10);
+
+					src++;
+					src_size -= sizeof(unicode_t);
+				}
+			}
+		}
+
+		encoded_size = codepoint_write(codepoint, &dst, &dst_size);
+		if (encoded_size == 0)
+		{
+			UTF8_SET_ERROR(NOT_ENOUGH_SPACE);
+
+			return bytes_written;
+		}
+
+		bytes_written += encoded_size;
+
+		src++;
+		src_size -= sizeof(unicode_t);
+	}
+
+	return bytes_written;
+
+invaliddata:
+	if (dst != 0)
+	{
+		if (dst_size < REPLACEMENT_CHARACTER_STRING_LENGTH)
+		{
+			UTF8_SET_ERROR(NOT_ENOUGH_SPACE);
+
+			return bytes_written;
+		}
+
+		/* Write replacement codepoint to output */
+
+		memcpy(dst, REPLACEMENT_CHARACTER_STRING, REPLACEMENT_CHARACTER_STRING_LENGTH);
+	}
+
+	UTF8_SET_ERROR(INVALID_DATA);
+
+	return bytes_written + REPLACEMENT_CHARACTER_STRING_LENGTH;
+}
+
+size_t widetoutf8(const wchar_t* input, size_t inputSize, char* target, size_t targetSize, int32_t* errors)
+{
+#if UTF8_WCHAR_UTF16
+	return utf16toutf8((const utf16_t*)input, inputSize, target, targetSize, errors);
+#elif UTF8_WCHAR_UTF32
+	return utf32toutf8((const unicode_t*)input, inputSize, target, targetSize, errors);
+#else
+	return SIZE_MAX;
+#endif
+}
+
+size_t utf8toutf16(const char* input, size_t inputSize, utf16_t* target, size_t targetSize, int32_t* errors)
+{
+	const char* src;
+	size_t src_size;
+	utf16_t* dst;
+	size_t dst_size;
+	size_t bytes_written = 0;
+
+	/* Validate parameters */
+
+	UTF8_VALIDATE_PARAMETERS(char, utf16_t, bytes_written);
+
+	/* Setup cursors */
+
+	src = input;
+	src_size = inputSize;
+	dst = target;
+	dst_size = targetSize;
+
+	/* Loop over input */
+
+	while (src_size > 0)
+	{
+		unicode_t decoded;
+		uint8_t decoded_size = codepoint_read(src, src_size, &decoded);
+
+		if (decoded <= MAX_BASIC_MULTILINGUAL_PLANE)
+		{
+			/* Codepoint fits in a single UTF-16 codepoint */
+
+			if (dst != 0)
+			{
+				/* Write to output */
+
+				if (dst_size < sizeof(utf16_t))
+				{
+					UTF8_SET_ERROR(NOT_ENOUGH_SPACE);
+
+					return bytes_written;
+				}
+
+				*dst++ = (utf16_t)decoded;
+				dst_size -= sizeof(utf16_t);
+			}
+
+			bytes_written += sizeof(utf16_t);
+		}
+		else
+		{
+			/* Codepoint must be encoded using a surrogate pair */
+
+			if (dst != 0)
+			{
+				/* Write to output */
+
+				if (dst_size < 2 * sizeof(utf16_t))
+				{
+					UTF8_SET_ERROR(NOT_ENOUGH_SPACE);
+
+					return bytes_written;
+				}
+
+				/* Encoded value is always beyond BMP */
+
+				decoded -= (MAX_BASIC_MULTILINGUAL_PLANE + 1);
+				*dst++ = SURROGATE_HIGH_START + (decoded >> 10);
+				*dst++ = SURROGATE_LOW_START + (decoded & 0x03FF);
+
+				dst_size -= 2 * sizeof(utf16_t);
+			}
+
+			bytes_written += 2 * sizeof(utf16_t);
+		}
+
+		src += decoded_size;
+		src_size -= decoded_size;
+	}
+
+	UTF8_SET_ERROR(NONE);
+
+	return bytes_written;
+}
+
+size_t utf8toutf32(const char* input, size_t inputSize, unicode_t* target, size_t targetSize, int32_t* errors)
+{
+	const char* src;
+	size_t src_size;
+	unicode_t* dst;
+	size_t dst_size;
+	size_t bytes_written = 0;
+
+	/* Validate parameters */
+
+	UTF8_VALIDATE_PARAMETERS(char, unicode_t, bytes_written);
+
+	/* Setup cursors */
+
+	src = input;
+	src_size = inputSize;
+	dst = target;
+	dst_size = targetSize;
+
+	/* Loop over input */
+
+	while (src_size > 0)
+	{
+		unicode_t decoded;
+		uint8_t decoded_length = codepoint_read(src, src_size, &decoded);
+
+		if (dst != 0)
+		{
+			/* Write to output */
+
+			if (dst_size < sizeof(unicode_t))
+			{
+				UTF8_SET_ERROR(NOT_ENOUGH_SPACE);
+
+				return bytes_written;
+			}
+
+			*dst++ = decoded;
+			dst_size -= sizeof(unicode_t);
+		}
+
+		bytes_written += sizeof(unicode_t);
+
+		src += decoded_length;
+		src_size -= decoded_length;
+	}
+
+	UTF8_SET_ERROR(NONE);
+
+	return bytes_written;
+}
+
+size_t utf8towide(const char* input, size_t inputSize, wchar_t* target, size_t targetSize, int32_t* errors)
+{
+#if UTF8_WCHAR_UTF16
+	return utf8toutf16(input, inputSize, (utf16_t*)target, targetSize, errors);
+#elif UTF8_WCHAR_UTF32
+	return utf8toutf32(input, inputSize, (unicode_t*)target, targetSize, errors);
+#else
+	return SIZE_MAX;
+#endif
+}
+
+const char* utf8seek(const char* text, size_t textSize, const char* textStart, off_t offset, int direction)
+{
+	const char* text_end;
+
+	if (text == 0 ||
+		textStart == 0)
+	{
+		return text;
+	}
+
+	text_end = textStart + textSize;
+
+	switch (direction)
+	{
+
+	case SEEK_CUR:
+		{
+			if (offset == 0)
+			{
+				return text;
+			}
+			else if (offset > 0)
+			{
+				return seeking_forward(text, text_end, textSize, offset);
+			}
+			else
+			{
+				return seeking_rewind(textStart, text, textSize, offset);
+			}
+
+		} break;
+
+	case SEEK_SET:
+		{
+			if (text < textStart)
+			{
+				return text;
+			}
+
+			return seeking_forward(textStart, text_end, textSize, offset);
+
+		} break;
+
+	case SEEK_END:
+		return seeking_rewind(textStart, text_end, textSize, -offset);
+
+	default:
+		return text;
+
+	}
+}
+
+UTF8_API size_t utf8envlocale()
+{
+	/*
+		Sources for locales and code pages
+
+		Windows
+		https://msdn.microsoft.com/en-US/goglobal/bb896001.aspx
+
+		POSIX
+		https://www-01.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.nlsgdrf/support_languages_locales.htm
+	*/
+
+// #if WIN32 || _WINDOWS
+// 	#define UTF8_LOCALE_CHECK(_name, _ansiCodepage, _oemCodepage) \
+// 		(codepage == _ansiCodepage || codepage == _oemCodepage)
+
+// 	unsigned int codepage;
+// 	_locale_t locale = _get_current_locale();
+
+// 	if (locale == 0)
+// 	{
+// 		return UTF8_LOCALE_DEFAULT;
+// 	}
+
+// 	// Microsoft changed the name of the codepage member in VS2015.
+
+// 	#if _MSC_VER >= 1900
+// 		codepage = ((__crt_locale_data_public*)(locale)->locinfo)->_locale_lc_codepage;
+// 	#else
+// 		codepage = locale->locinfo->lc_codepage;
+// 	#endif
+// #else
+	#define UTF8_LOCALE_CHECK(_name, _ansiCodepage, _oemCodepage) \
+		!strncasecmp(locale, _name, 5)
+
+	const char* locale = setlocale(LC_ALL, 0);
+	if (locale == 0)
+	{
+		return UTF8_LOCALE_DEFAULT;
+	}
+//#endif
+
+	if (UTF8_LOCALE_CHECK("lt_lt", 1257, 775))
+	{
+		return UTF8_LOCALE_LITHUANIAN;
+	}
+	else if (
+		UTF8_LOCALE_CHECK("tr_tr", 1254, 857) ||
+		UTF8_LOCALE_CHECK("az_az", 1254, 857))
+	{
+		return UTF8_LOCALE_TURKISH_AND_AZERI_LATIN;
+	}
+
+	return UTF8_LOCALE_DEFAULT;
+}
+
+size_t utf8toupper(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors)
+{
+	CaseMappingState state;
+
+	/* Validate parameters */
+
+	UTF8_VALIDATE_PARAMETERS_CHAR(char, 0);
+
+	/* Initialize case mapping */
+
+	if (!casemapping_initialize(
+		&state,
+		input, inputSize,
+		target, targetSize,
+		UppercaseIndex1Ptr, UppercaseIndex2Ptr, UppercaseDataPtr,
+		QuickCheckCaseMapped_Uppercase, locale,
+		errors))
+	{
+		return state.total_bytes_needed;
+	}
+
+	/* Execute case mapping as long as input remains */
+
+	while (state.src_size > 0)
+	{
+		size_t converted;
+
+		if ((converted = casemapping_execute(&state, errors)) == 0)
+		{
+			return state.total_bytes_needed;
+		}
+
+		state.total_bytes_needed += converted;
+	}
+
+	UTF8_SET_ERROR(NONE);
+
+	return state.total_bytes_needed;
+}
+
+size_t utf8tolower(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors)
+{
+	CaseMappingState state;
+
+	/* Validate parameters */
+
+	UTF8_VALIDATE_PARAMETERS_CHAR(char, 0);
+
+	/* Initialize case mapping */
+
+	if (!casemapping_initialize(
+		&state,
+		input, inputSize,
+		target, targetSize,
+		LowercaseIndex1Ptr, LowercaseIndex2Ptr, LowercaseDataPtr,
+		QuickCheckCaseMapped_Lowercase, locale,
+		errors))
+	{
+		return state.total_bytes_needed;
+	}
+
+	/* Execute case mapping as long as input remains */
+
+	while (state.src_size > 0)
+	{
+		size_t converted;
+
+		if ((converted = casemapping_execute(&state, errors)) == 0)
+		{
+			return state.total_bytes_needed;
+		}
+
+		state.total_bytes_needed += converted;
+	}
+
+	UTF8_SET_ERROR(NONE);
+
+	return state.total_bytes_needed;
+}
+
+size_t utf8totitle(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors)
+{
+	CaseMappingState state;
+
+	/* Validate parameters */
+
+	UTF8_VALIDATE_PARAMETERS_CHAR(char, 0);
+
+	/* Initialize case mapping */
+
+	if (!casemapping_initialize(
+		&state,
+		input, inputSize,
+		target, targetSize,
+		TitlecaseIndex1Ptr, TitlecaseIndex2Ptr, TitlecaseDataPtr,
+		QuickCheckCaseMapped_Titlecase, locale,
+		errors))
+	{
+		return state.total_bytes_needed;
+	}
+
+	/* Execute case mapping as long as input remains */
+
+	while (state.src_size > 0)
+	{
+		size_t converted;
+		
+		if ((converted = casemapping_execute(&state, errors)) == 0)
+		{
+			return state.total_bytes_needed;
+		}
+
+		/*
+			The first letter of every word should be titlecase, the rest should
+			be converted to lowercase.
+		*/
+
+		if (state.last_canonical_combining_class == CCC_NOT_REORDERED)
+		{
+			if (state.property_data == TitlecaseDataPtr)
+			{
+				if ((state.last_general_category & UTF8_CATEGORY_LETTER) != 0)
+				{
+					state.property_index1 = LowercaseIndex1Ptr;
+					state.property_index2 = LowercaseIndex2Ptr;
+					state.property_data = LowercaseDataPtr;
+
+					state.quickcheck_flags = QuickCheckCaseMapped_Lowercase;
+				}
+			}
+			else if (
+				(state.last_general_category & UTF8_CATEGORY_LETTER) == 0)
+			{
+				state.property_index1 = TitlecaseIndex1Ptr;
+				state.property_index2 = TitlecaseIndex2Ptr;
+				state.property_data = TitlecaseDataPtr;
+
+				state.quickcheck_flags = QuickCheckCaseMapped_Titlecase;
+			}
+		}
+
+		state.total_bytes_needed += converted;
+	}
+
+	UTF8_SET_ERROR(NONE);
+
+	return state.total_bytes_needed;
+}
+
+size_t utf8casefold(const char* input, size_t inputSize, char* target, size_t targetSize, size_t locale, int32_t* errors)
+{
+	CaseMappingState state;
+
+	/* Validate parameters */
+
+	UTF8_VALIDATE_PARAMETERS_CHAR(char, 0);
+
+	/* Initialize case mapping */
+
+	if (!casemapping_initialize(
+		&state,
+		input, inputSize,
+		target, targetSize,
+		CaseFoldingIndex1Ptr, CaseFoldingIndex2Ptr, CaseFoldingDataPtr,
+		QuickCheckCaseMapped_Casefolded, locale,
+		errors))
+	{
+		return state.total_bytes_needed;
+	}
+
+	if (state.locale == UTF8_LOCALE_TURKISH_AND_AZERI_LATIN)
+	{
+		/* Exceptional behavior for Turkish and Azerbaijani (Latin) locales */
+
+		while (state.src_size > 0)
+		{
+			const char* resolved = 0;
+			uint8_t bytes_needed = 0;
+
+			/* Read next code point */
+
+			if (!(state.last_code_point_size = codepoint_read(state.src, state.src_size, &state.last_code_point)))
+			{
+				goto invaliddata;
+			}
+
+			/* Move source cursor */
+
+			if (state.src_size >= state.last_code_point_size)
+			{
+				state.src += state.last_code_point_size;
+				state.src_size -= state.last_code_point_size;
+			}
+			else
+			{
+				state.src_size = 0;
+			}
+
+			/* Resolve case folding */
+
+			if ((PROPERTY_GET_CM(state.last_code_point) & QuickCheckCaseMapped_Casefolded) != 0)
+			{
+				if (state.last_code_point == CP_LATIN_CAPITAL_LETTER_I)
+				{
+					resolved = "\xC4\xB1";
+					bytes_needed = 2;
+				}
+				else if (
+					state.last_code_point == CP_LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE)
+				{
+					resolved = "i";
+					bytes_needed = 1;
+				}
+				else
+				{
+					resolved = database_querydecomposition(state.last_code_point, state.property_index1, state.property_index2, state.property_data, &bytes_needed);
+				}
+			}
+
+			/* Write to output */
+
+			if (resolved != 0)
+			{
+				/* Write resolved string to output */
+
+				if (state.dst != 0)
+				{
+					if (state.dst_size < bytes_needed)
+					{
+						goto outofspace;
+					}
+
+					memcpy(state.dst, resolved, bytes_needed);
+
+					state.dst += bytes_needed;
+					state.dst_size -= bytes_needed;
+				}
+			}
+			else
+			{
+				/* Write code point unchanged to output */
+
+				if (!(bytes_needed = codepoint_write(state.last_code_point, &state.dst, &state.dst_size)))
+				{
+					goto outofspace;
+				}
+			}
+
+			state.total_bytes_needed += bytes_needed;
+		}
+	}
+	else
+	{
+		/* Execute case mapping as long as input remains */
+
+		while (state.src_size > 0)
+		{
+			const char* resolved = 0;
+			uint8_t bytes_needed = 0;
+
+			/* Read next code point */
+
+			if (!(state.last_code_point_size = codepoint_read(state.src, state.src_size, &state.last_code_point)))
+			{
+				goto invaliddata;
+			}
+
+			/* Move source cursor */
+
+			if (state.src_size >= state.last_code_point_size)
+			{
+				state.src += state.last_code_point_size;
+				state.src_size -= state.last_code_point_size;
+			}
+			else
+			{
+				state.src_size = 0;
+			}
+
+			/* Resolve case folding */
+
+			if ((PROPERTY_GET_CM(state.last_code_point) & QuickCheckCaseMapped_Casefolded) != 0)
+			{
+				resolved = database_querydecomposition(state.last_code_point, state.property_index1, state.property_index2, state.property_data, &bytes_needed);
+			}
+
+			if (resolved != 0)
+			{
+				/* Write resolved string to output */
+
+				if (state.dst != 0)
+				{
+					if (state.dst_size < bytes_needed)
+					{
+						goto outofspace;
+					}
+
+					memcpy(state.dst, resolved, bytes_needed);
+
+					state.dst += bytes_needed;
+					state.dst_size -= bytes_needed;
+				}
+			}
+			else
+			{
+				/* Write code point unchanged to output */
+
+				if (!(bytes_needed = codepoint_write(state.last_code_point, &state.dst, &state.dst_size)))
+				{
+					goto outofspace;
+				}
+			}
+
+			state.total_bytes_needed += bytes_needed;
+		}
+	}
+
+	UTF8_SET_ERROR(NONE);
+
+	return state.total_bytes_needed;
+
+invaliddata:
+	UTF8_SET_ERROR(INVALID_DATA);
+
+	return state.total_bytes_needed;
+
+outofspace:
+	UTF8_SET_ERROR(NOT_ENOUGH_SPACE);
+
+	return state.total_bytes_needed;
+}
+
+uint8_t utf8isnormalized(const char* input, size_t inputSize, size_t flags, size_t* offset)
+{
+	const char* src = input;
+	size_t src_size = inputSize;
+	uint8_t last_canonical_class = CCC_NOT_REORDERED;
+	size_t found_offset = 0;
+	uint8_t result = UTF8_NORMALIZATION_RESULT_YES;
+	unicode_t decoded;
+	uint8_t canonical_class;
+	uint8_t quick_check;
+	const size_t* property_index;
+	const uint8_t* property_data;
+
+	/* Validate input and flags */
+
+	if (input == NULL ||
+		inputSize == 0 ||
+		(flags & (UTF8_NORMALIZE_DECOMPOSE | UTF8_NORMALIZE_COMPOSE)) == 0)
+	{
+		goto end;
+	}
+
+	/* Get properties */
+
+	if ((flags & UTF8_NORMALIZE_COMPOSE) != 0)
+	{
+		if ((flags & UTF8_NORMALIZE_COMPATIBILITY) != 0)
+		{
+			property_index = QuickCheckNFKCIndexPtr;
+			property_data = QuickCheckNFKCDataPtr;
+		}
+		else
+		{
+			property_index = QuickCheckNFCIndexPtr;
+			property_data = QuickCheckNFCDataPtr;
+		}
+	}
+	else
+	{
+		if ((flags & UTF8_NORMALIZE_COMPATIBILITY) != 0)
+		{
+			property_index = QuickCheckNFKDIndexPtr;
+			property_data = QuickCheckNFKDDataPtr;
+		}
+		else
+		{
+			property_index = QuickCheckNFDIndexPtr;
+			property_data = QuickCheckNFDDataPtr;
+		}
+	}
+
+	/* Process input */
+
+	while (src_size > 0)
+	{
+		/* Read codepoint at cursor */
+
+		uint8_t read = codepoint_read(src, src_size, &decoded);
+		if (read == 0)
+		{
+			break;
+		}
+
+		/* Get canonical combining class and quick check value */
+
+		canonical_class = PROPERTY_GET_CCC(decoded);
+		quick_check = PROPERTY_GET(property_index, property_data, decoded);
+
+		/* Compare CCC to previous CCC */
+
+		if (last_canonical_class > canonical_class &&
+			canonical_class > CCC_NOT_REORDERED)
+		{
+			result = UTF8_NORMALIZATION_RESULT_NO;
+
+			break;
+		}
+
+		/* Compare quick check value */
+
+		if (quick_check == QuickCheckResult_No)
+		{
+			result = UTF8_NORMALIZATION_RESULT_NO;
+
+			break;
+		}
+		else if (
+			quick_check == QuickCheckResult_Maybe)
+		{
+			result = UTF8_NORMALIZATION_RESULT_MAYBE;
+		}
+
+		/* Append to offset */
+
+		if (result != UTF8_NORMALIZATION_RESULT_MAYBE)
+		{
+			found_offset += read;
+		}
+
+		last_canonical_class = canonical_class;
+
+		src += read;
+		src_size -= read;
+	}
+
+end:
+	if (offset != 0)
+	{
+		*offset = found_offset;
+	}
+	return result;
+}
+
+size_t utf8normalize(const char* input, size_t inputSize, char* target, size_t targetSize, size_t flags, int32_t* errors)
+{
+	char* dst = target;
+	size_t dst_size = targetSize;
+	StreamState stream[4];
+	DecomposeState decompose_state;
+	ComposeState compose_state;
+	uint8_t compatibility = (flags & UTF8_NORMALIZE_COMPATIBILITY) != 0;
+	StreamState* stream_output;
+	uint8_t finished = 0;
+	size_t bytes_written = 0;
+
+	/*
+		Decomposition uses the following process:
+
+		input         -->  stream[0]  -->
+		(decompose)   -->  stream[1]  -->
+		(accumulate)  -->  stream[2]  -->
+		output
+
+		The accumulation step is necessary in order to prevent buffer overflow
+		attacks.
+
+		Composition adds another stream buffer:
+
+		input         --> stream[0]  -->
+		(decompose)   --> stream[1]  -->
+		(accumulate)  --> stream[2]  -->
+		(compose)     --> stream[3]  -->
+		output
+
+		Although four streaming buffers may seem excessive, they are necessary
+		for preventing allocations on the heap.
+	*/
+
+	/* Check for valid flags */
+
+	if ((flags & (UTF8_NORMALIZE_DECOMPOSE | UTF8_NORMALIZE_COMPOSE)) == 0)
+	{
+		UTF8_SET_ERROR(INVALID_FLAG);
+
+		return bytes_written;
+	}
+
+	/* Validate parameters */
+
+	UTF8_VALIDATE_PARAMETERS_CHAR(char, bytes_written);
+
+	/* Initialize decomposition */
+
+	memset(stream, 0, sizeof(stream));
+
+	if (!stream_initialize(&stream[0], input, inputSize) ||
+		!decompose_initialize(&decompose_state, &stream[0], &stream[1], compatibility))
+	{
+		UTF8_SET_ERROR(INVALID_DATA);
+
+		return bytes_written;
+	}
+
+	stream_output = &stream[2];
+
+	if ((flags & UTF8_NORMALIZE_COMPOSE) != 0)
+	{
+		/* Initialize composition */
+
+		if (!compose_initialize(&compose_state, &stream[2], &stream[3], compatibility))
+		{
+			UTF8_SET_ERROR(INVALID_DATA);
+
+			return bytes_written;
+		}
+
+		stream_output = &stream[3];
+	}
+
+	do
+	{
+		uint8_t write = 0;
+
+		/* Accumulate decomposed input in next stream */
+
+		if (stream[1].current > 0)
+		{
+			unicode_t* src_codepoint = stream[1].codepoint;
+			unicode_t* dst_codepoint = stream[2].codepoint + stream[2].filled;
+			uint8_t* src_qc = stream[1].quick_check;
+			uint8_t* dst_qc = stream[2].quick_check + stream[2].filled;
+			uint8_t* src_ccc = stream[1].canonical_combining_class;
+			uint8_t* dst_ccc = stream[2].canonical_combining_class + stream[2].filled;
+
+			if ((flags & UTF8_NORMALIZE_COMPOSE) != 0)
+			{
+				uint8_t i;
+
+				/* Update stream properties to use composition values */
+
+				for (i = 0; i < stream[1].current; ++i)
+				{
+					*dst_qc++ = PROPERTY_GET(compose_state.qc_index, compose_state.qc_data, *src_codepoint);
+					*dst_ccc++ = *src_ccc++;
+					*dst_codepoint++ = *src_codepoint++;
+				}
+			}
+			else
+			{
+				/* Copy directly */
+
+				memcpy(dst_codepoint, src_codepoint, stream[1].current * sizeof(unicode_t));
+				memcpy(dst_qc, src_qc, stream[1].current * sizeof(uint8_t));
+				memcpy(dst_ccc, src_ccc, stream[1].current * sizeof(uint8_t));
+			}
+
+			stream[2].current += stream[1].current;
+			stream[2].filled += stream[1].current;
+		}
+
+		/* Decompose input sequence into next stream */
+
+		finished = !decompose_execute(&decompose_state);
+		if (!finished)
+		{
+			/* Output current stream it it could overflow accumulation buffer */
+
+			write = (stream[1].current + stream[2].filled) >= STREAM_SAFE_MAX;
+		}
+
+		/* Reorder potentially unordered decomposed stream */
+
+		if (!stream[1].stable)
+		{
+			stream_reorder(&stream[1]);
+		}
+
+		/* Write stream to output when overflowing or when accumulation buffer is empty*/
+
+		if (write ||
+			finished)
+		{
+			uint8_t i;
+
+			/* Compose accumulation buffer */
+
+			if ((flags & UTF8_NORMALIZE_COMPOSE) != 0 &&
+				!compose_execute(&compose_state))
+			{
+				break;
+			}
+
+			/* Write to output buffer */
+
+			for (i = 0; i < stream_output->current; ++i)
+			{
+				uint8_t encoded_size = codepoint_write(stream_output->codepoint[i], &dst, &dst_size);
+				if (encoded_size == 0)
+				{
+					UTF8_SET_ERROR(NOT_ENOUGH_SPACE);
+
+					return bytes_written;
+				}
+
+				bytes_written += encoded_size;
+			}
+
+			/* Reset accumulation buffer */
+
+			stream[2].current = 0;
+			stream[2].filled = 0;
+		}
+	}
+	while (!finished);
+
+	UTF8_SET_ERROR(NONE);
+
+	return bytes_written;
+}
+
+size_t utf8iscategory(const char* input, size_t inputSize, size_t flags)
+{
+	const char* src = input;
+	size_t src_size = inputSize;
+
+	if (input == 0 ||
+		inputSize == 0)
+	{
+		return 0;
+	}
+
+	while (src_size > 0)
+	{
+		unicode_t code_point;
+		uint32_t general_category;
+		uint8_t canonical_combining_class;
+		uint8_t offset;
+
+		/* Compatibility fixes */
+
+		if ((flags & UTF8_CATEGORY_COMPATIBILITY) != 0 &&
+			*src < MAX_BASIC_LATIN)
+		{
+			if (flags == UTF8_CATEGORY_ISBLANK)
+			{
+				if (*src == 0x09)
+				{
+					/* CHARACTER TABULATION */
+
+					src++;
+					src_size--;
+
+					continue;
+				}
+				else if (
+					*src == 0x20)
+				{
+					/* SPACE */
+
+					src++;
+					src_size--;
+
+					continue;
+				}
+				else
+				{
+					break;
+				}
+			}
+			else if (
+				flags == UTF8_CATEGORY_ISSPACE)
+			{
+				if (*src < 0x09 ||
+					*src > 0x20)
+				{
+					break;
+				}
+				else if (
+					*src <= 0x0D)
+				{
+					/* CHARACTER TABULATION ... CARRIAGE RETURN (CR) */
+
+					src++;
+					src_size--;
+
+					continue;
+				}
+				else if (
+					*src == 0x20)
+				{
+					/* SPACE */
+
+					src++;
+					src_size--;
+
+					continue;
+				}
+				else
+				{
+					break;
+				}
+			}
+			else if (
+				flags == UTF8_CATEGORY_ISXDIGIT)
+			{
+				if (*src < 0x30 ||
+					*src > 0x66)
+				{
+					break;
+				}
+				else if (
+					*src <= 0x39)
+				{
+					/* DIGIT ZERO ... DIGIT NINE */
+
+					src++;
+					src_size--;
+
+					continue;
+				}
+				else if (
+					*src >= 0x41 &&
+					*src <= 0x46)
+				{
+					/* LATIN CAPITAL LETTER A ... LATIN CAPITAL LETTER F */
+
+					src++;
+					src_size--;
+
+					continue;
+				}
+				else if (
+					*src >= 0x61)
+				{
+					/* LATIN SMALL LETTER A ... LATIN SMALL LETTER F */
+
+					src++;
+					src_size--;
+
+					continue;
+				}
+				else
+				{
+					break;
+				}
+			}
+		}
+
+		/* Read next code point */
+
+		offset = codepoint_read(src, src_size, &code_point);
+
+		/* Match General Category against flags */
+
+		general_category = PROPERTY_GET_GC(code_point);
+		if ((general_category & flags) == 0 &&
+			/* Check for the start of the next grapheme cluster */
+			((flags & UTF8_CATEGORY_IGNORE_GRAPHEME_CLUSTER) != 0 || (canonical_combining_class = PROPERTY_GET_CCC(code_point)) == CCC_NOT_REORDERED))
+		{
+			break;
+		}
+
+		/* Move source cursor */
+
+		if (offset > src_size)
+		{
+			break;
+		}
+
+		src += offset;
+		src_size -= offset;
+	}
+
+	return src - input;
+}