packages feed

Z-Data (empty) → 0.1.0.0

raw patch · 89 files changed

+38909/−0 lines, 89 filesdep +HUnitdep +QuickCheckdep +Z-Data

Dependencies added: HUnit, QuickCheck, Z-Data, base, case-insensitive, deepseq, ghc-prim, hashable, hspec, integer-gmp, integer-simple, primitive, quickcheck-instances, scientific, tagged, template-haskell, unordered-containers, word8

Files

+ ChangeLog.md view
@@ -0,0 +1,18 @@+# Revision history for stdio++## 0.1.1.0  -- 2019-02-19++* Add LEON, a little endian first serialization/deserialization module.+* Use pkg-config to find libuv by default, which can be turned off via cabal flag no-pkg-config+* Export `Result` constructor in `Std.Data.Parser` module.++## 0.2.0.0  --2019-05-15++* Add UDP module.+* Add JSON module.+* Add `ToText` class to `TextBuilder` module.+* Improve numeric builders by using FFI code.+* Change `readParser` 's type in `Std.IO.Buffered` module to directly return parsing result.+* Add `FlatMap/FlatSet/FlatIntMap/FlatIntSet` module.+* Fix a bug of `Parser` 's  `Alternative` instance.+* Fix a bug of `PrimVector` 's `QuasiQuoter`.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2017-2019, Haskell Stdio Team++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,34 @@+<p align=center>+  <img src="https://github.com/haskell-Z/Z/raw/master/projectZ.svg">+</p>++## Z-Data++[![Linux Build Status](https://img.shields.io/travis/haskell-z/z-data/master.svg?label=Linux%20build)](https://travis-ci.org/haskell-z/z-data)++This package provides basic data structures and functions:++* Array, vector(array slice)+* Text based UTF-8, basic unicode manipulating+* FFI utilties+* Parsing and building monad+* JSON encoding and decoding++## dev guide+++ GHC(>=8.10.2) ++ cabal-install(>=3.4)++```bash+# get code+git clone --recursive git@github.com:haskell-Z/z-data.git +cd z-data+# build+cabal build+# test+cabal run Z-Data-Test+# install +cabal install+# generate document+cabal haddock+```
+ Z-Data.cabal view
@@ -0,0 +1,213 @@+name:                       Z-Data+version:                    0.1.0.0+synopsis:                   array, vector and text+description:                This package provides array, slice and text operations+license:                    BSD3+license-file:               LICENSE+author:                     Dong Han, Tao He+maintainer:                 winterland1989@gmail.com+copyright:                  (c) Dong Han, 2017-2020+                            (c) Tao He, 2017-2020+category:                   Data+build-type:                 Simple+cabal-version:              >=1.10+homepage:                   https://github.com/haskell-Z/z-data+bug-reports:                https://github.com/haskell-Z/z-data/issues++extra-source-files:         ChangeLog.md+                            README.md+                            LICENSE++                            include/bytes.h+                            include/dtoa.h+                            include/text.h+                            cbits/bytes.c+                            cbits/dtoa.c+                            cbits/text.c++                            -- 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-Z/z-data.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:        Z.Data.Array+                            Z.Data.Array.Cast+                            Z.Data.Array.Checked+                            Z.Data.Array.QQ+                            Z.Data.Array.UnalignedAccess+                            Z.Data.Array.UnliftedArray+                            Z.Data.CBytes+                            Z.Data.Vector+                            Z.Data.Vector.Base+                            Z.Data.Vector.Extra+                            Z.Data.Vector.Search+                            Z.Data.Vector.Sort+                            Z.Data.Vector.QQ+                            Z.Data.Vector.FlatIntMap+                            Z.Data.Vector.FlatIntSet+                            Z.Data.Vector.FlatMap+                            Z.Data.Vector.FlatSet++                            Z.Data.Text+                            Z.Data.Text.Base+                            Z.Data.Text.Extra+                            Z.Data.Text.Search+                            Z.Data.Text.UTF8Codec+                            Z.Data.Text.UTF8Rewind+                            Z.Data.Text.Builder++                            Z.Data.Builder+                            Z.Data.Builder.Base+                            Z.Data.Builder.Numeric+                            Z.Data.Builder.Numeric.DigitTable++                            Z.Data.Generics.Utils++                            Z.Data.Parser+                            Z.Data.Parser.Base+                            Z.Data.Parser.Numeric++                            Z.Data.PrimRef+                            Z.Data.PrimRef.PrimSTRef+                            Z.Data.PrimRef.PrimIORef++                            Z.Data.JSON+                            Z.Data.JSON.Base+                            Z.Data.JSON.Builder+                            Z.Data.JSON.Value++                            Z.Foreign++    build-depends:          base                    >= 4.12 && <5.0+                          , ghc-prim                >= 0.6.1 && < 0.6.2+                          , primitive               >= 0.7.1 && < 0.7.2+                          , scientific              == 0.3.*+                          , hashable                == 1.3.*+                          , case-insensitive        == 1.2.*+                          , deepseq                 >= 1.4 && < 1.5+                          , QuickCheck              >= 2.10+                          , template-haskell        == 2.16.*+                          , unordered-containers    == 0.2.*+                          , tagged                  == 0.8.*++    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+                            text.h+                            utf8rewind.h+                            simdasciicheck.h+                            simdutf8check.h+    install-includes:       bytes.h+                            dtoa.h+                            text.h+                            utf8rewind.h+                            simdasciicheck.h+                            simdutf8check.h+    c-sources:              cbits/bytes.c+                            cbits/dtoa.c+                            cbits/text.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++    default-language:       Haskell2010+    build-tools:            hsc2hs, hspec-discover+    cc-options:             -march=native+    ghc-options:            -Wall +                            -Wno-unticked-promoted-constructors+                            -Wno-incomplete-patterns+                            -- ploymorphic pattern synonym messed exhaustiveness checker++test-suite Z-Data-Test+    type:                   exitcode-stdio-1.0+    hs-source-dirs:         test/+    main-is:                Spec.hs++    ghc-options:            -threaded+    default-language:       Haskell2010++    other-modules:          Z.Data.CBytesSpec+                            Z.Data.Builder.NumericSpec+                            Z.Data.JSON.BaseSpec+                            Z.Data.JSON.ValueSpec+                            Z.Data.Parser.BaseSpec+                            Z.Data.Parser.NumericSpec+                            Z.Data.Array.UnalignedAccessSpec+                            Z.Data.Text.BaseSpec+                            Z.Data.Text.BuilderSpec+                            Z.Data.Text.ExtraSpec+                            Z.Data.Text.SearchSpec+                            Z.Data.Vector.BaseSpec+                            Z.Data.Vector.ExtraSpec+                            Z.Data.Vector.SearchSpec+                            Z.Data.Vector.SortSpec+                            Z.Data.Vector.FlatMapSpec+                            Z.Data.Vector.FlatSetSpec+    build-depends:          Z-Data+                          , base+                          , hspec                   >= 2.5.4+                          , hashable+                          , HUnit+                          , QuickCheck              >= 2.10+                          , quickcheck-instances+                          , word8+                          , scientific+                          , primitive++    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+
+ Z/Data/Array.hs view
@@ -0,0 +1,600 @@+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE TypeFamilyDependencies #-}+{-# LANGUAGE CPP                    #-}+{-# LANGUAGE FlexibleContexts       #-}+{-# LANGUAGE FlexibleInstances      #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE KindSignatures         #-}+{-# LANGUAGE MagicHash              #-}+{-# LANGUAGE MultiParamTypeClasses  #-}+{-# LANGUAGE ScopedTypeVariables    #-}+{-# LANGUAGE TypeFamilies           #-}+{-# LANGUAGE UnboxedTuples          #-}+{-# LANGUAGE UnliftedFFITypes       #-}+++{-|+Module      : Z.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 "Z.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 Z.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+  , Cast+  , 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           GHC.Prim+import           GHC.Types+import           Z.Data.Array.Cast+import           Z.Data.Array.UnliftedArray+++-- | Bottom value (@throw ('UndefinedElement' "Data.Array.uninitialized")@)+-- for initialize new boxed array('Array', 'SmallArray'..).+--+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 (arr :: * -> * ) a where+++    -- | Mutable version of this array type.+    --+    type MArr arr = (mar :: * -> * -> *) | mar -> arr+++    -- | 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 arr s a)+++    -- | Make a new array and fill it with an initial value.+    newArrWith :: (PrimMonad m, PrimState m ~ s) => Int -> a -> m (MArr arr s a)+++    -- | Index mutable array in a primitive monad.+    readArr :: (PrimMonad m, PrimState m ~ s) => MArr arr s a -> Int -> m a+++    -- | Write mutable array in a primitive monad.+    writeArr :: (PrimMonad m, PrimState m ~ s) => MArr arr s a -> Int -> a -> m ()+++    -- | Fill mutable array with a given value.+    setArr :: (PrimMonad m, PrimState m ~ s) => MArr arr 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 arr 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 arr s a)+++    -- | In place freeze a mutable array, the original mutable array can not be used+    -- anymore.+    unsafeFreezeArr :: (PrimMonad m, PrimState m ~ s) => MArr arr 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 arr s a)+++    -- | Copy a slice of immutable array to mutable array at given offset.+    copyArr ::  (PrimMonad m, PrimState m ~ s)+            => MArr arr s a -- ^ target+            -> Int          -- ^ target offset+            -> arr a        -- ^ source+            -> Int          -- ^ source offset+            -> Int          -- ^ source length+            -> 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 arr s a  -- ^ target+                   -> Int           -- ^ target offset+                   -> MArr arr s a  -- ^ source+                   -> Int           -- ^ source offset+                   -> Int           -- ^ source length+                   -> 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 arr s a  -- ^ target+            -> Int           -- ^ target offset+            -> MArr arr s a  -- ^ source+            -> Int           -- ^ source offset+            -> Int           -- ^ source length+            -> m ()+++    -- | Create immutable copy.+    cloneArr :: arr a -> Int -> Int -> arr a+++    -- | Create mutable copy.+    cloneMutableArr :: (PrimMonad m, PrimState m ~ s) => MArr arr s a -> Int -> Int -> m (MArr arr s a)+++    -- | Resize mutable array to given size.+    resizeMutableArr :: (PrimMonad m, PrimState m ~ s) => MArr arr s a -> Int -> m (MArr arr s a)+++    -- | Shrink mutable array to given size. This operation only works on primitive arrays.+    -- For some array types, this is a no-op, e.g. 'sizeOfMutableArr' will not change.+    shrinkMutableArr :: (PrimMonad m, PrimState m ~ s) => MArr arr s a -> Int -> m ()+++    -- | Is two mutable array are reference equal.+    sameMutableArr :: MArr arr s a -> MArr arr s a -> Bool+++    -- | Size of immutable array.+    sizeofArr :: arr a -> Int+++    -- | Size of mutable array.+    sizeofMutableArr :: (PrimMonad m, PrimState m ~ s) => MArr arr 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 Array a where+    type MArr Array = MutableArray+    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 SmallArray a where+    type MArr SmallArray = SmallMutableArray+    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 (SmallMutableArray smarr#) (I# n#) = primitive_ (+        shrinkSmallMutableArray# smarr# n#)+    {-# 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 PrimArray a where+    type MArr PrimArray = MutablePrimArray+    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 = freezePrimArray+    {-# 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 = clonePrimArray+    {-# INLINE cloneArr #-}+    cloneMutableArr = cloneMutablePrimArray+    {-# 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 UnliftedArray a where+    type MArr UnliftedArray = MutableUnliftedArray+    newArr = unsafeNewUnliftedArray+    {-# INLINE newArr #-}+    newArrWith = newUnliftedArray+    {-# INLINE newArrWith #-}+    readArr = readUnliftedArray+    {-# INLINE readArr #-}+    writeArr = writeUnliftedArray+    {-# INLINE writeArr #-}+    setArr = setUnliftedArray+    {-# INLINE setArr #-}+    indexArr = indexUnliftedArray+    {-# INLINE indexArr #-}+    indexArr' arr i = (# indexUnliftedArray arr i #)+    {-# INLINE indexArr' #-}+    indexArrM arr i = return (indexUnliftedArray arr i)+    {-# 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 #-}++--------------------------------------------------------------------------------++-- | 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+++-- | Cast between arrays+castArray :: (Arr arr a, Cast a b) => arr a -> arr b+castArray = unsafeCoerce#+++-- | Cast between arrays+castMutableArray :: (Arr arr a, Cast a b) => MArr arr s a -> MArr arr s b+castMutableArray = unsafeCoerce#
+ Z/Data/Array/Cast.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE DefaultSignatures     #-}+{-# LANGUAGE MagicHash             #-}+{-# LANGUAGE MultiParamTypeClasses #-}++{-|+Module      : Z.Data.Array.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.++-}++#include "MachDeps.h"++module Z.Data.Array.Cast+    ( Cast(..)+    ) where++import           GHC.Prim+import           GHC.Types+import           GHC.Int+import           GHC.Word+#if WORD_SIZE_IN_BITS < 64+import           GHC.IntWord64+#endif+import           GHC.Float++++-- | `Cast` between primitive types of the same size.+--+class Cast source destination where+    cast :: source -> destination++instance {-# INCOHERENT #-} 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
+ Z/Data/Array/Checked.hs view
@@ -0,0 +1,275 @@+{-# LANGUAGE CPP           #-}+{-# LANGUAGE TypeFamilies  #-}+{-# LANGUAGE UnboxedTuples #-}++{-|+Module      : Z.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 "Z.Data.Array", but will throw an 'IndexOutOfBounds'+'ArrayException' on bound check failure, it's useful when debugging array algorithms: just swap this+module with "Z.Data.Array", segmentation faults caused by out bound access will be turned into exceptions+with more informations.++-}+module Z.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.Stack+import qualified Z.Data.Array          as A++check :: HasCallStack => Bool -> a -> a+{-# INLINE check #-}+check True  x = x+check False _ = throw (IndexOutOfBounds $ show callStack)++newArr :: (A.Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+       => Int -> m (A.MArr arr s a)+newArr n = check  (n>=0) (A.newArr n)+{-# INLINE newArr #-}++newArrWith :: (A.Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+           => Int -> a -> m (A.MArr arr s a)+newArrWith n x = check  (n>=0) (A.newArrWith n x)+{-# INLINE newArrWith #-}++readArr :: (A.Arr arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+        => A.MArr arr 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 arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+         => A.MArr arr 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 arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+       => A.MArr arr 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 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 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 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 arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+          => A.MArr arr 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 arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+        => arr a -> Int -> Int -> m (A.MArr arr 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 arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+        => A.MArr arr 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 arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+               => A.MArr arr s a -> Int -> A.MArr arr 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 arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+        => A.MArr arr s a -> Int -> A.MArr arr 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 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 arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+                => A.MArr arr s a -> Int -> Int -> m (A.MArr arr 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 arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+                 => A.MArr arr s a -> Int -> m (A.MArr arr 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 arr a, PrimMonad m, PrimState m ~ s, HasCallStack)+                 => A.MArr arr 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)
+ Z/Data/Array/QQ.hs view
@@ -0,0 +1,500 @@+{-# LANGUAGE CPP             #-}+{-# LANGUAGE MagicHash       #-}+{-# LANGUAGE QuasiQuotes     #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections   #-}+++{-|+Module      : Z.Data.Array.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'.++@+> :set -XQuasiQuotes+> :t [arrASCII|asdfg|]+[arrASCII|asdfg|] :: PrimArray GHC.Word.Word8+> [arrASCII|asdfg|]+fromListN 5 [97,115,100,102,103]+> :t [arrI16|1,2,3,4,5|]+[arrI16|1,2,3,4,5|] :: PrimArray GHC.Int.Int16+> [arrI16|1,2,3,4,5|]+fromListN 5 [1,2,3,4,5]+@++-}++module Z.Data.Array.QQ+  ( -- * PrimArray literal quoters+    arrASCII+  , arrW8, arrW16, arrW32, arrW64, arrWord+  , arrI8, arrI16, arrI32, arrI64, arrInt+   -- * quoter helpers+  , asciiLiteral+  , utf8Literal+  , arrayLiteral+  , 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           Data.Word+import           Data.Int+import           Language.Haskell.TH+import           Language.Haskell.TH.Quote+import           Z.Data.Array+import           Control.Monad.ST++-- $asciiLiteralExample+-- @+-- 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+-- @++-- | Construct data with ASCII encoded literals.+--+-- Provide a packing function, return a packing expression. Example usage:+--+-- $asciiLiteralExample+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|asdfg|] :: PrimArray Word8@+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 UTF8 encoded literals.+--+-- See 'asciiLiteral'+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+++-- | Construct data with array literals @e.g. 1,2,3@.+arrayLiteral :: ([Integer] -> Q [Word8])+              -> (ExpQ -> ExpQ -> ExpQ)+              -> String -> ExpQ+arrayLiteral 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, [])++--------------------------------------------------------------------------------++#define ARRAY_LITERAL_DOC(T)  \+-- | Construct 'PrimArray' 'T' with array literals @e.g. 1,2,3@. See 'asciiLiteral'++ARRAY_LITERAL_DOC(Word8)+word8Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+word8Literal k str = arrayLiteral 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|1,2,3,4,5|] :: PrimArray Word8@+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")++ARRAY_LITERAL_DOC(Int8)+int8Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+int8Literal k str = arrayLiteral 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)++-- | @[arrW8|1,2,3,4,5|] :: PrimArray Int8@+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")++--------------------------------------------------------------------------------++ARRAY_LITERAL_DOC(Word16)+word16Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+word16Literal k str = arrayLiteral 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|1,2,3,4,5|] :: PrimArray Word16@+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#)++ARRAY_LITERAL_DOC(Int16)+int16Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+int16Literal k str = arrayLiteral 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|1,2,3,4,5|] :: PrimArray Int16@+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")+--------------------------------------------------------------------------------++ARRAY_LITERAL_DOC(Word32)+word32Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+word32Literal k str = arrayLiteral 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|1,2,3,4,5|] :: PrimArray Word32@+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#)++ARRAY_LITERAL_DOC(Int32)+int32Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+int32Literal k str = arrayLiteral 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|1,2,3,4,5|] :: PrimArray Int32@+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")++--------------------------------------------------------------------------------++ARRAY_LITERAL_DOC(Word64)+word64Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+word64Literal k str = arrayLiteral 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|1,2,3,4,5|] :: PrimArray Word64@+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#)++ARRAY_LITERAL_DOC(Int64)+int64Literal :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+int64Literal k str = arrayLiteral 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|1,2,3,4,5|] :: PrimArray Int64@+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++ARRAY_LITERAL_DOC(Word)+wordLiteral :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+wordLiteral =+#if SIZEOF_HSWORD == 8+    word64Literal+#else+    word32Literal+#endif++ARRAY_LITERAL_DOC(Int)+intLiteral :: (ExpQ -> ExpQ -> ExpQ) -> String -> ExpQ+intLiteral =+#if SIZEOF_HSWORD == 8+    int64Literal+#else+    int32Literal+#endif++-- | @[arrWord|1,2,3,4,5|] :: PrimArray Word@+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|1,2,3,4,5|] :: PrimArray Int@+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")++--------------------------------------------------------------------------------
+ Z/Data/Array/UnalignedAccess.hs view
@@ -0,0 +1,807 @@+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE CPP               #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MagicHash         #-}+{-# LANGUAGE UnboxedTuples     #-}++{-|+Module      : Z.Data.Array.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 Z.Data.Array.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+
+ Z/Data/Array/UnliftedArray.hs view
@@ -0,0 +1,325 @@+{-# language MagicHash #-}+{-# language UnboxedTuples #-}+{-# language TypeFamilies #-}+{-# language TypeApplications #-}+{-# language ScopedTypeVariables #-}++-- GHC contains three general classes of value types:+--+--   1. Unboxed types: values are machine values made up of fixed numbers of bytes+--   2. Unlifted types: values are pointers, but strictly evaluated+--   3. Lifted types: values are pointers, lazily evaluated+--+-- The first category can be stored in a 'ByteArray', and this allows types in+-- category 3 that are simple wrappers around category 1 types to be stored+-- more efficiently using a 'ByteArray'. This module provides the same facility+-- for category 2 types.+--+-- GHC has two primitive types, 'ArrayArray#' and 'MutableArrayArray#'. These+-- are arrays of pointers, but of category 2 values, so they are known to not+-- be bottom. This allows types that are wrappers around such types to be stored+-- in an array without an extra level of indirection.+--+-- The way that the 'ArrayArray#' API works is that one can read and write+-- 'ArrayArray#' values to the positions. This works because all category 2+-- types share a uniform representation, unlike unboxed values which are+-- represented by varying (by type) numbers of bytes. However, using the+-- this makes the internal API very unsafe to use, as one has to coerce values+-- to and from 'ArrayArray#'.+--+-- The API presented by this module is more type safe. 'UnliftedArray' and+-- 'MutableUnliftedArray' are parameterized by the type of arrays they contain, and+-- the coercions necessary are abstracted into a class, 'PrimUnlifted', of things+-- that are eligible to be stored.+--+module Z.Data.Array.UnliftedArray where++import Control.Monad.Primitive+import Data.Primitive.PrimArray (PrimArray(..),MutablePrimArray(..))+import Data.Primitive.ByteArray (ByteArray(..),MutableByteArray(..))+import GHC.MVar (MVar(..))+import GHC.IORef (IORef(..))+import GHC.STRef (STRef(..))+import GHC.Exts+import GHC.IO.Unsafe++class PrimUnlifted a where+    writeUnliftedArray# :: MutableArrayArray# s -> Int# -> a -> State# s -> State# s+    readUnliftedArray# :: MutableArrayArray# s -> Int# -> State# s -> (# State# s, a #)+    indexUnliftedArray# :: ArrayArray# -> Int# -> a++instance PrimUnlifted (PrimArray a) where+    {-# inline writeUnliftedArray# #-}+    {-# inline readUnliftedArray# #-}+    {-# inline indexUnliftedArray# #-}+    writeUnliftedArray# a i (PrimArray x) = writeByteArrayArray# a i x+    readUnliftedArray# a i s0 = case readByteArrayArray# a i s0 of+        (# s1, x #) -> (# s1, PrimArray x #)+    indexUnliftedArray# a i = PrimArray (indexByteArrayArray# a i)++instance PrimUnlifted ByteArray where+    {-# inline writeUnliftedArray# #-}+    {-# inline readUnliftedArray# #-}+    {-# inline indexUnliftedArray# #-}+    writeUnliftedArray# a i (ByteArray x) = writeByteArrayArray# a i x+    readUnliftedArray# a i s0 = case readByteArrayArray# a i s0 of+        (# s1, x #) -> (# s1, ByteArray x #)+    indexUnliftedArray# a i = ByteArray (indexByteArrayArray# a i)++-- This uses unsafeCoerce# in the implementation of+-- indexUnliftedArray#. This does not lead to corruption FFI codegen+-- since ByteArray# and MutableByteArray# have the same FFI offset+-- applied by add_shim.+-- This also uses unsafeCoerce# to relax the constraints on the+-- state token. The primitives in GHC.Prim are too restrictive.+instance PrimUnlifted (MutableByteArray s) where+    {-# inline writeUnliftedArray# #-}+    {-# inline readUnliftedArray# #-}+    {-# inline indexUnliftedArray# #-}+    writeUnliftedArray# a i (MutableByteArray x) =+        writeMutableByteArrayArray# a i (unsafeCoerce# x)+    readUnliftedArray# a i s0 = case readMutableByteArrayArray# a i s0 of+        (# s1, x #) -> (# s1, MutableByteArray (unsafeCoerce# x) #)+    indexUnliftedArray# a i = MutableByteArray (unsafeCoerce# (indexByteArrayArray# a i))++-- See the note on the PrimUnlifted instance for MutableByteArray.+-- The same uses of unsafeCoerce# happen here.+instance PrimUnlifted (MutablePrimArray s a) where+    {-# inline writeUnliftedArray# #-}+    {-# inline readUnliftedArray# #-}+    {-# inline indexUnliftedArray# #-}+    writeUnliftedArray# a i (MutablePrimArray x) =+        writeMutableByteArrayArray# a i (unsafeCoerce# x)+    readUnliftedArray# a i s0 = case readMutableByteArrayArray# a i s0 of+        (# s1, x #) -> (# s1, MutablePrimArray (unsafeCoerce# x) #)+    indexUnliftedArray# a i = MutablePrimArray (unsafeCoerce# (indexByteArrayArray# a i))++-- This uses unsafeCoerce# in the implementation of all of its+-- methods. See the note for the PrimUnlifted instance of+-- Data.Primitive.MVar.MVar.+instance PrimUnlifted (MVar a) where+    {-# inline writeUnliftedArray# #-}+    {-# inline readUnliftedArray# #-}+    {-# inline indexUnliftedArray# #-}+    writeUnliftedArray# a i (MVar x) =+        writeArrayArrayArray# a i (unsafeCoerce# x)+    readUnliftedArray# a i s0 = case readArrayArrayArray# a i s0 of+        (# s1, x #) -> (# s1, MVar (unsafeCoerce# x) #)+    indexUnliftedArray# a i = MVar (unsafeCoerce# (indexArrayArrayArray# a i))++-- This uses unsafeCoerce# in the implementation of all of its+-- methods. This does not lead to corruption FFI codegen since ArrayArray#+-- and MutVar# have the same FFI offset applied by add_shim.+instance PrimUnlifted (STRef s a) where+    {-# inline writeUnliftedArray# #-}+    {-# inline readUnliftedArray# #-}+    {-# inline indexUnliftedArray# #-}+    writeUnliftedArray# a i (STRef x) =+        writeArrayArrayArray# a i (unsafeCoerce# x)+    readUnliftedArray# a i s0 = case readArrayArrayArray# a i s0 of+        (# s1, x #) -> (# s1, STRef (unsafeCoerce# x) #)+    indexUnliftedArray# a i =+        STRef (unsafeCoerce# (indexArrayArrayArray# a i))++instance PrimUnlifted (IORef a) where+    {-# inline writeUnliftedArray# #-}+    {-# inline readUnliftedArray# #-}+    {-# inline indexUnliftedArray# #-}+    writeUnliftedArray# a i (IORef v) = writeUnliftedArray# a i v+    readUnliftedArray# a i s0 = case readUnliftedArray# a i s0 of+        (# s1, v #) -> (# s1, IORef v #)+    indexUnliftedArray# a i = IORef (indexUnliftedArray# a i)++--------------------------------------------------------------------------------++data MutableUnliftedArray s a+    = MutableUnliftedArray (MutableArrayArray# s)++data UnliftedArray a+    = UnliftedArray ArrayArray#++-- | Creates a new 'MutableUnliftedArray'. This function is unsafe because it+-- initializes all elements of the array as pointers to the array itself. Attempting+-- to read one of these elements before writing to it is in effect an unsafe+-- coercion from the @'MutableUnliftedArray' s a@ to the element type.+unsafeNewUnliftedArray+    :: (PrimMonad m)+    => Int -- ^ size+    -> m (MutableUnliftedArray (PrimState m) a)+{-# inline unsafeNewUnliftedArray #-}+unsafeNewUnliftedArray (I# i#) = primitive $ \s -> case newArrayArray# i# s of+    (# s', maa# #) -> (# s', MutableUnliftedArray maa# #)++-- | Creates a new 'MutableUnliftedArray' with the specified value as initial+-- contents. This is slower than 'unsafeNewUnliftedArray', but safer.+newUnliftedArray+    :: (PrimMonad m, PrimUnlifted a)+    => Int -- ^ size+    -> a -- ^ initial value+    -> m (MutableUnliftedArray (PrimState m) a)+newUnliftedArray len v = do+    mua <- unsafeNewUnliftedArray len+    setUnliftedArray mua 0 len v+    pure mua+{-# inline newUnliftedArray #-}++setUnliftedArray+    :: (PrimMonad m, PrimUnlifted a)+    => MutableUnliftedArray (PrimState m) a -- ^ destination+    -> Int -- ^ offset+    -> Int -- ^ length+    -> a -- ^ value to fill with+    -> m ()+{-# inline setUnliftedArray #-}+setUnliftedArray mua off len v = loop (len + off - 1)+  where+    loop i+        | i < off = pure ()+        | otherwise = writeUnliftedArray mua i v *> loop (i-1)++-- | Yields the length of an 'UnliftedArray'.+sizeofUnliftedArray :: UnliftedArray e -> Int+{-# inline sizeofUnliftedArray #-}+sizeofUnliftedArray (UnliftedArray aa#) = I# (sizeofArrayArray# aa#)++-- | Yields the length of a 'MutableUnliftedArray'.+sizeofMutableUnliftedArray :: MutableUnliftedArray s e -> Int+{-# inline sizeofMutableUnliftedArray #-}+sizeofMutableUnliftedArray (MutableUnliftedArray maa#)+    = I# (sizeofMutableArrayArray# maa#)++writeUnliftedArray :: (PrimMonad m, PrimUnlifted a)+    => MutableUnliftedArray (PrimState m) a+    -> Int+    -> a+    -> m ()+{-# inline writeUnliftedArray #-}+writeUnliftedArray (MutableUnliftedArray arr) (I# ix) a =+    primitive_ (writeUnliftedArray# arr ix a)++readUnliftedArray :: (PrimMonad m, PrimUnlifted a)+    => MutableUnliftedArray (PrimState m) a+    -> Int+    -> m a+{-# inline readUnliftedArray #-}+readUnliftedArray (MutableUnliftedArray arr) (I# ix) =+    primitive (readUnliftedArray# arr ix)++indexUnliftedArray :: PrimUnlifted a+    => UnliftedArray a+    -> Int+    -> a+{-# inline indexUnliftedArray #-}+indexUnliftedArray (UnliftedArray arr) (I# ix) =+    indexUnliftedArray# arr ix++-- | Freezes a 'MutableUnliftedArray', yielding an 'UnliftedArray'. This simply+-- marks the array as frozen in place, so it should only be used when no further+-- modifications to the mutable array will be performed.+unsafeFreezeUnliftedArray+    :: (PrimMonad m)+    => MutableUnliftedArray (PrimState m) a+    -> m (UnliftedArray a)+unsafeFreezeUnliftedArray (MutableUnliftedArray maa#)+    = primitive $ \s -> case unsafeFreezeArrayArray# maa# s of+        (# s', aa# #) -> (# s', UnliftedArray aa# #)+{-# inline unsafeFreezeUnliftedArray #-}++-- | Determines whether two 'MutableUnliftedArray' values are the same. This is+-- object/pointer identity, not based on the contents.+sameMutableUnliftedArray+    :: MutableUnliftedArray s a+    -> MutableUnliftedArray s a+    -> Bool+sameMutableUnliftedArray (MutableUnliftedArray maa1#) (MutableUnliftedArray maa2#)+    = isTrue# (sameMutableArrayArray# maa1# maa2#)+{-# inline sameMutableUnliftedArray #-}++-- | Copies the contents of an immutable array into a mutable array.+copyUnliftedArray+    :: (PrimMonad m)+    => MutableUnliftedArray (PrimState m) a -- ^ destination+    -> Int -- ^ offset into destination+    -> UnliftedArray a -- ^ source+    -> Int -- ^ offset into source+    -> Int -- ^ number of elements to copy+    -> m ()+{-# inline copyUnliftedArray #-}+copyUnliftedArray+    (MutableUnliftedArray dst) (I# doff)+    (UnliftedArray src) (I# soff) (I# ln) =+      primitive_ $ copyArrayArray# src soff dst doff ln+++-- | Copies the contents of one mutable array into another.+copyMutableUnliftedArray+    :: (PrimMonad m)+    => MutableUnliftedArray (PrimState m) a -- ^ destination+    -> Int -- ^ offset into destination+    -> MutableUnliftedArray (PrimState m) a -- ^ source+    -> Int -- ^ offset into source+    -> Int -- ^ number of elements to copy+    -> m ()+{-# inline copyMutableUnliftedArray #-}+copyMutableUnliftedArray+    (MutableUnliftedArray dst) (I# doff)+    (MutableUnliftedArray src) (I# soff) (I# ln) =+      primitive_ $ copyMutableArrayArray# src soff dst doff ln+++-- | Freezes a portion of a 'MutableUnliftedArray', yielding an 'UnliftedArray'.+-- This operation is safe, in that it copies the frozen portion, and the+-- existing mutable array may still be used afterward.+freezeUnliftedArray+    :: (PrimMonad m)+    => MutableUnliftedArray (PrimState m) a -- ^ source+    -> Int -- ^ offset+    -> Int -- ^ length+    -> m (UnliftedArray a)+freezeUnliftedArray src off len = do+    dst <- unsafeNewUnliftedArray len+    copyMutableUnliftedArray dst 0 src off len+    unsafeFreezeUnliftedArray dst+{-# inline freezeUnliftedArray #-}+++-- | Thaws a portion of an 'UnliftedArray', yielding a 'MutableUnliftedArray'.+-- This copies the thawed portion, so mutations will not affect the original+-- array.+thawUnliftedArray+    :: (PrimMonad m)+    => UnliftedArray a -- ^ source+    -> Int -- ^ offset+    -> Int -- ^ length+    -> m (MutableUnliftedArray (PrimState m) a)+{-# inline thawUnliftedArray #-}+thawUnliftedArray src off len = do+    dst <- unsafeNewUnliftedArray len+    copyUnliftedArray dst 0 src off len+    return dst++-- | Creates a copy of a portion of an 'UnliftedArray'+cloneUnliftedArray+    :: UnliftedArray a -- ^ source+    -> Int -- ^ offset+    -> Int -- ^ length+    -> UnliftedArray a+{-# inline cloneUnliftedArray #-}+cloneUnliftedArray src off len = unsafeDupablePerformIO $ do+    dst <- unsafeNewUnliftedArray len+    copyUnliftedArray dst 0 src off len+    unsafeFreezeUnliftedArray dst++-- | Creates a new 'MutableUnliftedArray' containing a copy of a portion of+-- another mutable array.+cloneMutableUnliftedArray+    :: (PrimMonad m)+    => MutableUnliftedArray (PrimState m) a -- ^ source+    -> Int -- ^ offset+    -> Int -- ^ length+    -> m (MutableUnliftedArray (PrimState m) a)+{-# inline cloneMutableUnliftedArray #-}+cloneMutableUnliftedArray src off len = do+    dst <- unsafeNewUnliftedArray len+    copyMutableUnliftedArray dst 0 src off len+    return dst
+ Z/Data/Builder.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UnboxedTuples       #-}++{-|+Module      : Z.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 Z.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+  , stringModifiedUTF8, charModifiedUTF8, 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+    -- * Builder helpers+  , paren, curly, square, angle, quotes, squotes, colon, comma, intercalateVec, intercalateList+  ) where++import           Z.Data.Builder.Base+import           Z.Data.Builder.Numeric
+ Z/Data/Builder/Base.hs view
@@ -0,0 +1,615 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE UnboxedTuples       #-}++{-|+Module      : Z.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 Z.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+  -- * Builder helpers+  , paren, curly, square, angle, quotes, squotes, colon, comma, intercalateVec, intercalateList+  ) 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.Primitive.PrimArray           (MutablePrimArray (..))+import           Data.Primitive.Ptr                 (copyPtrToMutablePrimArray)+import           Data.String                        (IsString (..))+import           Data.Word+import           Data.Int+import           GHC.CString                        (unpackCString#, unpackCStringUtf8#)+import           GHC.Prim+import           GHC.Ptr+import           GHC.Types+import qualified Z.Data.Array                     as A+import           Z.Data.Array.UnalignedAccess+import qualified Z.Data.Text.Base                 as T+import qualified Z.Data.Text.UTF8Codec            as T+import qualified Z.Data.Vector.Base               as V+import qualified Z.Data.Vector                    as V+import           System.IO.Unsafe+import           Test.QuickCheck.Arbitrary (Arbitrary(..), CoArbitrary(..))++-- | '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 Show (Builder a) where+    show = show . buildBytes++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++instance Arbitrary (Builder ()) where+    arbitrary = bytes <$> arbitrary+    shrink b = (bytes . V.pack) <$> shrink (V.unpack (buildBytes b))++instance CoArbitrary (Builder ()) where+    coarbitrary = coarbitrary . buildBytes++-- | Encode string with modified UTF-8 encoding, will be rewritten to a memcpy if possible.+stringModifiedUTF8 :: String -> Builder ()+{-# INLINE CONLIKE [0] stringModifiedUTF8 #-}+{-# RULES+    "stringModifiedUTF8/packAddrModified" forall addr . stringModifiedUTF8 (unpackCString# addr) = packAddrModified addr+  #-}+{-# RULES+    "stringModifiedUTF8/packAddrModified" forall addr . stringModifiedUTF8 (unpackCStringUtf8# addr) = packAddrModified 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'))++packAddrModified :: Addr# -> Builder ()+packAddrModified addr0# = copy addr0#+  where+    len = fromIntegral . unsafeDupablePerformIO $ V.c_strlen addr0#+    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. 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 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 buf offset) = do+    !siz <- A.sizeofMutableArr buf+    case () of+        _+            | offset /= 0 -> do+                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` pure (v : xs)+            | wantSiz <= siz -> k (Buffer buf 0) -- this should certainly not hold, but we still guard it+            | otherwise -> do+                buf' <- A.newArr (max wantSiz chunkSiz)        -- 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 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 )+    pure bs+  where+    lastStep _ (Buffer buf offset) = do+        siz <- A.sizeofMutableArr buf+        when (offset < siz) (A.shrinkMutableArr buf offset)+        arr <- A.unsafeFreezeArr buf+        pure [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+        pure [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))+    pure ()+  where+    lastStep :: a -> BuildStep RealWorld+    lastStep _ (Buffer buf offset) = do+        arr <- A.unsafeFreezeArr buf+        ioToPrim (action (V.PrimVector arr 0 offset))+        pure [] -- to match the silly pure type+{-# INLINABLE buildAndRun #-}++--------------------------------------------------------------------------------++atMost :: Int  -- ^ size bound+       -> (forall s. A.MutablePrimArray s Word8 -> Int -> ST s Int)  -- ^ the writer which pure 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 pure 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 [0] stringUTF8 #-}+{-# RULES+    "stringUTF8/packASCIIAddr" forall addr . stringUTF8 (unpackCString# addr) = packASCIIAddr addr+  #-}+{-# RULES+    "stringUTF8/packUTF8Addr" forall addr . stringUTF8 (unpackCString# addr) = packUTF8Addr addr+  #-}+stringUTF8 = mapM_ charUTF8++packASCIIAddr :: Addr# -> Builder ()+packASCIIAddr addr0# = copy addr0#+  where+    len = fromIntegral . unsafeDupablePerformIO $ V.c_strlen addr0#+    copy addr# = do+        ensureN len+        Builder (\ _  k (Buffer mba i) -> do+           copyPtrToMutablePrimArray mba i (Ptr addr#) len+           k () (Buffer mba (i + len)))++packUTF8Addr :: Addr# -> Builder ()+packUTF8Addr addr0# = validateAndCopy addr0#+  where+    len = fromIntegral . unsafeDupablePerformIO $ V.c_strlen addr0#+    valid = unsafeDupablePerformIO $ T.c_utf8_validate_addr addr0# 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++--------------------------------------------------------------------------------++#define BACKSLASH 92+#define CLOSE_ANGLE 62+#define CLOSE_CURLY 125+#define CLOSE_PAREN 41+#define CLOSE_SQUARE 93+#define COMMA 44+#define COLON 58+#define DOUBLE_QUOTE 34+#define OPEN_ANGLE 60+#define OPEN_CURLY 123+#define OPEN_PAREN 40+#define OPEN_SQUARE 91+#define SINGLE_QUOTE 39++-- | add @{...}@ to original builder.+paren :: Builder () -> Builder ()+{-# INLINE paren #-}+paren b = encodePrim @Word8 OPEN_PAREN >> b >> encodePrim @Word8 CLOSE_PAREN++-- | add @{...}@ to original builder.+curly :: Builder () -> Builder ()+{-# INLINE curly #-}+curly b = encodePrim @Word8 OPEN_CURLY >> b >> encodePrim @Word8 CLOSE_CURLY++-- | add @[...]@ to original builder.+square :: Builder () -> Builder ()+{-# INLINE square #-}+square b = encodePrim @Word8 OPEN_SQUARE >> b >> encodePrim @Word8 CLOSE_SQUARE++-- | add @<...>@ to original builder.+angle :: Builder () -> Builder ()+{-# INLINE angle #-}+angle b = encodePrim @Word8 OPEN_ANGLE >> b >> encodePrim @Word8 CLOSE_ANGLE++-- | add @"..."@ to original builder.+quotes :: Builder () -> Builder ()+{-# INLINE quotes #-}+quotes b = encodePrim @Word8 DOUBLE_QUOTE >> b >> encodePrim @Word8 DOUBLE_QUOTE++-- | add @'...'@ to original builder.+squotes :: Builder () -> Builder ()+{-# INLINE squotes #-}+squotes b = encodePrim @Word8 SINGLE_QUOTE >> b >> encodePrim @Word8 SINGLE_QUOTE++-- | write an ASCII @:@+colon :: Builder ()+{-# INLINE colon #-}+colon = encodePrim @Word8 COLON++-- | write an ASCII @,@+comma :: Builder ()+{-# INLINE comma #-}+comma = encodePrim @Word8 COMMA++-- | Use separator to connect a vector of builders.+intercalateVec :: (V.Vec v a)+            => Builder ()           -- ^ the seperator+            -> (a -> Builder ())    -- ^ value formatter+            -> v a                  -- ^ value vector+            ->  Builder ()+{-# INLINE intercalateVec #-}+intercalateVec s f v = do+    V.traverseVec_ (\ x -> f x >> s) (V.initMayEmpty v)+    forM_ (V.lastMaybe v) f++-- | Use separator to connect list of builders.+intercalateList :: Builder ()           -- ^ the seperator+                -> (a -> Builder ())    -- ^ value formatter+                -> [a]                  -- ^ value list+                -> Builder ()+{-# INLINE intercalateList #-}+intercalateList s f xs = go xs+  where+    go [] = pure ()+    go [x] = f x+    go (x:xs') = f x >> s >> go xs'
+ Z/Data/Builder/Numeric.hs view
@@ -0,0 +1,767 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE UnboxedTuples       #-}+{-# LANGUAGE UnliftedFFITypes    #-}++{-|+Module      : Z.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 Z.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+  , c_intWith, hs_intWith+) where++import           Control.Monad+import           Control.Monad.ST+import           Control.Monad.ST.Unsafe+import           Data.Bits+import           Data.Char+import           Data.Int+import qualified Data.List                           as List+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           Z.Data.Builder.Base+import           Z.Data.Builder.Numeric.DigitTable+import           Z.Foreign+import           System.IO.Unsafe+#ifdef INTEGER_GMP+import           GHC.Integer.GMP.Internals+#endif+import           Test.QuickCheck.Arbitrary           (Arbitrary(..), CoArbitrary(..))++--------------------------------------------------------------------------------++foreign import ccall unsafe "dtoa.h" c_int_dec :: Word64 -> Int -> Int -> Word8 -> MBA# Word8 -> Int -> IO Int++-- | Integral formatting options.+--+data IFormat = IFormat+    { width       :: Int            -- ^ total width, only effective with padding options+    , padding     :: Padding        -- ^ padding options+    , posSign     :: Bool           -- ^ show @+@ when the number is positive+    } deriving (Show, Eq, Ord)++instance Arbitrary IFormat where+    arbitrary = IFormat <$> arbitrary <*> arbitrary <*> arbitrary++instance CoArbitrary IFormat where+    coarbitrary (IFormat w pad p) = coarbitrary (w, pad, p)+++-- | @defaultIFormat = IFormat 0 NoPadding False@+defaultIFormat :: IFormat+defaultIFormat = IFormat 0 NoPadding False++data Padding = NoPadding | RightSpacePadding | LeftSpacePadding | ZeroPadding deriving (Show, Eq, Ord, Enum)++instance Arbitrary Padding where+    arbitrary = toEnum . (`mod` 4) <$> arbitrary++instance CoArbitrary Padding where+    coarbitrary = coarbitrary . fromEnum++-- | @int = intWith defaultIFormat@+int :: (Integral a, Bounded a) => a -> Builder ()+{-# INLINE int #-}+int = intWith defaultIFormat++-- | Format a 'Bounded' 'Integral' type like @Int@ or @Word16@ into decimal ASCII digits.+intWith :: (Integral a, Bounded a) => IFormat -> a -> Builder ()+intWith = hs_intWith+{-# INLINE[0] intWith #-}+{-# RULES "intWith'/Int8"    intWith = c_intWith  :: IFormat -> Int8    -> Builder () #-}+{-# RULES "intWith'/Int"     intWith = c_intWith  :: IFormat -> Int     -> Builder () #-}+{-# RULES "intWith'/Int16"   intWith = c_intWith  :: IFormat -> Int16   -> Builder () #-}+{-# RULES "intWith'/Int32"   intWith = c_intWith  :: IFormat -> Int32   -> Builder () #-}+{-# RULES "intWith'/Int64"   intWith = c_intWith  :: IFormat -> Int64   -> Builder () #-}+{-# RULES "intWith'/Word"    intWith = c_intWith  :: IFormat -> Word    -> Builder () #-}+{-# RULES "intWith'/Word8"   intWith = c_intWith  :: IFormat -> Word8   -> Builder () #-}+{-# RULES "intWith'/Word16"  intWith = c_intWith  :: IFormat -> Word16  -> Builder () #-}+{-# RULES "intWith'/Word32"  intWith = c_intWith  :: IFormat -> Word32  -> Builder () #-}+{-# RULES "intWith'/Word64"  intWith = c_intWith  :: IFormat -> Word64  -> Builder () #-}++-- | Internal formatting backed by C FFI, it must be used with type smaller than 'Word64'.+--+-- We use rewrite rules to rewrite most of the integral types formatting to this function.+c_intWith :: (Integral a, Bits a) => IFormat -> a -> Builder ()+{-# INLINE c_intWith #-}+c_intWith (IFormat{..}) x+    | x < 0 =+        let !x' = (fromIntegral (complement x) :: Word64) + 1+        in atMost width' (\ (MutablePrimArray mba#) i ->+            unsafeIOToST (c_int_dec x' (-1) width pad (unsafeCoerce# mba#) i))+    | posSign =+        atMost width' (\ (MutablePrimArray mba#) i ->+            unsafeIOToST (c_int_dec (fromIntegral x) 1 width pad (unsafeCoerce# mba#) i))+    | otherwise =+        atMost width' (\ (MutablePrimArray mba#) i ->+            unsafeIOToST (c_int_dec (fromIntegral x) 0 width pad (unsafeCoerce# mba#) i))+  where+    width' = max 21 width+    pad = case padding of NoPadding          -> 0+                          RightSpacePadding  -> 1+                          LeftSpacePadding   -> 2+                          ZeroPadding        -> 3++-- | Internal formatting in haskell, it can be used with any bounded integral type.+--+-- Other than provide fallback for the c version, this function is also used to check+-- the c version's formatting result.+hs_intWith :: (Integral a, Bounded a) => IFormat -> a -> Builder ()+{-# INLINABLE hs_intWith #-}+hs_intWith format@IFormat{..} 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 ()+{-# INLINABLE positiveInt #-}+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 $ indexOffPtr decDigitTable (j + 1)+        writePrimArray marr (off - 1) $ indexOffPtr 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 []     = pure ()+    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 = intWith defaultIFormat{padding = ZeroPadding, width=DIGITS}++    -- 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 hexSiz (go w (hexSiz-2))+  where+    bitSiz = finiteBitSize (undefined :: a)+    hexSiz = (bitSiz+3) `unsafeShiftR` 2+    go !v !d marr off+        | d > 0 = do+            let !i = fromIntegral v .&. 0xFF; !j = i + i+            writePrimArray marr (off + d) $ indexOffPtr hexDigitTable j+            writePrimArray marr (off + d + 1) $ indexOffPtr 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 $ indexOffPtr hexDigitTable j+            writePrimArray marr (off + 1) $ indexOffPtr 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 hexSiz (go w (hexSiz-2))+  where+    bitSiz = finiteBitSize (undefined :: a)+    hexSiz = (bitSiz+3) `unsafeShiftR` 2+    go !v !d marr off+        | d > 0 = do+            let !i = fromIntegral v .&. 0xFF; !j = i + i+            writePrimArray marr (off + d) $ indexOffPtr hexDigitTableUpper j+            writePrimArray marr (off + d + 1) $ indexOffPtr 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 $ indexOffPtr hexDigitTableUpper j+            writePrimArray marr (off + 1) $ indexOffPtr 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 (grisu3_sp (-x))+    | isNegativeZero x          = char8 '-' >> doFmt fmt decs ([0], 0)+    | x == 0                    = doFmt fmt decs ([0], 0)+    | otherwise                 = doFmt fmt decs (grisu3_sp x) -- Grisu only handles strictly positive finite numbers.++-- | 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 (grisu3 (-x))+    | isNegativeZero x          = char8 '-' >> doFmt fmt decs ([0], 0)+    | x == 0                    = doFmt fmt decs ([0], 0)+    | otherwise                 = doFmt fmt decs (grisu3 x) -- Grisu only handles strictly positive finite numbers.++-- | 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', note grisu only handles strictly positive finite numbers.+grisu3 :: Double -> ([Int], Int)+{-# INLINE grisu3 #-}+grisu3 d = unsafePerformIO $+    allocMutableByteArrayUnsafe GRISU3_DOUBLE_BUF_LEN $ \ pBuf -> do+        (len, (e, success)) <- allocPrimUnsafe $ \ pLen ->+            allocPrimUnsafe $ \ pE ->+                c_grisu3 (realToFrac d) pBuf pLen pE+        if success == 0 -- grisu3 fail+        then pure (floatToDigits 10 d)+        else do+            buf <- forM [0..len-1] $ \ i -> do+                w8 <- readByteArray (MutableByteArray pBuf) i :: IO Word8+                pure $! fromIntegral w8+            let !e' = e + len+            pure (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', note grisu3_sp only handles strictly positive finite numbers.+grisu3_sp :: Float -> ([Int], Int)+{-# INLINE grisu3_sp #-}+grisu3_sp d = unsafePerformIO $+    allocMutableByteArrayUnsafe GRISU3_SINGLE_BUF_LEN $ \ pBuf -> do+        (len, (e, success)) <- allocPrimUnsafe $ \ pLen ->+            allocPrimUnsafe $ \ pE ->+                c_grisu3_sp (realToFrac d) pBuf pLen pE+        if success == 0 -- grisu3 fail+        then pure (floatToDigits 10 d)+        else do+            buf <- forM [0..len-1] $ \ i -> do+                w8 <- readByteArray (MutableByteArray pBuf) i :: IO Word8+                pure $! fromIntegral w8+            let !e' = e + len+            pure (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)
+ Z/Data/Builder/Numeric/DigitTable.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE NoCPP     #-}++{-|+Module      : Z.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 Z.Data.Builder.Numeric.DigitTable where++import           Data.Primitive.Ptr+import           GHC.Word++decDigitTable :: Ptr Word8+decDigitTable = Ptr "0001020304050607080910111213141516171819\+                     \2021222324252627282930313233343536373839\+                     \4041424344454647484950515253545556575859\+                     \6061626364656667686970717273747576777879\+                     \8081828384858687888990919293949596979899"#++hexDigitTable :: Ptr Word8+hexDigitTable = Ptr "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\+                     \202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\+                     \404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f\+                     \606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f\+                     \808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f\+                     \a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf\+                     \c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf\+                     \e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"#++hexDigitTableUpper :: Ptr Word8+hexDigitTableUpper = Ptr "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\+                          \202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F\+                          \404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F\+                          \606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F\+                          \808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F\+                          \A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\+                          \C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\+                          \E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"#
+ Z/Data/CBytes.hs view
@@ -0,0 +1,444 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE UnliftedFFITypes #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE BangPatterns #-}+{-|+Module      : Z.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 Z.Data.CBytes+  ( CBytes+  , create+  , pack+  , unpack+  , null , length+  , empty, append, concat, intercalate, intercalateElem+  , toBytes, fromBytes, toText, toTextMaybe, fromText+  , fromCStringMaybe, fromCString, fromCStringN+  , withCBytes+  -- helpers re-export+  , V.w2c, V.c2w+  -- * exception+  , NullPointerException(..)+  ) where++import           Control.DeepSeq+import           Control.Exception (Exception, throwIO)+import           Control.Monad+import           Control.Monad.Primitive+import           Control.Monad.ST+import           Data.Bits+import           Data.Foldable           (foldlM)+import           Data.Hashable           (Hashable(..))+import qualified Data.List               as List+import           Data.String             (IsString (..))+import           Data.Typeable+import           Data.Primitive.PrimArray+import           Data.Word+import           Foreign.C+import           Foreign.Storable        (peekElemOff)+import           GHC.CString+import           GHC.Ptr+import           GHC.Stack+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           Z.Data.Array+import qualified Z.Data.Text           as T+import           Z.Data.Text.UTF8Codec (encodeCharModifiedUTF8)+import qualified Z.Data.Vector.Base    as V+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 NFData CBytes where+    {-# INLINE rnf #-}+    rnf (CBytesOnHeap _) = ()+    rnf (CBytesLiteral _) = ()++instance Eq CBytes where+    {-# INLINE (==) #-}+    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+    {-# INLINE compare #-}+    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 bss = case pre 0 0 bss of+    (0, _) -> empty+    (1, _) -> let Just b = List.find (not . null) bss in b -- there must be a not empty CBytes+    (_, l) -> runST $ do+        buf <- newPinnedPrimArray (l+1)+        copy bss 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)+        | l <= 0 = pre nacc lacc bs+        | otherwise     = pre (nacc+1) (l + lacc) bs+      where !l = length b++    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++-- | /O(n)/ The 'intercalate' function takes a 'CBytes' and a list of+-- 'CBytes' s and concatenates the list after interspersing the first+-- argument between each element of the list.+--+-- Note: 'intercalate' will force the entire 'CBytes' list.+--+intercalate :: CBytes -> [CBytes] -> CBytes+{-# INLINE intercalate #-}+intercalate s = concat . List.intersperse s+++-- | /O(n)/ An efficient way to join 'CByte' s with a byte.+--+intercalateElem :: Word8 -> [CBytes] -> CBytes+{-# INLINABLE intercalateElem #-}+intercalateElem w8 bss = case len bss 0 of+    0 -> empty+    l -> runST $ do+        buf <- newPinnedPrimArray (l+1)+        copy bss 0 buf+        writePrimArray buf l 0 -- the \NUL terminator+        CBytesOnHeap <$> unsafeFreezePrimArray buf+  where+    len []     !acc = acc+    len [b]    !acc = length b + acc+    len (b:bs) !acc = len bs (acc + length b + 1)+    copy :: [CBytes] -> Int -> MutablePrimArray s Word8 -> ST s ()+    -- bss must not be empty, which is checked by len above+    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)+        case bs of+            [] -> return () -- last one+            _  -> do+                let i' = i + l+                writePrimArray mba i' w8+                copy bs (i'+1) 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 to 'T.Text' using UTF8 encoding assumption.+--+-- Throw 'T.InvalidUTF8Exception' in case of invalid codepoint.+toText :: CBytes -> T.Text+{-# INLINABLE toText #-}+toText = T.validate . toBytes++-- | /O(n)/, convert to 'T.Text' using UTF8 encoding assumption.+--+-- Return 'Nothing' in case of invalid codepoint.+toTextMaybe :: CBytes -> Maybe T.Text+{-# INLINABLE toTextMaybe #-}+toTextMaybe = T.validateMaybe . toBytes++-- | /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 'NullPointerException' when meet a null pointer.+--+fromCString :: HasCallStack+            => CString+            -> IO CBytes+{-# INLINABLE fromCString #-}+fromCString cstring = do+    if cstring == nullPtr+    then throwIO (NullPointerException 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 = do+    if cstring == nullPtr+    then throwIO (NullPointerException 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)++data NullPointerException = NullPointerException CallStack deriving (Show, Typeable)+instance Exception NullPointerException++-- | 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#
+ Z/Data/Generics/Utils.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FunctionalDependencies #-}+++module Z.Data.Generics.Utils+  ( ProductSize(..)+  , productSize+  ) where++import GHC.Generics+import GHC.TypeNats+import GHC.Exts (Proxy#, proxy#)++-- | type class for calculating product size.+class KnownNat (PSize f) => ProductSize (f :: * -> *) where+    type PSize f :: Nat++instance ProductSize (S1 s a) where+    type PSize (S1 s a) = 1+instance (KnownNat (PSize a + PSize b), ProductSize a, ProductSize b) => ProductSize (a :*: b) where+    type PSize (a :*: b) = PSize a + PSize b++productSize :: forall f. KnownNat (PSize f) => Proxy# f -> Int+productSize _ = fromIntegral (natVal' (proxy# :: Proxy# (PSize f)))
+ Z/Data/JSON.hs view
@@ -0,0 +1,163 @@+{-|+Module      : Z.Data.JSON+Description : Fast JSON serialization/deserialization+Copyright   : (c) Dong Han, 2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++Types and functions for working efficiently with JSON data, the design is quite similar to @aeson@ or @json@:++  * Encode to bytes can be done directly via 'EncodeJSON'.+  * Decode are split in two step, first we parse JSON doc into 'Value', then convert to haskell data via 'FromValue'.+  * 'ToValue' are provided so that other doc formats can be easily supported, such as 'YAML'.++= How to use this module.++This module is intended to be used qualified, e.g.++@+    import qualified Z.Data.JSON as JSON+    import           Z.Data.JSON ((.:), ToValue(..), FromValue(..), EncodeJSON(..))+@++The easiest way to use the library is to define target data type, deriving 'GHC.Generics.Generic' and following instances:++  * 'FromValue', which provides 'fromValue' to convert 'Value' to Haskell values.+  * 'ToValue', which provides 'ToValue' to convert Haskell values to 'Value'.+  * 'EncodeJSON', which provides 'encodeJSON' to directly write Haskell value into JSON bytes.++The 'Generic' instances convert(encode) Haskell data with following rules:++  * Constructors without payloads are encoded as JSON String, @data T = A | B@ are encoded as @\"A\"@ or @\"B\"@.+  * Single constructor are ingored if there're payloads, @data T = T ...@,  @T@ is ingored:++    * Records are encoded as JSON object. @data T = T{k1 :: .., k2 :: ..}@ are encoded as @{\"k1\":...,\"k2\":...}@.+    * Plain product are encoded as JSON array. @data T = T t1 t2@ are encoded as "[x1,x2]".+    * Single field plain product are encoded as it is, i.e. @data T = T t@ are encoded as \"x\" just like its payload.++  * Multiple constructors are convert to single key JSON object if there're payloads:++    * Records are encoded as JSON object like above. @data T = A | B {k1 :: .., k2 :: ..}@ are encoded as+        @{\"B\":{\"k1\":...,\"k2\":...}}@ in @B .. ..@ case, or @\"A\"@ in @A@ case.+    * Plain product are similar to above, wrappered by an outer single-key object layer marking which constructor.++These rules apply to user defined ADTs, but some built-in instances have different behaviour, namely:++  * @Maybe a@ are encoded as JSON @null@ in 'Nothing' case, or directly encoded to its payload in 'Just' case.+  * @[a]@ are encoded to JSON array, including @[Char]@, i.e. there's no special treatment to 'String'. To get JSON string, use 'T.Text' or 'Z.Data.TextBuilder.Str'.+  * 'NonEmpty', 'Vector', 'PrimVector', 'HashSet', 'FlatSet', 'FlatIntSet' are also encoded to JSON array.+  * 'HashMap', 'FlatMap', 'FlatIntMap' are encoded to JSON object.++There're some modifying options if you providing a custom 'Settings', which allow you to modify field name or constructor+name, but please don't produce control characters during your modification, since we assume field labels and constructor+name won't contain them, thus we can save an extra escaping pass. To use constom 'Settings' just write:++@+    data T = T {fooBar :: Int, fooQux :: [Int]} deriving (Generic)+    instance ToValue T where toValue = JSON.gToValue JSON.defaultSettings{ JSON.fieldFmt = JSON.snakeCase } . from++    > JSON.toValue (T 0 [1,2,3])+    Object [(\"foo_bar\",Number 0.0),(\"bar_qux\",Array [Number 1.0,Number 2.0,Number 3.0])]+@++= Write instances manually.++You can write 'ToValue' and 'FromValue' instances by hand if the 'Generic' based one doesn't suit you. Here is an example+similar to aeson's.++@+    import qualified Z.Data.Text          as T+    import qualified Z.Data.Vector        as V+    import qualified Z.Data.Builder       as B++    data Person = Person { name :: T.Text , age  :: Int } deriving Show++    instance FromValue Person where+        fromValue = JSON.withFlatMapR \"Person\" $ \\ v -> Person+                        \<$\> v .: \"name\"+                        \<*\> v .: \"age\"++    instance ToValue Person where+        toValue (Person n a) = JSON.Object $ V.pack [(\"name\", toValue n),(\"age\", toValue a)]++    instance EncodeJSON Person where+        encodeJSON (Person n a) = B.curly $ do+            B.quotes \"name\" >> B.colon >> encodeJSON n+            B.comma+            B.quotes \"age\" >> B.colon >> encodeJSON a++    > toValue (Person \"Joe\" 12)+    Object [(\"name\",String \"Joe\"),(\"age\",Number 12.0)]+    > JSON.convert' @Person . JSON.Object $ V.pack [(\"name\",JSON.String \"Joe\"),(\"age\",JSON.Number 12.0)]+    Right (Person {name = \"Joe\", age = 12})+    > JSON.encodeText (Person \"Joe\" 12)+    "{\"name\":\"Joe\",\"age\":12}"+@++The 'Value' type is different from aeson's one in that we use @Vector (Text, Value)@ to represent JSON objects, thus+we can choose different strategies on key duplication, the lookup map type, etc. so instead of a single 'withObject',+we provide 'withHashMap', 'withHashMapR', 'withHashMap' and 'withHashMapR' which use different lookup map type, and different+key order piority. Most of time 'FlatMap' is faster than 'HashMap' since we only use the lookup map once, the cost of+constructing a 'HashMap' is higher. If you want to directly working on key-values, 'withKeyValues' provide key-values+vector access.++There're some useful tools to help write encoding code in "Z.Data.JSON.Builder" module, such as JSON string escaping tool, etc.+If you don't particularly care for fast encoding, you can also use 'toValue' together with value builder, the overhead is usually very small.++-}++module Z.Data.JSON+  ( -- * Encode & Decode+    DecodeError+  , decode, decode', decodeChunks, decodeChunks', encodeBytes, encodeText, encodeTextBuilder+    -- * Value type+  , Value(..)+    -- * parse into JSON Value+  , parseValue, parseValue', parseValueChunks, parseValueChunks'+  -- * Convert 'Value' to Haskell data+  , convert, convert', Converter(..), fail', (<?>), prependContext+  , PathElement(..), ConvertError+  , typeMismatch, fromNull, withBool, withScientific, withBoundedScientific, withRealFloat+  , withBoundedIntegral, withText, withArray, withKeyValues, withFlatMap, withFlatMapR+  , withHashMap, withHashMapR, withEmbeddedJSON+  , (.:), (.:?), (.:!), convertField, convertFieldMaybe, convertFieldMaybe'+  -- * FromValue, ToValue & EncodeJSON+  , ToValue(..)+  , FromValue(..)+  , EncodeJSON(..)+  , defaultSettings, Settings(..), snakeCase, trainCase+  , gToValue, gFromValue, gEncodeJSON+  ) where+++import Z.Data.JSON.Base+import qualified Z.Data.Text as T+import Data.Char+++-- | Snake casing a pascal cased constructor name or camel cased field name, words are always lower cased and separated by an+-- underscore.+snakeCase :: String -> T.Text+{-# INLINE snakeCase #-}+snakeCase = symbCase '_'++-- | Train casing a pascal cased constructor name or camel cased field name, words are always lower cased and separated by+-- a hyphen.+trainCase :: String -> T.Text+{-# INLINE trainCase #-}+trainCase = symbCase '-'++--------------------------------------------------------------------------------++symbCase :: Char -> String -> T.Text+{-# INLINE symbCase #-}+symbCase sym =  T.pack . go . applyFirst toLower+  where+    go []                       = []+    go (x:xs) | isUpper x = sym : toLower x : go xs+              | otherwise = x : go xs++    applyFirst _ []     = []+    applyFirst f (x:xs) = f x: xs
+ Z/Data/JSON/Base.hs view
@@ -0,0 +1,1317 @@+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE BangPatterns          #-}+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE DefaultSignatures     #-}+{-# LANGUAGE DeriveAnyClass        #-}+{-# LANGUAGE DeriveDataTypeable    #-}+{-# LANGUAGE DeriveGeneric         #-}+{-# LANGUAGE DerivingStrategies    #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE KindSignatures        #-}+{-# LANGUAGE MagicHash             #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes            #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE StandaloneDeriving    #-}+{-# LANGUAGE TypeApplications      #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE TypeOperators         #-}+{-# LANGUAGE PartialTypeSignatures #-}++{-|+Module      : Z.Data.JSON.Base+Description : Fast JSON serialization/deserialization+Copyright   : (c) Dong Han, 2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provides 'Converter' to convert 'Value' to haskell data types, and various tools to help+user define 'FromValue', 'ToValue' and 'EncodeJSON' instance.++-}++module Z.Data.JSON.Base+  ( -- * Encode & Decode+    DecodeError+  , decode, decode', decodeChunks, decodeChunks', encodeBytes, encodeText, encodeTextBuilder+  -- * Re-export 'Value' type+  , Value(..)+    -- * parse into JSON Value+  , JV.parseValue, JV.parseValue', JV.parseValueChunks, JV.parseValueChunks'+  -- * Convert 'Value' to Haskell data+  , convert, convert', Converter(..), fail', (<?>), prependContext+  , PathElement(..), ConvertError+  , typeMismatch, fromNull, withBool, withScientific, withBoundedScientific, withRealFloat+  , withBoundedIntegral, withText, withArray, withKeyValues, withFlatMap, withFlatMapR+  , withHashMap, withHashMapR, withEmbeddedJSON+  , (.:), (.:?), (.:!), convertField, convertFieldMaybe, convertFieldMaybe'+  -- * FromValue, ToValue & EncodeJSON+  , defaultSettings, Settings(..)+  , ToValue(..), GToValue(..)+  , FromValue(..), GFromValue(..)+  , EncodeJSON(..), GEncodeJSON(..)+  -- * Helper classes for generics+  , Field, GWriteFields(..), GMergeFields(..), GConstrToValue(..)+  , LookupTable, GFromFields(..), GBuildLookup(..), GConstrFromValue(..)+  , GAddPunctuation(..), GConstrEncodeJSON(..)+  ) where++import           Control.Applicative+import           Control.DeepSeq+import           Control.Monad+import qualified Control.Monad.Fail           as Fail+import           Control.Monad.ST+import           Data.Char                    (ord)+import           Data.Data+import           Data.Fixed+import           Data.Functor.Compose+import           Data.Functor.Const+import           Data.Functor.Identity+import           Data.Functor.Product+import           Data.Functor.Sum+import           Data.Hashable+import qualified Data.HashMap.Strict          as HM+import qualified Data.HashSet                 as HS+import           Data.Int+import           Data.List.NonEmpty           (NonEmpty (..))+import qualified Data.List.NonEmpty           as NonEmpty+import qualified Data.Monoid                  as Monoid+import           Data.Primitive.Types         (Prim)+import qualified Data.Primitive.SmallArray    as A+import           Data.Proxy                   (Proxy (..))+import           Data.Ratio                   (Ratio, (%), numerator, denominator)+import           Data.Scientific              (Scientific, base10Exponent, toBoundedInteger)+import qualified Data.Scientific              as Scientific+import qualified Data.Semigroup               as Semigroup+import           Data.Tagged                  (Tagged (..))+import           Data.Version                 (Version, parseVersion)+import           Data.Word+import           GHC.Exts                     (Proxy#, proxy#)+import           GHC.Generics+import           GHC.Natural+import qualified Z.Data.Builder             as B+import           Z.Data.Generics.Utils+import           Z.Data.JSON.Value          (Value(..))+import qualified Z.Data.JSON.Value          as JV+import qualified Z.Data.JSON.Builder        as JB+import qualified Z.Data.Parser              as P+import qualified Z.Data.Parser.Numeric      as P+import qualified Z.Data.Text                as T+import qualified Z.Data.Text.Builder        as TB+import qualified Z.Data.Vector.Base         as V+import qualified Z.Data.Vector.Extra        as V+import qualified Z.Data.Vector.FlatIntMap   as FIM+import qualified Z.Data.Vector.FlatIntSet   as FIS+import qualified Z.Data.Vector.FlatMap      as FM+import qualified Z.Data.Vector.FlatSet      as FS+import           Text.ParserCombinators.ReadP (readP_to_S)++--------------------------------------------------------------------------------++-- There're two possible failures here:+--+--   * 'P.ParseError' is an error during parsing bytes to 'Value'.+--   * 'ConvertError' is an error when converting 'Value' to target data type.+type DecodeError = Either P.ParseError ConvertError++-- | Decode a JSON doc, only trailing JSON whitespace are allowed.+--+decode' :: FromValue a => V.Bytes -> Either DecodeError a+{-# INLINE decode' #-}+decode' bs = case P.parse_ (JV.value <* JV.skipSpaces <* P.endOfInput) bs of+    Left pErr -> Left (Left pErr)+    Right v -> case convert fromValue v of+        Left cErr -> Left (Right cErr)+        Right r -> Right r++-- | Decode a JSON bytes, return any trailing bytes.+decode :: FromValue a => V.Bytes -> (V.Bytes, Either DecodeError a)+{-# INLINE decode #-}+decode bs = case P.parse JV.value bs of+    (bs', Left pErr) -> (bs', Left (Left pErr))+    (bs', Right v) -> case convert fromValue v of+        Left cErr -> (bs', Left (Right cErr))+        Right r -> (bs', Right r)++-- | Decode JSON doc chunks, return trailing bytes.+decodeChunks :: (FromValue a, Monad m) => m V.Bytes -> V.Bytes -> m (V.Bytes, Either DecodeError a)+{-# INLINE decodeChunks #-}+decodeChunks mb bs = do+    mr <- (P.parseChunks JV.value mb bs)+    case mr of+        (bs', Left pErr) -> pure (bs', Left (Left pErr))+        (bs', Right v) -> case convert fromValue v of+            Left cErr -> pure (bs', Left (Right cErr))+            Right r -> pure (bs', Right r)++-- | Decode JSON doc chunks, consuming trailing JSON whitespaces (other trailing bytes are not allowed).+decodeChunks' :: (FromValue a, Monad m) => m V.Bytes -> V.Bytes -> m (Either DecodeError a)+{-# INLINE decodeChunks' #-}+decodeChunks' mb bs = do+    mr <- (P.parseChunks (JV.value <* JV.skipSpaces <* P.endOfInput) mb bs)+    case mr of+        (_, Left pErr) -> pure (Left (Left pErr))+        (_, Right v) -> case convert fromValue v of+            Left cErr -> pure (Left (Right cErr))+            Right r -> pure (Right r)++-- | Directly encode data to JSON bytes.+encodeBytes :: EncodeJSON a => a -> V.Bytes+{-# INLINE encodeBytes #-}+encodeBytes = B.buildBytes . encodeJSON++-- | Text version 'encodeBytes'.+encodeText :: EncodeJSON a => a -> T.Text+{-# INLINE encodeText #-}+encodeText = TB.buildText . encodeTextBuilder++-- | JSON Docs are guaranteed to be valid UTF-8 texts, so we provide this.+encodeTextBuilder :: EncodeJSON a => a -> TB.TextBuilder ()+{-# INLINE encodeTextBuilder #-}+encodeTextBuilder = TB.unsafeFromBuilder . encodeJSON++-- | Run a 'Converter' with input value.+convert :: (a -> Converter r) -> a -> Either ConvertError r+{-# INLINE convert #-}+convert m v = runConverter (m v) (\ paths msg -> (Left (ConvertError paths msg))) Right++-- | Run a 'Converter' with input value.+convert' :: (FromValue a) => Value -> Either ConvertError a+{-# INLINE convert' #-}+convert' = convert fromValue++--------------------------------------------------------------------------------++-- | Elements of a (JSON) Value path used to describe the location of an error.+data PathElement+    = Key {-# UNPACK #-} !T.Text+        -- ^ Path element of a key into an object,+        -- \"object.key\".+    | Index {-# UNPACK #-} !Int+        -- ^ Path element of an index into an+        -- array, \"array[index]\".+    | Embedded+        -- ^ path of a embedded (JSON) String+  deriving (Eq, Show, Typeable, Ord, Generic, NFData)++data ConvertError = ConvertError { errPath :: [PathElement], errMsg :: T.Text } deriving (Eq, Ord, Generic, NFData)++instance Show ConvertError where+    -- TODO use standard format+    show (ConvertError paths msg) = T.unpack . TB.buildText $ do+        "<"+        mapM_ renderPath (reverse paths)+        "> "+        TB.text msg+      where+        renderPath (Index ix) = TB.char7 '[' >> TB.int ix >> TB.char7 ']'+        renderPath (Key k) = TB.char7 '.' >> (TB.unsafeFromBuilder $ JB.string k)+        renderPath Embedded = "<Embedded>"++-- | 'Converter' for convert result from JSON 'Value'.+--+-- This is intended to be named differently from 'P.Parser' to clear confusions.+newtype Converter a = Converter { runConverter :: forall r. ([PathElement] -> T.Text -> r) -> (a -> r) -> r }++instance Functor Converter where+    fmap f m = Converter (\ kf k -> runConverter m kf (k . f))+    {-# INLINE fmap #-}++instance Applicative Converter where+    pure a = Converter (\ _ k -> k a)+    {-# INLINE pure #-}+    (Converter f) <*> (Converter g) = Converter (\ kf k ->+        f kf (\ f' ->  g kf (k . f')))+    {-# INLINE (<*>) #-}++instance Alternative Converter where+    {-# INLINE (<|>) #-}+    (Converter f) <|> (Converter g) = Converter (\ kf k -> f (\ _ _ -> g kf k) k)+    {-# INLINE empty #-}+    empty = fail' "Z.Data.JSON.Base(Alternative).empty"++instance MonadPlus Converter where+    mzero = empty+    {-# INLINE mzero #-}+    mplus = (<|>)+    {-# INLINE mplus #-}++instance Monad Converter where+    (Converter f) >>= g = Converter (\ kf k ->+        f kf (\ a -> runConverter (g a) kf k))+    {-# INLINE (>>=) #-}+    return = pure+    {-# INLINE return #-}++instance Fail.MonadFail Converter where+    {-# INLINE fail #-}+    fail = fail' . T.pack++-- | 'T.Text' version of 'fail'.+fail' :: T.Text -> Converter a+{-# INLINE fail' #-}+fail' msg = Converter (\ kf _ -> kf [] msg)++--------------------------------------------------------------------------------++-- | Produce an error message like @converting XXX failed, expected XXX, encountered XXX@.+typeMismatch :: T.Text     -- ^ The name of the type you are trying to convert.+             -> T.Text     -- ^ The JSON value type you expecting to meet.+             -> Value      -- ^ The actual value encountered.+             -> Converter a+{-# INLINE typeMismatch #-}+typeMismatch name expected v =+    fail' $ T.concat ["converting ", name, " failed, expected ", expected, ", encountered ", actual]+  where+    actual = case v of+        Object _ -> "Object"+        Array _  -> "Array"+        String _ -> "String"+        Number _ -> "Number"+        Bool _   -> "Boolean"+        _        -> "Null"++-- | Add JSON Path context to a converter+--+-- When converting a complex structure, it helps to annotate (sub)converters+-- with context, so that if an error occurs, you can find its location.+--+-- > withFlatMapR "Person" $ \o ->+-- >   Person+-- >     <$> o .: "name" <?> Key "name"+-- >     <*> o .: "age" <?> Key "age"+--+-- (Standard methods like '(.:)' already do this.)+--+-- With such annotations, if an error occurs, you will get a JSON Path+-- location of that error.+(<?>) :: Converter a -> PathElement -> Converter a+{-# INLINE (<?>) #-}+(Converter p) <?> path = Converter (\ kf k -> p (kf . (path:)) k)+infixl 9 <?>++-- | Add context to a failure message, indicating the name of the structure+-- being converted.+--+-- > prependContext "MyType" (fail "[error message]")+-- > -- Error: "converting MyType failed, [error message]"+prependContext :: T.Text -> Converter a -> Converter a+{-# INLINE prependContext #-}+prependContext name (Converter p) = Converter (\ kf k ->+    p (\ paths msg -> kf paths (T.concat ["converting ", name, " failed, ", msg])) k)++fromNull :: T.Text -> a -> Value -> Converter a+{-# INLINE fromNull #-}+fromNull _ a Null = pure a+fromNull c _ v    = typeMismatch c "Null" v++withBool :: T.Text -> (Bool -> Converter a) -> Value ->  Converter a+{-# INLINE withBool #-}+withBool _    f (Bool x)  = f x+withBool name _ v         = typeMismatch name "Bool" v++-- | @'withScientific' name f value@ applies @f@ to the 'Scientific' number+-- when @value@ is a 'Data.Aeson.Number' and fails using 'typeMismatch'+-- otherwise.+--+-- /Warning/: If you are converting from a scientific to an unbounded+-- type such as 'Integer' you may want to add a restriction on the+-- size of the exponent (see 'withBoundedScientific') to prevent+-- malicious input from filling up the memory of the target system.+--+-- ==== Error message example+--+-- > withScientific "MyType" f (String "oops")+-- > -- Error: "converting MyType failed, expected Number, but encountered String"+withScientific :: T.Text -> (Scientific -> Converter a) -> Value ->  Converter a+{-# INLINE withScientific #-}+withScientific _    f (Number x)  = f x+withScientific name _ v           = typeMismatch name "Number" v++-- | @'withRealFloat' try to convert floating number with following rules:+--+--   * Use @±Infinity@ to represent out of range numbers.+--   * Convert @Null@ as @NaN@+--+withRealFloat :: RealFloat a => T.Text -> (a -> Converter r) -> Value -> Converter r+{-# INLINE withRealFloat #-}+withRealFloat _    f (Number s) = f (Scientific.toRealFloat s)+withRealFloat _    f Null       = f (0/0)+withRealFloat name _ v          = typeMismatch name "Number or Null" v++-- | @'withBoundedScientific' name f value@ applies @f@ to the 'Scientific' number+-- when @value@ is a 'Number' with exponent less than or equal to 1024.+withBoundedScientific :: T.Text -> (Scientific -> Converter a) -> Value ->  Converter a+{-# INLINE withBoundedScientific #-}+withBoundedScientific name f (Number x)+    | e <= 1024 = f x+    | otherwise = fail' . TB.buildText $ do+        "converting "+        TB.text name+        " failed, found a number with exponent "+        TB.int e+        ", but it must not be greater than 1024"+  where e = base10Exponent x+withBoundedScientific name _ v = typeMismatch name "Number" v++-- | @'withBoundedScientific' name f value@ applies @f@ to the 'Scientific' number+-- when @value@ is a 'Number' and value is within @minBound ~ maxBound@.+withBoundedIntegral :: (Bounded a, Integral a) => T.Text -> (a -> Converter r) -> Value -> Converter r+{-# INLINE withBoundedIntegral #-}+withBoundedIntegral name f (Number x) =+    case toBoundedInteger x of+        Just i -> f i+        _      -> fail' . TB.buildText $ do+            "converting "+            TB.text name+            "failed, value is either floating or will cause over or underflow "+            TB.scientific x+withBoundedIntegral name _ v = typeMismatch name "Number" v++withText :: T.Text -> (T.Text -> Converter a) -> Value -> Converter a+{-# INLINE withText #-}+withText _    f (String x)  = f x+withText name _ v           = typeMismatch name "String" v++withArray :: T.Text -> (V.Vector Value -> Converter a) -> Value -> Converter a+{-# INLINE withArray #-}+withArray _ f (Array arr)  = f arr+withArray name _ v         = typeMismatch name "Array" v++-- | Directly use 'Object' as key-values for further converting.+withKeyValues :: T.Text -> (V.Vector (T.Text, Value) -> Converter a) -> Value -> Converter a+{-# INLINE withKeyValues #-}+withKeyValues _    f (Object kvs) = f kvs+withKeyValues name _ v            = typeMismatch name "Object" v++-- | Take a 'Object' as an 'FM.FlatMap T.Text Value', on key duplication prefer first one.+withFlatMap :: T.Text -> (FM.FlatMap T.Text Value -> Converter a) -> Value -> Converter a+{-# INLINE withFlatMap #-}+withFlatMap _    f (Object obj) = f (FM.packVector obj)+withFlatMap name _ v            = typeMismatch name "Object" v++-- | Take a 'Object' as an 'FM.FlatMap T.Text Value', on key duplication prefer last one.+withFlatMapR :: T.Text -> (FM.FlatMap T.Text Value -> Converter a) -> Value -> Converter a+{-# INLINE withFlatMapR #-}+withFlatMapR _    f (Object obj) = f (FM.packVectorR obj)+withFlatMapR name _ v            = typeMismatch name "Object" v++-- | Take a 'Object' as an 'HM.HashMap T.Text Value', on key duplication prefer first one.+withHashMap :: T.Text -> (HM.HashMap T.Text Value -> Converter a) -> Value -> Converter a+{-# INLINE withHashMap #-}+withHashMap _    f (Object obj) = f (HM.fromList (V.unpackR obj))+withHashMap name _ v            = typeMismatch name "Object" v++-- | Take a 'Object' as an 'HM.HashMap T.Text Value', on key duplication prefer last one.+withHashMapR :: T.Text -> (HM.HashMap T.Text Value -> Converter a) -> Value -> Converter a+{-# INLINE withHashMapR #-}+withHashMapR _    f (Object obj) = f (HM.fromList (V.unpack obj))+withHashMapR name _ v            = typeMismatch name "Object" v++-- | Decode a nested JSON-encoded string.+withEmbeddedJSON :: T.Text                  -- ^ data type name+                 -> (Value -> Converter a)     -- ^ a inner converter which will get the converted 'Value'.+                 -> Value -> Converter a       -- a converter take a JSON String+{-# INLINE withEmbeddedJSON #-}+withEmbeddedJSON _ innerConverter (String txt) = Converter (\ kf k ->+        case decode' (T.getUTF8Bytes txt) of+            Right v -> runConverter (innerConverter v) (\ paths msg -> kf (Embedded:paths) msg) k+            Left (Left pErr) -> kf [] (T.intercalate ", " ("parsing embeded JSON failed ": pErr))+            _                -> error "Z.JSON.Base: impossible, converting to Value should not fail")+withEmbeddedJSON name _ v = typeMismatch name "String" v++-- | Retrieve the value associated with the given key of an 'Object'.+-- The result is 'empty' if the key is not present or the value cannot+-- be converted to the desired type.+--+-- This accessor is appropriate if the key and value /must/ be present+-- in an object for it to be valid.  If the key and value are+-- optional, use '.:?' instead.+(.:) :: (FromValue a) => FM.FlatMap T.Text Value -> T.Text -> Converter a+{-# INLINE (.:) #-}+(.:) = convertField fromValue++-- | Retrieve the value associated with the given key of an 'Object'. The+-- result is 'Nothing' if the key is not present or if its value is 'Null',+-- or 'empty' if the value cannot be converted to the desired type.+--+-- This accessor is most useful if the key and value can be absent+-- from an object without affecting its validity.  If the key and+-- value are mandatory, use '.:' instead.+(.:?) :: (FromValue a) => FM.FlatMap T.Text Value -> T.Text -> Converter (Maybe a)+{-# INLINE (.:?) #-}+(.:?) = convertFieldMaybe fromValue++-- | Retrieve the value associated with the given key of an 'Object'.+-- The result is 'Nothing' if the key is not present or 'empty' if the+-- value cannot be converted to the desired type.+--+-- This differs from '.:?' by attempting to convert 'Null' the same as any+-- other JSON value, instead of interpreting it as 'Nothing'.+(.:!) :: (FromValue a) => FM.FlatMap T.Text Value -> T.Text -> Converter (Maybe a)+{-# INLINE (.:!) #-}+(.:!) = convertFieldMaybe' fromValue++convertField :: (Value -> Converter a)  -- ^ the field converter (value part of a key value pair)+           -> FM.FlatMap T.Text Value -> T.Text -> Converter a+{-# INLINE convertField #-}+convertField p obj key = case FM.lookup key obj of+    Just v -> p v <?> Key key+    _      -> fail' (T.concat $ ["key ", key, " not present"])++-- | Variant of '.:?' with explicit converter function.+convertFieldMaybe :: (Value -> Converter a) -> FM.FlatMap T.Text Value -> T.Text -> Converter (Maybe a)+{-# INLINE convertFieldMaybe #-}+convertFieldMaybe p obj key = case FM.lookup key obj of+    Just Null -> pure Nothing+    Just v    -> Just <$> p v <?> Key key+    _         -> pure Nothing++-- | Variant of '.:!' with explicit converter function.+convertFieldMaybe' :: (Value -> Converter a) -> FM.FlatMap T.Text Value -> T.Text -> Converter (Maybe a)+{-# INLINE convertFieldMaybe' #-}+convertFieldMaybe' p obj key = case FM.lookup key obj of+    Just v  -> Just <$> p v <?> Key key+    _       -> pure Nothing++--------------------------------------------------------------------------------++-- | Use @,@ as separator to connect list of builders.+commaList' :: EncodeJSON a => [a] -> B.Builder ()+{-# INLINE commaList' #-}+commaList' = B.intercalateList B.comma encodeJSON++-- | Use @,@ as separator to connect a vector of builders.+commaVec' :: (EncodeJSON a, V.Vec v a) => v a ->  B.Builder ()+{-# INLINE commaVec' #-}+commaVec' = B.intercalateVec B.comma encodeJSON++--------------------------------------------------------------------------------++-- | Generic encode/decode Settings+--+-- There should be no control charactors in formatted texts since we don't escaping those+-- field names or constructor names ('defaultSettings' relys on Haskell's lexical property).+-- Otherwise 'encodeJSON' will output illegal JSON string.+data Settings = Settings+    { fieldFmt :: String -> T.Text  -- ^ format field labels+    , constrFmt :: String -> T.Text -- ^ format constructor names.+    }++defaultSettings :: Settings+defaultSettings = Settings T.pack T.pack++--------------------------------------------------------------------------------+-- ToValue+--------------------------------------------------------------------------------++-- | Typeclass for converting to JSON 'Value'.+class ToValue a where+    toValue :: a -> Value+    default toValue :: (Generic a, GToValue (Rep a)) => a -> Value+    toValue = gToValue defaultSettings . from++class GToValue f where+    gToValue :: Settings -> f a -> Value++--------------------------------------------------------------------------------+-- Selectors++type family Field f where+    Field (a :*: b) = Field a+    Field (S1 (MetaSel Nothing u ss ds) f) = Value+    Field (S1 (MetaSel (Just l) u ss ds) f) = (T.Text, Value)++class GWriteFields f where+    gWriteFields :: Settings -> A.SmallMutableArray s (Field f) -> Int -> f a -> ST s ()++instance (ProductSize a, GWriteFields a, GWriteFields b, Field a ~ Field b) => GWriteFields (a :*: b) where+    {-# INLINE gWriteFields #-}+    gWriteFields s marr idx (a :*: b) = do+        gWriteFields s marr idx a+        gWriteFields s marr (idx + productSize (proxy# :: Proxy# a)) b++instance (GToValue f) => GWriteFields (S1 (MetaSel Nothing u ss ds) f) where+    {-# INLINE gWriteFields #-}+    gWriteFields s marr idx (M1 x) = A.writeSmallArray marr idx (gToValue s x)++instance (GToValue f, Selector (MetaSel (Just l) u ss ds)) => GWriteFields (S1 (MetaSel (Just l) u ss ds) f) where+    {-# INLINE gWriteFields #-}+    gWriteFields s marr idx m1@(M1 x) = A.writeSmallArray marr idx ((fieldFmt s) (selName m1), gToValue s x)++instance (GToValue f, Selector (MetaSel (Just l) u ss ds)) => GToValue (S1 (MetaSel (Just l) u ss ds) f) where+    {-# INLINE gToValue #-}+    gToValue s m1@(M1 x) =+        let k = fieldFmt s $ selName m1+            v = gToValue s x+        in Object (V.singleton (k, v))++instance GToValue f => GToValue (S1 (MetaSel Nothing u ss ds) f) where+    {-# INLINE gToValue #-}+    gToValue s (M1 x) = gToValue s x++instance ToValue a => GToValue (K1 i a) where+    {-# INLINE gToValue #-}+    gToValue _ (K1 x) = toValue x++class GMergeFields f where+    gMergeFields :: Proxy# f -> A.SmallMutableArray s (Field f) -> ST s Value++instance GMergeFields a => GMergeFields (a :*: b) where+    {-# INLINE gMergeFields #-}+    gMergeFields _ = gMergeFields (proxy# :: Proxy# a)++instance GMergeFields (S1 (MetaSel Nothing u ss ds) f) where+    {-# INLINE gMergeFields #-}+    gMergeFields _ marr = do+        arr <- A.unsafeFreezeSmallArray marr+        let l = A.sizeofSmallArray arr+        pure (Array (V.Vector arr 0 l))++instance GMergeFields (S1 (MetaSel (Just l) u ss ds) f) where+    {-# INLINE gMergeFields #-}+    gMergeFields _ marr = do+        arr <- A.unsafeFreezeSmallArray marr+        let l = A.sizeofSmallArray arr+        pure (Object (V.Vector arr 0 l))++--------------------------------------------------------------------------------+-- Constructors++class GConstrToValue f where+    gConstrToValue :: Bool -> Settings -> f a -> Value++instance GConstrToValue V1 where+    {-# INLINE gConstrToValue #-}+    gConstrToValue _ _ _ = error "Z.Data.JSON.Base: empty data type"++instance (GConstrToValue f, GConstrToValue g) => GConstrToValue (f :+: g) where+    {-# INLINE gConstrToValue #-}+    gConstrToValue _ s (L1 x) = gConstrToValue True s x+    gConstrToValue _ s (R1 x) = gConstrToValue True s x++-- | Constructor without payload, convert to String+instance (Constructor c) => GConstrToValue (C1 c U1) where+    {-# INLINE gConstrToValue #-}+    gConstrToValue _ s (M1 _) = String . constrFmt s $ conName (undefined :: t c U1 a)++-- | Constructor with a single payload+instance (Constructor c, GToValue (S1 sc f)) => GConstrToValue (C1 c (S1 sc f)) where+    {-# INLINE gConstrToValue #-}+    gConstrToValue False s (M1 x) = gToValue s x+    gConstrToValue True s (M1 x) =+        let k = constrFmt s $ conName @c undefined+            v = gToValue s x+        in Object (V.singleton (k, v))++-- | Constructor with multiple payloads+instance (ProductSize (a :*: b), GWriteFields (a :*: b), GMergeFields (a :*: b), Constructor c)+    => GConstrToValue (C1 c (a :*: b)) where+    {-# INLINE gConstrToValue #-}+    gConstrToValue False s (M1 x) = runST (do+        marr <- A.newSmallArray (productSize (proxy# :: Proxy# (a :*: b))) undefined+        gWriteFields s marr 0 x+        gMergeFields (proxy# :: Proxy# (a :*: b)) marr)+    gConstrToValue True s (M1 x) =+        let k = constrFmt s $ conName @c undefined+            v = runST (do+                    marr <- A.newSmallArray (productSize (proxy# :: Proxy# (a :*: b))) undefined+                    gWriteFields s marr 0 x+                    gMergeFields (proxy# :: Proxy# (a :*: b)) marr)+        in Object (V.singleton (k, v))++--------------------------------------------------------------------------------+-- Data types+instance GConstrToValue f => GToValue (D1 c f) where+    {-# INLINE gToValue #-}+    gToValue s (M1 x) = gConstrToValue False s x++--------------------------------------------------------------------------------+-- EncodeJSON+--------------------------------------------------------------------------------++class EncodeJSON a where+    encodeJSON :: a -> B.Builder ()+    default encodeJSON :: (Generic a, GEncodeJSON (Rep a)) => a -> B.Builder ()+    encodeJSON = gEncodeJSON defaultSettings . from++class GEncodeJSON f where+    gEncodeJSON :: Settings -> f a -> B.Builder ()++--------------------------------------------------------------------------------+-- Selectors++instance (GEncodeJSON f, Selector (MetaSel (Just l) u ss ds)) => GEncodeJSON (S1 (MetaSel (Just l) u ss ds) f) where+    {-# INLINE gEncodeJSON #-}+    gEncodeJSON s m1@(M1 x) = (fieldFmt s $ selName m1) `JB.kv` gEncodeJSON s x++instance GEncodeJSON f => GEncodeJSON (S1 (MetaSel Nothing u ss ds) f) where+    {-# INLINE gEncodeJSON #-}+    gEncodeJSON s (M1 x) = gEncodeJSON s x++instance (GEncodeJSON a, GEncodeJSON b) => GEncodeJSON (a :*: b) where+    {-# INLINE gEncodeJSON #-}+    gEncodeJSON s (a :*: b) = gEncodeJSON s a >> B.comma >> gEncodeJSON s b++instance EncodeJSON a => GEncodeJSON (K1 i a) where+    {-# INLINE gEncodeJSON #-}+    gEncodeJSON _ (K1 x) = encodeJSON x++class GAddPunctuation (f :: * -> *) where+    gAddPunctuation :: Proxy# f -> B.Builder () -> B.Builder ()++instance GAddPunctuation a => GAddPunctuation (a :*: b) where+    {-# INLINE gAddPunctuation #-}+    gAddPunctuation _ = gAddPunctuation (proxy# :: Proxy# a)++instance GAddPunctuation (S1 (MetaSel Nothing u ss ds) f) where+    {-# INLINE gAddPunctuation #-}+    gAddPunctuation _ b = B.square b++instance GAddPunctuation (S1 (MetaSel (Just l) u ss ds) f) where+    {-# INLINE gAddPunctuation #-}+    gAddPunctuation _ b = B.curly b++--------------------------------------------------------------------------------+-- Constructors++class GConstrEncodeJSON f where+    gConstrEncodeJSON :: Bool -> Settings -> f a -> B.Builder ()++instance GConstrEncodeJSON V1 where+    {-# INLINE gConstrEncodeJSON #-}+    gConstrEncodeJSON _ _ _ = error "Z.Data.JSON.Base: empty data type"++instance (GConstrEncodeJSON f, GConstrEncodeJSON g) => GConstrEncodeJSON (f :+: g) where+    {-# INLINE gConstrEncodeJSON #-}+    gConstrEncodeJSON _ s (L1 x) = gConstrEncodeJSON True s x+    gConstrEncodeJSON _ s (R1 x) = gConstrEncodeJSON True s x++-- | Constructor without payload, convert to String+instance (Constructor c) => GConstrEncodeJSON (C1 c U1) where+    {-# INLINE gConstrEncodeJSON #-}+    -- There should be no chars need escaping in constructor name+    gConstrEncodeJSON _ s (M1 _) = B.quotes $+        B.text . constrFmt s $ conName (undefined :: t c U1 a)++-- | Constructor with a single payload+instance (Constructor c, GEncodeJSON (S1 sc f)) => GConstrEncodeJSON (C1 c (S1 sc f)) where+    {-# INLINE gConstrEncodeJSON #-}+    gConstrEncodeJSON False s (M1 x) = gEncodeJSON s x+    gConstrEncodeJSON True s (M1 x) = B.curly $ do+        (constrFmt s $ conName @c undefined) `JB.kv` gEncodeJSON s x++-- | Constructor with multiple payloads+instance (GEncodeJSON (a :*: b), GAddPunctuation (a :*: b), Constructor c)+    => GConstrEncodeJSON (C1 c (a :*: b)) where+    {-# INLINE gConstrEncodeJSON #-}+    gConstrEncodeJSON False s (M1 x) = gAddPunctuation (proxy# :: Proxy# (a :*: b)) (gEncodeJSON s x)+    gConstrEncodeJSON True s (M1 x) = B.curly $ do+        (constrFmt s $ conName @c @_ @_ @_ undefined) `JB.kv`+            gAddPunctuation (proxy# :: Proxy# (a :*: b)) (gEncodeJSON s x)++--------------------------------------------------------------------------------+-- Data types+instance GConstrEncodeJSON f => GEncodeJSON (D1 c f) where+    {-# INLINE gEncodeJSON #-}+    gEncodeJSON s (M1 x) = gConstrEncodeJSON False s x++--------------------------------------------------------------------------------+-- FromValue+--------------------------------------------------------------------------------++class FromValue a where+    fromValue :: Value -> Converter a+    default fromValue :: (Generic a, GFromValue (Rep a)) => Value -> Converter a+    fromValue v = to <$> gFromValue defaultSettings v++class GFromValue f where+    gFromValue :: Settings -> Value -> Converter (f a)++--------------------------------------------------------------------------------+-- Selectors++type family LookupTable f where+    LookupTable (a :*: b) = LookupTable a+    LookupTable (S1 (MetaSel Nothing u ss ds) f) = V.Vector Value+    LookupTable (S1 (MetaSel (Just l) u ss ds) f) = FM.FlatMap T.Text Value++class GFromFields f where+    gFromFields :: Settings -> LookupTable f -> Int -> Converter (f a)++instance (ProductSize a, GFromFields a, GFromFields b, LookupTable a ~ LookupTable b)+    => GFromFields (a :*: b) where+    {-# INLINE gFromFields #-}+    gFromFields s v idx = do+        a <- gFromFields s v idx+        b <- gFromFields s v (idx + productSize (proxy# :: Proxy# a))+        pure (a :*: b)++instance (GFromValue f) => GFromFields (S1 (MetaSel Nothing u ss ds) f) where+    {-# INLINE gFromFields #-}+    gFromFields s v idx = do+        v' <- V.unsafeIndexM v idx+        M1 <$> gFromValue s v' <?> Index idx++instance (GFromValue f, Selector (MetaSel (Just l) u ss ds)) => GFromFields (S1 (MetaSel (Just l) u ss ds) f) where+    {-# INLINE gFromFields #-}+    gFromFields s v _ = do+        case FM.lookup fn v of+            Just v' -> M1 <$> gFromValue s v' <?> Key fn+            _       -> fail' ("Z.Data.JSON.Base: missing field " <>  fn)+      where+        fn = (fieldFmt s) (selName (undefined :: S1 (MetaSel (Just l) u ss ds) f a))++instance GFromValue f => GFromValue (S1 (MetaSel Nothing u ss ds) f) where+    {-# INLINE gFromValue #-}+    gFromValue s x = M1 <$> gFromValue s x++instance (GFromValue f, Selector (MetaSel (Just l) u ss ds)) => GFromValue (S1 (MetaSel (Just l) u ss ds) f) where+    {-# INLINE gFromValue #-}+    gFromValue s (Object v) = do+        case FM.lookup fn (FM.packVectorR v) of+            Just v' -> M1 <$> gFromValue s v' <?> Key fn+            _       -> fail' ("Z.Data.JSON.Base: missing field " <>  fn)+      where fn = (fieldFmt s) (selName (undefined :: S1 (MetaSel (Just l) u ss ds) f a))+    gFromValue s v = typeMismatch ("field " <> fn) "Object" v <?> Key fn+      where fn = (fieldFmt s) (selName (undefined :: S1 (MetaSel (Just l) u ss ds) f a))++instance FromValue a => GFromValue (K1 i a) where+    {-# INLINE gFromValue #-}+    gFromValue _ x = K1 <$> fromValue x++class GBuildLookup f where+    gBuildLookup :: Proxy# f -> Int -> T.Text -> Value -> Converter (LookupTable f)++instance (GBuildLookup a, GBuildLookup b) => GBuildLookup (a :*: b) where+    {-# INLINE gBuildLookup #-}+    gBuildLookup _ siz = gBuildLookup (proxy# :: Proxy# a) siz++instance GBuildLookup (S1 (MetaSel Nothing u ss ds) f) where+    {-# INLINE gBuildLookup #-}+    gBuildLookup _ siz name (Array v)+        | siz' /= siz = fail' . TB.buildText $ do+            "converting "+            TB.text name+            " failed, product size mismatch, expected "+            TB.int siz+            ", get"+            TB.int siz'+        | otherwise = pure v+      where siz' = V.length v+    gBuildLookup _ _   name x         = typeMismatch name "Array" x++instance GBuildLookup (S1 ((MetaSel (Just l) u ss ds)) f) where+    {-# INLINE gBuildLookup #-}+    gBuildLookup _ siz name (Object v)+        | siz' /= siz = fail' . TB.buildText $ do+            "converting "+            TB.text name+            " failed, product size mismatch, expected "+            TB.int siz+            ", get"+            TB.int siz'+        | otherwise = pure m+      where siz' = FM.size m+            m = FM.packVectorR v+    gBuildLookup _ _   name x       = typeMismatch name "Object" x++--------------------------------------------------------------------------------+-- Constructors++class GConstrFromValue f where+    gConstrFromValue :: Bool -> Settings -> Value -> Converter (f a)++instance GConstrFromValue V1 where+    {-# INLINE gConstrFromValue #-}+    gConstrFromValue _ _ _ = error "Z.Data.JSON.Base: empty data type"++instance (GConstrFromValue f, GConstrFromValue g) => GConstrFromValue (f :+: g) where+    {-# INLINE gConstrFromValue #-}+    gConstrFromValue _ s x = (L1 <$> gConstrFromValue True s x) <|> (R1 <$> gConstrFromValue True s x)++-- | Constructor without payload, convert to String+instance (Constructor c) => GConstrFromValue (C1 c U1) where+    {-# INLINE gConstrFromValue #-}+    gConstrFromValue _ s (String x)+        | cn == x   = pure (M1 U1)+        | otherwise = fail' . T.concat $ ["converting ", cn', "failed, unknown constructor name ", x]+      where cn = constrFmt s $ conName (undefined :: t c U1 a)+            cn' = T.pack $ conName (undefined :: t c U1 a)+    gConstrFromValue _ _ v = typeMismatch cn' "String" v+      where cn' = T.pack $ conName (undefined :: t c U1 a)++-- | Constructor with a single payload+instance (Constructor c, GFromValue (S1 sc f)) => GConstrFromValue (C1 c (S1 sc f)) where+    {-# INLINE gConstrFromValue #-}+    gConstrFromValue False s x = M1 <$> gFromValue s x+    gConstrFromValue True s x = case x of+        Object v -> case V.indexM v 0 of+            Just (k, v') | k == cn -> M1 <$> gFromValue s v' <?> Key cn+            _                      -> fail' .T.concat $ ["converting ", cn', " failed, constructor not found"]+        _ ->  typeMismatch cn' "Object" x+      where cn = constrFmt s $ conName @c undefined+            cn' = T.pack $ conName @c undefined++-- | Constructor with multiple payloads+instance (ProductSize (a :*: b), GFromFields (a :*: b), GBuildLookup (a :*: b), Constructor c)+    => GConstrFromValue (C1 c (a :*: b)) where+    {-# INLINE gConstrFromValue #-}+    gConstrFromValue False s x = do+        t <- gBuildLookup p (productSize p) cn' x+        M1 <$> gFromFields s t 0+      where cn' = T.pack $ conName @c undefined+            p = proxy# :: Proxy# (a :*: b)+    gConstrFromValue True s x = case x of+        Object v -> case V.indexM v 0 of+            Just (k, v') | k == cn -> do t <- gBuildLookup p (productSize p) cn' v'+                                         M1 <$> gFromFields s t 0+            _                      -> fail' .T.concat $ ["converting ", cn', " failed, constructor not found"]+        _ ->  typeMismatch cn' "Object" x+      where cn = constrFmt s $ conName @c undefined+            cn' = T.pack $ conName @c undefined+            p = proxy# :: Proxy# (a :*: b)++--------------------------------------------------------------------------------+-- Data types+instance GConstrFromValue f => GFromValue (D1 c f) where+    {-# INLINE gFromValue #-}+    gFromValue s x = M1 <$> gConstrFromValue False s x++--------------------------------------------------------------------------------+-- Built-in Instances+--------------------------------------------------------------------------------+-- | Use 'Null' as @Proxy a@+instance FromValue (Proxy a)   where {{-# INLINE fromValue #-}; fromValue = fromNull "Proxy" Proxy;}+instance ToValue (Proxy a)     where {{-# INLINE toValue #-}; toValue _ = Null;}+instance EncodeJSON (Proxy a) where {{-# INLINE encodeJSON #-}; encodeJSON _ = "null";}++instance FromValue Value   where {{-# INLINE fromValue #-}; fromValue = pure;}+instance ToValue Value     where { {-# INLINE toValue #-}; toValue = id; }+instance EncodeJSON Value where { {-# INLINE encodeJSON #-}; encodeJSON = JB.value; }++instance FromValue T.Text   where {{-# INLINE fromValue #-}; fromValue = withText "Text" pure;}+instance ToValue T.Text     where {{-# INLINE toValue #-}; toValue = String;}+instance EncodeJSON T.Text where {{-# INLINE encodeJSON #-}; encodeJSON = JB.string;}++instance FromValue TB.Str where+    {-# INLINE fromValue #-}+    fromValue = withText "Str" (pure . TB.Str . T.unpack)+instance ToValue TB.Str where+    {-# INLINE toValue #-}+    toValue = String . T.pack . TB.chrs+instance EncodeJSON TB.Str where+    {-# INLINE encodeJSON #-}+    encodeJSON = JB.string . T.pack . TB.chrs++instance FromValue Scientific where {{-# INLINE fromValue #-}; fromValue = withScientific "Scientific" pure;}+instance ToValue Scientific where {{-# INLINE toValue #-}; toValue = Number;}+instance EncodeJSON Scientific where {{-# INLINE encodeJSON #-}; encodeJSON = B.scientific;}++-- | default instance prefer later key+instance FromValue a => FromValue (FM.FlatMap T.Text a) where+    {-# INLINE fromValue #-}+    fromValue = withFlatMapR "Z.Data.Vector.FlatMap.FlatMap"+        (FM.traverseWithKey $ \ k v -> fromValue v <?> Key k)+instance ToValue a => ToValue (FM.FlatMap T.Text a) where+    {-# INLINE toValue #-}+    toValue = Object . FM.sortedKeyValues . FM.map' toValue+instance EncodeJSON a => EncodeJSON (FM.FlatMap T.Text a) where+    {-# INLINE encodeJSON #-}+    encodeJSON = JB.object' encodeJSON . FM.sortedKeyValues++instance (Ord a, FromValue a) => FromValue (FS.FlatSet a) where+    {-# INLINE fromValue #-}+    fromValue = withArray "Z.Data.Vector.FlatSet.FlatSet" $ \ vs ->+        FS.packRN (V.length vs) <$>+            (zipWithM (\ k v -> fromValue v <?> Index k) [0..] (V.unpack vs))+instance ToValue a => ToValue (FS.FlatSet a) where+    {-# INLINE toValue #-}+    toValue = Array . V.map' toValue . FS.sortedValues+instance EncodeJSON a => EncodeJSON (FS.FlatSet a) where+    {-# INLINE encodeJSON #-}+    encodeJSON = JB.array' encodeJSON . FS.sortedValues++-- | default instance prefer later key+instance FromValue a => FromValue (HM.HashMap T.Text a) where+    {-# INLINE fromValue #-}+    fromValue = withHashMapR "Data.HashMap.HashMap"+        (HM.traverseWithKey $ \ k v -> fromValue v <?> Key k)+instance ToValue a => ToValue (HM.HashMap T.Text a) where+    {-# INLINE toValue #-}+    toValue = Object . V.pack . HM.toList . HM.map toValue+instance EncodeJSON a => EncodeJSON (HM.HashMap T.Text a) where+    {-# INLINE encodeJSON #-}+    encodeJSON = B.curly . B.intercalateList B.comma (\ (k, v) -> k `JB.kv'` encodeJSON v) . HM.toList++instance FromValue a => FromValue (FIM.FlatIntMap a) where+    {-# INLINE fromValue #-}+    fromValue = withFlatMapR "Z.Data.Vector.FlatIntMap.FlatIntMap" $ \ m ->+        let kvs = FM.sortedKeyValues m+        in FIM.packVectorR <$> (forM kvs $ \ (k, v) -> do+            case P.parse_ P.int (T.getUTF8Bytes k) of+                Right k' -> do+                    v' <- fromValue v <?> Key k+                    return (V.IPair k' v')+                _ -> fail' ("converting Z.Data.Vector.FlatIntMap.FlatIntMap failed, unexpected key " <> k))+instance ToValue a => ToValue (FIM.FlatIntMap a) where+    {-# INLINE toValue #-}+    toValue = Object . V.map' toKV . FIM.sortedKeyValues+      where toKV (V.IPair i x) = let !k = TB.buildText (TB.int i)+                                     !v = toValue x+                                 in (k, v)+instance EncodeJSON a => EncodeJSON (FIM.FlatIntMap a) where+    {-# INLINE encodeJSON #-}+    encodeJSON = B.curly . B.intercalateVec B.comma (\ (V.IPair i x) -> do+        B.quotes (B.int i)+        B.colon+        encodeJSON x) . FIM.sortedKeyValues++instance FromValue FIS.FlatIntSet where+    {-# INLINE fromValue #-}+    fromValue = withArray "Z.Data.Vector.FlatIntSet.FlatIntSet" $ \ vs ->+        FIS.packRN (V.length vs) <$> zipWithM (\ k v -> fromValue v <?> Index k) [0..] (V.unpack vs)+instance ToValue FIS.FlatIntSet where+    {-# INLINE toValue #-}+    toValue = toValue . FIS.sortedValues+instance EncodeJSON FIS.FlatIntSet where+    {-# INLINE encodeJSON #-}+    encodeJSON = encodeJSON . FIS.sortedValues++instance FromValue a => FromValue (V.Vector a) where+    {-# INLINE fromValue #-}+    fromValue = withArray "Z.Data.Vector.Vector"+        (V.traverseWithIndex $ \ k v -> fromValue v <?> Index k)+instance ToValue a => ToValue (V.Vector a) where+    {-# INLINE toValue #-}+    toValue = Array . V.map toValue+instance EncodeJSON a => EncodeJSON (V.Vector a) where+    {-# INLINE encodeJSON #-}+    encodeJSON = B.square . commaVec'++instance (Prim a, FromValue a) => FromValue (V.PrimVector a) where+    {-# INLINE fromValue #-}+    fromValue = withArray "Z.Data.Vector.PrimVector"+        (V.traverseWithIndex $ \ k v -> fromValue v <?> Index k)+instance (Prim a, ToValue a) => ToValue (V.PrimVector a) where+    {-# INLINE toValue #-}+    toValue = Array . V.map toValue+instance (Prim a, EncodeJSON a) => EncodeJSON (V.PrimVector a) where+    {-# INLINE encodeJSON #-}+    encodeJSON = B.square . commaVec'++instance (Eq a, Hashable a, FromValue a) => FromValue (HS.HashSet a) where+    {-# INLINE fromValue #-}+    fromValue = withArray "Z.Data.Vector.FlatSet.FlatSet" $ \ vs ->+        HS.fromList <$>+            (zipWithM (\ k v -> fromValue v <?> Index k) [0..] (V.unpack vs))+instance (ToValue a) => ToValue (HS.HashSet a) where+    {-# INLINE toValue #-}+    toValue = toValue . HS.toList+instance (EncodeJSON a) => EncodeJSON (HS.HashSet a) where+    {-# INLINE encodeJSON #-}+    encodeJSON = encodeJSON . HS.toList++instance FromValue a => FromValue [a] where+    {-# INLINE fromValue #-}+    fromValue = withArray "[a]" $ \ vs ->+        zipWithM (\ k v -> fromValue v <?> Index k) [0..] (V.unpack vs)+instance ToValue a => ToValue [a] where+    {-# INLINE toValue #-}+    toValue = Array . V.pack . map toValue+instance EncodeJSON a => EncodeJSON [a] where+    {-# INLINE encodeJSON #-}+    encodeJSON = B.square . commaList'++instance FromValue a => FromValue (NonEmpty a) where+    {-# INLINE fromValue #-}+    fromValue = withArray "NonEmpty" $ \ vs -> do+        l <- zipWithM (\ k v -> fromValue v <?> Index k) [0..] (V.unpack vs)+        case l of (x:xs) -> pure (x :| xs)+                  _      -> fail' "unexpected empty array"+instance (ToValue a) => ToValue (NonEmpty a) where+    {-# INLINE toValue #-}+    toValue = toValue . NonEmpty.toList+instance (EncodeJSON a) => EncodeJSON (NonEmpty a) where+    {-# INLINE encodeJSON #-}+    encodeJSON = encodeJSON . NonEmpty.toList++instance FromValue Bool where {{-# INLINE fromValue #-}; fromValue = withBool "Bool" pure;}+instance ToValue Bool where {{-# INLINE toValue #-}; toValue = Bool; }+instance EncodeJSON Bool where {{-# INLINE encodeJSON #-}; encodeJSON True = "true"; encodeJSON _ = "false";}++instance FromValue Char where+    {-# INLINE fromValue #-}+    fromValue = withText "Char" $ \ t ->+        case T.headMaybe t of+            Just c -> pure c+            _      -> fail' (T.concat ["converting Char failed, expected a string of length 1"])+instance ToValue Char where+    {-# INLINE toValue #-}+    toValue = String . T.singleton+instance EncodeJSON Char where+-- @+--    \'\\b\':  \"\\b\"+--    \'\\f\':  \"\\f\"+--    \'\\n\':  \"\\n\"+--    \'\\r\':  \"\\r\"+--    \'\\t\':  \"\\t\"+--    \'\"\':  \"\\\"\"+--    \'\\\':  \"\\\\\"+--    \'\/\':  \"\\/\"+--    other chars <= 0x1F: "\\u00XX"+-- @+    {-# INLINE encodeJSON #-}+    encodeJSON '\b' = "\"\\b\""+    encodeJSON '\f' = "\"\\f\""+    encodeJSON '\n' = "\"\\n\""+    encodeJSON '\r' = "\"\\r\""+    encodeJSON '\t' = "\"\\t\""+    encodeJSON '\"' = "\"\\\"\""+    encodeJSON '\\' = "\"\\\\\""+    encodeJSON '/'  = "\"\\/\""+    encodeJSON c | c <= '\US' = "\"\\u00" >> B.hex (fromIntegral (ord c) :: Word8) >> B.char8 '\"'+                 | otherwise  = B.quotes (B.charUTF8 c)+++instance FromValue Double where {{-# INLINE fromValue #-}; fromValue = withRealFloat "Double" pure;}+instance FromValue Float  where {{-# INLINE fromValue #-}; fromValue = withRealFloat "Double" pure;}+instance ToValue Float  where {{-# INLINE toValue #-}; toValue = Number . P.floatToScientific;}+instance ToValue Double where {{-# INLINE toValue #-}; toValue = Number . P.doubleToScientific;}+instance EncodeJSON Float  where {{-# INLINE encodeJSON #-}; encodeJSON = B.float;}+instance EncodeJSON Double where {{-# INLINE encodeJSON #-}; encodeJSON = B.double;}++instance FromValue Int    where {{-# INLINE fromValue #-}; fromValue = withBoundedIntegral "Int" pure;}+instance FromValue Int8   where {{-# INLINE fromValue #-}; fromValue = withBoundedIntegral "Int8" pure;}+instance FromValue Int16  where {{-# INLINE fromValue #-}; fromValue = withBoundedIntegral "Int16" pure;}+instance FromValue Int32  where {{-# INLINE fromValue #-}; fromValue = withBoundedIntegral "Int32" pure;}+instance FromValue Int64  where {{-# INLINE fromValue #-}; fromValue = withBoundedIntegral "Int64" pure;}+instance FromValue Word   where {{-# INLINE fromValue #-}; fromValue = withBoundedIntegral "Word" pure;}+instance FromValue Word8  where {{-# INLINE fromValue #-}; fromValue = withBoundedIntegral "Word8" pure;}+instance FromValue Word16 where {{-# INLINE fromValue #-}; fromValue = withBoundedIntegral "Word16" pure;}+instance FromValue Word32 where {{-# INLINE fromValue #-}; fromValue = withBoundedIntegral "Word32" pure;}+instance FromValue Word64 where {{-# INLINE fromValue #-}; fromValue = withBoundedIntegral "Word64" pure;}+instance ToValue Int    where {{-# INLINE toValue #-}; toValue = Number . fromIntegral;}+instance ToValue Int8   where {{-# INLINE toValue #-}; toValue = Number . fromIntegral;}+instance ToValue Int16  where {{-# INLINE toValue #-}; toValue = Number . fromIntegral;}+instance ToValue Int32  where {{-# INLINE toValue #-}; toValue = Number . fromIntegral;}+instance ToValue Int64  where {{-# INLINE toValue #-}; toValue = Number . fromIntegral;}+instance ToValue Word   where {{-# INLINE toValue #-}; toValue = Number . fromIntegral;}+instance ToValue Word8  where {{-# INLINE toValue #-}; toValue = Number . fromIntegral;}+instance ToValue Word16 where {{-# INLINE toValue #-}; toValue = Number . fromIntegral;}+instance ToValue Word32 where {{-# INLINE toValue #-}; toValue = Number . fromIntegral;}+instance ToValue Word64 where {{-# INLINE toValue #-}; toValue = Number . fromIntegral;}+instance EncodeJSON Int   where {{-# INLINE encodeJSON #-}; encodeJSON = B.int;}+instance EncodeJSON Int8  where {{-# INLINE encodeJSON #-}; encodeJSON = B.int;}+instance EncodeJSON Int16 where {{-# INLINE encodeJSON #-}; encodeJSON = B.int;}+instance EncodeJSON Int32 where {{-# INLINE encodeJSON #-}; encodeJSON = B.int;}+instance EncodeJSON Int64 where {{-# INLINE encodeJSON #-}; encodeJSON = B.int;}+instance EncodeJSON Word   where {{-# INLINE encodeJSON #-}; encodeJSON = B.int;}+instance EncodeJSON Word8  where {{-# INLINE encodeJSON #-}; encodeJSON = B.int;}+instance EncodeJSON Word16 where {{-# INLINE encodeJSON #-}; encodeJSON = B.int;}+instance EncodeJSON Word32 where {{-# INLINE encodeJSON #-}; encodeJSON = B.int;}+instance EncodeJSON Word64 where {{-# INLINE encodeJSON #-}; encodeJSON = B.int;}++-- | This instance includes a bounds check to prevent maliciously large inputs to fill up the memory of the target system. You can newtype Scientific and provide your own instance using 'withScientific' if you want to allow larger inputs.+instance FromValue Integer where+    {-# INLINE fromValue #-}+    fromValue = withBoundedScientific "Integer" $ \ n ->+        case Scientific.floatingOrInteger n :: Either Double Integer of+            Right x -> pure x+            Left _  -> fail' . TB.buildText $ do+                "converting Integer failed, unexpected floating number "+                TB.scientific n+instance ToValue Integer where+    {-# INLINE toValue #-}+    toValue = Number . fromIntegral+instance EncodeJSON Integer where+    {-# INLINE encodeJSON #-}+    encodeJSON = B.integer++instance FromValue Natural where+    {-# INLINE fromValue #-}+    fromValue = withBoundedScientific "Natural" $ \ n ->+        if n < 0+        then fail' . TB.buildText $ do+                "converting Natural failed, unexpected negative number "+                TB.scientific n+        else case Scientific.floatingOrInteger n :: Either Double Natural of+            Right x -> pure x+            Left _  -> fail' . TB.buildText $ do+                "converting Natural failed, unexpected floating number "+                TB.scientific n+instance ToValue Natural where+    {-# INLINE toValue #-}+    toValue = Number . fromIntegral+instance EncodeJSON Natural where+    {-# INLINE encodeJSON #-}+    encodeJSON = B.integer . fromIntegral++instance FromValue Ordering where+    fromValue = withText "Ordering" $ \ s ->+        case s of+            "LT" -> pure LT+            "EQ" -> pure EQ+            "GT" -> pure GT+            _ -> fail' . T.concat $ ["converting Ordering failed, unexpected ",+                                        s, " expected \"LT\", \"EQ\", or \"GT\""]+instance ToValue Ordering where+    {-# INLINE toValue #-}+    toValue LT = String "LT"+    toValue EQ = String "EQ"+    toValue GT = String "GT"+instance EncodeJSON Ordering where+    {-# INLINE encodeJSON #-}+    encodeJSON LT = "LT"+    encodeJSON EQ = "EQ"+    encodeJSON GT = "GT"++instance FromValue () where+    {-# INLINE fromValue #-}+    fromValue = withArray "()" $ \ v ->+        if V.null v+        then pure ()+        else fail' "converting () failed, expected an empty array"+instance ToValue () where+    {-# INLINE toValue #-}+    toValue () = Array V.empty+instance EncodeJSON () where+    {-# INLINE encodeJSON #-}+    encodeJSON () = "[]"++instance FromValue Version where+    {-# INLINE fromValue #-}+    fromValue = withText "Version" (go . readP_to_S parseVersion . T.unpack)+      where+        go [(v,[])] = pure v+        go (_ : xs) = go xs+        go _        = fail "converting Version failed"+instance ToValue Version where+    {-# INLINE toValue #-}+    toValue = String . T.pack . show+instance EncodeJSON Version where+    {-# INLINE encodeJSON #-}+    encodeJSON = B.string7 . show++instance FromValue a => FromValue (Maybe a) where+    {-# INLINE fromValue #-}+    fromValue Null = pure Nothing+    fromValue v = Just <$> fromValue v+instance ToValue a => ToValue (Maybe a) where+    {-# INLINE toValue #-}+    toValue Nothing = Null+    toValue (Just x) = toValue x+instance EncodeJSON a => EncodeJSON (Maybe a) where+    {-# INLINE encodeJSON #-}+    encodeJSON Nothing = "null"+    encodeJSON (Just x) = encodeJSON x++-- | This instance includes a bounds check to prevent maliciously large inputs to fill up the memory of the target system. You can newtype Ratio and provide your own instance using 'withScientific' if you want to allow larger inputs.+instance (FromValue a, Integral a) => FromValue (Ratio a) where+    {-# INLINE fromValue #-}+    fromValue = withFlatMapR "Rational" $ \obj -> do+        n <- obj .: "numerator"+        d <- obj .: "denominator"+        if d == 0+        then fail' "Ratio denominator was 0"+        else pure (n % d)+instance (ToValue a, Integral a) => ToValue (Ratio a) where+    {-# INLINE toValue #-}+    toValue x = Object (V.pack [("numerator", n), ("denominator", d)])+      where !n = toValue (numerator x)+            !d = toValue (denominator x)+instance (EncodeJSON a, Integral a) => EncodeJSON (Ratio a) where+    {-# INLINE encodeJSON #-}+    encodeJSON x =+        B.curly $ ("\"numerator\""   >> B.colon >> encodeJSON (numerator x))+            >> B.comma >> ("\"denominator\"" >> B.colon >> encodeJSON (denominator x))++-- | This instance includes a bounds check to prevent maliciously large inputs to fill up the memory of the target system. You can newtype Fixed and provide your own instance using 'withScientific' if you want to allow larger inputs.+instance HasResolution a => FromValue (Fixed a) where+    {-# INLINE fromValue #-}+    fromValue = withBoundedScientific "Fixed" (pure . realToFrac)+instance HasResolution a => ToValue (Fixed a) where+    {-# INLINE toValue #-}+    toValue = Number . realToFrac+instance HasResolution a => EncodeJSON (Fixed a) where+    {-# INLINE encodeJSON #-}+    encodeJSON = B.scientific . realToFrac++--------------------------------------------------------------------------------++deriving newtype instance FromValue (f (g a)) => FromValue (Compose f g a)+deriving newtype instance FromValue a => FromValue (Semigroup.Min a)+deriving newtype instance FromValue a => FromValue (Semigroup.Max a)+deriving newtype instance FromValue a => FromValue (Semigroup.First a)+deriving newtype instance FromValue a => FromValue (Semigroup.Last a)+deriving newtype instance FromValue a => FromValue (Semigroup.WrappedMonoid a)+deriving newtype instance FromValue a => FromValue (Semigroup.Dual a)+deriving newtype instance FromValue a => FromValue (Monoid.First a)+deriving newtype instance FromValue a => FromValue (Monoid.Last a)+deriving newtype instance FromValue a => FromValue (Identity a)+deriving newtype instance FromValue a => FromValue (Const a b)+deriving newtype instance FromValue b => FromValue (Tagged a b)++deriving newtype instance ToValue (f (g a)) => ToValue (Compose f g a)+deriving newtype instance ToValue a => ToValue (Semigroup.Min a)+deriving newtype instance ToValue a => ToValue (Semigroup.Max a)+deriving newtype instance ToValue a => ToValue (Semigroup.First a)+deriving newtype instance ToValue a => ToValue (Semigroup.Last a)+deriving newtype instance ToValue a => ToValue (Semigroup.WrappedMonoid a)+deriving newtype instance ToValue a => ToValue (Semigroup.Dual a)+deriving newtype instance ToValue a => ToValue (Monoid.First a)+deriving newtype instance ToValue a => ToValue (Monoid.Last a)+deriving newtype instance ToValue a => ToValue (Identity a)+deriving newtype instance ToValue a => ToValue (Const a b)+deriving newtype instance ToValue b => ToValue (Tagged a b)++deriving newtype instance EncodeJSON (f (g a)) => EncodeJSON (Compose f g a)+deriving newtype instance EncodeJSON a => EncodeJSON (Semigroup.Min a)+deriving newtype instance EncodeJSON a => EncodeJSON (Semigroup.Max a)+deriving newtype instance EncodeJSON a => EncodeJSON (Semigroup.First a)+deriving newtype instance EncodeJSON a => EncodeJSON (Semigroup.Last a)+deriving newtype instance EncodeJSON a => EncodeJSON (Semigroup.WrappedMonoid a)+deriving newtype instance EncodeJSON a => EncodeJSON (Semigroup.Dual a)+deriving newtype instance EncodeJSON a => EncodeJSON (Monoid.First a)+deriving newtype instance EncodeJSON a => EncodeJSON (Monoid.Last a)+deriving newtype instance EncodeJSON a => EncodeJSON (Identity a)+deriving newtype instance EncodeJSON a => EncodeJSON (Const a b)+deriving newtype instance EncodeJSON b => EncodeJSON (Tagged a b)++--------------------------------------------------------------------------------++deriving anyclass instance (FromValue (f a), FromValue (g a), FromValue a) => FromValue (Sum f g a)+deriving anyclass instance (FromValue a, FromValue b) => FromValue (Either a b)+deriving anyclass instance (FromValue (f a), FromValue (g a)) => FromValue (Product f g a)+deriving anyclass instance (FromValue a, FromValue b) => FromValue (a, b)+deriving anyclass instance (FromValue a, FromValue b, FromValue c) => FromValue (a, b, c)+deriving anyclass instance (FromValue a, FromValue b, FromValue c, FromValue d) => FromValue (a, b, c, d)+deriving anyclass instance (FromValue a, FromValue b, FromValue c, FromValue d, FromValue e) => FromValue (a, b, c, d, e)+deriving anyclass instance (FromValue a, FromValue b, FromValue c, FromValue d, FromValue e, FromValue f) => FromValue (a, b, c, d, e, f)+deriving anyclass instance (FromValue a, FromValue b, FromValue c, FromValue d, FromValue e, FromValue f, FromValue g) => FromValue (a, b, c, d, e, f, g)++deriving anyclass instance (ToValue (f a), ToValue (g a), ToValue a) => ToValue (Sum f g a)+deriving anyclass instance (ToValue a, ToValue b) => ToValue (Either a b)+deriving anyclass instance (ToValue (f a), ToValue (g a)) => ToValue (Product f g a)+deriving anyclass instance (ToValue a, ToValue b) => ToValue (a, b)+deriving anyclass instance (ToValue a, ToValue b, ToValue c) => ToValue (a, b, c)+deriving anyclass instance (ToValue a, ToValue b, ToValue c, ToValue d) => ToValue (a, b, c, d)+deriving anyclass instance (ToValue a, ToValue b, ToValue c, ToValue d, ToValue e) => ToValue (a, b, c, d, e)+deriving anyclass instance (ToValue a, ToValue b, ToValue c, ToValue d, ToValue e, ToValue f) => ToValue (a, b, c, d, e, f)+deriving anyclass instance (ToValue a, ToValue b, ToValue c, ToValue d, ToValue e, ToValue f, ToValue g) => ToValue (a, b, c, d, e, f, g)++deriving anyclass instance (EncodeJSON (f a), EncodeJSON (g a), EncodeJSON a) => EncodeJSON (Sum f g a)+deriving anyclass instance (EncodeJSON a, EncodeJSON b) => EncodeJSON (Either a b)+deriving anyclass instance (EncodeJSON (f a), EncodeJSON (g a)) => EncodeJSON (Product f g a)+deriving anyclass instance (EncodeJSON a, EncodeJSON b) => EncodeJSON (a, b)+deriving anyclass instance (EncodeJSON a, EncodeJSON b, EncodeJSON c) => EncodeJSON (a, b, c)+deriving anyclass instance (EncodeJSON a, EncodeJSON b, EncodeJSON c, EncodeJSON d) => EncodeJSON (a, b, c, d)+deriving anyclass instance (EncodeJSON a, EncodeJSON b, EncodeJSON c, EncodeJSON d, EncodeJSON e) => EncodeJSON (a, b, c, d, e)+deriving anyclass instance (EncodeJSON a, EncodeJSON b, EncodeJSON c, EncodeJSON d, EncodeJSON e, EncodeJSON f) => EncodeJSON (a, b, c, d, e, f)+deriving anyclass instance (EncodeJSON a, EncodeJSON b, EncodeJSON c, EncodeJSON d, EncodeJSON e, EncodeJSON f, EncodeJSON g) => EncodeJSON (a, b, c, d, e, f, g)
+ Z/Data/JSON/Builder.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE BangPatterns       #-}+{-# LANGUAGE CPP                #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE MagicHash          #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE UnliftedFFITypes   #-}+{-# LANGUAGE TypeApplications   #-}++{-|+Module      : Z.Data.JSON.Builder+Description : JSON representation and builders+Copyright   : (c) Dong Han, 2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provides builders for JSON 'Value's, a Haskell JSON representation. These builders are designed to comply with <https://tools.ietf.org/html/rfc8258 rfc8258>. Only control characters are escaped, other unicode codepoints are directly written instead of being escaped.++-}+module Z.Data.JSON.Builder+  ( -- * Value Builders+    value+  , object+  , object'+  , array+  , array'+  , string+    -- * Builder helpers+  , kv, kv'+    -- * Re-export 'Value' type+  , Value(..)+  ) where++import           Control.Monad+import           Control.Monad.ST.Unsafe  (unsafeIOToST)+import           Data.Primitive.PrimArray+import           Data.Word+import           GHC.Prim                 (unsafeCoerce#)+import qualified Z.Data.Builder              as B+import qualified Z.Data.Builder.Base         as B+import qualified Z.Data.Text            as T+import qualified Z.Data.Text.Base       as T+import           Z.Data.Vector.Base     as V+import           Z.Foreign+import           Z.Data.JSON.Value      (Value(..))++#define DOUBLE_QUOTE 34++-- | Use @:@ as separator to connect a label(no need to escape, only add quotes) with field builders.+kv :: T.Text -> B.Builder () -> B.Builder ()+{-# INLINE kv #-}+l `kv` b = B.quotes (B.text l) >> B.colon >> b++-- | Use @:@ as separator to connect a label(escaped and add quotes) with field builders.+kv' :: T.Text -> B.Builder () -> B.Builder ()+{-# INLINE kv' #-}+l `kv'` b = string l >> B.colon >> b++-- | Encode a 'Value', you can use this function with 'toValue' to get 'encodeJSON' with a small overhead.+value :: Value -> B.Builder ()+{-# INLINABLE value #-}+value (Object kvs) = object kvs+value (Array vs) = array vs+value (String t) = string t+value (Number n) = B.scientific n+value (Bool True) = "true"+value (Bool False) = "false"+value Null = "null"++array :: V.Vector Value -> B.Builder ()+{-# INLINE array #-}+array = B.square . B.intercalateVec B.comma value++array' :: (a -> B.Builder ()) -> V.Vector a -> B.Builder ()+{-# INLINE array' #-}+array' f = B.square . B.intercalateVec B.comma f++object :: V.Vector (T.Text, Value) -> B.Builder ()+{-# INLINE object #-}+object = B.curly . B.intercalateVec B.comma (\ (k, v) -> k `kv'` value v)++object' :: (a -> B.Builder ()) -> V.Vector (T.Text, a) -> B.Builder ()+{-# INLINE object' #-}+object' f = B.curly . B.intercalateVec B.comma (\ (k, v) -> k `kv'` f v)++-- | Escape text into JSON string and add double quotes, escaping rules:+--+-- @+--    \'\\b\':  \"\\b\"+--    \'\\f\':  \"\\f\"+--    \'\\n\':  \"\\n\"+--    \'\\r\':  \"\\r\"+--    \'\\t\':  \"\\t\"+--    \'\"\':  \"\\\"\"+--    \'\\\':  \"\\\\\"+--    \'\/\':  \"\\/\"+--    other chars <= 0x1F: "\\u00XX"+-- @+--+string :: T.Text -> B.Builder ()+{-# INLINE string #-}+string (T.Text (V.PrimVector ba@(PrimArray ba#) s l)) = do+    let siz = escape_json_string_length ba# s l+    B.ensureN siz+    B.Builder (\ _  k (B.Buffer mba@(MutablePrimArray mba#) i) -> do+        if siz == l+2   -- no need to escape+        then do+            writePrimArray mba i DOUBLE_QUOTE+            copyPrimArray mba (i+1) ba s l+            writePrimArray mba (i+1+l) DOUBLE_QUOTE+        else void $ unsafeIOToST (escape_json_string ba# s l (unsafeCoerce# mba#) i)+        k () (B.Buffer mba (i+siz)))++foreign import ccall unsafe escape_json_string_length+    :: BA# Word8 -> Int -> Int -> Int++foreign import ccall unsafe escape_json_string+    :: BA# Word8 -> Int -> Int -> MBA# Word8 -> Int -> IO Int
+ Z/Data/JSON/Value.hs view
@@ -0,0 +1,280 @@+{-# LANGUAGE BangPatterns       #-}+{-# LANGUAGE CPP                #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE DeriveAnyClass     #-}+{-# LANGUAGE MagicHash          #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE UnliftedFFITypes   #-}++{-|+Module      : Z.Data.JSON.Value+Description : JSON representation and parsers+Copyright   : (c) Dong Han, 2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provides definition and parsers for JSON 'Value's, a Haskell JSON representation. The parsers is designed to comply with <https://tools.ietf.org/html/rfc8258 rfc8258>, notable pitfalls are:++  * The numeric representation use 'Scientific', which impose a limit on number's exponent part(limited to 'Int').+  * Unescaped control characters(<=0x1F) are NOT accepted, (different from aeson).+  * Only @0x20, 0x09, 0x0A, 0x0D@ are valid JSON whitespaces, 'skipSpaces' from this module is different from 'P.skipSpaces'.+  * A JSON document shouldn't have trailing characters except whitespaces describe above, see 'parseValue''+    and 'parseValueChunks''.+  * Objects are represented as key-value vectors, key order and duplicated keys are preserved for further processing.++Note that rfc8258 doesn't enforce unique key in objects, it's up to users to decided how to deal with key duplication, e.g. prefer first or last key, see 'Z.Data.JSON.Base.withFlatMap' or 'Std.Data.JSON.Base.withFlatMapR' for example.++There's no lazy parsers here, every pieces of JSON document will be parsed into a normal form 'Value'. 'Object' and 'Array's payloads are packed into 'Vector's to avoid accumulating lists in memory. Read more about <http://winterland.me/2019/03/05/aeson's-mysterious-lazy-parsing why no lazy parsing is needed>.+-}++module Z.Data.JSON.Value+  ( -- * Value type+    Value(..)+    -- * parse into JSON Value+  , parseValue+  , parseValue'+  , parseValueChunks+  , parseValueChunks'+    -- * Value Parsers+  , value+  , object+  , array+  , string+  , skipSpaces+  ) where++import           Control.DeepSeq+import           Data.Bits                ((.&.))+import           Data.Functor+import           Data.Primitive.PrimArray+import           Data.Scientific          (Scientific, scientific)+import           Data.Typeable+import           Data.Word+import           GHC.Generics+import qualified Z.Data.Parser          as P+import           Z.Data.Parser          ((<?>))+import qualified Z.Data.Text            as T+import           Z.Data.Text.Builder    (ToText)+import qualified Z.Data.Text.Base       as T+import           Z.Data.Vector.Base     as V+import           Z.Data.Vector.Extra    as V+import           Z.Foreign+import           System.IO.Unsafe         (unsafeDupablePerformIO)+import           Test.QuickCheck.Arbitrary (Arbitrary(..))+import           Test.QuickCheck.Gen (Gen(..), listOf)++#define BACKSLASH 92+#define CLOSE_CURLY 125+#define CLOSE_SQUARE 93+#define COMMA 44+#define COLON 58+#define DOUBLE_QUOTE 34+#define OPEN_CURLY 123+#define OPEN_SQUARE 91+#define C_0 48+#define C_9 57+#define C_A 65+#define C_F 70+#define C_a 97+#define C_f 102+#define C_n 110+#define C_t 116+#define MINUS    45++--------------------------------------------------------------------------------+-- | A JSON value represented as a Haskell value.+--+-- The 'Object''s payload is a key-value vector instead of a map, which parsed+-- directly from JSON document. This design choice has following advantages:+--+--    * Allow different strategies handling duplicated keys.+--    * Allow different 'Map' type to do further parsing, e.g. 'Z.Data.Vector.FlatMap'+--    * Roundtrip without touching the original key-value order.+--    * Save time if constructing map is not neccessary, e.g.+--      using a linear scan to find a key if only that key is needed.+--+data Value = Object {-# UNPACK #-} !(V.Vector (T.Text, Value))+           | Array  {-# UNPACK #-} !(V.Vector Value)+           | String {-# UNPACK #-} !T.Text+           | Number {-# UNPACK #-} !Scientific+           | Bool   !Bool+           | Null+         deriving (Eq, Show, Typeable, Generic, ToText)++instance NFData Value where+    {-# INLINE rnf #-}+    rnf (Object o) = rnf o+    rnf (Array  a) = rnf a+    rnf (String s) = rnf s+    rnf (Number n) = rnf n+    rnf (Bool   b) = rnf b+    rnf Null = ()++instance Arbitrary Value where+    -- limit maximum depth of JSON document, otherwise it's too slow to run any tests+    arbitrary = arbitraryValue 0 4+      where+        arbitraryValue :: Int -> Int -> Gen Value+        arbitraryValue d s = do+            i <- arbitrary :: Gen Word+            case (i `mod` 6) of+                0 -> if d < s then Object . V.pack <$> listOf (arbitraryKV (d+1) s)+                              else pure Null+                1 -> if d < s then Array . V.pack <$> listOf (arbitraryValue (d+1) s)+                              else pure Null+                2 -> String <$> arbitrary+                3 -> do+                    c <- arbitrary+                    e <- arbitrary+                    pure . Number $ scientific c e+                4 -> Bool <$> arbitrary+                _ -> pure Null++        arbitraryKV d s = (,) <$> arbitrary <*> arbitraryValue d s++    shrink (Object kvs) = snd <$> (V.unpack kvs)+    shrink (Array vs) = V.unpack vs+    shrink _          = []++-- | Parse 'Value' without consuming trailing bytes.+parseValue :: V.Bytes -> (V.Bytes, Either P.ParseError Value)+{-# INLINE parseValue #-}+parseValue = P.parse value++-- | Parse 'Value', and consume all trailing JSON white spaces, if there're+-- bytes left, parsing will fail.+parseValue' :: V.Bytes -> Either P.ParseError Value+{-# INLINE parseValue' #-}+parseValue' = P.parse_ (value <* skipSpaces <* P.endOfInput)++-- | Increamental parse 'Value' without consuming trailing bytes.+parseValueChunks :: Monad m => m V.Bytes -> V.Bytes -> m (V.Bytes, Either P.ParseError Value)+{-# INLINE parseValueChunks #-}+parseValueChunks = P.parseChunks value++-- | Increamental parse 'Value' and consume all trailing JSON white spaces, if there're+-- bytes left, parsing will fail.+parseValueChunks' :: Monad m => m V.Bytes -> V.Bytes -> m (Either P.ParseError Value)+{-# INLINE parseValueChunks' #-}+parseValueChunks' mi inp = snd <$> P.parseChunks (value <* skipSpaces <* P.endOfInput) mi inp++--------------------------------------------------------------------------------++-- | The only valid whitespace in a JSON document is space, newline,+-- carriage pure, and tab.+skipSpaces :: P.Parser ()+{-# INLINE skipSpaces #-}+skipSpaces = P.skipWhile (\ w -> w == 0x20 || w == 0x0a || w == 0x0d || w == 0x09)++-- | JSON 'Value' parser.+value :: P.Parser Value+{-# INLINABLE value #-}+value = "Z.Data.JSON.Value.value" <?> do+    skipSpaces+    w <- P.peek+    case w of+        DOUBLE_QUOTE    -> P.skipWord8 *> (String <$> string_)+        OPEN_CURLY      -> P.skipWord8 *> (Object <$> object_)+        OPEN_SQUARE     -> P.skipWord8 *> (Array <$> array_)+        C_f             -> P.bytes "false" $> (Bool False)+        C_t             -> P.bytes "true" $> (Bool True)+        C_n             -> P.bytes "null" $> Null+        _   | w >= 48 && w <= 57 || w == MINUS -> Number <$> P.scientific'+            | otherwise -> fail "Z.Data.JSON.Value.value: not a valid json value"++-- | parse json array with leading OPEN_SQUARE.+array :: P.Parser (V.Vector Value)+{-# INLINE array #-}+array = "Z.Data.JSON.Value.array" <?> P.word8 OPEN_SQUARE *> array_++-- | parse json array without leading OPEN_SQUARE.+array_ :: P.Parser (V.Vector Value)+{-# INLINABLE array_ #-}+array_ = do+    skipSpaces+    w <- P.peek+    if w == CLOSE_SQUARE+    then P.skipWord8 $> V.empty+    else loop [] 1+  where+    loop :: [Value] -> Int -> P.Parser (V.Vector Value)+    loop acc !n = do+        !v <- value+        skipSpaces+        let acc' = v:acc+        ch <- P.satisfy $ \w -> w == COMMA || w == CLOSE_SQUARE+        if ch == COMMA+        then skipSpaces *> loop acc' (n+1)+        else pure $! V.packRN n acc'  -- n start from 1, so no need to +1 here++-- | parse json array with leading OPEN_CURLY.+object :: P.Parser (V.Vector (T.Text, Value))+{-# INLINE object #-}+object = "Z.Data.JSON.Value.object" <?> P.word8 OPEN_CURLY *> object_++-- | parse json object without leading OPEN_CURLY.+object_ :: P.Parser (V.Vector (T.Text, Value))+{-# INLINABLE object_ #-}+object_ = do+    skipSpaces+    w <- P.peek+    if w == CLOSE_CURLY+    then P.skipWord8 $> V.empty+    else loop [] 1+ where+    loop :: [(T.Text, Value)] -> Int -> P.Parser (V.Vector (T.Text, Value))+    loop acc !n = do+        !k <- string+        skipSpaces+        P.word8 COLON+        !v <- value+        skipSpaces+        let acc' = (k, v) : acc+        ch <- P.satisfy $ \w -> w == COMMA || w == CLOSE_CURLY+        if ch == COMMA+        then skipSpaces *> loop acc' (n+1)+        else pure $! V.packRN n acc'  -- n start from 1, so no need to +1 here++--------------------------------------------------------------------------------++string :: P.Parser T.Text+{-# INLINE string #-}+string = "Z.Data.JSON.Value.string" <?> P.word8 DOUBLE_QUOTE *> string_++string_ :: P.Parser T.Text+{-# INLINE string_ #-}+string_ = do+    (bs, state) <- P.scanChunks 0 go+    let mt = case state .&. 0xFF of+            -- need escaping+            1 -> unsafeDupablePerformIO (do+                    let !len = V.length bs+                    !mpa <- newPrimArray len+                    !len' <- withMutablePrimArrayUnsafe mpa (\ mba# _ ->+                        withPrimVectorUnsafe bs (decode_json_string mba#))+                    !pa <- unsafeFreezePrimArray mpa+                    if len' >= 0+                    then pure (Just (T.Text (V.PrimVector pa 0 len')))  -- unescaping also validate utf8+                    else pure Nothing)+            3 -> Nothing    -- reject unescaped control characters+            _ -> T.validateMaybe bs+    case mt of+        Just t -> P.skipWord8 $> t+        _  -> fail "Z.Data.JSON.Value.string_: utf8 validation or unescaping failed"+  where+    go :: Word32 -> V.Bytes -> Either Word32 (V.Bytes, V.Bytes, Word32)+    go !state v =+        case unsafeDupablePerformIO . withPrimUnsafe state $ \ ps ->+                withPrimVectorUnsafe v (find_json_string_end ps)+        of (state', len)+            | len >= 0 ->+                let !r = V.unsafeTake len v+                    !rest = V.unsafeDrop len v+                in Right (r, rest, state')+            | otherwise -> Left state'++foreign import ccall unsafe find_json_string_end :: MBA# Word32 -> BA# Word8 -> Int -> Int -> IO Int+foreign import ccall unsafe decode_json_string :: MBA# Word8 -> BA# Word8 -> Int -> Int -> IO Int
+ Z/Data/Parser.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Z.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 Z.Data.Parser+  ( -- * Parser types+    Result(..)+  , ParseError+  , Parser+  , (<?>)+    -- * Running a parser+  , parse, parse_, parseChunk, parseChunks, finishParsing+  , runAndKeepTrack, match+    -- * Basic parsers+  , ensureN, endOfInput, atEnd+    -- * Primitive decoders+  , decodePrim, decodePrimLE, decodePrimBE+    -- * More parsers+  , scan, scanChunks, peekMaybe, peek, satisfy, satisfyWith+  , word8, char8, skipWord8, endOfLine, skip, skipWhile, skipSpaces+  , take, takeTill, takeWhile, takeWhile1, bytes, bytesCI+  , text+    -- * Numeric parsers+    -- ** Decimal+  , uint, int+    -- ** Hex+  , hex+    -- ** Fractional+  , rational+  , float, double+  , scientific+  , scientifically+    -- * Stricter fractional(rfc8259)+  , rational'+  , float', double'+  , scientific'+  , scientifically'+    -- * Misc+  , isSpace, isHexDigit, isDigit+  ) where++import           Z.Data.Parser.Base+import           Z.Data.Parser.Numeric+import           Prelude hiding (take, takeWhile)
+ Z/Data/Parser/Base.hs view
@@ -0,0 +1,665 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE DeriveDataTypeable  #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Z.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. Both binary parsers ('decodePrim' ,etc) and textual parsers are provided, and they all work on 'V.Bytes'.++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' or 'peekMaybe' to avoid backtracking if possible to get high performance.++Error message can be attached using '<?>', which have very small overhead, so it's recommended to attach a message in front of a composed parser like @xPacket = "Foo.Bar.xPacket" <?> do ...@, following is an example message when parsing an integer failed:++@+    >parse int "foo"+    ([102,111,111],Left ["Z.Data.Parser.Numeric.int","Std.Data.Parser.Base.takeWhile1: no satisfied byte"])+    -- It's easy to see we're trying to match a leading sign or digit here+@++-}++module Z.Data.Parser.Base+  ( -- * Parser types+    Result(..)+  , ParseError+  , ParseStep+  , Parser(..)+  , (<?>)+    -- * Running a parser+  , parse, parse_, parseChunk, parseChunks, finishParsing+  , runAndKeepTrack, match+    -- * Basic parsers+  , ensureN, endOfInput, atEnd+    -- * Primitive decoders+  , decodePrim, decodePrimLE, decodePrimBE+    -- * More parsers+  , scan, scanChunks, peekMaybe, peek, satisfy, satisfyWith+  , word8, char8, skipWord8, endOfLine, skip, skipWhile, skipSpaces+  , take, takeTill, takeWhile, takeWhile1, bytes, bytesCI+  , text+    -- * Misc+  , isSpace+  ) 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           GHC.Types+import           Prelude                            hiding (take, takeWhile)+import           Z.Data.Array.UnalignedAccess+import qualified Z.Data.Text.Base                 as T+import qualified Z.Data.Vector.Base               as V+import qualified Z.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 a          !V.Bytes+    | Failure ParseError !V.Bytes+    | Partial (ParseStep a)++-- | A parse step consumes 'V.Bytes' and produce 'Result'.+type ParseStep r = V.Bytes -> Result r++-- | Type alias for error message+type ParseError = [T.Text]++instance Functor Result where+    fmap f (Success a s)   = Success (f a) s+    fmap f (Partial k)     = Partial (fmap f . k)+    fmap _ (Failure e v)   = Failure e v++instance Show a => Show (Result a) where+    show (Success a _)    = "Success " ++ show a+    show (Partial _)      = "Partial _"+    show (Failure errs _) = "Failure: " ++ show errs+++-- | Simple CPSed parser+--+-- A parser takes a failure continuation, and a success one, while the success continuation is+-- usually composed by 'Monad' instance, the failure one is more like a reader part, which can+-- be modified via '<?>'. If you build parsers from ground, a pattern like this can be used:+--+--  @+--    xxParser = do+--      ensureN errMsg ...            -- make sure we have some bytes+--      Parser $ \ kf k inp ->        -- fail continuation, success continuation and input+--        ...+--        ... kf errMsg (if input not OK)+--        ... k ... (if we get something useful for next parser)+--  @+newtype Parser a = Parser {+        runParser :: forall r . (ParseError -> ParseStep r) -> (a -> ParseStep r) -> ParseStep r+    }++-- It seems eta-expand all params to ensure parsers are saturated is helpful+instance Functor Parser where+    fmap f (Parser pa) = Parser (\ kf k inp -> pa kf (k . f) inp)+    {-# INLINE fmap #-}+    a <$ Parser pb = Parser (\ kf k inp -> pb kf (\ _ -> k a) inp)+    {-# INLINE (<$) #-}++instance Applicative Parser where+    pure x = Parser (\ _ k inp -> k x inp)+    {-# INLINE pure #-}+    Parser pf <*> Parser pa = Parser (\ kf k inp -> pf kf (\ f -> pa kf (k . f)) inp)+    {-# INLINE (<*>) #-}+    Parser pa *> Parser pb = Parser (\ kf k inp -> pa kf (\ _ inp' -> pb kf k inp') inp)+    {-# INLINE (*>) #-}+    Parser pa <* Parser pb = Parser (\ kf k inp -> pa kf (\ x inp' -> pb kf (\ _ -> k x) inp') inp)+    {-# INLINE (<*) #-}++instance Monad Parser where+    return = pure+    {-# INLINE return #-}+    Parser pa >>= f = Parser (\ kf k inp -> pa kf (\ a -> runParser (f a) kf k) inp)+    {-# INLINE (>>=) #-}+    (>>) = (*>)+    {-# INLINE (>>) #-}++instance Fail.MonadFail Parser where+    fail = fail' . T.pack+    {-# INLINE fail #-}++instance MonadPlus Parser where+    mzero = empty+    {-# INLINE mzero #-}+    mplus = (<|>)+    {-# INLINE mplus #-}++instance Alternative Parser where+    empty = fail' "Z.Data.Parser.Base(Alternative).empty"+    {-# INLINE empty #-}+    f <|> g = do+        (r, bss) <- runAndKeepTrack f+        case r of+            Success x inp   -> Parser (\ _ k _ -> k x inp)+            Failure _ _     -> let !bs = V.concat (reverse bss)+                               in Parser (\ kf k _ -> runParser g kf k bs)+            _               -> error "Z.Data.Parser.Base: impossible"+    {-# INLINE (<|>) #-}++-- | 'T.Text' version of 'fail'.+fail' :: T.Text -> Parser a+{-# INLINE fail' #-}+fail' msg = Parser (\ kf _ inp -> kf [msg] inp)++-- | Parse the complete input, without resupplying+parse_ :: Parser a -> V.Bytes -> Either ParseError a+{-# INLINE parse_ #-}+parse_ (Parser p) inp = snd $ finishParsing (p Failure Success inp)++-- | Parse the complete input, without resupplying, return the rest bytes+parse :: Parser a -> V.Bytes -> (V.Bytes, Either ParseError a)+{-# INLINE parse #-}+parse (Parser p) inp = finishParsing (p Failure Success inp)++-- | Parse an input chunk+parseChunk :: Parser a -> V.Bytes -> Result a+{-# INLINE parseChunk #-}+parseChunk (Parser p) = p Failure Success++-- | Finish parsing and fetch result, feed empty bytes if it's 'Partial' result.+finishParsing :: Result a -> (V.Bytes, Either ParseError a)+{-# INLINABLE finishParsing #-}+finishParsing r = case r of+    Success a rest    -> (rest, Right a)+    Failure errs rest -> (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 => Parser a -> m V.Bytes -> V.Bytes -> m (V.Bytes, Either ParseError a)+{-# INLINABLE parseChunks #-}+parseChunks (Parser p) m0 inp = go m0 (p Failure Success inp)+  where+    go m r = case r of+        Partial f -> do+            inp' <- m+            if V.null inp'+            then go (pure V.empty) (f V.empty)+            else go m (f inp')+        Success a rest    -> pure (rest, Right a)+        Failure errs rest -> pure (rest, Left errs)++(<?>) :: T.Text -> Parser a -> Parser a+{-# INLINE (<?>) #-}+msg <?> (Parser p) = Parser (\ kf k inp -> p (kf . (msg:)) k inp)+infixr 0 <?>++-- | Run a parser and keep track of all the input chunks 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 inp ->+    let go !acc r k = case r of+            Partial k'      -> Partial (\ inp' -> go (inp':acc) (k' inp') k)+            Success _ inp' -> k (r, reverse acc) inp'+            Failure _ inp' -> k (r, reverse acc) inp'+        r0 = pa Failure Success inp+    in go [inp] r0 k0++-- | Return both the result of a parse and the portion of the input+-- that was consumed while it was being parsed.+match :: Parser a -> Parser (V.Bytes, a)+{-# INLINE match #-}+match p = do+    (r, bss) <- runAndKeepTrack p+    Parser (\ _ k _ ->+        case r of+            Success r' inp'  -> let !consumed = V.dropR (V.length inp') (V.concat (reverse bss))+                                in k (consumed , r') inp'+            Failure err inp' -> Failure err inp'+            Partial _        -> error "Z.Data.Parser.Base.match: impossible")++-- | Ensure that there are at least @n@ bytes available. If not, the+-- computation will escape with 'Partial'.+--+-- Since this parser is used in many other parsers, an extra error param is provide+-- to attach custom error info.+ensureN :: Int -> ParseError -> Parser ()+{-# INLINE ensureN #-}+ensureN n0 err = Parser $ \ kf k inp -> do+    let l = V.length inp+    if l >= n0+    then k () inp+    else Partial (ensureNPartial l inp kf k)+  where+    {-# INLINABLE ensureNPartial #-}+    ensureNPartial l0 inp0 kf k =+        let go acc !l = \ inp -> do+                let l' = V.length inp+                if l' == 0+                then kf err (V.concat (reverse (inp:acc)))+                else do+                    let l'' = l + l'+                    if l'' < n0+                    then Partial (go (inp:acc) l'')+                    else+                        let !inp' = V.concat (reverse (inp:acc))+                        in k () inp'+        in go [inp0] l0++-- | Test whether all input has been consumed, i.e. there are no remaining+-- undecoded bytes. Fail if not 'atEnd'.+endOfInput :: Parser ()+{-# INLINE endOfInput #-}+endOfInput = Parser $ \ kf k inp ->+    if V.null inp+    then Partial (\ inp' ->+        if (V.null inp')+        then k () inp'+        else kf ["Z.Data.Parser.Base.endOfInput: end not reached yet"] inp)+    else kf ["Z.Data.Parser.Base.endOfInput: end not reached yet"] inp++-- | Test whether all input has been consumed, i.e. there are no remaining+-- undecoded bytes.+atEnd :: Parser Bool+{-# INLINE atEnd #-}+atEnd = 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 ["Z.Data.Parser.Base.decodePrim: not enough bytes"]+    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 = do+    ensureN n ["Z.Data.Parser.Base.decodePrimLE: not enough bytes"]+    Parser (\ _ k (V.PrimVector (A.PrimArray ba#) i@(I# i#) len) ->+        let !r = indexWord8ArrayAs ba# i#+        in k (getLE r) (V.PrimVector (A.PrimArray ba#) (i+n) (len-n)))+  where+    n = getUnalignedSize (unalignedSize :: UnalignedSize (LE a))++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 = do+    ensureN n ["Z.Data.Parser.Base.decodePrimBE: not enough bytes"]+    Parser (\ _ k (V.PrimVector (A.PrimArray ba#) i@(I# i#) len) ->+        let !r = indexWord8ArrayAs ba# i#+        in k (getBE r) (V.PrimVector (A.PrimArray ba#) (i+n) (len-n)))+  where+    n = getUnalignedSize (unalignedSize :: UnalignedSize (BE a))++-- | 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, s)+{-# INLINE scan #-}+scan s0 f = scanChunks s0 f'+  where+    f' s0' (V.PrimVector arr off l) =+        let !end = off + l+            go !st !i+                | i < end = do+                    let !w = A.indexPrimArray arr i+                    case f st w of+                        Just st' -> go st' (i+1)+                        _        ->+                            let !len1 = i - off+                                !len2 = end - off+                            in Right (V.PrimVector arr off len1, V.PrimVector arr i len2, st)+                | otherwise = Left st+        in go s0' off++-- | 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, s)) -> Parser (V.Bytes, s)+{-# INLINE scanChunks #-}+scanChunks s0 consume = Parser (\ _ k inp ->+    case consume s0 inp of+        Right (want, rest, s') -> k (want, s') rest+        Left s' -> Partial (scanChunksPartial s' k inp))+  where+    -- we want to inline consume if possible+    {-# INLINABLE scanChunksPartial #-}+    scanChunksPartial s0' k inp0 =+        let go s acc = \ inp ->+                if V.null inp+                then k (V.concat (reverse acc), s) inp+                else case consume s inp of+                        Left s' -> do+                            let acc' = inp : acc+                            Partial (go s' acc')+                        Right (want,rest,s') ->+                            let !r = V.concat (reverse (want:acc)) in k (r, s') rest+        in go s0' [inp0]++--------------------------------------------------------------------------------++-- | 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 =+    Parser $ \ _ k inp ->+        if V.null inp+        then Partial (\ inp' -> k (if V.null inp'+            then Nothing+            else Just (V.unsafeHead inp)) inp')+        else k (Just (V.unsafeHead inp)) inp++-- | 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 =+    Parser $ \ kf k inp ->+        if V.null inp+        then Partial (\ inp' ->+            if V.null inp'+            then kf ["Z.Data.Parser.Base.peek: not enough bytes"] inp'+            else k (V.unsafeHead inp') inp')+        else 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 ["Z.Data.Parser.Base.satisfy: not enough bytes"]+    Parser $ \ kf k inp ->+        let w = V.unsafeHead inp+        in if p w+            then k w (V.unsafeTail inp)+            else kf ["Z.Data.Parser.Base.satisfy: unsatisfied byte"] (V.unsafeTail inp)++-- | 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 ["Z.Data.Parser.Base.satisfyWith: not enough bytes"]+    Parser $ \ kf k inp ->+        let a = f (V.unsafeHead inp)+        in if p a+            then k a (V.unsafeTail inp)+            else kf ["Z.Data.Parser.Base.satisfyWith: unsatisfied byte"] (V.unsafeTail inp)++-- | Match a specific byte.+--+word8 :: Word8 -> Parser ()+{-# INLINE word8 #-}+word8 w' = do+    ensureN 1 ["Z.Data.Parser.Base.word8: not enough bytes"]+    Parser (\ kf k inp ->+        let w = V.unsafeHead inp+        in if w == w'+            then k () (V.unsafeTail inp)+            else kf ["Z.Data.Parser.Base.word8: mismatch byte"] inp)++-- | Match a specific 8bit char.+--+char8 :: Char -> Parser ()+{-# INLINE char8 #-}+char8 = word8 . V.c2w+++-- | 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 "Z.Data.Parser.Base.endOfLine: mismatch byte"++--------------------------------------------------------------------------------++-- | 'skip' N bytes.+--+skip :: Int -> Parser ()+{-# INLINE skip #-}+skip n =+    Parser (\ kf k inp ->+        let l = V.length inp+            !n' = max n 0+        in if l >= n'+            then k () $! V.unsafeDrop n' inp+            else Partial (skipPartial (n'-l) kf k))++skipPartial :: Int -> (ParseError -> ParseStep r) -> (() -> ParseStep r) -> ParseStep r+{-# INLINABLE skipPartial #-}+skipPartial n kf k =+    let go !n' = \ inp ->+            let l = V.length inp+            in if l >= n'+                then k () $! V.unsafeDrop n' inp+                else if l == 0+                    then kf ["Z.Data.Parser.Base.skip: not enough bytes"] inp+                    else Partial (go (n'-l))+    in go n++-- | Skip a byte.+--+skipWord8 :: Parser ()+{-# INLINE skipWord8 #-}+skipWord8 =+    Parser $ \ kf k inp ->+        if V.null inp+        then Partial (\ inp' ->+            if V.null inp'+            then kf ["Z.Data.Parser.Base.skipWord8: not enough bytes"] inp'+            else k () (V.unsafeTail inp'))+        else k () (V.unsafeTail inp)++-- | 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 (skipWhilePartial k)+            else k () rest)+  where+    -- we want to inline p if possible+    {-# INLINABLE skipWhilePartial #-}+    skipWhilePartial k =+        let go = \ inp ->+                if V.null inp+                then k () inp+                else+                    let !rest = V.dropWhile p inp+                    in if V.null rest then Partial go else k () rest+        in go++-- | Skip over white space using 'isSpace'.+--+skipSpaces :: Parser ()+{-# INLINE skipSpaces #-}+skipSpaces = skipWhile isSpace++-- | @isSpace w = w == 32 || w - 9 <= 4 || w == 0xA0@+isSpace :: Word8 -> Bool+{-# INLINE isSpace #-}+isSpace w = w == 32 || w - 9 <= 4 || w == 0xA0++take :: Int -> Parser V.Bytes+{-# INLINE take #-}+take n = do+    -- we use unsafe slice, guard negative n here+    ensureN n' ["Z.Data.Parser.Base.take: not enough bytes"]+    Parser (\ _ k inp ->+        let !r = V.unsafeTake n' inp+            !inp' = V.unsafeDrop n' inp+        in k r inp')+  where !n' = max 0 n++-- | 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 (takeTillPartial k want)+        else k want rest)+  where+    {-# INLINABLE takeTillPartial #-}+    takeTillPartial k want =+        let go acc = \ inp ->+                if V.null inp+                then let !r = V.concat (reverse acc) in k r inp+                else+                    let (want', rest) = V.break p inp+                        acc' = want' : acc+                    in if V.null rest+                        then Partial (go acc')+                        else let !r = V.concat (reverse acc') in k r rest+        in go [want]++-- | 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 (takeWhilePartial k want)+        else k want rest)+  where+    -- we want to inline p if possible+    {-# INLINABLE takeWhilePartial #-}+    takeWhilePartial k want =+        let go acc = \ inp ->+                if V.null inp+                then let !r = V.concat (reverse acc) in k r inp+                else+                    let (want', rest) = V.span p inp+                        acc' = want' : acc+                    in if V.null rest+                        then Partial (go acc')+                        else let !r = V.concat (reverse acc') in k r rest+        in go [want]++-- | 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 "Z.Data.Parser.Base.takeWhile1: no satisfied byte"+    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+    ensureN n ["Z.Data.Parser.Base.bytes: not enough bytes"]+    Parser (\ kf k inp ->+        if bs == V.unsafeTake n inp+        then k () $! V.unsafeDrop n inp+        else kf ["Z.Data.Parser.Base.bytes: mismatch bytes"] inp)+++-- | Same as 'bytes' but ignoring case.+bytesCI :: V.Bytes -> Parser ()+{-# INLINE bytesCI #-}+bytesCI bs = do+    let n = V.length bs+    -- casefold an ASCII string should not change it's length+    ensureN n ["Z.Data.Parser.Base.bytesCI: not enough bytes"]+    Parser (\ kf k inp ->+        if bs' == CI.foldCase (V.unsafeTake n inp)+        then k () $! V.unsafeDrop n inp+        else kf ["Z.Data.Parser.Base.bytesCI: mismatch bytes"] inp)+  where+    bs' = CI.foldCase bs++-- | @text s@ parses a sequence of UTF8 bytes that identically match @s@.+--+text :: T.Text -> Parser ()+{-# INLINE text #-}+text (T.Text bs) = bytes bs
+ Z/Data/Parser/Numeric.hs view
@@ -0,0 +1,398 @@+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications  #-}+{-# LANGUAGE CPP               #-}++{-|+Module      : Z.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 Z.Data.Parser.Numeric+  ( -- * Decimal+    uint, int+    -- * Hex+  , hex+    -- * Fractional+  , rational+  , float, double+  , scientific+  , scientifically+    -- * Stricter fractional(rfc8259)+  , rational'+  , float', double'+  , scientific'+  , scientifically'+    -- * Misc+  , hexLoop+  , decLoop+  , decLoopIntegerFast+  , isHexDigit+  , isDigit+  , floatToScientific+  , doubleToScientific+  ) where++import           Control.Applicative+import           Control.Monad+import           Data.Bits+import           Data.Int+import qualified Data.Scientific          as Sci+import           Data.Word+import           Foreign.Ptr              (IntPtr)+import qualified Z.Data.Builder.Numeric as B+import           Z.Data.Parser.Base     (Parser, (<?>))+import qualified Z.Data.Parser.Base     as P+import qualified Z.Data.Vector.Base     as V+import qualified Z.Data.Vector.Extra    as V++#define WORD64_MAX_DIGITS_LEN 18++#define PLUS     43+#define MINUS    45+#define DOT      46+#define LITTLE_E 101+#define BIG_E    69+#define C_0 48++-- | 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 Integer #-}+{-# SPECIALIZE INLINE hex :: Parser IntPtr #-}+hex = "Z.Data.Parser.Numeric.hex" <?> hexLoop 0 <$> P.takeWhile1 isHexDigit++-- | decode hex digits sequence within an array.+hexLoop :: (Integral a, Bits a)+        => a    -- ^ accumulator, usually start from 0+        -> V.Bytes+        -> a+{-# INLINE hexLoop #-}+hexLoop = V.foldl' step+  where+    step a w = a `unsafeShiftL` 4 + fromIntegral (w2iHex w)+    w2iHex w+        | w <= 57   = w - 48+        | w <= 70   = w - 55+        | w <= 102  = w - 87++-- | A fast digit predicate.+isHexDigit :: Word8 -> Bool+{-# INLINE isHexDigit #-}+isHexDigit w = w - 48 <= 9 || w - 65 <= 5 || w - 97 <= 5++-- | 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  #-}+{-# SPECIALIZE INLINE uint :: Parser Integer #-}+uint = "Z.Data.Parser.Numeric.uint" <?> decLoop 0 <$> P.takeWhile1 isDigit++-- | decode digits sequence within an array.+decLoop :: Integral a+        => a    -- ^ accumulator, usually start from 0+        -> V.Bytes+        -> a+{-# INLINE decLoop #-}+decLoop = V.foldl' step+  where step a w = a * 10 + fromIntegral (w - 48)++-- | decode digits sequence within an array.+--+-- A fast version to decode 'Integer' using machine word as much as possible.+decLoopIntegerFast :: V.Bytes -> Integer+{-# INLINE decLoopIntegerFast #-}+decLoopIntegerFast bs+    | V.length bs <= WORD64_MAX_DIGITS_LEN = fromIntegral (decLoop @Word64 0 bs)+    | otherwise                            = decLoop @Integer 0 bs++-- | A fast digit predicate.+isDigit :: Word8 -> Bool+isDigit w = w - 48 <= 9+{-# INLINE isDigit #-}++-- | 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  #-}+{-# SPECIALIZE INLINE int :: Parser Integer #-}+int = "Z.Data.Parser.Numeric.int" <?> do+    w <- P.peek+    if w == MINUS+    then P.skipWord8 *> (negate <$> uint')+    else if w == PLUS then P.skipWord8 *> uint' else uint'+  where+    -- strip uint's message+    uint' = decLoop 0 <$> P.takeWhile1 isDigit++-- | 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 = "Z.Data.Parser.Numeric.rational" <?> scientificallyInternal 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':+--+-- >parse_ double "3"     == ("", Right 3.0)+-- >parse_ double "3.1"   == ("", Right 3.1)+-- >parse_ double "3e4"   == ("", Right 30000.0)+-- >parse_ double "3.1e4" == ("", Right 31000.0)+--+-- >parse_ double ".3"    == (".3", Left ParserError)+-- >parse_ double "e3"    == ("e3", Left ParserError)+--+-- Examples of differences from 'read':+--+-- >parse_ double "3.foo" == (".foo", Right 3.0)+-- >parse_ double "3e"    == ("e",    Right 3.0)+-- >parse_ double "-3e"   == ("e",    Right -3.0)+--+-- This function does not accept string representations of \"NaN\" or+-- \"Infinity\".+--+double :: Parser Double+{-# INLINE double #-}+double = "Z.Data.Parser.Numeric.double" <?> scientificallyInternal Sci.toRealFloat++-- | Parse a rational number and round to 'Float'.+--+-- Single precision version of 'double'.+float :: Parser Float+{-# INLINE float #-}+float = "Z.Data.Parser.Numeric.float" <?> scientificallyInternal 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 = "Z.Data.Parser.Numeric.scientific" <?> scientificallyInternal 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 = "Z.Data.Parser.Numeric.scientifically" <?> scientificallyInternal h++-- | Strip message version.+scientificallyInternal :: (Sci.Scientific -> a) -> Parser a+{-# INLINE scientificallyInternal #-}+scientificallyInternal h = do+    !sign <- P.peek+    when (sign == PLUS || sign == MINUS) (P.skipWord8)+    !intPart <- P.takeWhile1 isDigit+    -- backtrack here is neccessary to avoid eating extra dot or e+    -- attoparsec is doing it wrong here: https://github.com/bos/attoparsec/issues/112+    !sci <- (do+        -- during number parsing we want to use machine word as much as possible+        -- so as long as range permit, we use Word64 instead of final Integer+        !fracPart <- P.word8 DOT *> P.takeWhile1 isDigit+        let !ilen = V.length intPart+            !flen = V.length fracPart+            !base =+                if ilen + flen <= WORD64_MAX_DIGITS_LEN+                then fromIntegral (decLoop @Word64 (decLoop @Word64 0 intPart) fracPart)+                else+                    let i = decLoopIntegerFast intPart+                        f = decLoopIntegerFast fracPart+                    in i * 10 ^ flen + f+        parseE base flen) <|> (parseE (decLoopIntegerFast intPart) 0)++    pure $! if sign /= MINUS then h sci else h (negate sci)+  where+    {-# INLINE parseE #-}+    parseE c e =+        (do _ <- P.satisfy (\w -> w ==  LITTLE_E || w == BIG_E)+            Sci.scientific c . subtract e <$> int) <|> pure (Sci.scientific c (negate e))++--------------------------------------------------------------------------------++-- | 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' = "Z.Data.Parser.Numeric.rational'" <?> scientificallyInternal' realToFrac++-- | More strict number parsing(rfc8259).+--+-- 'scientific' support parse @2314.@ and @21321exyz@ without eating extra dot or @e@ via+-- backtrack, this is not allowed in some strict grammer such as JSON, so we make an+-- non-backtrack strict number parser separately using LL(1) lookahead. This parser also+-- agree with 'read' on extra dot or e handling:+--+-- >parse_ double "3.foo" == Left ParseError+-- >parse_ double "3e"    == Left ParseError+--+-- Leading zeros or @+@ sign is also not allowed:+--+-- >parse_ double "+3.14" == Left ParseError+-- >parse_ double "0014" == Left ParseError+--+-- If you have a similar grammer, you can use this parser to save considerable time.+--+-- @+--      number = [ minus ] int [ frac ] [ exp ]+--      decimal-point = %x2E       ; .+--      digit1-9 = %x31-39         ; 1-9+--      e = %x65 / %x45            ; e E+--      exp = e [ minus / plus ] 1*DIGIT+--      frac = decimal-point 1*DIGIT+-- @+--+-- This function does not accept string representations of \"NaN\" or+-- \"Infinity\".+-- reference: https://tools.ietf.org/html/rfc8259#section-6+double' :: Parser Double+{-# INLINE double' #-}+double' = "Z.Data.Parser.Numeric.double'" <?> scientificallyInternal' Sci.toRealFloat++-- | Parse a rational number and round to 'Float' using stricter grammer.+--+-- Single precision version of 'double''.+float' :: Parser Float+{-# INLINE float' #-}+float' = "Z.Data.Parser.Numeric.float'" <?> scientificallyInternal' 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' = "Z.Data.Parser.Numeric.scientific'" <?> scientificallyInternal' 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) -> P.Parser a+{-# INLINE scientifically' #-}+scientifically' h = "Z.Data.Parser.Numeric.scientifically'" <?> scientificallyInternal' h++-- | Strip message version of scientifically'.+scientificallyInternal' :: (Sci.Scientific -> a) -> P.Parser a+{-# INLINE scientificallyInternal' #-}+scientificallyInternal' h = do+    !sign <- P.peek+    when (sign == MINUS) (P.skipWord8) -- no leading plus is allowed+    !intPart <- P.takeWhile1 isDigit+    when (V.length intPart > 1 && V.head intPart == C_0) (fail "leading zeros are not allowed")+    mdot <- P.peekMaybe+    !sci <- case mdot of+        Just DOT -> do+            !fracPart <- P.skipWord8 *> P.takeWhile1 isDigit+            -- during number parsing we want to use machine word as much as possible+            -- so as long as range permit, we use Word64 instead of final Integer+            let !ilen = V.length intPart+                !flen = V.length fracPart+                !base =+                    if ilen + flen <= WORD64_MAX_DIGITS_LEN+                    then fromIntegral (decLoop @Word64 (decLoop @Word64 0 intPart) fracPart)+                    else+                        let i = decLoopIntegerFast intPart+                            f = decLoopIntegerFast fracPart+                        in i * 10 ^ flen + f+            parseE base flen+        _ -> parseE (decLoopIntegerFast intPart) 0+    pure $! if sign /= MINUS then h sci else h (negate sci)+  where+    {-# INLINE parseE #-}+    parseE !c !e = do+        me <- P.peekMaybe+        e' <- case me of+            Just ec | ec == LITTLE_E || ec == BIG_E -> P.skipWord8 *> int+            _ -> pure 0+        pure $! Sci.scientific c (e' - e)++--------------------------------------------------------------------------------++floatToScientific :: Float -> Sci.Scientific+{-# INLINE floatToScientific #-}+floatToScientific rf | rf < 0    = -(fromFloatingDigits (B.grisu3_sp (-rf)))+                     | rf == 0   = 0+                     | otherwise = fromFloatingDigits (B.grisu3_sp rf)++doubleToScientific :: Double -> Sci.Scientific+{-# INLINE doubleToScientific #-}+doubleToScientific rf | rf < 0    = -(fromFloatingDigits (B.grisu3 (-rf)))+                      | rf == 0   = 0+                      | otherwise = fromFloatingDigits (B.grisu3 rf)++fromFloatingDigits :: ([Int], Int) -> Sci.Scientific+{-# INLINE fromFloatingDigits #-}+fromFloatingDigits (digits, e) = go digits 0 0+  where+    -- There's no way a float or double has more digits a 'Int64' can't handle+    go :: [Int] -> Int64 -> Int -> Sci.Scientific+    go []     !c !n = Sci.scientific (fromIntegral c) (e - n)+    go (d:ds) !c !n = go ds (c * 10 + fromIntegral d) (n + 1)
+ Z/Data/PrimRef.hs view
@@ -0,0 +1,51 @@+{-|+Module      :  Z.Data.PrimRef+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 and 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).+-}++module Z.Data.PrimRef+  ( -- * Unboxed ST references+    PrimSTRef+  , newPrimSTRef+  , readPrimSTRef+  , writePrimSTRef+  , modifyPrimSTRef+  , -- * 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 Z.Data.PrimRef.PrimSTRef+import Z.Data.PrimRef.PrimIORef
+ Z/Data/PrimRef/PrimIORef.hs view
@@ -0,0 +1,197 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE BangPatterns #-}++{-|+Module      :  Z.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 Z.Data.PrimRef.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.IO(stToIO)+import Z.Data.PrimRef.PrimSTRef++-- | 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 x = PrimIORef `fmap` stToIO (newPrimSTRef x)+{-# 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#, _ #) = 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#, _ #) = 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#, _ #) = 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#, _ #) = fetchXorIntArray# mba# 0# x# s1# in (# s2#, () #)+{-# INLINE atomicXorCounter_ #-}
+ Z/Data/PrimRef/PrimSTRef.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE MagicHash #-}++{-|+Module      :  Z.Data.PrimRef.PrimSTRef+Copyright   :  (c) Dong Han 2017~2019+License     :  BSD-style++Maintainer  :  winterland1989@gmail.com+Stability   :  experimental+Portability :  portable++This package 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 Z.Data.PrimRef.PrimSTRef+  ( -- * Unboxed ST references+    PrimSTRef(..)+  , newPrimSTRef+  , readPrimSTRef+  , writePrimSTRef+  , modifyPrimSTRef+  ) where++import Data.Primitive.Types+import Data.Primitive.ByteArray+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 x = do+     mba <- newByteArray (I# (sizeOf# x))+     writeByteArray mba 0 x+     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 #-}
+ Z/Data/Text.hs view
@@ -0,0 +1,149 @@+{-# LANGUAGE MagicHash, UnboxedTuples #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE UnliftedFFITypes #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE PatternSynonyms #-}++{-|+Module      : Z.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 Z.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           Z.Data.Text.Base+import           Z.Data.Text.Search+import           Z.Data.Text.Extra+import           Prelude                  ()++
+ Z/Data/Text/Base.hs view
@@ -0,0 +1,1005 @@+{-# LANGUAGE MagicHash, UnboxedTuples #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE UnliftedFFITypes #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE CPP #-}++{-|+Module      : Z.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 Z.Data.Text.Base (+  -- * Text type+    Text(..)+  -- * Building text+  , validate+  , InvalidUTF8Exception(..)+  , 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.Exception+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.Word+import           Foreign.C.Types          (CSize(..))+import           GHC.Exts+import           GHC.Types+import           GHC.Stack+import           GHC.CString              (unpackCString#, unpackCStringUtf8#)+import           Z.Data.Array+import           Z.Data.Text.UTF8Codec+import           Z.Data.Text.UTF8Rewind+import           Z.Data.Vector.Base     (Bytes, PrimVector(..), c_strlen)+import qualified Z.Data.Vector.Base     as V+import qualified Z.Data.Vector.Search   as V+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)++import           Test.QuickCheck.Arbitrary (Arbitrary(..), CoArbitrary(..))++-- | 'Text' represented as UTF-8 encoded 'Bytes'+--+newtype Text = Text+    { getUTF8Bytes :: Bytes -- ^ Extract UTF-8 encoded 'Bytes' from 'Text'+    } deriving (Semigroup, Monoid, Typeable)++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 Arbitrary Text where+    arbitrary = pack <$> arbitrary+    shrink a = pack <$> shrink (unpack a)++instance CoArbitrary Text where+    coarbitrary = coarbitrary . unpack++instance Hashable Text where+    {-# INLINE hashWithSalt #-}+    hashWithSalt salt (Text bs) = hashWithSalt salt bs++instance IsString Text where+    {-# INLINE fromString #-}+    fromString = pack++packASCIIAddr :: Addr# -> Text+packASCIIAddr addr0# = go addr0#+  where+    len = fromIntegral . unsafeDupablePerformIO $ c_strlen addr0#+    go addr# = runST $ do+        marr <- newPrimArray len+        copyPtrToMutablePrimArray marr 0 (Ptr addr#) len+        arr <- unsafeFreezePrimArray marr+        return $ Text (PrimVector arr 0 len)++packUTF8Addr :: Addr# -> Text+packUTF8Addr addr0# = validateAndCopy addr0#+  where+    len = fromIntegral . unsafeDupablePerformIO $ c_strlen addr0#+    valid = unsafeDupablePerformIO $ c_utf8_validate_addr addr0# len+    validateAndCopy addr#+        | valid == 0 = packN len (unpackCStringUtf8# addr#) -- three bytes surrogate -> three bytes replacement+                                                        -- two bytes NUL -> \NUL+                                                        -- the result's length will either smaller or equal+        | 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 'InvalidUTF8Exception' 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 = throw (InvalidUTF8Exception callStack)++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 :: ByteArray# -> Int# -> Int# -> Int+foreign import ccall unsafe "text.h utf8_validate_addr"+    c_utf8_validate_addr :: Addr# -> Int -> IO Int++data InvalidUTF8Exception = InvalidUTF8Exception CallStack+                    deriving (Show, Typeable)+instance Exception InvalidUTF8Exception++--------------------------------------------------------------------------------++-- | /O(n)/ Convert a string into a text+--+-- Alias for @'packN' 'defaultInitSize'@, will be rewritten to a memcpy if possible.+pack :: String -> Text+pack = packN V.defaultInitSize+{-# INLINE CONLIKE [0] pack #-}+{-# RULES "pack/packASCIIAddr" forall addr . pack (unpackCString# addr) = packASCIIAddr addr #-}+{-# RULES "pack/packUTF8Addr" forall addr . pack (unpackCStringUtf8# addr) = packUTF8Addr 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 >= end = 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 >= end = 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 ::+    ByteArray# -> Int# -> Int# -> CSize -> Int+foreign import ccall unsafe utf8_normalize ::+    ByteArray# -> Int# -> Int# -> MutableByteArray# RealWorld -> Int# -> CSize -> IO ()+foreign import ccall unsafe utf8_normalize_length ::+    ByteArray# -> 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 ::+    ByteArray# -> Int# -> Int# -> MutableByteArray# RealWorld -> Int# -> Locale -> IO ()+foreign import ccall unsafe utf8_casefold_length ::+    ByteArray# -> Int# -> Int# -> Locale -> Int++foreign import ccall unsafe utf8_tolower ::+    ByteArray# -> Int# -> Int# -> MutableByteArray# RealWorld -> Int# -> Locale -> IO ()+foreign import ccall unsafe utf8_tolower_length ::+    ByteArray# -> Int# -> Int# -> Locale -> Int++foreign import ccall unsafe utf8_toupper ::+    ByteArray# -> Int# -> Int# -> MutableByteArray# RealWorld -> Int# -> Locale -> IO ()+foreign import ccall unsafe utf8_toupper_length ::+    ByteArray# -> Int# -> Int# -> Locale -> Int++foreign import ccall unsafe utf8_totitle ::+    ByteArray# -> Int# -> Int# -> MutableByteArray# RealWorld -> Int# -> Locale -> IO ()+foreign import ccall unsafe utf8_totitle_length ::+    ByteArray# -> 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 (PrimArray arr#) (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 :: ByteArray# -> Int# -> Int# -> Category -> Int
+ Z/Data/Text/Builder.hs view
@@ -0,0 +1,591 @@+{-# LANGUAGE CPP                        #-}+{-# LANGUAGE DataKinds                  #-}+{-# LANGUAGE DefaultSignatures          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE TypeOperators              #-}+{-# LANGUAGE StandaloneDeriving         #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE OverloadedStrings          #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE DerivingStrategies         #-}+{-# LANGUAGE DeriveAnyClass             #-}++{-|+Module      : Z.Data.Text.Builder+Description : UTF8 compatible builders.+Copyright   : (c) Dong Han, 2017-2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++Base on UTF8 compatible textual builders from 'Z.Data.Builder', we provide a newtype wrapper+'TextBuilder' which can be directly used to build 'Text'.++We also provide faster alternative to 'Show' class, i.e. 'ToText', which also provides 'Generic'+based instances deriving.++-}++module Z.Data.Text.Builder+  ( -- * ToText class+  ToText(..), toText, toBuilder, toBytes, toString+  -- * Str newtype+  , Str(..)+  -- * Textual Builder+  , TextBuilder+  , getBuilder+  , unsafeFromBuilder+  , 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+  -- * Builder helpers+  , paren, parenWhen, curly, square, angle, quotes, squotes, colon, comma, intercalateVec, intercalateList+  ) where++import           Control.Monad+import qualified Data.Scientific          as Sci+import           Data.String+import           Data.Bits+import           Data.Data                (Data(..))+import           Data.Fixed+import           Data.Functor.Compose+import           Data.Functor.Const+import           Data.Functor.Identity+import           Data.Functor.Product+import           Data.Functor.Sum+import           Data.Int+import           Data.List.NonEmpty           (NonEmpty (..))+import qualified Data.Monoid                  as Monoid+import           Data.Proxy                   (Proxy (..))+import           Data.Ratio                   (Ratio, numerator, denominator)+import           Data.Tagged                  (Tagged (..))+import           Data.Word+import qualified Data.Semigroup               as Semigroup+import           Data.Typeable+import           GHC.Natural+import           GHC.Generics+import           Data.Version+import           Data.Primitive.Types+import qualified Z.Data.Builder         as B+import qualified Z.Data.Text.Base       as T+import           Z.Data.Text.Base       (Text(..))+import qualified Z.Data.Vector.Base     as V+import           Text.Read                (Read(..))+import           Test.QuickCheck.Arbitrary (Arbitrary(..), CoArbitrary(..))++-- | 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, there's a rewrite rule to+-- turn encoding loop into a memcpy, which is much faster (the same rule also apply to 'stringUTF8').+-- Different from @Builder ()@, @TextBuilder ()@'s 'IsString' instance will give you desired UTF8 guarantees:+--+-- * @\NUL@ will be written directly as @\x00@.+--+-- * @\xD800@ ~ @\xDFFF@ will be replaced by replacement char.+--+newtype TextBuilder a = TextBuilder { getBuilder :: B.Builder a }+    deriving newtype (Functor, Applicative, Monad)++deriving newtype instance Semigroup (TextBuilder ())+deriving newtype instance Monoid (TextBuilder ())++instance (a ~ ()) => IsString (TextBuilder a) where+    {-# INLINE fromString #-}+    fromString = TextBuilder <$> B.stringUTF8++instance Arbitrary (TextBuilder ()) where+    arbitrary = TextBuilder . B.text <$> arbitrary+    shrink b = TextBuilder . B.text <$> shrink (buildText b)++instance CoArbitrary (TextBuilder ()) where+    coarbitrary = coarbitrary . buildText++instance Show (TextBuilder a) where+    show = show . buildText++instance ToText (TextBuilder a) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ b = quotes (void b)++-- | Build a 'Text' using 'TextBuilder', which provide UTF-8 encoding guarantee.+buildText :: TextBuilder a -> Text+{-# INLINE buildText #-}+buildText = Text . B.buildBytes . getBuilder++-- | Unsafely turn a 'B.Builder' into 'TextBuilder', thus it's user's responsibility to+-- ensure only UTF-8 complied bytes are written.+unsafeFromBuilder :: B.Builder a -> TextBuilder a+{-# INLINE unsafeFromBuilder #-}+unsafeFromBuilder = TextBuilder++--------------------------------------------------------------------------------++-- | 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 'T.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 -> 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)++--------------------------------------------------------------------------------++-- | add @(...)@ to original builder.+paren :: TextBuilder () -> TextBuilder ()+{-# INLINE paren #-}+paren (TextBuilder b) = TextBuilder (B.paren b)++-- | Add "(..)" around builders when condition is met, otherwise add nothing.+--+-- This is useful when defining 'ToText' instances.+parenWhen :: Bool -> TextBuilder () -> TextBuilder ()+{-# INLINE parenWhen #-}+parenWhen True b = paren b+parenWhen _    b = b++-- | add @{...}@ to original builder.+curly :: TextBuilder () -> TextBuilder ()+{-# INLINE curly #-}+curly (TextBuilder b) = TextBuilder (B.curly b)++-- | add @[...]@ to original builder.+square :: TextBuilder () -> TextBuilder ()+{-# INLINE square #-}+square (TextBuilder b) = TextBuilder (B.square b)++-- | add @<...>@ to original builder.+angle :: TextBuilder () -> TextBuilder ()+{-# INLINE angle #-}+angle (TextBuilder b) = TextBuilder (B.angle b)++-- | add @"..."@ to original builder.+quotes :: TextBuilder () -> TextBuilder ()+{-# INLINE quotes #-}+quotes (TextBuilder b) = TextBuilder (B.quotes b)++-- | add @'...'@ to original builder.+squotes :: TextBuilder () -> TextBuilder ()+{-# INLINE squotes #-}+squotes (TextBuilder b) = TextBuilder (B.squotes b)++-- | write an ASCII @:@+colon ::  TextBuilder ()+{-# INLINE colon #-}+colon = TextBuilder B.colon++-- | write an ASCII @,@+comma ::  TextBuilder ()+{-# INLINE comma #-}+comma = TextBuilder B.comma++-- | Use separator to connect a vector of builders.+intercalateVec :: (V.Vec v a)+               => TextBuilder ()            -- ^ the seperator+               -> (a -> TextBuilder ())     -- ^ value formatter+               -> v a                       -- ^ value list+               ->  TextBuilder ()+{-# INLINE intercalateVec #-}+intercalateVec (TextBuilder s) f = TextBuilder . B.intercalateVec s (getBuilder . f)++-- | Use separator to connect a list of builders.+intercalateList :: TextBuilder ()           -- ^ the seperator+                -> (a -> TextBuilder ())    -- ^ value formatter+                -> [a]                      -- ^ value vector+                -> TextBuilder ()+{-# INLINE intercalateList #-}+intercalateList (TextBuilder s) f = TextBuilder . B.intercalateList s (getBuilder . f)++--------------------------------------------------------------------------------+-- | Newtype wrapper for @[Char]@ to provide textual instances.+--+-- To encourage using 'Text' as the textual representation, we didn't provide special+-- treatment to differentiate instances between @[a]@ and @[Char]@ in various places.+-- This newtype is therefore to provide instances similar to @T.Text@, in case you really+-- need to wrap a 'String'.+newtype Str = Str { chrs :: [Char] } deriving stock (Eq, Ord, Data, Typeable, Generic)++instance Show Str where show = show . chrs+instance Read Str where readPrec = Str <$> readPrec++instance ToText Str where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ = TextBuilder . B.string8 . show++--------------------------------------------------------------------------------+-- Data types+--+-- | A class similar to 'Show', serving the purpose that quickly convert a data type+-- to a 'Text' value.+class ToText a where+    toTextBuilder :: Int -> a  -> TextBuilder ()+    default toTextBuilder :: (Generic a, GToText (Rep a)) => Int -> a -> TextBuilder ()+    toTextBuilder p = gToTextBuilder p . from++class GToText f where+    gToTextBuilder :: Int -> f a -> TextBuilder ()+++class GFieldToText f where+    gFieldToTextBuilder :: B.Builder () -> Int -> f a -> B.Builder ()++instance (GFieldToText a, GFieldToText b) => GFieldToText (a :*: b) where+    {-# INLINE gFieldToTextBuilder #-}+    gFieldToTextBuilder sep p (a :*: b) =+        gFieldToTextBuilder sep p a >> sep >> gFieldToTextBuilder sep p b++instance (GToText f) => GFieldToText (S1 (MetaSel Nothing u ss ds) f) where+    {-# INLINE gFieldToTextBuilder #-}+    gFieldToTextBuilder _ p (M1 x) = getBuilder (gToTextBuilder p x)++instance (GToText f, Selector (MetaSel (Just l) u ss ds)) => GFieldToText (S1 (MetaSel (Just l) u ss ds) f) where+    {-# INLINE gFieldToTextBuilder #-}+    gFieldToTextBuilder _ _ m1@(M1 x) =+        B.stringModifiedUTF8 (selName m1) >> " = " >> getBuilder (gToTextBuilder 0 x)++instance GToText V1 where+    {-# INLINE gToTextBuilder #-}+    gToTextBuilder _ = error "Z.Data.TextBuilder: empty data type"++instance (GToText f, GToText g) => GToText (f :+: g) where+    {-# INLINE gToTextBuilder #-}+    gToTextBuilder p (L1 x) = gToTextBuilder p x+    gToTextBuilder p (R1 x) = gToTextBuilder p x++-- | Constructor without payload, convert to String+instance (Constructor c) => GToText (C1 c U1) where+    {-# INLINE gToTextBuilder #-}+    gToTextBuilder _ m1 =+        TextBuilder . B.stringModifiedUTF8 $ conName m1++-- | Constructor with payloads+instance (GFieldToText (S1 sc f), Constructor c) => GToText (C1 c (S1 sc f)) where+    {-# INLINE gToTextBuilder #-}+    gToTextBuilder p m1@(M1 x) =+        parenWhen (p > 10) . TextBuilder $ do+            B.stringModifiedUTF8 $ conName m1+            B.char8 ' '+            if conIsRecord m1+            then B.curly $ gFieldToTextBuilder (B.char7 ',' >> B.char7 ' ') p x+            else gFieldToTextBuilder (B.char7 ' ') 11 x++instance (GFieldToText (a :*: b), Constructor c) => GToText (C1 c (a :*: b)) where+    {-# INLINE gToTextBuilder #-}+    gToTextBuilder p m1@(M1 x) =+        case conFixity m1 of+            Prefix -> parenWhen (p > 10) . TextBuilder $ do+                B.stringModifiedUTF8 $ conName m1+                B.char8 ' '+                if conIsRecord m1+                then B.curly $ gFieldToTextBuilder (B.char7 ',' >> B.char7 ' ') p x+                else gFieldToTextBuilder (B.char7 ' ') 11 x+            Infix _ p' -> parenWhen (p > p') . TextBuilder $ do+                gFieldToTextBuilder+                    (B.char8 ' ' >> B.stringModifiedUTF8 (conName m1) >> B.char8 ' ') (p'+1) x++instance ToText a => GToText (K1 i a) where+    {-# INLINE gToTextBuilder #-}+    gToTextBuilder p (K1 x) = toTextBuilder p x++--------------------------------------------------------------------------------+-- Data types+instance GToText f => GToText (D1 c f) where+    {-# INLINE gToTextBuilder #-}+    gToTextBuilder p (M1 x) = gToTextBuilder p x+++-- | Directly convert data to 'Text'.+toText :: ToText a => a -> Text+{-# INLINE toText #-}+toText = buildText .  toTextBuilder 0++-- | Directly convert data to 'B.Builder'.+toBuilder :: ToText a => a -> B.Builder ()+{-# INLINE toBuilder #-}+toBuilder = getBuilder . toTextBuilder 0++-- | Directly convert data to 'V.Bytes'.+toBytes :: ToText a => a -> V.Bytes+{-# INLINE toBytes #-}+toBytes = B.buildBytes .  toBuilder++-- | Faster 'show' replacement.+toString :: ToText a => a -> String+{-# INLINE toString #-}+toString = T.unpack . toText++instance ToText Bool where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ True = TextBuilder "True"+    toTextBuilder _ _    = TextBuilder "False"++instance ToText Char where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ = TextBuilder . B.string8 . show++instance ToText Double where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = double;}+instance ToText Float  where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = float;}++instance ToText Int     where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = int;}+instance ToText Int8    where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = int;}+instance ToText Int16   where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = int;}+instance ToText Int32   where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = int;}+instance ToText Int64   where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = int;}+instance ToText Word     where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = int;}+instance ToText Word8    where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = int;}+instance ToText Word16   where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = int;}+instance ToText Word32   where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = int;}+instance ToText Word64   where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = int;}++instance ToText Integer  where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = integer;}+instance ToText Natural  where {{-# INLINE toTextBuilder #-}; toTextBuilder _ = integer . fromIntegral}+instance ToText Ordering where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ GT = TextBuilder "GT"+    toTextBuilder _ EQ = TextBuilder "EQ"+    toTextBuilder _ _  = TextBuilder "LT"++instance ToText () where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ () = TextBuilder "()"++instance ToText Version where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ = stringUTF8 . show++-- | To keep sync with 'Show' instance's escaping rule, we reuse show here, so it won't be as fast as memcpy.+instance ToText Text where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ = stringUTF8 . show++instance ToText Sci.Scientific where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ = scientific++instance ToText a => ToText [a] where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ = square . intercalateList comma (toTextBuilder 0)++instance ToText a => ToText (V.Vector a) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ = square . intercalateVec comma (toTextBuilder 0)++instance (Prim a, ToText a) => ToText (V.PrimVector a) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ = square . intercalateVec comma (toTextBuilder 0)++instance (ToText a, ToText b) => ToText (a, b) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ (a, b) = paren $  toTextBuilder 0 a+                     >> comma >> toTextBuilder 0 b++instance (ToText a, ToText b, ToText c) => ToText (a, b, c) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ (a, b, c) = paren $  toTextBuilder 0 a+                     >> comma >> toTextBuilder 0 b+                     >> comma >> toTextBuilder 0 c++instance (ToText a, ToText b, ToText c, ToText d) => ToText (a, b, c, d) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ (a, b, c, d) = paren $  toTextBuilder 0 a+                     >> comma >> toTextBuilder 0 b+                     >> comma >> toTextBuilder 0 c+                     >> comma >> toTextBuilder 0 d++instance (ToText a, ToText b, ToText c, ToText d, ToText e) => ToText (a, b, c, d, e) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ (a, b, c, d, e) = paren $  toTextBuilder 0 a+                     >> comma >> toTextBuilder 0 b+                     >> comma >> toTextBuilder 0 c+                     >> comma >> toTextBuilder 0 d+                     >> comma >> toTextBuilder 0 e++instance (ToText a, ToText b, ToText c, ToText d, ToText e, ToText f) => ToText (a, b, c, d, e, f) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ (a, b, c, d, e, f) = paren $  toTextBuilder 0 a+                     >> comma >> toTextBuilder 0 b+                     >> comma >> toTextBuilder 0 c+                     >> comma >> toTextBuilder 0 d+                     >> comma >> toTextBuilder 0 e+                     >> comma >> toTextBuilder 0 f++instance (ToText a, ToText b, ToText c, ToText d, ToText e, ToText f, ToText g) => ToText (a, b, c, d, e, f, g) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ (a, b, c, d, e, f, g) = paren $  toTextBuilder 0 a+                     >> comma >> toTextBuilder 0 b+                     >> comma >> toTextBuilder 0 c+                     >> comma >> toTextBuilder 0 d+                     >> comma >> toTextBuilder 0 e+                     >> comma >> toTextBuilder 0 f+                     >> comma >> toTextBuilder 0 g++instance ToText a => ToText (Maybe a) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder p (Just x) = parenWhen (p > 10) $ do TextBuilder "Just "+                                                       toTextBuilder 11 x+    toTextBuilder _ _        = TextBuilder "Nothing"++instance (ToText a, ToText b) => ToText (Either a b) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder p (Left x) = parenWhen (p > 10) $ do TextBuilder "Left "+                                                       toTextBuilder 11 x+    toTextBuilder p (Right x) = parenWhen (p > 10) $ do TextBuilder "Right "+                                                        toTextBuilder 11 x++instance (ToText a, Integral a) => ToText (Ratio a) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder p r = parenWhen (p > 10) $ do toTextBuilder 8 (numerator r)+                                                TextBuilder " % "+                                                toTextBuilder 8 (denominator r)++instance HasResolution a => ToText (Fixed a) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder _ = TextBuilder . B.string8 .  show++deriving anyclass instance ToText a => ToText (Semigroup.Min a)+deriving anyclass instance ToText a => ToText (Semigroup.Max a)+deriving anyclass instance ToText a => ToText (Semigroup.First a)+deriving anyclass instance ToText a => ToText (Semigroup.Last a)+deriving anyclass instance ToText a => ToText (Semigroup.WrappedMonoid a)+deriving anyclass instance ToText a => ToText (Semigroup.Dual a)+deriving anyclass instance ToText a => ToText (Monoid.First a)+deriving anyclass instance ToText a => ToText (Monoid.Last a)+deriving anyclass instance ToText a => ToText (NonEmpty a)+deriving anyclass instance ToText a => ToText (Identity a)+deriving anyclass instance ToText a => ToText (Const a b)+deriving anyclass instance ToText (Proxy a)+deriving anyclass instance ToText b => ToText (Tagged a b)+deriving anyclass instance ToText (f (g a)) => ToText (Compose f g a)+deriving anyclass instance (ToText (f a), ToText (g a)) => ToText (Product f g a)+deriving anyclass instance (ToText (f a), ToText (g a), ToText a) => ToText (Sum f g a)
+ Z/Data/Text/Extra.hs view
@@ -0,0 +1,596 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE TypeApplications #-}++{-|+Module      : Z.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 Z.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 Z.Data.Vector.Base as V+import qualified Z.Data.Vector.Extra as V+import qualified Z.Data.Vector.Search as V+import Data.Coerce+import qualified Data.List as List+import Z.Data.Text.Base+import Z.Data.Text.UTF8Codec+import Z.Data.Text.Search+import           Control.Monad.ST+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 t0 = go t0 [t0]+  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 _))+    | 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 _))+    | 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 _)) =+    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 _)) =+    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@.+--+-- NOTE: This functions is different from 'Prelude.unlines', it DOES NOT add a trailing @\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+
+ Z/Data/Text/Search.hs view
@@ -0,0 +1,145 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UnboxedTuples       #-}+++{-|+Module      : Z.Data.Text.Search+Description : Searching text+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++-}++module Z.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)+import           Z.Data.Array+import           Z.Data.Text.Base+import           Z.Data.Text.UTF8Codec+import qualified Z.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 in slice, 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 start of the byte slice.+--+findR :: (Char -> Bool)+      -> Text+      -> (Int, Int, Maybe Char)  -- ^ (char index(counting backwards), byte index in slice, matching 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
+ Z/Data/Text/UTF8Codec.hs view
@@ -0,0 +1,356 @@+{-# LANGUAGE BangPatterns  #-}+{-# LANGUAGE MagicHash     #-}+{-# LANGUAGE UnboxedTuples #-}++{-|+Module      : Z.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 Z.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#, _ #) = 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#, _ #) = 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'
+ Z/Data/Text/UTF8Rewind.hsc view
@@ -0,0 +1,126 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++{-|+Module      : Z.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 Z.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 Z.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 'Z.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
+ Z/Data/Vector.hs view
@@ -0,0 +1,180 @@+{-# 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      : Z.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++  * Many functions DO NOT NEED result vectors's type to be the same+    with source one, e.g. @map :: (Vec v a, Vec u b) => (a -> b) -> v a -> u b@.++  * There're some specialized functions only works on 'Bytes', which is enabled+    by rewrite rules, if you want to use specialized versions directly, import+    "Z.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 Z.Data.Vector (+  -- * The Vec typeclass+    Vec(IArray)+  -- * 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', traverseVec, traverseWithIndex, traverseVec_, traverseWithIndex_+  , 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           Z.Data.Vector.Base+import           Z.Data.Vector.Extra+import           Z.Data.Vector.Search+import           Z.Data.Vector.Sort+import           Z.Data.Vector.QQ
+ Z/Data/Vector/Base.hs view
@@ -0,0 +1,1342 @@+{-# 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  #-}+{-# LANGUAGE TypeApplications       #-}++{-|+Module      : Z.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 Z.Data.Vector.Base (+  -- * The Vec typeclass+    Vec(..)+  , pattern Vec+  , indexMaybe+  -- * Boxed and unboxed vector type+  , Vector(..)+  , PrimVector(..)+  -- ** Word8 vector+  , Bytes, packASCII+  , w2c, c2w+  -- * Creating utilities+  , 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', traverseVec, traverseWithIndex, traverseVec_, traverseWithIndex_+  , 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(..), mapIPair'+  , defaultInitSize+  , chunkOverhead+  , defaultChunkSize+  , smallChunkSize+  , VectorException(..)+  , errorEmptyVector+  , errorOutRange+  , castVector+  -- * C FFI+  , c_strcmp+  , c_memchr+  , c_memrchr+  , 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.Hashable                 (Hashable(..))+import           Data.Hashable.Lifted          (Hashable1(..), hashWithSalt1)+import qualified Data.List                     as List+import           Data.Maybe+import qualified Data.CaseInsensitive          as CI+import           Data.Primitive+import           Data.Primitive.Ptr+import qualified Data.Traversable              as T+import           Foreign.C+import           GHC.CString+import           GHC.Exts+import           GHC.Stack+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           Test.QuickCheck.Arbitrary (Arbitrary(..), CoArbitrary(..))+import           System.IO.Unsafe              (unsafeDupablePerformIO)++import           Z.Data.Array++-- | Typeclass for box and unboxed vectors, which are created by slicing arrays.+--+-- Instead of providing a generalized vector with polymorphric array field, we use this typeclass+-- so that instances use concrete array type can unpack their array payload.+class (Arr (IArray v) a) => Vec v a where+    -- | Vector's immutable array type+    type IArray 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++instance Vec Array a where+    type IArray Array = Array+    {-# INLINE toArr #-}+    toArr arr = (arr, 0, sizeofArr arr)+    {-# INLINE fromArr #-}+    fromArr = cloneArr++instance Vec SmallArray a where+    type IArray SmallArray = SmallArray+    {-# INLINE toArr #-}+    toArr arr = (arr, 0, sizeofArr arr)+    {-# INLINE fromArr #-}+    fromArr = cloneArr++instance Prim a => Vec PrimArray a where+    type IArray PrimArray = PrimArray+    {-# INLINE toArr #-}+    toArr arr = (arr, 0, sizeofArr arr)+    {-# INLINE fromArr #-}+    fromArr = cloneArr++instance PrimUnlifted a => Vec UnliftedArray a where+    type IArray UnliftedArray = UnliftedArray+    {-# INLINE toArr #-}+    toArr arr = (arr, 0, sizeofArr arr)+    {-# INLINE fromArr #-}+    fromArr = cloneArr++-- | 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 => 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 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+    {-# INLINE traverse #-}+    traverse = traverseVec++instance Arbitrary a => Arbitrary (Vector a) where+    arbitrary = pack <$> arbitrary+    shrink v = pack <$> shrink (unpack v)++instance CoArbitrary a => CoArbitrary (Vector a) where+    coarbitrary = coarbitrary . unpack++instance Hashable a => Hashable (Vector a) where+    {-# INLINE hashWithSalt #-}+    hashWithSalt = hashWithSalt1++instance Hashable1 Vector where+    {-# INLINE liftHashWithSalt #-}+    liftHashWithSalt h salt0 (Vector arr s l) = hashWithSalt (go salt0 s) l+      where+        !end = s + l+        go !salt !i+            | i >= end  = salt+            | otherwise = go (h salt (indexArr arr i)) (i+1)++traverseVec :: (Vec v a, Vec u b, Applicative f) => (a -> f b) -> v a -> f (u b)+{-# INLINE [1] traverseVec #-}+{-# RULES "traverseVec/ST" forall f. traverseVec f = traverseWithIndexST (const f) #-}+{-# RULES "traverseVec/IO" forall f. traverseVec f = traverseWithIndexIO (const f) #-}+traverseVec f v = packN (length v) <$> T.traverse f (unpack v)++traverseWithIndex :: (Vec v a, Vec u b, Applicative f) => (Int -> a -> f b) -> v a -> f (u b)+{-# INLINE [1] traverseWithIndex #-}+{-# RULES "traverseWithIndex/ST" traverseWithIndex = traverseWithIndexST #-}+{-# RULES "traverseWithIndex/IO" traverseWithIndex = traverseWithIndexIO #-}+traverseWithIndex f v = packN (length v) <$> zipWithM f [0..] (unpack v)++traverseWithIndexST :: forall v u a b s. (Vec v a, Vec u b) => (Int -> a -> ST s b) -> v a -> ST s (u b)+{-# INLINE traverseWithIndexST #-}+traverseWithIndexST 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 :: MArr (IArray u) s b -> Int -> ST s ()+    go !marr !i+        | i >= l = return ()+        | otherwise = do+            x <- indexArrM arr (i+s)+            writeArr marr i =<< f i x+            go marr (i+1)++traverseWithIndexIO :: forall v u a b. (Vec v a, Vec u b) => (Int -> a -> IO b) -> v a -> IO (u b)+{-# INLINE traverseWithIndexIO #-}+traverseWithIndexIO 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 :: MArr (IArray u) RealWorld b -> Int -> IO ()+    go !marr !i+        | i >= l = return ()+        | otherwise = do+            x <- indexArrM arr (i+s)+            writeArr marr i =<< f i x+            go marr (i+1)++traverseVec_ :: (Vec v a, Applicative f) => (a -> f b) -> v a -> f ()+{-# INLINE traverseVec_ #-}+traverseVec_ f = traverseWithIndex_ (\ _ x -> f x)++traverseWithIndex_ :: (Vec v a, Applicative f) => (Int -> a -> f b) -> v a -> f ()+{-# INLINE traverseWithIndex_ #-}+traverseWithIndex_ f (Vec arr s l) = go s+  where+    end = s + l+    go !i+        | i >= end = pure ()+        | otherwise = f (i-s) (indexArr arr i) *> go (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 IArray PrimVector = PrimArray+    {-# INLINE toArr #-}+    toArr (PrimVector arr s l) = (arr, s, l)+    {-# INLINE fromArr #-}+    fromArr = PrimVector++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)+             (PrimVector (PrimArray baB#) (I# sB#) 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 (Prim a, Ord a) => Ord (PrimVector a) where+    {-# INLINE compare #-}+    compare = comparePrimVector+++comparePrimVector :: (Prim a, Ord a) => PrimVector a -> PrimVector a -> Ordering+{-# INLINE [1] comparePrimVector #-}+{-# RULES+    "comparePrimVector/Bytes" comparePrimVector = compareBytes+  #-}+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)+             (PrimVector (PrimArray baB#) (I# sB#) 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 (Prim a, Arbitrary a) => Arbitrary (PrimVector a) where+    arbitrary = pack <$> arbitrary+    shrink v = pack <$> shrink (unpack v)++instance (Prim a, CoArbitrary a) => CoArbitrary (PrimVector a) where+    coarbitrary = coarbitrary . unpack++instance (Hashable a, Prim a) => Hashable (PrimVector a) where+    {-# INLINE hashWithSalt #-}+    hashWithSalt = hashWithSaltPrimVector++hashWithSaltPrimVector :: (Hashable a, Prim a) => Int -> PrimVector a -> Int+{-# INLINE [1] hashWithSaltPrimVector #-}+{-# RULES+    "hashWithSaltPrimVector/Bytes" hashWithSaltPrimVector = hashWithSaltBytes+  #-}+hashWithSaltPrimVector salt0 (PrimVector arr s l) = go salt0 s+  where+    -- we don't do a final hash with length to keep consistent with Bytes's instance+    !end = s + l+    go !salt !i+        | i >= end  = salt+        | otherwise = go (hashWithSalt salt (indexPrimArray arr i)) (i+1)++hashWithSaltBytes :: Int -> Bytes -> Int+{-# INLINE hashWithSaltBytes #-}+hashWithSaltBytes 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 toLower8+      where+        toLower8 :: Word8 -> Word8+        toLower8 w+          |  65 <= w && w <=  90 ||+            192 <= w && w <= 214 ||+            216 <= w && w <= 222 = w + 32+          | otherwise            = w++-- | /O(n)/, pack an ASCII 'String', multi-bytes char WILL BE CHOPPED!+packASCII :: String -> Bytes+{-# INLINE CONLIKE [0] packASCII #-}+{-# RULES+    "packASCII/packASCIIAddr" forall addr . packASCII (unpackCString# addr) = packASCIIAddr addr+  #-}+packASCII = pack . fmap (fromIntegral . ord)++packASCIIAddr :: Addr# -> Bytes+packASCIIAddr addr0# = go addr0#+  where+    len = fromIntegral . unsafeDupablePerformIO $ c_strlen addr0#+    go addr# = 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. MArr (IArray 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. MArr (IArray v) s a -> ST s (IPair (MArr (IArray 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. MArr (IArray 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. MArr (IArray v) s a -> ST s (b, (IPair (MArr (IArray 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. MArr (IArray 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. MArr (IArray v) s a -> MArr (IArray 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 (MArr (IArray v) s a) -> a -> ST s (IPair (MArr (IArray 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 (MArr (IArray v) s a) -> a -> ST s (IPair (MArr (IArray 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 -> MArr (IArray 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 -> MArr (IArray 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 -> MArr (IArray 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 (go 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 (Vec _ _ l:vs')+        | l <= 0    = pre nacc lacc vs'+        | otherwise = pre (nacc+1) (l+lacc) vs'++    go :: [v a] -> Int -> MArr (IArray v) s a -> ST s ()+    go [] !_ !_                  = return ()+    go (Vec ba s l:vs') !i !marr = do when (l /= 0) (copyArr marr i ba s l)+                                      go 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) => 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) => 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 -> MArr (IArray 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 ->  MArr (IArray 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 -> MArr (IArray 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 @v n (go z 0)+        in (Vec arr 0 len, r)+  where+    go :: a -> Int -> MArr (IArray 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++--------------------------------------------------------------------------------++-- | Pair type to help GHC unpack in some loops, useful when write fast folds.+data IPair a = IPair { ifst :: {-# UNPACK #-}!Int, isnd :: a } deriving (Show, Eq, Ord)++instance (Arbitrary v) => Arbitrary (IPair v) where+    arbitrary = iPairFromTuple <$> arbitrary+    shrink v = iPairFromTuple <$> shrink (iPairToTuple v)++instance (CoArbitrary v) => CoArbitrary (IPair v) where+    coarbitrary = coarbitrary . iPairToTuple++instance Functor IPair where+    {-# INLINE fmap #-}+    fmap f (IPair i v) = IPair i (f v)++instance NFData a => NFData (IPair a) where+    {-# INLINE rnf #-}+    rnf (IPair _ a) = rnf a++-- | Unlike 'Functor' instance, this mapping evaluate value inside 'IPair' strictly.+mapIPair' :: (a -> b) -> IPair a -> IPair b+{-# INLINE mapIPair' #-}+mapIPair' f (IPair i v) = let !v' = f v in IPair i v'++iPairToTuple :: IPair a -> (Int, a)+{-# INLINE iPairToTuple #-}+iPairToTuple (IPair i v) = (i, v)++iPairFromTuple :: (Int, a) -> IPair a+{-# INLINE iPairFromTuple #-}+iPairFromTuple (i, v) = IPair i v++-- | 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++-- 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++-- HsInt hs_memrchr(uint8_t *a, HsInt aoff, uint8_t b, HsInt n);+foreign import ccall unsafe "hs_memrchr" c_memrchr ::+    ByteArray# -> Int -> Word8 -> Int -> Int
+ Z/Data/Vector/Extra.hs view
@@ -0,0 +1,848 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE TypeApplications #-}++{-|+Module      : Z.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 Z.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, indexM+  , unsafeHead+  , unsafeTail+  , unsafeInit+  , unsafeLast+  , unsafeIndex, unsafeIndexM+  , unsafeTake+  , unsafeDrop+  ) where++import           Control.Monad.ST+import           GHC.Stack+import           GHC.Word+import           Z.Data.Array+import           Z.Data.Vector.Base+import           Z.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           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 _) =+    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 _) =+    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 (==x)@ will be rewritten using a @memchr@.+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 (/=x)@ will be rewritten using a @memchr@.+span :: Vec v a => (a -> Bool) -> v a -> (v a, v a)+{-# INLINE [1] span #-}+span f = break (not . f)+{-# RULES "spanNEq/breakEq1" forall w. span (w `neWord8`) = break (w `eqWord8`) #-}+{-# RULES "spanNEq/breakEq2" forall w. span (`neWord8` w) = break (`eqWord8` w) #-}++-- | '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 :: forall v a. 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 @v (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 :: forall v a. (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 = (==) @(v a) (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 :: forall v a. (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 = (==) @(v a) (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 :: Int -> Int -> [Bytes]+    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 :: Int -> Int -> [Bytes]+    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@.+--+-- NOTE: This functions is different from 'Prelude.unlines', it DOES NOT add a trailing @\n@.+unlines :: [Bytes] -> Bytes+{-# INLINE unlines #-}+unlines = intercalateElem 10++-- | 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 -> MArr (IArray 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 v@(Vec arr s l) | l <= 1 = v+                              | otherwise = 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+       -> MArr (IArray 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) (go 0 vs)+  where+    len []             !acc = acc+    len [Vec _ _ l]    !acc = l + acc+    len (Vec _ _ l:vs') !acc = len vs' (acc+l+1)+    go !_ []               !_    = return ()+    go !i (Vec arr s l:[]) !marr = copyArr marr i arr s l+    go !i (Vec arr s l:vs') !marr = do+        let !i' = i + l+        copyArr marr i arr s l+        writeArr marr i' w+        go (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 -> MArr (IArray 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 -> MArr (IArray 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)/ Index array element.+--+-- Throw 'IndexOutOfVectorRange' if index outside of the vector.+indexM :: (Vec v a, Monad m, HasCallStack) => v a -> Int -> m a+{-# INLINE indexM #-}+indexM (Vec arr s l) i | i < 0 || i >= l = errorOutRange i+                       | otherwise       = arr `indexArrM` (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 _) i = indexArr arr (s + i)++-- | /O(1)/ Index array element.+--+-- Make sure index is in bound, otherwise segmentation fault await!+unsafeIndexM :: (Vec v a, Monad m) => v a -> Int -> m a+{-# INLINE unsafeIndexM #-}+unsafeIndexM (Vec arr s _) i = indexArrM 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))
+ Z/Data/Vector/FlatIntMap.hs view
@@ -0,0 +1,392 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE OverloadedStrings #-}++{-|+Module      : Z.Data.Vector.FlatIntMap+Description : Fast int map based on sorted 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 a simple int key value map based on sorted vector and binary search. It's particularly+suitable for small sized key value collections such as deserializing intermediate representation.+But can also used in various place where insertion and deletion is rare but require fast lookup.++-}++module Z.Data.Vector.FlatIntMap+  ( -- * FlatIntMap backed by sorted vector+    FlatIntMap, sortedKeyValues, size, null, empty, map', imap'+  , pack, packN, packR, packRN+  , unpack, unpackR, packVector, packVectorR+  , lookup+  , delete+  , insert+  , adjust'+  , merge, mergeWithKey'+    -- * fold and traverse+  , foldrWithKey, foldrWithKey', foldlWithKey, foldlWithKey', traverseWithKey+    -- * binary & linear search on vectors+  , binarySearch+  , linearSearch, linearSearchR+  ) where++import           Control.DeepSeq+import           Control.Monad+import           Control.Monad.ST+import qualified Data.Foldable              as Foldable+import qualified Data.Traversable           as Traversable+import qualified Data.Semigroup             as Semigroup+import qualified Data.Monoid                as Monoid+import qualified Data.Primitive.SmallArray  as A+import qualified Z.Data.Vector.Base         as V+import qualified Z.Data.Vector.Sort         as V+import qualified Z.Data.Text.Builder        as T+import           Data.Function              (on)+import           Data.Bits                   (shiftR)+import           Data.Data+import           Prelude hiding (lookup, null)+import           Test.QuickCheck.Arbitrary (Arbitrary(..), CoArbitrary(..))++--------------------------------------------------------------------------------++newtype FlatIntMap v = FlatIntMap { sortedKeyValues :: V.Vector (V.IPair v) }+    deriving (Show, Eq, Ord, Typeable)++instance T.ToText v => T.ToText (FlatIntMap v) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder p (FlatIntMap vec) = T.parenWhen (p > 10) $ do+        T.unsafeFromBuilder "FlatIntMap {"+        T.intercalateVec T.comma (\ (V.IPair i v) ->+            T.toTextBuilder 0 i >> ":" >> T.toTextBuilder 0 v) vec+        T.char7 '}'++instance (Arbitrary v) => Arbitrary (FlatIntMap v) where+    arbitrary = pack <$> arbitrary+    shrink v = pack <$> shrink (unpack v)++instance (CoArbitrary v) => CoArbitrary (FlatIntMap v) where+    coarbitrary = coarbitrary . unpack++instance Semigroup.Semigroup (FlatIntMap v) where+    {-# INLINE (<>) #-}+    (<>) = merge++instance Monoid.Monoid (FlatIntMap v) where+    {-# INLINE mappend #-}+    mappend = merge+    {-# INLINE mempty #-}+    mempty = empty++instance NFData v => NFData (FlatIntMap v) where+    {-# INLINE rnf #-}+    rnf (FlatIntMap ivs) = rnf ivs++instance Functor (FlatIntMap) where+    {-# INLINE fmap #-}+    fmap f (FlatIntMap vs) = FlatIntMap (V.map' (fmap f) vs)++instance Foldable.Foldable FlatIntMap where+    {-# INLINE foldr' #-}+    foldr' f = foldrWithKey' (const f)+    {-# INLINE foldr #-}+    foldr f = foldrWithKey (const f)+    {-# INLINE foldl' #-}+    foldl' f = foldlWithKey' (\ a _ v -> f a v)+    {-# INLINE foldl #-}+    foldl f = foldlWithKey (\ a _ v -> f a v)+    {-# INLINE toList #-}+    toList = fmap V.isnd . unpack+    {-# INLINE null #-}+    null (FlatIntMap vs) = V.null vs+    {-# INLINE length #-}+    length (FlatIntMap vs) = V.length vs+    {-# INLINE elem #-}+    elem a (FlatIntMap vs) = elem a (map V.isnd $ V.unpack vs)++instance Traversable.Traversable FlatIntMap where+    {-# INLINE traverse #-}+    traverse f = traverseWithKey (const f)++size :: FlatIntMap v -> Int+{-# INLINE size #-}+size = V.length . sortedKeyValues++null :: FlatIntMap v -> Bool+{-# INLINE null #-}+null = V.null . sortedKeyValues++map' :: (v -> v') -> FlatIntMap v -> FlatIntMap v'+{-# INLINE map' #-}+map' f (FlatIntMap vs) = FlatIntMap (V.map' (V.mapIPair' f) vs)++imap' :: (Int -> v -> v') -> FlatIntMap v -> FlatIntMap v'+{-# INLINE imap' #-}+imap' f (FlatIntMap vs) = FlatIntMap (V.imap' (\ i -> V.mapIPair' (f i)) vs)++-- | /O(1)/ empty flat map.+empty :: FlatIntMap v+{-# INLINE empty #-}+empty = FlatIntMap V.empty++-- | /O(N*logN)/ Pack list of key values, on key duplication prefer left one.+pack :: [V.IPair v] -> FlatIntMap v+{-# INLINE pack #-}+pack kvs = FlatIntMap (V.mergeDupAdjacentLeft ((==) `on` V.ifst) (V.mergeSortBy (compare `on` V.ifst) (V.pack kvs)))++-- | /O(N*logN)/ Pack list of key values with suggested size, on key duplication prefer left one.+packN :: Int -> [V.IPair v] -> FlatIntMap v+{-# INLINE packN #-}+packN n kvs = FlatIntMap (V.mergeDupAdjacentLeft ((==) `on` V.ifst) (V.mergeSortBy (compare `on` V.ifst) (V.packN n kvs)))++-- | /O(N*logN)/ Pack list of key values, on key duplication prefer right one.+packR :: [V.IPair v] -> FlatIntMap v+{-# INLINE packR #-}+packR kvs = FlatIntMap (V.mergeDupAdjacentRight ((==) `on` V.ifst) (V.mergeSortBy (compare `on` V.ifst) (V.pack kvs)))++-- | /O(N*logN)/ Pack list of key values with suggested size, on key duplication prefer right one.+packRN :: Int -> [V.IPair v] -> FlatIntMap v+{-# INLINE packRN #-}+packRN n kvs = FlatIntMap (V.mergeDupAdjacentRight ((==) `on` V.ifst) (V.mergeSortBy (compare `on` V.ifst) (V.packN n kvs)))++-- | /O(N)/ Unpack key value pairs to a list sorted by keys in ascending order.+--+-- This function works with @foldr/build@ fusion in base.+unpack :: FlatIntMap v -> [V.IPair v]+{-# INLINE unpack #-}+unpack = V.unpack . sortedKeyValues++-- | /O(N)/ Unpack key value pairs to a list sorted by keys in descending order.+--+-- This function works with @foldr/build@ fusion in base.+unpackR :: FlatIntMap v -> [V.IPair v]+{-# INLINE unpackR #-}+unpackR = V.unpackR . sortedKeyValues++-- | /O(N*logN)/ Pack vector of key values, on key duplication prefer left one.+packVector :: V.Vector (V.IPair v) -> FlatIntMap v+{-# INLINE packVector #-}+packVector kvs = FlatIntMap (V.mergeDupAdjacentLeft ((==) `on` V.ifst) (V.mergeSortBy (compare `on` V.ifst) kvs))++-- | /O(N*logN)/ Pack vector of key values, on key duplication prefer right one.+packVectorR :: V.Vector (V.IPair v) -> FlatIntMap v+{-# INLINE packVectorR #-}+packVectorR kvs = FlatIntMap (V.mergeDupAdjacentRight ((==) `on` V.ifst) (V.mergeSortBy (compare `on` V.ifst) kvs))++-- | /O(logN)/ Binary search on flat map.+lookup :: Int -> FlatIntMap v -> Maybe v+{-# INLINABLE lookup #-}+lookup _ (FlatIntMap (V.Vector _ _ 0)) = Nothing+lookup k' (FlatIntMap (V.Vector arr s0 l)) = go s0 (s0+l-1)+  where+    go !s !e+        | s == e =+            case arr `A.indexSmallArray` s of (V.IPair k v) | k == k'  -> Just v+                                                            | otherwise -> Nothing+        | s >  e = Nothing+        | otherwise =+            let mid = (s+e) `shiftR` 1+                (V.IPair k v)  = arr `A.indexSmallArray` mid+            in case k' `compare` k of LT -> go s (mid-1)+                                      GT -> go (mid+1) e+                                      _  -> Just v++-- | /O(N)/ Insert new key value into map, replace old one if key exists.+insert :: Int -> v -> FlatIntMap v -> FlatIntMap v+{-# INLINE insert #-}+insert k v (FlatIntMap vec@(V.Vector arr s l)) =+    case binarySearch vec k of+        Left i -> FlatIntMap (V.create (l+1) (\ marr -> do+            when (i>s) $ A.copySmallArray marr 0 arr s (i-s)+            A.writeSmallArray marr i (V.IPair k v)+            when (i<(s+l)) $ A.copySmallArray marr (i+1) arr i (s+l-i)))+        Right i -> FlatIntMap (V.Vector (runST (do+            let arr' = A.cloneSmallArray arr s l+            marr <- A.unsafeThawSmallArray arr'+            A.writeSmallArray marr i (V.IPair k v)+            A.unsafeFreezeSmallArray marr)) 0 l)++-- | /O(N)/ Delete a key value pair by key.+delete :: Int -> FlatIntMap v -> FlatIntMap v+{-# INLINE delete #-}+delete k m@(FlatIntMap vec@(V.Vector arr s l)) =+    case binarySearch vec k of+        Left _  -> m+        Right i -> FlatIntMap $ V.create (l-1) (\ marr -> do+            when (i>s) $ A.copySmallArray marr 0 arr s (i-s)+            let !end = s+l+                !j = i+1+            when (end > j) $ A.copySmallArray marr 0 arr j (end-j))++-- | /O(N)/ Modify a value by key.+--+-- The value is evaluated to WHNF before writing into map.+adjust' :: (v -> v) -> Int -> FlatIntMap v -> FlatIntMap v+{-# INLINE adjust' #-}+adjust' f k m@(FlatIntMap vec@(V.Vector arr s l)) =+    case binarySearch vec k of+        Left _  -> m+        Right i -> FlatIntMap $ V.create l (\ marr -> do+            A.copySmallArray marr 0 arr s l+            let !v' = f (V.isnd (A.indexSmallArray arr i))+            A.writeSmallArray marr i (V.IPair k v'))++-- | /O(n+m)/ Merge two 'FlatIntMap', prefer right value on key duplication.+merge :: forall v. FlatIntMap v -> FlatIntMap v -> FlatIntMap v+{-# INLINE merge #-}+merge fmL@(FlatIntMap (V.Vector arrL sL lL)) fmR@(FlatIntMap (V.Vector arrR sR lR))+    | null fmL = fmR+    | null fmR = fmL+    | otherwise = FlatIntMap (V.createN (lL+lR) (go sL sR 0))+  where+    endL = sL + lL+    endR = sR + lR+    go :: Int -> Int -> Int -> A.SmallMutableArray s (V.IPair v) -> ST s Int+    go !i !j !k marr+        | i >= endL = do+            A.copySmallArray marr k arrR j (lR-j)+            return $! k+lR-j+        | j >= endR = do+            A.copySmallArray marr k arrL i (lL-i)+            return $! k+lL-i+        | otherwise = do+            kvL@(V.IPair kL _) <- arrL `A.indexSmallArrayM` i+            kvR@(V.IPair kR _) <- arrR `A.indexSmallArrayM` j+            case kL `compare` kR of LT -> do A.writeSmallArray marr k kvL+                                             go (i+1) j (k+1) marr+                                    EQ -> do A.writeSmallArray marr k kvR+                                             go (i+1) (j+1) (k+1) marr+                                    _  -> do A.writeSmallArray marr k kvR+                                             go i (j+1) (k+1) marr++-- | /O(n+m)/ Merge two 'FlatIntMap' with a merge function.+mergeWithKey' :: forall v. (Int -> v -> v -> v) -> FlatIntMap v -> FlatIntMap v -> FlatIntMap v+{-# INLINABLE mergeWithKey' #-}+mergeWithKey' f fmL@(FlatIntMap (V.Vector arrL sL lL)) fmR@(FlatIntMap (V.Vector arrR sR lR))+    | null fmL = fmR+    | null fmR = fmL+    | otherwise = FlatIntMap (V.createN (lL+lR) (go sL sR 0))+  where+    endL = sL + lL+    endR = sR + lR+    go :: Int -> Int -> Int -> A.SmallMutableArray s (V.IPair v) -> ST s Int+    go !i !j !k marr+        | i >= endL = do+            A.copySmallArray marr k arrR j (lR-j)+            return $! k+lR-j+        | j >= endR = do+            A.copySmallArray marr k arrL i (lL-i)+            return $! k+lL-i+        | otherwise = do+            kvL@(V.IPair kL vL) <- arrL `A.indexSmallArrayM` i+            kvR@(V.IPair kR vR) <- arrR `A.indexSmallArrayM` j+            case kL `compare` kR of LT -> do A.writeSmallArray marr k kvL+                                             go (i+1) j (k+1) marr+                                    EQ -> do let !v' = f kL vL vR+                                             A.writeSmallArray marr k (V.IPair kL v')+                                             go (i+1) (j+1) (k+1) marr+                                    _  -> do A.writeSmallArray marr k kvR+                                             go i (j+1) (k+1) marr++-- | /O(n)/ Reduce this map by applying a binary operator to all+-- elements, using the given starting value (typically the+-- right-identity of the operator).+--+-- During folding k is in descending order.+foldrWithKey :: (Int -> v -> a -> a) -> a -> FlatIntMap v -> a+{-# INLINE foldrWithKey #-}+foldrWithKey f a (FlatIntMap vs) = foldr (\ (V.IPair k v) a' -> f k v a') a vs++-- | /O(n)/ Reduce this map by applying a binary operator to all+-- elements, using the given starting value (typically the+-- right-identity of the operator).+--+-- During folding Int is in ascending order.+foldlWithKey :: (a -> Int -> v -> a) -> a -> FlatIntMap v -> a+{-# INLINE foldlWithKey #-}+foldlWithKey f a (FlatIntMap vs) = foldl (\ a' (V.IPair k v) -> f a' k v) a vs++-- | /O(n)/ Reduce this map by applying a binary operator to all+-- elements, using the given starting value (typically the+-- right-identity of the operator).+--+-- During folding Int is in descending order.+foldrWithKey' :: (Int -> v -> a -> a) -> a -> FlatIntMap v -> a+{-# INLINE foldrWithKey' #-}+foldrWithKey' f a (FlatIntMap vs) = V.foldr' (\ (V.IPair k v) -> f k v) a vs++-- | /O(n)/ Reduce this map by applying a binary operator to all+-- elements, using the given starting value (typically the+-- right-identity of the operator).+--+-- During folding Int is in ascending order.+foldlWithKey' :: (a -> Int -> v -> a) -> a -> FlatIntMap v -> a+{-# INLINE foldlWithKey' #-}+foldlWithKey' f a (FlatIntMap vs) = V.foldl' (\ a' (V.IPair k v) -> f a' k v) a vs++-- | /O(n)/.+-- @'traverseWithKey' f s == 'pack' <$> 'traverse' (\(k, v) -> (,) k <$> f k v) ('unpack' m)@+-- That is, behaves exactly like a regular 'traverse' except that the traversing+-- function also has access to the key associated with a value.+traverseWithKey :: Applicative t => (Int -> a -> t b) -> FlatIntMap a -> t (FlatIntMap b)+{-# INLINE traverseWithKey #-}+traverseWithKey f (FlatIntMap vs) = FlatIntMap <$> traverse (\ (V.IPair k v) -> V.IPair k <$> f k v) vs++--------------------------------------------------------------------------------++-- | Find the key's index in the vector slice, if key exists return 'Right',+-- otherwise 'Left', i.e. the insert index+--+-- This function only works on ascending sorted vectors.+binarySearch :: V.Vector (V.IPair v) -> Int -> Either Int Int+{-# INLINABLE binarySearch #-}+binarySearch (V.Vector _ _ 0) _   = Left 0+binarySearch (V.Vector arr s0 l) !k' = go s0 (s0+l-1)+  where+    go !s !e+        | s == e =+            let V.IPair k _  = arr `A.indexSmallArray` s+            in case k' `compare` k of LT -> Left s+                                      GT -> let !s' = s+1 in Left s'+                                      _  -> Right s+        | s >  e = Left s+        | otherwise =+            let !mid = (s+e) `shiftR` 1+                (V.IPair k _)  = arr `A.indexSmallArray` mid+            in case k' `compare` k of LT -> go s (mid-1)+                                      GT -> go (mid+1) e+                                      _  -> Right mid++--------------------------------------------------------------------------------++-- | linear scan search from left to right, return the first one if exist.+linearSearch :: V.Vector (V.IPair v) -> Int -> Maybe v+{-# INLINABLE linearSearch #-}+linearSearch (V.Vector arr s l) !k' = go s+  where+    !end = s + l+    go !i+        | i >= end = Nothing+        | otherwise =+            let V.IPair k v  = arr `A.indexSmallArray` i+            in if k' == k then Just v else go (i+1)++-- | linear scan search from right to left, return the first one if exist.+linearSearchR :: V.Vector (V.IPair v) -> Int -> Maybe v+{-# INLINABLE linearSearchR #-}+linearSearchR (V.Vector arr s l) !k' = go (s+l-1)+  where+    go !i+        | i < s = Nothing+        | otherwise =+            let V.IPair k v  = arr `A.indexSmallArray` i+            in if k' == k then Just v else go (i-1)
+ Z/Data/Vector/FlatIntSet.hs view
@@ -0,0 +1,226 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-}++{-|+Module      : Z.Data.Vector.FlatIntSet+Description : Fast int set based on sorted 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 a simple int set based on sorted vector and binary search. It's particularly+suitable for small sized value collections such as deserializing intermediate representation.+But can also used in various place where insertion and deletion is rare but require fast elem.++-}++module Z.Data.Vector.FlatIntSet+  ( -- * FlatIntSet backed by sorted vector+    FlatIntSet, sortedValues, size, null, empty, map'+  , pack, packN, packR, packRN+  , unpack, unpackR, packVector, packVectorR+  , elem+  , delete+  , insert+  , merge+    -- * binary & linear search on vectors+  , binarySearch+  ) where++import           Control.DeepSeq+import           Control.Monad+import           Control.Monad.ST+import qualified Data.Semigroup             as Semigroup+import qualified Data.Monoid                as Monoid+import qualified Data.Primitive.PrimArray   as A+import qualified Z.Data.Vector.Base         as V+import qualified Z.Data.Vector.Sort         as V+import qualified Z.Data.Text.Builder        as T+import           Data.Bits                   (shiftR)+import           Data.Data+import           Prelude hiding (elem, null)+import           Test.QuickCheck.Arbitrary (Arbitrary(..), CoArbitrary(..))++--------------------------------------------------------------------------------++newtype FlatIntSet = FlatIntSet { sortedValues :: V.PrimVector Int }+    deriving (Show, Eq, Ord, Typeable, NFData)++instance T.ToText FlatIntSet where+    {-# INLINE toTextBuilder #-}+    toTextBuilder p (FlatIntSet vec) = T.parenWhen (p > 10) $ do+        T.unsafeFromBuilder "FlatIntSet {"+        T.intercalateVec T.comma (T.toTextBuilder 0) vec+        T.char7 '}'++instance Semigroup.Semigroup FlatIntSet where+    {-# INLINE (<>) #-}+    (<>) = merge++instance Monoid.Monoid FlatIntSet where+    {-# INLINE mappend #-}+    mappend = merge+    {-# INLINE mempty #-}+    mempty = empty++instance Arbitrary FlatIntSet where+    arbitrary = pack <$> arbitrary+    shrink v = pack <$> shrink (unpack v)++instance CoArbitrary FlatIntSet where+    coarbitrary = coarbitrary . unpack++size :: FlatIntSet -> Int+{-# INLINE size #-}+size = V.length . sortedValues++null :: FlatIntSet -> Bool+{-# INLINE null #-}+null = V.null . sortedValues++-- | Mapping values of within a set, the result size may change if there're duplicated values+-- after mapping.+map' :: (Int -> Int) -> FlatIntSet -> FlatIntSet+{-# INLINE map' #-}+map' f (FlatIntSet vs) = packVector (V.map' f vs)++-- | /O(1)/ empty flat set.+empty :: FlatIntSet+{-# INLINE empty #-}+empty = FlatIntSet V.empty++-- | /O(N*logN)/ Pack list of values, on duplication prefer left one.+pack :: [Int] -> FlatIntSet+{-# INLINE pack #-}+pack vs = FlatIntSet (V.mergeDupAdjacentLeft (==) (V.mergeSort (V.pack vs)))++-- | /O(N*logN)/ Pack list of values with suggested size, on duplication prefer left one.+packN :: Int -> [Int] -> FlatIntSet+{-# INLINE packN #-}+packN n vs = FlatIntSet (V.mergeDupAdjacentLeft (==) (V.mergeSort (V.packN n vs)))++-- | /O(N*logN)/ Pack list of values, on duplication prefer right one.+packR :: [Int] -> FlatIntSet+{-# INLINE packR #-}+packR vs = FlatIntSet (V.mergeDupAdjacentRight (==) (V.mergeSort (V.pack vs)))++-- | /O(N*logN)/ Pack list of values with suggested size, on duplication prefer right one.+packRN :: Int -> [Int] -> FlatIntSet+{-# INLINE packRN #-}+packRN n vs = FlatIntSet (V.mergeDupAdjacentRight (==) (V.mergeSort (V.packN n vs)))++-- | /O(N)/ Unpack a set of values to a list s in ascending order.+--+-- This function works with @foldr/build@ fusion in base.+unpack :: FlatIntSet -> [Int]+{-# INLINE unpack #-}+unpack = V.unpack . sortedValues++-- | /O(N)/ Unpack a set of values to a list s in descending order.+--+-- This function works with @foldr/build@ fusion in base.+unpackR :: FlatIntSet -> [Int]+{-# INLINE unpackR #-}+unpackR = V.unpackR . sortedValues++-- | /O(N*logN)/ Pack vector of values, on duplication prefer left one.+packVector :: V.PrimVector Int -> FlatIntSet+{-# INLINE packVector #-}+packVector vs = FlatIntSet (V.mergeDupAdjacentLeft (==) (V.mergeSort vs))++-- | /O(N*logN)/ Pack vector of values, on duplication prefer right one.+packVectorR :: V.PrimVector Int -> FlatIntSet+{-# INLINE packVectorR #-}+packVectorR vs = FlatIntSet (V.mergeDupAdjacentRight (==) (V.mergeSort vs))++-- | /O(logN)/ Binary search on flat set.+elem :: Int -> FlatIntSet -> Bool+{-# INLINE elem #-}+elem v (FlatIntSet vec) = case binarySearch vec v of Left _ -> False+                                                     _      -> True++-- | /O(N)/ Insert new value into set.+insert :: Int -> FlatIntSet -> FlatIntSet+{-# INLINE insert #-}+insert v m@(FlatIntSet vec@(V.PrimVector arr s l)) =+    case binarySearch vec v of+        Left i -> FlatIntSet (V.create (l+1) (\ marr -> do+            when (i>s) $ A.copyPrimArray marr 0 arr s (i-s)+            A.writePrimArray marr i v+            when (i<(s+l)) $ A.copyPrimArray marr (i+1) arr i (s+l-i)))+        Right _ -> m++-- | /O(N)/ Delete a value.+delete :: Int -> FlatIntSet -> FlatIntSet+{-# INLINE delete #-}+delete v m@(FlatIntSet vec@(V.PrimVector arr s l)) =+    case binarySearch vec v of+        Left _ -> m+        Right i -> FlatIntSet $ V.create (l-1) (\ marr -> do+            when (i>s) $ A.copyPrimArray marr 0 arr s (i-s)+            let !end = s+l+                !j = i+1+            when (end > j) $ A.copyPrimArray marr 0 arr j (end-j))++-- | /O(n+m)/ Merge two 'FlatIntSet', prefer right value on value duplication.+merge :: FlatIntSet -> FlatIntSet -> FlatIntSet+{-# INLINE merge #-}+merge fmL@(FlatIntSet (V.PrimVector arrL sL lL)) fmR@(FlatIntSet (V.PrimVector arrR sR lR))+    | null fmL = fmR+    | null fmR = fmL+    | otherwise = FlatIntSet (V.createN (lL+lR) (go sL sR 0))+  where+    endL = sL + lL+    endR = sR + lR+    go :: Int -> Int -> Int -> A.MutablePrimArray s Int -> ST s Int+    go !i !j !k marr+        | i >= endL = do+            A.copyPrimArray marr k arrR j (lR-j)+            return $! k+lR-j+        | j >= endR = do+            A.copyPrimArray marr k arrL i (lL-i)+            return $! k+lL-i+        | otherwise = do+            let !vL = arrL `A.indexPrimArray` i+            let !vR = arrR `A.indexPrimArray` j+            case vL `compare` vR of LT -> do A.writePrimArray marr k vL+                                             go (i+1) j (k+1) marr+                                    EQ -> do A.writePrimArray marr k vR+                                             go (i+1) (j+1) (k+1) marr+                                    _  -> do A.writePrimArray marr k vR+                                             go i (j+1) (k+1) marr++--------------------------------------------------------------------------------++-- | Find the value's index in the vector slice, if value exists return 'Right',+-- otherwise 'Left', i.e. the insert index+--+-- This function only works on ascending sorted vectors.+binarySearch :: V.PrimVector Int -> Int -> Either Int Int+{-# INLINABLE binarySearch #-}+binarySearch (V.PrimVector _ _ 0) _   = Left 0+binarySearch (V.PrimVector arr s0 l) !v' = go s0 (s0+l-1)+  where+    go !s !e+        | s == e =+            let v = arr `A.indexPrimArray` s+            in case v' `compare` v of LT -> Left s+                                      GT -> let !s' = s+1 in Left s'+                                      _  -> Right s+        | s >  e = Left s+        | otherwise =+            let !mid = (s+e) `shiftR` 1+                v = arr `A.indexPrimArray` mid+            in case v' `compare` v of LT -> go s (mid-1)+                                      GT -> go (mid+1) e+                                      _  -> Right mid
+ Z/Data/Vector/FlatMap.hs view
@@ -0,0 +1,394 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Z.Data.Vector.FlatMap+Description : Fast map based on sorted 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 a simple key value map based on sorted vector and binary search. It's particularly+suitable for small sized key value collections such as deserializing intermediate representation.+But can also used in various place where insertion and deletion is rare but require fast lookup.++-}++module Z.Data.Vector.FlatMap+  ( -- * FlatMap backed by sorted vector+    FlatMap, sortedKeyValues, size, null, empty, map', kmap'+  , pack, packN, packR, packRN+  , unpack, unpackR, packVector, packVectorR+  , lookup+  , delete+  , insert+  , adjust'+  , merge, mergeWithKey'+    -- * fold and traverse+  , foldrWithKey, foldrWithKey', foldlWithKey, foldlWithKey', traverseWithKey+    -- * binary & linear search on vectors+  , binarySearch+  , linearSearch, linearSearchR+  ) where++import           Control.DeepSeq+import           Control.Monad+import           Control.Monad.ST+import qualified Data.Primitive.SmallArray  as A+import qualified Data.Foldable              as Foldable+import qualified Data.Traversable           as Traversable+import qualified Data.Semigroup             as Semigroup+import qualified Data.Monoid                as Monoid+import qualified Z.Data.Vector.Base as V+import qualified Z.Data.Vector.Sort as V+import qualified Z.Data.Text.Builder        as T+import           Data.Function              (on)+import           Data.Bits                   (shiftR)+import           Data.Data+import           Prelude hiding (lookup, null)+import           Test.QuickCheck.Arbitrary (Arbitrary(..), CoArbitrary(..))++--------------------------------------------------------------------------------++newtype FlatMap k v = FlatMap { sortedKeyValues :: V.Vector (k, v) }+    deriving (Show, Eq, Ord, Typeable)++instance (T.ToText k, T.ToText v) => T.ToText (FlatMap k v) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder p (FlatMap vec) = T.parenWhen (p > 10) $ do+        T.unsafeFromBuilder "FlatMap {"+        T.intercalateVec T.comma (\ (k, v) ->+            T.toTextBuilder 0 k >> ":" >> T.toTextBuilder 0 v) vec+        T.char7 '}'++instance (Ord k, Arbitrary k, Arbitrary v) => Arbitrary (FlatMap k v) where+    arbitrary = pack <$> arbitrary+    shrink v = pack <$> shrink (unpack v)++instance (CoArbitrary k, CoArbitrary v) => CoArbitrary (FlatMap k v) where+    coarbitrary = coarbitrary . unpack++instance Ord k => Semigroup.Semigroup (FlatMap k v) where+    {-# INLINE (<>) #-}+    (<>) = merge++instance Ord k => Monoid.Monoid (FlatMap k v) where+    {-# INLINE mappend #-}+    mappend = merge+    {-# INLINE mempty #-}+    mempty = empty++instance (NFData k, NFData v) => NFData (FlatMap k v) where+    {-# INLINE rnf #-}+    rnf (FlatMap kvs) = rnf kvs++instance Functor (FlatMap k) where+    {-# INLINE fmap #-}+    fmap f (FlatMap vs) = FlatMap (V.map' (fmap f) vs)++instance Foldable.Foldable (FlatMap k) where+    {-# INLINE foldr' #-}+    foldr' f = foldrWithKey' (const f)+    {-# INLINE foldr #-}+    foldr f = foldrWithKey (const f)+    {-# INLINE foldl' #-}+    foldl' f = foldlWithKey' (\ a _ v -> f a v)+    {-# INLINE foldl #-}+    foldl f = foldlWithKey (\ a _ v -> f a v)+    {-# INLINE toList #-}+    toList = fmap snd . unpack+    {-# INLINE null #-}+    null (FlatMap vs) = V.null vs+    {-# INLINE length #-}+    length (FlatMap vs) = V.length vs+    {-# INLINE elem #-}+    elem a (FlatMap vs) = elem a (map snd $ V.unpack vs)++instance Traversable.Traversable (FlatMap k) where+    {-# INLINE traverse #-}+    traverse f = traverseWithKey (const f)++size :: FlatMap k v -> Int+{-# INLINE size #-}+size = V.length . sortedKeyValues++null :: FlatMap k v -> Bool+{-# INLINE null #-}+null = V.null . sortedKeyValues++map' :: (v -> v') -> FlatMap k v -> FlatMap k v'+{-# INLINE map' #-}+map' f (FlatMap vs) = FlatMap (V.map' (fmap f) vs)++kmap' :: (k -> v -> v') -> FlatMap k v -> FlatMap k v'+{-# INLINE kmap' #-}+kmap' f (FlatMap vs) = FlatMap (V.map' (\ (k, v) -> (k, f k v)) vs)++-- | /O(1)/ empty flat map.+empty :: FlatMap k v+{-# INLINE empty #-}+empty = FlatMap V.empty++-- | /O(N*logN)/ Pack list of key values, on key duplication prefer left one.+pack :: Ord k => [(k, v)] -> FlatMap k v+{-# INLINE pack #-}+pack kvs = FlatMap (V.mergeDupAdjacentLeft ((==) `on` fst) (V.mergeSortBy (compare `on` fst) (V.pack kvs)))++-- | /O(N*logN)/ Pack list of key values with suggested size, on key duplication prefer left one.+packN :: Ord k => Int -> [(k, v)] -> FlatMap k v+{-# INLINE packN #-}+packN n kvs = FlatMap (V.mergeDupAdjacentLeft ((==) `on` fst) (V.mergeSortBy (compare `on` fst) (V.packN n kvs)))++-- | /O(N*logN)/ Pack list of key values, on key duplication prefer right one.+packR :: Ord k => [(k, v)] -> FlatMap k v+{-# INLINE packR #-}+packR kvs = FlatMap (V.mergeDupAdjacentRight ((==) `on` fst) (V.mergeSortBy (compare `on` fst) (V.pack kvs)))++-- | /O(N*logN)/ Pack list of key values with suggested size, on key duplication prefer right one.+packRN :: Ord k => Int -> [(k, v)] -> FlatMap k v+{-# INLINE packRN #-}+packRN n kvs = FlatMap (V.mergeDupAdjacentRight ((==) `on` fst) (V.mergeSortBy (compare `on` fst) (V.packN n kvs)))++-- | /O(N)/ Unpack key value pairs to a list sorted by keys in ascending order.+--+-- This function works with @foldr/build@ fusion in base.+unpack :: FlatMap k v -> [(k, v)]+{-# INLINE unpack #-}+unpack = V.unpack . sortedKeyValues++-- | /O(N)/ Unpack key value pairs to a list sorted by keys in descending order.+--+-- This function works with @foldr/build@ fusion in base.+unpackR :: FlatMap k v -> [(k, v)]+{-# INLINE unpackR #-}+unpackR = V.unpackR . sortedKeyValues++-- | /O(N*logN)/ Pack vector of key values, on key duplication prefer left one.+packVector :: Ord k => V.Vector (k, v) -> FlatMap k v+{-# INLINE packVector #-}+packVector kvs = FlatMap (V.mergeDupAdjacentLeft ((==) `on` fst) (V.mergeSortBy (compare `on` fst) kvs))++-- | /O(N*logN)/ Pack vector of key values, on key duplication prefer right one.+packVectorR :: Ord k => V.Vector (k, v) -> FlatMap k v+{-# INLINE packVectorR #-}+packVectorR kvs = FlatMap (V.mergeDupAdjacentRight ((==) `on` fst) (V.mergeSortBy (compare `on` fst) kvs))++-- | /O(logN)/ Binary search on flat map.+lookup :: Ord k => k -> FlatMap k v -> Maybe v+{-# INLINABLE lookup #-}+lookup _  (FlatMap (V.Vector _ _ 0)) = Nothing+lookup k' (FlatMap (V.Vector arr s l)) = go s (s+l-1)+  where+    go !i !j+        | i == j =+            case arr `A.indexSmallArray` i of (k, v)  | k == k'  -> Just v+                                                      | otherwise -> Nothing+        | i >  j = Nothing+        | otherwise =+            let mid = (i+j) `shiftR` 1+                (k, v)  = arr `A.indexSmallArray` mid+            in case k' `compare` k of LT -> go i (mid-1)+                                      GT -> go (mid+1) j+                                      _  -> Just v++-- | /O(N)/ Insert new key value into map, replace old one if key exists.+insert :: Ord k => k -> v -> FlatMap k v -> FlatMap k v+{-# INLINE insert #-}+insert k v (FlatMap vec@(V.Vector arr s l)) =+    case binarySearch vec k of+        Left i -> FlatMap (V.create (l+1) (\ marr -> do+            when (i>s) $ A.copySmallArray marr 0 arr s (i-s)+            A.writeSmallArray marr i (k, v)+            when (i<(s+l)) $ A.copySmallArray marr (i+1) arr i (s+l-i)))+        Right i -> FlatMap (V.Vector (runST (do+            let arr' = A.cloneSmallArray arr s l+            marr <- A.unsafeThawSmallArray arr'+            A.writeSmallArray marr i (k, v)+            A.unsafeFreezeSmallArray marr)) 0 l)++-- | /O(N)/ Delete a key value pair by key.+delete :: Ord k => k -> FlatMap k v -> FlatMap k v+{-# INLINE delete #-}+delete k m@(FlatMap vec@(V.Vector arr s l)) =+    case binarySearch vec k of+        Left _ -> m+        Right i -> FlatMap $ V.create (l-1) (\ marr -> do+            when (i>s) $ A.copySmallArray marr 0 arr s (i-s)+            let !end = s+l+                !j = i+1+            when (end > j) $ A.copySmallArray marr 0 arr j (end-j))++-- | /O(N)/ Modify a value by key.+--+-- The value is evaluated to WHNF before writing into map.+adjust' :: Ord k => (v -> v) -> k -> FlatMap k v -> FlatMap k v+{-# INLINE adjust' #-}+adjust' f k m@(FlatMap vec@(V.Vector arr s l)) =+    case binarySearch vec k of+        Left _ -> m+        Right i -> FlatMap $ V.create l (\ marr -> do+            A.copySmallArray marr 0 arr s l+            let !v' = f (snd (A.indexSmallArray arr i))+            A.writeSmallArray marr i (k, v'))++-- | /O(n+m)/ Merge two 'FlatMap', prefer right value on key duplication.+merge :: forall k v. Ord k => FlatMap k v -> FlatMap k v -> FlatMap k v+{-# INLINE merge #-}+merge fmL@(FlatMap (V.Vector arrL sL lL)) fmR@(FlatMap (V.Vector arrR sR lR))+    | null fmL = fmR+    | null fmR = fmL+    | otherwise = FlatMap (V.createN (lL+lR) (go sL sR 0))+  where+    endL = sL + lL+    endR = sR + lR+    go :: Int -> Int -> Int -> A.SmallMutableArray s (k, v) -> ST s Int+    go !i !j !k marr+        | i >= endL = do+            A.copySmallArray marr k arrR j (lR-j)+            return $! k+lR-j+        | j >= endR = do+            A.copySmallArray marr k arrL i (lL-i)+            return $! k+lL-i+        | otherwise = do+            kvL@(kL, _) <- arrL `A.indexSmallArrayM` i+            kvR@(kR, _) <- arrR `A.indexSmallArrayM` j+            case kL `compare` kR of LT -> do A.writeSmallArray marr k kvL+                                             go (i+1) j (k+1) marr+                                    EQ -> do A.writeSmallArray marr k kvR+                                             go (i+1) (j+1) (k+1) marr+                                    _  -> do A.writeSmallArray marr k kvR+                                             go i (j+1) (k+1) marr++-- | /O(n+m)/ Merge two 'FlatMap' with a merge function.+mergeWithKey' :: forall k v. Ord k => (k -> v -> v -> v) -> FlatMap k v -> FlatMap k v -> FlatMap k v+{-# INLINABLE mergeWithKey' #-}+mergeWithKey' f fmL@(FlatMap (V.Vector arrL sL lL)) fmR@(FlatMap (V.Vector arrR sR lR))+    | null fmL = fmR+    | null fmR = fmL+    | otherwise = FlatMap (V.createN (lL+lR) (go sL sR 0))+  where+    endL = sL + lL+    endR = sR + lR+    go :: Int -> Int -> Int -> A.SmallMutableArray s (k, v) -> ST s Int+    go !i !j !k marr+        | i >= endL = do+            A.copySmallArray marr k arrR j (lR-j)+            return $! k+lR-j+        | j >= endR = do+            A.copySmallArray marr k arrL i (lL-i)+            return $! k+lL-i+        | otherwise = do+            kvL@(kL, vL) <- arrL `A.indexSmallArrayM` i+            kvR@(kR, vR) <- arrR `A.indexSmallArrayM` j+            case kL `compare` kR of LT -> do A.writeSmallArray marr k kvL+                                             go (i+1) j (k+1) marr+                                    EQ -> do let !v' = f kL vL vR+                                             A.writeSmallArray marr k (kL, v')+                                             go (i+1) (j+1) (k+1) marr+                                    _  -> do A.writeSmallArray marr k kvR+                                             go i (j+1) (k+1) marr+++-- | /O(n)/ Reduce this map by applying a binary operator to all+-- elements, using the given starting value (typically the+-- right-identity of the operator).+--+-- During folding k is in descending order.+foldrWithKey :: (k -> v -> a -> a) -> a -> FlatMap k v -> a+{-# INLINE foldrWithKey #-}+foldrWithKey f a (FlatMap vs) = foldr (uncurry f) a vs++-- | /O(n)/ Reduce this map by applying a binary operator to all+-- elements, using the given starting value (typically the+-- right-identity of the operator).+--+-- During folding k is in ascending order.+foldlWithKey :: (a -> k -> v -> a) -> a -> FlatMap k v -> a+{-# INLINE foldlWithKey #-}+foldlWithKey f a (FlatMap vs) = foldl (\ a' (k,v) -> f a' k v) a vs++-- | /O(n)/ Reduce this map by applying a binary operator to all+-- elements, using the given starting value (typically the+-- right-identity of the operator).+--+-- During folding k is in descending order.+foldrWithKey' :: (k -> v -> a -> a) -> a -> FlatMap k v -> a+{-# INLINE foldrWithKey' #-}+foldrWithKey' f a (FlatMap vs) = V.foldr' (uncurry f) a vs++-- | /O(n)/ Reduce this map by applying a binary operator to all+-- elements, using the given starting value (typically the+-- right-identity of the operator).+--+-- During folding k is in ascending order.+foldlWithKey' :: (a -> k -> v -> a) -> a -> FlatMap k v -> a+{-# INLINE foldlWithKey' #-}+foldlWithKey' f a (FlatMap vs) = V.foldl' (\ a' (k,v) -> f a' k v) a vs++-- | /O(n)/.+-- @'traverseWithKey' f s == 'pack' <$> 'traverse' (\(k, v) -> (,) k <$> f k v) ('unpack' m)@+-- That is, behaves exactly like a regular 'traverse' except that the traversing+-- function also has access to the key associated with a value.+traverseWithKey :: Applicative t => (k -> a -> t b) -> FlatMap k a -> t (FlatMap k b)+{-# INLINE traverseWithKey #-}+traverseWithKey f (FlatMap vs) = FlatMap <$> traverse (\ (k,v) -> (k,) <$> f k v) vs++--------------------------------------------------------------------------------++-- | Find the key's index in the vector slice, if key exists return 'Right',+-- otherwise 'Left', i.e. the insert index+--+-- This function only works on ascending sorted vectors.+binarySearch :: Ord k => V.Vector (k, v) -> k -> Either Int Int+{-# INLINABLE binarySearch #-}+binarySearch (V.Vector _ _ 0) _   = Left 0+binarySearch (V.Vector arr s l) !k' = go s (s+l-1)+  where+    go !i !j+        | i == j =+            let (k, _)  = arr `A.indexSmallArray` i+            in case k' `compare` k of LT -> Left i+                                      GT -> let !i' = i+1 in Left i'+                                      _  -> Right i+        | i >  j = Left i+        | otherwise =+            let !mid = (i+j) `shiftR` 1+                (k, _)  = arr `A.indexSmallArray` mid+            in case k' `compare` k of LT -> go i (mid-1)+                                      GT -> go (mid+1) j+                                      _  -> Right mid++--------------------------------------------------------------------------------++-- | linear scan search from left to right, return the first one if exist.+linearSearch :: Ord k => V.Vector (k, v) -> k -> Maybe v+{-# INLINABLE linearSearch #-}+linearSearch (V.Vector arr s l) !k' = go s+  where+    !end = s + l+    go !i+        | i >= end = Nothing+        | otherwise =+            let (k, v)  = arr `A.indexSmallArray` i+            in if k' == k then Just v else go (i+1)++-- | linear scan search from right to left, return the first one if exist.+linearSearchR :: Ord k => V.Vector (k, v) -> k -> Maybe v+{-# INLINABLE linearSearchR #-}+linearSearchR (V.Vector arr s l) !k' = go (s+l-1)+  where+    go !i+        | i < s = Nothing+        | otherwise =+            let (k, v)  = arr `A.indexSmallArray` i+            in if k' == k then Just v else go (i-1)
+ Z/Data/Vector/FlatSet.hs view
@@ -0,0 +1,227 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Z.Data.Vector.FlatSet+Description : Fast set based on sorted 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 a simple value set based on sorted vector and binary search. It's particularly+suitable for small sized value collections such as deserializing intermediate representation.+But can also used in various place where insertion and deletion is rare but require fast elem.++-}++module Z.Data.Vector.FlatSet+  ( -- * FlatSet backed by sorted vector+    FlatSet, sortedValues, size, null, empty, map'+  , pack, packN, packR, packRN+  , unpack, unpackR, packVector, packVectorR+  , elem+  , delete+  , insert+  , merge+    -- * binary & linear search on vectors+  , binarySearch+  ) where++import           Control.DeepSeq+import           Control.Monad+import           Control.Monad.ST+import qualified Data.Primitive.SmallArray  as A+import qualified Data.Semigroup             as Semigroup+import qualified Data.Monoid                as Monoid+import qualified Z.Data.Vector.Base as V+import qualified Z.Data.Vector.Sort as V+import qualified Z.Data.Text.Builder        as T+import           Data.Bits                   (shiftR)+import           Data.Data+import           Prelude hiding (elem, null)+import           Test.QuickCheck.Arbitrary (Arbitrary(..), CoArbitrary(..))++--------------------------------------------------------------------------------++newtype FlatSet v = FlatSet { sortedValues :: V.Vector v }+    deriving (Show, Eq, Ord, Typeable, Foldable, NFData)++instance T.ToText v => T.ToText (FlatSet v) where+    {-# INLINE toTextBuilder #-}+    toTextBuilder p (FlatSet vec) = T.parenWhen (p > 10) $ do+        T.unsafeFromBuilder "FlatSet {"+        T.intercalateVec T.comma (T.toTextBuilder 0) vec+        T.char7 '}'++instance Ord v => Semigroup.Semigroup (FlatSet v) where+    {-# INLINE (<>) #-}+    (<>) = merge++instance Ord v => Monoid.Monoid (FlatSet v) where+    {-# INLINE mappend #-}+    mappend = merge+    {-# INLINE mempty #-}+    mempty = empty++instance (Ord v, Arbitrary v) => Arbitrary (FlatSet v) where+    arbitrary = pack <$> arbitrary+    shrink v = pack <$> shrink (unpack v)++instance (CoArbitrary v) => CoArbitrary (FlatSet v) where+    coarbitrary = coarbitrary . unpack++size :: FlatSet v -> Int+{-# INLINE size #-}+size = V.length . sortedValues++null :: FlatSet v -> Bool+{-# INLINE null #-}+null = V.null . sortedValues++-- | Mapping values of within a set, the result size may change if there're duplicated values+-- after mapping.+map' :: forall v. Ord v => (v -> v) -> FlatSet v -> FlatSet v+{-# INLINE map' #-}+map' f (FlatSet vs) = packVector (V.map' f vs :: V.Vector v)++-- | /O(1)/ empty flat set.+empty :: FlatSet v+{-# INLINE empty #-}+empty = FlatSet V.empty++-- | /O(N*logN)/ Pack list of values, on duplication prefer left one.+pack :: Ord v => [v] -> FlatSet v+{-# INLINE pack #-}+pack vs = FlatSet (V.mergeDupAdjacentLeft (==) (V.mergeSort (V.pack vs)))++-- | /O(N*logN)/ Pack list of values with suggested size, on duplication prefer left one.+packN :: Ord v => Int -> [v] -> FlatSet v+{-# INLINE packN #-}+packN n vs = FlatSet (V.mergeDupAdjacentLeft (==) (V.mergeSort (V.packN n vs)))++-- | /O(N*logN)/ Pack list of values, on duplication prefer right one.+packR :: Ord v => [v] -> FlatSet v+{-# INLINE packR #-}+packR vs = FlatSet (V.mergeDupAdjacentRight (==) (V.mergeSort (V.pack vs)))++-- | /O(N*logN)/ Pack list of values with suggested size, on duplication prefer right one.+packRN :: Ord v => Int -> [v] -> FlatSet v+{-# INLINE packRN #-}+packRN n vs = FlatSet (V.mergeDupAdjacentRight (==) (V.mergeSort (V.packN n vs)))++-- | /O(N)/ Unpack a set of values to a list s in ascending order.+--+-- This function works with @foldr/build@ fusion in base.+unpack :: FlatSet v -> [v]+{-# INLINE unpack #-}+unpack = V.unpack . sortedValues++-- | /O(N)/ Unpack a set of values to a list s in descending order.+--+-- This function works with @foldr/build@ fusion in base.+unpackR :: FlatSet v -> [v]+{-# INLINE unpackR #-}+unpackR = V.unpackR . sortedValues++-- | /O(N*logN)/ Pack vector of values, on duplication prefer left one.+packVector :: Ord v => V.Vector v -> FlatSet v+{-# INLINE packVector #-}+packVector vs = FlatSet (V.mergeDupAdjacentLeft (==) (V.mergeSort vs))++-- | /O(N*logN)/ Pack vector of values, on duplication prefer right one.+packVectorR :: Ord v => V.Vector v -> FlatSet v+{-# INLINE packVectorR #-}+packVectorR vs = FlatSet (V.mergeDupAdjacentRight (==) (V.mergeSort vs))++-- | /O(logN)/ Binary search on flat set.+elem :: Ord v => v -> FlatSet v -> Bool+{-# INLINE elem #-}+elem v (FlatSet vec) = case binarySearch vec v of Left _ -> False+                                                  _      -> True++-- | /O(N)/ Insert new value into set.+insert :: Ord v => v -> FlatSet v -> FlatSet v+{-# INLINE insert #-}+insert v m@(FlatSet vec@(V.Vector arr s l)) =+    case binarySearch vec v of+        Left i -> FlatSet (V.create (l+1) (\ marr -> do+            when (i>s) $ A.copySmallArray marr 0 arr s (i-s)+            A.writeSmallArray marr i v+            when (i<(s+l)) $ A.copySmallArray marr (i+1) arr i (s+l-i)))+        Right _ -> m++-- | /O(N)/ Delete a value from set.+delete :: Ord v => v -> FlatSet v -> FlatSet v+{-# INLINE delete #-}+delete v m@(FlatSet vec@(V.Vector arr s l)) =+    case binarySearch vec v of+        Left _ -> m+        Right i -> FlatSet $ V.create (l-1) (\ marr -> do+            when (i>s) $ A.copySmallArray marr 0 arr s (i-s)+            let !end = s+l+                !j = i+1+            when (end > j) $ A.copySmallArray marr 0 arr j (end-j))++-- | /O(n+m)/ Merge two 'FlatSet', prefer right value on value duplication.+merge :: forall v . Ord v => FlatSet v -> FlatSet v -> FlatSet v+{-# INLINE merge #-}+merge fmL@(FlatSet (V.Vector arrL sL lL)) fmR@(FlatSet (V.Vector arrR sR lR))+    | null fmL = fmR+    | null fmR = fmL+    | otherwise = FlatSet (V.createN (lL+lR) (go sL sR 0))+  where+    endL = sL + lL+    endR = sR + lR+    go :: Int -> Int -> Int -> A.SmallMutableArray s v -> ST s Int+    go !i !j !k marr+        | i >= endL = do+            A.copySmallArray marr k arrR j (lR-j)+            return $! k+lR-j+        | j >= endR = do+            A.copySmallArray marr k arrL i (lL-i)+            return $! k+lL-i+        | otherwise = do+            vL <- arrL `A.indexSmallArrayM` i+            vR <- arrR `A.indexSmallArrayM` j+            case vL `compare` vR of LT -> do A.writeSmallArray marr k vL+                                             go (i+1) j (k+1) marr+                                    EQ -> do A.writeSmallArray marr k vR+                                             go (i+1) (j+1) (k+1) marr+                                    _  -> do A.writeSmallArray marr k vR+                                             go i (j+1) (k+1) marr++--------------------------------------------------------------------------------++-- | Find the value's index in the vector slice, if value exists return 'Right',+-- otherwise 'Left', i.e. the insert index+--+-- This function only works on ascending sorted vectors.+binarySearch :: Ord v => V.Vector v -> v -> Either Int Int+{-# INLINABLE binarySearch #-}+binarySearch (V.Vector _ _ 0) _   = Left 0+binarySearch (V.Vector arr s0 l) !v' = go s0 (s0+l-1)+  where+    go !s !e+        | s == e =+            let v = arr `A.indexSmallArray` s+            in case v' `compare` v of LT -> Left s+                                      GT -> let !s' = s+1 in Left s'+                                      _  -> Right s+        | s >  e = Left s+        | otherwise =+            let !mid = (s+e) `shiftR` 1+                v = arr `A.indexSmallArray` mid+            in case v' `compare` v of LT -> go s (mid-1)+                                      GT -> go (mid+1) e+                                      _  -> Right mid
+ Z/Data/Vector/QQ.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE MagicHash #-}++{-|+Module      : Z.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 Z.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           Z.Data.Array.QQ                as QQ+import           Z.Data.Vector.Base++--------------------------------------------------------------------------------+-- Quoters++ascii :: QQ.QuasiQuoter+ascii = QQ.QuasiQuoter+    (asciiLiteral $ \ len addr -> [| PrimVector (QQ.word8ArrayFromAddr $(len) $(addr)) 0 $(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 $(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 $(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 $(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 $(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 $(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 $(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 $(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 $(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 $(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 $(len) |])+    (error "Cannot use vecInt as a pattern")+    (error "Cannot use vecInt as a type")+    (error "Cannot use vecInt as a dec")+
+ Z/Data/Vector/Search.hs view
@@ -0,0 +1,462 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Z.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 Z.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)+import           Z.Data.Array+import           Z.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/Bytes1" forall w. findIndices (w `eqWord8`) = elemIndicesBytes w #-}+{-# RULES "findIndices/Bytes2" 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/Bytes1" forall w. find (w `eqWord8`) = findByte w #-}+{-# RULES "find/Bytes2" 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/Bytes1" forall w. findR (w `eqWord8`) = findByteR w #-}+{-# RULES "findR/Bytes2" 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 (PrimArray ba#) s l) =+    case c_memrchr ba# s w 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 g (Vec arr s l)+    | l == 0    = empty+    | otherwise = createN l (go g 0 s)+  where+    !end = s + l+    go :: (a -> Bool) -> Int -> Int -> MArr (IArray 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 g (Vec arr s l)+    | l == 0    = (empty, empty)+    | otherwise = createN2 l l (go g 0 0 s)+  where+    !end = s + l+    go :: (a -> Bool) -> Int -> Int -> Int -> MArr (IArray v) s a -> MArr (IArray 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
+ Z/Data/Vector/Sort.hs view
@@ -0,0 +1,498 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE CPP #-}++{-|+Module      : Z.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 Z.Data.Vector.Sort (+  -- * Sort+    mergeSort+  , mergeSortBy+  , mergeTileSize+  , insertSort+  , insertSortBy+  , Down(..)+  , radixSort+  , Radix(..)+  , RadixDown(..)+  -- * merge duplicated+  , mergeDupAdjacent+  , mergeDupAdjacentLeft+  , mergeDupAdjacentRight+  , mergeDupAdjacentBy+  ) where++import           Control.Monad.ST+import           Data.Bits+import           Data.Int+import           Data.Ord               (Down (..))+import           Data.Primitive         (sizeOf)+import           Data.Word+import           Prelude                hiding (splitAt)+import           Z.Data.Array+import           Z.Data.Vector.Base+import           Z.Data.Vector.Extra++--------------------------------------------------------------------------------+-- 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 vec@(Vec _ _ l)+    | l <= mergeTileSize = insertSortBy cmp vec+    | otherwise = runST (do+        -- create two worker array+        w1 <- newArr l+        w2 <- newArr l+        firstPass vec 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+        lv <- readArr src i+        rv <- readArr src j+        case rv `cmp` lv of+            LT -> do+                writeArr target k rv+                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 lv+                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 = 8@.+mergeTileSize :: Int+{-# INLINE mergeTileSize #-}+mergeTileSize = 8++-- | /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 cmp v@(Vec _ _ l) | l <= 1 = v+                               | otherwise = 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+                  -> MArr (IArray 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 arr s l)+    | l <= 1 = v+    | otherwise = 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 !bsiz !i !acc+        | i >= bsiz = return ()+        | otherwise = do+            c <- readArr bucket i+            writeArr bucket i acc+            accumBucket bucket bsiz (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 !bsiz !pass+        | pass >= passSiz-1 = do+            setArr bucket 0 bsiz 0   -- clear the counting bucket+            lastCountPass w1 bucket 0+            accumBucket bucket bsiz 0 0+            lastMovePass w1 bucket w2 0+            unsafeFreezeArr w2+        | otherwise = do+            setArr bucket 0 bsiz 0   -- clear the counting bucket+            countPass w1 bucket pass 0+            accumBucket bucket bsiz 0 0+            movePass w1 bucket pass w2 0+            radixLoop w2 w1 bucket bsiz (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))+-}++--------------------------------------------------------------------------------+-- | merge duplicated adjacent element, prefer left element.+--+-- Use this function on a sorted vector will have the same effects as 'nub'.+mergeDupAdjacent :: (Vec v a, Eq a) => v a -> v a+{-# INLINE mergeDupAdjacent #-}+mergeDupAdjacent = mergeDupAdjacentBy (==) const++-- | Merge duplicated adjacent element, prefer left element.+mergeDupAdjacentLeft :: Vec v a+                     => (a -> a -> Bool)   -- ^ equality tester, @\ left right -> eq left right@+                     -> v a+                     -> v a+mergeDupAdjacentLeft eq = mergeDupAdjacentBy eq const+{-# INLINE mergeDupAdjacentLeft #-}++-- | Merge duplicated adjacent element, prefer right element.+mergeDupAdjacentRight :: Vec v a+                      => (a -> a -> Bool)  -- ^ equality tester, @\ left right -> eq left right@+                      -> v a+                      -> v a+{-# INLINE mergeDupAdjacentRight #-}+mergeDupAdjacentRight eq = mergeDupAdjacentBy eq (\ _ x -> x)++-- | Merge duplicated adjacent element, based on a equality tester and a merger function.+mergeDupAdjacentBy :: Vec v a+                   => (a -> a -> Bool)  -- ^ equality tester, @\ left right -> eq left right@+                   -> (a -> a -> a)     -- ^ the merger, @\ left right -> merge left right@+                   -> v a -> v a+{-# INLINABLE mergeDupAdjacentBy #-}+mergeDupAdjacentBy eq merger v@(Vec arr s l)+    | l == 0 = empty+    | l == 1 = v+    | otherwise = createN l $ \ marr -> do+        x0 <- indexArrM arr 0+        writeArr marr 0 x0+        go arr marr s 1 x0+  where+    !end = s + l+    go !arr' !marr !i !j !x+        | i >= end  = return j+        | otherwise = do+            x' <- indexArrM arr' i+            if x `eq` x'+            then do+                let !x'' = merger x x'+                writeArr marr (j-1) x''+                go arr' marr (i+1) j x''+            else do+                writeArr marr j x'+                go arr' marr (i+1) (j+1) x'
+ Z/Foreign.hs view
@@ -0,0 +1,291 @@+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-|+Module      : Z.Foreign+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.++-}++module Z.Foreign+  ( -- ** Unsafe FFI+    withPrimArrayUnsafe+  , withMutablePrimArrayUnsafe+  , allocMutableByteArrayUnsafe+  , withPrimVectorUnsafe+  , withPrimUnsafe+  , allocPrimUnsafe+    -- ** Safe FFI+  , withPrimArraySafe+  , withMutablePrimArraySafe+  , allocMutablePrimArraySafe+  , withPrimVectorSafe+  , withPrimSafe+  , allocPrimSafe+    -- ** Pointer helpers+  , BA#, MBA#+  , clearPtr+  , castPtr+  -- ** re-export+  , module Data.Primitive.Ptr+  ) where++import           Control.Monad.Primitive+import           Data.Primitive+import           Data.Primitive.Ptr+import           Foreign.C.Types+import           GHC.Ptr+import           Z.Data.Array+import           Z.Data.Vector.Base++-- | 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.+-- A 'ByteArray#' COULD BE MOVED BY GC DURING SAFE FFI CALL.+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.+-- A 'MutableByteArray#' COULD BE MOVED BY GC DURING SAFE FFI CALL.+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+{-# INLINE withPrimArrayUnsafe #-}+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+{-# INLINE withMutablePrimArrayUnsafe #-}+withMutablePrimArrayUnsafe mpa@(MutablePrimArray mba#) f =+    getSizeofMutablePrimArray mpa >>= f mba#++allocMutableByteArrayUnsafe :: Int      -- ^ In bytes not element+                            -> (MBA# a -> IO b) -> IO b+{-# INLINE allocMutableByteArrayUnsafe #-}+allocMutableByteArrayUnsafe 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+{-# INLINE withPrimVectorUnsafe #-}+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)+{-# INLINE withPrimUnsafe #-}+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)++allocPrimUnsafe :: (Prim a) => (MBA# a -> IO b) -> IO (a, b)+{-# INLINE allocPrimUnsafe #-}+allocPrimUnsafe 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+{-# INLINE withPrimArraySafe #-}+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+{-# INLINE withMutablePrimArraySafe #-}+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++allocMutablePrimArraySafe :: (Prim a) => Int -- ^ in number of elements not bytes+                          -> (Ptr a -> IO b) -> IO b+{-# INLINE allocMutablePrimArraySafe #-}+allocMutablePrimArraySafe 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+{-# INLINE withPrimVectorSafe #-}+withPrimVectorSafe (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)+{-# INLINE withPrimSafe #-}+withPrimSafe v f = do+    buf <- newAlignedPinnedPrimArray 1+    writePrimArray buf 0 v+    !b <- withMutablePrimArrayContents buf $ \ ptr -> f ptr+    !a <- readPrimArray buf 0+    return (a, b)++allocPrimSafe :: forall a b. Prim a => (Ptr a -> IO b) -> IO (a, b)+{-# INLINE allocPrimSafe #-}+allocPrimSafe 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 ()+{-# INLINE clearPtr #-}+clearPtr dest nbytes = memset dest 0 (fromIntegral nbytes)
+ cbits/bytes.c view
@@ -0,0 +1,137 @@+/*+Copyright (c) 2017-2019 Dong Han+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);+}++void* __memrchr(void *src_void, unsigned char c, size_t length);+HsInt hs_memrchr(uint8_t *a, HsInt aoff, uint8_t c, HsInt n) {+    uint8_t *s = a + aoff;+    uint8_t *p = __memrchr(s, c, (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);+}++/*+ * memrchr implementation taken from newlib(which is under free software licenses)+ * https://sourceware.org/newlib+*/+/* Nonzero if X is not aligned on a "long" boundary.  */+#define UNALIGNED(X) ((long)(X + 1) & (sizeof (long) - 1))+/* How many bytes are loaded each iteration of the word copy loop.  */+#define LBLOCKSIZE (sizeof (long))+/* Threshhold for punting to the bytewise iterator.  */+#define TOO_SMALL(LEN)  ((LEN) < LBLOCKSIZE)+#if LONG_MAX == 2147483647L+#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)+#else+#if LONG_MAX == 9223372036854775807L+/* Nonzero if X (a long int) contains a NULL byte. */+#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)+#else+#error long int is not a 32bit or 64bit type.+#endif+#endif+#ifndef DETECTNULL+#error long int is not a 32bit or 64bit byte+#endif+/* DETECTCHAR returns nonzero if (long)X contains the byte used+   to fill (long)MASK. */+#define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK))+void* __memrchr(void *src_void, unsigned char c, size_t length){+    unsigned char *src = (unsigned char *) src_void + length - 1;+    unsigned char d = c;+    unsigned long *asrc;+    unsigned long  mask;+    int i;+    while (UNALIGNED (src)) {+        if (!length--)+            return NULL;+        if (*src == d)+            return (void *) src;+        src--;+    }+    if (!TOO_SMALL (length)) {+        /* If we get this far, we know that length is large and src is+         word-aligned. */+        /* The fast code reads the source one word at a time and only+         performs the bytewise search on word-sized segments if they+         contain the search character, which is detected by XORing+         the word-sized segment with a word-sized block of the search+         character and then detecting for the presence of NUL in the+         result.  */+        asrc = (unsigned long *) (src - LBLOCKSIZE + 1);+        mask = d << 8 | d;+        mask = mask << 16 | mask;+        for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)+            mask = (mask << i) | mask;+            while (length >= LBLOCKSIZE) {+                if (DETECTCHAR (*asrc, mask))+                    break;+                length -= LBLOCKSIZE;+                asrc--;+            }+        /* If there are fewer than LBLOCKSIZE characters left,+         then we resort to the bytewise loop.  */+        src = (unsigned char *) asrc + LBLOCKSIZE - 1;+    }+    while (length--) {+        if (*src == d)+            return (void *) src;+        src--;+    }+    return NULL;+}
+ cbits/dtoa.c view
@@ -0,0 +1,452 @@+/*+ * Copyright (c) 2017-2019 Dong Han+ * 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;+}++////////////////////////////////////////////////////////////////////////////////++static const char* digits = "0123456789abcdef";++// convert a positive uint64_t to ascii digits, with following params+// sign: +//  -1: negative +//  0: non-negative+//  1: non-negative with show positive sign options+// width: value smaller than necessary will be ignored+// pad:+//   0: no padding +//   1: right space padding +//   2: left space padding+//   3: left zero padding+// ba, off: buffer bytearray and offset+// buffer must be guaranteed to be have max(width, 21) bytes left for (sign + digits)+//+// return: new offset for next writing+HsInt c_int_dec (uint64_t x, HsInt sign, HsInt width, uint8_t pad, char* ba, HsInt off)+{+    // writing from the right end+    char *start = ba + off, *end = start + (width > 21 ? width : 21), *p = end, *q = start;+    uint64_t mod;++    // encode positive number as little-endian decimal+    do {+        mod = x % 10;+        x = x / 10;+        *(--p) = digits[mod];+    } while ( x );++    switch(pad){+        // no padding, copy to left part+        case 0:+            if (sign != 0) *(q++) = (sign == -1 ? '-' : '+');+            if (q < p) {+                do {+                    *(q++) = *(p++);+                } while (p < end);+                return (q - start) + off;+            } else return (end - start) + off;+        // write right space paddings+        case 1:+            if (sign != 0) *(q++) = (sign == -1 ? '-' : '+');+            if (q < p) {+                do {+                    *(q++) = *(p++);+                } while (p < end);+                while (q < start + width) {+                    *(q++) = ' ';+                }+                return (q - start) + off;+            } else return (end - start) + off;+        // write left space paddings+        case 2:+            if (sign != 0) *(--p) = (sign == -1 ? '-' : '+');+            while (p > end - width){+                *(--p) = ' ';+            }+            if (q < p) {+                do {+                    *(q++) = *(p++);+                } while (p < end);+                return (q - start) + off;+            } else return (end - start) + off;+        // write left zero paddings+        //case 3:+        default:+            if (sign != 0) {+                *(q++) = (sign == -1 ? '-' : '+');+                // we have to make one byte's room for the sign+                while (p > end - width + 1) *(--p) = '0';+            } else  {+                while (p > end - width) *(--p) = '0';+            }+            if (q < p) {+                do {+                    *(q++) = *(p++);+                } while (p < end);+                return (q - start) + off;+            } else return (end -start) + off;+    } +}
+ cbits/text.c view
@@ -0,0 +1,502 @@+#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;+}++////////////////////////////////////////////////////////////////////////////////++// Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>+// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.++#define UTF8_ACCEPT 0+#define UTF8_REJECT 12++static const uint8_t utf8d[] = {+  // The first part of the table maps bytes to character classes that+  // to reduce the size of the transition table and create bitmasks.+   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   // 0x00 ~ 0x1F+   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   // 0x20 ~ 0x3F+   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   // 0x40 ~ 0x5F+   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   // 0x60 ~ 0x7F+   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,   // 0x80 ~ 0x9F+   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,   // 0xA0 ~ 0xBF+   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,   // 0xC0 ~ 0xDF+  10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,   // 0xE0 ~ 0xFF++  // The second part is a transition table that maps a combination+  // of a state of the automaton and a character class to a state.+   0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,+  12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,+  12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,+  12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,+  12,36,12,12,12,12,12,12,12,12,12,12, +};+++static uint32_t inline updatestate(uint32_t *state, uint32_t byte) {+    uint32_t type = utf8d[byte];+    *state = utf8d[256 + *state + type];+    return *state;+}++// return 2 instead of 1, so that we can observe difference if SIMD is not used+HsInt utf8_validate_slow(const char* c, size_t len){+    const unsigned char *cu = (const unsigned char *)c;+    uint32_t state = UTF8_ACCEPT;+    for (size_t i = 0; i < len; i++) {+        uint32_t byteval = (uint32_t)cu[i];+        if (updatestate(&state, byteval) == UTF8_REJECT)+            return 0;+    }+    return ((state == UTF8_ACCEPT) ? 2 : 0);+}++static inline uint32_t decode_hex(uint32_t c) {+    if (c >= '0' && c <= '9')      return c - '0';+    else if (c >= 'a' && c <= 'f') return c - 'a' + 10;+    else if (c >= 'A' && c <= 'F') return c - 'A' + 10;+    return 0xFFFFFFFF; // Should not happen+}++// Decode, return negative value on error+HsInt decode_json_string(char *dest, const char *src, HsInt srcoff, HsInt srclen) {+    char *d = dest;+    const char *s      = src + srcoff;+    const char *srcend = s + srclen;++    uint32_t state = UTF8_ACCEPT;+    unsigned char cur_byte;++    uint8_t surrogate = 0;+    uint32_t temp_hex = 0;+    uint32_t unidata;+    // ECMA 404 require codepoints beyond Basic Multilingual Plane encoded as surrogate pair+    uint32_t h_surrogate;+    uint32_t l_surrogate;++// read current byte to cur_byte and guard input end+#define DISPATCH(label) {\+    if (s >= srcend) {\+        return -1;\+    }\+    cur_byte = *s++;\+    goto label;\+}++standard:+    // Test end of stream+    while (s < srcend) {+        cur_byte = *s++;+        if (updatestate(&state, (uint32_t)cur_byte) == UTF8_REJECT) { return -1; }++        if (cur_byte == '\\')+            DISPATCH(backslash)+        else {+            *d++ = cur_byte;+        }+    }+    // Exit point, use sign bit to indicate utf8 validation error+    return (state == UTF8_ACCEPT) ? (d - dest) : (dest - d);++backslash:+    switch (cur_byte) {+        case '"':+        case '\\':+        case '/':+            *d++ = cur_byte;+            goto standard;+            break;+        case 'b': *d++ = '\b';goto standard;+        case 'f': *d++ = '\f';goto standard;+        case 'n': *d++ = '\n';goto standard;+        case 'r': *d++ = '\r';goto standard;+        case 't': *d++ = '\t';goto standard;+        case 'u': DISPATCH(unicode1);;break;+        default:+            return -1;+    }++unicode1:+    temp_hex = decode_hex(cur_byte);+    if (temp_hex == 0xFFFFFFFF) { return -1; }+    else unidata = temp_hex << 12;+    DISPATCH(unicode2);+unicode2:+    temp_hex = decode_hex(cur_byte);+    if (temp_hex == 0xFFFFFFFF) { return -1; }+    else unidata |= temp_hex << 8;+    DISPATCH(unicode3);+unicode3:+    temp_hex = decode_hex(cur_byte);+    if (temp_hex == 0xFFFFFFFF) { return -1; }+    else unidata |= temp_hex << 4;+    DISPATCH(unicode4);+unicode4:+    temp_hex = decode_hex(cur_byte);+    if (temp_hex == 0xFFFFFFFF) { return -1; }+    else unidata |= temp_hex;+    if (surrogate) {+        if (unidata < 0xDC00 || unidata > 0xDFFF) // is not low surrogate+            return -1;+        surrogate = 0;+        // decode surrogate pair+        l_surrogate = unidata;  +        unidata = 0x10000;+        unidata += (h_surrogate & 0x03FF) << 10;+        unidata += (l_surrogate & 0x03FF);+    } else if (unidata >= 0xD800 && unidata <= 0xDBFF ) { // is high surrogate+        surrogate = 1;+        DISPATCH(surrogate1);+    } else if (unidata >= 0xDC00 && unidata <= 0xDFFF) { // is low surrogate+        return -1;+    }+    // encode unidata into UTF8 bytes+    if (unidata <= 0x7F) {+        // plain ASCII+        *d++ = (char) unidata;+    }+    else if (unidata <= 0x07FF) {+        // 2-byte unicode+        *d++ = (char) (((unidata >> 6) & 0x1F) | 0xC0);+        *d++ = (char) (((unidata >> 0) & 0x3F) | 0x80);+    }+    else if (unidata <= 0xFFFF) {+        // 3-byte unicode+        *d++ = (char) (((unidata >> 12) & 0x0F) | 0xE0);+        *d++ = (char) (((unidata >>  6) & 0x3F) | 0x80);+        *d++ = (char) (((unidata >>  0) & 0x3F) | 0x80);+    }+    else if (unidata <= 0x10FFFF) {+        // 4-byte unicode+        *d++ = (char) (((unidata >> 18) & 0x07) | 0xF0);+        *d++ = (char) (((unidata >> 12) & 0x3F) | 0x80);+        *d++ = (char) (((unidata >>  6) & 0x3F) | 0x80);+        *d++ = (char) (((unidata >>  0) & 0x3F) | 0x80);+    }+    else { +        // error +        return -1;+    }+    goto standard;+surrogate1:+    if (cur_byte != '\\') { return -1; }+    h_surrogate = unidata;+    DISPATCH(surrogate2)+surrogate2:+    if (cur_byte != 'u') { return -1; }+    DISPATCH(unicode1)+}++// This function is used to find the ending double quote for a json string+// if return >= 0, it's the split offset, excluding the last double quote+//    return == -1, string is not ended yet+// the lowest two bytes of state record two things:+//    skip: 1 if we should skip next char, 0 otherwise+//    escaped(LSB): 1 if this string contain escaped char(s),+//                  3 if this string contain unescaped control char(s),+//                  0 otherwise+HsInt find_json_string_end(uint32_t* state, const unsigned char* ba, HsInt offset, HsInt len){+    const unsigned char *s   = ba + offset;+    const unsigned char *end = s + len;+    uint32_t skip = *state >> 8;+    uint32_t escaped = *state & 0xFF;+    for (; s < end; s++) {+        if (skip == 1){+            skip = 0;       // skip this char+        }+        else if (*s == '\\') {  // backslash+            escaped = 1;+            skip = 1;+        }+        else if (*s == '\"') {  // double quote+            *state = (skip << 8) | escaped; // save the state+            return (s - ba - offset);+        } else if (*s <= 0x1F) {  // unescaped control characters+            escaped = 3;          // even if it's skipped, it will be rejected in decode_json_string+        }+    }+    *state = (skip << 8) | escaped; // save the state+    return (-1);+}++HsInt escape_json_string_length(const unsigned char *src, HsInt srcoff, HsInt srclen){+    HsInt rv = 2; // for start and end quotes +    const unsigned char *i = src + srcoff;+    const unsigned char *srcend = i + srclen;+    for (; i < srcend; i++) {+        switch (*i) {+            case '\b': rv += 2; break;+            case '\f': rv += 2; break;+            case '\n': rv += 2; break;+            case '\r': rv += 2; break;+            case '\t': rv += 2; break;+            case '\"': rv += 2; break;+            case '\\': rv += 2; break;+            case '/': rv += 2; break;+            default:+                if (*i <= 0x1F) {+                    rv += 6;+                } else {+                    rv += 1;+                }+        }+    }+    return rv;+}++static const unsigned char DEC2HEX[16] = {+    '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'+};++HsInt escape_json_string(const unsigned char *src, HsInt srcoff, HsInt srclen, unsigned char *dest, HsInt desoff){+    const unsigned char *i = src + srcoff;+    const unsigned char *srcend = i + srclen;+    unsigned char *j = dest + desoff;+    *j++ = '\"'; // start quote+    for (; i < srcend; i++){+        switch (*i) {+            case '\b': *j++ = '\\'; *j++ = 'b'; break;+            case '\f': *j++ = '\\'; *j++ = 'f'; break;+            case '\n': *j++ = '\\'; *j++ = 'n'; break;+            case '\r': *j++ = '\\'; *j++ = 'r'; break;+            case '\t': *j++ = '\\'; *j++ = 't'; break;+            case '\"': *j++ = '\\'; *j++ = '\"'; break;+            case '\\': *j++ = '\\'; *j++ = '\\'; break;+            case '/': *j++ = '\\'; *j++ = '/'; break;+            default: +                if (*i <= 0x1F) {+                    *j++ = '\\';+                    *j++ = 'u';+                    *j++ = '0';+                    *j++ = '0';+                    *j++ = DEC2HEX[*i >> 4];+                    *j++ = DEC2HEX[*i & 0xF];+                } else {+                    *j++ = *i;+                }+        }+    }+    *j++ = '\"'; // end quote+    return (HsInt)(j-dest);+}++////////////////////////////////////////////////////////////////////////////////++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,39 @@+/*+ * 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 <limits.h>+#include <stdint.h>+#include <string.h>+#include <Rts.h>++HsInt hs_memchr(uint8_t *a, HsInt aoff, uint8_t b, HsInt n);+HsInt hs_memrchr(uint8_t *a, HsInt aoff, uint8_t c, 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,35 @@+/*+ * 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);+HsInt c_int_dec (uint64_t x, HsInt sign, HsInt width, uint8_t pad, char* ba, HsInt off);
+ include/text.h view
@@ -0,0 +1,60 @@+/*+ * 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 find_json_string_end(uint32_t* state, const unsigned char* ba, HsInt offset, HsInt len);+HsInt decode_json_string(char *dest, const char *src, HsInt srcoff, HsInt srclen);+HsInt escape_json_string_length(const unsigned char *src, HsInt srcoff, HsInt srclen);+HsInt escape_json_string(const unsigned char *src, HsInt srcoff, HsInt srclen, unsigned char *dest, HsInt desoff);++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);
+ test/Spec.hs view
@@ -0,0 +1,2 @@+-- file test/Spec.hs+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ test/Z/Data/Array/UnalignedAccessSpec.hs view
@@ -0,0 +1,294 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.Data.Array.UnalignedAccessSpec where++import qualified Data.List                as L+import           Data.Int+import           GHC.Float+import           Data.Word+import           Z.Data.Array.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/Z/Data/Builder/NumericSpec.hs view
@@ -0,0 +1,261 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.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 Z.Data.Builder.Numeric as B+import qualified Z.Data.Builder.Base    as B+import qualified Z.Data.Text as T+import qualified Z.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 "c_intWith == hs_intWith" $ do+        prop "c_intWith == hs_intWith @Word" $ \ i f ->+            (B.buildBytes $ B.hs_intWith f i) === (B.buildBytes $ B.c_intWith @Word f i)+        prop "c_intWith == hs_intWith @Word8" $ \ i f ->+            (B.buildBytes $ B.hs_intWith f i) === (B.buildBytes $ B.c_intWith @Word8 f i)+        prop "c_intWith == hs_intWith @Word16" $ \ i f ->+            (B.buildBytes $ B.hs_intWith f i) === (B.buildBytes $ B.c_intWith @Word16 f i)+        prop "c_intWith == hs_intWith @Word32" $ \ i f ->+            (B.buildBytes $ B.hs_intWith f i) === (B.buildBytes $ B.c_intWith @Word32 f i)+        prop "c_intWith == hs_intWith @Word64" $ \ i f ->+            (B.buildBytes $ B.hs_intWith f i) === (B.buildBytes $ B.c_intWith @Word64 f i)+        prop "c_intWith == hs_intWith @Int" $ \ i f ->+            (B.buildBytes $ B.hs_intWith f i) === (B.buildBytes $ B.c_intWith @Int f i)+        prop "c_intWith == hs_intWith @Int8" $ \ i f ->+            (B.buildBytes $ B.hs_intWith f i) === (B.buildBytes $ B.c_intWith @Int8 f i)+        prop "c_intWith == hs_intWith @Int16" $ \ i f ->+            (B.buildBytes $ B.hs_intWith f i) === (B.buildBytes $ B.c_intWith @Int16 f i)+        prop "c_intWith == hs_intWith @Int32" $ \ i f ->+            (B.buildBytes $ B.hs_intWith f i) === (B.buildBytes $ B.c_intWith @Int32 f i)+        prop "c_intWith == hs_intWith @Int64" $ \ i f ->+            (B.buildBytes $ B.hs_intWith f i) === (B.buildBytes $ B.c_intWith @Int64 f i)++    describe "integer roundtrip" $ do+        prop "integer roundtrip" $ \ i ->+            i === (read . T.unpack . T.validate . B.buildBytes $ B.integer i)+        prop "integer roundtrip II" $+            -- there're an issue with leading zeros in front of an block, so we add a case manually here+            (2132132100000000000000000000000000213213 :: Integer) ===+                (read . T.unpack . T.validate . B.buildBytes $ B.integer 2132132100000000000000000000000000213213)++    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 %d" $ \ i ->+            printf "%d" i ===+                (T.unpack . T.validate . B.buildBytes $ B.intWith @Int B.defaultIFormat i)+        prop "int === printf %xxd" $ \ 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 %0xxd" $ \ 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 %-xx%" $ \ 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 "hex === printf %08x" $ \ 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)++    describe "grisu3, grisu3_sp === floatToDigits 10" $ do+        prop "grisu3 === floatToDigits" $ \ (Positive f) ->+            B.grisu3 f === floatToDigits 10 f+        prop "grisu3_sp === floatToDigits" $ \ (Positive f) ->+            B.grisu3_sp f === floatToDigits 10 f
+ test/Z/Data/CBytesSpec.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.Data.CBytesSpec where++import qualified Data.List                as List+import           Data.Word+import           Data.Hashable            (hashWithSalt, hash)+import qualified Z.Data.CBytes          as CB+import qualified Z.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/Z/Data/JSON/BaseSpec.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE OverloadedStrings #-}++module Z.Data.JSON.BaseSpec where++import qualified Data.List                as L+import           Data.Word+import           Data.Int+import           GHC.Generics+import qualified Z.Data.Text            as T+import qualified Z.Data.Builder         as B+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck+import qualified Z.Data.JSON as JSON+import           Z.Data.JSON (FromValue, ToValue, EncodeJSON)+++data T a+    = Nullary+    | Unary Int+    | Product T.Text (Maybe Char) a+    | Record { testOne   :: Double+             , testTwo   :: Maybe Bool+             , testThree :: Maybe a+             }+    | List [a]+   deriving (Show, Eq, Generic, FromValue, ToValue, EncodeJSON)++spec :: Spec+spec = describe "JSON Base instances" $ do++    it "Nullary constructor are encoded as text" $+        JSON.encodeText (Nullary :: T Integer) === "\"Nullary\""++    it "Unary constructor are encoded as single field object" $+        JSON.encodeText (Unary 123456 :: T Integer) === "{\"Unary\":123456}"++    it "Product are encoded as array" $+        JSON.encodeText (Product "ABC" (Just 'x') (123456::Integer)) ===+            "{\"Product\":[\"ABC\",\"x\",123456]}"++    it "Record are encoded as key values" $+        JSON.encodeText (Record 0.123456 Nothing (Just (123456::Integer))) ===+            "{\"Record\":{\+                \\"testOne\":0.123456,\+                \\"testTwo\":null,\+                \\"testThree\":123456}}"++    it "List are encode as array" $+        JSON.encodeText (List [Nullary+            , Unary 123456+            , (Product "ABC" (Just 'x') (123456::Integer))+            , (Record 0.123456 Nothing (Just (123456::Integer)))]) ===+                "{\"List\":[\"Nullary\",\+                \{\"Unary\":123456},\+                \{\"Product\":[\"ABC\",\"x\",123456]},\+                \{\"Record\":{\+                \\"testOne\":0.123456,\+                \\"testTwo\":null,\+                \\"testThree\":123456}}]}"++    it "control characters are escaped" $+        JSON.encodeText (T.pack $ map toEnum [0..0x1F]) ===+            "\"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\+            \\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f\""
+ test/Z/Data/JSON/ValueSpec.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.Data.JSON.ValueSpec where++import qualified Data.List                as L+import           Data.Word+import           Data.Int+import           GHC.Float+import           Data.Word8                  (toLower, toUpper)+import qualified Z.Data.Builder         as B+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck+import qualified Z.Data.JSON.Value as JSON+import qualified Z.Data.JSON.Builder as JSONB+++spec :: Spec+spec = describe "JSON" $ do -- large size will generate too huge JSON document+    prop "value roundtrip" $ \ v ->+        Right v === JSON.parseValue' (B.buildBytes (JSONB.value v))
+ test/Z/Data/Parser/BaseSpec.hs view
@@ -0,0 +1,122 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.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 Z.Data.Parser.Base    as P+import qualified Z.Data.Text as T+import qualified Z.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 "skipWord8" $ \ s ->+            parse' (P.skipWord8 *> P.takeWhile (const True)) s ===+                case s of [] -> Nothing+                          (w:s') -> Just (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 "atEnd" $ \ s ->+            parse' P.atEnd s ===+                case s of [] -> Just True+                          _  -> Just False++        prop "scan" $ \ s l ->+            let go l  _ | l <= 0    = Nothing+                        | otherwise = Just (l-1)+            in (fst <$> 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/Z/Data/Parser/NumericSpec.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.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 Z.Data.Parser.Numeric    as P+import qualified Z.Data.Parser.Base    as P+import qualified Z.Data.Builder.Numeric    as B+import qualified Z.Data.Builder.Base    as B+import qualified Z.Data.Text as T+import qualified Z.Data.Vector.Base as V+import qualified Data.Scientific as Sci+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++spec :: Spec+spec = do+    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)++    describe "floatToScientific, doubleToScientific === fromFloatDigits"  $ do+        prop "floatToScientific == fromFloatDigits" $ \ i ->+            P.floatToScientific i === Sci.fromFloatDigits i+        prop "floatToScientific === fromFloatDigits" $ \ i ->+            P.doubleToScientific i === Sci.fromFloatDigits i
+ test/Z/Data/Text/BaseSpec.hs view
@@ -0,0 +1,112 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.Data.Text.BaseSpec where++import qualified Data.List                as List+import           Data.Word+import qualified Z.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世界"+        prop "surrogate codepoint2" $+            "你好\xD800世界" === 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/Z/Data/Text/BuilderSpec.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE OverloadedStrings #-}++module Z.Data.Text.BuilderSpec where++import qualified Data.List                as L+import           Data.Word+import           Data.Int+import           GHC.Generics+import qualified Z.Data.Text            as T+import           Z.Data.Text.Builder+import           Z.Data.JSON            (Value)+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck+++data T a+    = Nullary+    | Unary Int+    | Product T.Text (Maybe Char) a+    | Record { testOne   :: Double+             , testTwo   :: Maybe Bool+             , testThree :: Maybe a+             }+    | List [a]+   deriving (Show, Eq, ToText, Generic)++data I a = I a :+ I a | I a :- I a | J a deriving (Show, Generic, ToText)+infixr 5 :++infixl 6 :-++spec :: Spec+spec = describe "JSON Base instances" $ do++    it "Nullary constructor are encoded as text" $+        toText (Nullary :: T Integer) === "Nullary"++    it "Unary constructor are encoded as single field" $+        toText (Unary 123456 :: T Integer) === "Unary 123456"++    it "Product are encoded as multiple field" $+        toText (Product "ABC" (Just 'x') (123456::Integer)) ===+            "Product \"ABC\" (Just 'x') 123456"++    it "Record are encoded as key values" $+        toText (Record 0.123456 Nothing (Just (123456::Integer))) ===+            "Record {testOne = 0.123456, testTwo = Nothing, testThree = Just 123456}"++    it "List are encode as array" $+        toText (List [Nullary+            , Unary 123456+            , (Product "ABC" (Just 'x') (123456::Integer))+            , (Record 0.123456 Nothing (Just (123456::Integer)))]) ===+                "List [Nullary,Unary 123456,Product \"ABC\" (Just 'x') 123456,\+                    \Record {testOne = 0.123456, testTwo = Nothing, testThree = Just 123456}]"++    it "infix constructor should respect piority" $+        toString (J 1 :- J 2 :+ J 3 :- J 4 :- J 5 :+ J 6 :+ J 7 :+ J 8 :- J 9 :- J 10 :- J 11 :: I Int)+            === show (J 1 :- J 2 :+ J 3 :- J 4 :- J 5 :+ J 6 :+ J 7 :+ J 8 :- J 9 :- J 10 :- J 11)++    prop "Value Show instance === ToText instances" $ \ (v :: Value) ->+        toString v === show v
+ test/Z/Data/Text/ExtraSpec.hs view
@@ -0,0 +1,210 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.Data.Text.ExtraSpec where++import qualified Data.List                as List+import           Data.Word+import qualified Z.Data.Text.Base        as T+import qualified Z.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" $ \ (NonEmpty xs) ->+            (T.unlines $ List.map T.pack xs) <> (T.pack "\n") === (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/Z/Data/Text/SearchSpec.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.Data.Text.SearchSpec where++import qualified Data.List                as List+import           Data.Word+import qualified Z.Data.Text.Base        as T+import qualified Z.Data.Text.Extra        as T+import qualified Z.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/Z/Data/Vector/BaseSpec.hs view
@@ -0,0 +1,285 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.Data.Vector.BaseSpec where++import qualified Data.List                as List+import           Data.Word+import           Data.Hashable            (hashWithSalt, hash)+import qualified Z.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/Z/Data/Vector/ExtraSpec.hs view
@@ -0,0 +1,532 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.Data.Vector.ExtraSpec where++import qualified Data.List                as List+import           Data.Word+import qualified Z.Data.Vector          as V+import qualified Z.Data.Vector.Base     as V+import qualified Z.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" $ \ (NonEmpty xs) ->+            ((V.unlines $ V.pack @V.PrimVector @Word8 <$> xs) <> V.singleton 10) ===+                (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/Z/Data/Vector/FlatMapSpec.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.Data.Vector.FlatMapSpec where++import qualified Data.List                as List+import           Data.Word+import qualified Z.Data.Vector          as V+import qualified Z.Data.Vector.FlatMap  as FM+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++type FMS = FM.FlatMap String String++spec :: Spec+spec = do+    describe "flatmap-semigroup-monoid" $ do+        prop "flatmap monoid unit law" $ \ (m :: FMS)  ->+            (m <> FM.empty) === m+        prop "flatmap monoid unit law" $ \ (m :: FMS) ->+            (FM.empty <> m) === m+        prop "flatmap semigroup associativity low" $ \ (m1 :: FMS) m2 m3 ->+            (m1 <> m2) <> m3 === m1 <> (m2 <> m3)++    describe "flatmap insert lookup roundtrip" $ do+        prop "flatmap insert lookup roundtrip" $ \ (m :: FMS) k v ->+            FM.lookup k (FM.insert k v m) === Just v++    describe "flatmap delete lookup" $ do+        prop "flatmap delete lookup" $ \ (m :: FMS) k ->+            FM.lookup k (FM.delete k m) === Nothing++    describe "flatmap adjust lookup roundtrip" $ do+        prop "flatmap adjust lookup roundtrip" $ \ (m :: FMS) k (Fun _ f) ->+            FM.lookup k (FM.adjust' f k m) === f `fmap` FM.lookup k m
+ test/Z/Data/Vector/FlatSetSpec.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.Data.Vector.FlatSetSpec where++import qualified Data.List                as List+import           Data.Word+import qualified Z.Data.Vector          as V+import qualified Z.Data.Vector.FlatSet  as FS+import           Test.QuickCheck+import           Test.QuickCheck.Function+import           Test.QuickCheck.Property+import           Test.Hspec+import           Test.Hspec.QuickCheck++type FMS = FS.FlatSet String++spec :: Spec+spec = do+    describe "flatset-semigroup-monoid" $ do+        prop "flatset monoid unit law" $ \ (m :: FMS)  ->+            (m <> FS.empty) === m+        prop "flatset monoid unit law" $ \ (m :: FMS) ->+            (FS.empty <> m) === m+        prop "flatset semigroup associativity low" $ \ (m1 :: FMS) m2 m3 ->+            (m1 <> m2) <> m3 === m1 <> (m2 <> m3)++    describe "flatset insert elem roundtrip" $ do+        prop "flatset insert elem roundtrip" $ \ (m :: FMS) v ->+            FS.elem v (FS.insert v m) === True++    describe "flatset delete elem" $ do+        prop "flatset delete elem" $ \ (m :: FMS) v ->+            FS.elem v (FS.delete v m) === False
+ test/Z/Data/Vector/SearchSpec.hs view
@@ -0,0 +1,194 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.Data.Vector.SearchSpec where++import qualified Data.List                as List+import           Data.Word+import qualified Z.Data.Vector          as V+import qualified Z.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/Z/Data/Vector/SortSpec.hs view
@@ -0,0 +1,138 @@+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Z.Data.Vector.SortSpec where++import qualified Data.List                as List+import           Data.Word+import           Data.Int+import qualified Z.Data.Vector          as V+import qualified Z.Data.Vector.Sort     as V+import           Z.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)
+ 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/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.2"
+
+/*!
+	\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,337 @@+/*
+	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 &&
+                    ((state->output->codepoint[cursor_current] - HANGUL_S_FIRST) % HANGUL_T_COUNT) == 0)
+				{
+					/* 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,12159 @@+/*
+	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:
+		2020-05-24T19:53:00
+
+	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, 527, 1088, 1120, 1152, 1184, 1216, 1248, 1280, 1312, 1248, 1248, 1344, 1376, 1408, 1440, 1472, 1248, 1248, 1504, 1536, 1568,
+	1600, 1632, 1664, 1696, 1728, 1760, 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, 2848, 2880, 2912, 2944, 2976, 3008, 3040, 3072, 3104, 3136, 3168, 3200, 1707, 3232, 3264, 3296, 1707, 3328, 3360, 3392, 3424, 3456, 3488, 3520, 1707,
+	1248, 3552, 3584, 3616, 3648, 893, 3680, 3712, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 3744, 1248, 3776, 3808, 3840, 1248, 3872, 1248, 3904, 3936, 3968, 893, 893, 4000,
+	4032, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 4064, 4096, 1248, 1248, 4128, 4160, 4192, 4224, 4256, 1248, 4288, 4320, 4352,
+	4384, 1248, 4416, 4448, 4480, 4512, 1248, 4544, 4576, 4608, 4640, 4672, 1248, 4704, 4736, 4768, 4800, 1248, 4832, 4864, 4896, 4928, 4960, 1707, 4992, 5024, 5056, 5088, 1857, 5120, 1248, 5152,
+	1248, 5184, 5216, 5248, 5280, 5312, 5344, 5376, 527, 5408, 5440, 5472, 597, 5420, 704, 5504, 224, 224, 224, 224, 5536, 224, 224, 224, 5568, 5600, 5632, 5664, 5696, 5728, 5760, 5792,
+	5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112, 6144, 6176, 6208, 6240, 6272, 6304, 6336, 6324, 6324, 6324, 6324, 6324, 6324, 6324, 6368, 6400, 4766, 6432, 6464, 6496, 6528, 6560,
+	4766, 6592, 6624, 6656, 6688, 4766, 4766, 6720, 4766, 4766, 4766, 4766, 4766, 6752, 6253, 6784, 4766, 4766, 4766, 6816, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 6848, 6880, 4766, 6912, 6944,
+	4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 6324, 6324, 6324, 6324, 6976, 6324, 7008, 7040, 6324, 6324, 6324, 6324, 6324, 6324, 6324, 6324, 4766, 7072, 7104, 7136, 7168, 4766, 4766, 4766,
+	893, 7200, 7232, 7264, 224, 224, 224, 7296, 527, 7328, 1248, 7360, 7392, 7424, 7424, 704, 7456, 7488, 7520, 1707, 7552, 4766, 4766, 7584, 4766, 4766, 4766, 4766, 4766, 4766, 7616, 7648,
+	7680, 7712, 3400, 1248, 7744, 4032, 1248, 7776, 4523, 7808, 1248, 1248, 7840, 1248, 4766, 7872, 7904, 7936, 7968, 4766, 7936, 8000, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766,
+	1706, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 8032, 4766, 4766, 1706, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 8064,
+	8096, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248,
+	1248, 1248, 1248, 1248, 8128, 4766, 8160, 8192, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 8224, 8256, 224, 8288, 8320, 1248, 1248, 8352, 8384, 8416, 224, 8448, 8480, 8512, 8544, 8576,
+	8608, 8640, 1248, 8672, 8704, 8736, 8768, 8800, 1536, 8832, 8864, 8896, 8928, 8960, 8992, 9024, 1248, 9056, 9088, 9120, 1248, 9152, 9184, 9216, 9248, 9280, 9312, 9344, 527, 527, 1248, 9376,
+	1706, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 9408, 9440, 9472,
+	9504, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 9536, 9504, 1707, 1707, 9568,
+	9504, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 9568,
+	9600, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 9632, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 9664, 1248, 1248, 4447, 1707, 9696, 9728, 9760, 1248, 1248, 9792, 9824, 1248,
+	1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 9856, 9888, 1248, 9920, 1248, 9952, 9984, 10016, 10048, 10080, 10112, 1248, 1248, 1248, 10144, 10176, 10208, 10240, 10272, 5242, 4576, 10304, 10336,
+	10368, 10400, 10432, 1707, 1248, 1248, 1248, 10464, 10496, 10528, 6176, 10560, 10592, 10624, 10656, 10688, 1707, 1707, 1707, 1707, 8896, 1248, 10720, 10752, 1248, 10784, 10816, 10848, 10880, 1248, 10912, 1707,
+	893, 10944, 10976, 1248, 4656, 11008, 11040, 11072, 1248, 11104, 1248, 11136, 1707, 1707, 1707, 1707, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 7392, 9938, 11168, 1707, 1707, 1707, 1707,
+	11200, 11232, 11264, 11296, 4576, 11328, 1707, 11360, 11392, 11424, 1707, 1707, 1248, 11456, 11488, 6656, 11520, 11552, 11584, 11616, 11648, 1707, 11680, 11712, 1248, 11744, 11776, 11808, 11840, 11872, 1707, 1707,
+	1248, 1248, 11904, 1707, 893, 11936, 527, 11968, 1248, 12000, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 12032, 1248, 12064, 1707, 1707, 11648, 12096, 12128, 1707, 1707, 9888, 12160, 7392,
+	12192, 12224, 12256, 12288, 1857, 12320, 12352, 12384, 12416, 12448, 12480, 12512, 1857, 12544, 12576, 12608, 12640, 12672, 1707, 1707, 12704, 12736, 12768, 12800, 12832, 12864, 12896, 12928, 1707, 1707, 1707, 1707,
+	1248, 12960, 12992, 1705, 1248, 13024, 13056, 1707, 1707, 1707, 1707, 1707, 1248, 13088, 13120, 1707, 1248, 13152, 13184, 13216, 1248, 13248, 13280, 1707, 13312, 13344, 1707, 1707, 1707, 1707, 1707, 1707,
+	1248, 13376, 1707, 1707, 1707, 893, 527, 13408, 13440, 13472, 13504, 1707, 1707, 13536, 13568, 13600, 13632, 13664, 13696, 1248, 13728, 13760, 1248, 12368, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	13792, 13824, 13856, 13888, 13920, 13952, 1707, 1707, 13984, 14016, 14048, 14080, 14112, 13280, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 14144, 1707, 1707, 1707, 1707, 1707, 14176, 14208, 14240,
+	1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 4447, 1707, 1707, 1707,
+	6176, 6176, 6176, 14272, 1248, 1248, 1248, 1248, 1248, 1248, 14304, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248,
+	1248, 14336, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 14368, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 12368, 4576, 14400, 1707, 1707, 9888, 14432, 1248, 14464, 14496, 14528, 14560, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 893, 527, 14592, 1707, 1707, 1707, 1248, 1248, 14624, 14656, 14688, 1707, 1707, 14720,
+	1706, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 14169,
+	1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248,
+	1248, 1248, 1248, 1248, 1248, 1248, 9938, 1707, 14752, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 4576, 1707, 14784, 14816, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 14848, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1248, 1248, 1248, 14880, 14912, 14944, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	4766, 4766, 4766, 4766, 4766, 4766, 4766, 7616, 4766, 7149, 4766, 14976, 15008, 15040, 4766, 15072, 4766, 4766, 15104, 1707, 1707, 1707, 1707, 15136, 4766, 4766, 8144, 15168, 1707, 1707, 1707, 1707,
+	15200, 15232, 15264, 15244, 15296, 15328, 15360, 15392, 15424, 15456, 15488, 15520, 15552, 15200, 15584, 15616, 15244, 15224, 15648, 15680, 15712, 15744, 15776, 15808, 15840, 15872, 15904, 15936, 15968, 16000, 16032, 16064,
+	4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 704, 16096, 704, 16128, 16160, 16192, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	16224, 16256, 1707, 1707, 1707, 1707, 1707, 1707, 1248, 16288, 16320, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1248, 16352, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1248, 1248, 1248, 1248, 1248, 1248, 16384, 1707, 893, 10950, 16416, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 16448, 6656, 16480, 1707, 1707, 6655, 16512, 1707, 1707, 1707, 1707, 1707, 1707, 13797, 16544, 16576, 16608, 16640, 16672, 1707, 16704, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	4766, 16736, 4766, 4766, 16768, 16800, 16832, 7616, 16864, 4766, 4766, 4766, 4766, 16896, 1707, 7546, 16928, 16960, 16992, 17024, 1707, 1707, 1707, 1707, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 17056,
+	4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 4766, 17088, 17120, 4766, 4766, 4766, 17152, 4766, 4766, 7579, 17184,
+	16736, 4766, 17216, 4766, 17248, 17280, 1707, 1707, 4766, 4766, 4766, 17312, 4766, 4766, 17344, 4766, 4766, 4766, 17152, 17376, 17408, 17440, 17472, 1707, 4766, 4766, 4766, 4766, 17504, 4766, 6624, 17536,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1706, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 17568, 1707, 1706, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 17600, 1706, 1707, 1707, 1707, 1707, 1707,
+	17632, 1706, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 17664, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1706,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, 4656, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1706, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 17696, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	17728, 17760, 17760, 17760, 1707, 1707, 1707, 1707, 704, 704, 704, 704, 704, 704, 704, 17792, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	9600, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 17824,
+	9600, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+	1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, 17856,
+};
+const size_t* GeneralCategoryIndexPtr = GeneralCategoryIndex;
+
+const uint32_t GeneralCategoryData[17888] = {
+	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,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 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, 0x10, 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, 0x20, 0x80000, 0x80000,
+	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,
+	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, 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, 0x00, 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, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x4000000, 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, 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, 0x10, 0x20000, 0x20, 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, 0x20000, 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, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	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, 0x20, 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, 0x20, 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, 0x10, 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, 0x20000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000,
+	0x10, 0x20, 0x40, 0x40, 0x20000, 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,
+	0x20, 0x20, 0x40, 0x40, 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, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x10, 0x40, 0x40,
+	0x40, 0x20, 0x20, 0x20, 0x20, 0x00, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x20, 0x10, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x40, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x10,
+	0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x200000, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x00, 0x20, 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, 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, 0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 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, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x20000, 0x08, 0x02, 0x02, 0x02,
+	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,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 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, 0x200000, 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, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 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, 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, 0x10, 0x10, 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, 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, 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,
+	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,
+	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,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 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, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01,
+	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, 0x10, 0x10, 0x20, 0x10, 0x10, 0x40, 0x20, 0x20, 0x10, 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, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 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, 0x80000, 0x80000,
+	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, 0x200000, 0x200000, 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, 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,
+	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, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	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, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x200000, 0x200000, 0x20000, 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, 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, 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,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 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, 0x20, 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, 0x10, 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, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
+	0x00, 0x00, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 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, 0x01, 0x02, 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, 0x20, 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, 0x20, 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, 0x20000, 0x10, 0x10, 0x20,
+	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,
+	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, 0x40, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 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,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x08, 0x100000, 0x100000, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	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,
+	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,
+	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, 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, 0x20, 0x20, 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,
+	0x10, 0x10, 0x10, 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, 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, 0x200000, 0x200000, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 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, 0x10, 0x10, 0x10, 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, 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, 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, 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, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 0x400, 0x400, 0x10, 0x10,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	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, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 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,
+	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,
+	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, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400,
+	0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x20, 0x20, 0x1000, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 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, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x400, 0x400, 0x400, 0x400, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x4000000, 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, 0x10, 0x40, 0x40, 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, 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, 0x20, 0x20, 0x20, 0x20, 0x20000, 0x40, 0x20, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x10, 0x20000, 0x10, 0x20000, 0x20000, 0x20000,
+	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, 0x20, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 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, 0x20000, 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, 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,
+	0x20, 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, 0x20, 0x20, 0x10, 0x40, 0x40,
+	0x20, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 0x00, 0x10, 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, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x40, 0x40, 0x20, 0x20, 0x20, 0x40, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x20000, 0x20000, 0x00, 0x20000, 0x20, 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, 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, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 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,
+	0x20000, 0x20000, 0x20000, 0x20000, 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,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x20, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	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, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x20,
+	0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x400, 0x400, 0x20000, 0x20000, 0x20000, 0x200000,
+	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, 0x20, 0x20, 0x20000, 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,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 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, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x40, 0x20, 0x10,
+	0x40, 0x10, 0x40, 0x20, 0x20000, 0x20000, 0x20000, 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, 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, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40,
+	0x20, 0x10, 0x20000, 0x10, 0x40, 0x00, 0x00, 0x00, 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, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 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, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20000,
+	0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x20, 0x20, 0x20, 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, 0x40, 0x20, 0x20, 0x20000, 0x20000, 0x20000, 0x10, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	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, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20,
+	0x10, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 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, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 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, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x20, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	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, 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, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x20, 0x00, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x20, 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, 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, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x20, 0x20, 0x00, 0x40, 0x40, 0x20, 0x40, 0x20, 0x10, 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, 0x20, 0x20, 0x40, 0x40, 0x20000, 0x20000, 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,
+	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, 0x80000, 0x80000, 0x80000,
+	0x80000, 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, 0x20000,
+	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, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x4000000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	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,
+	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,
+	0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 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, 0x40,
+	0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x20000, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 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, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 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, 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,
+	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, 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, 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, 0x400, 0x400, 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, 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,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x20, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x20, 0x200000, 0x200000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x00, 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,
+	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, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x00, 0x20, 0x20, 0x00, 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,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
+	0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x10, 0x200000, 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, 0x20, 0x20, 0x20, 0x20, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80000,
+	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,
+	0x02, 0x02, 0x02, 0x02, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x08, 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, 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, 0x200000, 0x400, 0x400, 0x400, 0x80000, 0x400, 0x400, 0x400, 0x400, 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, 0x200000, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x400, 0x00, 0x00,
+	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, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 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,
+	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, 0x200000, 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, 0x00, 0x00, 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, 0x100000, 0x100000, 0x100000, 0x100000, 0x100000,
+	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, 0x200000, 0x200000, 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, 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, 0x00, 0x00, 0x00, 0x00, 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, 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, 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, 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, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x200000, 0x200000, 0x200000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 0x200000, 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, 0x00, 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, 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, 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, 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, 0x10, 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, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 672, 704, 0, 736, 768, 0, 0, 736, 800, 832, 0, 736, 864, 0, 0, 736, 896, 0, 0, 736, 928, 0, 0, 0, 960, 0,
+	0, 0, 992, 0, 0, 736, 1024, 0, 0, 1056, 1088, 0, 0, 0, 1120, 0, 0, 1152, 1184, 0, 0, 1216, 1248, 0, 1280, 1312, 0, 1344, 1376, 0, 1408, 0,
+	0, 1440, 0, 0, 1472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1536, 1536, 0, 0, 0, 0, 1568, 0,
+	0, 0, 0, 0, 0, 1600, 0, 0, 0, 1632, 0, 0, 0, 0, 0, 0, 1664, 0, 0, 1696, 0, 1728, 429, 0, 0, 1760, 809, 1792, 0, 1824, 0, 1856,
+	0, 1888, 0, 0, 0, 0, 1920, 1952, 0, 0, 0, 0, 0, 0, 1984, 2016, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 2048, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 1518, 0, 0, 0, 878, 0, 0, 0, 2001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 2112, 0, 0, 2144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2176, 2208, 0, 0, 2240, 0, 0, 0, 0, 0, 0, 0, 0,
+	1550, 2272, 0, 0, 0, 0, 809, 2304, 0, 2336, 2368, 0, 0, 2400, 813, 0, 0, 0, 0, 0, 0, 2432, 2464, 1015, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	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, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2560, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2592, 0, 0, 0, 0, 0, 0, 0, 429, 0, 0, 0, 2624, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2656, 2688, 0, 0, 0, 0, 0, 2720, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 2752, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2784, 0, 0, 0, 0, 2816, 0, 0, 0, 0, 0,
+	0, 0, 1550, 878, 0, 2848, 0, 0, 2880, 2912, 0, 2944, 0, 0, 2976, 0, 0, 3008, 0, 0, 0, 0, 0, 3040, 0, 3072, 3104, 3136, 0, 0, 0, 0,
+	0, 0, 3168, 0, 0, 0, 3200, 0, 0, 0, 0, 0, 0, 878, 2986, 0, 0, 878, 0, 0, 0, 3232, 0, 0, 0, 3264, 0, 0, 0, 0, 0, 0,
+	0, 3296, 0, 0, 0, 0, 0, 0, 0, 3328, 2416, 0, 0, 0, 0, 813, 0, 1536, 902, 0, 3360, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 878, 0, 0, 0, 0, 0, 0, 0, 0, 3392, 0, 3424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3456, 0, 3488, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 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,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 3552, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3584, 3616, 3648, 0, 0, 0, 0, 2878, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	3680, 3712, 0, 0, 0, 0, 0, 0, 0, 3744, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3776, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 3808, 0, 0, 0, 3840, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 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[3872] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+	0xE6, 0xE6, 0x00, 0xDC, 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, 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, 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, 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, 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, 0x09, 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, 0xDC,
+	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, 0xE8, 0xE4, 0xE4, 0xDC, 0x00, 0xE6, 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, 0xE6, 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,
+	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,
+	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, 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, 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, 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, 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, 0xE6, 0xE6, 0xE6, 0xDC, 0xE6, 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, 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,
+	0x09, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 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, 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, 0xE6, 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, 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, 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, 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, 0x09, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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,
+	0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+	0xE6, 0xE6, 0x00, 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, 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, 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, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 1088, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1120, 1120, 1152,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 1184, 1216, 0, 0, 0, 0, 0, 1248, 1280, 0, 0, 0, 192, 192, 192, 192, 1312, 192, 192, 192, 1344, 1376, 1408, 1440, 1472, 1504, 1536, 1568,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 1600, 1632, 1664, 1696, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 1728, 1664, 1760, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 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, 1792, 1824, 1856, 192, 192, 192, 1888, 816, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1952, 1984, 0, 0, 0, 0, 2016, 192, 2048, 2080, 2112, 2144, 2176,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2208, 2240, 2272, 2256, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 32, 2336, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 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, 2368, 2400, 0, 0, 17, 2432, 2464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 2496, 816, 2528, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 765, 2374, 2560, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 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[2592] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x00, 0x05, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+	0x05, 0x00, 0x05, 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, 0x05, 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, 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, 0x00, 0x00, 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, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00,
+	0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 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, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x0A, 0x0A, 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, 0x05, 0x00, 0x00, 0x00, 0x05, 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, 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, 0x05, 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, 0x0A, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0A, 0x05,
+	0x00, 0x00, 0x0A, 0x05, 0x0A, 0x0A, 0x0A, 0x0A, 0x05, 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, 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, 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, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+	0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
+	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,
+	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 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, 0x00, 0x00, 0x00, 0x00,
+	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, 0x00, 0x00, 0x00,
+	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,
+	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, 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, 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, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1568, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 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[1632] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 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, 2084, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1504, 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, 2432, 0, 0, 0, 0, 0, 0, 2464, 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, 1034, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 2496, 2528, 1504, 2560, 1504, 1504, 2592, 0, 2624, 2656, 2688, 1504, 1504, 2720, 2752, 1504,
+	1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 2289, 2160, 1504, 2784, 1504, 696, 2816, 2848, 2160, 2880, 2912, 1504, 1504, 1504, 2944, 1503, 1504, 1504, 1504, 1504, 2976, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3232, 288, 0, 669, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1504, 1504, 3264, 1504, 3296, 3328, 3360, 1504, 3392, 3424, 3456, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 3488, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 1504, 3520, 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, 3552, 3584, 3616, 3648, 3680, 3712, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 3744, 3776, 3808, 3840, 3872, 0, 0, 0, 3904, 1455, 3936, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3968,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 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[4000] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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,
+	0x00, 0x00, 0x00, 0x00, 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,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 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, 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, 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, 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, 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, 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, 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, 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, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 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, 344, 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, 3232, 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, 3264, 3296, 344, 3328, 344, 344, 232, 0, 3360, 3392, 3424, 344, 344, 3456, 273, 344,
+	344, 344, 344, 344, 344, 344, 344, 344, 344, 3089, 3488, 344, 326, 344, 3466, 3520, 3552, 3584, 3616, 3648, 344, 344, 344, 3680, 3305, 344, 344, 344, 344, 1919, 3712, 3744,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 3776, 2205, 0, 0, 0, 3808, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3840, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 3872, 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, 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, 3474, 480, 0, 3936, 440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	344, 344, 1952, 344, 3968, 4000, 4032, 344, 4064, 4096, 4128, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 4160, 344, 344, 344, 344, 344, 344, 344, 344, 4192, 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, 4224, 4256, 4288, 4320, 4352, 4384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 4416, 4448, 3152, 1216, 963, 0, 0, 0, 4480, 1775, 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, 4544,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 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[4576] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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,
+	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, 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, 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, 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,
+	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, 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, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 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, 0xD20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xD40, 0xD60, 0x0, 0xD80, 0xDA0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0xDC0, 0xDE0, 0xE00, 0xE20, 0xE40, 0xE60, 0xE80, 0xEA0, 0xEC0, 0xEE0, 0xF00, 0xF20, 0xF40, 0xF60, 0xF80, 0xFA0,
+	0xFC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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[4064] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x8001693, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800169B, 0x80016A3,
+	0xC0016AB, 0xC0016B7, 0xC0016C3, 0xC0016CF, 0xC0016DB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80016E7, 0x80016EF, 0xC0016F7, 0xC001703, 0xC00170F,
+	0xC00171B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3001727, 0x300172A, 0x300172D, 0x4001730, 0x3001734, 0x3001403, 0x3001737, 0x300173A, 0x300173D, 0x3001740, 0x3001406, 0x3001743, 0x3001746, 0x4001749, 0x3001409, 0x300174D,
+	0x3001750, 0x3001753, 0x4001756, 0x300175A, 0x300175D, 0x3001760, 0x4001763, 0x3001767, 0x300176A, 0x300176D, 0x3001770, 0x30014B8, 0x4001773, 0x3001777, 0x300177A, 0x300177D,
+	0x3001780, 0x3001783, 0x3001786, 0x3001789, 0x300178C, 0x30014C7, 0x300140C, 0x300140F, 0x30014CA, 0x300178F, 0x3001792, 0x30011CC, 0x3001795, 0x3001412, 0x3001798, 0x300179B,
+	0x300179E, 0x30017A1, 0x30017A1, 0x30017A1, 0x40017A4, 0x30017A8, 0x30017AB, 0x30017AE, 0x40017B1, 0x30017B5, 0x30017B8, 0x30017BB, 0x30017BE, 0x30017C1, 0x30017C4, 0x30017C7,
+	0x30017CA, 0x30017CD, 0x30017D0, 0x30017D3, 0x30017D6, 0x30017D9, 0x30017D9, 0x30014D0, 0x30017DC, 0x30017DF, 0x30017E2, 0x30017E5, 0x3001418, 0x30017E8, 0x30017EB, 0x30017EE,
+	0x3001397, 0x30017F1, 0x30017F4, 0x30017F7, 0x30017FA, 0x30017FD, 0x3001800, 0x3001803, 0x3001806, 0x4001809, 0x300180D, 0x3001810, 0x3001813, 0x3001816, 0x3001819, 0x300181C,
+	0x400181F, 0x4001823, 0x3001827, 0x300182A, 0x300182D, 0x3001830, 0x3001833, 0x3001836, 0x3001839, 0x300183C, 0x300183F, 0x300183F, 0x4001842, 0x3001846, 0x3001849, 0x30011C0,
+	0x300184C, 0x400184F, 0x3001853, 0x3001856, 0x3001859, 0x300185C, 0x300185F, 0x3001862, 0x3001427, 0x3001865, 0x3001868, 0x400186B, 0x300186F, 0x4001872, 0x3001876, 0x3001879,
+	0x300187C, 0x300187F, 0x3001882, 0x3001885, 0x3001888, 0x300188B, 0x300188E, 0x3001891, 0x3001894, 0x4001897, 0x300189B, 0x300189E, 0x30018A1, 0x30018A4, 0x300111E, 0x40018A7,
+	0x30018AB, 0x40018AE, 0x40018AE, 0x30018B2, 0x30018B5, 0x30018B5, 0x30018B8, 0x40018BB, 0x40018BF, 0x30018C3, 0x30018C6, 0x30018C9, 0x30018CC, 0x30018CF, 0x30018D2, 0x30018D5,
+	0x30018D8, 0x30018DB, 0x30018DE, 0x300142A, 0x40018E1, 0x30018E5, 0x30018E8, 0x30018EB, 0x30014F4, 0x30018EB, 0x30018EE, 0x3001430, 0x30018F1, 0x30018F4, 0x30018F7, 0x30018FA,
+	0x3001433, 0x30010CD, 0x30018FD, 0x3001900, 0x3001903, 0x3001906, 0x3001909, 0x300190C, 0x400190F, 0x3001913, 0x3001916, 0x3001919, 0x300191C, 0x300191F, 0x4001922, 0x3001926,
+	0x3001929, 0x300192C, 0x300192F, 0x3001932, 0x3001935, 0x3001938, 0x300193B, 0x300193E, 0x3001436, 0x3001941, 0x4001944, 0x3001948, 0x300194B, 0x300194E, 0x3001951, 0x300143C,
+	0x3001954, 0x3001957, 0x300195A, 0x300195D, 0x3001960, 0x3001963, 0x3001966, 0x3001969, 0x3001121, 0x300150C, 0x300196C, 0x300196F, 0x3001972, 0x4001975, 0x3001979, 0x300197C,
+	0x300197F, 0x3001982, 0x300143F, 0x4001985, 0x3001989, 0x300198C, 0x300198F, 0x3001590, 0x3001992, 0x3001995, 0x3001998, 0x300199B, 0x400199E, 0x30019A2, 0x30019A5, 0x30019A8,
+	0x40019AB, 0x30019AF, 0x30019B2, 0x30019B5, 0x30019B8, 0x30011F3, 0x30019BB, 0x40019BE, 0x40019C2, 0x40019C6, 0x30019CA, 0x40019CD, 0x30019D1, 0x30019D4, 0x30019D7, 0x30019DA,
+	0x30019DD, 0x3001442, 0x30012F8, 0x30019E0, 0x30019E3, 0x30019E6, 0x40019E9, 0x30019ED, 0x30019F0, 0x30019F3, 0x30019F6, 0x3001518, 0x30019F9, 0x40019FC, 0x3001A00, 0x3001A03,
+	0x4001A06, 0x4001A0A, 0x3001A0E, 0x3001A11, 0x300151B, 0x3001A14, 0x3001A17, 0x3001A1A, 0x3001A1D, 0x3001A20, 0x3001A23, 0x4001A26, 0x3001A2A, 0x4001A2D, 0x3001A31, 0x4001A34,
+	0x3001A38, 0x3001521, 0x3001A3B, 0x4001A3E, 0x3001A42, 0x3001A45, 0x4001A48, 0x4001A4C, 0x3001A50, 0x3001A53, 0x3001A56, 0x3001A59, 0x3001A5C, 0x3001A5C, 0x3001A5F, 0x3001A62,
+	0x3001527, 0x3001A65, 0x3001A68, 0x3001A6B, 0x3001A6E, 0x4001A71, 0x3001A75, 0x4001A78, 0x30011C9, 0x4001A7C, 0x3001A80, 0x4001A83, 0x4001A87, 0x4001A8B, 0x3001A8F, 0x3001A92,
+	0x3001539, 0x4001A95, 0x4001A99, 0x4001A9D, 0x4001AA1, 0x3001AA5, 0x3001AA8, 0x3001AA8, 0x300153C, 0x3001596, 0x3001AAB, 0x3001AAE, 0x3001AB1, 0x4001AB4, 0x3001AB8, 0x3001157,
+	0x3001542, 0x3001ABB, 0x4001ABE, 0x3001463, 0x4001AC2, 0x4001AC6, 0x30013D9, 0x3001ACA, 0x3001ACD, 0x300146F, 0x3001AD0, 0x3001AD3, 0x4001AD6, 0x4001ADA, 0x4001ADA, 0x3001ADE,
+	0x3001AE1, 0x4001AE4, 0x3001AE8, 0x3001AEB, 0x3001AEE, 0x4001AF1, 0x3001AF5, 0x3001AF8, 0x3001AFB, 0x3001AFE, 0x3001B01, 0x4001B04, 0x3001B08, 0x3001B0B, 0x3001B0E, 0x3001B11,
+	0x3001B14, 0x3001B17, 0x4001B1A, 0x4001B1E, 0x3001B22, 0x4001B25, 0x3001B29, 0x4001B2C, 0x3001B30, 0x3001B33, 0x3001481, 0x4001B36, 0x4001B3A, 0x3001B3E, 0x4001B41, 0x3001B45,
+	0x4001B48, 0x3001B4C, 0x3001B4F, 0x3001B52, 0x3001B55, 0x3001B58, 0x3001B5B, 0x4001B5E, 0x4001B62, 0x4001B66, 0x4001B6A, 0x30018B2, 0x3001B6E, 0x3001B71, 0x3001B74, 0x3001B77,
+	0x3001B7A, 0x3001B7D, 0x3001B80, 0x3001B83, 0x3001B86, 0x3001B89, 0x3001B8C, 0x4001B8F, 0x30011FF, 0x3001B93, 0x3001B96, 0x3001B99, 0x3001B9C, 0x3001B9F, 0x3001BA2, 0x300148A,
+	0x3001BA5, 0x3001BA8, 0x3001BAB, 0x3001BAE, 0x4001BB1, 0x4001BB5, 0x4001BB9, 0x3001BBD, 0x3001BC0, 0x3001BC3, 0x3001BC6, 0x4001BC9, 0x3001BCD, 0x4001BD0, 0x3001BD4, 0x3001BD7,
+	0x4001BDA, 0x4001BDE, 0x3001BE2, 0x3001BE5, 0x3001148, 0x3001BE8, 0x3001BEB, 0x3001BEE, 0x3001BF1, 0x3001BF4, 0x3001BF7, 0x3001557, 0x3001BFA, 0x3001BFD, 0x3001C00, 0x3001C03,
+	0x3001C06, 0x3001C09, 0x3001C0C, 0x3001C0F, 0x3001C12, 0x4001C15, 0x3001C19, 0x3001C1C, 0x3001C1F, 0x3001C22, 0x3001C25, 0x4001C28, 0x4001C2C, 0x3001C30, 0x3001C33, 0x3001C36,
+	0x3001566, 0x3001569, 0x3001C39, 0x4001C3C, 0x3001C40, 0x3001C43, 0x3001C46, 0x3001C49, 0x4001C4C, 0x4001C50, 0x3001C54, 0x3001C57, 0x3001C5A, 0x4001C5D, 0x3001C61, 0x300156C,
+	0x4001C64, 0x4001C68, 0x3001C6C, 0x3001C6F, 0x3001C72, 0x4001C75, 0x3001C79, 0x3001C7C, 0x3001C7F, 0x3001C82, 0x3001C85, 0x3001C88, 0x3001C8B, 0x4001C8E, 0x3001C92, 0x3001C95,
+	0x3001C98, 0x4001C9B, 0x3001C9F, 0x3001CA2, 0x3001CA5, 0x3001CA8, 0x4001CAB, 0x4001CAF, 0x3001CB3, 0x3001CB6, 0x3001CB9, 0x4001CBC, 0x3001CC0, 0x4001CC3, 0x300157E, 0x300157E,
+	0x3001CC7, 0x4001CCA, 0x3001CCE, 0x3001CD1, 0x3001CD4, 0x3001CD7, 0x3001CDA, 0x3001CDD, 0x3001CE0, 0x4001CE3, 0x3001581, 0x3001CE7, 0x3001CEA, 0x3001CED, 0x3001CF0, 0x3001CF3,
+	0x4001CF6, 0x3001CFA, 0x4001CFD, 0x4001D01, 0x4001D05, 0x3001D09, 0x3001D0C, 0x3001D0F, 0x3001D12, 0x3001D15, 0x3001D18, 0x3001D1B, 0x3001D1E, 0x4001D21, 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, 0x12C0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12E0, 0x1300, 0x1320, 0x1340, 0x1360, 0x1380, 0x13A0, 0x13C0,
+	0x13E0, 0x1400, 0x1420, 0x1440, 0x1460, 0x1480, 0x14A0, 0x0, 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, 0x19A0,
+	0x0, 0x0, 0x0, 0x0, 0x19C0, 0x19E0, 0x0, 0x0, 0x0, 0x1A00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1A20, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x1A40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1A60, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1A80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1AA0, 0x1AC0, 0x0, 0x1AE0, 0x1B00, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0xCB6, 0x1B20, 0x1B40, 0x1B2C, 0x1B60, 0x1B80, 0x1BA0, 0xCC6, 0x1BC0, 0x1BE0, 0x1C00, 0x1B28, 0xCCA, 0xCB6, 0x1B20, 0xCC2,
+	0x1B2C, 0x1C20, 0xCBA, 0x1B24, 0xCC6, 0x1C40, 0x1C60, 0x1C80, 0x1C66, 0x1C4C, 0x1C6C, 0x1C52, 0x1C72, 0x1C58, 0x1CA0, 0x1CC0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1CE0, 0x1D00, 0x1D20, 0x1D40, 0x1D60, 0x1D80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1DA0, 0x1DC0, 0x1DE0, 0x1E00, 0x1E20, 0x0, 0x0, 0x0,
+	0x1E40, 0x1E60, 0x1E80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1EA0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1EC0, 0x1EE0, 0x1F00, 0x1F20, 0x1F40, 0x1F60, 0x1F80, 0x1FA0, 0x1FC0, 0x1FE0, 0x2000, 0x2020, 0x2040, 0x2060, 0x2080, 0x20A0,
+	0x20C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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[8416] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1001D25, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001D26, 0x0, 0x100004E, 0x0, 0x0, 0x0, 0x0, 0x3001D29,
+	0x0, 0x0, 0x1001D2C, 0x1001D2D, 0x3001D2E, 0x2001D31, 0x0, 0x0, 0x3001D33, 0x1001D36, 0x100007E, 0x0, 0x5001D37, 0x5001D3C, 0x5001D41, 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, 0x2001D46, 0x2001D48, 0x3000126, 0x3000129, 0x300012C, 0x300012F, 0x0, 0x3000132, 0x3000135, 0x3000138, 0x300013B, 0x300013E, 0x3000141, 0x3001D4A,
+	0x3001D4D, 0x0, 0x0, 0x3000144, 0x3000147, 0x300014A, 0x300014D, 0x3000150, 0x3000153, 0x3001D50, 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, 0x4001D53, 0x4001D57, 0x4001D5B, 0x2001D5F, 0x2001D61, 0x2001D63, 0x2001D65, 0x2001D67, 0x2001D69, 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, 0x2001D53, 0x2001D57, 0x2001D5B, 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, 0x2001D6B, 0x1000129, 0x100016B, 0x2001D6D, 0x2001D6F, 0x2001D71, 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, 0x3001D73, 0x3001D76, 0x3001D79, 0x3001D7C, 0x3001D7F, 0x3001D82, 0x0, 0x0,
+	0x2001D85, 0x1000135, 0x100017D, 0x100080E, 0x2001D87, 0x0, 0x0, 0x0, 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, 0x3001D89, 0x0, 0x0, 0x0, 0x1000326, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x3001D2E, 0x5001D8C, 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,
+	0x2001D91, 0x2001D93, 0x2000341, 0x4000341, 0x4000353, 0x2001D95, 0x2001D97, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2001D99, 0x2000E17, 0x2001D9B, 0x0, 0x2001D9D, 0x200035B, 0x0, 0x0, 0x0, 0x2001D9F, 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, 0x4001DA1, 0x0, 0x0, 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, 0x4001DA5, 0x4001DA9, 0x4001DAD, 0x4001DB1, 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, 0x9001DB5, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 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, 0x9001DBE, 0x6000579, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x6001DC7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x6001DCD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6001DD3, 0x6001DD9, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001DDF, 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, 0x9001DE2, 0x60005B5, 0x9001DEB, 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, 0x3001DF4, 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, 0x2001DF7, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x0, 0x1000030, 0x2001DF9, 0x1000751, 0x1000168,
+	0x1000192, 0x100003F, 0x10001C2, 0x100004E, 0x2001DFB, 0x2001DFD, 0x3001DFF, 0x1000636, 0x10000CC, 0x1000063, 0x2001E02, 0x2001E04, 0x2001E06, 0x10000F0, 0x0, 0x100012F,
+	0x1000702, 0x2001E08, 0x100007E, 0x2001E0A, 0x3001E0C, 0x3001E0F, 0x1000754, 0x1000195, 0x100008D, 0x3001E12, 0x2001E15, 0x10007E4, 0x3001E17, 0x2001D91, 0x2001E1A, 0x2001E1C,
+	0x2001D95, 0x2001E1E, 0x100006F, 0x100016B, 0x100008D, 0x10007E4, 0x2001D91, 0x2001E1A, 0x2000E17, 0x2001D95, 0x2001E1E, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2001E20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2001E22, 0x1000060, 0x2001E24, 0x2001E26, 0x2001E06,
+	0x100069A, 0x2001E28, 0x2001E2A, 0x2001E2C, 0x2001E2E, 0x2001E30, 0x2001E32, 0x3001E34, 0x2001E37, 0x2001E39, 0x3001E3B, 0x2001E3E, 0x2001E40, 0x2001E42, 0x2001E44, 0x2001E46,
+	0x2001E48, 0x2001E4A, 0x2001E4C, 0x2001E4E, 0x2001E50, 0x2001E52, 0x2001E54, 0x2001E56, 0x3001E58, 0x2001E5B, 0x2001E5D, 0x10001D4, 0x2001E5F, 0x2001E61, 0x200026B, 0x2001D93,
+	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, 0x3001E63, 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, 0x6001E66, 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, 0x6001E6C, 0x4000D8D, 0x4000D91, 0x4000D95, 0x400032B, 0x4000D99, 0x3001E72, 0x2000349, 0x3001E72,
+	0x3001E75, 0x5001E78, 0x6000DA1, 0x4000DA7, 0x6000DAB, 0x0, 0x4000DB1, 0x6001E7D, 0x4000DBB, 0x4000331, 0x4000DBF, 0x4000335, 0x4000DC3, 0x5001E83, 0x5001E88, 0x5001E8D,
+	0x4000DD6, 0x4000DDA, 0x6000DDE, 0x6000349, 0x0, 0x0, 0x4000DE4, 0x6000DE8, 0x4000DEE, 0x4000DF2, 0x4000DF6, 0x4000339, 0x0, 0x5001E92, 0x5001E97, 0x5001E9C,
+	0x4000E09, 0x4000E0D, 0x6000E11, 0x6000367, 0x4000E17, 0x4000E1B, 0x4000E1F, 0x6000E23, 0x4000E29, 0x4000E2D, 0x4000E31, 0x4000341, 0x4000E35, 0x5001EA1, 0x5001D8C, 0x1000E3D,
+	0x0, 0x0, 0x6000E3E, 0x4000E44, 0x6000E48, 0x0, 0x4000E4E, 0x6001EA6, 0x4000E58, 0x400033D, 0x4000E5C, 0x4000345, 0x4000E60, 0x3001D2E, 0x3001E92, 0x0,
+	0x1001D25, 0x1001D25, 0x1001D25, 0x1001D25, 0x1001D25, 0x1001D25, 0x1001D25, 0x1001D25, 0x1001D25, 0x1001D25, 0x1001D25, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3001EAC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3001EAF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x1001EB2, 0x2001EB3, 0x3001EB2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1001D25,
+	0x0, 0x0, 0x0, 0x6001EB5, 0x9001EBB, 0x0, 0x6001EC4, 0x9001ECA, 0x0, 0x0, 0x0, 0x0, 0x2001ED3, 0x0, 0x3001ED5, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2001ED8, 0x2001EDA, 0x2001EDC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC001EB5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1001D25,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1001EDE, 0x100006F, 0x0, 0x0, 0x1001D3B, 0x1001EDF, 0x1001EE0, 0x1001EE1, 0x1001EE2, 0x1001EE3, 0x1001EE4, 0x3001EE5, 0x1000EB7, 0x1001EE8, 0x1001EE9, 0x100007B,
+	0x1001EDE, 0x1001D36, 0x1001D2C, 0x1001D2D, 0x1001D3B, 0x1001EDF, 0x1001EE0, 0x1001EE1, 0x1001EE2, 0x1001EE3, 0x1001EE4, 0x3001EE5, 0x1000EB7, 0x1001EE8, 0x1001EE9, 0x0,
+	0x100004E, 0x1000063, 0x100007E, 0x100080E, 0x2001E02, 0x1000108, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x1000754, 0x100017D, 0x1000195, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2001EEA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3001EEC, 0x3001EEF, 0x1000012, 0x3001EF2, 0x0, 0x3001EF5, 0x3001EF8, 0x2001EFB, 0x0, 0x3001EFD, 0x10000F0, 0x1000105, 0x1000105, 0x1000105, 0x1000108, 0x2001F00,
+	0x1000021, 0x1000021, 0x1000132, 0x1000135, 0x0, 0x100002D, 0x2001F02, 0x0, 0x0, 0x1000751, 0x1001F04, 0x1000168, 0x1000168, 0x1000168, 0x0, 0x0,
+	0x2001F05, 0x3001F07, 0x2001F0A, 0x0, 0x10001D1, 0x0, 0x2000345, 0x0, 0x10001D1, 0x0, 0x100012C, 0x300000F, 0x1000633, 0x1000012, 0x0, 0x1000063,
+	0x1000015, 0x1000697, 0x0, 0x10006FF, 0x100007E, 0x20015C7, 0x20015D3, 0x20015D7, 0x20015DB, 0x100006F, 0x0, 0x3001F0C, 0x2001D97, 0x2001E1A, 0x2001F0F, 0x2001F11,
+	0x3001F13, 0x0, 0x0, 0x0, 0x0, 0x10000C9, 0x10000CC, 0x1000063, 0x100006F, 0x1000129, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x5001F16, 0x5001F1B, 0x6001F20, 0x5001F26, 0x5001F2B, 0x5001F30, 0x5001F35, 0x5001F3A, 0x5001F3F, 0x5001F44, 0x5001F49, 0x5001F4E, 0x5001F53, 0x5001F58, 0x5001F5D, 0x4001D3C,
+	0x1000021, 0x2001F62, 0x3001F64, 0x2001F67, 0x10007E1, 0x2001F69, 0x3001F6B, 0x4001F6E, 0x2001F72, 0x100080B, 0x2001F74, 0x3001F76, 0x1000132, 0x1000012, 0x10000C9, 0x10006FF,
+	0x100006F, 0x2001F79, 0x3001F7B, 0x2001F7E, 0x10007E4, 0x2001F80, 0x3001F82, 0x4001F85, 0x2001F89, 0x100080E, 0x2001F8B, 0x3001F8D, 0x1000135, 0x1000060, 0x10000CC, 0x1000702,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5001F90, 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, 0x6001F95, 0x9001F9B, 0x0, 0x6001FA4,
+	0x9001FAA, 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,
+	0x1001D36, 0x1001D2C, 0x1001D2D, 0x1001D3B, 0x1001EDF, 0x1001EE0, 0x1001EE1, 0x1001EE2, 0x1001EE3, 0x2001F24, 0x2001D36, 0x2001FB3, 0x2001FB5, 0x2001FB7, 0x2001FB9, 0x2001FBB,
+	0x2001FBD, 0x2001FBF, 0x2001FC1, 0x2001FC3, 0x3001FC5, 0x3001FC8, 0x3001FCB, 0x3001FCE, 0x3001FD1, 0x3001FD4, 0x3001FD7, 0x3001FDA, 0x3001FDD, 0x4001FE0, 0x4001FE4, 0x4001FE8,
+	0x4001FEC, 0x4001FF0, 0x4001FF4, 0x4001FF8, 0x4001FFC, 0x4002000, 0x4002004, 0x4002008, 0x200200C, 0x200200E, 0x2002010, 0x2002012, 0x2002014, 0x2002016, 0x2002018, 0x200201A,
+	0x200201C, 0x300201E, 0x3002021, 0x3002024, 0x3002027, 0x300202A, 0x300202D, 0x3002030, 0x3002033, 0x3002036, 0x3002039, 0x300203C, 0x300203F, 0x3002042, 0x3002045, 0x3002048,
+	0x300204B, 0x300204E, 0x3002051, 0x3002054, 0x3002057, 0x300205A, 0x300205D, 0x3002060, 0x3002063, 0x3002066, 0x3002069, 0x300206C, 0x300206F, 0x3002072, 0x3002075, 0x3002078,
+	0x300207B, 0x300207E, 0x3002081, 0x3002084, 0x3002087, 0x300208A, 0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126,
+	0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030, 0x1000751, 0x1001F04, 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,
+	0x1002070, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1001EDE, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC001F95, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x2002090, 0x300208F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 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, 0x3002092,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3002095,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3002098, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300209B, 0x300209E, 0x30020A1, 0x30020A4, 0x30020A7, 0x30020AA, 0x30020AD, 0x30020B0, 0x30020B3, 0x30020B6, 0x30020B9, 0x30020BC, 0x30020BF, 0x30020C2, 0x30020C5, 0x30020C8,
+	0x3001777, 0x30020CB, 0x3001241, 0x30020CE, 0x30020D1, 0x30020D4, 0x30020D7, 0x30020DA, 0x30020DD, 0x30020E0, 0x30020E3, 0x30020E6, 0x30020E9, 0x30020EC, 0x30020EF, 0x30020F2,
+	0x30020F5, 0x30020F8, 0x30020FB, 0x30020FE, 0x3002101, 0x3001226, 0x3002104, 0x3002107, 0x300210A, 0x300210D, 0x300185C, 0x3002110, 0x3001427, 0x3002113, 0x3002116, 0x3002119,
+	0x300211C, 0x300211F, 0x3002122, 0x3002125, 0x3002128, 0x300212B, 0x30018AB, 0x300212E, 0x3002131, 0x3002134, 0x3002137, 0x300213A, 0x300213D, 0x3002140, 0x3002143, 0x3002146,
+	0x3002149, 0x300214C, 0x300214F, 0x3002152, 0x3002155, 0x3002158, 0x300215B, 0x300215E, 0x3002161, 0x3002164, 0x3002167, 0x300216A, 0x300216D, 0x3001512, 0x3002170, 0x3002173,
+	0x3002176, 0x3002179, 0x300217C, 0x300217F, 0x3002182, 0x3002185, 0x3002188, 0x300218B, 0x300218E, 0x3002191, 0x3002194, 0x3002197, 0x300219A, 0x300219D, 0x30021A0, 0x30021A3,
+	0x30021A6, 0x30021A9, 0x30021AC, 0x30021AF, 0x30021B2, 0x30021B5, 0x30021B8, 0x30021BB, 0x30021BE, 0x30021C1, 0x30021C4, 0x30021C7, 0x30021CA, 0x30021CD, 0x30021D0, 0x30021D3,
+	0x30021D6, 0x30021D9, 0x30021DC, 0x30021DF, 0x300137C, 0x30021E2, 0x30021E5, 0x30021E8, 0x30021EB, 0x30021EE, 0x30021F1, 0x30013E2, 0x3001142, 0x30021F4, 0x30021F7, 0x30021FA,
+	0x30021FD, 0x3002200, 0x3002203, 0x3002206, 0x3002209, 0x300220C, 0x300220F, 0x3002212, 0x3002215, 0x3002218, 0x300221B, 0x300221E, 0x3002221, 0x3002224, 0x3002227, 0x30013AF,
+	0x3001C12, 0x300222A, 0x30013B5, 0x300222D, 0x3002230, 0x3002233, 0x3002236, 0x3001C39, 0x3002239, 0x300223C, 0x300223F, 0x3002242, 0x3002245, 0x3002248, 0x30010AF, 0x300224B,
+	0x30011F6, 0x300224E, 0x3002251, 0x3002254, 0x3002257, 0x3001352, 0x30010C4, 0x300225A, 0x300225D, 0x3002260, 0x3002263, 0x3002266, 0x3002269, 0x300226C, 0x300226F, 0x3002272,
+	0x3002275, 0x3002278, 0x300227B, 0x300227E, 0x3002281, 0x3002284, 0x3002287, 0x300228A, 0x300228D, 0x3002290, 0x3002293, 0x3002296, 0x3002299, 0x300229C, 0x300229F, 0x30022A2,
+	0x30022A5, 0x30022A8, 0x30022AB, 0x30022AE, 0x30022B1, 0x3001166, 0x30022B4, 0x3001D09, 0x30022B7, 0x30022BA, 0x30022BD, 0x3001D0F, 0x30022C0, 0x30022C3, 0x30022C6, 0x30022C9,
+	0x3001D1E, 0x30022CC, 0x30022CF, 0x30012E6, 0x30010BE, 0x30022D2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1001D25, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30022D5, 0x0, 0x30020DA, 0x30022D8, 0x30022DB, 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, 0x40022DE, 0x40022E2, 0x0, 0x6000FE9, 0x60022E6,
+	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, 0x60022EC,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x30022F2, 0x30022F5, 0x30022F8, 0x30022FB, 0x30022FE, 0x3002301, 0x3002304, 0x3002307, 0x300230A, 0x300230D, 0x3002310, 0x3002313, 0x3002316, 0x3002319, 0x300231C,
+	0x300231F, 0x3002322, 0x3002325, 0x3002328, 0x300232B, 0x300232E, 0x3002331, 0x3002334, 0x3002337, 0x300233A, 0x300233D, 0x3002340, 0x3002343, 0x3002346, 0x3002349, 0x300234C,
+	0x300234F, 0x3002352, 0x3002355, 0x3002358, 0x300235B, 0x300235E, 0x3002361, 0x3002364, 0x3002367, 0x300236A, 0x300236D, 0x3002370, 0x3002373, 0x3002376, 0x3002379, 0x300237C,
+	0x300237F, 0x3002382, 0x3002385, 0x3002388, 0x300238B, 0x300238E, 0x3002391, 0x3002394, 0x3002397, 0x300239A, 0x300239D, 0x30023A0, 0x30023A3, 0x30023A6, 0x30023A9, 0x30023AC,
+	0x30023AF, 0x30023B2, 0x30023B5, 0x30023B8, 0x30023BB, 0x30023BE, 0x30023C1, 0x30023C4, 0x30023C7, 0x30023CA, 0x30023CD, 0x30023D0, 0x30023D3, 0x30023D6, 0x30023D9, 0x30023DC,
+	0x30023DF, 0x30023E2, 0x30023E5, 0x30023E8, 0x30023EB, 0x30023EE, 0x30023F1, 0x30023F4, 0x30023F7, 0x30023FA, 0x30023FD, 0x3002400, 0x3002403, 0x3002406, 0x3002409, 0x0,
+	0x0, 0x0, 0x300209B, 0x30020AD, 0x300240C, 0x300240F, 0x3002412, 0x3002415, 0x3002418, 0x300241B, 0x30020A7, 0x300241E, 0x3002421, 0x3002424, 0x3002427, 0x30020B3,
+	0x500242A, 0x500242F, 0x5002434, 0x5002439, 0x500243E, 0x5002443, 0x5002448, 0x500244D, 0x5002452, 0x5002457, 0x500245C, 0x5002461, 0x5002466, 0x500246B, 0x8002470, 0x8002478,
+	0x8002480, 0x8002488, 0x8002490, 0x8002498, 0x80024A0, 0x80024A8, 0x80024B0, 0x80024B8, 0x80024C0, 0x80024C8, 0x80024D0, 0x80024D8, 0x80024E0, 0x110024E8, 0xE0024F9, 0x0,
+	0x5002507, 0x500250C, 0x5002511, 0x5002516, 0x500251B, 0x5002520, 0x5002525, 0x500252A, 0x500252F, 0x5002534, 0x5002539, 0x500253E, 0x5002543, 0x5002548, 0x500254D, 0x5002552,
+	0x5002557, 0x500255C, 0x5002561, 0x5002566, 0x500256B, 0x5002570, 0x5002575, 0x500257A, 0x500257F, 0x5002584, 0x5002589, 0x500258E, 0x5002593, 0x5002598, 0x500259D, 0x50025A2,
+	0x50025A7, 0x50025AC, 0x50025B1, 0x50025B6, 0x30025BB, 0x30025BE, 0x300214F, 0x30025C1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30025C4, 0x2001FB4, 0x20025C7, 0x2001D2C, 0x20025C9, 0x20025CB, 0x20025CD, 0x20025CF, 0x20025D1, 0x20025D3, 0x20025D5, 0x2001F2F, 0x2001F2A, 0x20025D7, 0x20025D9, 0x20025DB,
+	0x30022F2, 0x30022FB, 0x3002304, 0x300230A, 0x3002322, 0x3002325, 0x300232E, 0x3002334, 0x3002337, 0x300233D, 0x3002340, 0x3002343, 0x3002346, 0x3002349, 0x6002471, 0x6002479,
+	0x6002481, 0x6002489, 0x6002491, 0x6002499, 0x60024A1, 0x60024A9, 0x60024B1, 0x60024B9, 0x60024C1, 0x60024C9, 0x60024D1, 0x6002349, 0xF0025DD, 0xC0025EC, 0x60025F8, 0x0,
+	0x300209B, 0x30020AD, 0x300240C, 0x300240F, 0x300251C, 0x300130D, 0x3002526, 0x30020BC, 0x3002530, 0x30020DA, 0x3002164, 0x3002185, 0x3002182, 0x3002167, 0x30010C4, 0x30020F2,
+	0x300215E, 0x300255D, 0x3002562, 0x3001457, 0x300256C, 0x3002571, 0x3002576, 0x3001466, 0x3002580, 0x30025FE, 0x3002601, 0x3001226, 0x3002604, 0x3002607, 0x300260A, 0x300260D,
+	0x3002610, 0x30025AD, 0x3002613, 0x3002616, 0x3002412, 0x3002415, 0x3002418, 0x3002619, 0x300261C, 0x300261F, 0x3002622, 0x300258F, 0x3002594, 0x3002599, 0x300259E, 0x30025A3,
+	0x3002625, 0x2002628, 0x200262A, 0x200262C, 0x200262E, 0x2002630, 0x2001D3B, 0x20025CA, 0x20025DA, 0x2002632, 0x2002634, 0x2002636, 0x2002638, 0x200263A, 0x200263C, 0x200263E,
+	0x4002640, 0x4002644, 0x4002648, 0x400264C, 0x4002650, 0x4002654, 0x4002658, 0x400265C, 0x4002660, 0x5002664, 0x5002669, 0x500266E, 0x2002673, 0x3002675, 0x2002678, 0x300267A,
+	0x300267D, 0x3002680, 0x3001085, 0x3002683, 0x3002686, 0x3000FEF, 0x3000FF5, 0x3000FFB, 0x3001001, 0x3001007, 0x300100D, 0x3001013, 0x3001019, 0x300101F, 0x3001025, 0x300102B,
+	0x3001031, 0x3001037, 0x300103D, 0x3001043, 0x3002689, 0x300268C, 0x300268F, 0x3002692, 0x3002695, 0x3001049, 0x3001055, 0x3001061, 0x300106D, 0x3001079, 0x3002698, 0x300269B,
+	0x300269E, 0x30026A1, 0x30026A4, 0x30026A7, 0x30026AA, 0x30026AD, 0x30026B0, 0x30026B3, 0x30026B6, 0x30026B9, 0x30026BC, 0x300108B, 0x3001091, 0x3001097, 0x300109D, 0x60026BF,
+	0xF0026C5, 0xC0026D4, 0xF0026E0, 0x90026EF, 0xF0026F8, 0x9002707, 0x9002710, 0x12002719, 0xC00272B, 0x9002737, 0x9002740, 0x9002749, 0xC002752, 0xC00275E, 0xC00276A, 0xC002776,
+	0xC002782, 0xC00278E, 0xC00279A, 0x120027A6, 0x60027B8, 0x120027BE, 0x120027D0, 0xF0027E2, 0xC0027C4, 0x120027F1, 0x12002803, 0xC002815, 0x9002821, 0x900282A, 0xC002833, 0xC00283F,
+	0xF00284B, 0xF00285A, 0x9002869, 0x9002872, 0xC00287B, 0x9002887, 0x9002890, 0x60027FD, 0x6002899, 0x900289F, 0x90028A8, 0x120028B1, 0xC0028C3, 0xF0028CF, 0x120028DE, 0xC0028F0,
+	0x90028FC, 0x9002905, 0x1200290E, 0xC002920, 0x1200292C, 0x900293E, 0xF002947, 0x9002956, 0xC00295F, 0x900296B, 0xC002974, 0xF002980, 0xC00298F, 0xF00299B, 0xC0029AA, 0x60029B6,
+	0xF0029BC, 0x90029CB, 0x90029D4, 0xC0029DD, 0x90029E9, 0x90029F2, 0x90029FB, 0xF002A04, 0xC002A13, 0x6002A1F, 0x12002A25, 0x9002A37, 0xF002A40, 0xC0027D6, 0xC002A4F, 0x9002A5B,
+	0x9002A64, 0xC002A6D, 0x6002A79, 0xC002A7F, 0xF002A8B, 0x6002A9A, 0x12002AA0, 0x90027E8, 0x4002AB2, 0x4002AB6, 0x4002ABA, 0x4002ABE, 0x4002AC2, 0x4002AC6, 0x4002ACA, 0x4002ACE,
+	0x4002AD2, 0x4002AD6, 0x5002ADA, 0x5002ADF, 0x5002AE4, 0x5002AE9, 0x5002AEE, 0x5002AF3, 0x5002AF8, 0x5002AFD, 0x5002B02, 0x5002B07, 0x5002B0C, 0x5002B11, 0x5002B16, 0x5002B1B,
+	0x5002B20, 0x3002B25, 0x2002B28, 0x2002B2A, 0x3002B2C, 0x2002B2F, 0x2002B31, 0x2002B33, 0x3002B35, 0x3002B38, 0x2002B3B, 0x6002B3D, 0x6002B43, 0x6002B49, 0x6002B4F, 0xC002B55,
+	0x2002B61, 0x2002B63, 0x3002B65, 0x2002B68, 0x2002B6A, 0x2002B6C, 0x2002B6E, 0x2002B70, 0x3002B72, 0x4002B75, 0x2002B79, 0x2002B7B, 0x3002B7D, 0x3002B80, 0x2002B83, 0x2002B85,
+	0x2002B87, 0x3002B89, 0x3002B8C, 0x3002B8F, 0x3002B92, 0x3002B95, 0x2002B98, 0x2002B9A, 0x2002B9C, 0x2002B9E, 0x2002BA0, 0x3002BA2, 0x2002BA5, 0x2002BA7, 0x2002BA9, 0x3002BAB,
+	0x3002BAE, 0x2002B36, 0x3002BB1, 0x3002BB4, 0x3002BB7, 0x2002B39, 0x3002BBA, 0x5002BBD, 0x6002BC2, 0x2002B26, 0x3002BC8, 0x3002BCB, 0x3002BCE, 0x3002BD1, 0x7002BD4, 0x8002BDB,
+	0x2002BE3, 0x2002BE5, 0x3002BE7, 0x2002BEA, 0x2002BEC, 0x2002BEE, 0x3002BF0, 0x2002BF3, 0x2002BF5, 0x2002BF7, 0x2002BF9, 0x2002BFB, 0x3002BFD, 0x2002C00, 0x2002C02, 0x2002C04,
+	0x3002C06, 0x3002C09, 0x4002C0C, 0x2002C10, 0x2002C12, 0x2002B32, 0x6002C14, 0x3002C1A, 0x2002C1D, 0x2002C1F, 0x2002C21, 0x2002C23, 0x2002C25, 0x2002C27, 0x2002C29, 0x2002C2B,
+	0x2002B97, 0x2002C2D, 0x3002C2F, 0x2002C32, 0x2002C34, 0x3002C36, 0x3002C39, 0x2002C3C, 0x4002C3E, 0x3002C42, 0x2002C45, 0x2002BDA, 0x2002C47, 0x2002C49, 0x5002C4B, 0x5002C50,
+	0x4002C55, 0x4002C59, 0x4002C5D, 0x4002C61, 0x4002C65, 0x4002C69, 0x4002C6D, 0x4002C71, 0x4002C75, 0x5002C79, 0x5002C7E, 0x5002C83, 0x5002C88, 0x5002C8D, 0x5002C92, 0x5002C97,
+	0x5002C9C, 0x5002CA1, 0x5002CA6, 0x5002CAB, 0x5002CB0, 0x5002CB5, 0x5002CBA, 0x5002CBF, 0x5002CC4, 0x5002CC9, 0x5002CCE, 0x5002CD3, 0x5002CD8, 0x5002CDD, 0x5002CE2, 0x3002CE7,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2002CEA, 0x2002CEC, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3002CEE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2002CF1, 0x2002CF3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3002CF5, 0x3002CF8, 0x2002CFB, 0x3002CFD,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2002D00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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,
+	0x2002D02, 0x2002D04, 0x2002D06, 0x3002D08, 0x3002D0B, 0x2002D0E, 0x2002D0E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x4002D10, 0x4002D14, 0x4002D18, 0x4002D1C, 0x4002D20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40015AB, 0x0, 0x40015AF,
+	0x2002D24, 0x20015C7, 0x20015DB, 0x20015DF, 0x20015F7, 0x20015FB, 0x2002D26, 0x200161B, 0x200161F, 0x1001EE4, 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, 0x4002D28,
+	0x2002D2C, 0x2002D2C, 0x2002D2E, 0x2002D2E, 0x2002D2E, 0x2002D2E, 0x2002D30, 0x2002D30, 0x2002D30, 0x2002D30, 0x2002D32, 0x2002D32, 0x2002D32, 0x2002D32, 0x2002D34, 0x2002D34,
+	0x2002D34, 0x2002D34, 0x2002D36, 0x2002D36, 0x2002D36, 0x2002D36, 0x2002D38, 0x2002D38, 0x2002D38, 0x2002D38, 0x2002D3A, 0x2002D3A, 0x2002D3A, 0x2002D3A, 0x2002D3C, 0x2002D3C,
+	0x2002D3C, 0x2002D3C, 0x2002D3E, 0x2002D3E, 0x2002D3E, 0x2002D3E, 0x2002D40, 0x2002D40, 0x2002D40, 0x2002D40, 0x2002D42, 0x2002D42, 0x2002D42, 0x2002D42, 0x2002D44, 0x2002D44,
+	0x2002D44, 0x2002D44, 0x2002D46, 0x2002D46, 0x2002D48, 0x2002D48, 0x2002D4A, 0x2002D4A, 0x2002D4C, 0x2002D4C, 0x2002D4E, 0x2002D4E, 0x2002D50, 0x2002D50, 0x2002D52, 0x2002D52,
+	0x2002D52, 0x2002D52, 0x2002D54, 0x2002D54, 0x2002D54, 0x2002D54, 0x2002D56, 0x2002D56, 0x2002D56, 0x2002D56, 0x2002D58, 0x2002D58, 0x2002D58, 0x2002D58, 0x2002D5A, 0x2002D5A,
+	0x2002D5C, 0x2002D5C, 0x2002D5C, 0x2002D5C, 0x4000465, 0x4000465, 0x2000469, 0x2000469, 0x2000469, 0x2000469, 0x2002D5E, 0x2002D5E, 0x2002D5E, 0x2002D5E, 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, 0x2002D60, 0x2002D60, 0x2002D60, 0x2002D60, 0x2001DAD, 0x2001DAD, 0x2002D62, 0x2002D62, 0x2002D64, 0x2002D64, 0x4001DAD, 0x2002D66, 0x2002D66,
+	0x2002D68, 0x2002D68, 0x2002D6A, 0x2002D6A, 0x2002D6C, 0x2002D6C, 0x2002D6C, 0x2002D6C, 0x2002D6E, 0x2002D6E, 0x6002D70, 0x6002D70, 0x6000461, 0x6000461, 0x6002D76, 0x6002D76,
+	0x6002D7C, 0x6002D7C, 0x6002D82, 0x6002D82, 0x6002D88, 0x6002D88, 0x6002D8E, 0x6002D8E, 0x6002D8E, 0x6002D94, 0x6002D94, 0x6002D94, 0x2002D9A, 0x2002D9A, 0x2002D9A, 0x2002D9A,
+	0x6002D9C, 0x6002DA2, 0x6002DA8, 0x6002D94, 0x6002DAE, 0x4002DB4, 0x4002DB8, 0x4002DBC, 0x4002DC0, 0x4002DC4, 0x4002DC8, 0x4002DCC, 0x4002DD0, 0x4002DD4, 0x4002DD8, 0x4002DDC,
+	0x4002DE0, 0x4002DE4, 0x4002DE8, 0x4002DEC, 0x4002DF0, 0x4002DF4, 0x4002DF8, 0x4002DF6, 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, 0x4002EA4, 0x4002EA8, 0x4002EAC, 0x4002EB0, 0x4002DFA, 0x4002DFE, 0x4002EB4, 0x4002EB8, 0x4002DAC, 0x4002EBC, 0x4002EC0, 0x4002EC4, 0x4002EC8, 0x4002ECC,
+	0x4002ED0, 0x4002ED4, 0x4002ED8, 0x4002EDC, 0x4002EE0, 0x4002DF2, 0x4002EE4, 0x4002EE8, 0x4002EAE, 0x4002EEC, 0x4002EE2, 0x4002EF0, 0x4002EF4, 0x4002EF8, 0x5002EFC, 0x5002F01,
+	0x5002F06, 0x5002F0B, 0x5002F10, 0x5002F15, 0x6002F1A, 0x6002F20, 0x6002DA8, 0x6002F26, 0x6002D94, 0x6002DAE, 0x4002F2C, 0x4002F30, 0x4002DC0, 0x4002F34, 0x4002DC4, 0x4002DC8,
+	0x4002F38, 0x4002F3C, 0x4002DD8, 0x4002F40, 0x4002DDC, 0x4002DE0, 0x4002F44, 0x4002F48, 0x4002DE8, 0x4002F4C, 0x4002DEC, 0x4002DF0, 0x4002E60, 0x4002E64, 0x4002E70, 0x4002E74,
+	0x4002E78, 0x4002E88, 0x4002E8C, 0x4002E90, 0x4002E94, 0x4002EA4, 0x4002EA8, 0x4002EAC, 0x4002F50, 0x4002EB4, 0x4002F54, 0x4002F58, 0x4002EC8, 0x4002F5C, 0x4002ECC, 0x4002ED0,
+	0x4002EF8, 0x4002F60, 0x4002F64, 0x4002EAE, 0x4002F68, 0x4002EEC, 0x4002EE2, 0x6002D9C, 0x6002DA2, 0x6002F6C, 0x6002DA8, 0x6002F72, 0x4002DB4, 0x4002DB8, 0x4002DBC, 0x4002DC0,
+	0x4002F78, 0x4002DCC, 0x4002DD0, 0x4002DD4, 0x4002DD8, 0x4002F7C, 0x4002DE8, 0x4002DF4, 0x4002DF8, 0x4002DF6, 0x4002DFC, 0x4002E00, 0x4002E08, 0x4002E0C, 0x4002E10, 0x4002E14,
+	0x4002E18, 0x4002E1C, 0x4002F80, 0x4002E20, 0x4002E24, 0x4002E28, 0x4002E2C, 0x4002E30, 0x4002E34, 0x4002E3C, 0x4002E40, 0x4002E44, 0x4002E48, 0x4002E4C, 0x4002E50, 0x4002E54,
+	0x4002E58, 0x4002E5C, 0x4002E68, 0x4002E6C, 0x4002E7C, 0x4002E80, 0x4002E84, 0x4002E88, 0x4002E8C, 0x4002E98, 0x4002E9C, 0x4002EA0, 0x4002EA4, 0x4002F84, 0x4002EB0, 0x4002DFA,
+	0x4002DFE, 0x4002EB4, 0x4002EBC, 0x4002EC0, 0x4002EC4, 0x4002EC8, 0x4002F88, 0x4002ED4, 0x4002ED8, 0x4002F8C, 0x4002DF2, 0x4002F90, 0x4002EE8, 0x4002EAE, 0x4002ED2, 0x6002DA8,
+	0x6002F72, 0x4002DC0, 0x4002F78, 0x4002DD8, 0x4002F7C, 0x4002DE8, 0x4002F94, 0x4002E18, 0x4002F98, 0x4002F9C, 0x4002FA0, 0x4002E88, 0x4002E8C, 0x4002EA4, 0x4002EC8, 0x4002F88,
+	0x4002EAE, 0x4002ED2, 0x6002FA4, 0x6002FAA, 0x6002FB0, 0x4002FB6, 0x4002FBA, 0x4002FBE, 0x4002FC2, 0x4002FC6, 0x4002FCA, 0x4002FCE, 0x4002FD2, 0x4002FD6, 0x4002FDA, 0x4002FDE,
+	0x4002DA6, 0x4002FE2, 0x4002DA0, 0x4002FE6, 0x4002EEA, 0x4002FEA, 0x4002FEE, 0x4002FF2, 0x4002FF6, 0x4002FFA, 0x4002FFE, 0x4003002, 0x4002F9C, 0x4003006, 0x400300A, 0x400300E,
+	0x4003012, 0x4002FB6, 0x4002FBA, 0x4002FBE, 0x4002FC2, 0x4002FC6, 0x4002FCA, 0x4002FCE, 0x4002FD2, 0x4002FD6, 0x4002FDA, 0x4002FDE, 0x4002DA6, 0x4002FE2, 0x4002DA0, 0x4002FE6,
+	0x4002EEA, 0x4002FEA, 0x4002FEE, 0x4002FF2, 0x4002FF6, 0x4002FFA, 0x4002FFE, 0x4003002, 0x4002F9C, 0x4003006, 0x400300A, 0x400300E, 0x4003012, 0x4002FFA, 0x4002FFE, 0x4003002,
+	0x4002F9C, 0x4002F98, 0x4002FA0, 0x4002E38, 0x4002E0C, 0x4002E10, 0x4002E14, 0x4002FFA, 0x4002FFE, 0x4003002, 0x4002E38, 0x4002E3C, 0x4003016, 0x4003016, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x600301A, 0x6003020, 0x6003020, 0x6003026, 0x600302C, 0x6003032, 0x6003038, 0x600303E, 0x6002DF8, 0x6002DF8, 0x6003044, 0x600304A, 0x6003050, 0x6003056, 0x600305C, 0x6003062,
+	0x6003062, 0x6003068, 0x600306E, 0x600306E, 0x6003074, 0x6003074, 0x600307A, 0x6003080, 0x6003080, 0x6003086, 0x600308C, 0x600308C, 0x6003092, 0x6003092, 0x6003098, 0x600309E,
+	0x600309E, 0x60030A4, 0x60030A4, 0x60030AA, 0x60030B0, 0x60030B6, 0x60030BC, 0x60030BC, 0x60030C2, 0x60030C8, 0x60030CE, 0x60030D4, 0x60030DA, 0x60030DA, 0x60030E0, 0x60030E6,
+	0x60030EC, 0x60030F2, 0x60030F8, 0x60030FE, 0x60030FE, 0x6003104, 0x6003104, 0x600310A, 0x600310A, 0x6003110, 0x6002DFA, 0x6003116, 0x600311C, 0x6002EB0, 0x6002DFE, 0x6003122,
+	0x0, 0x0, 0x6003128, 0x600312E, 0x6003134, 0x600313A, 0x6003140, 0x6003146, 0x6003146, 0x600314C, 0x6003152, 0x6003158, 0x600315E, 0x600315E, 0x6003164, 0x600316A,
+	0x6003170, 0x6003176, 0x600317C, 0x6003182, 0x6003188, 0x600318E, 0x6003194, 0x600319A, 0x60031A0, 0x60031A6, 0x60031AC, 0x60031B2, 0x60031B8, 0x60031BE, 0x60031C4, 0x60031CA,
+	0x60031D0, 0x60031D6, 0x60031DC, 0x60031E2, 0x60030E0, 0x60030EC, 0x60031E8, 0x60031EE, 0x60031F4, 0x60031FA, 0x6003200, 0x6003206, 0x6003200, 0x60031F4, 0x600320C, 0x6003212,
+	0x6003218, 0x600321E, 0x6003224, 0x6003206, 0x60030B6, 0x600307A, 0x600322A, 0x6003230, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6003236, 0x600323C, 0x8003242, 0x800324A, 0x8003252, 0x800325A, 0x8003262, 0x800326A, 0x8003272, 0x600327A, 0x21003280, 0xF0032A1, 0x80032B0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x10032B8, 0x30032B9, 0x30032BC, 0x100208D, 0x1000326, 0x1001ED3, 0x1001ED8, 0x30032BF, 0x30032C2, 0x3001EB2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2001EB2, 0x30032C5, 0x30032C8, 0x10032CB, 0x10032CB, 0x1001EE8, 0x1001EE9, 0x10032CC, 0x10032CD, 0x30032CE, 0x30032D1, 0x30032D4, 0x30032D7, 0x30032DA, 0x30032DD, 0x3000F42,
+	0x3000F45, 0x30032E0, 0x30032E3, 0x30032E6, 0x30032E9, 0x0, 0x0, 0x10032EC, 0x10032ED, 0x3001ED5, 0x3001ED5, 0x3001ED5, 0x3001ED5, 0x10032CB, 0x10032CB, 0x10032CB,
+	0x10032B8, 0x30032B9, 0x1001EB2, 0x0, 0x1000326, 0x100208D, 0x1001ED8, 0x1001ED3, 0x30032C5, 0x1001EE8, 0x1001EE9, 0x10032CC, 0x10032CD, 0x30032CE, 0x30032D1, 0x10032EE,
+	0x10032EF, 0x10032F0, 0x1001EE4, 0x10032F1, 0x1000EC4, 0x1000EC7, 0x1000EB7, 0x0, 0x10032F2, 0x10032F3, 0x10032F4, 0x10032F5, 0x0, 0x0, 0x0, 0x0,
+	0x30032F6, 0x40032F9, 0x3002EFC, 0x0, 0x3002F01, 0x0, 0x3002F06, 0x4002FA4, 0x3002F0B, 0x4002FAA, 0x3002F10, 0x4002FB0, 0x3002F15, 0x40032FD, 0x3003301, 0x4003304,
+	0x2003308, 0x4000451, 0x4000451, 0x4000455, 0x4000455, 0x4000459, 0x4000459, 0x400045D, 0x400045D, 0x4000461, 0x4000461, 0x4000461, 0x4000461, 0x2000451, 0x2000451, 0x2002DB4,
+	0x2002DB4, 0x2002DB4, 0x2002DB4, 0x200330A, 0x200330A, 0x2002DCC, 0x2002DCC, 0x2002DCC, 0x2002DCC, 0x2002DE4, 0x2002DE4, 0x2002DE4, 0x2002DE4, 0x2002DA0, 0x2002DA0, 0x2002DA0,
+	0x2002DA0, 0x2002DA6, 0x2002DA6, 0x2002DA6, 0x2002DA6, 0x2002DBE, 0x2002DBE, 0x2002DBE, 0x2002DBE, 0x2003258, 0x2003258, 0x2002EF0, 0x2002EF0, 0x2002EF4, 0x2002EF4, 0x2002F24,
+	0x2002F24, 0x2002E0C, 0x2002E0C, 0x2002E0C, 0x2002E0C, 0x2002F9C, 0x2002F9C, 0x2002F9C, 0x2002F9C, 0x2002E1C, 0x2002E1C, 0x2002E1C, 0x2002E1C, 0x2002E24, 0x2002E24, 0x2002E24,
+	0x2002E24, 0x2002E34, 0x2002E34, 0x2002E34, 0x2002E34, 0x2002E3C, 0x2002E3C, 0x2002E3C, 0x2002E3C, 0x2002E40, 0x2002E40, 0x2002E40, 0x2002E40, 0x2002E48, 0x2002E48, 0x2002E48,
+	0x2002E48, 0x2002E50, 0x2002E50, 0x2002E50, 0x2002E50, 0x2002E68, 0x2002E68, 0x2002E68, 0x2002E68, 0x2002E78, 0x2002E78, 0x2002E78, 0x2002E78, 0x2002E8A, 0x2002E8A, 0x2002E8A,
+	0x2002E8A, 0x2002DAC, 0x2002DAC, 0x2002DAC, 0x2002DAC, 0x2002EBC, 0x2002EBC, 0x2002EBC, 0x2002EBC, 0x2002ED4, 0x2002ED4, 0x2002ED4, 0x2002ED4, 0x2000459, 0x2000459, 0x2002D6E,
+	0x2002D6E, 0x2000461, 0x2000461, 0x2000461, 0x2000461, 0x600330C, 0x600330C, 0x6003312, 0x6003312, 0x6003318, 0x6003318, 0x40032A8, 0x40032A8, 0x0, 0x0, 0x0,
+	0x0, 0x1001ED3, 0x100331E, 0x10032EE, 0x10032F3, 0x10032F4, 0x10032EF, 0x100331F, 0x1001EE8, 0x1001EE9, 0x10032F0, 0x1001EE4, 0x10032B8, 0x10032F1, 0x1001EB2, 0x1001EED,
+	0x1001EDE, 0x1001D36, 0x1001D2C, 0x1001D2D, 0x1001D3B, 0x1001EDF, 0x1001EE0, 0x1001EE1, 0x1001EE2, 0x1001EE3, 0x100208D, 0x1000326, 0x1000EC4, 0x1000EB7, 0x1000EC7, 0x1001ED8,
+	0x10032F5, 0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030,
+	0x1000751, 0x1001F04, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x10032EC, 0x10032F2, 0x10032ED, 0x1003320, 0x10032CB,
+	0x1000E3D, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B, 0x100007E,
+	0x1000754, 0x1002070, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x10032CC, 0x1003321, 0x10032CD, 0x1003322, 0x3003323,
+	0x3003326, 0x30032BC, 0x30032E0, 0x30032E3, 0x30032B9, 0x3003329, 0x300109D, 0x30026DD, 0x3002923, 0x300332C, 0x3002938, 0x3002713, 0x300332F, 0x300279D, 0x3002A0D, 0x3002758,
+	0x30026CE, 0x300267D, 0x3002680, 0x3001085, 0x3002683, 0x3002686, 0x3000FEF, 0x3000FF5, 0x3000FFB, 0x3001001, 0x3001007, 0x300100D, 0x3001013, 0x3001019, 0x300101F, 0x3001025,
+	0x300102B, 0x3001031, 0x3001037, 0x300103D, 0x3001043, 0x3002689, 0x300268C, 0x300268F, 0x3002692, 0x3002695, 0x3001049, 0x3001055, 0x3001061, 0x300106D, 0x3001079, 0x3002698,
+	0x300269B, 0x300269E, 0x30026A1, 0x30026A4, 0x30026A7, 0x30026AA, 0x30026AD, 0x30026B0, 0x30026B3, 0x30026B6, 0x30026B9, 0x30026BC, 0x300108B, 0x30026E3, 0x3000F50, 0x3000FB0,
+	0x300238B, 0x30022F2, 0x30022F5, 0x30022F8, 0x30022FB, 0x30022FE, 0x3002301, 0x3002304, 0x3002307, 0x300230A, 0x300230D, 0x3002310, 0x3002313, 0x3002316, 0x3002319, 0x300231C,
+	0x300231F, 0x3002322, 0x3002325, 0x3002328, 0x300232B, 0x300232E, 0x3002331, 0x3002334, 0x3002337, 0x300233A, 0x300233D, 0x3002340, 0x3002343, 0x3002346, 0x3002349, 0x0,
+	0x0, 0x0, 0x300234C, 0x300234F, 0x3002352, 0x3002355, 0x3002358, 0x300235B, 0x0, 0x0, 0x300235E, 0x3002361, 0x3002364, 0x3002367, 0x300236A, 0x300236D,
+	0x0, 0x0, 0x3002370, 0x3002373, 0x3002376, 0x3002379, 0x300237C, 0x300237F, 0x0, 0x0, 0x3002382, 0x3002385, 0x3002388, 0x0, 0x0, 0x0,
+	0x2003332, 0x2003334, 0x2003336, 0x3001D29, 0x2003338, 0x200333A, 0x300333C, 0x0, 0x300333F, 0x3000E6C, 0x3003342, 0x3000E71, 0x3003345, 0x3003348, 0x300334B, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 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, 0x8001693, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800169B, 0x80016A3,
+	0xC00334E, 0xC0016B7, 0xC0016C3, 0xC0016CF, 0xC0016DB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80016E7, 0x80016EF, 0xC0016F7, 0xC001703, 0xC00170F,
+	0xC00171B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x1002070, 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, 0x1001F04, 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, 0x1002070, 0x100016B,
+	0x100004B, 0x10001D1, 0x100004E, 0x1000636, 0x1000060, 0x10000CC, 0x1000063, 0x100069A, 0x10000F0, 0x1000108, 0x100006F, 0x1000129, 0x100012F, 0x1000135, 0x1000702, 0x100007B,
+	0x100007E, 0x1000754, 0x1002070, 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, 0x1001F04, 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, 0x1002070, 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, 0x1001F04, 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, 0x1002070, 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, 0x1002070, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x1000000, 0x1000633, 0x1000012, 0x10000C9,
+	0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x200335A, 0x200335C, 0x0, 0x0, 0x200032B, 0x200335E, 0x2001F0F, 0x2003360, 0x2000331, 0x2003362, 0x2000335, 0x2001D9D,
+	0x2000339, 0x2003364, 0x2003366, 0x2003368, 0x200336A, 0x200336C, 0x200033D, 0x2001F11, 0x2000E35, 0x2001D9D, 0x2001D9F, 0x200336E, 0x2000341, 0x2003370, 0x2003372, 0x2003374,
+	0x2000345, 0x3003376, 0x2000357, 0x2001D91, 0x2001E1A, 0x2001E1C, 0x200035B, 0x2003379, 0x200035F, 0x2001D93, 0x2000349, 0x2001D99, 0x200337B, 0x2001D31, 0x200337D, 0x200337F,
+	0x200036D, 0x2001D97, 0x2000E17, 0x2001D9B, 0x2003381, 0x2003383, 0x2000367, 0x2001D95, 0x2001E1E, 0x2003385, 0x2000375, 0x3003387, 0x200035B, 0x2001D93, 0x2001D99, 0x2001D95,
+	0x2000E17, 0x2001D97, 0x200032B, 0x200335E, 0x2001F0F, 0x2003360, 0x2000331, 0x2003362, 0x2000335, 0x2001D9D, 0x2000339, 0x2003364, 0x2003366, 0x2003368, 0x200336A, 0x200336C,
+	0x200033D, 0x2001F11, 0x2000E35, 0x2001D9D, 0x2001D9F, 0x200336E, 0x2000341, 0x2003370, 0x2003372, 0x2003374, 0x2000345, 0x3003376, 0x2000357, 0x2001D91, 0x2001E1A, 0x2001E1C,
+	0x2001E1E, 0x2003385, 0x2000375, 0x3003387, 0x200035B, 0x2001D93, 0x2001D99, 0x2001D95, 0x2000E17, 0x2001D97, 0x200338A, 0x200338C, 0x0, 0x0, 0x1001EDE, 0x1001D36,
+	0x1001D2C, 0x1001D2D, 0x1001D3B, 0x1001EDF, 0x1001EE0, 0x1001EE1, 0x1001EE2, 0x1001EE3, 0x1001EDE, 0x1001D36, 0x1001D2C, 0x1001D2D, 0x1001D3B, 0x1001EDF, 0x1001EE0, 0x1001EE1,
+	0x1001EE2, 0x1001EE3, 0x1001EDE, 0x1001D36, 0x1001D2C, 0x1001D2D, 0x1001D3B, 0x1001EDF, 0x1001EE0, 0x1001EE1, 0x1001EE2, 0x1001EE3, 0x1001EDE, 0x1001D36, 0x1001D2C, 0x1001D2D,
+	0x1001D3B, 0x1001EDF, 0x1001EE0, 0x1001EE1, 0x1001EE2, 0x1001EE3, 0x1001EDE, 0x1001D36, 0x1001D2C, 0x1001D2D, 0x1001D3B, 0x1001EDF, 0x1001EE0, 0x1001EE1, 0x1001EE2, 0x1001EE3,
+	0x2000451, 0x2002DB4, 0x2002DA0, 0x2003258, 0x0, 0x2000459, 0x2002F24, 0x2002DA6, 0x2002E34, 0x2000461, 0x2002E78, 0x2002E8A, 0x2002DAC, 0x2002EBC, 0x2002E0C, 0x2002E40,
+	0x2002E50, 0x2002E1C, 0x2002E68, 0x2002EF4, 0x2002F9C, 0x2002DCC, 0x2002DE4, 0x2002DBE, 0x2002EF0, 0x2002E24, 0x2002E3C, 0x2002E48, 0x200338E, 0x2002D5A, 0x2003390, 0x2003392,
+	0x0, 0x2002DB4, 0x2002DA0, 0x0, 0x2002ED4, 0x0, 0x0, 0x2002DA6, 0x0, 0x2000461, 0x2002E78, 0x2002E8A, 0x2002DAC, 0x2002EBC, 0x2002E0C, 0x2002E40,
+	0x2002E50, 0x2002E1C, 0x2002E68, 0x0, 0x2002F9C, 0x2002DCC, 0x2002DE4, 0x2002DBE, 0x0, 0x2002E24, 0x0, 0x2002E48, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x2002DA0, 0x0, 0x0, 0x0, 0x0, 0x2002DA6, 0x0, 0x2000461, 0x0, 0x2002E8A, 0x0, 0x2002EBC, 0x2002E0C, 0x2002E40,
+	0x0, 0x2002E1C, 0x2002E68, 0x0, 0x2002F9C, 0x0, 0x0, 0x2002DBE, 0x0, 0x2002E24, 0x0, 0x2002E48, 0x0, 0x2002D5A, 0x0, 0x2003392,
+	0x0, 0x2002DB4, 0x2002DA0, 0x0, 0x2002ED4, 0x0, 0x0, 0x2002DA6, 0x2002E34, 0x2000461, 0x2002E78, 0x0, 0x2002DAC, 0x2002EBC, 0x2002E0C, 0x2002E40,
+	0x2002E50, 0x2002E1C, 0x2002E68, 0x0, 0x2002F9C, 0x2002DCC, 0x2002DE4, 0x2002DBE, 0x0, 0x2002E24, 0x2002E3C, 0x2002E48, 0x200338E, 0x0, 0x2003390, 0x0,
+	0x2000451, 0x2002DB4, 0x2002DA0, 0x2003258, 0x2002ED4, 0x2000459, 0x2002F24, 0x2002DA6, 0x2002E34, 0x2000461, 0x0, 0x2002E8A, 0x2002DAC, 0x2002EBC, 0x2002E0C, 0x2002E40,
+	0x2002E50, 0x2002E1C, 0x2002E68, 0x2002EF4, 0x2002F9C, 0x2002DCC, 0x2002DE4, 0x2002DBE, 0x2002EF0, 0x2002E24, 0x2002E3C, 0x2002E48, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x2002DB4, 0x2002DA0, 0x2003258, 0x0, 0x2000459, 0x2002F24, 0x2002DA6, 0x2002E34, 0x2000461, 0x0, 0x2002E8A, 0x2002DAC, 0x2002EBC, 0x2002E0C, 0x2002E40,
+	0x2002E50, 0x2002E1C, 0x2002E68, 0x2002EF4, 0x2002F9C, 0x2002DCC, 0x2002DE4, 0x2002DBE, 0x2002EF0, 0x2002E24, 0x2002E3C, 0x2002E48, 0x0, 0x0, 0x0, 0x0,
+	0x200201F, 0x2003394, 0x2003396, 0x2003398, 0x200339A, 0x200339C, 0x200339E, 0x20033A0, 0x20033A2, 0x20033A4, 0x20033A6, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30033A8, 0x30033AB, 0x30033AE, 0x30033B1, 0x30033B4, 0x30033B7, 0x30033BA, 0x30033BD, 0x30033C0, 0x30033C3, 0x30033C6, 0x30033C9, 0x30033CC, 0x30033CF, 0x30033D2, 0x30033D5,
+	0x30033D8, 0x30033DB, 0x30033DE, 0x30033E1, 0x30033E4, 0x30033E7, 0x30033EA, 0x30033ED, 0x30033F0, 0x30033F3, 0x70033F6, 0x1000012, 0x1000168, 0x20033FD, 0x20033FF, 0x0,
+	0x1000000, 0x1000633, 0x1000012, 0x10000C9, 0x1000015, 0x1000697, 0x10000ED, 0x1000105, 0x1000021, 0x1000126, 0x100012C, 0x1000132, 0x10006FF, 0x100002D, 0x1000030, 0x1000751,
+	0x1001F04, 0x1000168, 0x100017A, 0x1000192, 0x100003F, 0x10007E1, 0x10001C2, 0x100080B, 0x100004B, 0x10001D1, 0x2003401, 0x2002BF7, 0x2003403, 0x2003405, 0x3003407, 0x200340A,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200340C, 0x200340E, 0x2003410, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2003412, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6003414, 0x600341A, 0x300100D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3002146, 0x3003420, 0x3003423, 0x600103D, 0x30020AD, 0x3001816, 0x3003426, 0x3002424, 0x3003429, 0x300342C, 0x300342F, 0x30012D7, 0x3003432, 0x3003435, 0x3001760, 0x3003438,
+	0x300343B, 0x300343E, 0x30021AF, 0x3003441, 0x3003444, 0x3003447, 0x300344A, 0x300344D, 0x3003450, 0x300209B, 0x300240C, 0x3003453, 0x3002619, 0x3002415, 0x300261C, 0x3003456,
+	0x3002242, 0x3003459, 0x300345C, 0x300345F, 0x3003462, 0x3003465, 0x3002562, 0x3002164, 0x3003468, 0x3001786, 0x300346B, 0x300346E, 0x0, 0x0, 0x0, 0x0,
+	0x9003471, 0x900347A, 0x9003483, 0x900348C, 0x9003495, 0x900349E, 0x90034A7, 0x90034B0, 0x90034B9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30034C2, 0x30034C5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x1001EDE, 0x1001D36, 0x1001D2C, 0x1001D2D, 0x1001D3B, 0x1001EDF, 0x1001EE0, 0x1001EE1, 0x1001EE2, 0x1001EE3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3001727, 0x300172A, 0x300172D, 0x4001730, 0x3001734, 0x3001403, 0x3001737, 0x300173A, 0x300173D, 0x3001740, 0x3001406, 0x3001743, 0x3001746, 0x4001749, 0x3001409, 0x300174D,
+	0x3001750, 0x3001753, 0x4001756, 0x300175A, 0x300175D, 0x3001760, 0x4001763, 0x3001767, 0x300176A, 0x300176D, 0x3001770, 0x30014B8, 0x4001773, 0x3001777, 0x300177A, 0x300177D,
+	0x3001780, 0x3001783, 0x3001786, 0x3001789, 0x300178C, 0x30014C7, 0x300140C, 0x300140F, 0x30014CA, 0x300178F, 0x3001792, 0x30011CC, 0x3001795, 0x3001412, 0x3001798, 0x300179B,
+	0x300179E, 0x30017A1, 0x30017A1, 0x30017A1, 0x40017A4, 0x30017A8, 0x30017AB, 0x30017AE, 0x40017B1, 0x30017B5, 0x30017B8, 0x30017BB, 0x30017BE, 0x30017C1, 0x30017C4, 0x30017C7,
+	0x30017CA, 0x30017CD, 0x30017D0, 0x30017D3, 0x30017D6, 0x30017D9, 0x30017D9, 0x30014D0, 0x30017DC, 0x30017DF, 0x30017E2, 0x30017E5, 0x3001418, 0x30017E8, 0x30017EB, 0x30017EE,
+	0x3001397, 0x30017F1, 0x30017F4, 0x30017F7, 0x30017FA, 0x30017FD, 0x3001800, 0x3001803, 0x3001806, 0x4001809, 0x300180D, 0x3001810, 0x3001813, 0x3001816, 0x3001819, 0x300181C,
+	0x400181F, 0x4001823, 0x3001827, 0x300182A, 0x300182D, 0x3001830, 0x3001833, 0x3001836, 0x3001839, 0x300183C, 0x300183F, 0x300183F, 0x4001842, 0x3001846, 0x3001849, 0x30011C0,
+	0x300184C, 0x400184F, 0x3001853, 0x3001856, 0x3001859, 0x300185C, 0x300185F, 0x3001862, 0x3001427, 0x3001865, 0x3001868, 0x400186B, 0x300186F, 0x4001872, 0x3001876, 0x3001879,
+	0x300187C, 0x300187F, 0x3001882, 0x3001885, 0x3001888, 0x300188B, 0x300188E, 0x3001891, 0x3001894, 0x4001897, 0x300189B, 0x300189E, 0x30018A1, 0x30018A4, 0x300111E, 0x40018A7,
+	0x30018AB, 0x40018AE, 0x40018AE, 0x30018B2, 0x30018B5, 0x30018B5, 0x30018B8, 0x40018BB, 0x40018BF, 0x30018C3, 0x30018C6, 0x30018C9, 0x30018CC, 0x30018CF, 0x30018D2, 0x30018D5,
+	0x30018D8, 0x30018DB, 0x30018DE, 0x300142A, 0x40018E1, 0x30018E5, 0x30018E8, 0x30018EB, 0x30014F4, 0x30018EB, 0x30018EE, 0x3001430, 0x30018F1, 0x30018F4, 0x30018F7, 0x30018FA,
+	0x3001433, 0x30010CD, 0x30018FD, 0x3001900, 0x3001903, 0x3001906, 0x3001909, 0x300190C, 0x400190F, 0x3001913, 0x3001916, 0x3001919, 0x300191C, 0x300191F, 0x4001922, 0x3001926,
+	0x3001929, 0x300192C, 0x300192F, 0x3001932, 0x3001935, 0x3001938, 0x300193B, 0x300193E, 0x3001436, 0x3001941, 0x4001944, 0x3001948, 0x300194B, 0x300194E, 0x3001951, 0x300143C,
+	0x3001954, 0x3001957, 0x300195A, 0x300195D, 0x3001960, 0x3001963, 0x3001966, 0x3001969, 0x3001121, 0x300150C, 0x300196C, 0x300196F, 0x3001972, 0x4001975, 0x3001979, 0x300197C,
+	0x300197F, 0x3001982, 0x300143F, 0x4001985, 0x3001989, 0x300198C, 0x300198F, 0x3001590, 0x3001992, 0x3001995, 0x3001998, 0x300199B, 0x400199E, 0x30019A2, 0x30019A5, 0x30019A8,
+	0x40019AB, 0x30019AF, 0x30019B2, 0x30019B5, 0x30019B8, 0x30011F3, 0x30019BB, 0x40019BE, 0x40019C2, 0x40019C6, 0x30019CA, 0x40019CD, 0x30019D1, 0x30019D4, 0x30019D7, 0x30019DA,
+	0x30019DD, 0x3001442, 0x30012F8, 0x30019E0, 0x30019E3, 0x30019E6, 0x40019E9, 0x30019ED, 0x30019F0, 0x30019F3, 0x30019F6, 0x3001518, 0x30019F9, 0x40019FC, 0x3001A00, 0x3001A03,
+	0x4001A06, 0x4001A0A, 0x3001A0E, 0x3001A11, 0x300151B, 0x3001A14, 0x3001A17, 0x3001A1A, 0x3001A1D, 0x3001A20, 0x3001A23, 0x4001A26, 0x3001A2A, 0x4001A2D, 0x3001A31, 0x4001A34,
+	0x3001A38, 0x3001521, 0x3001A3B, 0x4001A3E, 0x3001A42, 0x3001A45, 0x4001A48, 0x4001A4C, 0x3001A50, 0x3001A53, 0x3001A56, 0x3001A59, 0x3001A5C, 0x3001A5C, 0x3001A5F, 0x3001A62,
+	0x3001527, 0x3001A65, 0x3001A68, 0x3001A6B, 0x3001A6E, 0x4001A71, 0x3001A75, 0x4001A78, 0x30011C9, 0x4001A7C, 0x3001A80, 0x4001A83, 0x4001A87, 0x4001A8B, 0x3001A8F, 0x3001A92,
+	0x3001539, 0x4001A95, 0x4001A99, 0x4001A9D, 0x4001AA1, 0x3001AA5, 0x3001AA8, 0x3001AA8, 0x300153C, 0x3001596, 0x3001AAB, 0x3001AAE, 0x3001AB1, 0x4001AB4, 0x3001AB8, 0x3001157,
+	0x3001542, 0x3001ABB, 0x4001ABE, 0x3001463, 0x4001AC2, 0x4001AC6, 0x30013D9, 0x3001ACA, 0x3001ACD, 0x300146F, 0x3001AD0, 0x3001AD3, 0x4001AD6, 0x4001ADA, 0x4001ADA, 0x3001ADE,
+	0x3001AE1, 0x4001AE4, 0x3001AE8, 0x3001AEB, 0x3001AEE, 0x4001AF1, 0x3001AF5, 0x3001AF8, 0x3001AFB, 0x3001AFE, 0x3001B01, 0x4001B04, 0x3001B08, 0x3001B0B, 0x3001B0E, 0x3001B11,
+	0x3001B14, 0x3001B17, 0x4001B1A, 0x4001B1E, 0x3001B22, 0x4001B25, 0x3001B29, 0x4001B2C, 0x3001B30, 0x3001B33, 0x3001481, 0x4001B36, 0x4001B3A, 0x3001B3E, 0x4001B41, 0x3001B45,
+	0x4001B48, 0x3001B4C, 0x3001B4F, 0x3001B52, 0x3001B55, 0x3001B58, 0x3001B5B, 0x4001B5E, 0x4001B62, 0x4001B66, 0x4001B6A, 0x30018B2, 0x3001B6E, 0x3001B71, 0x3001B74, 0x3001B77,
+	0x3001B7A, 0x3001B7D, 0x3001B80, 0x3001B83, 0x3001B86, 0x3001B89, 0x3001B8C, 0x4001B8F, 0x30011FF, 0x3001B93, 0x3001B96, 0x3001B99, 0x3001B9C, 0x3001B9F, 0x3001BA2, 0x300148A,
+	0x3001BA5, 0x3001BA8, 0x3001BAB, 0x3001BAE, 0x4001BB1, 0x4001BB5, 0x4001BB9, 0x3001BBD, 0x3001BC0, 0x3001BC3, 0x3001BC6, 0x4001BC9, 0x3001BCD, 0x4001BD0, 0x3001BD4, 0x3001BD7,
+	0x4001BDA, 0x4001BDE, 0x3001BE2, 0x3001BE5, 0x3001148, 0x3001BE8, 0x3001BEB, 0x3001BEE, 0x3001BF1, 0x3001BF4, 0x3001BF7, 0x3001557, 0x3001BFA, 0x3001BFD, 0x3001C00, 0x3001C03,
+	0x3001C06, 0x3001C09, 0x3001C0C, 0x3001C0F, 0x3001C12, 0x4001C15, 0x3001C19, 0x3001C1C, 0x3001C1F, 0x3001C22, 0x3001C25, 0x4001C28, 0x4001C2C, 0x3001C30, 0x3001C33, 0x3001C36,
+	0x3001566, 0x3001569, 0x3001C39, 0x4001C3C, 0x3001C40, 0x3001C43, 0x3001C46, 0x3001C49, 0x4001C4C, 0x4001C50, 0x3001C54, 0x3001C57, 0x3001C5A, 0x4001C5D, 0x3001C61, 0x300156C,
+	0x4001C64, 0x4001C68, 0x3001C6C, 0x3001C6F, 0x3001C72, 0x4001C75, 0x3001C79, 0x3001C7C, 0x3001C7F, 0x3001C82, 0x3001C85, 0x3001C88, 0x3001C8B, 0x4001C8E, 0x3001C92, 0x3001C95,
+	0x3001C98, 0x4001C9B, 0x3001C9F, 0x3001CA2, 0x3001CA5, 0x3001CA8, 0x4001CAB, 0x4001CAF, 0x3001CB3, 0x3001CB6, 0x3001CB9, 0x4001CBC, 0x3001CC0, 0x4001CC3, 0x300157E, 0x300157E,
+	0x3001CC7, 0x4001CCA, 0x3001CCE, 0x3001CD1, 0x3001CD4, 0x3001CD7, 0x3001CDA, 0x3001CDD, 0x3001CE0, 0x4001CE3, 0x3001581, 0x3001CE7, 0x3001CEA, 0x3001CED, 0x3001CF0, 0x3001CF3,
+	0x4001CF6, 0x3001CFA, 0x4001CFD, 0x4001D01, 0x4001D05, 0x3001D09, 0x3001D0C, 0x3001D0F, 0x3001D12, 0x3001D15, 0x3001D18, 0x3001D1B, 0x3001D1E, 0x4001D21, 0x0, 0x0,
+};
+const uint32_t* NFKDDataPtr = NFKDData;
+
+const uint32_t UppercaseIndex1[272] = {
+	0, 128, 256, 384, 362, 362, 362, 362, 362, 362, 512, 362, 362, 362, 362, 640,
+	768, 896, 362, 362, 362, 362, 1024, 362, 362, 362, 362, 362, 362, 362, 1152, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+};
+const uint32_t* UppercaseIndex1Ptr = UppercaseIndex1;
+
+const uint32_t UppercaseIndex2[1280] = {
+	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, 0x460, 0x480, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4A0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x4C0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4E0, 0x500, 0x0, 0x0, 0x0,
+	0x520, 0x540, 0x560, 0x580, 0x5A0, 0x5C0, 0x5E0, 0x600, 0x620, 0x640, 0x660, 0x680, 0x6A0, 0x6C0, 0x6E0, 0x700,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x720, 0x740, 0x760, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x7C0, 0x7E0, 0x800, 0x820, 0x840, 0x860, 0x880, 0x8A0, 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x900, 0x920, 0x0, 0x0, 0x0, 0x0, 0x940, 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, 0xA20, 0xA40, 0xA60, 0xA80, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xAA0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xAC0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0xAE0, 0xB00, 0x0, 0x0, 0x0, 0xB20, 0xB40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB60, 0xB80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xBA0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0xBC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xBE0, 0xC00, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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[3104] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x1001F04, 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, 0x2003368, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2003405,
+	0x20034C8, 0x20034CA, 0x20034CC, 0x20034CE, 0x20034D0, 0x20034D2, 0x2000243, 0x20034D4, 0x20034D6, 0x20034D8, 0x20034DA, 0x20034DC, 0x20034DE, 0x20034E0, 0x20034E2, 0x20034E4,
+	0x20034E6, 0x20034E8, 0x20034EA, 0x20034EC, 0x20034EE, 0x20034F0, 0x20034F2, 0x0, 0x2000290, 0x20034F4, 0x20034F6, 0x20034F8, 0x20034FA, 0x20034FC, 0x20034FE, 0x2003500,
+	0x0, 0x2003502, 0x0, 0x2003504, 0x0, 0x2003506, 0x0, 0x2003508, 0x0, 0x200350A, 0x0, 0x200350C, 0x0, 0x200350E, 0x0, 0x2003510,
+	0x0, 0x2003512, 0x0, 0x2003514, 0x0, 0x2003516, 0x0, 0x2003518, 0x0, 0x200351A, 0x0, 0x200351C, 0x0, 0x200351E, 0x0, 0x2003520,
+	0x0, 0x2003522, 0x0, 0x2003524, 0x0, 0x2003526, 0x0, 0x2002CF1, 0x0, 0x2003528, 0x0, 0x200352A, 0x0, 0x200352C, 0x0, 0x200352E,
+	0x0, 0x1000021, 0x0, 0x2003530, 0x0, 0x2003532, 0x0, 0x2003534, 0x0, 0x0, 0x2003536, 0x0, 0x2003538, 0x0, 0x200353A, 0x0,
+	0x200353C, 0x0, 0x200353E, 0x0, 0x2003540, 0x0, 0x2003542, 0x0, 0x2003544, 0x3003546, 0x0, 0x2003549, 0x0, 0x200354B, 0x0, 0x200354D,
+	0x0, 0x200354F, 0x0, 0x2003551, 0x0, 0x2003553, 0x0, 0x2003555, 0x0, 0x2003557, 0x0, 0x2003559, 0x0, 0x200355B, 0x0, 0x200355D,
+	0x0, 0x200355F, 0x0, 0x2003561, 0x0, 0x2003563, 0x0, 0x2003565, 0x0, 0x2003567, 0x0, 0x2003569, 0x0, 0x200356B, 0x0, 0x200356D,
+	0x0, 0x200356F, 0x0, 0x2003571, 0x0, 0x2003573, 0x0, 0x2003575, 0x0, 0x0, 0x2003577, 0x0, 0x2003579, 0x0, 0x200357B, 0x100017A,
+	0x200357D, 0x0, 0x0, 0x200357F, 0x0, 0x2003581, 0x0, 0x0, 0x2003583, 0x0, 0x0, 0x0, 0x2003585, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x2003587, 0x0, 0x0, 0x2003589, 0x0, 0x0, 0x0, 0x200358B, 0x200358D, 0x0, 0x0, 0x0, 0x200358F, 0x0,
+	0x0, 0x2003591, 0x0, 0x2003593, 0x0, 0x2003595, 0x0, 0x0, 0x2003597, 0x0, 0x0, 0x0, 0x0, 0x2003599, 0x0, 0x0,
+	0x200359B, 0x0, 0x0, 0x0, 0x200359D, 0x0, 0x200359F, 0x0, 0x0, 0x20035A1, 0x0, 0x0, 0x0, 0x20035A3, 0x0, 0x20035A5,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x20035A7, 0x20035A7, 0x0, 0x20035A9, 0x20035A9, 0x0, 0x20035AB, 0x20035AB, 0x0, 0x20035AD, 0x0,
+	0x20035AF, 0x0, 0x20035B1, 0x0, 0x20035B3, 0x0, 0x20035B5, 0x0, 0x20035B7, 0x0, 0x20035B9, 0x0, 0x20035BB, 0x2001DF7, 0x0, 0x20035BD,
+	0x0, 0x20035BF, 0x0, 0x20035C1, 0x0, 0x20035C3, 0x0, 0x20035C5, 0x0, 0x20035C7, 0x0, 0x20035C9, 0x0, 0x20035CB, 0x0, 0x20035CD,
+	0x30035CF, 0x0, 0x20035D2, 0x20035D2, 0x0, 0x20035D4, 0x0, 0x0, 0x0, 0x20035D6, 0x0, 0x20035D8, 0x0, 0x20035DA, 0x0, 0x20035DC,
+	0x0, 0x20035DE, 0x0, 0x20035E0, 0x0, 0x20035E2, 0x0, 0x20035E4, 0x0, 0x20035E6, 0x0, 0x20035E8, 0x0, 0x20035EA, 0x0, 0x20035EC,
+	0x0, 0x20035EE, 0x0, 0x20035F0, 0x0, 0x20035F2, 0x0, 0x20035F4, 0x0, 0x20035F6, 0x0, 0x20035F8, 0x0, 0x20035FA, 0x0, 0x20035FC,
+	0x0, 0x0, 0x0, 0x2001DF9, 0x0, 0x20035FE, 0x0, 0x2003600, 0x0, 0x2003602, 0x0, 0x2003604, 0x0, 0x2003606, 0x0, 0x2003608,
+	0x0, 0x200360A, 0x0, 0x200360C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200360E, 0x0, 0x0, 0x3003610,
+	0x3003613, 0x0, 0x2003616, 0x0, 0x0, 0x0, 0x0, 0x2003618, 0x0, 0x200361A, 0x0, 0x200361C, 0x0, 0x200361E, 0x0, 0x2003620,
+	0x3003622, 0x3003625, 0x3003628, 0x200362B, 0x200362D, 0x0, 0x200362F, 0x2003631, 0x0, 0x2003633, 0x0, 0x2001EFB, 0x3003635, 0x0, 0x0, 0x0,
+	0x2003638, 0x300363A, 0x0, 0x200363D, 0x0, 0x300363F, 0x3003642, 0x0, 0x2003645, 0x2003647, 0x3003649, 0x300364C, 0x300364F, 0x0, 0x0, 0x2003652,
+	0x0, 0x3003654, 0x2003657, 0x0, 0x0, 0x2003659, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300365B, 0x0, 0x0,
+	0x200365E, 0x0, 0x3003660, 0x2003663, 0x0, 0x0, 0x0, 0x3003665, 0x2003668, 0x200366A, 0x200366C, 0x200366E, 0x2003670, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x2000267, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003672, 0x3003675, 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, 0x2003678, 0x0, 0x200367A, 0x0, 0x0, 0x0, 0x200367C, 0x0, 0x0, 0x0, 0x200367E, 0x2003680, 0x2003682, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6003684, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200368A, 0x200368C, 0x200368E, 0x2003690,
+	0x6003692, 0x200032B, 0x200335E, 0x2001F0F, 0x2003360, 0x2000331, 0x2003362, 0x2000335, 0x2001D9D, 0x2000339, 0x2003364, 0x2003366, 0x2003368, 0x200336A, 0x200336C, 0x200033D,
+	0x2001F11, 0x2000E35, 0x2001D9F, 0x2001D9F, 0x200336E, 0x2000341, 0x2003370, 0x2003372, 0x2003374, 0x2000345, 0x2003698, 0x200369A, 0x200369C, 0x200369E, 0x20036A0, 0x0,
+	0x200335E, 0x2001D9D, 0x0, 0x0, 0x0, 0x2003370, 0x2001F11, 0x20036A2, 0x0, 0x20036A4, 0x0, 0x20036A6, 0x0, 0x200338A, 0x0, 0x20036A8,
+	0x0, 0x20036AA, 0x0, 0x20036AC, 0x0, 0x20036AE, 0x0, 0x20036B0, 0x0, 0x20036B2, 0x0, 0x20036B4, 0x0, 0x20036B6, 0x0, 0x20036B8,
+	0x2003364, 0x2000E35, 0x20036BA, 0x20036BC, 0x0, 0x2000331, 0x0, 0x0, 0x20036BE, 0x0, 0x0, 0x20036C0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x20003D1, 0x20036C2, 0x20036C4, 0x2000389, 0x20036C6, 0x2000381, 0x20003C9, 0x20003F9, 0x2000395, 0x20036C8, 0x2000391, 0x20036CA, 0x20036CC, 0x20036CE, 0x2000411, 0x20036D0,
+	0x20036D2, 0x20036D4, 0x20036D6, 0x2000399, 0x20036D8, 0x20036DA, 0x20036DC, 0x2000441, 0x20036DE, 0x20036E0, 0x20036E2, 0x2000449, 0x20036E4, 0x2000421, 0x20036E6, 0x20036E8,
+	0x20036EA, 0x20036EC, 0x20036EE, 0x20036F0, 0x20036F2, 0x20036F4, 0x200038D, 0x20036F6, 0x20036F8, 0x20036FA, 0x20036FC, 0x20036FE, 0x2003700, 0x2003702, 0x2003704, 0x2003706,
+	0x0, 0x2003708, 0x0, 0x200370A, 0x0, 0x200370C, 0x0, 0x200370E, 0x0, 0x2003710, 0x0, 0x2003712, 0x0, 0x2003714, 0x0, 0x2003716,
+	0x0, 0x2003718, 0x0, 0x200371A, 0x0, 0x20003C1, 0x0, 0x200371C, 0x0, 0x200371E, 0x0, 0x2003720, 0x0, 0x2003722, 0x0, 0x2003724,
+	0x0, 0x2003726, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x2003740, 0x0, 0x2003742, 0x0, 0x2003744, 0x0, 0x2003746, 0x0, 0x2003748, 0x0, 0x200374A, 0x0, 0x200374C,
+	0x0, 0x200374E, 0x0, 0x2003750, 0x0, 0x2003752, 0x0, 0x2003754, 0x0, 0x2003756, 0x0, 0x2003758, 0x0, 0x200375A, 0x0, 0x200375C,
+	0x0, 0x0, 0x200375E, 0x0, 0x2003760, 0x0, 0x2003762, 0x0, 0x2003764, 0x0, 0x2003766, 0x0, 0x2003768, 0x0, 0x200376A, 0x200376C,
+	0x0, 0x200376E, 0x0, 0x2003770, 0x0, 0x2003772, 0x0, 0x2003774, 0x0, 0x20003E9, 0x0, 0x2003776, 0x0, 0x2003778, 0x0, 0x200377A,
+	0x0, 0x200377C, 0x0, 0x200377E, 0x0, 0x2003780, 0x0, 0x2003782, 0x0, 0x2000419, 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, 0x20037AC, 0x0, 0x20037AE, 0x0, 0x20037B0, 0x0, 0x20037B2, 0x0, 0x20037B4, 0x0, 0x20037B6, 0x0, 0x20037B8,
+	0x0, 0x20037BA, 0x0, 0x20037BC, 0x0, 0x20037BE, 0x0, 0x20037C0, 0x0, 0x20037C2, 0x0, 0x20037C4, 0x0, 0x20037C6, 0x0, 0x20037C8,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x20037CA, 0x20037CC, 0x20037CE, 0x20037D0, 0x20037D2, 0x20037D4, 0x20037D6, 0x20037D8, 0x20037DA, 0x20037DC, 0x20037DE, 0x20037E0, 0x20037E2, 0x20037E4, 0x20037E6,
+	0x20037E8, 0x20037EA, 0x20037EC, 0x20037EE, 0x20037F0, 0x20037F2, 0x20037F4, 0x20037F6, 0x20037F8, 0x20037FA, 0x20037FC, 0x20037FE, 0x2003800, 0x2003802, 0x2003804, 0x2003806,
+	0x2003808, 0x200380A, 0x200380C, 0x200380E, 0x2003810, 0x2003812, 0x2003814, 0x4003816, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x300381A, 0x300381D, 0x3003820, 0x3003823, 0x3003826, 0x3003829, 0x300382C, 0x300382F, 0x3003832, 0x3003835, 0x3003838, 0x300383B, 0x300383E, 0x3003841, 0x3003844, 0x3003847,
+	0x300384A, 0x300384D, 0x3003850, 0x3003853, 0x3003856, 0x3003859, 0x300385C, 0x300385F, 0x3003862, 0x3003865, 0x3003868, 0x300386B, 0x300386E, 0x3003871, 0x3003874, 0x3003877,
+	0x300387A, 0x300387D, 0x3003880, 0x3003883, 0x3003886, 0x3003889, 0x300388C, 0x300388F, 0x3003892, 0x3003895, 0x3003898, 0x0, 0x0, 0x300389B, 0x300389E, 0x30038A1,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30038A4, 0x30038A7, 0x30038AA, 0x30038AD, 0x30038B0, 0x30038B3, 0x0, 0x0,
+	0x20036C4, 0x20036C6, 0x2000411, 0x20036D4, 0x20036D6, 0x20036D6, 0x20036E2, 0x200370A, 0x30038B6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30038B9, 0x0, 0x0, 0x0, 0x30038BC, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30038BF, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x30038C2, 0x0, 0x30038C5, 0x0, 0x30038C8, 0x0, 0x30038CB, 0x0, 0x30038CE, 0x0, 0x30038D1, 0x0, 0x30038D4, 0x0, 0x30038D7,
+	0x0, 0x30038DA, 0x0, 0x30038DD, 0x0, 0x30038E0, 0x0, 0x30038E3, 0x0, 0x30038E6, 0x0, 0x30038E9, 0x0, 0x30038EC, 0x0, 0x30038EF,
+	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,
+	0x0, 0x3003982, 0x0, 0x3003985, 0x0, 0x3003988, 0x0, 0x300398B, 0x0, 0x300398E, 0x0, 0x3003991, 0x0, 0x3003994, 0x0, 0x3003997,
+	0x0, 0x300399A, 0x0, 0x300399D, 0x0, 0x30039A0, 0x30039A3, 0x30039A6, 0x30039A9, 0x30039AC, 0x30039AF, 0x3003952, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x30039B2, 0x0, 0x30039B5, 0x0, 0x30039B8, 0x0, 0x30039BB, 0x0, 0x30039BE, 0x0, 0x30039C1, 0x0, 0x30039C4, 0x0, 0x30039C7,
+	0x0, 0x30039CA, 0x0, 0x30039CD, 0x0, 0x30039D0, 0x0, 0x30039D3, 0x0, 0x30039D6, 0x0, 0x30039D9, 0x0, 0x30039DC, 0x0, 0x30039DF,
+	0x0, 0x30039E2, 0x0, 0x30039E5, 0x0, 0x30039E8, 0x0, 0x30039EB, 0x0, 0x30039EE, 0x0, 0x30039F1, 0x0, 0x30039F4, 0x0, 0x30039F7,
+	0x0, 0x30039FA, 0x0, 0x30039FD, 0x0, 0x3003A00, 0x0, 0x3003A03, 0x0, 0x3003A06, 0x0, 0x3003A09, 0x0, 0x3003A0C, 0x0, 0x3003A0F,
+	0x0, 0x3003A12, 0x0, 0x3003A15, 0x0, 0x3003A18, 0x0, 0x3003A1B, 0x0, 0x3003A1E, 0x0, 0x3003A21, 0x0, 0x3003A24, 0x0, 0x3003A27,
+	0x0, 0x3003A2A, 0x0, 0x3003A2D, 0x0, 0x3003A30, 0x0, 0x3003A33, 0x0, 0x3003A36, 0x0, 0x3003A39, 0x0, 0x3003A3C, 0x0, 0x3003A3F,
+	0x3003A42, 0x3003A45, 0x3003A48, 0x3003A4B, 0x3003A4E, 0x3003A51, 0x3003A54, 0x3003A57, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003A5A, 0x3003A5D, 0x3003A60, 0x3003A63, 0x3003A66, 0x3003A69, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003A6C, 0x3003A6F, 0x3003A72, 0x3003A75, 0x3003A78, 0x3003A7B, 0x3003A7E, 0x3003A81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003A84, 0x3003A87, 0x3003A8A, 0x3003A8D, 0x3003A90, 0x3003A93, 0x3003A96, 0x3003A99, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003A9C, 0x3003A9F, 0x3003AA2, 0x3003AA5, 0x3003AA8, 0x3003AAB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4003AAE, 0x3003AB2, 0x6003AB5, 0x3003ABB, 0x6003ABE, 0x3003AC4, 0x6003AC7, 0x3003ACD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003AD0, 0x3003AD3, 0x3003AD6, 0x3003AD9, 0x3003ADC, 0x3003ADF, 0x3003AE2, 0x3003AE5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003AE8, 0x3003AEB, 0x3003AEE, 0x3003AF1, 0x3003AF4, 0x3003AF7, 0x3003AFA, 0x3003AFD, 0x3003B00, 0x3003B03, 0x3003B06, 0x3003B09, 0x3003B0C, 0x3003B0F, 0x0, 0x0,
+	0x5003B12, 0x5003B17, 0x5003B1C, 0x5003B21, 0x5003B26, 0x5003B2B, 0x5003B30, 0x5003B35, 0x5003B12, 0x5003B17, 0x5003B1C, 0x5003B21, 0x5003B26, 0x5003B2B, 0x5003B30, 0x5003B35,
+	0x5003B3A, 0x5003B3F, 0x5003B44, 0x5003B49, 0x5003B4E, 0x5003B53, 0x5003B58, 0x5003B5D, 0x5003B3A, 0x5003B3F, 0x5003B44, 0x5003B49, 0x5003B4E, 0x5003B53, 0x5003B58, 0x5003B5D,
+	0x5003B62, 0x5003B67, 0x5003B6C, 0x5003B71, 0x5003B76, 0x5003B7B, 0x5003B80, 0x5003B85, 0x5003B62, 0x5003B67, 0x5003B6C, 0x5003B71, 0x5003B76, 0x5003B7B, 0x5003B80, 0x5003B85,
+	0x3003B8A, 0x3003B8D, 0x5003B90, 0x4003B95, 0x4003B99, 0x0, 0x4003B9D, 0x6003BA1, 0x0, 0x0, 0x0, 0x0, 0x4003B95, 0x0, 0x2000339, 0x0,
+	0x0, 0x0, 0x5003BA7, 0x4003BAC, 0x4003BB0, 0x0, 0x4003BB4, 0x6003BB8, 0x0, 0x0, 0x0, 0x0, 0x4003BAC, 0x0, 0x0, 0x0,
+	0x3003BBE, 0x3003BC1, 0x6003BC4, 0x6003684, 0x0, 0x0, 0x4003BCA, 0x6003BCE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003BD4, 0x3003BD7, 0x6003BDA, 0x6003692, 0x4003BE0, 0x3003BE4, 0x4003BE7, 0x6003BEB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x5003BF1, 0x4003BF6, 0x4003BFA, 0x0, 0x4003BFE, 0x6003C02, 0x0, 0x0, 0x0, 0x0, 0x4003BF6, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003C08, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003C0B, 0x3003C0E, 0x3003C11, 0x3003C14, 0x3003C17, 0x3003C1A, 0x3003C1D, 0x3003C20, 0x3003C23, 0x3003C26, 0x3003C29, 0x3003C2C, 0x3003C2F, 0x3003C32, 0x3003C35, 0x3003C38,
+	0x0, 0x0, 0x0, 0x0, 0x3003C3B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003C3E, 0x3003C41, 0x3003C44, 0x3003C47, 0x3003C4A, 0x3003C4D, 0x3003C50, 0x3003C53, 0x3003C56, 0x3003C59, 0x3003C5C, 0x3003C5F, 0x3003C62, 0x3003C65, 0x3003C68, 0x3003C6B,
+	0x3003C6E, 0x3003C71, 0x3003C74, 0x3003C77, 0x3003C7A, 0x3003C7D, 0x3003C80, 0x3003C83, 0x3003C86, 0x3003C89, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003C8C, 0x3003C8F, 0x3003C92, 0x3003C95, 0x3003C98, 0x3003C9B, 0x3003C9E, 0x3003CA1, 0x3003CA4, 0x3003CA7, 0x3003CAA, 0x3003CAD, 0x3003CB0, 0x3003CB3, 0x3003CB6, 0x3003CB9,
+	0x3003CBC, 0x3003CBF, 0x3003CC2, 0x3003CC5, 0x3003CC8, 0x3003CCB, 0x3003CCE, 0x3003CD1, 0x3003CD4, 0x3003CD7, 0x3003CDA, 0x3003CDD, 0x3003CE0, 0x3003CE3, 0x3003CE6, 0x3003CE9,
+	0x3003CEC, 0x3003CEF, 0x3003CF2, 0x3003CF5, 0x3003CF8, 0x3003CFB, 0x3003CFE, 0x3003D01, 0x3003D04, 0x3003D07, 0x3003D0A, 0x3003D0D, 0x3003D10, 0x3003D13, 0x3003D16, 0x0,
+	0x0, 0x3003D19, 0x0, 0x0, 0x0, 0x2003D1C, 0x2003D1E, 0x0, 0x3003D20, 0x0, 0x3003D23, 0x0, 0x3003D26, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3003D29, 0x0, 0x0, 0x3003D2C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003D2F, 0x0, 0x3003D32, 0x0, 0x3003D35, 0x0, 0x3003D38, 0x0, 0x3003D3B, 0x0, 0x3003D3E, 0x0, 0x3003D41, 0x0, 0x3003D44,
+	0x0, 0x3003D47, 0x0, 0x3003D4A, 0x0, 0x3003D4D, 0x0, 0x3003D50, 0x0, 0x3003D53, 0x0, 0x3003D56, 0x0, 0x3003D59, 0x0, 0x3003D5C,
+	0x0, 0x3003D5F, 0x0, 0x3003D62, 0x0, 0x3003D65, 0x0, 0x3003D68, 0x0, 0x3003D6B, 0x0, 0x3003D6E, 0x0, 0x3003D71, 0x0, 0x3003D74,
+	0x0, 0x3003D77, 0x0, 0x3003D7A, 0x0, 0x3003D7D, 0x0, 0x3003D80, 0x0, 0x3003D83, 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003DC5, 0x0, 0x3003DC8, 0x0,
+	0x0, 0x0, 0x0, 0x3003DCB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003DCE, 0x3003DD1, 0x3003DD4, 0x3003DD7, 0x3003DDA, 0x3003DDD, 0x3003DE0, 0x3003DE3, 0x3003DE6, 0x3003DE9, 0x3003DEC, 0x3003DEF, 0x3003DF2, 0x3003DF5, 0x3003DF8, 0x3003DFB,
+	0x3003DFE, 0x3003E01, 0x3003E04, 0x3003E07, 0x3003E0A, 0x3003E0D, 0x3003E10, 0x3003E13, 0x3003E16, 0x3003E19, 0x3003E1C, 0x3003E1F, 0x3003E22, 0x3003E25, 0x3003E28, 0x3003E2B,
+	0x3003E2E, 0x3003E31, 0x3003E34, 0x3003E37, 0x3003E3A, 0x3003E3D, 0x0, 0x3003E40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003E43, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003E46, 0x0, 0x3003E49, 0x0, 0x3003E4C, 0x0, 0x3003E4F, 0x0, 0x3003E52, 0x0, 0x30038B6, 0x0, 0x3003E55, 0x0, 0x3003E58,
+	0x0, 0x3003E5B, 0x0, 0x3003E5E, 0x0, 0x3003E61, 0x0, 0x3003E64, 0x0, 0x3003E67, 0x0, 0x3003E6A, 0x0, 0x3003E6D, 0x0, 0x3003E70,
+	0x0, 0x3003E73, 0x0, 0x3003E76, 0x0, 0x3003E79, 0x0, 0x3003E7C, 0x0, 0x3003E7F, 0x0, 0x3003E82, 0x0, 0x3003E85, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003E88, 0x0, 0x3003E8B, 0x0, 0x3003E8E, 0x0, 0x3003E91, 0x0, 0x3003E94, 0x0, 0x3003E97, 0x0, 0x3003E9A, 0x0, 0x3003E9D,
+	0x0, 0x3003EA0, 0x0, 0x3003EA3, 0x0, 0x3003EA6, 0x0, 0x3003EA9, 0x0, 0x3003EAC, 0x0, 0x3003EAF, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3003EB2, 0x0, 0x3003EB5, 0x0, 0x3003EB8, 0x0, 0x3003EBB, 0x0, 0x3003EBE, 0x0, 0x3003EC1, 0x0, 0x3003EC4,
+	0x0, 0x0, 0x0, 0x3003EC7, 0x0, 0x3003ECA, 0x0, 0x3003ECD, 0x0, 0x3003ED0, 0x0, 0x3003ED3, 0x0, 0x3003ED6, 0x0, 0x3003ED9,
+	0x0, 0x3003EDC, 0x0, 0x3003EDF, 0x0, 0x3003EE2, 0x0, 0x3003EE5, 0x0, 0x3003EE8, 0x0, 0x3003EEB, 0x0, 0x3003EEE, 0x0, 0x3003EF1,
+	0x0, 0x3003EF4, 0x0, 0x3003EF7, 0x0, 0x3003EFA, 0x0, 0x3003EFD, 0x0, 0x3003F00, 0x0, 0x3003F03, 0x0, 0x3003F06, 0x0, 0x3003F09,
+	0x0, 0x3003F0C, 0x0, 0x3003F0F, 0x0, 0x3003F12, 0x0, 0x3003F15, 0x0, 0x3003F18, 0x0, 0x3003F1B, 0x0, 0x3003F1E, 0x0, 0x3003F21,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003F24, 0x0, 0x3003F27, 0x0, 0x0, 0x3003F2A,
+	0x0, 0x3003F2D, 0x0, 0x3003F30, 0x0, 0x3003F33, 0x0, 0x3003F36, 0x0, 0x0, 0x0, 0x0, 0x3003F39, 0x0, 0x0, 0x0,
+	0x0, 0x3003F3C, 0x0, 0x3003F3F, 0x3003F42, 0x0, 0x0, 0x3003F45, 0x0, 0x3003F48, 0x0, 0x3003F4B, 0x0, 0x3003F4E, 0x0, 0x3003F51,
+	0x0, 0x3003F54, 0x0, 0x3003F57, 0x0, 0x3003F5A, 0x0, 0x3003F5D, 0x0, 0x3003F60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x3003F63, 0x0, 0x3003F66, 0x0, 0x3003F69, 0x0, 0x3003F6C, 0x0, 0x3003F6F, 0x0, 0x3003F72,
+	0x0, 0x0, 0x0, 0x3003F75, 0x0, 0x0, 0x0, 0x0, 0x3003F78, 0x0, 0x3003F7B, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003F7E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3003F81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003F84, 0x3003F87, 0x3003F8A, 0x3003F8D, 0x3003F90, 0x3003F93, 0x3003F96, 0x3003F99, 0x3003F9C, 0x3003F9F, 0x3003FA2, 0x3003FA5, 0x3003FA8, 0x3003FAB, 0x3003FAE, 0x3003FB1,
+	0x3003FB4, 0x3003FB7, 0x3003FBA, 0x3003FBD, 0x3003FC0, 0x3003FC3, 0x3003FC6, 0x3003FC9, 0x3003FCC, 0x3003FCF, 0x3003FD2, 0x3003FD5, 0x3003FD8, 0x3003FDB, 0x3003FDE, 0x3003FE1,
+	0x3003FE4, 0x3003FE7, 0x3003FEA, 0x3003FED, 0x3003FF0, 0x3003FF3, 0x3003FF6, 0x3003FF9, 0x3003FFC, 0x3003FFF, 0x3004002, 0x3004005, 0x3004008, 0x300400B, 0x300400E, 0x3004011,
+	0x3004014, 0x3004017, 0x300401A, 0x300401D, 0x3004020, 0x3004023, 0x3004026, 0x3004029, 0x300402C, 0x300402F, 0x3004032, 0x3004035, 0x3004038, 0x300403B, 0x300403E, 0x3004041,
+	0x3004044, 0x3004047, 0x300404A, 0x300404D, 0x3004050, 0x3004053, 0x3004056, 0x3004059, 0x300405C, 0x300405F, 0x3004062, 0x3004065, 0x3004068, 0x300406B, 0x300406E, 0x3004071,
+	0x2004074, 0x2004076, 0x2004078, 0x300407A, 0x300407D, 0x2004080, 0x2004080, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x4004082, 0x4004086, 0x400408A, 0x400408E, 0x4004092, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3004096, 0x3004099, 0x300409C, 0x300409F, 0x30040A2, 0x30040A5, 0x30040A8, 0x30040AB, 0x30040AE, 0x30040B1, 0x30040B4, 0x30040B7, 0x30040BA, 0x30040BD, 0x30040C0,
+	0x30040C3, 0x30040C6, 0x30040C9, 0x30040CC, 0x30040CF, 0x30040D2, 0x30040D5, 0x30040D8, 0x30040DB, 0x30040DE, 0x30040E1, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40040E4, 0x40040E8, 0x40040EC, 0x40040F0, 0x40040F4, 0x40040F8, 0x40040FC, 0x4004100,
+	0x4004104, 0x4004108, 0x400410C, 0x4004110, 0x4004114, 0x4004118, 0x400411C, 0x4004120, 0x4004124, 0x4004128, 0x400412C, 0x4004130, 0x4004134, 0x4004138, 0x400413C, 0x4004140,
+	0x4004144, 0x4004148, 0x400414C, 0x4004150, 0x4004154, 0x4004158, 0x400415C, 0x4004160, 0x4004164, 0x4004168, 0x400416C, 0x4004170, 0x4004174, 0x4004178, 0x400417C, 0x4004180,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4004184, 0x4004188, 0x400418C, 0x4004190, 0x4004194, 0x4004198, 0x400419C, 0x40041A0,
+	0x40041A4, 0x40041A8, 0x40041AC, 0x40041B0, 0x40041B4, 0x40041B8, 0x40041BC, 0x40041C0, 0x40041C4, 0x40041C8, 0x40041CC, 0x40041D0, 0x40041D4, 0x40041D8, 0x40041DC, 0x40041E0,
+	0x40041E4, 0x40041E8, 0x40041EC, 0x40041F0, 0x40041F4, 0x40041F8, 0x40041FC, 0x4004200, 0x4004204, 0x4004208, 0x400420C, 0x4004210, 0x0, 0x0, 0x0, 0x0,
+	0x4004214, 0x4004218, 0x400421C, 0x4004220, 0x4004224, 0x4004228, 0x400422C, 0x4004230, 0x4004234, 0x4004238, 0x400423C, 0x4004240, 0x4004244, 0x4004248, 0x400424C, 0x4004250,
+	0x4004254, 0x4004258, 0x400425C, 0x4004260, 0x4004264, 0x4004268, 0x400426C, 0x4004270, 0x4004274, 0x4004278, 0x400427C, 0x4004280, 0x4004284, 0x4004288, 0x400428C, 0x4004290,
+	0x4004294, 0x4004298, 0x400429C, 0x40042A0, 0x40042A4, 0x40042A8, 0x40042AC, 0x40042B0, 0x40042B4, 0x40042B8, 0x40042BC, 0x40042C0, 0x40042C4, 0x40042C8, 0x40042CC, 0x40042D0,
+	0x40042D4, 0x40042D8, 0x40042DC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x40042E0, 0x40042E4, 0x40042E8, 0x40042EC, 0x40042F0, 0x40042F4, 0x40042F8, 0x40042FC, 0x4004300, 0x4004304, 0x4004308, 0x400430C, 0x4004310, 0x4004314, 0x4004318, 0x400431C,
+	0x4004320, 0x4004324, 0x4004328, 0x400432C, 0x4004330, 0x4004334, 0x4004338, 0x400433C, 0x4004340, 0x4004344, 0x4004348, 0x400434C, 0x4004350, 0x4004354, 0x4004358, 0x400435C,
+	0x4004360, 0x4004364, 0x4004368, 0x400436C, 0x4004370, 0x4004374, 0x4004378, 0x400437C, 0x4004380, 0x4004384, 0x4004388, 0x400438C, 0x4004390, 0x4004394, 0x4004398, 0x400439C,
+	0x40043A0, 0x40043A4, 0x40043A8, 0x40043AC, 0x40043B0, 0x40043B4, 0x40043B8, 0x40043BC, 0x40043C0, 0x40043C4, 0x40043C8, 0x40043CC, 0x40043D0, 0x40043D4, 0x40043D8, 0x40043DC,
+	0x0, 0x0, 0x40043E0, 0x40043E4, 0x40043E8, 0x40043EC, 0x40043F0, 0x40043F4, 0x40043F8, 0x40043FC, 0x4004400, 0x4004404, 0x4004408, 0x400440C, 0x4004410, 0x4004414,
+	0x4004418, 0x400441C, 0x4004420, 0x4004424, 0x4004428, 0x400442C, 0x4004430, 0x4004434, 0x4004438, 0x400443C, 0x4004440, 0x4004444, 0x4004448, 0x400444C, 0x4004450, 0x4004454,
+	0x4004458, 0x400445C, 0x4004460, 0x4004464, 0x0, 0x0, 0x0, 0x0, 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* 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, 1024, 360, 360, 360, 360, 360, 360, 360, 1152, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 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[1280] = {
+	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, 0x3E0, 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, 0x440, 0x460, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x680, 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, 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, 0x0, 0x760, 0x780, 0x7A0, 0x7C0, 0x7E0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x800, 0x820, 0x840, 0x0, 0x0, 0x0, 0x0, 0x860, 0x880, 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 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,
+	0x960, 0x980, 0x0, 0x0, 0x0, 0x9A0, 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,
+	0x0, 0x0, 0x0, 0x0, 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, 0xA20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0xA40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xA60, 0xA80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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[2720] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x1002070, 0x100016B, 0x100017D, 0x1000195, 0x100008D, 0x10007E4, 0x10001C5, 0x100080E, 0x1000099, 0x10001D4, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2004468, 0x200446A, 0x200446C, 0x200446E, 0x2004470, 0x2004472, 0x2000247, 0x2004474, 0x2004476, 0x2004478, 0x200447A, 0x200447C, 0x200447E, 0x2004480, 0x2004482, 0x2004484,
+	0x2001E26, 0x2004486, 0x2004488, 0x200448A, 0x200448C, 0x200448E, 0x2004490, 0x0, 0x2000294, 0x2004492, 0x2004494, 0x2004496, 0x2004498, 0x200449A, 0x200449C, 0x0,
+	0x200449E, 0x0, 0x20044A0, 0x0, 0x20044A2, 0x0, 0x20044A4, 0x0, 0x20044A6, 0x0, 0x20044A8, 0x0, 0x20044AA, 0x0, 0x20044AC, 0x0,
+	0x20044AE, 0x0, 0x20044B0, 0x0, 0x20044B2, 0x0, 0x20044B4, 0x0, 0x20044B6, 0x0, 0x20044B8, 0x0, 0x20044BA, 0x0, 0x20044BC, 0x0,
+	0x20044BE, 0x0, 0x20044C0, 0x0, 0x20044C2, 0x0, 0x2001F00, 0x0, 0x20044C4, 0x0, 0x20044C6, 0x0, 0x20044C8, 0x0, 0x20044CA, 0x0,
+	0x30044CC, 0x0, 0x20044CF, 0x0, 0x20044D1, 0x0, 0x20044D3, 0x0, 0x0, 0x20044D5, 0x0, 0x20044D7, 0x0, 0x20044D9, 0x0, 0x20044DB,
+	0x0, 0x20044DD, 0x0, 0x20044DF, 0x0, 0x20044E1, 0x0, 0x20044E3, 0x0, 0x0, 0x2001E08, 0x0, 0x20044E5, 0x0, 0x20044E7, 0x0,
+	0x20044E9, 0x0, 0x2002CF3, 0x0, 0x20044EB, 0x0, 0x20044ED, 0x0, 0x20044EF, 0x0, 0x20044F1, 0x0, 0x20044F3, 0x0, 0x20044F5, 0x0,
+	0x20044F7, 0x0, 0x20044F9, 0x0, 0x20044FB, 0x0, 0x20044FD, 0x0, 0x20044FF, 0x0, 0x2004501, 0x0, 0x2004503, 0x0, 0x2004505, 0x0,
+	0x2004507, 0x0, 0x2004509, 0x0, 0x200450B, 0x0, 0x200450D, 0x0, 0x200450F, 0x2004511, 0x0, 0x2004513, 0x0, 0x2004515, 0x0, 0x0,
+	0x0, 0x2004517, 0x2004519, 0x0, 0x200451B, 0x0, 0x2001E0A, 0x200451D, 0x0, 0x200451F, 0x2004521, 0x2004523, 0x0, 0x0, 0x2004525, 0x2001E02,
+	0x2001E04, 0x2004527, 0x0, 0x2004529, 0x2001D85, 0x0, 0x2001E30, 0x2001E2E, 0x200452B, 0x0, 0x0, 0x0, 0x2001E15, 0x2001E44, 0x0, 0x2001E4A,
+	0x200452D, 0x0, 0x200452F, 0x0, 0x2004531, 0x0, 0x2004533, 0x2004535, 0x0, 0x2001E50, 0x0, 0x0, 0x2004537, 0x0, 0x2004539, 0x200453B,
+	0x0, 0x2001E56, 0x2001E5B, 0x200453D, 0x0, 0x200453F, 0x0, 0x200026B, 0x2004541, 0x0, 0x0, 0x0, 0x2004543, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x2004545, 0x2004545, 0x0, 0x2004547, 0x2004547, 0x0, 0x2004549, 0x2004549, 0x0, 0x200454B, 0x0, 0x200454D,
+	0x0, 0x200454F, 0x0, 0x2004551, 0x0, 0x2004553, 0x0, 0x2004555, 0x0, 0x2004557, 0x0, 0x2004559, 0x0, 0x0, 0x200455B, 0x0,
+	0x200455D, 0x0, 0x200455F, 0x0, 0x2004561, 0x0, 0x2004563, 0x0, 0x2004565, 0x0, 0x2004567, 0x0, 0x2004569, 0x0, 0x200456B, 0x0,
+	0x0, 0x200456D, 0x200456D, 0x0, 0x200456F, 0x0, 0x2004571, 0x2004573, 0x2004575, 0x0, 0x2004577, 0x0, 0x2004579, 0x0, 0x200457B, 0x0,
+	0x200457D, 0x0, 0x200457F, 0x0, 0x2004581, 0x0, 0x2004583, 0x0, 0x2004585, 0x0, 0x2004587, 0x0, 0x2004589, 0x0, 0x200458B, 0x0,
+	0x200458D, 0x0, 0x200458F, 0x0, 0x2004591, 0x0, 0x2004593, 0x0, 0x2004595, 0x0, 0x2004597, 0x0, 0x2004599, 0x0, 0x200459B, 0x0,
+	0x200459D, 0x0, 0x200459F, 0x0, 0x20045A1, 0x0, 0x20045A3, 0x0, 0x20045A5, 0x0, 0x20045A7, 0x0, 0x20045A9, 0x0, 0x20045AB, 0x0,
+	0x20045AD, 0x0, 0x20045AF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045B1, 0x20045B4, 0x0, 0x20045B6, 0x30045B8, 0x0,
+	0x0, 0x20045BB, 0x0, 0x20045BD, 0x2001E54, 0x2001E5D, 0x20045BF, 0x0, 0x20045C1, 0x0, 0x20045C3, 0x0, 0x20045C5, 0x0, 0x20045C7, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x20045C9, 0x0, 0x20045CB, 0x0, 0x0, 0x0, 0x20045CD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20045CF,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20045D1, 0x0, 0x20045D3, 0x20045D5, 0x20045D7, 0x0, 0x20045D9, 0x0, 0x20045DB, 0x20045DD,
+	0x0, 0x2000357, 0x2001D91, 0x2001E1A, 0x2001E1C, 0x200035B, 0x2003379, 0x200035F, 0x2001D93, 0x2000349, 0x2001D99, 0x200337B, 0x2001D31, 0x200337D, 0x200337F, 0x200036D,
+	0x2001D97, 0x2000E17, 0x0, 0x2003381, 0x2003383, 0x2000367, 0x2001D95, 0x2001E1E, 0x2003385, 0x2000375, 0x20045DF, 0x20045E1, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20045E3,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20045E5, 0x0, 0x20045E7, 0x0, 0x200338C, 0x0, 0x20045E9, 0x0,
+	0x20045EB, 0x0, 0x20045ED, 0x0, 0x20045EF, 0x0, 0x20045F1, 0x0, 0x20045F3, 0x0, 0x20045F5, 0x0, 0x20045F7, 0x0, 0x20045F9, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x2001D93, 0x0, 0x0, 0x20045FB, 0x0, 0x20045FD, 0x20045FF, 0x0, 0x0, 0x2004601, 0x2004603, 0x2004605,
+	0x2004607, 0x2004609, 0x200460B, 0x200460D, 0x200460F, 0x2004611, 0x20003B1, 0x2004613, 0x2004615, 0x2004617, 0x2004619, 0x200461B, 0x200461D, 0x200461F, 0x2004621, 0x2004623,
+	0x20003D5, 0x2004625, 0x2004627, 0x20003AD, 0x2004629, 0x20003A5, 0x20003CD, 0x20003FD, 0x20003A1, 0x200462B, 0x20003B5, 0x200462D, 0x200462F, 0x2001E20, 0x2000415, 0x2004631,
+	0x2004633, 0x2004635, 0x2004637, 0x20003BD, 0x2004639, 0x200463B, 0x200463D, 0x2000445, 0x200463F, 0x2004641, 0x2002CEA, 0x200044D, 0x2002CEC, 0x2000425, 0x2004643, 0x2004645,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2004647, 0x0, 0x2004649, 0x0, 0x200464B, 0x0, 0x200464D, 0x0, 0x200464F, 0x0, 0x2004651, 0x0, 0x2004653, 0x0, 0x2004655, 0x0,
+	0x2004657, 0x0, 0x2004659, 0x0, 0x20003C5, 0x0, 0x200465B, 0x0, 0x200465D, 0x0, 0x200465F, 0x0, 0x2004661, 0x0, 0x2004663, 0x0,
+	0x2004665, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004667, 0x0, 0x2004669, 0x0, 0x200466B, 0x0,
+	0x200466D, 0x0, 0x200466F, 0x0, 0x2004671, 0x0, 0x2004673, 0x0, 0x2004675, 0x0, 0x2004677, 0x0, 0x2004679, 0x0, 0x200467B, 0x0,
+	0x200467D, 0x0, 0x200467F, 0x0, 0x2004681, 0x0, 0x2004683, 0x0, 0x2004685, 0x0, 0x2004687, 0x0, 0x2004689, 0x0, 0x200468B, 0x0,
+	0x200468D, 0x0, 0x200468F, 0x0, 0x2004691, 0x0, 0x2004693, 0x0, 0x2004695, 0x0, 0x2004697, 0x0, 0x2004699, 0x0, 0x200469B, 0x0,
+	0x200469D, 0x200469F, 0x0, 0x20046A1, 0x0, 0x20046A3, 0x0, 0x20046A5, 0x0, 0x20046A7, 0x0, 0x20046A9, 0x0, 0x20046AB, 0x0, 0x0,
+	0x20046AD, 0x0, 0x20046AF, 0x0, 0x20046B1, 0x0, 0x20046B3, 0x0, 0x20003ED, 0x0, 0x20046B5, 0x0, 0x20046B7, 0x0, 0x20046B9, 0x0,
+	0x20046BB, 0x0, 0x20046BD, 0x0, 0x20046BF, 0x0, 0x20046C1, 0x0, 0x200041D, 0x0, 0x20046C3, 0x0, 0x20046C5, 0x0, 0x20046C7, 0x0,
+	0x20046C9, 0x0, 0x20046CB, 0x0, 0x20046CD, 0x0, 0x20046CF, 0x0, 0x20046D1, 0x0, 0x20046D3, 0x0, 0x20046D5, 0x0, 0x20046D7, 0x0,
+	0x20046D9, 0x0, 0x20046DB, 0x0, 0x20046DD, 0x0, 0x20046DF, 0x0, 0x20046E1, 0x0, 0x20046E3, 0x0, 0x20046E5, 0x0, 0x20046E7, 0x0,
+	0x20046E9, 0x0, 0x20046EB, 0x0, 0x20046ED, 0x0, 0x20046EF, 0x0, 0x20046F1, 0x0, 0x20046F3, 0x0, 0x20046F5, 0x0, 0x20046F7, 0x0,
+	0x20046F9, 0x0, 0x20046FB, 0x0, 0x20046FD, 0x0, 0x20046FF, 0x0, 0x2004701, 0x0, 0x2004703, 0x0, 0x2004705, 0x0, 0x2004707, 0x0,
+	0x0, 0x2004709, 0x200470B, 0x200470D, 0x200470F, 0x2001DA1, 0x2004711, 0x2004713, 0x2004715, 0x2004717, 0x2004719, 0x2002D1A, 0x200471B, 0x2002D22, 0x200471D, 0x200471F,
+	0x2004721, 0x2004723, 0x2004725, 0x2004727, 0x2002D10, 0x2004729, 0x2002D12, 0x200472B, 0x200472D, 0x200472F, 0x2004731, 0x2004733, 0x2004735, 0x2004737, 0x2002D1C, 0x2004739,
+	0x200473B, 0x200473D, 0x2001DA3, 0x200473F, 0x2004741, 0x2004743, 0x2004745, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004747, 0x300474A, 0x300474D, 0x3004750, 0x3004753, 0x3004756, 0x3004759, 0x300475C, 0x300475F, 0x3004762, 0x3004765, 0x3004768, 0x300476B, 0x300476E, 0x3004771, 0x3004774,
+	0x3004777, 0x300477A, 0x300477D, 0x3004780, 0x3004783, 0x3004786, 0x3004789, 0x300478C, 0x300478F, 0x3004792, 0x3004795, 0x3004798, 0x300479B, 0x300479E, 0x30047A1, 0x30047A4,
+	0x30047A7, 0x30047AA, 0x30047AD, 0x30047B0, 0x30047B3, 0x30047B6, 0x0, 0x30047B9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30047BC, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30047BF, 0x30047C2, 0x30047C5, 0x30047C8, 0x30047CB, 0x30047CE, 0x30047D1, 0x30047D4, 0x30047D7, 0x30047DA, 0x30047DD, 0x30047E0, 0x30047E3, 0x30047E6, 0x30047E9, 0x30047EC,
+	0x30047EF, 0x30047F2, 0x30047F5, 0x30047F8, 0x30047FB, 0x30047FE, 0x3004801, 0x3004804, 0x3004807, 0x300480A, 0x300480D, 0x3004810, 0x3004813, 0x3004816, 0x3004819, 0x300481C,
+	0x300481F, 0x3004822, 0x3004825, 0x3004828, 0x300482B, 0x300482E, 0x3004831, 0x3004834, 0x3004837, 0x300483A, 0x300483D, 0x3004840, 0x3004843, 0x3004846, 0x3004849, 0x300484C,
+	0x300484F, 0x3004852, 0x3004855, 0x3004858, 0x300485B, 0x300485E, 0x3004861, 0x3004864, 0x3004867, 0x300486A, 0x300486D, 0x3004870, 0x3004873, 0x3004876, 0x3004879, 0x300487C,
+	0x300487F, 0x3004882, 0x3004885, 0x3004888, 0x300488B, 0x300488E, 0x3004891, 0x3004894, 0x3004897, 0x300489A, 0x300489D, 0x30048A0, 0x30048A3, 0x30048A6, 0x30048A9, 0x30048AC,
+	0x30048AF, 0x30048B2, 0x30048B5, 0x30048B8, 0x30048BB, 0x30048BE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30048C1, 0x30048C4, 0x30048C7, 0x30048CA, 0x30048CD, 0x30048D0, 0x30048D3, 0x30048D6, 0x30048D9, 0x30048DC, 0x30048DF, 0x30048E2, 0x3001DF4, 0x30048E5, 0x30048E8, 0x30048EB,
+	0x30048EE, 0x30048F1, 0x30048F4, 0x30048F7, 0x30048FA, 0x30048FD, 0x3004900, 0x3004903, 0x3004906, 0x3004909, 0x300490C, 0x300490F, 0x3004912, 0x3004915, 0x3004918, 0x300491B,
+	0x300491E, 0x3004921, 0x3004924, 0x3004927, 0x300492A, 0x300492D, 0x3004930, 0x3004933, 0x3004936, 0x3004939, 0x300493C, 0x0, 0x0, 0x300493F, 0x3004942, 0x3004945,
+	0x3004948, 0x0, 0x300494B, 0x0, 0x300494E, 0x0, 0x3004951, 0x0, 0x3004954, 0x0, 0x3004957, 0x0, 0x300495A, 0x0, 0x300495D, 0x0,
+	0x3004960, 0x0, 0x3004963, 0x0, 0x3004966, 0x0, 0x3004969, 0x0, 0x300496C, 0x0, 0x300496F, 0x0, 0x3004972, 0x0, 0x3004975, 0x0,
+	0x3004978, 0x0, 0x300497B, 0x0, 0x300497E, 0x0, 0x3004981, 0x0, 0x3004984, 0x0, 0x3004987, 0x0, 0x300498A, 0x0, 0x300498D, 0x0,
+	0x3004990, 0x0, 0x3004993, 0x0, 0x3004996, 0x0, 0x3004999, 0x0, 0x300499C, 0x0, 0x300499F, 0x0, 0x30049A2, 0x0, 0x30049A5, 0x0,
+	0x30049A8, 0x0, 0x30049AB, 0x0, 0x30049AE, 0x0, 0x30049B1, 0x0, 0x30049B4, 0x0, 0x30049B7, 0x0, 0x30049BA, 0x0, 0x30049BD, 0x0,
+	0x30049C0, 0x0, 0x30049C3, 0x0, 0x30049C6, 0x0, 0x30049C9, 0x0, 0x30049CC, 0x0, 0x30049CF, 0x0, 0x30049D2, 0x0, 0x30049D5, 0x0,
+	0x30049D8, 0x0, 0x30049DB, 0x0, 0x30049DE, 0x0, 0x30049E1, 0x0, 0x30049E4, 0x0, 0x30049E7, 0x0, 0x30049EA, 0x0, 0x30049ED, 0x0,
+	0x30049F0, 0x0, 0x30049F3, 0x0, 0x30049F6, 0x0, 0x30049F9, 0x0, 0x30049FC, 0x0, 0x30049FF, 0x0, 0x3004A02, 0x0, 0x3004A05, 0x0,
+	0x3004A08, 0x0, 0x3004A0B, 0x0, 0x3004A0E, 0x0, 0x3004A11, 0x0, 0x3004A14, 0x0, 0x3004A17, 0x0, 0x3004A1A, 0x0, 0x3004A1D, 0x0,
+	0x3004A20, 0x0, 0x3004A23, 0x0, 0x3004A26, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004A29, 0x0,
+	0x3004A2B, 0x0, 0x3004A2E, 0x0, 0x3004A31, 0x0, 0x3004A34, 0x0, 0x3004A37, 0x0, 0x3004A3A, 0x0, 0x3004A3D, 0x0, 0x3004A40, 0x0,
+	0x3004A43, 0x0, 0x3004A46, 0x0, 0x3004A49, 0x0, 0x3004A4C, 0x0, 0x3004A4F, 0x0, 0x3004A52, 0x0, 0x3004A55, 0x0, 0x3004A58, 0x0,
+	0x3004A5B, 0x0, 0x3004A5E, 0x0, 0x3004A61, 0x0, 0x3004A64, 0x0, 0x3004A67, 0x0, 0x3004A6A, 0x0, 0x3004A6D, 0x0, 0x3004A70, 0x0,
+	0x3004A73, 0x0, 0x3004A76, 0x0, 0x3004A79, 0x0, 0x3004A7C, 0x0, 0x3004A7F, 0x0, 0x3004A82, 0x0, 0x3004A85, 0x0, 0x3004A88, 0x0,
+	0x3004A8B, 0x0, 0x3004A8E, 0x0, 0x3004A91, 0x0, 0x3004A94, 0x0, 0x3004A97, 0x0, 0x3004A9A, 0x0, 0x3004A9D, 0x0, 0x3004AA0, 0x0,
+	0x3004AA3, 0x0, 0x3004AA6, 0x0, 0x3004AA9, 0x0, 0x3004AAC, 0x0, 0x3004AAF, 0x0, 0x3004AB2, 0x0, 0x3004AB5, 0x0, 0x3004AB8, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004ABB, 0x3004ABE, 0x3004AC1, 0x3004AC4, 0x3004AC7, 0x3004ACA, 0x3004ACD, 0x3004AD0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004AD3, 0x3004AD6, 0x3004AD9, 0x3004ADC, 0x3004ADF, 0x3004AE2, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004AE5, 0x3004AE8, 0x3004AEB, 0x3004AEE, 0x3004AF1, 0x3004AF4, 0x3004AF7, 0x3004AFA,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004AFD, 0x3004B00, 0x3004B03, 0x3004B06, 0x3004B09, 0x3004B0C, 0x3004B0F, 0x3004B12,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004B15, 0x3004B18, 0x3004B1B, 0x3004B1E, 0x3004B21, 0x3004B24, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004B27, 0x0, 0x3004B2A, 0x0, 0x3004B2D, 0x0, 0x3004B30,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004B33, 0x3004B36, 0x3004B39, 0x3004B3C, 0x3004B3F, 0x3004B42, 0x3004B45, 0x3004B48,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004B4B, 0x3004B4E, 0x3004B51, 0x3004B54, 0x3004B57, 0x3004B5A, 0x3004B5D, 0x3004B60,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004B63, 0x3004B66, 0x3004B69, 0x3004B6C, 0x3004B6F, 0x3004B72, 0x3004B75, 0x3004B78,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004B7B, 0x3004B7E, 0x3004B81, 0x3004B84, 0x3004B87, 0x3004B8A, 0x3004B8D, 0x3004B90,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004B93, 0x3004B96, 0x3004B99, 0x3004B9C, 0x3004B9F, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004BA2, 0x3004BA5, 0x3004BA8, 0x3004BAB, 0x3004BAE, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004BB1, 0x3004BB4, 0x3004BB7, 0x3004BBA, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004BBD, 0x3004BC0, 0x3004BC3, 0x3004BC6, 0x3004BC9, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004BCC, 0x3004BCF, 0x3004BD2, 0x3004BD5, 0x3004BD8, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000375, 0x0, 0x0, 0x0, 0x100012F, 0x2004472, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x3004BDB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004BDE, 0x3004BE1, 0x3004BE4, 0x3004BE7, 0x3004BEA, 0x3004BED, 0x3004BF0, 0x3004BF3, 0x3004BF6, 0x3004BF9, 0x3004BFC, 0x3004BFF, 0x3004C02, 0x3004C05, 0x3004C08, 0x3004C0B,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3004C0E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004C11, 0x3004C14, 0x3004C17, 0x3004C1A, 0x3004C1D, 0x3004C20, 0x3004C23, 0x3004C26, 0x3004C29, 0x3004C2C,
+	0x3004C2F, 0x3004C32, 0x3004C35, 0x3004C38, 0x3004C3B, 0x3004C3E, 0x3004C41, 0x3004C44, 0x3004C47, 0x3004C4A, 0x3004C4D, 0x3004C50, 0x3004C53, 0x3004C56, 0x3004C59, 0x3004C5C,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004C5F, 0x3004C62, 0x3004C65, 0x3004C68, 0x3004C6B, 0x3004C6E, 0x3004C71, 0x3004C74, 0x3004C77, 0x3004C7A, 0x3004C7D, 0x3004C80, 0x3004C83, 0x3004C86, 0x3004C89, 0x3004C8C,
+	0x3004C8F, 0x3004C92, 0x3004C95, 0x3004C98, 0x3004C9B, 0x3004C9E, 0x3004CA1, 0x3004CA4, 0x3004CA7, 0x3004CAA, 0x3004CAD, 0x3004CB0, 0x3004CB3, 0x3004CB6, 0x3004CB9, 0x3004CBC,
+	0x3004CBF, 0x3004CC2, 0x3004CC5, 0x3004CC8, 0x3004CCB, 0x3004CCE, 0x3004CD1, 0x3004CD4, 0x3004CD7, 0x3004CDA, 0x3004CDD, 0x3004CE0, 0x3004CE3, 0x3004CE6, 0x3004CE9, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004CEC, 0x0, 0x2002CFB, 0x3004CEF, 0x2004CF2, 0x0, 0x0, 0x3004CF4, 0x0, 0x3004CF7, 0x0, 0x3004CFA, 0x0, 0x2001DFD, 0x2001E40, 0x2001DFB,
+	0x2001E22, 0x0, 0x3004CFD, 0x0, 0x0, 0x3004D00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004D03, 0x2004D05,
+	0x3004D07, 0x0, 0x3004D0A, 0x0, 0x3004D0D, 0x0, 0x3004D10, 0x0, 0x3004D13, 0x0, 0x3004D16, 0x0, 0x3004D19, 0x0, 0x3004D1C, 0x0,
+	0x3004D1F, 0x0, 0x3004D22, 0x0, 0x3004D25, 0x0, 0x3004D28, 0x0, 0x3004D2B, 0x0, 0x3004D2E, 0x0, 0x3004D31, 0x0, 0x3004D34, 0x0,
+	0x3004D37, 0x0, 0x3004D3A, 0x0, 0x3004D3D, 0x0, 0x3004D40, 0x0, 0x3004D43, 0x0, 0x3004D46, 0x0, 0x3004D49, 0x0, 0x3004D4C, 0x0,
+	0x3004D4F, 0x0, 0x3004D52, 0x0, 0x3004D55, 0x0, 0x3004D58, 0x0, 0x3004D5B, 0x0, 0x3004D5E, 0x0, 0x3004D61, 0x0, 0x3004D64, 0x0,
+	0x3004D67, 0x0, 0x3004D6A, 0x0, 0x3004D6D, 0x0, 0x3004D70, 0x0, 0x3004D73, 0x0, 0x3004D76, 0x0, 0x3004D79, 0x0, 0x3004D7C, 0x0,
+	0x3004D7F, 0x0, 0x3004D82, 0x0, 0x3004D85, 0x0, 0x3004D88, 0x0, 0x3004D8B, 0x0, 0x3004D8E, 0x0, 0x3004D91, 0x0, 0x3004D94, 0x0,
+	0x3004D97, 0x0, 0x3004D9A, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004D9D, 0x0, 0x3004DA0, 0x0, 0x0,
+	0x0, 0x0, 0x3004DA3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004DA6, 0x0, 0x3004DA9, 0x0, 0x3004DAC, 0x0, 0x3004DAF, 0x0, 0x3004DB2, 0x0, 0x3004DB5, 0x0, 0x3004DB8, 0x0, 0x3004DBB, 0x0,
+	0x3004DBE, 0x0, 0x3004DC1, 0x0, 0x3004DC4, 0x0, 0x3004DC7, 0x0, 0x3004DCA, 0x0, 0x3004DCD, 0x0, 0x3004DD0, 0x0, 0x3004DD3, 0x0,
+	0x3004DD6, 0x0, 0x3004DD9, 0x0, 0x3004DDC, 0x0, 0x3004DDF, 0x0, 0x3004DE2, 0x0, 0x3004DE5, 0x0, 0x3004DE8, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004DEB, 0x0, 0x3004DEE, 0x0, 0x3004DF1, 0x0, 0x3004DF4, 0x0, 0x3004DF7, 0x0, 0x3004DFA, 0x0, 0x3004DFD, 0x0, 0x3004E00, 0x0,
+	0x3004E03, 0x0, 0x3004E06, 0x0, 0x3004E09, 0x0, 0x3004E0C, 0x0, 0x3004E0F, 0x0, 0x3004E12, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x3004E15, 0x0, 0x3004E18, 0x0, 0x3002CF5, 0x0, 0x3004E1B, 0x0, 0x3004E1E, 0x0, 0x3004E21, 0x0, 0x3004E24, 0x0,
+	0x0, 0x0, 0x3004E27, 0x0, 0x3004E2A, 0x0, 0x3004E2D, 0x0, 0x3004E30, 0x0, 0x3004E33, 0x0, 0x3004E36, 0x0, 0x3004E39, 0x0,
+	0x3004E3C, 0x0, 0x3004E3F, 0x0, 0x3004E42, 0x0, 0x3004E45, 0x0, 0x3004E48, 0x0, 0x3004E4B, 0x0, 0x3004E4E, 0x0, 0x3004E51, 0x0,
+	0x3004E54, 0x0, 0x3004E57, 0x0, 0x3004E5A, 0x0, 0x3004E5D, 0x0, 0x3004E60, 0x0, 0x3004E63, 0x0, 0x3004E66, 0x0, 0x3004E69, 0x0,
+	0x3004E6C, 0x0, 0x3004E6F, 0x0, 0x3004E72, 0x0, 0x3004E75, 0x0, 0x3004E78, 0x0, 0x3004E7B, 0x0, 0x3004E7E, 0x0, 0x3002CEE, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004E81, 0x0, 0x3004E84, 0x0, 0x3004E87, 0x3004E8A, 0x0,
+	0x3004E8D, 0x0, 0x3004E90, 0x0, 0x3004E93, 0x0, 0x3004E96, 0x0, 0x0, 0x0, 0x0, 0x3004E99, 0x0, 0x2001E2C, 0x0, 0x0,
+	0x3004E9C, 0x0, 0x3004E9F, 0x0, 0x0, 0x0, 0x3004EA2, 0x0, 0x3004EA5, 0x0, 0x3004EA8, 0x0, 0x3004EAB, 0x0, 0x3004EAE, 0x0,
+	0x3004EB1, 0x0, 0x3004EB4, 0x0, 0x3004EB7, 0x0, 0x3004EBA, 0x0, 0x3004EBD, 0x0, 0x2001D6B, 0x2001E06, 0x2001E2A, 0x2004EC0, 0x2001E32, 0x0,
+	0x2004EC2, 0x2004EC4, 0x2001E37, 0x3004EC6, 0x3004EC9, 0x0, 0x3004ECC, 0x0, 0x3004ECF, 0x0, 0x3004ED2, 0x0, 0x3004ED5, 0x0, 0x3004ED8, 0x0,
+	0x0, 0x0, 0x3004EDB, 0x0, 0x3004EDE, 0x2001E4E, 0x3004EE1, 0x3004EE4, 0x0, 0x3004EE7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x3004EEA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3004EED, 0x3004EF0, 0x3004EF3, 0x3004EF6, 0x3004EF9, 0x3004EFC, 0x3004EFF, 0x3004F02, 0x3004F05, 0x3004F08, 0x3004F0B, 0x3004F0E, 0x3004F11, 0x3004F14, 0x3004F17,
+	0x3004F1A, 0x3004F1D, 0x3004F20, 0x3004F23, 0x3004F26, 0x3004F29, 0x3004F2C, 0x3004F2F, 0x3004F32, 0x3004F35, 0x3004F38, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4004F3B, 0x4004F3F, 0x4004F43, 0x4004F47, 0x4004F4B, 0x4004F4F, 0x4004F53, 0x4004F57, 0x4004F5B, 0x4004F5F, 0x4004F63, 0x4004F67, 0x4004F6B, 0x4004F6F, 0x4004F73, 0x4004F77,
+	0x4004F7B, 0x4004F7F, 0x4004F83, 0x4004F87, 0x4004F8B, 0x4004F8F, 0x4004F93, 0x4004F97, 0x4004F9B, 0x4004F9F, 0x4004FA3, 0x4004FA7, 0x4004FAB, 0x4004FAF, 0x4004FB3, 0x4004FB7,
+	0x4004FBB, 0x4004FBF, 0x4004FC3, 0x4004FC7, 0x4004FCB, 0x4004FCF, 0x4004FD3, 0x4004FD7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4004FDB, 0x4004FDF, 0x4004FE3, 0x4004FE7, 0x4004FEB, 0x4004FEF, 0x4004FF3, 0x4004FF7, 0x4004FFB, 0x4004FFF, 0x4005003, 0x4005007, 0x400500B, 0x400500F, 0x4005013, 0x4005017,
+	0x400501B, 0x400501F, 0x4005023, 0x4005027, 0x400502B, 0x400502F, 0x4005033, 0x4005037, 0x400503B, 0x400503F, 0x4005043, 0x4005047, 0x400504B, 0x400504F, 0x4005053, 0x4005057,
+	0x400505B, 0x400505F, 0x4005063, 0x4005067, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x400506B, 0x400506F, 0x4005073, 0x4005077, 0x400507B, 0x400507F, 0x4005083, 0x4005087, 0x400508B, 0x400508F, 0x4005093, 0x4005097, 0x400509B, 0x400509F, 0x40050A3, 0x40050A7,
+	0x40050AB, 0x40050AF, 0x40050B3, 0x40050B7, 0x40050BB, 0x40050BF, 0x40050C3, 0x40050C7, 0x40050CB, 0x40050CF, 0x40050D3, 0x40050D7, 0x40050DB, 0x40050DF, 0x40050E3, 0x40050E7,
+	0x40050EB, 0x40050EF, 0x40050F3, 0x40050F7, 0x40050FB, 0x40050FF, 0x4005103, 0x4005107, 0x400510B, 0x400510F, 0x4005113, 0x4005117, 0x400511B, 0x400511F, 0x4005123, 0x4005127,
+	0x400512B, 0x400512F, 0x4005133, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4005137, 0x400513B, 0x400513F, 0x4005143, 0x4005147, 0x400514B, 0x400514F, 0x4005153, 0x4005157, 0x400515B, 0x400515F, 0x4005163, 0x4005167, 0x400516B, 0x400516F, 0x4005173,
+	0x4005177, 0x400517B, 0x400517F, 0x4005183, 0x4005187, 0x400518B, 0x400518F, 0x4005193, 0x4005197, 0x400519B, 0x400519F, 0x40051A3, 0x40051A7, 0x40051AB, 0x40051AF, 0x40051B3,
+	0x40051B7, 0x40051BB, 0x40051BF, 0x40051C3, 0x40051C7, 0x40051CB, 0x40051CF, 0x40051D3, 0x40051D7, 0x40051DB, 0x40051DF, 0x40051E3, 0x40051E7, 0x40051EB, 0x40051EF, 0x40051F3,
+	0x40051F7, 0x40051FB, 0x40051FF, 0x4005203, 0x4005207, 0x400520B, 0x400520F, 0x4005213, 0x4005217, 0x400521B, 0x400521F, 0x4005223, 0x4005227, 0x400522B, 0x400522F, 0x4005233,
+	0x4005237, 0x400523B, 0x400523F, 0x4005243, 0x4005247, 0x400524B, 0x400524F, 0x4005253, 0x4005257, 0x400525B, 0x400525F, 0x4005263, 0x4005267, 0x400526B, 0x400526F, 0x4005273,
+	0x4005277, 0x400527B, 0x400527F, 0x4005283, 0x4005287, 0x400528B, 0x400528F, 0x4005293, 0x4005297, 0x400529B, 0x400529F, 0x40052A3, 0x40052A7, 0x40052AB, 0x40052AF, 0x40052B3,
+	0x40052B7, 0x40052BB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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* LowercaseDataPtr = LowercaseData;
+
+const uint32_t TitlecaseIndex1[272] = {
+	0, 128, 256, 384, 362, 362, 362, 362, 362, 362, 512, 362, 362, 362, 362, 640,
+	768, 896, 362, 362, 362, 362, 1024, 362, 362, 362, 362, 362, 362, 362, 1152, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+	362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+};
+const uint32_t* TitlecaseIndex1Ptr = TitlecaseIndex1;
+
+const uint32_t TitlecaseIndex2[1280] = {
+	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, 0x460,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x480, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4A0, 0x4C0, 0x0, 0x0, 0x0,
+	0x4E0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5A0, 0x5C0, 0x5E0, 0x600, 0x620, 0x640, 0x660, 0x680, 0x6A0, 0x6C0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6E0, 0x700, 0x720, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x740, 0x760, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x780, 0x7A0, 0x7C0, 0x7E0, 0x800, 0x820, 0x840, 0x860, 0x880, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x8A0, 0x8C0, 0x8E0, 0x0, 0x0, 0x0, 0x0, 0x900, 0x920, 0x940, 0x960, 0x980, 0x9A0, 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, 0x9E0, 0xA00, 0xA20, 0xA40, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xA60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xA80, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0xAA0, 0xAC0, 0x0, 0x0, 0x0, 0xAE0, 0xB00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB20, 0xB40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0xB80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xBA0, 0xBC0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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[3040] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x1001F04, 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, 0x2003368, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20052BF,
+	0x20034C8, 0x20034CA, 0x20034CC, 0x20034CE, 0x20034D0, 0x20034D2, 0x2000243, 0x20034D4, 0x20034D6, 0x20034D8, 0x20034DA, 0x20034DC, 0x20034DE, 0x20034E0, 0x20034E2, 0x20034E4,
+	0x20034E6, 0x20034E8, 0x20034EA, 0x20034EC, 0x20034EE, 0x20034F0, 0x20034F2, 0x0, 0x2000290, 0x20034F4, 0x20034F6, 0x20034F8, 0x20034FA, 0x20034FC, 0x20034FE, 0x2003500,
+	0x0, 0x2003502, 0x0, 0x2003504, 0x0, 0x2003506, 0x0, 0x2003508, 0x0, 0x200350A, 0x0, 0x200350C, 0x0, 0x200350E, 0x0, 0x2003510,
+	0x0, 0x2003512, 0x0, 0x2003514, 0x0, 0x2003516, 0x0, 0x2003518, 0x0, 0x200351A, 0x0, 0x200351C, 0x0, 0x200351E, 0x0, 0x2003520,
+	0x0, 0x2003522, 0x0, 0x2003524, 0x0, 0x2003526, 0x0, 0x2002CF1, 0x0, 0x2003528, 0x0, 0x200352A, 0x0, 0x200352C, 0x0, 0x200352E,
+	0x0, 0x1000021, 0x0, 0x2003530, 0x0, 0x2003532, 0x0, 0x2003534, 0x0, 0x0, 0x2003536, 0x0, 0x2003538, 0x0, 0x200353A, 0x0,
+	0x200353C, 0x0, 0x200353E, 0x0, 0x2003540, 0x0, 0x2003542, 0x0, 0x2003544, 0x3003546, 0x0, 0x2003549, 0x0, 0x200354B, 0x0, 0x200354D,
+	0x0, 0x200354F, 0x0, 0x2003551, 0x0, 0x2003553, 0x0, 0x2003555, 0x0, 0x2003557, 0x0, 0x2003559, 0x0, 0x200355B, 0x0, 0x200355D,
+	0x0, 0x200355F, 0x0, 0x2003561, 0x0, 0x2003563, 0x0, 0x2003565, 0x0, 0x2003567, 0x0, 0x2003569, 0x0, 0x200356B, 0x0, 0x200356D,
+	0x0, 0x200356F, 0x0, 0x2003571, 0x0, 0x2003573, 0x0, 0x2003575, 0x0, 0x0, 0x2003577, 0x0, 0x2003579, 0x0, 0x200357B, 0x100017A,
+	0x200357D, 0x0, 0x0, 0x200357F, 0x0, 0x2003581, 0x0, 0x0, 0x2003583, 0x0, 0x0, 0x0, 0x2003585, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x2003587, 0x0, 0x0, 0x2003589, 0x0, 0x0, 0x0, 0x200358B, 0x200358D, 0x0, 0x0, 0x0, 0x200358F, 0x0,
+	0x0, 0x2003591, 0x0, 0x2003593, 0x0, 0x2003595, 0x0, 0x0, 0x2003597, 0x0, 0x0, 0x0, 0x0, 0x2003599, 0x0, 0x0,
+	0x200359B, 0x0, 0x0, 0x0, 0x200359D, 0x0, 0x200359F, 0x0, 0x0, 0x20035A1, 0x0, 0x0, 0x0, 0x20035A3, 0x0, 0x20035A5,
+	0x0, 0x0, 0x0, 0x0, 0x20052C1, 0x0, 0x20052C1, 0x20052C3, 0x0, 0x20052C3, 0x20052C5, 0x0, 0x20052C5, 0x0, 0x20035AD, 0x0,
+	0x20035AF, 0x0, 0x20035B1, 0x0, 0x20035B3, 0x0, 0x20035B5, 0x0, 0x20035B7, 0x0, 0x20035B9, 0x0, 0x20035BB, 0x2001DF7, 0x0, 0x20035BD,
+	0x0, 0x20035BF, 0x0, 0x20035C1, 0x0, 0x20035C3, 0x0, 0x20035C5, 0x0, 0x20035C7, 0x0, 0x20035C9, 0x0, 0x20035CB, 0x0, 0x20035CD,
+	0x30035CF, 0x20052C7, 0x0, 0x20052C7, 0x0, 0x20035D4, 0x0, 0x0, 0x0, 0x20035D6, 0x0, 0x20035D8, 0x0, 0x20035DA, 0x0, 0x20035DC,
+	0x0, 0x20035DE, 0x0, 0x20035E0, 0x0, 0x20035E2, 0x0, 0x20035E4, 0x0, 0x20035E6, 0x0, 0x20035E8, 0x0, 0x20035EA, 0x0, 0x20035EC,
+	0x0, 0x20035EE, 0x0, 0x20035F0, 0x0, 0x20035F2, 0x0, 0x20035F4, 0x0, 0x20035F6, 0x0, 0x20035F8, 0x0, 0x20035FA, 0x0, 0x20035FC,
+	0x0, 0x0, 0x0, 0x2001DF9, 0x0, 0x20035FE, 0x0, 0x2003600, 0x0, 0x2003602, 0x0, 0x2003604, 0x0, 0x2003606, 0x0, 0x2003608,
+	0x0, 0x200360A, 0x0, 0x200360C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200360E, 0x0, 0x0, 0x3003610,
+	0x3003613, 0x0, 0x2003616, 0x0, 0x0, 0x0, 0x0, 0x2003618, 0x0, 0x200361A, 0x0, 0x200361C, 0x0, 0x200361E, 0x0, 0x2003620,
+	0x3003622, 0x3003625, 0x3003628, 0x200362B, 0x200362D, 0x0, 0x200362F, 0x2003631, 0x0, 0x2003633, 0x0, 0x2001EFB, 0x3003635, 0x0, 0x0, 0x0,
+	0x2003638, 0x300363A, 0x0, 0x200363D, 0x0, 0x300363F, 0x3003642, 0x0, 0x2003645, 0x2003647, 0x3003649, 0x300364C, 0x300364F, 0x0, 0x0, 0x2003652,
+	0x0, 0x3003654, 0x2003657, 0x0, 0x0, 0x2003659, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300365B, 0x0, 0x0,
+	0x200365E, 0x0, 0x3003660, 0x2003663, 0x0, 0x0, 0x0, 0x3003665, 0x2003668, 0x200366A, 0x200366C, 0x200366E, 0x2003670, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x2000267, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003672, 0x3003675, 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, 0x2003678, 0x0, 0x200367A, 0x0, 0x0, 0x0, 0x200367C, 0x0, 0x0, 0x0, 0x200367E, 0x2003680, 0x2003682, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x6003684, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x200368A, 0x200368C, 0x200368E, 0x2003690,
+	0x6003692, 0x200032B, 0x200335E, 0x2001F0F, 0x2003360, 0x2000331, 0x2003362, 0x2000335, 0x2001D9D, 0x2000339, 0x2003364, 0x2003366, 0x2003368, 0x200336A, 0x200336C, 0x200033D,
+	0x2001F11, 0x2000E35, 0x2001D9F, 0x2001D9F, 0x200336E, 0x2000341, 0x2003370, 0x2003372, 0x2003374, 0x2000345, 0x2003698, 0x200369A, 0x200369C, 0x200369E, 0x20036A0, 0x0,
+	0x200335E, 0x2001D9D, 0x0, 0x0, 0x0, 0x2003370, 0x2001F11, 0x20036A2, 0x0, 0x20036A4, 0x0, 0x20036A6, 0x0, 0x200338A, 0x0, 0x20036A8,
+	0x0, 0x20036AA, 0x0, 0x20036AC, 0x0, 0x20036AE, 0x0, 0x20036B0, 0x0, 0x20036B2, 0x0, 0x20036B4, 0x0, 0x20036B6, 0x0, 0x20036B8,
+	0x2003364, 0x2000E35, 0x20036BA, 0x20036BC, 0x0, 0x2000331, 0x0, 0x0, 0x20036BE, 0x0, 0x0, 0x20036C0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x20003D1, 0x20036C2, 0x20036C4, 0x2000389, 0x20036C6, 0x2000381, 0x20003C9, 0x20003F9, 0x2000395, 0x20036C8, 0x2000391, 0x20036CA, 0x20036CC, 0x20036CE, 0x2000411, 0x20036D0,
+	0x20036D2, 0x20036D4, 0x20036D6, 0x2000399, 0x20036D8, 0x20036DA, 0x20036DC, 0x2000441, 0x20036DE, 0x20036E0, 0x20036E2, 0x2000449, 0x20036E4, 0x2000421, 0x20036E6, 0x20036E8,
+	0x20036EA, 0x20036EC, 0x20036EE, 0x20036F0, 0x20036F2, 0x20036F4, 0x200038D, 0x20036F6, 0x20036F8, 0x20036FA, 0x20036FC, 0x20036FE, 0x2003700, 0x2003702, 0x2003704, 0x2003706,
+	0x0, 0x2003708, 0x0, 0x200370A, 0x0, 0x200370C, 0x0, 0x200370E, 0x0, 0x2003710, 0x0, 0x2003712, 0x0, 0x2003714, 0x0, 0x2003716,
+	0x0, 0x2003718, 0x0, 0x200371A, 0x0, 0x20003C1, 0x0, 0x200371C, 0x0, 0x200371E, 0x0, 0x2003720, 0x0, 0x2003722, 0x0, 0x2003724,
+	0x0, 0x2003726, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x2003740, 0x0, 0x2003742, 0x0, 0x2003744, 0x0, 0x2003746, 0x0, 0x2003748, 0x0, 0x200374A, 0x0, 0x200374C,
+	0x0, 0x200374E, 0x0, 0x2003750, 0x0, 0x2003752, 0x0, 0x2003754, 0x0, 0x2003756, 0x0, 0x2003758, 0x0, 0x200375A, 0x0, 0x200375C,
+	0x0, 0x0, 0x200375E, 0x0, 0x2003760, 0x0, 0x2003762, 0x0, 0x2003764, 0x0, 0x2003766, 0x0, 0x2003768, 0x0, 0x200376A, 0x200376C,
+	0x0, 0x200376E, 0x0, 0x2003770, 0x0, 0x2003772, 0x0, 0x2003774, 0x0, 0x20003E9, 0x0, 0x2003776, 0x0, 0x2003778, 0x0, 0x200377A,
+	0x0, 0x200377C, 0x0, 0x200377E, 0x0, 0x2003780, 0x0, 0x2003782, 0x0, 0x2000419, 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, 0x20037AC, 0x0, 0x20037AE, 0x0, 0x20037B0, 0x0, 0x20037B2, 0x0, 0x20037B4, 0x0, 0x20037B6, 0x0, 0x20037B8,
+	0x0, 0x20037BA, 0x0, 0x20037BC, 0x0, 0x20037BE, 0x0, 0x20037C0, 0x0, 0x20037C2, 0x0, 0x20037C4, 0x0, 0x20037C6, 0x0, 0x20037C8,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x20037CA, 0x20037CC, 0x20037CE, 0x20037D0, 0x20037D2, 0x20037D4, 0x20037D6, 0x20037D8, 0x20037DA, 0x20037DC, 0x20037DE, 0x20037E0, 0x20037E2, 0x20037E4, 0x20037E6,
+	0x20037E8, 0x20037EA, 0x20037EC, 0x20037EE, 0x20037F0, 0x20037F2, 0x20037F4, 0x20037F6, 0x20037F8, 0x20037FA, 0x20037FC, 0x20037FE, 0x2003800, 0x2003802, 0x2003804, 0x2003806,
+	0x2003808, 0x200380A, 0x200380C, 0x200380E, 0x2003810, 0x2003812, 0x2003814, 0x40052C9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30038A4, 0x30038A7, 0x30038AA, 0x30038AD, 0x30038B0, 0x30038B3, 0x0, 0x0,
+	0x20036C4, 0x20036C6, 0x2000411, 0x20036D4, 0x20036D6, 0x20036D6, 0x20036E2, 0x200370A, 0x30038B6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30038B9, 0x0, 0x0, 0x0, 0x30038BC, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30038BF, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x30038C2, 0x0, 0x30038C5, 0x0, 0x30038C8, 0x0, 0x30038CB, 0x0, 0x30038CE, 0x0, 0x30038D1, 0x0, 0x30038D4, 0x0, 0x30038D7,
+	0x0, 0x30038DA, 0x0, 0x30038DD, 0x0, 0x30038E0, 0x0, 0x30038E3, 0x0, 0x30038E6, 0x0, 0x30038E9, 0x0, 0x30038EC, 0x0, 0x30038EF,
+	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,
+	0x0, 0x3003982, 0x0, 0x3003985, 0x0, 0x3003988, 0x0, 0x300398B, 0x0, 0x300398E, 0x0, 0x3003991, 0x0, 0x3003994, 0x0, 0x3003997,
+	0x0, 0x300399A, 0x0, 0x300399D, 0x0, 0x30039A0, 0x30039A3, 0x30039A6, 0x30039A9, 0x30039AC, 0x30039AF, 0x3003952, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x30039B2, 0x0, 0x30039B5, 0x0, 0x30039B8, 0x0, 0x30039BB, 0x0, 0x30039BE, 0x0, 0x30039C1, 0x0, 0x30039C4, 0x0, 0x30039C7,
+	0x0, 0x30039CA, 0x0, 0x30039CD, 0x0, 0x30039D0, 0x0, 0x30039D3, 0x0, 0x30039D6, 0x0, 0x30039D9, 0x0, 0x30039DC, 0x0, 0x30039DF,
+	0x0, 0x30039E2, 0x0, 0x30039E5, 0x0, 0x30039E8, 0x0, 0x30039EB, 0x0, 0x30039EE, 0x0, 0x30039F1, 0x0, 0x30039F4, 0x0, 0x30039F7,
+	0x0, 0x30039FA, 0x0, 0x30039FD, 0x0, 0x3003A00, 0x0, 0x3003A03, 0x0, 0x3003A06, 0x0, 0x3003A09, 0x0, 0x3003A0C, 0x0, 0x3003A0F,
+	0x0, 0x3003A12, 0x0, 0x3003A15, 0x0, 0x3003A18, 0x0, 0x3003A1B, 0x0, 0x3003A1E, 0x0, 0x3003A21, 0x0, 0x3003A24, 0x0, 0x3003A27,
+	0x0, 0x3003A2A, 0x0, 0x3003A2D, 0x0, 0x3003A30, 0x0, 0x3003A33, 0x0, 0x3003A36, 0x0, 0x3003A39, 0x0, 0x3003A3C, 0x0, 0x3003A3F,
+	0x3003A42, 0x3003A45, 0x3003A48, 0x3003A4B, 0x3003A4E, 0x3003A51, 0x3003A54, 0x3003A57, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003A5A, 0x3003A5D, 0x3003A60, 0x3003A63, 0x3003A66, 0x3003A69, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003A6C, 0x3003A6F, 0x3003A72, 0x3003A75, 0x3003A78, 0x3003A7B, 0x3003A7E, 0x3003A81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003A84, 0x3003A87, 0x3003A8A, 0x3003A8D, 0x3003A90, 0x3003A93, 0x3003A96, 0x3003A99, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003A9C, 0x3003A9F, 0x3003AA2, 0x3003AA5, 0x3003AA8, 0x3003AAB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4003AAE, 0x3003AB2, 0x6003AB5, 0x3003ABB, 0x6003ABE, 0x3003AC4, 0x6003AC7, 0x3003ACD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003AD0, 0x3003AD3, 0x3003AD6, 0x3003AD9, 0x3003ADC, 0x3003ADF, 0x3003AE2, 0x3003AE5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003AE8, 0x3003AEB, 0x3003AEE, 0x3003AF1, 0x3003AF4, 0x3003AF7, 0x3003AFA, 0x3003AFD, 0x3003B00, 0x3003B03, 0x3003B06, 0x3003B09, 0x3003B0C, 0x3003B0F, 0x0, 0x0,
+	0x30052CD, 0x30052D0, 0x30052D3, 0x30052D6, 0x30052D9, 0x30052DC, 0x30052DF, 0x30052E2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30052E5, 0x30052E8, 0x30052EB, 0x30052EE, 0x30052F1, 0x30052F4, 0x30052F7, 0x30052FA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30052FD, 0x3005300, 0x3005303, 0x3005306, 0x3005309, 0x300530C, 0x300530F, 0x3005312, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003B8A, 0x3003B8D, 0x5005315, 0x300531A, 0x400531D, 0x0, 0x4003B9D, 0x6005321, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000339, 0x0,
+	0x0, 0x0, 0x5005327, 0x300532C, 0x400532F, 0x0, 0x4003BB4, 0x6005333, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003BBE, 0x3003BC1, 0x6003BC4, 0x6003684, 0x0, 0x0, 0x4003BCA, 0x6003BCE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003BD4, 0x3003BD7, 0x6003BDA, 0x6003692, 0x4003BE0, 0x3003BE4, 0x4003BE7, 0x6003BEB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x5005339, 0x300533E, 0x4005341, 0x0, 0x4003BFE, 0x6005345, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003C08, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003C0B, 0x3003C0E, 0x3003C11, 0x3003C14, 0x3003C17, 0x3003C1A, 0x3003C1D, 0x3003C20, 0x3003C23, 0x3003C26, 0x3003C29, 0x3003C2C, 0x3003C2F, 0x3003C32, 0x3003C35, 0x3003C38,
+	0x0, 0x0, 0x0, 0x0, 0x3003C3B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003C3E, 0x3003C41, 0x3003C44, 0x3003C47, 0x3003C4A, 0x3003C4D, 0x3003C50, 0x3003C53, 0x3003C56, 0x3003C59, 0x3003C5C, 0x3003C5F, 0x3003C62, 0x3003C65, 0x3003C68, 0x3003C6B,
+	0x3003C6E, 0x3003C71, 0x3003C74, 0x3003C77, 0x3003C7A, 0x3003C7D, 0x3003C80, 0x3003C83, 0x3003C86, 0x3003C89, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003C8C, 0x3003C8F, 0x3003C92, 0x3003C95, 0x3003C98, 0x3003C9B, 0x3003C9E, 0x3003CA1, 0x3003CA4, 0x3003CA7, 0x3003CAA, 0x3003CAD, 0x3003CB0, 0x3003CB3, 0x3003CB6, 0x3003CB9,
+	0x3003CBC, 0x3003CBF, 0x3003CC2, 0x3003CC5, 0x3003CC8, 0x3003CCB, 0x3003CCE, 0x3003CD1, 0x3003CD4, 0x3003CD7, 0x3003CDA, 0x3003CDD, 0x3003CE0, 0x3003CE3, 0x3003CE6, 0x3003CE9,
+	0x3003CEC, 0x3003CEF, 0x3003CF2, 0x3003CF5, 0x3003CF8, 0x3003CFB, 0x3003CFE, 0x3003D01, 0x3003D04, 0x3003D07, 0x3003D0A, 0x3003D0D, 0x3003D10, 0x3003D13, 0x3003D16, 0x0,
+	0x0, 0x3003D19, 0x0, 0x0, 0x0, 0x2003D1C, 0x2003D1E, 0x0, 0x3003D20, 0x0, 0x3003D23, 0x0, 0x3003D26, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3003D29, 0x0, 0x0, 0x3003D2C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003D2F, 0x0, 0x3003D32, 0x0, 0x3003D35, 0x0, 0x3003D38, 0x0, 0x3003D3B, 0x0, 0x3003D3E, 0x0, 0x3003D41, 0x0, 0x3003D44,
+	0x0, 0x3003D47, 0x0, 0x3003D4A, 0x0, 0x3003D4D, 0x0, 0x3003D50, 0x0, 0x3003D53, 0x0, 0x3003D56, 0x0, 0x3003D59, 0x0, 0x3003D5C,
+	0x0, 0x3003D5F, 0x0, 0x3003D62, 0x0, 0x3003D65, 0x0, 0x3003D68, 0x0, 0x3003D6B, 0x0, 0x3003D6E, 0x0, 0x3003D71, 0x0, 0x3003D74,
+	0x0, 0x3003D77, 0x0, 0x3003D7A, 0x0, 0x3003D7D, 0x0, 0x3003D80, 0x0, 0x3003D83, 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, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003DC5, 0x0, 0x3003DC8, 0x0,
+	0x0, 0x0, 0x0, 0x3003DCB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003DCE, 0x3003DD1, 0x3003DD4, 0x3003DD7, 0x3003DDA, 0x3003DDD, 0x3003DE0, 0x3003DE3, 0x3003DE6, 0x3003DE9, 0x3003DEC, 0x3003DEF, 0x3003DF2, 0x3003DF5, 0x3003DF8, 0x3003DFB,
+	0x3003DFE, 0x3003E01, 0x3003E04, 0x3003E07, 0x3003E0A, 0x3003E0D, 0x3003E10, 0x3003E13, 0x3003E16, 0x3003E19, 0x3003E1C, 0x3003E1F, 0x3003E22, 0x3003E25, 0x3003E28, 0x3003E2B,
+	0x3003E2E, 0x3003E31, 0x3003E34, 0x3003E37, 0x3003E3A, 0x3003E3D, 0x0, 0x3003E40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003E43, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003E46, 0x0, 0x3003E49, 0x0, 0x3003E4C, 0x0, 0x3003E4F, 0x0, 0x3003E52, 0x0, 0x30038B6, 0x0, 0x3003E55, 0x0, 0x3003E58,
+	0x0, 0x3003E5B, 0x0, 0x3003E5E, 0x0, 0x3003E61, 0x0, 0x3003E64, 0x0, 0x3003E67, 0x0, 0x3003E6A, 0x0, 0x3003E6D, 0x0, 0x3003E70,
+	0x0, 0x3003E73, 0x0, 0x3003E76, 0x0, 0x3003E79, 0x0, 0x3003E7C, 0x0, 0x3003E7F, 0x0, 0x3003E82, 0x0, 0x3003E85, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3003E88, 0x0, 0x3003E8B, 0x0, 0x3003E8E, 0x0, 0x3003E91, 0x0, 0x3003E94, 0x0, 0x3003E97, 0x0, 0x3003E9A, 0x0, 0x3003E9D,
+	0x0, 0x3003EA0, 0x0, 0x3003EA3, 0x0, 0x3003EA6, 0x0, 0x3003EA9, 0x0, 0x3003EAC, 0x0, 0x3003EAF, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3003EB2, 0x0, 0x3003EB5, 0x0, 0x3003EB8, 0x0, 0x3003EBB, 0x0, 0x3003EBE, 0x0, 0x3003EC1, 0x0, 0x3003EC4,
+	0x0, 0x0, 0x0, 0x3003EC7, 0x0, 0x3003ECA, 0x0, 0x3003ECD, 0x0, 0x3003ED0, 0x0, 0x3003ED3, 0x0, 0x3003ED6, 0x0, 0x3003ED9,
+	0x0, 0x3003EDC, 0x0, 0x3003EDF, 0x0, 0x3003EE2, 0x0, 0x3003EE5, 0x0, 0x3003EE8, 0x0, 0x3003EEB, 0x0, 0x3003EEE, 0x0, 0x3003EF1,
+	0x0, 0x3003EF4, 0x0, 0x3003EF7, 0x0, 0x3003EFA, 0x0, 0x3003EFD, 0x0, 0x3003F00, 0x0, 0x3003F03, 0x0, 0x3003F06, 0x0, 0x3003F09,
+	0x0, 0x3003F0C, 0x0, 0x3003F0F, 0x0, 0x3003F12, 0x0, 0x3003F15, 0x0, 0x3003F18, 0x0, 0x3003F1B, 0x0, 0x3003F1E, 0x0, 0x3003F21,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003F24, 0x0, 0x3003F27, 0x0, 0x0, 0x3003F2A,
+	0x0, 0x3003F2D, 0x0, 0x3003F30, 0x0, 0x3003F33, 0x0, 0x3003F36, 0x0, 0x0, 0x0, 0x0, 0x3003F39, 0x0, 0x0, 0x0,
+	0x0, 0x3003F3C, 0x0, 0x3003F3F, 0x3003F42, 0x0, 0x0, 0x3003F45, 0x0, 0x3003F48, 0x0, 0x3003F4B, 0x0, 0x3003F4E, 0x0, 0x3003F51,
+	0x0, 0x3003F54, 0x0, 0x3003F57, 0x0, 0x3003F5A, 0x0, 0x3003F5D, 0x0, 0x3003F60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x3003F63, 0x0, 0x3003F66, 0x0, 0x3003F69, 0x0, 0x3003F6C, 0x0, 0x3003F6F, 0x0, 0x3003F72,
+	0x0, 0x0, 0x0, 0x3003F75, 0x0, 0x0, 0x0, 0x0, 0x3003F78, 0x0, 0x3003F7B, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3003F7E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3003F81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003F84, 0x3003F87, 0x3003F8A, 0x3003F8D, 0x3003F90, 0x3003F93, 0x3003F96, 0x3003F99, 0x3003F9C, 0x3003F9F, 0x3003FA2, 0x3003FA5, 0x3003FA8, 0x3003FAB, 0x3003FAE, 0x3003FB1,
+	0x3003FB4, 0x3003FB7, 0x3003FBA, 0x3003FBD, 0x3003FC0, 0x3003FC3, 0x3003FC6, 0x3003FC9, 0x3003FCC, 0x3003FCF, 0x3003FD2, 0x3003FD5, 0x3003FD8, 0x3003FDB, 0x3003FDE, 0x3003FE1,
+	0x3003FE4, 0x3003FE7, 0x3003FEA, 0x3003FED, 0x3003FF0, 0x3003FF3, 0x3003FF6, 0x3003FF9, 0x3003FFC, 0x3003FFF, 0x3004002, 0x3004005, 0x3004008, 0x300400B, 0x300400E, 0x3004011,
+	0x3004014, 0x3004017, 0x300401A, 0x300401D, 0x3004020, 0x3004023, 0x3004026, 0x3004029, 0x300402C, 0x300402F, 0x3004032, 0x3004035, 0x3004038, 0x300403B, 0x300403E, 0x3004041,
+	0x3004044, 0x3004047, 0x300404A, 0x300404D, 0x3004050, 0x3004053, 0x3004056, 0x3004059, 0x300405C, 0x300405F, 0x3004062, 0x3004065, 0x3004068, 0x300406B, 0x300406E, 0x3004071,
+	0x200534B, 0x200534D, 0x200534F, 0x3005351, 0x3005354, 0x2005357, 0x2005357, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x4005359, 0x400535D, 0x4005361, 0x4005365, 0x4005369, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3004096, 0x3004099, 0x300409C, 0x300409F, 0x30040A2, 0x30040A5, 0x30040A8, 0x30040AB, 0x30040AE, 0x30040B1, 0x30040B4, 0x30040B7, 0x30040BA, 0x30040BD, 0x30040C0,
+	0x30040C3, 0x30040C6, 0x30040C9, 0x30040CC, 0x30040CF, 0x30040D2, 0x30040D5, 0x30040D8, 0x30040DB, 0x30040DE, 0x30040E1, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40040E4, 0x40040E8, 0x40040EC, 0x40040F0, 0x40040F4, 0x40040F8, 0x40040FC, 0x4004100,
+	0x4004104, 0x4004108, 0x400410C, 0x4004110, 0x4004114, 0x4004118, 0x400411C, 0x4004120, 0x4004124, 0x4004128, 0x400412C, 0x4004130, 0x4004134, 0x4004138, 0x400413C, 0x4004140,
+	0x4004144, 0x4004148, 0x400414C, 0x4004150, 0x4004154, 0x4004158, 0x400415C, 0x4004160, 0x4004164, 0x4004168, 0x400416C, 0x4004170, 0x4004174, 0x4004178, 0x400417C, 0x4004180,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4004184, 0x4004188, 0x400418C, 0x4004190, 0x4004194, 0x4004198, 0x400419C, 0x40041A0,
+	0x40041A4, 0x40041A8, 0x40041AC, 0x40041B0, 0x40041B4, 0x40041B8, 0x40041BC, 0x40041C0, 0x40041C4, 0x40041C8, 0x40041CC, 0x40041D0, 0x40041D4, 0x40041D8, 0x40041DC, 0x40041E0,
+	0x40041E4, 0x40041E8, 0x40041EC, 0x40041F0, 0x40041F4, 0x40041F8, 0x40041FC, 0x4004200, 0x4004204, 0x4004208, 0x400420C, 0x4004210, 0x0, 0x0, 0x0, 0x0,
+	0x4004214, 0x4004218, 0x400421C, 0x4004220, 0x4004224, 0x4004228, 0x400422C, 0x4004230, 0x4004234, 0x4004238, 0x400423C, 0x4004240, 0x4004244, 0x4004248, 0x400424C, 0x4004250,
+	0x4004254, 0x4004258, 0x400425C, 0x4004260, 0x4004264, 0x4004268, 0x400426C, 0x4004270, 0x4004274, 0x4004278, 0x400427C, 0x4004280, 0x4004284, 0x4004288, 0x400428C, 0x4004290,
+	0x4004294, 0x4004298, 0x400429C, 0x40042A0, 0x40042A4, 0x40042A8, 0x40042AC, 0x40042B0, 0x40042B4, 0x40042B8, 0x40042BC, 0x40042C0, 0x40042C4, 0x40042C8, 0x40042CC, 0x40042D0,
+	0x40042D4, 0x40042D8, 0x40042DC, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x40042E0, 0x40042E4, 0x40042E8, 0x40042EC, 0x40042F0, 0x40042F4, 0x40042F8, 0x40042FC, 0x4004300, 0x4004304, 0x4004308, 0x400430C, 0x4004310, 0x4004314, 0x4004318, 0x400431C,
+	0x4004320, 0x4004324, 0x4004328, 0x400432C, 0x4004330, 0x4004334, 0x4004338, 0x400433C, 0x4004340, 0x4004344, 0x4004348, 0x400434C, 0x4004350, 0x4004354, 0x4004358, 0x400435C,
+	0x4004360, 0x4004364, 0x4004368, 0x400436C, 0x4004370, 0x4004374, 0x4004378, 0x400437C, 0x4004380, 0x4004384, 0x4004388, 0x400438C, 0x4004390, 0x4004394, 0x4004398, 0x400439C,
+	0x40043A0, 0x40043A4, 0x40043A8, 0x40043AC, 0x40043B0, 0x40043B4, 0x40043B8, 0x40043BC, 0x40043C0, 0x40043C4, 0x40043C8, 0x40043CC, 0x40043D0, 0x40043D4, 0x40043D8, 0x40043DC,
+	0x0, 0x0, 0x40043E0, 0x40043E4, 0x40043E8, 0x40043EC, 0x40043F0, 0x40043F4, 0x40043F8, 0x40043FC, 0x4004400, 0x4004404, 0x4004408, 0x400440C, 0x4004410, 0x4004414,
+	0x4004418, 0x400441C, 0x4004420, 0x4004424, 0x4004428, 0x400442C, 0x4004430, 0x4004434, 0x4004438, 0x400443C, 0x4004440, 0x4004444, 0x4004448, 0x400444C, 0x4004450, 0x4004454,
+	0x4004458, 0x400445C, 0x4004460, 0x4004464, 0x0, 0x0, 0x0, 0x0, 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* 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, 1024, 360, 360, 360, 360, 360, 360, 360, 1152, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
+	360, 360, 360, 360, 360, 360, 360, 360, 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[1280] = {
+	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, 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, 0x460, 0x480, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4A0, 0x4C0, 0x4E0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5A0, 0x5C0, 0x5E0, 0x600, 0x620, 0x640, 0x660, 0x680,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6A0, 0x0, 0x6C0, 0x6E0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x700, 0x720, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x740, 0x760, 0x0, 0x780, 0x7A0, 0x7C0, 0x7E0, 0x800, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x820, 0x840, 0x860, 0x0, 0x0, 0x0, 0x0, 0x880, 0x8A0, 0x8C0, 0x8E0, 0x900, 0x920, 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, 0x960, 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, 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, 0x9E0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0xA00, 0xA20, 0x0, 0x0, 0x0, 0xA40, 0xA60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0xA80, 0xAA0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0xAC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0xAE0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB00, 0xB20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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[2880] = {
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x1002070, 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, 0x2001D31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2004468, 0x200446A, 0x200446C, 0x200446E, 0x2004470, 0x2004472, 0x2000247, 0x2004474, 0x2004476, 0x2004478, 0x200447A, 0x200447C, 0x200447E, 0x2004480, 0x2004482, 0x2004484,
+	0x2001E26, 0x2004486, 0x2004488, 0x200448A, 0x200448C, 0x200448E, 0x2004490, 0x0, 0x2000294, 0x2004492, 0x2004494, 0x2004496, 0x2004498, 0x200449A, 0x200449C, 0x200536D,
+	0x200449E, 0x0, 0x20044A0, 0x0, 0x20044A2, 0x0, 0x20044A4, 0x0, 0x20044A6, 0x0, 0x20044A8, 0x0, 0x20044AA, 0x0, 0x20044AC, 0x0,
+	0x20044AE, 0x0, 0x20044B0, 0x0, 0x20044B2, 0x0, 0x20044B4, 0x0, 0x20044B6, 0x0, 0x20044B8, 0x0, 0x20044BA, 0x0, 0x20044BC, 0x0,
+	0x20044BE, 0x0, 0x20044C0, 0x0, 0x20044C2, 0x0, 0x2001F00, 0x0, 0x20044C4, 0x0, 0x20044C6, 0x0, 0x20044C8, 0x0, 0x20044CA, 0x0,
+	0x30044CC, 0x0, 0x20044CF, 0x0, 0x20044D1, 0x0, 0x20044D3, 0x0, 0x0, 0x20044D5, 0x0, 0x20044D7, 0x0, 0x20044D9, 0x0, 0x20044DB,
+	0x0, 0x20044DD, 0x0, 0x20044DF, 0x0, 0x20044E1, 0x0, 0x20044E3, 0x0, 0x3001D50, 0x2001E08, 0x0, 0x20044E5, 0x0, 0x20044E7, 0x0,
+	0x20044E9, 0x0, 0x2002CF3, 0x0, 0x20044EB, 0x0, 0x20044ED, 0x0, 0x20044EF, 0x0, 0x20044F1, 0x0, 0x20044F3, 0x0, 0x20044F5, 0x0,
+	0x20044F7, 0x0, 0x20044F9, 0x0, 0x20044FB, 0x0, 0x20044FD, 0x0, 0x20044FF, 0x0, 0x2004501, 0x0, 0x2004503, 0x0, 0x2004505, 0x0,
+	0x2004507, 0x0, 0x2004509, 0x0, 0x200450B, 0x0, 0x200450D, 0x0, 0x200450F, 0x2004511, 0x0, 0x2004513, 0x0, 0x2004515, 0x0, 0x100017D,
+	0x0, 0x2004517, 0x2004519, 0x0, 0x200451B, 0x0, 0x2001E0A, 0x200451D, 0x0, 0x200451F, 0x2004521, 0x2004523, 0x0, 0x0, 0x2004525, 0x2001E02,
+	0x2001E04, 0x2004527, 0x0, 0x2004529, 0x2001D85, 0x0, 0x2001E30, 0x2001E2E, 0x200452B, 0x0, 0x0, 0x0, 0x2001E15, 0x2001E44, 0x0, 0x2001E4A,
+	0x200452D, 0x0, 0x200452F, 0x0, 0x2004531, 0x0, 0x2004533, 0x2004535, 0x0, 0x2001E50, 0x0, 0x0, 0x2004537, 0x0, 0x2004539, 0x200453B,
+	0x0, 0x2001E56, 0x2001E5B, 0x200453D, 0x0, 0x200453F, 0x0, 0x200026B, 0x2004541, 0x0, 0x0, 0x0, 0x2004543, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x2004545, 0x2004545, 0x0, 0x2004547, 0x2004547, 0x0, 0x2004549, 0x2004549, 0x0, 0x200454B, 0x0, 0x200454D,
+	0x0, 0x200454F, 0x0, 0x2004551, 0x0, 0x2004553, 0x0, 0x2004555, 0x0, 0x2004557, 0x0, 0x2004559, 0x0, 0x0, 0x200455B, 0x0,
+	0x200455D, 0x0, 0x200455F, 0x0, 0x2004561, 0x0, 0x2004563, 0x0, 0x2004565, 0x0, 0x2004567, 0x0, 0x2004569, 0x0, 0x200456B, 0x0,
+	0x300026F, 0x200456D, 0x200456D, 0x0, 0x200456F, 0x0, 0x2004571, 0x2004573, 0x2004575, 0x0, 0x2004577, 0x0, 0x2004579, 0x0, 0x200457B, 0x0,
+	0x200457D, 0x0, 0x200457F, 0x0, 0x2004581, 0x0, 0x2004583, 0x0, 0x2004585, 0x0, 0x2004587, 0x0, 0x2004589, 0x0, 0x200458B, 0x0,
+	0x200458D, 0x0, 0x200458F, 0x0, 0x2004591, 0x0, 0x2004593, 0x0, 0x2004595, 0x0, 0x2004597, 0x0, 0x2004599, 0x0, 0x200459B, 0x0,
+	0x200459D, 0x0, 0x200459F, 0x0, 0x20045A1, 0x0, 0x20045A3, 0x0, 0x20045A5, 0x0, 0x20045A7, 0x0, 0x20045A9, 0x0, 0x20045AB, 0x0,
+	0x20045AD, 0x0, 0x20045AF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30045B1, 0x20045B4, 0x0, 0x20045B6, 0x30045B8, 0x0,
+	0x0, 0x20045BB, 0x0, 0x20045BD, 0x2001E54, 0x2001E5D, 0x20045BF, 0x0, 0x20045C1, 0x0, 0x20045C3, 0x0, 0x20045C5, 0x0, 0x20045C7, 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,
+	0x20045C9, 0x0, 0x20045CB, 0x0, 0x0, 0x0, 0x20045CD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20045CF,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20045D1, 0x0, 0x20045D3, 0x20045D5, 0x20045D7, 0x0, 0x20045D9, 0x0, 0x20045DB, 0x20045DD,
+	0x6000349, 0x2000357, 0x2001D91, 0x2001E1A, 0x2001E1C, 0x200035B, 0x2003379, 0x200035F, 0x2001D93, 0x2000349, 0x2001D99, 0x200337B, 0x2001D31, 0x200337D, 0x200337F, 0x200036D,
+	0x2001D97, 0x2000E17, 0x0, 0x2003381, 0x2003383, 0x2000367, 0x2001D95, 0x2001E1E, 0x2003385, 0x2000375, 0x20045DF, 0x20045E1, 0x0, 0x0, 0x0, 0x0,
+	0x6000367, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x2003381, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20045E3,
+	0x2001D91, 0x2001D93, 0x0, 0x0, 0x0, 0x2001D95, 0x2001D97, 0x0, 0x20045E5, 0x0, 0x20045E7, 0x0, 0x200338C, 0x0, 0x20045E9, 0x0,
+	0x20045EB, 0x0, 0x20045ED, 0x0, 0x20045EF, 0x0, 0x20045F1, 0x0, 0x20045F3, 0x0, 0x20045F5, 0x0, 0x20045F7, 0x0, 0x20045F9, 0x0,
+	0x2001D99, 0x2000E17, 0x0, 0x0, 0x2001D93, 0x200035B, 0x0, 0x20045FB, 0x0, 0x20045FD, 0x20045FF, 0x0, 0x0, 0x2004601, 0x2004603, 0x2004605,
+	0x2004607, 0x2004609, 0x200460B, 0x200460D, 0x200460F, 0x2004611, 0x20003B1, 0x2004613, 0x2004615, 0x2004617, 0x2004619, 0x200461B, 0x200461D, 0x200461F, 0x2004621, 0x2004623,
+	0x20003D5, 0x2004625, 0x2004627, 0x20003AD, 0x2004629, 0x20003A5, 0x20003CD, 0x20003FD, 0x20003A1, 0x200462B, 0x20003B5, 0x200462D, 0x200462F, 0x2001E20, 0x2000415, 0x2004631,
+	0x2004633, 0x2004635, 0x2004637, 0x20003BD, 0x2004639, 0x200463B, 0x200463D, 0x2000445, 0x200463F, 0x2004641, 0x2002CEA, 0x200044D, 0x2002CEC, 0x2000425, 0x2004643, 0x2004645,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x2004647, 0x0, 0x2004649, 0x0, 0x200464B, 0x0, 0x200464D, 0x0, 0x200464F, 0x0, 0x2004651, 0x0, 0x2004653, 0x0, 0x2004655, 0x0,
+	0x2004657, 0x0, 0x2004659, 0x0, 0x20003C5, 0x0, 0x200465B, 0x0, 0x200465D, 0x0, 0x200465F, 0x0, 0x2004661, 0x0, 0x2004663, 0x0,
+	0x2004665, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004667, 0x0, 0x2004669, 0x0, 0x200466B, 0x0,
+	0x200466D, 0x0, 0x200466F, 0x0, 0x2004671, 0x0, 0x2004673, 0x0, 0x2004675, 0x0, 0x2004677, 0x0, 0x2004679, 0x0, 0x200467B, 0x0,
+	0x200467D, 0x0, 0x200467F, 0x0, 0x2004681, 0x0, 0x2004683, 0x0, 0x2004685, 0x0, 0x2004687, 0x0, 0x2004689, 0x0, 0x200468B, 0x0,
+	0x200468D, 0x0, 0x200468F, 0x0, 0x2004691, 0x0, 0x2004693, 0x0, 0x2004695, 0x0, 0x2004697, 0x0, 0x2004699, 0x0, 0x200469B, 0x0,
+	0x200469D, 0x200469F, 0x0, 0x20046A1, 0x0, 0x20046A3, 0x0, 0x20046A5, 0x0, 0x20046A7, 0x0, 0x20046A9, 0x0, 0x20046AB, 0x0, 0x0,
+	0x20046AD, 0x0, 0x20046AF, 0x0, 0x20046B1, 0x0, 0x20046B3, 0x0, 0x20003ED, 0x0, 0x20046B5, 0x0, 0x20046B7, 0x0, 0x20046B9, 0x0,
+	0x20046BB, 0x0, 0x20046BD, 0x0, 0x20046BF, 0x0, 0x20046C1, 0x0, 0x200041D, 0x0, 0x20046C3, 0x0, 0x20046C5, 0x0, 0x20046C7, 0x0,
+	0x20046C9, 0x0, 0x20046CB, 0x0, 0x20046CD, 0x0, 0x20046CF, 0x0, 0x20046D1, 0x0, 0x20046D3, 0x0, 0x20046D5, 0x0, 0x20046D7, 0x0,
+	0x20046D9, 0x0, 0x20046DB, 0x0, 0x20046DD, 0x0, 0x20046DF, 0x0, 0x20046E1, 0x0, 0x20046E3, 0x0, 0x20046E5, 0x0, 0x20046E7, 0x0,
+	0x20046E9, 0x0, 0x20046EB, 0x0, 0x20046ED, 0x0, 0x20046EF, 0x0, 0x20046F1, 0x0, 0x20046F3, 0x0, 0x20046F5, 0x0, 0x20046F7, 0x0,
+	0x20046F9, 0x0, 0x20046FB, 0x0, 0x20046FD, 0x0, 0x20046FF, 0x0, 0x2004701, 0x0, 0x2004703, 0x0, 0x2004705, 0x0, 0x2004707, 0x0,
+	0x0, 0x2004709, 0x200470B, 0x200470D, 0x200470F, 0x2001DA1, 0x2004711, 0x2004713, 0x2004715, 0x2004717, 0x2004719, 0x2002D1A, 0x200471B, 0x2002D22, 0x200471D, 0x200471F,
+	0x2004721, 0x2004723, 0x2004725, 0x2004727, 0x2002D10, 0x2004729, 0x2002D12, 0x200472B, 0x200472D, 0x200472F, 0x2004731, 0x2004733, 0x2004735, 0x2004737, 0x2002D1C, 0x2004739,
+	0x200473B, 0x200473D, 0x2001DA3, 0x200473F, 0x2004741, 0x2004743, 0x2004745, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4001DA1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004747, 0x300474A, 0x300474D, 0x3004750, 0x3004753, 0x3004756, 0x3004759, 0x300475C, 0x300475F, 0x3004762, 0x3004765, 0x3004768, 0x300476B, 0x300476E, 0x3004771, 0x3004774,
+	0x3004777, 0x300477A, 0x300477D, 0x3004780, 0x3004783, 0x3004786, 0x3004789, 0x300478C, 0x300478F, 0x3004792, 0x3004795, 0x3004798, 0x300479B, 0x300479E, 0x30047A1, 0x30047A4,
+	0x30047A7, 0x30047AA, 0x30047AD, 0x30047B0, 0x30047B3, 0x30047B6, 0x0, 0x30047B9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30047BC, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30038A4, 0x30038A7, 0x30038AA, 0x30038AD, 0x30038B0, 0x30038B3, 0x0, 0x0,
+	0x2004627, 0x2004629, 0x2000415, 0x2004635, 0x2004637, 0x2004637, 0x2002CEA, 0x2004649, 0x3004DB5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x30048C1, 0x30048C4, 0x30048C7, 0x30048CA, 0x30048CD, 0x30048D0, 0x30048D3, 0x30048D6, 0x30048D9, 0x30048DC, 0x30048DF, 0x30048E2, 0x3001DF4, 0x30048E5, 0x30048E8, 0x30048EB,
+	0x30048EE, 0x30048F1, 0x30048F4, 0x30048F7, 0x30048FA, 0x30048FD, 0x3004900, 0x3004903, 0x3004906, 0x3004909, 0x300490C, 0x300490F, 0x3004912, 0x3004915, 0x3004918, 0x300491B,
+	0x300491E, 0x3004921, 0x3004924, 0x3004927, 0x300492A, 0x300492D, 0x3004930, 0x3004933, 0x3004936, 0x3004939, 0x300493C, 0x0, 0x0, 0x300493F, 0x3004942, 0x3004945,
+	0x3004948, 0x0, 0x300494B, 0x0, 0x300494E, 0x0, 0x3004951, 0x0, 0x3004954, 0x0, 0x3004957, 0x0, 0x300495A, 0x0, 0x300495D, 0x0,
+	0x3004960, 0x0, 0x3004963, 0x0, 0x3004966, 0x0, 0x3004969, 0x0, 0x300496C, 0x0, 0x300496F, 0x0, 0x3004972, 0x0, 0x3004975, 0x0,
+	0x3004978, 0x0, 0x300497B, 0x0, 0x300497E, 0x0, 0x3004981, 0x0, 0x3004984, 0x0, 0x3004987, 0x0, 0x300498A, 0x0, 0x300498D, 0x0,
+	0x3004990, 0x0, 0x3004993, 0x0, 0x3004996, 0x0, 0x3004999, 0x0, 0x300499C, 0x0, 0x300499F, 0x0, 0x30049A2, 0x0, 0x30049A5, 0x0,
+	0x30049A8, 0x0, 0x30049AB, 0x0, 0x30049AE, 0x0, 0x30049B1, 0x0, 0x30049B4, 0x0, 0x30049B7, 0x0, 0x30049BA, 0x0, 0x30049BD, 0x0,
+	0x30049C0, 0x0, 0x30049C3, 0x0, 0x30049C6, 0x0, 0x30049C9, 0x0, 0x30049CC, 0x0, 0x30049CF, 0x0, 0x30049D2, 0x0, 0x30049D5, 0x0,
+	0x30049D8, 0x0, 0x30049DB, 0x0, 0x30049DE, 0x0, 0x30049E1, 0x0, 0x30049E4, 0x0, 0x30049E7, 0x0, 0x30049EA, 0x0, 0x30049ED, 0x0,
+	0x30049F0, 0x0, 0x30049F3, 0x0, 0x30049F6, 0x0, 0x30049F9, 0x0, 0x30049FC, 0x0, 0x30049FF, 0x0, 0x3004A02, 0x0, 0x3004A05, 0x0,
+	0x3004A08, 0x0, 0x3004A0B, 0x0, 0x3004A0E, 0x0, 0x3004A11, 0x0, 0x3004A14, 0x0, 0x3004A17, 0x0, 0x3004A1A, 0x0, 0x3004A1D, 0x0,
+	0x3004A20, 0x0, 0x3004A23, 0x0, 0x3004A26, 0x0, 0x300082F, 0x3000832, 0x3000835, 0x3000838, 0x3001E63, 0x30049D8, 0x0, 0x0, 0x200536D, 0x0,
+	0x3004A2B, 0x0, 0x3004A2E, 0x0, 0x3004A31, 0x0, 0x3004A34, 0x0, 0x3004A37, 0x0, 0x3004A3A, 0x0, 0x3004A3D, 0x0, 0x3004A40, 0x0,
+	0x3004A43, 0x0, 0x3004A46, 0x0, 0x3004A49, 0x0, 0x3004A4C, 0x0, 0x3004A4F, 0x0, 0x3004A52, 0x0, 0x3004A55, 0x0, 0x3004A58, 0x0,
+	0x3004A5B, 0x0, 0x3004A5E, 0x0, 0x3004A61, 0x0, 0x3004A64, 0x0, 0x3004A67, 0x0, 0x3004A6A, 0x0, 0x3004A6D, 0x0, 0x3004A70, 0x0,
+	0x3004A73, 0x0, 0x3004A76, 0x0, 0x3004A79, 0x0, 0x3004A7C, 0x0, 0x3004A7F, 0x0, 0x3004A82, 0x0, 0x3004A85, 0x0, 0x3004A88, 0x0,
+	0x3004A8B, 0x0, 0x3004A8E, 0x0, 0x3004A91, 0x0, 0x3004A94, 0x0, 0x3004A97, 0x0, 0x3004A9A, 0x0, 0x3004A9D, 0x0, 0x3004AA0, 0x0,
+	0x3004AA3, 0x0, 0x3004AA6, 0x0, 0x3004AA9, 0x0, 0x3004AAC, 0x0, 0x3004AAF, 0x0, 0x3004AB2, 0x0, 0x3004AB5, 0x0, 0x3004AB8, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004ABB, 0x3004ABE, 0x3004AC1, 0x3004AC4, 0x3004AC7, 0x3004ACA, 0x3004ACD, 0x3004AD0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004AD3, 0x3004AD6, 0x3004AD9, 0x3004ADC, 0x3004ADF, 0x3004AE2, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004AE5, 0x3004AE8, 0x3004AEB, 0x3004AEE, 0x3004AF1, 0x3004AF4, 0x3004AF7, 0x3004AFA,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004AFD, 0x3004B00, 0x3004B03, 0x3004B06, 0x3004B09, 0x3004B0C, 0x3004B0F, 0x3004B12,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004B15, 0x3004B18, 0x3004B1B, 0x3004B1E, 0x3004B21, 0x3004B24, 0x0, 0x0,
+	0x4000B4D, 0x0, 0x6000B55, 0x0, 0x6000B61, 0x0, 0x6000B6D, 0x0, 0x0, 0x3004B27, 0x0, 0x3004B2A, 0x0, 0x3004B2D, 0x0, 0x3004B30,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004B33, 0x3004B36, 0x3004B39, 0x3004B3C, 0x3004B3F, 0x3004B42, 0x3004B45, 0x3004B48,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x500536F, 0x5005374, 0x5005379, 0x500537E, 0x5005383, 0x5005388, 0x500538D, 0x5005392, 0x500536F, 0x5005374, 0x5005379, 0x500537E, 0x5005383, 0x5005388, 0x500538D, 0x5005392,
+	0x5005397, 0x500539C, 0x50053A1, 0x50053A6, 0x50053AB, 0x50053B0, 0x50053B5, 0x50053BA, 0x5005397, 0x500539C, 0x50053A1, 0x50053A6, 0x50053AB, 0x50053B0, 0x50053B5, 0x50053BA,
+	0x50053BF, 0x50053C4, 0x50053C9, 0x50053CE, 0x50053D3, 0x50053D8, 0x50053DD, 0x50053E2, 0x50053BF, 0x50053C4, 0x50053C9, 0x50053CE, 0x50053D3, 0x50053D8, 0x50053DD, 0x50053E2,
+	0x0, 0x0, 0x50053E7, 0x40053EC, 0x40053F0, 0x0, 0x4000D83, 0x60053F4, 0x3004B93, 0x3004B96, 0x3004B99, 0x3004B9C, 0x40053EC, 0x0, 0x2000349, 0x0,
+	0x0, 0x0, 0x50053FA, 0x40053FF, 0x4005403, 0x0, 0x4000DB1, 0x6005407, 0x3004BA2, 0x3004BA5, 0x3004BA8, 0x3004BAB, 0x40053FF, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x6000DDE, 0x6000349, 0x0, 0x0, 0x4000DE4, 0x6000DE8, 0x3004BB1, 0x3004BB4, 0x3004BB7, 0x3004BBA, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x6000E11, 0x6000367, 0x4000E17, 0x0, 0x4000E1F, 0x6000E23, 0x3004BBD, 0x3004BC0, 0x3004BC3, 0x3004BC6, 0x3004BC9, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x500540D, 0x4005412, 0x4005416, 0x0, 0x4000E4E, 0x600541A, 0x3004BCC, 0x3004BCF, 0x3004BD2, 0x3004BD5, 0x4005412, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000375, 0x0, 0x0, 0x0, 0x100012F, 0x2004472, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x3004BDB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004BDE, 0x3004BE1, 0x3004BE4, 0x3004BE7, 0x3004BEA, 0x3004BED, 0x3004BF0, 0x3004BF3, 0x3004BF6, 0x3004BF9, 0x3004BFC, 0x3004BFF, 0x3004C02, 0x3004C05, 0x3004C08, 0x3004C0B,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x3004C0E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004C11, 0x3004C14, 0x3004C17, 0x3004C1A, 0x3004C1D, 0x3004C20, 0x3004C23, 0x3004C26, 0x3004C29, 0x3004C2C,
+	0x3004C2F, 0x3004C32, 0x3004C35, 0x3004C38, 0x3004C3B, 0x3004C3E, 0x3004C41, 0x3004C44, 0x3004C47, 0x3004C4A, 0x3004C4D, 0x3004C50, 0x3004C53, 0x3004C56, 0x3004C59, 0x3004C5C,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004C5F, 0x3004C62, 0x3004C65, 0x3004C68, 0x3004C6B, 0x3004C6E, 0x3004C71, 0x3004C74, 0x3004C77, 0x3004C7A, 0x3004C7D, 0x3004C80, 0x3004C83, 0x3004C86, 0x3004C89, 0x3004C8C,
+	0x3004C8F, 0x3004C92, 0x3004C95, 0x3004C98, 0x3004C9B, 0x3004C9E, 0x3004CA1, 0x3004CA4, 0x3004CA7, 0x3004CAA, 0x3004CAD, 0x3004CB0, 0x3004CB3, 0x3004CB6, 0x3004CB9, 0x3004CBC,
+	0x3004CBF, 0x3004CC2, 0x3004CC5, 0x3004CC8, 0x3004CCB, 0x3004CCE, 0x3004CD1, 0x3004CD4, 0x3004CD7, 0x3004CDA, 0x3004CDD, 0x3004CE0, 0x3004CE3, 0x3004CE6, 0x3004CE9, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004CEC, 0x0, 0x2002CFB, 0x3004CEF, 0x2004CF2, 0x0, 0x0, 0x3004CF4, 0x0, 0x3004CF7, 0x0, 0x3004CFA, 0x0, 0x2001DFD, 0x2001E40, 0x2001DFB,
+	0x2001E22, 0x0, 0x3004CFD, 0x0, 0x0, 0x3004D00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2004D03, 0x2004D05,
+	0x3004D07, 0x0, 0x3004D0A, 0x0, 0x3004D0D, 0x0, 0x3004D10, 0x0, 0x3004D13, 0x0, 0x3004D16, 0x0, 0x3004D19, 0x0, 0x3004D1C, 0x0,
+	0x3004D1F, 0x0, 0x3004D22, 0x0, 0x3004D25, 0x0, 0x3004D28, 0x0, 0x3004D2B, 0x0, 0x3004D2E, 0x0, 0x3004D31, 0x0, 0x3004D34, 0x0,
+	0x3004D37, 0x0, 0x3004D3A, 0x0, 0x3004D3D, 0x0, 0x3004D40, 0x0, 0x3004D43, 0x0, 0x3004D46, 0x0, 0x3004D49, 0x0, 0x3004D4C, 0x0,
+	0x3004D4F, 0x0, 0x3004D52, 0x0, 0x3004D55, 0x0, 0x3004D58, 0x0, 0x3004D5B, 0x0, 0x3004D5E, 0x0, 0x3004D61, 0x0, 0x3004D64, 0x0,
+	0x3004D67, 0x0, 0x3004D6A, 0x0, 0x3004D6D, 0x0, 0x3004D70, 0x0, 0x3004D73, 0x0, 0x3004D76, 0x0, 0x3004D79, 0x0, 0x3004D7C, 0x0,
+	0x3004D7F, 0x0, 0x3004D82, 0x0, 0x3004D85, 0x0, 0x3004D88, 0x0, 0x3004D8B, 0x0, 0x3004D8E, 0x0, 0x3004D91, 0x0, 0x3004D94, 0x0,
+	0x3004D97, 0x0, 0x3004D9A, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004D9D, 0x0, 0x3004DA0, 0x0, 0x0,
+	0x0, 0x0, 0x3004DA3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004DA6, 0x0, 0x3004DA9, 0x0, 0x3004DAC, 0x0, 0x3004DAF, 0x0, 0x3004DB2, 0x0, 0x3004DB5, 0x0, 0x3004DB8, 0x0, 0x3004DBB, 0x0,
+	0x3004DBE, 0x0, 0x3004DC1, 0x0, 0x3004DC4, 0x0, 0x3004DC7, 0x0, 0x3004DCA, 0x0, 0x3004DCD, 0x0, 0x3004DD0, 0x0, 0x3004DD3, 0x0,
+	0x3004DD6, 0x0, 0x3004DD9, 0x0, 0x3004DDC, 0x0, 0x3004DDF, 0x0, 0x3004DE2, 0x0, 0x3004DE5, 0x0, 0x3004DE8, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3004DEB, 0x0, 0x3004DEE, 0x0, 0x3004DF1, 0x0, 0x3004DF4, 0x0, 0x3004DF7, 0x0, 0x3004DFA, 0x0, 0x3004DFD, 0x0, 0x3004E00, 0x0,
+	0x3004E03, 0x0, 0x3004E06, 0x0, 0x3004E09, 0x0, 0x3004E0C, 0x0, 0x3004E0F, 0x0, 0x3004E12, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x3004E15, 0x0, 0x3004E18, 0x0, 0x3002CF5, 0x0, 0x3004E1B, 0x0, 0x3004E1E, 0x0, 0x3004E21, 0x0, 0x3004E24, 0x0,
+	0x0, 0x0, 0x3004E27, 0x0, 0x3004E2A, 0x0, 0x3004E2D, 0x0, 0x3004E30, 0x0, 0x3004E33, 0x0, 0x3004E36, 0x0, 0x3004E39, 0x0,
+	0x3004E3C, 0x0, 0x3004E3F, 0x0, 0x3004E42, 0x0, 0x3004E45, 0x0, 0x3004E48, 0x0, 0x3004E4B, 0x0, 0x3004E4E, 0x0, 0x3004E51, 0x0,
+	0x3004E54, 0x0, 0x3004E57, 0x0, 0x3004E5A, 0x0, 0x3004E5D, 0x0, 0x3004E60, 0x0, 0x3004E63, 0x0, 0x3004E66, 0x0, 0x3004E69, 0x0,
+	0x3004E6C, 0x0, 0x3004E6F, 0x0, 0x3004E72, 0x0, 0x3004E75, 0x0, 0x3004E78, 0x0, 0x3004E7B, 0x0, 0x3004E7E, 0x0, 0x3002CEE, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3004E81, 0x0, 0x3004E84, 0x0, 0x3004E87, 0x3004E8A, 0x0,
+	0x3004E8D, 0x0, 0x3004E90, 0x0, 0x3004E93, 0x0, 0x3004E96, 0x0, 0x0, 0x0, 0x0, 0x3004E99, 0x0, 0x2001E2C, 0x0, 0x0,
+	0x3004E9C, 0x0, 0x3004E9F, 0x0, 0x0, 0x0, 0x3004EA2, 0x0, 0x3004EA5, 0x0, 0x3004EA8, 0x0, 0x3004EAB, 0x0, 0x3004EAE, 0x0,
+	0x3004EB1, 0x0, 0x3004EB4, 0x0, 0x3004EB7, 0x0, 0x3004EBA, 0x0, 0x3004EBD, 0x0, 0x2001D6B, 0x2001E06, 0x2001E2A, 0x2004EC0, 0x2001E32, 0x0,
+	0x2004EC2, 0x2004EC4, 0x2001E37, 0x3004EC6, 0x3004EC9, 0x0, 0x3004ECC, 0x0, 0x3004ECF, 0x0, 0x3004ED2, 0x0, 0x3004ED5, 0x0, 0x3004ED8, 0x0,
+	0x0, 0x0, 0x3004EDB, 0x0, 0x3004EDE, 0x2001E4E, 0x3004EE1, 0x3004EE4, 0x0, 0x3004EE7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x3004EEA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x3003F84, 0x3003F87, 0x3003F8A, 0x3003F8D, 0x3003F90, 0x3003F93, 0x3003F96, 0x3003F99, 0x3003F9C, 0x3003F9F, 0x3003FA2, 0x3003FA5, 0x3003FA8, 0x3003FAB, 0x3003FAE, 0x3003FB1,
+	0x3003FB4, 0x3003FB7, 0x3003FBA, 0x3003FBD, 0x3003FC0, 0x3003FC3, 0x3003FC6, 0x3003FC9, 0x3003FCC, 0x3003FCF, 0x3003FD2, 0x3003FD5, 0x3003FD8, 0x3003FDB, 0x3003FDE, 0x3003FE1,
+	0x3003FE4, 0x3003FE7, 0x3003FEA, 0x3003FED, 0x3003FF0, 0x3003FF3, 0x3003FF6, 0x3003FF9, 0x3003FFC, 0x3003FFF, 0x3004002, 0x3004005, 0x3004008, 0x300400B, 0x300400E, 0x3004011,
+	0x3004014, 0x3004017, 0x300401A, 0x300401D, 0x3004020, 0x3004023, 0x3004026, 0x3004029, 0x300402C, 0x300402F, 0x3004032, 0x3004035, 0x3004038, 0x300403B, 0x300403E, 0x3004041,
+	0x3004044, 0x3004047, 0x300404A, 0x300404D, 0x3004050, 0x3004053, 0x3004056, 0x3004059, 0x300405C, 0x300405F, 0x3004062, 0x3004065, 0x3004068, 0x300406B, 0x300406E, 0x3004071,
+	0x2002D02, 0x2002D04, 0x2002D06, 0x3002D08, 0x3002D0B, 0x2002D0E, 0x2002D0E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x4002D10, 0x4002D14, 0x4002D18, 0x4002D1C, 0x4002D20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x3004EED, 0x3004EF0, 0x3004EF3, 0x3004EF6, 0x3004EF9, 0x3004EFC, 0x3004EFF, 0x3004F02, 0x3004F05, 0x3004F08, 0x3004F0B, 0x3004F0E, 0x3004F11, 0x3004F14, 0x3004F17,
+	0x3004F1A, 0x3004F1D, 0x3004F20, 0x3004F23, 0x3004F26, 0x3004F29, 0x3004F2C, 0x3004F2F, 0x3004F32, 0x3004F35, 0x3004F38, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4004F3B, 0x4004F3F, 0x4004F43, 0x4004F47, 0x4004F4B, 0x4004F4F, 0x4004F53, 0x4004F57, 0x4004F5B, 0x4004F5F, 0x4004F63, 0x4004F67, 0x4004F6B, 0x4004F6F, 0x4004F73, 0x4004F77,
+	0x4004F7B, 0x4004F7F, 0x4004F83, 0x4004F87, 0x4004F8B, 0x4004F8F, 0x4004F93, 0x4004F97, 0x4004F9B, 0x4004F9F, 0x4004FA3, 0x4004FA7, 0x4004FAB, 0x4004FAF, 0x4004FB3, 0x4004FB7,
+	0x4004FBB, 0x4004FBF, 0x4004FC3, 0x4004FC7, 0x4004FCB, 0x4004FCF, 0x4004FD3, 0x4004FD7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4004FDB, 0x4004FDF, 0x4004FE3, 0x4004FE7, 0x4004FEB, 0x4004FEF, 0x4004FF3, 0x4004FF7, 0x4004FFB, 0x4004FFF, 0x4005003, 0x4005007, 0x400500B, 0x400500F, 0x4005013, 0x4005017,
+	0x400501B, 0x400501F, 0x4005023, 0x4005027, 0x400502B, 0x400502F, 0x4005033, 0x4005037, 0x400503B, 0x400503F, 0x4005043, 0x4005047, 0x400504B, 0x400504F, 0x4005053, 0x4005057,
+	0x400505B, 0x400505F, 0x4005063, 0x4005067, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x400506B, 0x400506F, 0x4005073, 0x4005077, 0x400507B, 0x400507F, 0x4005083, 0x4005087, 0x400508B, 0x400508F, 0x4005093, 0x4005097, 0x400509B, 0x400509F, 0x40050A3, 0x40050A7,
+	0x40050AB, 0x40050AF, 0x40050B3, 0x40050B7, 0x40050BB, 0x40050BF, 0x40050C3, 0x40050C7, 0x40050CB, 0x40050CF, 0x40050D3, 0x40050D7, 0x40050DB, 0x40050DF, 0x40050E3, 0x40050E7,
+	0x40050EB, 0x40050EF, 0x40050F3, 0x40050F7, 0x40050FB, 0x40050FF, 0x4005103, 0x4005107, 0x400510B, 0x400510F, 0x4005113, 0x4005117, 0x400511B, 0x400511F, 0x4005123, 0x4005127,
+	0x400512B, 0x400512F, 0x4005133, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+	0x4005137, 0x400513B, 0x400513F, 0x4005143, 0x4005147, 0x400514B, 0x400514F, 0x4005153, 0x4005157, 0x400515B, 0x400515F, 0x4005163, 0x4005167, 0x400516B, 0x400516F, 0x4005173,
+	0x4005177, 0x400517B, 0x400517F, 0x4005183, 0x4005187, 0x400518B, 0x400518F, 0x4005193, 0x4005197, 0x400519B, 0x400519F, 0x40051A3, 0x40051A7, 0x40051AB, 0x40051AF, 0x40051B3,
+	0x40051B7, 0x40051BB, 0x40051BF, 0x40051C3, 0x40051C7, 0x40051CB, 0x40051CF, 0x40051D3, 0x40051D7, 0x40051DB, 0x40051DF, 0x40051E3, 0x40051E7, 0x40051EB, 0x40051EF, 0x40051F3,
+	0x40051F7, 0x40051FB, 0x40051FF, 0x4005203, 0x4005207, 0x400520B, 0x400520F, 0x4005213, 0x4005217, 0x400521B, 0x400521F, 0x4005223, 0x4005227, 0x400522B, 0x400522F, 0x4005233,
+	0x4005237, 0x400523B, 0x400523F, 0x4005243, 0x4005247, 0x400524B, 0x400524F, 0x4005253, 0x4005257, 0x400525B, 0x400525F, 0x4005263, 0x4005267, 0x400526B, 0x400526F, 0x4005273,
+	0x4005277, 0x400527B, 0x400527F, 0x4005283, 0x4005287, 0x400528B, 0x400528F, 0x4005293, 0x4005297, 0x400529B, 0x400529F, 0x40052A3, 0x40052A7, 0x40052AB, 0x40052AF, 0x40052B3,
+	0x40052B7, 0x40052BB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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* CaseFoldingDataPtr = CaseFoldingData;
+
+const size_t UnicodeCompositionRecordCount = 941;
+const CompositionRecord UnicodeCompositionRecord[941] = {
+	{ 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 },
+	{ 0x1193500011930, 0x11938 },
+};
+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\x91\xA4\xB5\xF0\x91\xA4\xB0\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\xE4\xBB\xA4\xE5\x92\x8C"
+	"\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\xCA\x8D\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\x4D\x52\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\xE9\x85\x8D"
+	"\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\xEA\x9E\xAE"
+	"\xE2\xB1\xA2\xEA\x9E\xAD\xC6\x9C\xE2\xB1\xAE\xC6\x9D\xC6\x9F\xE2\xB1\xA4\xC6\xA6\xEA\x9F\x85\xC6\xA9"
+	"\xEA\x9E\xB1\xC6\xAE\xC9\x84\xC6\xB1\xC6\xB2\xC9\x85\xEA\x9E\xB2\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\xE1\xB2\x90\xE1\xB2\x91\xE1\xB2\x92\xE1\xB2\x93\xE1"
+	"\xB2\x94\xE1\xB2\x95\xE1\xB2\x96\xE1\xB2\x97\xE1\xB2\x98\xE1\xB2\x99\xE1\xB2\x9A\xE1\xB2\x9B\xE1\xB2"
+	"\x9C\xE1\xB2\x9D\xE1\xB2\x9E\xE1\xB2\x9F\xE1\xB2\xA0\xE1\xB2\xA1\xE1\xB2\xA2\xE1\xB2\xA3\xE1\xB2\xA4"
+	"\xE1\xB2\xA5\xE1\xB2\xA6\xE1\xB2\xA7\xE1\xB2\xA8\xE1\xB2\xA9\xE1\xB2\xAA\xE1\xB2\xAB\xE1\xB2\xAC\xE1"
+	"\xB2\xAD\xE1\xB2\xAE\xE1\xB2\xAF\xE1\xB2\xB0\xE1\xB2\xB1\xE1\xB2\xB2\xE1\xB2\xB3\xE1\xB2\xB4\xE1\xB2"
+	"\xB5\xE1\xB2\xB6\xE1\xB2\xB7\xE1\xB2\xB8\xE1\xB2\xB9\xE1\xB2\xBA\xE1\xB2\xBD\xE1\xB2\xBE\xE1\xB2\xBF"
+	"\xE1\x8F\xB0\xE1\x8F\xB1\xE1\x8F\xB2\xE1\x8F\xB3\xE1\x8F\xB4\xE1\x8F\xB5\xEA\x99\x8A\xEA\x9D\xBD\xE2"
+	"\xB1\xA3\xEA\x9F\x86\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\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\x9F\x84\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\xEA\x9E\xB4\xEA\x9E\xB6\xEA\x9E\xB8\xEA\x9E\xBA\xEA\x9E\xBC\xEA\x9E\xBE\xEA\x9F\x82\xEA\x9F"
+	"\x87\xEA\x9F\x89\xEA\x9F\xB5\xEA\x9E\xB3\xE1\x8E\xA0\xE1\x8E\xA1\xE1\x8E\xA2\xE1\x8E\xA3\xE1\x8E\xA4"
+	"\xE1\x8E\xA5\xE1\x8E\xA6\xE1\x8E\xA7\xE1\x8E\xA8\xE1\x8E\xA9\xE1\x8E\xAA\xE1\x8E\xAB\xE1\x8E\xAC\xE1"
+	"\x8E\xAD\xE1\x8E\xAE\xE1\x8E\xAF\xE1\x8E\xB0\xE1\x8E\xB1\xE1\x8E\xB2\xE1\x8E\xB3\xE1\x8E\xB4\xE1\x8E"
+	"\xB5\xE1\x8E\xB6\xE1\x8E\xB7\xE1\x8E\xB8\xE1\x8E\xB9\xE1\x8E\xBA\xE1\x8E\xBB\xE1\x8E\xBC\xE1\x8E\xBD"
+	"\xE1\x8E\xBE\xE1\x8E\xBF\xE1\x8F\x80\xE1\x8F\x81\xE1\x8F\x82\xE1\x8F\x83\xE1\x8F\x84\xE1\x8F\x85\xE1"
+	"\x8F\x86\xE1\x8F\x87\xE1\x8F\x88\xE1\x8F\x89\xE1\x8F\x8A\xE1\x8F\x8B\xE1\x8F\x8C\xE1\x8F\x8D\xE1\x8F"
+	"\x8E\xE1\x8F\x8F\xE1\x8F\x90\xE1\x8F\x91\xE1\x8F\x92\xE1\x8F\x93\xE1\x8F\x94\xE1\x8F\x95\xE1\x8F\x96"
+	"\xE1\x8F\x97\xE1\x8F\x98\xE1\x8F\x99\xE1\x8F\x9A\xE1\x8F\x9B\xE1\x8F\x9C\xE1\x8F\x9D\xE1\x8F\x9E\xE1"
+	"\x8F\x9F\xE1\x8F\xA0\xE1\x8F\xA1\xE1\x8F\xA2\xE1\x8F\xA3\xE1\x8F\xA4\xE1\x8F\xA5\xE1\x8F\xA6\xE1\x8F"
+	"\xA7\xE1\x8F\xA8\xE1\x8F\xA9\xE1\x8F\xAA\xE1\x8F\xAB\xE1\x8F\xAC\xE1\x8F\xAD\xE1\x8F\xAE\xE1\x8F\xAF"
+	"\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\x90\x92"
+	"\xB0\xF0\x90\x92\xB1\xF0\x90\x92\xB2\xF0\x90\x92\xB3\xF0\x90\x92\xB4\xF0\x90\x92\xB5\xF0\x90\x92\xB6"
+	"\xF0\x90\x92\xB7\xF0\x90\x92\xB8\xF0\x90\x92\xB9\xF0\x90\x92\xBA\xF0\x90\x92\xBB\xF0\x90\x92\xBC\xF0"
+	"\x90\x92\xBD\xF0\x90\x92\xBE\xF0\x90\x92\xBF\xF0\x90\x93\x80\xF0\x90\x93\x81\xF0\x90\x93\x82\xF0\x90"
+	"\x93\x83\xF0\x90\x93\x84\xF0\x90\x93\x85\xF0\x90\x93\x86\xF0\x90\x93\x87\xF0\x90\x93\x88\xF0\x90\x93"
+	"\x89\xF0\x90\x93\x8A\xF0\x90\x93\x8B\xF0\x90\x93\x8C\xF0\x90\x93\x8D\xF0\x90\x93\x8E\xF0\x90\x93\x8F"
+	"\xF0\x90\x93\x90\xF0\x90\x93\x91\xF0\x90\x93\x92\xF0\x90\x93\x93\xF0\x90\xB2\x80\xF0\x90\xB2\x81\xF0"
+	"\x90\xB2\x82\xF0\x90\xB2\x83\xF0\x90\xB2\x84\xF0\x90\xB2\x85\xF0\x90\xB2\x86\xF0\x90\xB2\x87\xF0\x90"
+	"\xB2\x88\xF0\x90\xB2\x89\xF0\x90\xB2\x8A\xF0\x90\xB2\x8B\xF0\x90\xB2\x8C\xF0\x90\xB2\x8D\xF0\x90\xB2"
+	"\x8E\xF0\x90\xB2\x8F\xF0\x90\xB2\x90\xF0\x90\xB2\x91\xF0\x90\xB2\x92\xF0\x90\xB2\x93\xF0\x90\xB2\x94"
+	"\xF0\x90\xB2\x95\xF0\x90\xB2\x96\xF0\x90\xB2\x97\xF0\x90\xB2\x98\xF0\x90\xB2\x99\xF0\x90\xB2\x9A\xF0"
+	"\x90\xB2\x9B\xF0\x90\xB2\x9C\xF0\x90\xB2\x9D\xF0\x90\xB2\x9E\xF0\x90\xB2\x9F\xF0\x90\xB2\xA0\xF0\x90"
+	"\xB2\xA1\xF0\x90\xB2\xA2\xF0\x90\xB2\xA3\xF0\x90\xB2\xA4\xF0\x90\xB2\xA5\xF0\x90\xB2\xA6\xF0\x90\xB2"
+	"\xA7\xF0\x90\xB2\xA8\xF0\x90\xB2\xA9\xF0\x90\xB2\xAA\xF0\x90\xB2\xAB\xF0\x90\xB2\xAC\xF0\x90\xB2\xAD"
+	"\xF0\x90\xB2\xAE\xF0\x90\xB2\xAF\xF0\x90\xB2\xB0\xF0\x90\xB2\xB1\xF0\x90\xB2\xB2\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\xF0\x96"
+	"\xB9\x80\xF0\x96\xB9\x81\xF0\x96\xB9\x82\xF0\x96\xB9\x83\xF0\x96\xB9\x84\xF0\x96\xB9\x85\xF0\x96\xB9"
+	"\x86\xF0\x96\xB9\x87\xF0\x96\xB9\x88\xF0\x96\xB9\x89\xF0\x96\xB9\x8A\xF0\x96\xB9\x8B\xF0\x96\xB9\x8C"
+	"\xF0\x96\xB9\x8D\xF0\x96\xB9\x8E\xF0\x96\xB9\x8F\xF0\x96\xB9\x90\xF0\x96\xB9\x91\xF0\x96\xB9\x92\xF0"
+	"\x96\xB9\x93\xF0\x96\xB9\x94\xF0\x96\xB9\x95\xF0\x96\xB9\x96\xF0\x96\xB9\x97\xF0\x96\xB9\x98\xF0\x96"
+	"\xB9\x99\xF0\x96\xB9\x9A\xF0\x96\xB9\x9B\xF0\x96\xB9\x9C\xF0\x96\xB9\x9D\xF0\x96\xB9\x9E\xF0\x96\xB9"
+	"\x9F\xF0\x9E\xA4\x80\xF0\x9E\xA4\x81\xF0\x9E\xA4\x82\xF0\x9E\xA4\x83\xF0\x9E\xA4\x84\xF0\x9E\xA4\x85"
+	"\xF0\x9E\xA4\x86\xF0\x9E\xA4\x87\xF0\x9E\xA4\x88\xF0\x9E\xA4\x89\xF0\x9E\xA4\x8A\xF0\x9E\xA4\x8B\xF0"
+	"\x9E\xA4\x8C\xF0\x9E\xA4\x8D\xF0\x9E\xA4\x8E\xF0\x9E\xA4\x8F\xF0\x9E\xA4\x90\xF0\x9E\xA4\x91\xF0\x9E"
+	"\xA4\x92\xF0\x9E\xA4\x93\xF0\x9E\xA4\x94\xF0\x9E\xA4\x95\xF0\x9E\xA4\x96\xF0\x9E\xA4\x97\xF0\x9E\xA4"
+	"\x98\xF0\x9E\xA4\x99\xF0\x9E\xA4\x9A\xF0\x9E\xA4\x9B\xF0\x9E\xA4\x9C\xF0\x9E\xA4\x9D\xF0\x9E\xA4\x9E"
+	"\xF0\x9E\xA4\x9F\xF0\x9E\xA4\xA0\xF0\x9E\xA4\xA1\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\xEA\xAD\xB0\xEA\xAD\xB1\xEA\xAD"
+	"\xB2\xEA\xAD\xB3\xEA\xAD\xB4\xEA\xAD\xB5\xEA\xAD\xB6\xEA\xAD\xB7\xEA\xAD\xB8\xEA\xAD\xB9\xEA\xAD\xBA"
+	"\xEA\xAD\xBB\xEA\xAD\xBC\xEA\xAD\xBD\xEA\xAD\xBE\xEA\xAD\xBF\xEA\xAE\x80\xEA\xAE\x81\xEA\xAE\x82\xEA"
+	"\xAE\x83\xEA\xAE\x84\xEA\xAE\x85\xEA\xAE\x86\xEA\xAE\x87\xEA\xAE\x88\xEA\xAE\x89\xEA\xAE\x8A\xEA\xAE"
+	"\x8B\xEA\xAE\x8C\xEA\xAE\x8D\xEA\xAE\x8E\xEA\xAE\x8F\xEA\xAE\x90\xEA\xAE\x91\xEA\xAE\x92\xEA\xAE\x93"
+	"\xEA\xAE\x94\xEA\xAE\x95\xEA\xAE\x96\xEA\xAE\x97\xEA\xAE\x98\xEA\xAE\x99\xEA\xAE\x9A\xEA\xAE\x9B\xEA"
+	"\xAE\x9C\xEA\xAE\x9D\xEA\xAE\x9E\xEA\xAE\x9F\xEA\xAE\xA0\xEA\xAE\xA1\xEA\xAE\xA2\xEA\xAE\xA3\xEA\xAE"
+	"\xA4\xEA\xAE\xA5\xEA\xAE\xA6\xEA\xAE\xA7\xEA\xAE\xA8\xEA\xAE\xA9\xEA\xAE\xAA\xEA\xAE\xAB\xEA\xAE\xAC"
+	"\xEA\xAE\xAD\xEA\xAE\xAE\xEA\xAE\xAF\xEA\xAE\xB0\xEA\xAE\xB1\xEA\xAE\xB2\xEA\xAE\xB3\xEA\xAE\xB4\xEA"
+	"\xAE\xB5\xEA\xAE\xB6\xEA\xAE\xB7\xEA\xAE\xB8\xEA\xAE\xB9\xEA\xAE\xBA\xEA\xAE\xBB\xEA\xAE\xBC\xEA\xAE"
+	"\xBD\xEA\xAE\xBE\xEA\xAE\xBF\xE1\x8F\xB8\xE1\x8F\xB9\xE1\x8F\xBA\xE1\x8F\xBB\xE1\x8F\xBC\xE1\x8F\xBD"
+	"\xE1\x83\x90\xE1\x83\x91\xE1\x83\x92\xE1\x83\x93\xE1\x83\x94\xE1\x83\x95\xE1\x83\x96\xE1\x83\x97\xE1"
+	"\x83\x98\xE1\x83\x99\xE1\x83\x9A\xE1\x83\x9B\xE1\x83\x9D\xE1\x83\x9E\xE1\x83\x9F\xE1\x83\xA0\xE1\x83"
+	"\xA1\xE1\x83\xA2\xE1\x83\xA3\xE1\x83\xA4\xE1\x83\xA5\xE1\x83\xA6\xE1\x83\xA7\xE1\x83\xA8\xE1\x83\xA9"
+	"\xE1\x83\xAA\xE1\x83\xAB\xE1\x83\xAC\xE1\x83\xAD\xE1\x83\xAE\xE1\x83\xAF\xE1\x83\xB0\xE1\x83\xB1\xE1"
+	"\x83\xB2\xE1\x83\xB3\xE1\x83\xB4\xE1\x83\xB5\xE1\x83\xB6\xE1\x83\xB7\xE1\x83\xB8\xE1\x83\xB9\xE1\x83"
+	"\xBA\xE1\x83\xBD\xE1\x83\xBE\xE1\x83\xBF\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\xEA\xAD\x93\xEA\x9E\xB5\xEA\x9E\xB7"
+	"\xEA\x9E\xB9\xEA\x9E\xBB\xEA\x9E\xBD\xEA\x9E\xBF\xEA\x9F\x83\xEA\x9E\x94\xE1\xB6\x8E\xEA\x9F\x88\xEA"
+	"\x9F\x8A\xEA\x9F\xB6\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\x90\x93\x98\xF0\x90\x93"
+	"\x99\xF0\x90\x93\x9A\xF0\x90\x93\x9B\xF0\x90\x93\x9C\xF0\x90\x93\x9D\xF0\x90\x93\x9E\xF0\x90\x93\x9F"
+	"\xF0\x90\x93\xA0\xF0\x90\x93\xA1\xF0\x90\x93\xA2\xF0\x90\x93\xA3\xF0\x90\x93\xA4\xF0\x90\x93\xA5\xF0"
+	"\x90\x93\xA6\xF0\x90\x93\xA7\xF0\x90\x93\xA8\xF0\x90\x93\xA9\xF0\x90\x93\xAA\xF0\x90\x93\xAB\xF0\x90"
+	"\x93\xAC\xF0\x90\x93\xAD\xF0\x90\x93\xAE\xF0\x90\x93\xAF\xF0\x90\x93\xB0\xF0\x90\x93\xB1\xF0\x90\x93"
+	"\xB2\xF0\x90\x93\xB3\xF0\x90\x93\xB4\xF0\x90\x93\xB5\xF0\x90\x93\xB6\xF0\x90\x93\xB7\xF0\x90\x93\xB8"
+	"\xF0\x90\x93\xB9\xF0\x90\x93\xBA\xF0\x90\x93\xBB\xF0\x90\xB3\x80\xF0\x90\xB3\x81\xF0\x90\xB3\x82\xF0"
+	"\x90\xB3\x83\xF0\x90\xB3\x84\xF0\x90\xB3\x85\xF0\x90\xB3\x86\xF0\x90\xB3\x87\xF0\x90\xB3\x88\xF0\x90"
+	"\xB3\x89\xF0\x90\xB3\x8A\xF0\x90\xB3\x8B\xF0\x90\xB3\x8C\xF0\x90\xB3\x8D\xF0\x90\xB3\x8E\xF0\x90\xB3"
+	"\x8F\xF0\x90\xB3\x90\xF0\x90\xB3\x91\xF0\x90\xB3\x92\xF0\x90\xB3\x93\xF0\x90\xB3\x94\xF0\x90\xB3\x95"
+	"\xF0\x90\xB3\x96\xF0\x90\xB3\x97\xF0\x90\xB3\x98\xF0\x90\xB3\x99\xF0\x90\xB3\x9A\xF0\x90\xB3\x9B\xF0"
+	"\x90\xB3\x9C\xF0\x90\xB3\x9D\xF0\x90\xB3\x9E\xF0\x90\xB3\x9F\xF0\x90\xB3\xA0\xF0\x90\xB3\xA1\xF0\x90"
+	"\xB3\xA2\xF0\x90\xB3\xA3\xF0\x90\xB3\xA4\xF0\x90\xB3\xA5\xF0\x90\xB3\xA6\xF0\x90\xB3\xA7\xF0\x90\xB3"
+	"\xA8\xF0\x90\xB3\xA9\xF0\x90\xB3\xAA\xF0\x90\xB3\xAB\xF0\x90\xB3\xAC\xF0\x90\xB3\xAD\xF0\x90\xB3\xAE"
+	"\xF0\x90\xB3\xAF\xF0\x90\xB3\xB0\xF0\x90\xB3\xB1\xF0\x90\xB3\xB2\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\xF0\x96\xB9\xA0\xF0\x96"
+	"\xB9\xA1\xF0\x96\xB9\xA2\xF0\x96\xB9\xA3\xF0\x96\xB9\xA4\xF0\x96\xB9\xA5\xF0\x96\xB9\xA6\xF0\x96\xB9"
+	"\xA7\xF0\x96\xB9\xA8\xF0\x96\xB9\xA9\xF0\x96\xB9\xAA\xF0\x96\xB9\xAB\xF0\x96\xB9\xAC\xF0\x96\xB9\xAD"
+	"\xF0\x96\xB9\xAE\xF0\x96\xB9\xAF\xF0\x96\xB9\xB0\xF0\x96\xB9\xB1\xF0\x96\xB9\xB2\xF0\x96\xB9\xB3\xF0"
+	"\x96\xB9\xB4\xF0\x96\xB9\xB5\xF0\x96\xB9\xB6\xF0\x96\xB9\xB7\xF0\x96\xB9\xB8\xF0\x96\xB9\xB9\xF0\x96"
+	"\xB9\xBA\xF0\x96\xB9\xBB\xF0\x96\xB9\xBC\xF0\x96\xB9\xBD\xF0\x96\xB9\xBE\xF0\x96\xB9\xBF\xF0\x9E\xA4"
+	"\xA2\xF0\x9E\xA4\xA3\xF0\x9E\xA4\xA4\xF0\x9E\xA4\xA5\xF0\x9E\xA4\xA6\xF0\x9E\xA4\xA7\xF0\x9E\xA4\xA8"
+	"\xF0\x9E\xA4\xA9\xF0\x9E\xA4\xAA\xF0\x9E\xA4\xAB\xF0\x9E\xA4\xAC\xF0\x9E\xA4\xAD\xF0\x9E\xA4\xAE\xF0"
+	"\x9E\xA4\xAF\xF0\x9E\xA4\xB0\xF0\x9E\xA4\xB1\xF0\x9E\xA4\xB2\xF0\x9E\xA4\xB3\xF0\x9E\xA4\xB4\xF0\x9E"
+	"\xA4\xB5\xF0\x9E\xA4\xB6\xF0\x9E\xA4\xB7\xF0\x9E\xA4\xB8\xF0\x9E\xA4\xB9\xF0\x9E\xA4\xBA\xF0\x9E\xA4"
+	"\xBB\xF0\x9E\xA4\xBC\xF0\x9E\xA4\xBD\xF0\x9E\xA4\xBE\xF0\x9E\xA4\xBF\xF0\x9E\xA5\x80\xF0\x9E\xA5\x81"
+	"\xF0\x9E\xA5\x82\xF0\x9E\xA5\x83\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 = 21536;
+ 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;
+}