diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4f15289..47e610c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,29 +1,46 @@ -on: [push, pull_request] +on: + push: + branches: [master] + pull_request: name: Test +permissions: + contents: read jobs: test: strategy: matrix: - go-version: [1.20.x, 1.21.x] - os: [ubuntu-latest, macos-latest, windows-latest] - runs-on: ${{ matrix.os }} + go-version: [1.21.x, 1.22.x] + platform: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.platform }} steps: - - name: Install Go - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go-version }} - - name: Checkout code - uses: actions/checkout@v2 - - name: Test Linux - if: matrix.os == 'ubuntu-latest' - run: go test -race ./libwebp -coverprofile=coverage.txt -covermode=atomic - - name: Test Other - if: matrix.os != 'ubuntu-latest' - run: go test ./libwebp - - name: Upload coverage - if: success() && matrix.os == 'ubuntu-latest' - run: | - curl -s https://codecov.io/bash | bash - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - shell: bash \ No newline at end of file + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go-version }} + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + shell: bash + - name: Install golint + run: go install golang.org/x/lint/golint@latest + shell: bash + - name: Update PATH + run: echo "$(go env GOPATH)/bin" >> $GITHUB_PATH + shell: bash + - name: Checkout code + uses: actions/checkout@v4 + - name: Fmt + if: matrix.platform != 'windows-latest' # :( + run: "diff <(gofmt -d .) <(printf '')" + shell: bash + - name: Vet + run: go vet ./... + - name: Staticcheck + run: staticcheck ./... + - name: Lint + run: golint ./... + - name: Test + run: go test -race ./libwebp -coverprofile=coverage.txt -covermode=atomic + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.5.0 + with: + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/README.md b/README.md index 1cbb524..af1054e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/bep/gowebp)](https://goreportcard.com/report/github.com/bep/gowebp) -[![libwebp Version](https://img.shields.io/badge/libwebp-v1.3.2-blue)](https://github.com/webmproject/libwebp) +[![libwebp Version](https://img.shields.io/badge/libwebp-v1.4.0-blue)](https://github.com/webmproject/libwebp) [![codecov](https://codecov.io/gh/bep/gowebp/branch/master/graph/badge.svg)](https://codecov.io/gh/bep/gowebp) [![GoDoc](https://godoc.org/github.com/bep/gowebp/libwebp?status.svg)](https://godoc.org/github.com/bep/gowebp/libwebp) diff --git a/gen/main.go b/gen/main.go index f67d20c..7f52921 100644 --- a/gen/main.go +++ b/gen/main.go @@ -4,7 +4,6 @@ package main import ( "fmt" - "io/ioutil" "log" "os" "path" @@ -30,7 +29,7 @@ func main() { // directory. // // The custom bindings are named with a "a__" prefix. Keep those. - fis, err := ioutil.ReadDir(dstDir) + fis, err := os.ReadDir(dstDir) if err != nil { log.Fatal(err) } @@ -61,7 +60,7 @@ func main() { filename = strings.TrimPrefix(filename, "/") target := filepath.Join(dstDir, fi.Name()) - if err := ioutil.WriteFile(target, []byte(fmt.Sprintf(`#ifndef LIBWEBP_NO_SRC + if err := os.WriteFile(target, []byte(fmt.Sprintf(`#ifndef LIBWEBP_NO_SRC #include "../../libwebp_src/%s" #endif `, filename)), 0o644); err != nil { @@ -70,7 +69,6 @@ func main() { return nil }) - if err != nil { log.Fatal(err) } diff --git a/go.mod b/go.mod index 019b8a5..97246e2 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/bep/gowebp -go 1.16 +go 1.20 require golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb // indirect diff --git a/internal/libwebp/a__encoder.go b/internal/libwebp/a__encoder.go index 0df2124..cf6db4c 100644 --- a/internal/libwebp/a__encoder.go +++ b/internal/libwebp/a__encoder.go @@ -105,7 +105,6 @@ type ( // // Any src that isn't one of *image.RGBA, *image.NRGBA, or *image.Gray // will be converted to *image.NRGBA using draw.Draw first. -// func Encode(w io.Writer, src image.Image, o webpoptions.EncodingOptions) error { config, err := encodingOptionsToCConfig(o) if err != nil { diff --git a/internal/libwebp/palette.c b/internal/libwebp/palette.c new file mode 100644 index 0000000..ea750c2 --- /dev/null +++ b/internal/libwebp/palette.c @@ -0,0 +1,3 @@ +#ifndef LIBWEBP_NO_SRC +#include "../../libwebp_src/src/utils/palette.c" +#endif diff --git a/internal/libwebp/palette.h b/internal/libwebp/palette.h new file mode 100644 index 0000000..d8bc3a5 --- /dev/null +++ b/internal/libwebp/palette.h @@ -0,0 +1,3 @@ +#ifndef LIBWEBP_NO_SRC +#include "../../libwebp_src/src/utils/palette.h" +#endif diff --git a/libwebp/encode.go b/libwebp/encode.go index 370ac61..66f7177 100644 --- a/libwebp/encode.go +++ b/libwebp/encode.go @@ -13,7 +13,6 @@ import ( // // Any src that isn't one of *image.RGBA, *image.NRGBA, or *image.Gray // will be converted to *image.NRGBA using draw.Draw first. -// func Encode(w io.Writer, src image.Image, o webpoptions.EncodingOptions) error { return libwebp.Encode(w, src, o) } diff --git a/libwebp/encode_test.go b/libwebp/encode_test.go index 4e7dee0..6456edb 100644 --- a/libwebp/encode_test.go +++ b/libwebp/encode_test.go @@ -6,10 +6,8 @@ import ( "image" "image/draw" "image/jpeg" - _ "image/jpeg" _ "image/png" "io" - "io/ioutil" "os" "path/filepath" "runtime" @@ -108,7 +106,7 @@ func TestEncodeLongRunning(t *testing.T) { t.Fatal(err) } - if err = Encode(ioutil.Discard, img, test.opts); err != nil { + if err = Encode(io.Discard, img, test.opts); err != nil { t.Fatal(err) } } @@ -138,7 +136,7 @@ func BenchmarkEncode(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - if err = Encode(ioutil.Discard, imgrgba, test.opts); err != nil { + if err = Encode(io.Discard, imgrgba, test.opts); err != nil { b.Fatal(err) } } @@ -163,7 +161,7 @@ func BenchmarkEncodeJpeg(b *testing.B) { } for i := 0; i < b.N; i++ { - if err = jpeg.Encode(ioutil.Discard, img, opts); err != nil { + if err = jpeg.Encode(io.Discard, img, opts); err != nil { b.Fatal(err) } } diff --git a/libwebp_src/AUTHORS b/libwebp_src/AUTHORS index 8359b20..4cbe976 100644 --- a/libwebp_src/AUTHORS +++ b/libwebp_src/AUTHORS @@ -2,6 +2,8 @@ Contributors: - Aidan O'Loan (aidanol at gmail dot com) - Alan Browning (browning at google dot com) - Alexandru Ardelean (ardeleanalex at gmail dot com) +- Anuraag Agrawal (anuraaga at gmail dot com) +- Arthur Eubanks (aeubanks at google dot com) - Brian Ledger (brianpl at google dot com) - Charles Munger (clm at google dot com) - Cheng Yi (cyi at google dot com) @@ -19,6 +21,8 @@ Contributors: - Jehan (jehan at girinstud dot io) - Jeremy Maitin-Shepard (jbms at google dot com) - Johann Koenig (johann dot koenig at duck dot com) +- Jonathan Grant (jgrantinfotech at gmail dot com) +- Jonliu1993 (13720414433 at 163 dot com) - Jovan Zelincevic (jovan dot zelincevic at imgtec dot com) - Jyrki Alakuijala (jyrki at google dot com) - Konstantin Ivlev (tomskside at gmail dot com) @@ -28,13 +32,16 @@ Contributors: - Marcin Kowalczyk (qrczak at google dot com) - Martin Olsson (mnemo at minimum dot se) - Maryla Ustarroz-Calonge (maryla at google dot com) +- Masahiro Hanada (hanada at atmark-techno dot com) - Mikołaj Zalewski (mikolajz at google dot com) - Mislav Bradac (mislavm at google dot com) +- natewood (natewood at fb dot com) - Nico Weber (thakis at chromium dot org) - Noel Chromium (noel at chromium dot org) - Nozomi Isozaki (nontan at pixiv dot co dot jp) - Oliver Wolff (oliver dot wolff at qt dot io) - Owen Rodley (orodley at google dot com) +- Ozkan Sezer (sezeroz at gmail dot com) - Parag Salasakar (img dot mips1 at gmail dot com) - Pascal Massimino (pascal dot massimino at gmail dot com) - Paweł Hajdan, Jr (phajdan dot jr at chromium dot org) diff --git a/libwebp_src/Android.mk b/libwebp_src/Android.mk index 9d16f08..f1e9ad8 100644 --- a/libwebp_src/Android.mk +++ b/libwebp_src/Android.mk @@ -164,6 +164,7 @@ utils_dec_srcs := \ src/utils/color_cache_utils.c \ src/utils/filters_utils.c \ src/utils/huffman_utils.c \ + src/utils/palette.c \ src/utils/quant_levels_dec_utils.c \ src/utils/random_utils.c \ src/utils/rescaler_utils.c \ diff --git a/libwebp_src/CMakeLists.txt b/libwebp_src/CMakeLists.txt index ad5e14c..b785a8e 100644 --- a/libwebp_src/CMakeLists.txt +++ b/libwebp_src/CMakeLists.txt @@ -51,6 +51,8 @@ option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces." OFF) set(WEBP_BITTRACE "0" CACHE STRING "Bit trace mode (0=none, 1=bit, 2=bytes)") set_property(CACHE WEBP_BITTRACE PROPERTY STRINGS 0 1 2) +option(WEBP_ENABLE_WUNUSED_RESULT "Add [[nodiscard]] to some functions. \ + CMake must be at least 3.21 to force C23" OFF) if(WEBP_LINK_STATIC) if(WIN32) @@ -133,7 +135,7 @@ if(WEBP_UNICODE) add_definitions(-DUNICODE -D_UNICODE) endif() -if(MSVC AND BUILD_SHARED_LIBS) +if(WIN32 AND BUILD_SHARED_LIBS) add_definitions(-DWEBP_DLL) endif() @@ -161,7 +163,20 @@ if(MSVC) set(CMAKE_STATIC_LIBRARY_PREFIX "${webp_libname_prefix}") endif() -set(CMAKE_C_VISIBILITY_PRESET hidden) +if(NOT WIN32) + set(CMAKE_C_VISIBILITY_PRESET hidden) +endif() + +if(WEBP_ENABLE_WUNUSED_RESULT) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21.0) + set(CMAKE_C_STANDARD 23) + else() + unset(CMAKE_C_STANDARD) + add_compile_options($<$:-std=gnu2x>) + endif() + add_compile_options(-Wunused-result) + add_definitions(-DWEBP_ENABLE_NODISCARD=1) +endif() # ############################################################################## # Android only. @@ -463,6 +478,7 @@ endif() if(WEBP_BUILD_ANIM_UTILS OR WEBP_BUILD_CWEBP OR WEBP_BUILD_DWEBP + OR WEBP_BUILD_EXTRAS OR WEBP_BUILD_GIF2WEBP OR WEBP_BUILD_IMG2WEBP OR WEBP_BUILD_VWEBP @@ -499,6 +515,8 @@ if(WEBP_BUILD_ANIM_UTILS TARGET exampleutil imageioutil imagedec imageenc PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/src) + target_include_directories(imagedec PRIVATE ${WEBP_DEP_IMG_INCLUDE_DIRS}) + target_include_directories(imageenc PRIVATE ${WEBP_DEP_IMG_INCLUDE_DIRS}) endif() if(WEBP_BUILD_DWEBP) @@ -638,15 +656,30 @@ if(WEBP_BUILD_EXTRAS) ${CMAKE_CURRENT_BINARY_DIR}) # vwebp_sdl - find_package(SDL) - if(WEBP_BUILD_VWEBP AND SDL_FOUND) + find_package(SDL2 QUIET) + if(WEBP_BUILD_VWEBP AND SDL2_FOUND) add_executable(vwebp_sdl ${VWEBP_SDL_SRCS}) - target_link_libraries(vwebp_sdl ${SDL_LIBRARY} imageioutil webp) + target_link_libraries(vwebp_sdl ${SDL2_LIBRARIES} imageioutil webp) target_include_directories( vwebp_sdl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/src ${SDL_INCLUDE_DIR}) + ${CMAKE_CURRENT_BINARY_DIR}/src ${SDL2_INCLUDE_DIRS}) set(WEBP_HAVE_SDL 1) target_compile_definitions(vwebp_sdl PUBLIC WEBP_HAVE_SDL) + + set(CMAKE_REQUIRED_INCLUDES "${SDL2_INCLUDE_DIRS}") + check_c_source_compiles( + " + #define SDL_MAIN_HANDLED + #include \"SDL.h\" + int main(void) { + return 0; + } + " + HAVE_JUST_SDL_H) + set(CMAKE_REQUIRED_INCLUDES) + if(HAVE_JUST_SDL_H) + target_compile_definitions(vwebp_sdl PRIVATE WEBP_HAVE_JUST_SDL_H) + endif() endif() endif() @@ -661,31 +694,44 @@ if(WEBP_BUILD_WEBP_JS) else() set(emscripten_stack_size "-sTOTAL_STACK=5MB") endif() + find_package(SDL2 REQUIRED) # wasm2js does not support SIMD. if(NOT WEBP_ENABLE_SIMD) # JavaScript version add_executable(webp_js ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c) - target_link_libraries(webp_js webpdecoder SDL) + target_link_libraries(webp_js webpdecoder SDL2) target_include_directories(webp_js PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set(WEBP_HAVE_SDL 1) set_target_properties( webp_js - PROPERTIES LINK_FLAGS "-sWASM=0 ${emscripten_stack_size} \ + PROPERTIES + # Emscripten puts -sUSE_SDL2=1 in this variable, though it's needed at + # compile time to ensure the headers are downloaded. + COMPILE_OPTIONS "${SDL2_LIBRARIES}" + LINK_FLAGS + "-sWASM=0 ${emscripten_stack_size} \ -sEXPORTED_FUNCTIONS=_WebPToSDL -sINVOKE_RUN=0 \ - -sEXPORTED_RUNTIME_METHODS=cwrap") + -sEXPORTED_RUNTIME_METHODS=cwrap ${SDL2_LIBRARIES} \ + -sALLOW_MEMORY_GROWTH") set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp) target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL) endif() # WASM version add_executable(webp_wasm ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c) - target_link_libraries(webp_wasm webpdecoder SDL) + target_link_libraries(webp_wasm webpdecoder SDL2) target_include_directories(webp_wasm PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties( webp_wasm - PROPERTIES LINK_FLAGS "-sWASM=1 ${emscripten_stack_size} \ + PROPERTIES + # Emscripten puts -sUSE_SDL2=1 in this variable, though it's needed at + # compile time to ensure the headers are downloaded. + COMPILE_OPTIONS "${SDL2_LIBRARIES}" + LINK_FLAGS + "-sWASM=1 ${emscripten_stack_size} \ -sEXPORTED_FUNCTIONS=_WebPToSDL -sINVOKE_RUN=0 \ - -sEXPORTED_RUNTIME_METHODS=cwrap") + -sEXPORTED_RUNTIME_METHODS=cwrap ${SDL2_LIBRARIES} \ + -sALLOW_MEMORY_GROWTH") target_compile_definitions(webp_wasm PUBLIC EMSCRIPTEN WEBP_HAVE_SDL) target_compile_definitions(webpdspdecode PUBLIC EMSCRIPTEN) diff --git a/libwebp_src/ChangeLog b/libwebp_src/ChangeLog index 33ec486..e0d920e 100644 --- a/libwebp_src/ChangeLog +++ b/libwebp_src/ChangeLog @@ -1,21 +1,171 @@ +8a6a55bb update NEWS +cf7c5a5d provide a way to opt-out/override WEBP_NODISCARD +cc34288a update ChangeLog (tag: v1.4.0-rc1) +f13c0886 NEWS: fix date +74555950 Merge "vwebp: fix window title when options are given" into 1.4.0 +d781646c vwebp: fix window title when options are given +c2e394de update NEWS +f6d15cb7 bump version to 1.4.0 +57c388b8 update AUTHORS +b3d1b2cb Merge changes I26f4aa22,I83386b6c,I320ed1a2 into main +07216886 webp-container-spec: fix VP8 chunk ref ('VP8'->'VP8 ') +f88666eb webp_js/*.html: fix canvas mapping +e2c8f233 cmake,wasm: simplify SDL2 related flags +d537cd37 cmake: fix vwebp_sdl compile w/libsdl-org release +6c484cbf CMakeLists.txt: add missing WEBP_BUILD_EXTRAS check +7b0bc235 man/cwebp.1: add more detail to -partition_limit +3c0011bb WebPMuxGetChunk: add an assert +955a3d14 Merge "muxread,MuxGet: add an assert" into main +00abc000 muxread,MuxGet: add an assert +40e85a0b Have the window title reflect the filename. +1bf46358 man/cwebp.1: clarify -pass > 1 behavior w/o -size/-psnr +eba03acb webp-container-spec: replace 'above' with 'earlier' +a16d30cb webp-container-spec: clarify chunk order requirements +8a7e9112 Merge "CMakeLists.txt: apply cmake-format" into main +7fac6c1b Merge "Copy C code to not have multiplication overflow" into main +e2922e43 Merge "Check for the presence of the ANDROID_ABI variable" into main +501d9274 Copy C code to not have multiplication overflow +fba7d62e CMakeLists.txt: apply cmake-format +661c1b66 Merge "windows exports: use dllexport attribute, instead of visibility." into main +8487860a windows exports: use dllexport attribute, instead of visibility. +8ea678b9 webp/mux.h: data lifetime note w/copy_data=0 +79e05c7f Check for the presence of the ANDROID_ABI variable +45f995a3 Expose functions for managing non-image chunks on WebPAnimEncoder +1fb9f3dc gifdec: fix ErrorGIFNotAvailable() declaration +4723db65 cosmetics: s/SANITY_CHECK/DCHECK/ +f4b9bc9e clear -Wextra-semi-stmt warnings +713982b8 Limit animdecoder_fuzzer to 320MB +cbe825e4 cmake: fix sharpyuv simd files' build +f99305e9 Makefile.vc: add ARM64 support +5efd6300 mv SharpYuvEstimate420Risk to extras/ +e78e924f Makefile.vc: add sharpyuv_risk_table.obj +d7a0506d Add YUV420 riskiness metric. +89c5b917 Merge "BuildHuffmanTable check sorted[] array bounds before writing" into main +34c80749 Remove alpha encoding pessimization. +13d9c30b Add a WEBP_NODISCARD +24d7f9cb Switch code to SDL2. +0b56dedc BuildHuffmanTable check sorted[] array bounds before writing +a429c0de sharpyuv: convert some for() to do/while +f0cd7861 DoSharpArgbToYuv: remove constant from loop +339231cc SharpYuvConvertWithOptions,cosmetics: fix formatting +307071f1 Remove medium/large code model-specific inline asm +deadc339 Fix transfer functions where toGamma and toLinear are swapped. +e7b78d43 Merge "Fix bug in FromLinearLog100." into main +15a1309e Merge "webp-lossless-bitstream-spec: delete extra blank line" into main +54ca9752 Fix bug in FromLinearLog100. +d2cb2d8c Dereference after NULL check. +e9d50107 webp-lossless-bitstream-spec: delete extra blank line +78657971 Merge changes Ief442c90,Ie6e9c9a5 into main +e30a5884 webp-lossless-bitstream-spec: update variable names +09ca1368 Merge "webp-container-spec: change assert to MUST be TRUE" into main +38cb4fc0 iosbuild,xcframeworkbuild: add SharpYuv framework +40afa926 webp-lossless-bitstream-spec: simplify abstract +9db21143 webp-container-spec: change assert to MUST be TRUE +cdbf88ae Fix typo in API docs for incremental decoding +05c46984 Reformat vcpkg build instructions. +8534f539 Merge "Never send VP8_STATUS_SUSPENDED back in non-incremental." into main +35e197bd Never send VP8_STATUS_SUSPENDED back in non-incremental. +61441425 Add vcpkg installation instructions +dce8397f Fix next is invalid pointer when WebPSafeMalloc fails +57c58105 Cmake: wrong public macro WEBP_INCLUDE_DIRS +c1ffd9ac Merge "vp8l_enc: fix non-C90 code" into main +a3965948 Merge changes If628bb93,Ic79f6309,I45f0db23 into main +f80e9b7e vp8l_enc: fix non-C90 code +accd141d Update lossless spec for two simple codes. +ac17ffff Fix non-C90 code. +433c7dca Fix static analyzer warnings. +5fac76cf Merge tag 'v1.3.2' +ca332209 update ChangeLog (tag: v1.3.2) 1ace578c update NEWS 63234c42 bump version to 1.3.2 +a35ea50d Add a fuzzer for ReadHuffmanCodes +95ea5226 Fix invalid incremental decoding check. 2af26267 Fix OOB write in BuildHuffmanTable. +902bc919 Fix OOB write in BuildHuffmanTable. +7ba44f80 Homogenize "__asm__ volatile" vs "asm volatile" +68e27135 webp-container-spec: reorder example chunk layout +943b932a Merge changes I6a4d0a04,Ibc37b91e into main +1cc94f95 decode.h: wrap idec example in /* */ +63acdd1e decode.h: fix decode example +aac5c5d0 ReadHuffmanCode: rm redundant num code lengths check +a2de25f6 webp-lossless-bitstream-spec: normalize list item case +68820f0e webp-lossless-bitstream-spec: normalize pixel ref +cdb31aa8 webp-lossless-bitstream-spec: add missing periods +0535a8cf webp-lossless-bitstream-spec: fix grammar +b6c4ce26 normalize numbered list item format +dd7364c3 Merge "palette.c: fix msvc warnings" into main +c63c5df6 palette.c: fix msvc warnings +0a2cad51 webp-container-spec: move terms from intro section +dd88d2ff webp-lossless-bitstream-spec: color_cache -> color cache +6e750547 Merge changes I644d7d39,Icf05491e,Ic02e6652,I63b11258 into main +67a7cc2b webp-lossless-bitstream-spec: fix code blocks +1432ebba Refactor palette sorting computation. +cd436142 webp-lossless-bitstream-spec: block -> chunk +3cb66f64 webp-lossless-bitstream-spec: add some missing commas +56471a53 webp-lossless-bitstream-spec: normalize item text in 5.1 +af7fbfd2 vp8l_dec,ReadTransform: improve error status reporting +7d8e0896 vp8l_dec: add VP8LSetError() +a71ce1cf animencoder_fuzzer: fix error check w/Nallocfuzz +e94b36d6 webp-lossless-bitstream-spec: relocate details from 5.1 +84628e56 webp-lossless-bitstream-spec: clarify image width changes +ee722997 alpha_dec: add missing VP8SetError() +0081693d enc_dec_fuzzer: use WebPDecode() +0fcb311c enc_dec_fuzzer: fix WebPEncode/pic.error_code check +982c177c webp-lossless-bitstream-spec: fix struct member refs +56cf5625 webp-lossless-bitstream-spec: use RFC 7405 for ABNF +6c6b3fd3 webp-lossless-bitstream-spec,cosmetics: delete blank lines +29b9eb15 Merge changes Id56ca4fd,I662bd1d7 into main +47c0af8d ReadHuffmanCodes: rm max_alphabet_size calc +b92deba3 animencoder_fuzzer: no WebPAnimEncoderAssemble check w/nallocfuzz +6be9bf8b animencoder_fuzzer: fix leak on alloc failure +5c965e55 vp8l_dec,cosmetics: add some /*param=*/ comments +e4fc2f78 webp-lossless-bitstream-spec: add validity note for max_symbol +71916726 webp-lossless-bitstream-spec: fix max_symbol definition +eac3bd5c Have the palette code be in its own file. +e2c85878 Add an initializer for the SharpYuvOptions struct. +4222b006 Merge tag 'v1.3.1' +25d94f47 Implement more transfer functions in libsharpyuv +2153a679 Merge changes Id0300937,I5dba5ccf,I57bb68e0,I2dba7b4e,I172aca36, ... into main +4298e976 webp-lossless-bitstream-spec: add PredictorTransformOutput +cd7e02be webp-lossless-bitstream-spec: fix RIFF-header ABNF +6c3845f9 webp-lossless-bitstream-spec: split LZ77 Backward Ref section +7f1b6799 webp-lossless-bitstream-spec: split Meta Prefix Codes section +7b634d8f webp-lossless-bitstream-spec: note transform order +6d6d4915 webp-lossless-bitstream-spec: update transformations text fd7bb21c update ChangeLog (tag: v1.3.1-rc2, tag: v1.3.1) e1adea50 update NEWS +6b1c722a lossless_common.h,cosmetics: fix a typo +08d60d60 webp-lossless-bitstream-spec: split code length section +7a12afcc webp-lossless-bitstream-spec: rm unused anchor 43393320 enc/*: normalize WebPEncodingSetError() calls 287fdefe enc/*: add missing WebPEncodingSetError() calls c3bd7cff EncodeAlphaInternal: add missing error check +14a9dbfb webp-lossless-bitstream-spec: refine single node text +64819c7c Implement ExtractGreen_SSE2 d49cfbb3 vp8l_enc,WriteImage: add missing error check 2e5a9ec3 muxread,MuxImageParse: add missing error checks ebb6f949 cmake,emscripten: explicitly set stack size 59a2b1f9 WebPDecodeYUV: check u/v/stride/uv_stride ptrs 8e965ccb Call png_get_channels() to see if image has alpha +fe80fbbd webp-container-spec: add some missing commas +e8ed3176 Merge "treat FILTER_NONE as a regular Unfilter[] call" into main +03a7a048 webp-lossless-bitstream-spec: rm redundant statement +c437c7aa webp-lossless-bitstream-spec: mv up prefix code group def +e4f17a31 webp-lossless-bitstream-spec: fix section reference +e2ecd5e9 webp-lossless-bitstream-spec: clarify ABNF syntax +8b55425a webp-lossless-bitstream-spec: refine pixel copy text +29c9f2d4 webp-lossless-bitstream-spec: minor wording updates +6b02f660 treat FILTER_NONE as a regular Unfilter[] call +7f75c91c webp-container-spec: fix location of informative msg +f6499943 webp-container-spec: consistently quote FourCCs +49918af3 webp-container-spec: minor wording updates 7f0a3419 update ChangeLog (tag: v1.3.1-rc1) bab7efbe update NEWS 7138bf8f bump version to 1.3.1 435b4ded update AUTHORS 47351229 update .mailmap +46bc4fc9 Merge "Switch ExtraCost to ints and implement it in SSE." into main +828b4ce0 Switch ExtraCost to ints and implement it in SSE. ff6c7f4e CONTRIBUTING.md: add C style / cmake-format notes dd530437 add .cmake-format.py adbe2cb1 cmake,cosmetics: apply cmake-format @@ -1213,7 +1363,7 @@ b016cb91 NEON: faster fancy upsampling f04eb376 Merge tag 'v0.5.2' 341d711c NEON: 5% faster conversion to RGB565 and RGBA4444 abb54827 remove Clang warnings with unused arch arguments. -ece9684f update ChangeLog (tag: v0.5.2-rc2, tag: v0.5.2, origin/0.5.2) +ece9684f update ChangeLog (tag: v0.5.2-rc2, tag: v0.5.2) aa7744ca anim_util: quiet implicit conv warnings in 32-bit d9120271 jpegdec: correct ContextFill signature 24eb3940 Remove some errors when compiling the code as C++. @@ -1500,7 +1650,7 @@ bbb6ecd9 Merge "Add MSA optimized distortion functions" c0991a14 io,EmitRescaledAlphaYUV: factor out a common expr 48bf5ed1 build.gradle: remove tab bfef6c9f Merge tag 'v0.5.1' -3d97bb75 update ChangeLog (tag: v0.5.1, origin/0.5.1) +3d97bb75 update ChangeLog (tag: v0.5.1) deb54d91 Clarify the expected 'config' lifespan in WebPIDecode() 435308e0 Add MSA optimized encoder transform functions dce64bfa Add MSA optimized alpha filter functions diff --git a/libwebp_src/Makefile.vc b/libwebp_src/Makefile.vc index cb6b7a9..84e9a5d 100644 --- a/libwebp_src/Makefile.vc +++ b/libwebp_src/Makefile.vc @@ -12,6 +12,8 @@ LIBSHARPYUV_BASENAME = libsharpyuv ARCH = x86 !ELSE IF ! [ cl 2>&1 | find "x64" > NUL ] ARCH = x64 +!ELSE IF ! [ cl 2>&1 | find "ARM64" > NUL ] +ARCH = ARM64 !ELSE IF ! [ cl 2>&1 | find "ARM" > NUL ] ARCH = ARM !ELSE @@ -321,6 +323,7 @@ ENC_OBJS = \ EXTRAS_OBJS = \ $(DIROBJ)\extras\extras.obj \ $(DIROBJ)\extras\quality_estimate.obj \ + $(DIROBJ)\extras\sharpyuv_risk_table.obj \ IMAGEIO_UTIL_OBJS = \ $(DIROBJ)\imageio\imageio_util.obj \ @@ -336,6 +339,7 @@ UTILS_DEC_OBJS = \ $(DIROBJ)\utils\color_cache_utils.obj \ $(DIROBJ)\utils\filters_utils.obj \ $(DIROBJ)\utils\huffman_utils.obj \ + $(DIROBJ)\utils\palette.obj \ $(DIROBJ)\utils\quant_levels_dec_utils.obj \ $(DIROBJ)\utils\rescaler_utils.obj \ $(DIROBJ)\utils\random_utils.obj \ diff --git a/libwebp_src/NEWS b/libwebp_src/NEWS index 47f8451..8e40d8e 100644 --- a/libwebp_src/NEWS +++ b/libwebp_src/NEWS @@ -1,3 +1,18 @@ +- 4/12/2024: version 1.4.0 + This is a binary compatible release. + * API changes: + - libwebpmux: WebPAnimEncoderSetChunk, WebPAnimEncoderGetChunk, + WebPAnimEncoderDeleteChunk + - libsharpyuv: SharpYuvOptionsInit, SharpYuvConvertWithOptions + - extras: SharpYuvEstimate420Risk + * further security related hardening in libwebp & examples + * some minor optimizations in the lossless encoder + * added WEBP_NODISCARD to report unused result warnings; enable with + -DWEBP_ENABLE_NODISCARD=1 + * improvements and corrections in webp-container-spec.txt and + webp-lossless-bitstream-spec.txt (#611) + * miscellaneous warning, bug & build fixes (#615, #619, #632, #635) + - 9/13/2023: version 1.3.2 This is a binary compatible release. * security fix for lossless decoder (chromium: #1479274, CVE-2023-4863) diff --git a/libwebp_src/README.md b/libwebp_src/README.md index a9f2c0e..ffffa53 100644 --- a/libwebp_src/README.md +++ b/libwebp_src/README.md @@ -7,7 +7,7 @@ \__\__/\____/\_____/__/ ____ ___ / _/ / \ \ / _ \/ _/ / \_/ / / \ \ __/ \__ - \____/____/\_____/_____/____/v1.3.2 + \____/____/\_____/_____/____/v1.4.0 ``` WebP codec is a library to encode and decode images in WebP format. This package diff --git a/libwebp_src/build.gradle b/libwebp_src/build.gradle index c25314c..14ceebf 100644 --- a/libwebp_src/build.gradle +++ b/libwebp_src/build.gradle @@ -173,6 +173,7 @@ model { include "color_cache_utils.c" include "filters_utils.c" include "huffman_utils.c" + include "palette.c" include "quant_levels_dec_utils.c" include "random_utils.c" include "rescaler_utils.c" diff --git a/libwebp_src/cmake/WebPConfig.cmake.in b/libwebp_src/cmake/WebPConfig.cmake.in index 8c883fe..a0d721f 100644 --- a/libwebp_src/cmake/WebPConfig.cmake.in +++ b/libwebp_src/cmake/WebPConfig.cmake.in @@ -11,7 +11,8 @@ endif() include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") set_and_check(WebP_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") -set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIRS}) +set(WebP_INCLUDE_DIRS ${WebP_INCLUDE_DIR}) +set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIR}) set(WebP_LIBRARIES "@INSTALLED_LIBRARIES@") set(WEBP_LIBRARIES "${WebP_LIBRARIES}") diff --git a/libwebp_src/cmake/cpu.cmake b/libwebp_src/cmake/cpu.cmake index 7513ca8..040c524 100644 --- a/libwebp_src/cmake/cpu.cmake +++ b/libwebp_src/cmake/cpu.cmake @@ -61,7 +61,7 @@ endif() set(WEBP_SIMD_FILES_TO_INCLUDE) set(WEBP_SIMD_FLAGS_TO_INCLUDE) -if(${ANDROID}) +if(ANDROID AND ANDROID_ABI) if(${ANDROID_ABI} STREQUAL "armeabi-v7a") # This is because Android studio uses the configuration "-march=armv7-a # -mfloat-abi=softfp -mfpu=vfpv3-d16" that does not trigger neon @@ -106,8 +106,9 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE}) endif() # Check which files we should include or not. list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION) - file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../" - "src/dsp/*${WEBP_SIMD_FILE_EXTENSION}") + file(GLOB SIMD_FILES + "${CMAKE_CURRENT_LIST_DIR}/../sharpyuv/*${WEBP_SIMD_FILE_EXTENSION}" + "${CMAKE_CURRENT_LIST_DIR}/../src/dsp/*${WEBP_SIMD_FILE_EXTENSION}") if(WEBP_HAVE_${WEBP_SIMD_FLAG}) # Memorize the file and flags. foreach(FILE ${SIMD_FILES}) diff --git a/libwebp_src/configure.ac b/libwebp_src/configure.ac index 2216e4a..af7ac0e 100644 --- a/libwebp_src/configure.ac +++ b/libwebp_src/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([libwebp], [1.3.2], +AC_INIT([libwebp], [1.4.0], [https://bugs.chromium.org/p/webp],, [https://developers.google.com/speed/webp]) AC_CANONICAL_HOST @@ -106,6 +106,7 @@ TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wall]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wconstant-conversion]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wdeclaration-after-statement]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra-semi-stmt]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wfloat-conversion]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-nonliteral]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-security]) @@ -115,6 +116,7 @@ TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wold-style-definition]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wparentheses-equality]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshadow]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshorten-64-to-32]) +TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wstrict-prototypes]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wundef]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code-aggressive]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code]) @@ -464,7 +466,7 @@ AC_ARG_ENABLE([sdl], @<:@default=auto@:>@])) AS_IF([test "x$enable_sdl" != "xno"], [ CLEAR_LIBVARS([SDL]) - AC_PATH_PROGS([LIBSDL_CONFIG], [sdl-config]) + AC_PATH_PROGS([LIBSDL_CONFIG], [sdl2-config]) if test -n "$LIBSDL_CONFIG"; then SDL_INCLUDES=`$LIBSDL_CONFIG --cflags` SDL_LIBS="`$LIBSDL_CONFIG --libs`" @@ -474,13 +476,12 @@ AS_IF([test "x$enable_sdl" != "xno"], [ sdl_header="no" LIBCHECK_PROLOGUE([SDL]) - AC_CHECK_HEADER([SDL/SDL.h], [sdl_header="SDL/SDL.h"], - [AC_CHECK_HEADER([SDL.h], [sdl_header="SDL.h"], - [AC_MSG_WARN(SDL library not available - no sdl.h)])]) + AC_CHECK_HEADER([SDL2/SDL.h], [sdl_header="SDL2/SDL.h"], + [AC_MSG_WARN(SDL2 library not available - no SDL.h)]) if test x"$sdl_header" != "xno"; then AC_LANG_PUSH(C) SDL_SAVED_LIBS="$LIBS" - for lib in "" "-lSDL" "-lSDLmain -lSDL"; do + for lib in "" "-lSDL2" "-lSDL2main -lSDL2"; do LIBS="$SDL_SAVED_LIBS $lib" # Perform a full link to ensure SDL_main is resolved if needed. AC_LINK_IFELSE( @@ -762,7 +763,8 @@ AC_CONFIG_FILES([Makefile src/Makefile man/Makefile \ src/libwebp.pc src/libwebpdecoder.pc \ src/demux/libwebpdemux.pc src/mux/libwebpmux.pc]) - +dnl fix exports from MinGW builds +AC_CONFIG_COMMANDS_POST([$SED -i 's/-DDLL_EXPORT/-DWEBP_DLL/' config.status]) AC_OUTPUT AC_MSG_NOTICE([ diff --git a/libwebp_src/doc/api.md b/libwebp_src/doc/api.md index c613ed3..c5d83db 100644 --- a/libwebp_src/doc/api.md +++ b/libwebp_src/doc/api.md @@ -157,7 +157,7 @@ decoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other status is an error condition. The 'idec' object must always be released (even upon an error condition) by -calling: WebPDelete(idec). +calling: WebPIDelete(idec). To retrieve partially decoded picture samples, one must use the corresponding method: WebPIDecGetRGB or WebPIDecGetYUVA. It will return the last displayable diff --git a/libwebp_src/doc/building.md b/libwebp_src/doc/building.md index 5efeab9..d870e34 100644 --- a/libwebp_src/doc/building.md +++ b/libwebp_src/doc/building.md @@ -96,6 +96,24 @@ make make install ``` +## Building libwebp - Using vcpkg + +You can download and install libwebp using the +[vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: + +```shell +git clone https://github.com/Microsoft/vcpkg.git +cd vcpkg +./bootstrap-vcpkg.sh +./vcpkg integrate install +./vcpkg install libwebp +``` + +The libwebp port in vcpkg is kept up to date by Microsoft team members and +community contributors. If the version is out of date, please +[create an issue or pull request](https://github.com/Microsoft/vcpkg) on the +vcpkg repository. + ## CMake With CMake, you can compile libwebp, cwebp, dwebp, gif2webp, img2webp, webpinfo diff --git a/libwebp_src/doc/webp-container-spec.txt b/libwebp_src/doc/webp-container-spec.txt index 3e66526..c64bfd4 100644 --- a/libwebp_src/doc/webp-container-spec.txt +++ b/libwebp_src/doc/webp-container-spec.txt @@ -21,9 +21,9 @@ Introduction ------------ WebP is an image format that uses either (i) the VP8 key frame encoding to -compress image data in a lossy way, or (ii) the WebP lossless encoding. These -encoding schemes should make it more efficient than older formats such as JPEG, -GIF and PNG. It is optimized for fast image transfer over the network (for +compress image data in a lossy way or (ii) the WebP lossless encoding. These +encoding schemes should make it more efficient than older formats, such as JPEG, +GIF, and PNG. It is optimized for fast image transfer over the network (for example, for websites). The WebP format has feature parity (color profile, metadata, animation, etc.) with other formats as well. This document describes the structure of a WebP file. @@ -31,36 +31,37 @@ the structure of a WebP file. The WebP container (that is, the RIFF container for WebP) allows feature support over and above the basic use case of WebP (that is, a file containing a single image encoded as a VP8 key frame). The WebP container provides additional -support for: +support for the following: - * **Lossless compression.** An image can be losslessly compressed, using the + * Lossless Compression: An image can be losslessly compressed, using the WebP Lossless Format. - * **Metadata.** An image may have metadata stored in Exif or XMP formats. + * Metadata: An image may have metadata stored in Exchangeable Image File + Format (Exif) or Extensible Metadata Platform (XMP) format. - * **Transparency.** An image may have transparency, that is, an alpha channel. + * Transparency: An image may have transparency, that is, an alpha channel. - * **Color Profile.** An image may have an embedded ICC profile as described + * Color Profile: An image may have an embedded ICC profile as described by the [International Color Consortium][iccspec]. - * **Animation.** An image may have multiple frames with pauses between them, + * Animation: An image may have multiple frames with pauses between them, making it an animation. +Terminology & Basics +-------------------- + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC 2119][] [RFC 8174][] when, and only when, they appear in all capitals, as shown here. -Bit numbering in chunk diagrams starts at `0` for the most significant bit -('MSB 0') as described in [RFC 1166][]. - -Terminology & Basics --------------------- - A WebP file contains either a still image (that is, an encoded matrix of pixels) or an [animation](#animation). Optionally, it can also contain transparency -information, color profile and metadata. We refer to the matrix of pixels as the -_canvas_ of the image. +information, a color profile and metadata. We refer to the matrix of pixels as +the _canvas_ of the image. + +Bit numbering in chunk diagrams starts at `0` for the most significant bit +('MSB 0'), as described in [RFC 1166][]. Below are additional terms used throughout this document: @@ -83,7 +84,7 @@ _uint32_ _FourCC_ -: A _FourCC_ (four-character code) is a _uint32_ created by concatenating four +: A four-character code (FourCC) is a _uint32_ created by concatenating four ASCII characters in little-endian order. This means 'aaaa' (0x61616161) and 'AAAA' (0x41414141) are treated as different _FourCCs_. @@ -94,9 +95,8 @@ _1-based_ _ChunkHeader('ABCD')_ -: This is used to describe the _FourCC_ and _Chunk Size_ header of individual - chunks, where 'ABCD' is the FourCC for the chunk. This element's size is 8 - bytes. +: Used to describe the _FourCC_ and _Chunk Size_ header of individual chunks, + where 'ABCD' is the FourCC for the chunk. This element's size is 8 bytes. RIFF File Format @@ -124,11 +124,11 @@ Chunk FourCC: 32 bits Chunk Size: 32 bits (_uint32_) : The size of the chunk in bytes, not including this field, the chunk - identifier or padding. + identifier, or padding. Chunk Payload: _Chunk Size_ bytes -: The data payload. If _Chunk Size_ is odd, a single padding byte -- that MUST +: The data payload. If _Chunk Size_ is odd, a single padding byte -- which MUST be `0` to conform with RIFF -- is added. **Note:** RIFF has a convention that all-uppercase chunk FourCCs are standard @@ -151,17 +151,17 @@ WebP File Header 'RIFF': 32 bits -: The ASCII characters 'R' 'I' 'F' 'F'. +: The ASCII characters 'R', 'I', 'F', 'F'. File Size: 32 bits (_uint32_) -: The size of the file in bytes starting at offset 8. The maximum value of +: The size of the file in bytes, starting at offset 8. The maximum value of this field is 2^32 minus 10 bytes and thus the size of the whole file is at - most 4GiB minus 2 bytes. + most 4 GiB minus 2 bytes. 'WEBP': 32 bits -: The ASCII characters 'W' 'E' 'B' 'P'. +: The ASCII characters 'W', 'E', 'B', 'P'. A WebP file MUST begin with a RIFF header with the FourCC 'WEBP'. The file size in the header is the total size of the chunks that follow plus `4` bytes for @@ -188,10 +188,10 @@ Simple WebP (lossy) file format: | WebP file header (12 bytes) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - : VP8 chunk : + : 'VP8 ' Chunk : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -VP8 chunk: +'VP8 ' Chunk: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -206,15 +206,15 @@ VP8 data: _Chunk Size_ bytes : VP8 bitstream data. -Note the fourth character in the 'VP8 ' FourCC is an ASCII space (0x20). +Note that the fourth character in the 'VP8 ' FourCC is an ASCII space (0x20). -The VP8 bitstream format specification can be found at [VP8 Data Format and -Decoding Guide][vp8spec]. Note that the VP8 frame header contains the VP8 frame +The VP8 bitstream format specification is described in [VP8 Data Format and +Decoding Guide][rfc 6386]. Note that the VP8 frame header contains the VP8 frame width and height. That is assumed to be the width and height of the canvas. The VP8 specification describes how to decode the image into Y'CbCr format. To -convert to RGB, Rec. 601 SHOULD be used. Applications MAY use another -conversion method, but visual results may differ among decoders. +convert to RGB, [Recommendation BT.601][rec601] SHOULD be used. Applications MAY +use another conversion method, but visual results may differ among decoders. Simple File Format (Lossless) @@ -235,10 +235,10 @@ Simple WebP (lossless) file format: | WebP file header (12 bytes) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - : VP8L chunk : + : 'VP8L' Chunk : +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -VP8L chunk: +'VP8L' Chunk: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -266,17 +266,17 @@ Extended File Format An extended format file consists of: - * A 'VP8X' chunk with information about features used in the file. + * A 'VP8X' Chunk with information about features used in the file. - * An optional 'ICCP' chunk with color profile. + * An optional 'ICCP' Chunk with a color profile. - * An optional 'ANIM' chunk with animation control data. + * An optional 'ANIM' Chunk with animation control data. * Image data. - * An optional 'EXIF' chunk with Exif metadata. + * An optional 'EXIF' Chunk with Exif metadata. - * An optional 'XMP ' chunk with XMP metadata. + * An optional 'XMP ' Chunk with XMP metadata. * An optional list of [unknown chunks](#unknown-chunks). @@ -290,15 +290,18 @@ up of: For an _animated image_, the _image data_ consists of multiple frames. More details about frames can be found in the [Animation](#animation) section. -All chunks SHOULD be placed in the same order as listed above. If a chunk -appears in the wrong place, the file is invalid, but readers MAY parse the -file, ignoring the chunks that are out of order. +All chunks necessary for reconstruction and color correction, that is 'VP8X', +'ICCP', 'ANIM', 'ANMF', 'ALPH', 'VP8 ' and 'VP8L', MUST appear in the order +described earlier. Readers SHOULD fail when chunks necessary for reconstruction +and color correction are out of order. + +[Metadata](#metadata) and [unknown](#unknown-chunks) chunks MAY appear out of +order. -**Rationale:** Setting the order of chunks should allow quicker file -parsing. For example, if an 'ALPH' chunk does not appear in its required -position, a decoder can choose to stop searching for it. The rule of -ignoring late chunks should make programs that need to do a full search -give the same results as the ones stopping early. +**Rationale:** The chunks necessary for reconstruction should appear first in +the file to allow a reader to begin decoding an image before receiving all of +the data. An application may benefit from varying the order of metadata and +custom chunks to suit the implementation. Extended WebP file header: {:#extended_header} @@ -326,7 +329,7 @@ Reserved (Rsv): 2 bits ICC profile (I): 1 bit -: Set if the file contains an ICC profile. +: Set if the file contains an 'ICCP' Chunk. Alpha (L): 1 bit @@ -343,7 +346,7 @@ XMP metadata (X): 1 bit Animation (A): 1 bit -: Set if this is an animated image. Data in 'ANIM' and 'ANMF' chunks should be +: Set if this is an animated image. Data in 'ANIM' and 'ANMF' Chunks should be used to control the animation. Reserved (R): 1 bit @@ -372,9 +375,9 @@ Future specifications may add more fields. Unknown fields MUST be ignored. #### Animation -An animation is controlled by ANIM and ANMF chunks. +An animation is controlled by 'ANIM' and 'ANMF' Chunks. -ANIM Chunk: +'ANIM' Chunk: {:#anim_chunk} For an animated image, this chunk contains the _global parameters_ of the @@ -396,14 +399,14 @@ Background Color: 32 bits (_uint32_) : The default background color of the canvas in \[Blue, Green, Red, Alpha\] byte order. This color MAY be used to fill the unused space on the canvas around the frames, as well as the transparent pixels of the first frame. - Background color is also used when disposal method is `1`. + The background color is also used when the Disposal method is `1`. **Note**: - * Background color MAY contain a non-opaque alpha value, even if the _Alpha_ - flag in [VP8X chunk](#extended_header) is unset. + * The background color MAY contain a non-opaque alpha value, even if the + _Alpha_ flag in the ['VP8X' Chunk](#extended_header) is unset. - * Viewer applications SHOULD treat the background color value as a hint, and + * Viewer applications SHOULD treat the background color value as a hint and are not required to use it. * The canvas is cleared at the start of each loop. The background color MAY be @@ -411,13 +414,14 @@ Background Color: 32 bits (_uint32_) Loop Count: 16 bits (_uint16_) -: The number of times to loop the animation. `0` means infinitely. +: The number of times to loop the animation. If it is `0`, this means + infinitely. -This chunk MUST appear if the _Animation_ flag in the VP8X chunk is set. +This chunk MUST appear if the _Animation_ flag in the 'VP8X' Chunk is set. If the _Animation_ flag is not set and this chunk is present, it MUST be ignored. -ANMF chunk: +'ANMF' Chunk: For animated images, this chunk contains information about a _single_ frame. If the _Animation flag_ is not set, then this chunk SHOULD NOT be present. @@ -459,10 +463,10 @@ Frame Height Minus One: 24 bits (_uint24_) Frame Duration: 24 bits (_uint24_) -: The time to wait before displaying the next frame, in 1 millisecond units. - Note the interpretation of frame duration of 0 (and often <= 10) is - implementation defined. Many tools and browsers assign a minimum duration - similar to GIF. +: The time to wait before displaying the next frame, in 1-millisecond units. + Note that the interpretation of the Frame Duration of 0 (and often <= 10) is + defined by the implementation. Many tools and browsers assign a minimum + duration similar to GIF. Reserved: 6 bits @@ -473,10 +477,10 @@ Blending method (B): 1 bit : Indicates how transparent pixels of _the current frame_ are to be blended with corresponding pixels of the previous canvas: - * `0`: Use alpha blending. After disposing of the previous frame, render the + * `0`: Use alpha-blending. After disposing of the previous frame, render the current frame on the canvas using [alpha-blending](#alpha-blending). If - the current frame does not have an alpha channel, assume alpha value of - 255, effectively replacing the rectangle. + the current frame does not have an alpha channel, assume the alpha value + is 255, effectively replacing the rectangle. * `1`: Do not blend. After disposing of the previous frame, render the current frame on the canvas by overwriting the rectangle covered by the @@ -489,20 +493,20 @@ Disposal method (D): 1 bit * `0`: Do not dispose. Leave the canvas as is. - * `1`: Dispose to background color. Fill the _rectangle_ on the canvas - covered by the _current frame_ with background color specified in the - [ANIM chunk](#anim_chunk). + * `1`: Dispose to the background color. Fill the _rectangle_ on the canvas + covered by the _current frame_ with the background color specified in the + ['ANIM' Chunk](#anim_chunk). **Notes**: * The frame disposal only applies to the _frame rectangle_, that is, the - rectangle defined by _Frame X_, _Frame Y_, _frame width_ and _frame height_. - It may or may not cover the whole canvas. + rectangle defined by _Frame X_, _Frame Y_, _frame width_, and _frame + height_. It may or may not cover the whole canvas. {:#alpha-blending} - * **Alpha-blending**: + * Alpha-blending: - Given that each of the R, G, B and A channels is 8-bit, and the RGB + Given that each of the R, G, B, and A channels is 8 bits, and the RGB channels are _not premultiplied_ by alpha, the formula for blending 'dst' onto 'src' is: @@ -518,8 +522,8 @@ Disposal method (D): 1 bit * Alpha-blending SHOULD be done in linear color space, by taking into account the [color profile](#color-profile) of the image. If the color profile is - not present, sRGB is to be assumed. (Note that sRGB also needs to be - linearized due to a gamma of ~2.2). + not present, standard RGB (sRGB) is to be assumed. (Note that sRGB also + needs to be linearized due to a gamma of ~2.2.) Frame Data: _Chunk Size_ - `16` bytes @@ -531,8 +535,8 @@ Frame Data: _Chunk Size_ - `16` bytes * An optional list of [unknown chunks](#unknown-chunks). -**Note**: The 'ANMF' payload, _Frame Data_ above, consists of individual -_padded_ chunks as described by the [RIFF file format](#riff-file-format). +**Note**: The 'ANMF' payload, _Frame Data_, consists of individual +_padded_ chunks, as described by the [RIFF file format](#riff-file-format). #### Alpha @@ -549,18 +553,20 @@ Reserved (Rsv): 2 bits : MUST be `0`. Readers MUST ignore this field. -Pre-processing (P): 2 bits +Preprocessing (P): 2 bits -: These _informative_ bits are used to signal the pre-processing that has +: These _informative_ bits are used to signal the preprocessing that has been performed during compression. The decoder can use this information to for example, dither the values or smooth the gradients prior to display. - * `0`: No pre-processing. + * `0`: No preprocessing. * `1`: Level reduction. +Decoders are not required to use this information in any specified way. + Filtering method (F): 2 bits -: The filtering method used: +: The filtering methods used are described as follows: * `0`: None. * `1`: Horizontal filter. @@ -584,8 +590,8 @@ made depending on the filtering method: where `clip(v)` is equal to: - * 0 if v < 0 - * 255 if v > 255 + * 0 if v < 0, + * 255 if v > 255, or * v otherwise The final value is derived by adding the decompressed value `X` to the @@ -594,17 +600,15 @@ into the \[0..255\] one: `alpha = (predictor + X) % 256` -There are special cases for the left-most and top-most pixel positions: +There are special cases for the left-most and top-most pixel positions. For +example, the top-left value at location (0, 0) uses 0 as the predictor value. +Otherwise: - * The top-left value at location (0, 0) uses 0 as predictor value. Otherwise, * For horizontal or gradient filtering methods, the left-most pixels at location (0, y) are predicted using the location (0, y-1) just above. * For vertical or gradient filtering methods, the top-most pixels at location (x, 0) are predicted using the location (x-1, 0) on the left. - -Decoders are not required to use this information in any specified way. - Compression method (C): 2 bits : The compression method used: @@ -617,32 +621,32 @@ Alpha bitstream: _Chunk Size_ - `1` bytes : Encoded alpha bitstream. This optional chunk contains encoded alpha data for this frame. A frame -containing a 'VP8L' chunk SHOULD NOT contain this chunk. +containing a 'VP8L' Chunk SHOULD NOT contain this chunk. **Rationale**: The transparency information is already part of the 'VP8L' -chunk. +Chunk. -The alpha channel data is stored as uncompressed raw data (when +The alpha channel data is stored as uncompressed raw data (when the compression method is '0') or compressed using the lossless format (when the compression method is '1'). - * Raw data: consists of a byte sequence of length width * height, + * Raw data: This consists of a byte sequence of length = width * height, containing all the 8-bit transparency values in scan order. - * Lossless format compression: the byte sequence is a compressed - image-stream (as described in the [WebP Lossless Bitstream Format] - [webpllspec]) of implicit dimension width x height. That is, this - image-stream does NOT contain any headers describing the image dimension. + * Lossless format compression: The byte sequence is a compressed + image-stream (as described in ["WebP Lossless Bitstream Format"] + [webpllspec]) of implicit dimensions width x height. That is, this + image-stream does NOT contain any headers describing the image dimensions. - **Rationale**: the dimension is already known from other sources, - so storing it again would be redundant and error-prone. + **Rationale**: The dimensions are already known from other sources, + so storing them again would be redundant and prone to error. - Once the image-stream is decoded into ARGB color values, following - the process described in the lossless format specification, the - transparency information must be extracted from the *green* channel - of the ARGB quadruplet. + Once the image-stream is decoded into Alpha, Red, Green, Blue (ARGB) color + values, following the process described in the lossless format + specification, the transparency information must be extracted from the + *green* channel of the ARGB quadruplet. - **Rationale**: the green channel is allowed extra transformation + **Rationale**: The green channel is allowed extra transformation steps in the specification -- unlike the other channels -- that can improve compression. @@ -650,13 +654,13 @@ compression method is '0') or compressed using the lossless format This chunk contains compressed bitstream data for a single frame. -A bitstream chunk may be either (i) a VP8 chunk, using "VP8 " (note the -significant fourth-character space) as its tag _or_ (ii) a VP8L chunk, using -"VP8L" as its tag. +A bitstream chunk may be either (i) a 'VP8 ' Chunk, using 'VP8 ' (note the +significant fourth-character space) as its FourCC, _or_ (ii) a 'VP8L' Chunk, +using 'VP8L' as its FourCC. -The formats of VP8 and VP8L chunks are as described in sections +The formats of 'VP8 ' and 'VP8L' Chunks are as described in sections [Simple File Format (Lossy)](#simple-file-format-lossy) -and [Simple File Format (Lossless)](#simple-file-format-lossless) respectively. +and [Simple File Format (Lossless)](#simple-file-format-lossless), respectively. #### Color Profile @@ -683,14 +687,14 @@ If this chunk is not present, sRGB SHOULD be assumed. #### Metadata -Metadata can be stored in 'EXIF' or 'XMP ' chunks. +Metadata can be stored in 'EXIF' or 'XMP ' Chunks. There SHOULD be at most one chunk of each type ('EXIF' and 'XMP '). If there are more such chunks, readers MAY ignore all except the first one. The chunks are defined as follows: -EXIF chunk: +'EXIF' Chunk: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -705,7 +709,7 @@ Exif Metadata: _Chunk Size_ bytes : Image metadata in Exif format. -XMP chunk: +'XMP ' Chunk: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -720,62 +724,62 @@ XMP Metadata: _Chunk Size_ bytes : Image metadata in XMP format. -Note the fourth character in the 'XMP ' FourCC is an ASCII space (0x20). +Note that the fourth character in the 'XMP ' FourCC is an ASCII space (0x20). Additional guidance about handling metadata can be found in the -Metadata Working Group's [Guidelines for Handling Metadata][metadata]. +Metadata Working Group's ["Guidelines for Handling Metadata"][metadata]. #### Unknown Chunks -A RIFF chunk (described in [this](#terminology-amp-basics) section) whose _chunk -tag_ is different from any of the chunks described in this document, is +A RIFF chunk (described in the [RIFF File Format](#riff-file-format) section) +whose FourCC is different from any of the chunks described in this document, is considered an _unknown chunk_. **Rationale**: Allowing unknown chunks gives a provision for future extension -of the format, and also allows storage of any application-specific data. +of the format and also allows storage of any application-specific data. A file MAY contain unknown chunks: - * At the end of the file as described in [Extended WebP file - header](#extended_header) section. - * At the end of ANMF chunks as described in the + * at the end of the file, as described in [Extended WebP file + header](#extended_header) section, or + * at the end of 'ANMF' Chunks, as described in the [Animation](#animation) section. Readers SHOULD ignore these chunks. Writers SHOULD preserve them in their original order (unless they specifically intend to modify these chunks). -### Assembling the Canvas From Frames +### Canvas Assembly from Frames Here we provide an overview of how a reader MUST assemble a canvas in the case of an animated image. The process begins with creating a canvas using the dimensions given in the -'VP8X' chunk, `Canvas Width Minus One + 1` pixels wide by `Canvas Height Minus -One + 1` pixels high. The `Loop Count` field from the 'ANIM' chunk controls how +'VP8X' Chunk, `Canvas Width Minus One + 1` pixels wide by `Canvas Height Minus +One + 1` pixels high. The `Loop Count` field from the 'ANIM' Chunk controls how many times the animation process is repeated. This is `Loop Count - 1` for -non-zero `Loop Count` values or infinitely if `Loop Count` is zero. +nonzero `Loop Count` values or infinite if the `Loop Count` is zero. -At the beginning of each loop iteration the canvas is filled using the -background color from the 'ANIM' chunk or an application defined color. +At the beginning of each loop iteration, the canvas is filled using the +background color from the 'ANIM' Chunk or an application-defined color. -'ANMF' chunks contain individual frames given in display order. Before rendering +'ANMF' Chunks contain individual frames given in display order. Before rendering each frame, the previous frame's `Disposal method` is applied. The rendering of the decoded frame begins at the Cartesian coordinates (`2 * -Frame X`, `2 * Frame Y`) using the top-left corner of the canvas as the origin. +Frame X`, `2 * Frame Y`), using the top-left corner of the canvas as the origin. `Frame Width Minus One + 1` pixels wide by `Frame Height Minus One + 1` pixels high are rendered onto the canvas using the `Blending method`. The canvas is displayed for `Frame Duration` milliseconds. This continues until -all frames given by 'ANMF' chunks have been displayed. A new loop iteration is -then begun or the canvas is left in its final state if all iterations have been +all frames given by 'ANMF' Chunks have been displayed. A new loop iteration is +then begun, or the canvas is left in its final state if all iterations have been completed. The following pseudocode illustrates the rendering process. The notation -_VP8X.field_ means the field in the 'VP8X' chunk with the same description. +_VP8X.field_ means the field in the 'VP8X' Chunk with the same description. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -assert VP8X.flags.hasAnimation +VP8X.flags.hasAnimation MUST be TRUE canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with background color ANIM.background_color. loop_count ← ANIM.loopCount @@ -783,9 +787,9 @@ dispose_method ← Dispose to background color if loop_count == 0: loop_count = ∞ frame_params ← nil -assert next chunk in image_data is ANMF +next chunk in image_data is ANMF MUST be TRUE for loop = 0..loop_count - 1 - clear canvas to ANIM.background_color or application defined color + clear canvas to ANIM.background_color or application-defined color until eof or non-ANMF chunk frame_params.frameX = Frame X frame_params.frameY = Frame Y @@ -794,22 +798,24 @@ for loop = 0..loop_count - 1 frame_params.frameDuration = Frame Duration frame_right = frame_params.frameX + frame_params.frameWidth frame_bottom = frame_params.frameY + frame_params.frameHeight - assert VP8X.canvasWidth >= frame_right - assert VP8X.canvasHeight >= frame_bottom + VP8X.canvasWidth >= frame_right MUST be TRUE + VP8X.canvasHeight >= frame_bottom MUST be TRUE for subchunk in 'Frame Data': if subchunk.tag == "ALPH": - assert alpha subchunks not found in 'Frame Data' earlier + alpha subchunks not found in 'Frame Data' earlier MUST be + TRUE frame_params.alpha = alpha_data else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L": - assert bitstream subchunks not found in 'Frame Data' earlier + bitstream subchunks not found in 'Frame Data' earlier MUST + be TRUE frame_params.bitstream = bitstream_data render frame with frame_params.alpha and frame_params.bitstream on canvas with top-left corner at (frame_params.frameX, - frame_params.frameY), using blending method + frame_params.frameY), using Blending method frame_params.blendingMethod. canvas contains the decoded image. Show the contents of the canvas for - frame_params.frameDuration * 1ms. + frame_params.frameDuration * 1 ms. dispose_method = frame_params.disposeMethod ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -817,7 +823,7 @@ for loop = 0..loop_count - 1 Example File Layouts -------------------- -A lossy encoded image with alpha may look as follows: +A lossy-encoded image with alpha may look as follows: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RIFF/WEBP @@ -826,16 +832,16 @@ RIFF/WEBP +- VP8 (bitstream) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A losslessly encoded image may look as follows: +A lossless-encoded image may look as follows: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RIFF/WEBP +- VP8X (descriptions of features used) -+- XYZW (unknown chunk) +- VP8L (lossless bitstream) ++- XYZW (unknown chunk) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A lossless image with ICC profile and XMP metadata may +A lossless image with an ICC profile and XMP metadata may look as follows: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -859,10 +865,11 @@ RIFF/WEBP +- EXIF (metadata) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -[vp8spec]: https://datatracker.ietf.org/doc/html/rfc6386 [webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/webp-lossless-bitstream-spec.txt [iccspec]: https://www.color.org/icc_specs2.xalter [metadata]: https://web.archive.org/web/20180919181934/http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf +[rec601]: https://www.itu.int/rec/R-REC-BT.601 [rfc 1166]: https://datatracker.ietf.org/doc/html/rfc1166 [rfc 2119]: https://datatracker.ietf.org/doc/html/rfc2119 +[rfc 6386]: https://datatracker.ietf.org/doc/html/rfc6386 [rfc 8174]: https://datatracker.ietf.org/doc/html/rfc8174 diff --git a/libwebp_src/doc/webp-lossless-bitstream-spec.txt b/libwebp_src/doc/webp-lossless-bitstream-spec.txt index ebaf655..f4db09a 100644 --- a/libwebp_src/doc/webp-lossless-bitstream-spec.txt +++ b/libwebp_src/doc/webp-lossless-bitstream-spec.txt @@ -19,19 +19,15 @@ Abstract WebP lossless is an image format for lossless compression of ARGB images. The lossless format stores and restores the pixel values exactly, including the -color values for pixels whose alpha value is 0. The format uses subresolution -images, recursively embedded into the format itself, for storing statistical -data about the images, such as the used entropy codes, spatial predictors, color -space conversion, and color table. LZ77, prefix coding, and a color cache are -used for compression of the bulk data. Decoding speeds faster than PNG have been +color values for fully transparent pixels. A universal algorithm for sequential +data compression (LZ77), prefix coding, and a color cache are used for +compression of the bulk data. Decoding speeds faster than PNG have been demonstrated, as well as 25% denser compression than can be achieved using today's PNG format. - * TOC placeholder {:toc} - 1 Introduction -------------- @@ -40,7 +36,7 @@ image. It is intended as a detailed reference for the WebP lossless encoder and decoder implementation. In this document, we extensively use C programming language syntax to describe -the bitstream, and assume the existence of a function for reading bits, +the bitstream and assume the existence of a function for reading bits, `ReadBits(n)`. The bytes are read in the natural order of the stream containing them, and bits of each byte are read in least-significant-bit-first order. When multiple bits are read at the same time, the integer is constructed from the @@ -59,20 +55,19 @@ b = ReadBits(1); b |= ReadBits(1) << 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -We assume that each color component, that is, alpha, red, blue and green, is +We assume that each color component, that is, alpha, red, blue, and green, is represented using an 8-bit byte. We define the corresponding type as uint8. A -whole ARGB pixel is represented by a type called uint32, an unsigned integer -consisting of 32 bits. In the code showing the behavior of the transformations, -alpha value is codified in bits 31..24, red in bits 23..16, green in bits 15..8 -and blue in bits 7..0, but implementations of the format are free to use another -representation internally. - -Broadly, a WebP lossless image contains header data, transform information and -actual image data. Headers contain width and height of the image. A WebP -lossless image can go through four different types of transformation before -being entropy encoded. The transform information in the bitstream contains the -data required to apply the respective inverse transforms. - +whole ARGB pixel is represented by a type called uint32, which is an unsigned +integer consisting of 32 bits. In the code showing the behavior of the +transforms, these values are codified in the following bits: alpha in bits +31..24, red in bits 23..16, green in bits 15..8, and blue in bits 7..0; however, +implementations of the format are free to use another representation internally. + +Broadly, a WebP lossless image contains header data, transform information, and +actual image data. Headers contain the width and height of the image. A WebP +lossless image can go through four different types of transforms before being +entropy encoded. The transform information in the bitstream contains the data +required to apply the respective inverse transforms. 2 Nomenclature -------------- @@ -84,7 +79,7 @@ ARGB image : A two-dimensional array containing ARGB pixels. color cache -: A small hash-addressed array to store recently used colors, to be able to +: A small hash-addressed array to store recently used colors to be able to recall them with shorter codes. color indexing image @@ -96,20 +91,16 @@ color transform image color components. distance mapping -: Changes LZ77 distances to have the smallest values for pixels in 2D - proximity. +: Changes LZ77 distances to have the smallest values for pixels in + two-dimensional proximity. entropy image : A two-dimensional subresolution image indicating which entropy coding should be used in a respective square in the image, that is, each pixel is a meta prefix code. -prefix code -: A classic way to do entropy coding where a smaller number of bits are used - for more frequent codes. - LZ77 -: Dictionary-based sliding window compression algorithm that either emits +: A dictionary-based sliding window compression algorithm that either emits symbols or describes them as sequences of past symbols. meta prefix code @@ -120,16 +111,20 @@ predictor image : A two-dimensional subresolution image indicating which spatial predictor is used for a particular square in the image. +prefix code +: A classic way to do entropy coding where a smaller number of bits are used + for more frequent codes. + prefix coding -: A way to entropy code larger integers that codes a few bits of the integer +: A way to entropy code larger integers, which codes a few bits of the integer using an entropy code and codifies the remaining bits raw. This allows for the descriptions of the entropy codes to remain relatively small even when the range of symbols is large. scan-line order -: A processing order of pixels, left-to-right, top-to-bottom, starting from - the left-hand-top pixel, proceeding to the right. Once a row is completed, - continue from the left-hand column of the next row. +: A processing order of pixels (left to right and top to bottom), starting + from the left-hand-top pixel. Once a row is completed, continue from the + left-hand column of the next row. 3 RIFF Header ------------- @@ -137,16 +132,16 @@ scan-line order The beginning of the header has the RIFF container. This consists of the following 21 bytes: - 1. String "RIFF" - 2. A little-endian 32 bit value of the block length, the whole size - of the block controlled by the RIFF header. Normally this equals + 1. String 'RIFF'. + 2. A little-endian, 32-bit value of the chunk length, which is the whole size + of the chunk controlled by the RIFF header. Normally, this equals the payload size (file size minus 8 bytes: 4 bytes for the 'RIFF' identifier and 4 bytes for storing the value itself). - 3. String "WEBP" (RIFF container name). - 4. String "VP8L" (chunk tag for lossless encoded image data). - 5. A little-endian 32-bit value of the number of bytes in the + 3. String 'WEBP' (RIFF container name). + 4. String 'VP8L' (FourCC for lossless-encoded image data). + 5. A little-endian, 32-bit value of the number of bytes in the lossless stream. - 6. One byte signature 0x2f. + 6. 1-byte signature 0x2f. The first 28 bits of the bitstream specify the width and height of the image. Width and height are decoded as 14-bit integers as follows: @@ -173,18 +168,18 @@ be treated as an error. int version_number = ReadBits(3); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +4 Transforms +------------ -4 Transformations ------------------ - -Transformations are reversible manipulations of the image data that can reduce -the remaining symbolic entropy by modeling spatial and color correlations. -Transformations can make the final compression more dense. +The transforms are reversible manipulations of the image data that can reduce +the remaining symbolic entropy by modeling spatial and color correlations. They +can make the final compression more dense. -An image can go through four types of transformation. A 1 bit indicates the +An image can go through four types of transforms. A 1 bit indicates the presence of a transform. Each transform is allowed to be used only once. The -transformations are used only for the main level ARGB image: the subresolution -images have no transforms, not even the 0 bit indicating the end-of-transforms. +transforms are used only for the main-level ARGB image; the subresolution images +(color transform image, entropy image, and predictor image) have no transforms, +not even the 0 bit indicating the end of transforms. Typically, an encoder would use these transforms to reduce the Shannon entropy in the residual image. Also, the transform data can be decided based on entropy @@ -198,10 +193,10 @@ while (ReadBits(1)) { // Transform present. ... } -// Decode actual image data (Section 4). +// Decode actual image data (Section 5). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If a transform is present then the next two bits specify the transform type. +If a transform is present, then the next two bits specify the transform type. There are four types of transforms. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -215,39 +210,45 @@ enum TransformType { The transform type is followed by the transform data. Transform data contains the information required to apply the inverse transform and depends on the -transform type. Next we describe the transform data for different types. +transform type. The inverse transforms are applied in the reverse order that +they are read from the bitstream, that is, last one first. +Next, we describe the transform data for different types. ### 4.1 Predictor Transform The predictor transform can be used to reduce entropy by exploiting the fact that neighboring pixels are often correlated. In the predictor transform, the current pixel value is predicted from the pixels already decoded (in scan-line -order) and only the residual value (actual - predicted) is encoded. The -_prediction mode_ determines the type of prediction to use. We divide the image -into squares and all the pixels in a square use the same prediction mode. +order) and only the residual value (actual - predicted) is encoded. The green +component of a pixel defines which of the 14 predictors is used within a +particular block of the ARGB image. The _prediction mode_ determines the type of +prediction to use. We divide the image into squares, and all the pixels in a +square use the same prediction mode. The first 3 bits of prediction data define the block width and height in number -of bits. The number of block columns, `block_xsize`, is used in indexing -two-dimensionally. +of bits. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int size_bits = ReadBits(3) + 2; int block_width = (1 << size_bits); int block_height = (1 << size_bits); #define DIV_ROUND_UP(num, den) (((num) + (den) - 1) / (den)) -int block_xsize = DIV_ROUND_UP(image_width, 1 << size_bits); +int transform_width = DIV_ROUND_UP(image_width, 1 << size_bits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The transform data contains the prediction mode for each block of the image. All -the `block_width * block_height` pixels of a block use same prediction mode. The -prediction modes are treated as pixels of an image and encoded using the same -techniques described in [Chapter 5](#image-data). +The transform data contains the prediction mode for each block of the image. It +is a subresolution image where the green component of a pixel defines which of +the 14 predictors is used for all the `block_width * block_height` pixels within +a particular block of the ARGB image. This subresolution image is encoded using +the same techniques described in [Chapter 5](#image-data). -For a pixel _x, y_, one can compute the respective filter block address by: +The number of block columns, `transform_width`, is used in two-dimensional +indexing. For a pixel (x, y), one can compute the respective filter block +address by: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -int block_index = (y >> size_bits) * block_xsize + +int block_index = (y >> size_bits) * transform_width + (x >> size_bits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -255,7 +256,7 @@ There are 14 different prediction modes. In each prediction mode, the current pixel value is predicted from one or more neighboring pixels whose values are already known. -We choose the neighboring pixels (TL, T, TR, and L) of the current pixel (P) as +We chose the neighboring pixels (TL, T, TR, and L) of the current pixel (P) as follows: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -267,12 +268,12 @@ X X X X X X X X X X X X X X X X X X X X X X ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -where TL means top-left, T top, TR top-right, L left pixel. At the time of -predicting a value for P, all pixels O, TL, T, TR and L have already been -processed, and pixel P and all pixels X are unknown. +where TL means top-left, T means top, TR means top-right, and L means left. At +the time of predicting a value for P, all O, TL, T, TR and L pixels have already +been processed, and the P pixel and all X pixels are unknown. -Given the above neighboring pixels, the different prediction modes are defined -as follows. +Given the preceding neighboring pixels, the different prediction modes are +defined as follows. | Mode | Predicted value of each channel of the current pixel | | ------ | ------------------------------------------------------- | @@ -304,7 +305,7 @@ The Select predictor is defined as follows: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uint32 Select(uint32 L, uint32 T, uint32 TL) { - // L = left pixel, T = top pixel, TL = top left pixel. + // L = left pixel, T = top pixel, TL = top-left pixel. // ARGB component estimates for prediction. int pAlpha = ALPHA(L) + ALPHA(T) - ALPHA(TL); @@ -333,7 +334,7 @@ for each ARGB component as follows: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Clamp the input value between 0 and 255. int Clamp(int a) { - return (a < 0) ? 0 : (a > 255) ? 255 : a; + return (a < 0) ? 0 : (a > 255) ? 255 : a; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -351,25 +352,39 @@ int ClampAddSubtractHalf(int a, int b) { There are special handling rules for some border pixels. If there is a prediction transform, regardless of the mode \[0..13\] for these pixels, the -predicted value for the left-topmost pixel of the image is 0xff000000, L-pixel -for all pixels on the top row, and T-pixel for all pixels on the leftmost -column. +predicted value for the left-topmost pixel of the image is 0xff000000, all +pixels on the top row are L-pixel, and all pixels on the leftmost column are +T-pixel. Addressing the TR-pixel for pixels on the rightmost column is exceptional. The pixels on the rightmost column are predicted by using the modes -\[0..13\] just like pixels not on the border, but the leftmost pixel on the same -row as the current pixel is instead used as the TR-pixel. +\[0..13\], just like pixels not on the border, but the leftmost pixel on the +same row as the current pixel is instead used as the TR-pixel. +The final pixel value is obtained by adding each channel of the predicted value +to the encoded residual value. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void PredictorTransformOutput(uint32 residual, uint32 pred, + uint8* alpha, uint8* red, + uint8* green, uint8* blue) { + *alpha = ALPHA(residual) + ALPHA(pred); + *red = RED(residual) + RED(pred); + *green = GREEN(residual) + GREEN(pred); + *blue = BLUE(residual) + BLUE(pred); +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ### 4.2 Color Transform -The goal of the color transform is to decorrelate the R, G and B values of each -pixel. The color transform keeps the green (G) value as it is, transforms red -(R) based on green and transforms blue (B) based on green and then based on red. +The goal of the color transform is to decorrelate the R, G, and B values of each +pixel. The color transform keeps the green (G) value as it is, transforms the +red (R) value based on the green value, and transforms the blue (B) value based +on the green value and then on the red value. As is the case for the predictor transform, first the image is divided into -blocks and the same transform mode is used for all the pixels in a block. For -each block there are three types of color transform elements. +blocks, and the same transform mode is used for all the pixels in a block. For +each block, there are three types of color transform elements. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ typedef struct { @@ -379,7 +394,7 @@ typedef struct { } ColorTransformElement; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The actual color transformation is done by defining a color transform delta. The +The actual color transform is done by defining a color transform delta. The color transform delta depends on the `ColorTransformElement`, which is the same for all the pixels in a particular block. The delta is subtracted during the color transform. The inverse color transform then is just adding those deltas. @@ -395,9 +410,9 @@ void ColorTransform(uint8 red, uint8 blue, uint8 green, int tmp_blue = blue; // Applying the transform is just subtracting the transform deltas - tmp_red -= ColorTransformDelta(trans->green_to_red_, green); - tmp_blue -= ColorTransformDelta(trans->green_to_blue_, green); - tmp_blue -= ColorTransformDelta(trans->red_to_blue_, red); + tmp_red -= ColorTransformDelta(trans->green_to_red, green); + tmp_blue -= ColorTransformDelta(trans->green_to_blue, green); + tmp_blue -= ColorTransformDelta(trans->red_to_blue, red); *new_red = tmp_red & 0xff; *new_blue = tmp_blue & 0xff; @@ -405,7 +420,7 @@ void ColorTransform(uint8 red, uint8 blue, uint8 green, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `ColorTransformDelta` is computed using a signed 8-bit integer representing a -3.5-fixed-point number, and a signed 8-bit RGB color channel (c) \[-128..127\] +3.5-fixed-point number and a signed 8-bit RGB color channel (c) \[-128..127\] and is defined as follows: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -415,16 +430,16 @@ int8 ColorTransformDelta(int8 t, int8 c) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A conversion from the 8-bit unsigned representation (uint8) to the 8-bit signed -one (int8) is required before calling `ColorTransformDelta()`. It should be -performed using 8-bit two's complement (that is: uint8 range \[128..255\] is -mapped to the \[-128..-1\] range of its converted int8 value). +one (int8) is required before calling `ColorTransformDelta()`. The signed value +should be interpreted as an 8-bit two's complement number (that is: uint8 range +\[128..255\] is mapped to the \[-128..-1\] range of its converted int8 value). The multiplication is to be done using more precision (with at least 16-bit precision). The sign extension property of the shift operation does not matter -here: only the lowest 8 bits are used from the result, and there the sign +here; only the lowest 8 bits are used from the result, and there the sign extension shifting and unsigned shifting are consistent with each other. -Now we describe the contents of color transform data so that decoding can apply +Now, we describe the contents of color transform data so that decoding can apply the inverse color transform and recover the original red and blue values. The first 3 bits of the color transform data contain the width and height of the image block in number of bits, just like the predictor transform: @@ -436,14 +451,16 @@ int block_height = 1 << size_bits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The remaining part of the color transform data contains `ColorTransformElement` -instances corresponding to each block of the image. `ColorTransformElement` -instances are treated as pixels of an image and encoded using the methods -described in [Chapter 5](#image-data). +instances, corresponding to each block of the image. Each +`ColorTransformElement` `'cte'` is treated as a pixel in a subresolution image +whose alpha component is `255`, red component is `cte.red_to_blue`, green +component is `cte.green_to_blue`, and blue component is `cte.green_to_red`. During decoding, `ColorTransformElement` instances of the blocks are decoded and the inverse color transform is applied on the ARGB values of the pixels. As mentioned earlier, that inverse color transform is just adding -`ColorTransformElement` values to the red and blue channels. +`ColorTransformElement` values to the red and blue channels. The alpha and green +channels are left as is. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void InverseTransform(uint8 red, uint8 green, uint8 blue, @@ -465,13 +482,12 @@ void InverseTransform(uint8 red, uint8 green, uint8 blue, } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ### 4.3 Subtract Green Transform The subtract green transform subtracts green values from red and blue values of each pixel. When this transform is present, the decoder needs to add the green -value to both red and blue. There is no data associated with this transform. The -decoder applies the inverse transform as follows: +value to both the red and blue values. There is no data associated with this +transform. The decoder applies the inverse transform as follows: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void AddGreenToBlueAndRed(uint8 green, uint8 *red, uint8 *blue) { @@ -480,41 +496,40 @@ void AddGreenToBlueAndRed(uint8 green, uint8 *red, uint8 *blue) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This transform is redundant as it can be modeled using the color transform, but +This transform is redundant, as it can be modeled using the color transform, but since there is no additional data here, the subtract green transform can be coded using fewer bits than a full-blown color transform. - ### 4.4 Color Indexing Transform If there are not many unique pixel values, it may be more efficient to create a color index array and replace the pixel values by the array's indices. The color indexing transform achieves this. (In the context of WebP lossless, we specifically do not call this a palette transform because a similar but more -dynamic concept exists in WebP lossless encoding: color cache). +dynamic concept exists in WebP lossless encoding: color cache.) The color indexing transform checks for the number of unique ARGB values in the image. If that number is below a threshold (256), it creates an array of those ARGB values, which is then used to replace the pixel values with the corresponding index: the green channel of the pixels are replaced with the -index; all alpha values are set to 255; all red and blue values to 0. +index, all alpha values are set to 255, and all red and blue values to 0. -The transform data contains color table size and the entries in the color table. -The decoder reads the color indexing transform data as follows: +The transform data contains the color table size and the entries in the color +table. The decoder reads the color indexing transform data as follows: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// 8 bit value for color table size +// 8-bit value for the color table size int color_table_size = ReadBits(8) + 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The color table is stored using the image storage format itself. The color table can be obtained by reading an image, without the RIFF header, image size, and -transforms, assuming a height of one pixel and a width of `color_table_size`. +transforms, assuming the height of 1 pixel and the width of `color_table_size`. The color table is always subtraction-coded to reduce image entropy. The deltas of palette colors contain typically much less entropy than the colors themselves, leading to significant savings for smaller images. In decoding, every final color in the color table can be obtained by adding the previous -color component values by each ARGB component separately, and storing the least +color component values by each ARGB component separately and storing the least significant 8 bits of the result. The inverse transform for the image is simply replacing the pixel values (which @@ -526,14 +541,14 @@ is done based on the green component of the ARGB color. argb = color_table[GREEN(argb)]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If the index is equal or larger than `color_table_size`, the argb color value +If the index is equal to or larger than `color_table_size`, the argb color value should be set to 0x00000000 (transparent black). When the color table is small (equal to or less than 16 colors), several pixels are bundled into a single pixel. The pixel bundling packs several (2, 4, or 8) pixels into a single pixel, reducing the image width respectively. Pixel bundling allows for a more efficient joint distribution entropy coding of -neighboring pixels, and gives some arithmetic coding-like benefits to the +neighboring pixels and gives some arithmetic coding-like benefits to the entropy code, but it can only be used when there are 16 or fewer unique values. `color_table_size` specifies how many pixels are combined: @@ -551,7 +566,7 @@ if (color_table_size <= 2) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -`width_bits` has a value of 0, 1, 2 or 3. A value of 0 indicates no pixel +`width_bits` has a value of 0, 1, 2, or 3. A value of 0 indicates no pixel bundling is to be done for the image. A value of 1 indicates that two pixels are combined, and each pixel has a range of \[0..15\]. A value of 2 indicates that four pixels are combined, and each pixel has a range of \[0..3\]. A value of 3 @@ -560,19 +575,26 @@ that is, a binary value. The values are packed into the green component as follows: - * `width_bits` = 1: for every x value where x ≡ 0 (mod 2), a green - value at x is positioned into the 4 least-significant bits of the - green value at x / 2, a green value at x + 1 is positioned into the - 4 most-significant bits of the green value at x / 2. - * `width_bits` = 2: for every x value where x ≡ 0 (mod 4), a green + * `width_bits` = 1: For every x value, where x ≡ 0 (mod 2), a green + value at x is positioned into the 4 least significant bits of the + green value at x / 2, and a green value at x + 1 is positioned into the + 4 most significant bits of the green value at x / 2. + * `width_bits` = 2: For every x value, where x ≡ 0 (mod 4), a green value at x is positioned into the 2 least-significant bits of the - green value at x / 4, green values at x + 1 to x + 3 are positioned in order - to the more significant bits of the green value at x / 4. - * `width_bits` = 3: for every x value where x ≡ 0 (mod 8), a green - value at x is positioned into the least-significant bit of the green - value at x / 8, green values at x + 1 to x + 7 are positioned in order to - the more significant bits of the green value at x / 8. + green value at x / 4, and green values at x + 1 to x + 3 are positioned in + order to the more significant bits of the green value at x / 4. + * `width_bits` = 3: For every x value, where x ≡ 0 (mod 8), a green + value at x is positioned into the least significant bit of the green + value at x / 8, and green values at x + 1 to x + 7 are positioned in order + to the more significant bits of the green value at x / 8. +After reading this transform, `image_width` is subsampled by `width_bits`. This +affects the size of subsequent transforms. The new size can be calculated using +`DIV_ROUND_UP`, as defined [earlier](#predictor-transform). + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +image_width = DIV_ROUND_UP(image_width, 1 << width_bits); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 Image Data ------------ @@ -584,23 +606,16 @@ Image data is an array of pixel values in scan-line order. We use image data in five different roles: 1. ARGB image: Stores the actual pixels of the image. - 1. Entropy image: Stores the - [meta prefix codes](#decoding-of-meta-prefix-codes). The red and green - components of a pixel define the meta prefix code used in a particular - block of the ARGB image. - 1. Predictor image: Stores the metadata for - [Predictor Transform](#predictor-transform). The green component of a pixel - defines which of the 14 predictors is used within a particular block of the - ARGB image. - 1. Color transform image. It is created by `ColorTransformElement` values - (defined in [Color Transform](#color-transform)) for different blocks of - the image. Each `ColorTransformElement` `'cte'` is treated as a pixel whose - alpha component is `255`, red component is `cte.red_to_blue`, green - component is `cte.green_to_blue` and blue component is `cte.green_to_red`. - 1. Color indexing image: An array of size `color_table_size` (up to 256 - ARGB values) storing the metadata for the - [Color Indexing Transform](#color-indexing-transform). This is stored as an - image of width `color_table_size` and height `1`. + 1. Entropy image: Stores the meta prefix codes (see + ["Decoding of Meta Prefix Codes"](#decoding-of-meta-prefix-codes)). + 1. Predictor image: Stores the metadata for the predictor transform (see + ["Predictor Transform"](#predictor-transform)). + 1. Color transform image: Created by `ColorTransformElement` values + (defined in ["Color Transform"](#color-transform)) for different blocks of + the image. + 1. Color indexing image: An array of size `color_table_size` (up to 256 ARGB + values) storing the metadata for the color indexing transform (see + ["Color Indexing Transform"](#color-indexing-transform)). ### 5.2 Encoding of Image Data @@ -613,24 +628,24 @@ several blocks may share the same entropy codes. **Rationale:** Storing an entropy code incurs a cost. This cost can be minimized if statistically similar blocks share an entropy code, thereby storing that code only once. For example, an encoder can find similar blocks by clustering them -using their statistical properties, or by repeatedly joining a pair of randomly +using their statistical properties or by repeatedly joining a pair of randomly selected clusters when it reduces the overall amount of bits needed to encode the image. Each pixel is encoded using one of the three possible methods: - 1. Prefix coded literal: each channel (green, red, blue and alpha) is - entropy-coded independently; - 2. LZ77 backward reference: a sequence of pixels are copied from elsewhere - in the image; or - 3. Color cache code: using a short multiplicative hash code (color cache + 1. Prefix-coded literals: Each channel (green, red, blue, and alpha) is + entropy-coded independently. + 2. LZ77 backward reference: A sequence of pixels are copied from elsewhere in + the image. + 3. Color cache code: Using a short multiplicative hash code (color cache index) of a recently seen color. The following subsections describe each of these in detail. -#### 5.2.1 Prefix Coded Literals +#### 5.2.1 Prefix-Coded Literals -The pixel is stored as prefix coded values of green, red, blue and alpha (in +The pixel is stored as prefix-coded values of green, red, blue, and alpha (in that order). See [Section 6.2.3](#decoding-entropy-coded-image-data) for details. @@ -646,12 +661,12 @@ Backward references are tuples of _length_ and _distance code_: The length and distance values are stored using **LZ77 prefix coding**. LZ77 prefix coding divides large integer values into two parts: the _prefix -code_ and the _extra bits_: the prefix code is stored using an entropy code, +code_ and the _extra bits_. The prefix code is stored using an entropy code, while the extra bits are stored as they are (without an entropy code). **Rationale**: This approach reduces the storage requirement for the entropy -code. Also, large values are usually rare, and so extra bits would be used for -very few values in the image. Thus, this approach results in better compression +code. Also, large values are usually rare, so extra bits would be used for very +few values in the image. Thus, this approach results in better compression overall. The following table denotes the prefix codes and extra bits used for storing @@ -689,28 +704,27 @@ int offset = (2 + (prefix_code & 1)) << extra_bits; return offset + ReadBits(extra_bits) + 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**Distance Mapping:** -{:#distance-mapping} +##### Distance Mapping As noted previously, a distance code is a number indicating the position of a previously seen pixel, from which the pixels are to be copied. This subsection defines the mapping between a distance code and the position of a previous pixel. -Distance codes larger than 120 denote the pixel-distance in scan-line order, +Distance codes larger than 120 denote the pixel distance in scan-line order, offset by 120. -The smallest distance codes \[1..120\] are special, and are reserved for a close +The smallest distance codes \[1..120\] are special and are reserved for a close neighborhood of the current pixel. This neighborhood consists of 120 pixels: - * Pixels that are 1 to 7 rows above the current pixel, and are up to 8 columns + * Pixels that are 1 to 7 rows above the current pixel and are up to 8 columns to the left or up to 7 columns to the right of the current pixel. \[Total such pixels = `7 * (8 + 1 + 7) = 112`\]. - * Pixels that are in same row as the current pixel, and are up to 8 columns to - the left of the current pixel. \[`8` such pixels\]. + * Pixels that are in the same row as the current pixel and are up to 8 + columns to the left of the current pixel. \[`8` such pixels\]. -The mapping between distance code `i` and the neighboring pixel offset -`(xi, yi)` is as follows: +The mapping between distance code `distance_code` and the neighboring pixel +offset `(xi, yi)` is as follows: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (0, 1), (1, 0), (1, 1), (-1, 1), (0, 2), (2, 0), (1, 2), @@ -735,23 +749,22 @@ The mapping between distance code `i` and the neighboring pixel offset For example, the distance code `1` indicates an offset of `(0, 1)` for the neighboring pixel, that is, the pixel above the current pixel (0 pixel -difference in the X-direction and 1 pixel difference in the Y-direction). -Similarly, the distance code `3` indicates the left-top pixel. +difference in the X direction and 1 pixel difference in the Y direction). +Similarly, the distance code `3` indicates the top-left pixel. -The decoder can convert a distance code `i` to a scan-line order distance `dist` -as follows: +The decoder can convert a distance code `distance_code` to a scan-line order +distance `dist` as follows: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -(xi, yi) = distance_map[i - 1] -dist = xi + yi * xsize +(xi, yi) = distance_map[distance_code - 1] +dist = xi + yi * image_width if (dist < 1) { dist = 1 } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -where `distance_map` is the mapping noted above and `xsize` is the width of the -image in pixels. - +where `distance_map` is the mapping noted above, and `image_width` is the width +of the image in pixels. #### 5.2.3 Color Cache Coding {:#color-cache-code} @@ -760,7 +773,7 @@ Color cache stores a set of colors that have been recently used in the image. **Rationale:** This way, the recently used colors can sometimes be referred to more efficiently than emitting them using the other two methods (described in -[5.2.1](#prefix-coded-literals) and [5.2.2](#lz77-backward-reference)). +Sections [5.2.1](#prefix-coded-literals) and [5.2.2](#lz77-backward-reference)). Color cache codes are stored as follows. First, there is a 1-bit value that indicates if the color cache is used. If this bit is 0, no color cache codes @@ -773,14 +786,14 @@ int color_cache_code_bits = ReadBits(4); int color_cache_size = 1 << color_cache_code_bits; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -`color_cache_code_bits` defines the size of the color_cache by (1 << -`color_cache_code_bits`). The range of allowed values for +`color_cache_code_bits` defines the size of the color cache (`1 << +color_cache_code_bits`). The range of allowed values for `color_cache_code_bits` is \[1..11\]. Compliant decoders must indicate a corrupted bitstream for other values. A color cache is an array of size `color_cache_size`. Each entry stores one ARGB -color. Colors are looked up by indexing them by (0x1e35a7bd * `color`) >> (32 - -`color_cache_code_bits`). Only one lookup is done in a color cache; there is no +color. Colors are looked up by indexing them by `(0x1e35a7bd * color) >> (32 - +color_cache_code_bits)`. Only one lookup is done in a color cache; there is no conflict resolution. In the beginning of decoding or encoding of an image, all entries in all color @@ -789,7 +802,6 @@ decoding time. The state of the color cache is maintained by inserting every pixel, be it produced by backward referencing or as literals, into the cache in the order they appear in the stream. - 6 Entropy Code -------------- @@ -799,7 +811,7 @@ Most of the data is coded using a [canonical prefix code][canonical_huff]. Hence, the codes are transmitted by sending the _prefix code lengths_, as opposed to the actual _prefix codes_. -In particular, the format uses **spatially-variant prefix coding**. In other +In particular, the format uses **spatially variant prefix coding**. In other words, different blocks of the image can potentially use different entropy codes. @@ -811,23 +823,29 @@ potentially better compression. The encoded image data consists of several parts: - 1. Decoding and building the prefix codes - 1. Meta prefix codes - 1. Entropy-coded image data + 1. Decoding and building the prefix codes. + 1. Meta prefix codes. + 1. Entropy-coded image data. -#### 6.2.1 Decoding and Building the Prefix Codes +For any given pixel (x, y), there is a set of five prefix codes associated with +it. These codes are (in bitstream order): -There are several steps in decoding the prefix codes. + * **Prefix code #1**: Used for green channel, backward-reference length, and + color cache. + * **Prefix code #2, #3, and #4**: Used for red, blue, and alpha channels, + respectively. + * **Prefix code #5**: Used for backward-reference distance. -**Decoding the Code Lengths:** -{:#decoding-the-code-lengths} +From here on, we refer to this set as a **prefix code group**. + +#### 6.2.1 Decoding and Building the Prefix Codes This section describes how to read the prefix code lengths from the bitstream. The prefix code lengths can be coded in two ways. The method used is specified by a 1-bit value. - * If this bit is 1, it is a _simple code length code_, and + * If this bit is 1, it is a _simple code length code_. * If this bit is 0, it is a _normal code length code_. In both cases, there can be unused code lengths that are still part of the @@ -835,11 +853,11 @@ stream. This may be inefficient, but it is allowed by the format. The described tree must be a complete binary tree. A single leaf node is considered a complete binary tree and can be encoded using either the simple code length code or the normal code length code. When coding a single leaf -node using the _normal code length code_, all but one code length should be -zeros, and the single leaf node value is marked with the length of 1 -- even -when no bits are consumed when that single leaf node tree is used. +node using the _normal code length code_, all but one code length are zeros, +and the single leaf node value is marked with the length of 1 -- even when no +bits are consumed when that single leaf node tree is used. -**(i) Simple Code Length Code:** +##### Simple Code Length Code This variant is used in the special case when only 1 or 2 prefix symbols are in the range \[0..255\] with code length `1`. All other prefix code lengths are @@ -851,9 +869,9 @@ The first bit indicates the number of symbols: int num_symbols = ReadBits(1) + 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Following are the symbol values. +The following are the symbol values. -This first symbol is coded using 1 or 8 bits depending on the value of +This first symbol is coded using 1 or 8 bits, depending on the value of `is_first_8bits`. The range is \[0..1\] or \[0..255\], respectively. The second symbol, if present, is always assumed to be in the range \[0..255\] and coded using 8 bits. @@ -868,6 +886,9 @@ if (num_symbols == 2) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The two symbols should be different. Duplicate symbols are allowed, but +inefficient. + **Note:** Another special case is when _all_ prefix code lengths are _zeros_ (an empty prefix code). For example, a prefix code for distance can be empty if there are no backward references. Similarly, prefix codes for alpha, red, and @@ -875,7 +896,7 @@ blue can be empty if all pixels within the same meta prefix code are produced using the color cache. However, this case doesn't need special handling, as empty prefix codes can be coded as those containing a single symbol `0`. -**(ii) Normal Code Length Code:** +##### Normal Code Length Code The code lengths of the prefix code fit in 8 bits and are read as follows. First, `num_code_lengths` specifies the number of code lengths. @@ -884,9 +905,7 @@ First, `num_code_lengths` specifies the number of code lengths. int num_code_lengths = 4 + ReadBits(4); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If `num_code_lengths` is > 19, the bitstream is invalid. - -The code lengths are themselves encoded using prefix codes: lower level code +The code lengths are themselves encoded using prefix codes; lower-level code lengths, `code_length_code_lengths`, first have to be read. The rest of those `code_length_code_lengths` (according to the order in `kCodeLengthCodeOrder`) are zeros. @@ -902,34 +921,40 @@ for (i = 0; i < num_code_lengths; ++i) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Next, if `ReadBits(1) == 0`, the maximum number of different read symbols is -`num_code_lengths`. Otherwise, it is defined as: +Next, if `ReadBits(1) == 0`, the maximum number of different read symbols +(`max_symbol`) for each symbol type (A, R, G, B, and distance) is set to its +alphabet size: + + * G channel: 256 + 24 + `color_cache_size` + * Other literals (A, R, and B): 256 + * Distance code: 40 + +Otherwise, it is defined as: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int length_nbits = 2 + 2 * ReadBits(3); int max_symbol = 2 + ReadBits(length_nbits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +If `max_symbol` is larger than the size of the alphabet for the symbol type, the +bitstream is invalid. + A prefix table is then built from `code_length_code_lengths` and used to read up to `max_symbol` code lengths. * Code \[0..15\] indicates literal code lengths. * Value 0 means no symbols have been coded. * Values \[1..15\] indicate the bit length of the respective code. - * Code 16 repeats the previous non-zero value \[3..6\] times, that is, - `3 + ReadBits(2)` times. If code 16 is used before a non-zero + * Code 16 repeats the previous nonzero value \[3..6\] times, that is, + `3 + ReadBits(2)` times. If code 16 is used before a nonzero value has been emitted, a value of 8 is repeated. - * Code 17 emits a streak of zeros \[3..10\], that is, `3 + ReadBits(3)` - times. + * Code 17 emits a streak of zeros of length \[3..10\], that is, `3 + + ReadBits(3)` times. * Code 18 emits a streak of zeros of length \[11..138\], that is, `11 + ReadBits(7)` times. -Once code lengths are read, a prefix code for each symbol type (A, R, G, B, -distance) is formed using their respective alphabet sizes: - - * G channel: 256 + 24 + `color_cache_size` - * other literals (A,R,B): 256 - * distance code: 40 +Once code lengths are read, a prefix code for each symbol type (A, R, G, B, and +distance) is formed using their respective alphabet sizes. The Normal Code Length Code must code a full decision tree, that is, the sum of `2 ^ (-length)` for all non-zero codes must be exactly one. There is however @@ -953,37 +978,31 @@ value: * If this bit is one, the image uses multiple meta prefix codes. These meta prefix codes are stored as an _entropy image_ (described below). -**Entropy image:** +The red and green components of a pixel define a 16-bit meta prefix code used in +a particular block of the ARGB image. + +##### Entropy Image The entropy image defines which prefix codes are used in different parts of the -image, as described below. +image. -The first 3-bits contain the `prefix_bits` value. The dimensions of the entropy -image are derived from `prefix_bits`. +The first 3 bits contain the `prefix_bits` value. The dimensions of the entropy +image are derived from `prefix_bits`: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int prefix_bits = ReadBits(3) + 2; -int prefix_xsize = DIV_ROUND_UP(xsize, 1 << prefix_bits); -int prefix_ysize = DIV_ROUND_UP(ysize, 1 << prefix_bits); +int prefix_image_width = + DIV_ROUND_UP(image_width, 1 << prefix_bits); +int prefix_image_height = + DIV_ROUND_UP(image_height, 1 << prefix_bits); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ where `DIV_ROUND_UP` is as defined [earlier](#predictor-transform). -The next bits contain an entropy image of width `prefix_xsize` and height -`prefix_ysize`. +The next bits contain an entropy image of width `prefix_image_width` and height +`prefix_image_height`. -**Interpretation of Meta Prefix Codes:** - -For any given pixel (x, y), there is a set of five prefix codes associated with -it. These codes are (in bitstream order): - - * **Prefix code #1**: used for green channel, backward-reference length and - color cache. - * **Prefix code #2, #3 and #4**: used for red, blue and alpha channels - respectively. - * **Prefix code #5**: used for backward-reference distance. - -From here on, we refer to this set as a **prefix code group**. +##### Interpretation of Meta Prefix Codes The number of prefix code groups in the ARGB image can be obtained by finding the _largest meta prefix code_ from the entropy image: @@ -1006,72 +1025,73 @@ codes to be used as follows: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int position = - (y >> prefix_bits) * prefix_xsize + (x >> prefix_bits); + (y >> prefix_bits) * prefix_image_width + (x >> prefix_bits); int meta_prefix_code = (entropy_image[position] >> 8) & 0xffff; PrefixCodeGroup prefix_group = prefix_code_groups[meta_prefix_code]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -where, we have assumed the existence of `PrefixCodeGroup` structure, which +where we have assumed the existence of `PrefixCodeGroup` structure, which represents a set of five prefix codes. Also, `prefix_code_groups` is an array of `PrefixCodeGroup` (of size `num_prefix_groups`). The decoder then uses prefix code group `prefix_group` to decode the pixel -(x, y) as explained in the [next section](#decoding-entropy-coded-image-data). +(x, y), as explained in ["Decoding Entropy-Coded Image +Data"](#decoding-entropy-coded-image-data). #### 6.2.3 Decoding Entropy-Coded Image Data For the current position (x, y) in the image, the decoder first identifies the corresponding prefix code group (as explained in the last section). Given the -prefix code group, the pixel is read and decoded as follows: +prefix code group, the pixel is read and decoded as follows. -Read the next symbol S from the bitstream using prefix code #1. Note that S is +Next, read the symbol S from the bitstream using prefix code #1. Note that S is any integer in the range `0` to `(256 + 24 + ` [`color_cache_size`](#color-cache-code)` - 1)`. The interpretation of S depends on its value: - 1. if S < 256 + 1. If S < 256 1. Use S as the green component. 1. Read red from the bitstream using prefix code #2. 1. Read blue from the bitstream using prefix code #3. 1. Read alpha from the bitstream using prefix code #4. - 1. if S >= 256 && S < 256 + 24 + 1. If S >= 256 & S < 256 + 24 1. Use S - 256 as a length prefix code. - 1. Read extra bits for length from the bitstream. + 1. Read extra bits for the length from the bitstream. 1. Determine backward-reference length L from length prefix code and the extra bits read. - 1. Read distance prefix code from the bitstream using prefix code #5. - 1. Read extra bits for distance from the bitstream. - 1. Determine backward-reference distance D from distance prefix code and - the extra bits read. - 1. Copy the L pixels (in scan-line order) from the sequence of pixels - prior to them by D pixels. - 1. if S >= 256 + 24 + 1. Read the distance prefix code from the bitstream using prefix code #5. + 1. Read extra bits for the distance from the bitstream. + 1. Determine backward-reference distance D from the distance prefix code + and the extra bits read. + 1. Copy L pixels (in scan-line order) from the sequence of pixels starting + at the current position minus D pixels. + 1. If S >= 256 + 24 1. Use S - (256 + 24) as the index into the color cache. 1. Get ARGB color from the color cache at that index. - 7 Overall Structure of the Format --------------------------------- -Below is a view into the format in Augmented Backus-Naur Form ([ABNF]). It does -not cover all details. End-of-image (EOI) is only implicitly coded into the -number of pixels (xsize * ysize). +Below is a view into the format in Augmented Backus-Naur Form (ABNF) +[RFC 5234][] [RFC 7405][]. It does not cover all details. The end-of-image (EOI) +is only implicitly coded into the number of pixels (image_width * image_height). +Note that `*element` means `element` can be repeated 0 or more times. `5element` +means `element` is repeated exactly 5 times. `%b` represents a binary value. #### 7.1 Basic Structure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ format = RIFF-header image-header image-stream -RIFF-header = "RIFF" 4OCTET "WEBP" "VP8L" 4OCTET %x2F -image-header = image-size alpha-is-used version +RIFF-header = %s"RIFF" 4OCTET %s"WEBPVP8L" 4OCTET +image-header = %x2F image-size alpha-is-used version image-size = 14BIT 14BIT ; width - 1, height - 1 alpha-is-used = 1BIT version = 3BIT ; 0 image-stream = optional-transform spatially-coded-image ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - #### 7.2 Structure of Transforms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1094,7 +1114,6 @@ color-indexing-image = 8BIT ; color count entropy-coded-image ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - #### 7.3 Structure of the Image Data ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1124,7 +1143,7 @@ lz77-coded-image = *((argb-pixel / lz77-copy / color-cache-code) lz77-coded-image) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A possible example sequence: +The following is a possible example sequence: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RIFF-header image-size %b1 subtract-green-tx @@ -1132,5 +1151,6 @@ RIFF-header image-size %b1 subtract-green-tx %b0 prefix-codes lz77-coded-image ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -[ABNF]: https://www.rfc-editor.org/rfc/rfc5234 +[RFC 5234]: https://www.rfc-editor.org/rfc/rfc5234 +[RFC 7405]: https://www.rfc-editor.org/rfc/rfc7405 [canonical_huff]: https://en.wikipedia.org/wiki/Canonical_Huffman_code diff --git a/libwebp_src/examples/anim_dump.c b/libwebp_src/examples/anim_dump.c index e447338..269cbab 100644 --- a/libwebp_src/examples/anim_dump.c +++ b/libwebp_src/examples/anim_dump.c @@ -98,7 +98,11 @@ int main(int argc, const char* argv[]) { for (i = 0; !error && i < image.num_frames; ++i) { W_CHAR out_file[1024]; WebPDecBuffer buffer; - WebPInitDecBuffer(&buffer); + if (!WebPInitDecBuffer(&buffer)) { + fprintf(stderr, "Cannot init dec buffer\n"); + error = 1; + continue; + } buffer.colorspace = MODE_RGBA; buffer.is_external_memory = 1; buffer.width = image.canvas_width; diff --git a/libwebp_src/examples/cwebp.c b/libwebp_src/examples/cwebp.c index 835579d..cab7005 100644 --- a/libwebp_src/examples/cwebp.c +++ b/libwebp_src/examples/cwebp.c @@ -306,6 +306,7 @@ static int MyWriter(const uint8_t* data, size_t data_size, // Dumps a picture as a PGM file using the IMC4 layout. static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) { int y; + int ok = 0; const int uv_width = (picture->width + 1) / 2; const int uv_height = (picture->height + 1) / 2; const int stride = (picture->width + 1) & ~1; @@ -320,23 +321,26 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) { if (f == NULL) return 0; fprintf(f, "P5\n%d %d\n255\n", stride, height); for (y = 0; y < picture->height; ++y) { - if (fwrite(src_y, picture->width, 1, f) != 1) return 0; + if (fwrite(src_y, picture->width, 1, f) != 1) goto Error; if (picture->width & 1) fputc(0, f); // pad src_y += picture->y_stride; } for (y = 0; y < uv_height; ++y) { - if (fwrite(src_u, uv_width, 1, f) != 1) return 0; - if (fwrite(src_v, uv_width, 1, f) != 1) return 0; + if (fwrite(src_u, uv_width, 1, f) != 1) goto Error; + if (fwrite(src_v, uv_width, 1, f) != 1) goto Error; src_u += picture->uv_stride; src_v += picture->uv_stride; } for (y = 0; y < alpha_height; ++y) { - if (fwrite(src_a, picture->width, 1, f) != 1) return 0; + if (fwrite(src_a, picture->width, 1, f) != 1) goto Error; if (picture->width & 1) fputc(0, f); // pad src_a += picture->a_stride; } + ok = 1; + + Error: fclose(f); - return 1; + return ok; } // ----------------------------------------------------------------------------- diff --git a/libwebp_src/examples/gifdec.c b/libwebp_src/examples/gifdec.c index 99ee996..9b9a694 100644 --- a/libwebp_src/examples/gifdec.c +++ b/libwebp_src/examples/gifdec.c @@ -317,7 +317,7 @@ void GIFDisplayError(const GifFileType* const gif, int gif_error) { #else // !WEBP_HAVE_GIF -static void ErrorGIFNotAvailable() { +static void ErrorGIFNotAvailable(void) { fprintf(stderr, "GIF support not compiled. Please install the libgif-dev " "package before building.\n"); } diff --git a/libwebp_src/examples/vwebp.c b/libwebp_src/examples/vwebp.c index 35f1b18..fa5fadb 100644 --- a/libwebp_src/examples/vwebp.c +++ b/libwebp_src/examples/vwebp.c @@ -18,6 +18,7 @@ #define _POSIX_C_SOURCE 200112L // for setenv #endif +#include #include #include #include @@ -430,10 +431,13 @@ static void HandleDisplay(void) { #endif } -static void StartDisplay(void) { +static void StartDisplay(const char* filename) { int width = kParams.canvas_width; int height = kParams.canvas_height; int screen_width, screen_height; + const char viewername[] = " - WebP viewer"; + // max linux file len + viewername string + char title[4096 + sizeof(viewername)] = ""; // TODO(webp:365) GLUT_DOUBLE results in flickering / old frames to be // partially displayed with animated webp + alpha. #if defined(__APPLE__) || defined(_WIN32) @@ -453,8 +457,9 @@ static void StartDisplay(void) { height = screen_height; } } + snprintf(title, sizeof(title), "%s%s", filename, viewername); glutInitWindowSize(width, height); - glutCreateWindow("WebP viewer"); + glutCreateWindow(title); glutDisplayFunc(HandleDisplay); glutReshapeFunc(HandleReshape); glutIdleFunc(NULL); @@ -493,7 +498,7 @@ static void Help(void) { } int main(int argc, char* argv[]) { - int c; + int c, file_name_argv_index = 1; WebPDecoderConfig* const config = &kParams.config; WebPIterator* const curr = &kParams.curr_frame; @@ -540,7 +545,10 @@ int main(int argc, char* argv[]) { } else if (!strcmp(argv[c], "-mt")) { config->options.use_threads = 1; } else if (!strcmp(argv[c], "--")) { - if (c < argc - 1) kParams.file_name = (const char*)GET_WARGV(argv, ++c); + if (c < argc - 1) { + kParams.file_name = (const char*)GET_WARGV(argv, ++c); + file_name_argv_index = c; + } break; } else if (argv[c][0] == '-') { printf("Unknown option '%s'\n", argv[c]); @@ -548,6 +556,7 @@ int main(int argc, char* argv[]) { FREE_WARGV_AND_RETURN(-1); } else { kParams.file_name = (const char*)GET_WARGV(argv, c); + file_name_argv_index = c; } if (parse_error) { @@ -613,7 +622,7 @@ int main(int argc, char* argv[]) { // Position iterator to last frame. Next call to HandleDisplay will wrap over. // We take this into account by bumping up loop_count. - WebPDemuxGetFrame(kParams.dmux, 0, curr); + if (!WebPDemuxGetFrame(kParams.dmux, 0, curr)) goto Error; if (kParams.loop_count) ++kParams.loop_count; #if defined(__unix__) || defined(__CYGWIN__) @@ -627,7 +636,7 @@ int main(int argc, char* argv[]) { #ifdef FREEGLUT glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION); #endif - StartDisplay(); + StartDisplay(argv[file_name_argv_index]); if (kParams.has_animation) glutTimerFunc(0, decode_callback, 0); glutMainLoop(); diff --git a/libwebp_src/examples/webpinfo.c b/libwebp_src/examples/webpinfo.c index 356abae..1d2278e 100644 --- a/libwebp_src/examples/webpinfo.c +++ b/libwebp_src/examples/webpinfo.c @@ -357,12 +357,12 @@ static WebPInfoStatus ParseLossyHeader(const ChunkData* const chunk_data, } data += 3; data_size -= 3; - printf(" Key frame: %s\n" - " Profile: %d\n" - " Display: %s\n" - " Part. 0 length: %d\n", - key_frame ? "Yes" : "No", profile, - display ? "Yes" : "No", partition0_length); + printf( + " Key frame: %s\n" + " Profile: %d\n" + " Display: Yes\n" + " Part. 0 length: %d\n", + key_frame ? "Yes" : "No", profile, partition0_length); if (key_frame) { if (!(data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a)) { LOG_ERROR("Invalid lossy bitstream signature."); diff --git a/libwebp_src/examples/webpmux.c b/libwebp_src/examples/webpmux.c index b61eed6..9bf4510 100644 --- a/libwebp_src/examples/webpmux.c +++ b/libwebp_src/examples/webpmux.c @@ -150,16 +150,20 @@ static const char* ErrorString(WebPMuxError err) { } #define RETURN_IF_ERROR(ERR_MSG) \ - if (err != WEBP_MUX_OK) { \ - fprintf(stderr, ERR_MSG); \ - return err; \ - } + do { \ + if (err != WEBP_MUX_OK) { \ + fprintf(stderr, ERR_MSG); \ + return err; \ + } \ + } while (0) #define RETURN_IF_ERROR3(ERR_MSG, FORMAT_STR1, FORMAT_STR2) \ - if (err != WEBP_MUX_OK) { \ - fprintf(stderr, ERR_MSG, FORMAT_STR1, FORMAT_STR2); \ - return err; \ - } + do { \ + if (err != WEBP_MUX_OK) { \ + fprintf(stderr, ERR_MSG, FORMAT_STR1, FORMAT_STR2); \ + return err; \ + } \ + } while (0) #define ERROR_GOTO1(ERR_MSG, LABEL) \ do { \ @@ -605,20 +609,26 @@ static int ValidateCommandLine(const CommandLineArguments* const cmd_args, #define FEATURETYPE_IS_NIL (config->type_ == NIL_FEATURE) #define CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL) \ - if (argc < i + (NUM)) { \ - fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \ - goto LABEL; \ - } + do { \ + if (argc < i + (NUM)) { \ + fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \ + goto LABEL; \ + } \ + } while (0) #define CHECK_NUM_ARGS_AT_MOST(NUM, LABEL) \ - if (argc > i + (NUM)) { \ - fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \ - goto LABEL; \ - } + do { \ + if (argc > i + (NUM)) { \ + fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \ + goto LABEL; \ + } \ + } while (0) #define CHECK_NUM_ARGS_EXACTLY(NUM, LABEL) \ - CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL); \ - CHECK_NUM_ARGS_AT_MOST(NUM, LABEL); + do { \ + CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL); \ + CHECK_NUM_ARGS_AT_MOST(NUM, LABEL); \ + } while (0) // Parses command-line arguments to fill up config object. Also performs some // semantic checks. unicode_argv contains wchar_t arguments or is null. diff --git a/libwebp_src/extras/Makefile.am b/libwebp_src/extras/Makefile.am index 7e29888..d5a9af4 100644 --- a/libwebp_src/extras/Makefile.am +++ b/libwebp_src/extras/Makefile.am @@ -7,6 +7,7 @@ noinst_HEADERS += ../src/webp/types.h libwebpextras_la_SOURCES = libwebpextras_la_SOURCES += extras.c extras.h quality_estimate.c +libwebpextras_la_SOURCES += sharpyuv_risk_table.c sharpyuv_risk_table.h libwebpextras_la_CPPFLAGS = $(AM_CPPFLAGS) libwebpextras_la_LDFLAGS = -lm diff --git a/libwebp_src/extras/extras.c b/libwebp_src/extras/extras.c index afe5b70..3a3d254 100644 --- a/libwebp_src/extras/extras.c +++ b/libwebp_src/extras/extras.c @@ -11,15 +11,21 @@ // #include "extras/extras.h" -#include "webp/format_constants.h" -#include "src/dsp/dsp.h" #include +#include #include +#include "extras/sharpyuv_risk_table.h" +#include "sharpyuv/sharpyuv.h" +#include "src/dsp/dsp.h" +#include "src/utils/utils.h" +#include "webp/format_constants.h" +#include "webp/types.h" + #define XTRA_MAJ_VERSION 1 -#define XTRA_MIN_VERSION 3 -#define XTRA_REV_VERSION 2 +#define XTRA_MIN_VERSION 4 +#define XTRA_REV_VERSION 0 //------------------------------------------------------------------------------ @@ -160,3 +166,159 @@ int WebPUnmultiplyARGB(WebPPicture* pic) { } //------------------------------------------------------------------------------ +// 420 risk metric + +#define YUV_FIX 16 // fixed-point precision for RGB->YUV +static const int kYuvHalf = 1 << (YUV_FIX - 1); + +// Maps a value in [0, (256 << YUV_FIX) - 1] to [0, +// precomputed_scores_table_sampling - 1]. It is important that the extremal +// values are preserved and 1:1 mapped: +// ConvertValue(0) = 0 +// ConvertValue((256 << 16) - 1) = rgb_sampling_size - 1 +static int SharpYuvConvertValueToSampledIdx(int v, int rgb_sampling_size) { + v = (v + kYuvHalf) >> YUV_FIX; + v = (v < 0) ? 0 : (v > 255) ? 255 : v; + return (v * (rgb_sampling_size - 1)) / 255; +} + +#undef YUV_FIX + +// For each pixel, computes the index to look up that color in a precomputed +// risk score table where the YUV space is subsampled to a size of +// precomputed_scores_table_sampling^3 (see sharpyuv_risk_table.h) +static int SharpYuvConvertToYuvSharpnessIndex( + int r, int g, int b, const SharpYuvConversionMatrix* matrix, + int precomputed_scores_table_sampling) { + const int y = SharpYuvConvertValueToSampledIdx( + matrix->rgb_to_y[0] * r + matrix->rgb_to_y[1] * g + + matrix->rgb_to_y[2] * b + matrix->rgb_to_y[3], + precomputed_scores_table_sampling); + const int u = SharpYuvConvertValueToSampledIdx( + matrix->rgb_to_u[0] * r + matrix->rgb_to_u[1] * g + + matrix->rgb_to_u[2] * b + matrix->rgb_to_u[3], + precomputed_scores_table_sampling); + const int v = SharpYuvConvertValueToSampledIdx( + matrix->rgb_to_v[0] * r + matrix->rgb_to_v[1] * g + + matrix->rgb_to_v[2] * b + matrix->rgb_to_v[3], + precomputed_scores_table_sampling); + return y + u * precomputed_scores_table_sampling + + v * precomputed_scores_table_sampling * + precomputed_scores_table_sampling; +} + +static void SharpYuvRowToYuvSharpnessIndex( + const uint8_t* r_ptr, const uint8_t* g_ptr, const uint8_t* b_ptr, + int rgb_step, int rgb_bit_depth, int width, uint16_t* dst, + const SharpYuvConversionMatrix* matrix, + int precomputed_scores_table_sampling) { + int i; + assert(rgb_bit_depth == 8); + (void)rgb_bit_depth; // Unused for now. + for (i = 0; i < width; + ++i, r_ptr += rgb_step, g_ptr += rgb_step, b_ptr += rgb_step) { + dst[i] = + SharpYuvConvertToYuvSharpnessIndex(r_ptr[0], g_ptr[0], b_ptr[0], matrix, + precomputed_scores_table_sampling); + } +} + +#define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((uint64_t)(W) * (H), sizeof(T))) + +static int DoEstimateRisk(const uint8_t* r_ptr, const uint8_t* g_ptr, + const uint8_t* b_ptr, int rgb_step, int rgb_stride, + int rgb_bit_depth, int width, int height, + const SharpYuvOptions* options, + const uint8_t precomputed_scores_table[], + int precomputed_scores_table_sampling, + float* score_out) { + const int sampling3 = precomputed_scores_table_sampling * + precomputed_scores_table_sampling * + precomputed_scores_table_sampling; + const int kNoiseLevel = 4; + double total_score = 0; + double count = 0; + // Rows of indices in + uint16_t* row1 = SAFE_ALLOC(width, 1, uint16_t); + uint16_t* row2 = SAFE_ALLOC(width, 1, uint16_t); + uint16_t* tmp; + int i, j; + + if (row1 == NULL || row2 == NULL) { + WebPFree(row1); + WebPFree(row2); + return 0; + } + + // Convert the first row ahead. + SharpYuvRowToYuvSharpnessIndex(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth, + width, row2, options->yuv_matrix, + precomputed_scores_table_sampling); + + for (j = 1; j < height; ++j) { + r_ptr += rgb_stride; + g_ptr += rgb_stride; + b_ptr += rgb_stride; + // Swap row 1 and row 2. + tmp = row1; + row1 = row2; + row2 = tmp; + // Convert the row below. + SharpYuvRowToYuvSharpnessIndex(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth, + width, row2, options->yuv_matrix, + precomputed_scores_table_sampling); + for (i = 0; i < width - 1; ++i) { + const int idx0 = row1[i + 0]; + const int idx1 = row1[i + 1]; + const int idx2 = row2[i + 0]; + const int score = precomputed_scores_table[idx0 + sampling3 * idx1] + + precomputed_scores_table[idx0 + sampling3 * idx2] + + precomputed_scores_table[idx1 + sampling3 * idx2]; + if (score > kNoiseLevel) { + total_score += score; + count += 1.0; + } + } + } + if (count > 0.) total_score /= count; + + // If less than 1% of pixels were evaluated -> below noise level. + if (100. * count / (width * height) < 1.) total_score = 0.; + + // Rescale to [0:100] + total_score = (total_score > 25.) ? 100. : total_score * 100. / 25.; + + WebPFree(row1); + WebPFree(row2); + + *score_out = (float)total_score; + return 1; +} + +#undef SAFE_ALLOC + +int SharpYuvEstimate420Risk(const void* r_ptr, const void* g_ptr, + const void* b_ptr, int rgb_step, int rgb_stride, + int rgb_bit_depth, int width, int height, + const SharpYuvOptions* options, float* score) { + if (width < 1 || height < 1 || width == INT_MAX || height == INT_MAX || + r_ptr == NULL || g_ptr == NULL || b_ptr == NULL || options == NULL || + score == NULL) { + return 0; + } + if (rgb_bit_depth != 8) { + return 0; + } + + if (width <= 4 || height <= 4) { + *score = 0.0f; // too small, no real risk. + return 1; + } + + return DoEstimateRisk( + (const uint8_t*)r_ptr, (const uint8_t*)g_ptr, (const uint8_t*)b_ptr, + rgb_step, rgb_stride, rgb_bit_depth, width, height, options, + kSharpYuvPrecomputedRisk, kSharpYuvPrecomputedRiskYuvSampling, score); +} + +//------------------------------------------------------------------------------ diff --git a/libwebp_src/extras/extras.h b/libwebp_src/extras/extras.h index c084682..3cc9d70 100644 --- a/libwebp_src/extras/extras.h +++ b/libwebp_src/extras/extras.h @@ -17,9 +17,10 @@ extern "C" { #endif +#include "sharpyuv/sharpyuv.h" #include "webp/encode.h" -#define WEBP_EXTRAS_ABI_VERSION 0x0002 // MAJOR(8b) + MINOR(8b) +#define WEBP_EXTRAS_ABI_VERSION 0x0003 // MAJOR(8b) + MINOR(8b) //------------------------------------------------------------------------------ @@ -70,6 +71,38 @@ WEBP_EXTERN int VP8EstimateQuality(const uint8_t* const data, size_t size); //------------------------------------------------------------------------------ +// Computes a score between 0 and 100 which represents the risk of having visual +// quality loss from converting an RGB image to YUV420. +// A low score, typically < 40, means there is a low risk of artifacts from +// chroma subsampling and a simple averaging algorithm can be used instead of +// the more expensive SharpYuvConvert function. +// A medium score, typically >= 40 and < 70, means that simple chroma +// subsampling will produce artifacts and it may be advisable to use the more +// costly SharpYuvConvert for YUV420 conversion. +// A high score, typically >= 70, means there is a very high risk of artifacts +// from chroma subsampling even with SharpYuvConvert, and best results might be +// achieved by using YUV444. +// If not using SharpYuvConvert, a threshold of about 50 can be used to decide +// between (simple averaging) 420 and 444. +// r_ptr, g_ptr, b_ptr: pointers to the source r, g and b channels. Should point +// to uint8_t buffers if rgb_bit_depth is 8, or uint16_t buffers otherwise. +// rgb_step: distance in bytes between two horizontally adjacent pixels on the +// r, g and b channels. If rgb_bit_depth is > 8, it should be a +// multiple of 2. +// rgb_stride: distance in bytes between two vertically adjacent pixels on the +// r, g, and b channels. If rgb_bit_depth is > 8, it should be a +// multiple of 2. +// rgb_bit_depth: number of bits for each r/g/b value. Only a value of 8 is +// currently supported. +// width, height: width and height of the image in pixels +// Returns 0 on failure. +WEBP_EXTERN int SharpYuvEstimate420Risk( + const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step, + int rgb_stride, int rgb_bit_depth, int width, int height, + const SharpYuvOptions* options, float* score); + +//------------------------------------------------------------------------------ + #ifdef __cplusplus } // extern "C" #endif diff --git a/libwebp_src/extras/sharpyuv_risk_table.c b/libwebp_src/extras/sharpyuv_risk_table.c new file mode 100644 index 0000000..ab3e7fd --- /dev/null +++ b/libwebp_src/extras/sharpyuv_risk_table.c @@ -0,0 +1,6210 @@ +// Copyright 2023 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Precomputed data for 420 risk estimation. + +#include "src/webp/types.h" + +const int kSharpYuvPrecomputedRiskYuvSampling = 7; + +const uint8_t kSharpYuvPrecomputedRisk[] = { + 0, 2, 2, 3, 3, 2, 2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 2, 2, 2, + 1, 2, 2, 1, 1, 2, 2, 3, 4, 4, 4, 4, 4, 5, 4, 4, 8, 8, 8, + 7, 5, 4, 4, 14, 12, 9, 8, 6, 4, 4, 2, 1, 2, 2, 2, 2, 1, 2, + 0, 2, 2, 2, 1, 1, 2, 1, 1, 2, 2, 1, 3, 2, 2, 2, 2, 2, 3, + 4, 5, 5, 5, 5, 5, 4, 4, 11, 9, 9, 8, 6, 5, 4, 18, 14, 11, 9, + 7, 5, 4, 2, 1, 1, 1, 1, 3, 6, 2, 2, 1, 1, 1, 3, 6, 3, 2, + 2, 2, 3, 3, 7, 6, 3, 5, 6, 6, 6, 8, 9, 7, 9, 9, 9, 8, 8, + 14, 12, 13, 12, 11, 10, 8, 20, 18, 16, 14, 13, 11, 10, 3, 6, 6, 7, 7, + 7, 10, 6, 7, 7, 8, 8, 8, 10, 10, 7, 9, 9, 10, 10, 10, 13, 10, 12, + 13, 13, 13, 12, 13, 15, 17, 17, 17, 16, 15, 14, 22, 21, 20, 19, 18, 17, 20, + 27, 25, 23, 20, 19, 19, 14, 15, 14, 14, 15, 14, 9, 16, 16, 16, 16, 16, 15, + 9, 16, 17, 18, 18, 18, 17, 14, 16, 21, 21, 22, 22, 20, 17, 19, 26, 27, 26, + 25, 24, 18, 23, 30, 32, 29, 28, 25, 20, 27, 33, 35, 32, 30, 28, 22, 24, 25, + 24, 24, 21, 17, 12, 23, 27, 25, 26, 22, 17, 14, 24, 30, 29, 28, 24, 20, 17, + 24, 31, 32, 32, 28, 24, 20, 27, 34, 37, 36, 32, 27, 22, 30, 36, 42, 41, 34, + 29, 23, 33, 39, 44, 44, 38, 31, 26, 32, 37, 36, 29, 23, 19, 15, 31, 38, 39, + 31, 25, 20, 16, 31, 38, 41, 34, 28, 24, 20, 31, 38, 44, 38, 33, 27, 24, 34, + 41, 46, 45, 37, 31, 25, 36, 43, 47, 49, 40, 33, 27, 39, 44, 49, 49, 42, 36, + 29, 2, 0, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 1, 1, 2, 2, 1, 2, + 1, 2, 3, 2, 2, 2, 2, 3, 4, 5, 5, 5, 5, 5, 6, 5, 5, 9, 9, + 9, 8, 6, 5, 5, 15, 14, 10, 8, 7, 5, 5, 2, 2, 1, 2, 1, 1, 4, + 2, 2, 0, 2, 1, 1, 4, 2, 2, 1, 1, 1, 3, 5, 3, 3, 3, 3, 3, + 4, 6, 7, 6, 7, 6, 6, 5, 6, 12, 11, 10, 9, 8, 7, 6, 19, 16, 12, + 10, 9, 8, 6, 2, 2, 3, 3, 3, 5, 7, 3, 2, 3, 4, 4, 5, 7, 7, + 2, 4, 6, 6, 6, 9, 10, 4, 8, 9, 9, 9, 11, 13, 8, 11, 13, 13, 12, + 11, 17, 14, 15, 16, 15, 14, 10, 21, 20, 18, 18, 16, 15, 13, 7, 7, 9, 9, + 10, 8, 11, 11, 8, 10, 11, 11, 11, 11, 13, 8, 11, 13, 13, 14, 13, 16, 11, + 16, 17, 17, 17, 15, 17, 17, 20, 21, 21, 20, 18, 18, 23, 25, 24, 23, 21, 20, + 21, 29, 28, 26, 25, 23, 22, 16, 17, 17, 17, 18, 17, 11, 20, 18, 19, 19, 19, + 18, 11, 19, 20, 20, 22, 21, 20, 16, 19, 24, 26, 25, 26, 24, 22, 21, 29, 31, + 30, 31, 27, 22, 26, 33, 35, 33, 31, 30, 25, 30, 36, 39, 36, 35, 31, 26, 27, + 28, 28, 27, 23, 20, 15, 26, 30, 29, 29, 25, 21, 17, 27, 32, 32, 32, 28, 24, + 21, 26, 35, 38, 37, 32, 29, 25, 30, 38, 41, 41, 36, 31, 25, 34, 40, 47, 45, + 39, 33, 27, 37, 44, 48, 49, 41, 35, 29, 35, 42, 40, 33, 27, 22, 18, 36, 41, + 42, 34, 29, 24, 21, 36, 41, 46, 38, 32, 28, 24, 35, 43, 49, 42, 37, 32, 28, + 38, 45, 51, 48, 42, 36, 30, 40, 47, 53, 51, 44, 38, 32, 44, 49, 54, 55, 47, + 39, 34, 2, 2, 0, 2, 2, 1, 2, 3, 2, 1, 2, 2, 1, 3, 3, 2, 1, + 1, 2, 3, 5, 3, 3, 3, 3, 3, 4, 5, 6, 6, 7, 6, 6, 5, 6, 11, + 10, 10, 9, 7, 5, 5, 17, 15, 12, 10, 8, 5, 6, 3, 2, 2, 1, 1, 3, + 6, 3, 2, 2, 1, 1, 3, 6, 4, 3, 2, 2, 3, 5, 7, 7, 4, 4, 5, + 6, 6, 8, 11, 7, 8, 9, 9, 6, 9, 14, 12, 12, 11, 11, 10, 8, 20, 17, + 14, 12, 13, 11, 9, 4, 3, 4, 5, 6, 6, 8, 8, 3, 4, 6, 7, 6, 9, + 11, 3, 5, 9, 10, 8, 11, 14, 5, 9, 12, 13, 12, 13, 17, 10, 12, 16, 17, + 16, 13, 21, 15, 17, 20, 19, 17, 12, 23, 20, 20, 21, 20, 19, 16, 11, 8, 12, + 13, 12, 10, 13, 15, 9, 12, 14, 14, 14, 14, 18, 10, 13, 16, 17, 17, 16, 20, + 14, 18, 20, 21, 21, 18, 21, 20, 22, 24, 25, 24, 21, 21, 25, 27, 28, 27, 26, + 25, 23, 31, 30, 30, 28, 27, 26, 19, 19, 20, 21, 21, 20, 13, 23, 21, 21, 22, + 23, 21, 14, 23, 22, 23, 25, 25, 25, 19, 23, 26, 28, 29, 29, 28, 25, 24, 31, + 34, 34, 34, 32, 26, 28, 36, 40, 38, 37, 34, 28, 32, 40, 43, 40, 39, 35, 29, + 29, 32, 31, 30, 26, 22, 17, 29, 33, 32, 32, 29, 25, 21, 29, 36, 36, 36, 32, + 28, 24, 29, 38, 42, 40, 36, 32, 28, 32, 42, 45, 44, 40, 35, 30, 37, 45, 50, + 49, 42, 37, 31, 40, 47, 52, 52, 46, 39, 33, 38, 45, 42, 36, 30, 25, 21, 39, + 45, 45, 38, 32, 28, 24, 39, 45, 49, 42, 37, 32, 28, 38, 46, 52, 46, 41, 35, + 31, 42, 49, 55, 52, 45, 40, 34, 45, 51, 57, 57, 48, 42, 36, 48, 53, 58, 57, + 51, 44, 38, 3, 2, 2, 0, 0, 2, 4, 3, 2, 2, 0, 1, 3, 6, 3, 3, + 2, 2, 2, 4, 7, 4, 4, 4, 5, 4, 5, 7, 8, 7, 8, 8, 7, 6, 7, + 12, 11, 12, 10, 8, 6, 7, 18, 16, 13, 11, 9, 6, 8, 3, 2, 2, 2, 3, + 5, 7, 4, 3, 2, 2, 3, 6, 8, 8, 3, 2, 3, 6, 7, 9, 11, 4, 5, + 6, 9, 8, 11, 14, 8, 9, 10, 12, 8, 11, 17, 13, 13, 13, 14, 12, 11, 22, + 18, 15, 13, 16, 15, 11, 8, 3, 5, 8, 8, 8, 10, 12, 3, 5, 8, 10, 8, + 11, 15, 5, 6, 11, 13, 9, 13, 18, 9, 10, 15, 16, 16, 16, 21, 12, 14, 19, + 19, 19, 16, 24, 17, 18, 21, 22, 21, 16, 26, 22, 20, 23, 23, 22, 19, 15, 9, + 13, 15, 16, 12, 15, 18, 11, 14, 16, 17, 17, 17, 22, 13, 15, 19, 21, 21, 19, + 26, 17, 20, 24, 23, 25, 21, 26, 22, 24, 27, 28, 27, 24, 25, 27, 30, 31, 31, + 29, 27, 25, 33, 33, 33, 32, 31, 30, 23, 20, 22, 24, 24, 23, 16, 26, 22, 25, + 25, 26, 25, 17, 26, 25, 26, 28, 30, 28, 22, 26, 29, 31, 33, 33, 32, 27, 28, + 34, 37, 36, 38, 36, 30, 30, 39, 42, 42, 41, 37, 32, 34, 43, 46, 44, 42, 39, + 33, 31, 34, 33, 33, 30, 26, 20, 31, 36, 35, 35, 32, 28, 24, 32, 37, 39, 39, + 36, 31, 28, 32, 40, 45, 42, 40, 37, 32, 34, 44, 50, 48, 44, 40, 34, 39, 47, + 54, 52, 47, 40, 35, 43, 48, 56, 56, 49, 43, 37, 43, 46, 45, 39, 32, 29, 25, + 42, 47, 47, 40, 35, 31, 28, 41, 47, 49, 44, 39, 36, 31, 42, 48, 55, 50, 44, + 40, 34, 45, 52, 57, 55, 49, 43, 38, 48, 54, 59, 60, 53, 44, 39, 51, 57, 61, + 60, 54, 47, 41, 3, 2, 2, 0, 0, 2, 4, 3, 2, 2, 1, 0, 3, 6, 3, + 2, 2, 2, 2, 4, 6, 4, 4, 4, 4, 4, 5, 7, 8, 7, 8, 8, 7, 6, + 8, 12, 12, 11, 11, 8, 6, 8, 18, 16, 13, 11, 9, 6, 8, 3, 2, 2, 2, + 3, 5, 7, 4, 3, 2, 2, 3, 6, 8, 8, 3, 2, 3, 6, 7, 9, 12, 5, + 5, 6, 9, 8, 11, 14, 8, 9, 10, 12, 8, 10, 17, 13, 13, 13, 14, 13, 11, + 22, 18, 15, 13, 15, 15, 11, 8, 3, 5, 8, 8, 8, 10, 12, 3, 5, 9, 10, + 8, 11, 16, 5, 6, 11, 13, 9, 13, 17, 8, 9, 15, 16, 15, 15, 22, 12, 14, + 19, 20, 20, 16, 24, 17, 18, 21, 22, 21, 16, 26, 22, 20, 23, 24, 22, 19, 15, + 9, 13, 15, 15, 12, 16, 18, 11, 14, 16, 17, 17, 17, 21, 13, 15, 19, 21, 21, + 19, 26, 17, 20, 23, 24, 25, 20, 25, 21, 24, 27, 27, 27, 24, 24, 27, 29, 30, + 30, 29, 27, 26, 33, 32, 33, 32, 31, 30, 23, 21, 23, 24, 23, 22, 15, 26, 22, + 24, 24, 26, 25, 17, 26, 24, 25, 28, 30, 27, 22, 26, 29, 30, 33, 33, 32, 27, + 28, 34, 36, 38, 37, 35, 30, 30, 38, 43, 42, 41, 37, 32, 33, 42, 46, 44, 42, + 39, 34, 32, 34, 33, 33, 29, 26, 20, 32, 37, 35, 35, 32, 28, 24, 31, 38, 38, + 39, 36, 32, 28, 31, 40, 44, 44, 39, 36, 32, 35, 42, 49, 48, 44, 40, 33, 39, + 47, 54, 53, 46, 40, 36, 44, 50, 54, 55, 48, 43, 37, 40, 47, 44, 37, 33, 28, + 25, 41, 48, 47, 40, 35, 31, 28, 40, 47, 50, 44, 40, 35, 31, 41, 49, 55, 50, + 44, 39, 35, 44, 52, 58, 55, 47, 43, 38, 48, 55, 60, 59, 50, 45, 39, 50, 57, + 62, 62, 53, 47, 42, 2, 2, 1, 2, 2, 0, 3, 2, 2, 1, 2, 2, 1, 4, + 2, 2, 1, 2, 4, 3, 5, 3, 3, 4, 4, 6, 6, 6, 6, 7, 7, 7, 9, + 8, 6, 11, 11, 11, 10, 9, 8, 6, 18, 15, 13, 11, 10, 7, 6, 2, 2, 2, + 1, 1, 3, 5, 3, 2, 2, 1, 1, 4, 6, 6, 2, 2, 3, 4, 5, 7, 10, + 4, 5, 6, 7, 6, 9, 11, 8, 9, 9, 10, 7, 8, 16, 13, 13, 12, 12, 11, + 9, 21, 18, 15, 13, 14, 13, 9, 6, 2, 4, 6, 6, 6, 8, 10, 2, 4, 7, + 8, 6, 9, 14, 3, 5, 9, 10, 7, 11, 16, 6, 9, 13, 14, 13, 13, 18, 11, + 12, 17, 18, 17, 13, 22, 16, 17, 20, 20, 18, 13, 25, 22, 20, 22, 22, 20, 17, + 14, 7, 12, 13, 13, 9, 13, 17, 9, 12, 14, 15, 14, 14, 20, 12, 13, 17, 18, + 19, 16, 22, 15, 18, 22, 22, 22, 18, 22, 20, 22, 25, 26, 25, 21, 23, 25, 28, + 28, 28, 27, 24, 24, 31, 31, 30, 30, 29, 27, 22, 19, 21, 21, 21, 20, 13, 24, + 20, 22, 22, 23, 22, 14, 24, 22, 23, 26, 26, 25, 19, 25, 26, 28, 29, 32, 29, + 25, 25, 32, 34, 35, 35, 32, 27, 28, 36, 41, 39, 37, 34, 30, 32, 40, 43, 43, + 39, 36, 30, 29, 32, 32, 30, 26, 22, 17, 29, 35, 32, 32, 29, 25, 22, 29, 35, + 35, 36, 33, 29, 25, 29, 38, 41, 41, 37, 33, 29, 33, 41, 47, 45, 42, 37, 30, + 38, 44, 52, 52, 44, 38, 32, 41, 47, 53, 53, 47, 40, 34, 39, 46, 42, 36, 30, + 26, 22, 39, 45, 45, 38, 33, 29, 25, 39, 44, 48, 42, 36, 33, 28, 39, 46, 52, + 47, 41, 37, 33, 42, 50, 54, 52, 45, 39, 36, 45, 52, 58, 56, 49, 43, 35, 49, + 54, 58, 59, 52, 44, 37, 1, 1, 2, 4, 4, 3, 0, 2, 1, 2, 4, 4, 3, + 2, 2, 1, 1, 4, 5, 4, 4, 2, 3, 3, 5, 7, 7, 6, 5, 6, 7, 8, + 10, 8, 7, 10, 10, 11, 11, 10, 8, 7, 17, 15, 12, 11, 11, 8, 7, 2, 1, + 1, 3, 2, 2, 3, 2, 2, 1, 2, 2, 2, 4, 2, 2, 1, 3, 3, 3, 5, + 6, 3, 4, 5, 5, 4, 6, 9, 7, 8, 8, 8, 6, 6, 13, 12, 12, 11, 9, + 8, 6, 20, 18, 13, 12, 11, 9, 6, 2, 2, 3, 3, 3, 5, 6, 6, 2, 3, + 4, 4, 4, 6, 11, 2, 4, 7, 7, 5, 8, 15, 4, 8, 10, 10, 10, 10, 16, + 9, 11, 14, 14, 14, 10, 19, 14, 16, 18, 16, 15, 10, 23, 21, 19, 19, 18, 16, + 14, 11, 7, 9, 10, 10, 7, 11, 15, 7, 10, 11, 12, 11, 11, 17, 9, 12, 14, + 15, 15, 12, 19, 13, 16, 18, 18, 18, 14, 19, 17, 20, 22, 23, 22, 18, 20, 23, + 26, 26, 25, 23, 21, 22, 29, 29, 27, 26, 25, 23, 19, 17, 18, 18, 18, 17, 11, + 22, 18, 20, 19, 20, 19, 11, 22, 20, 21, 23, 23, 22, 17, 22, 24, 26, 27, 27, + 26, 22, 23, 30, 31, 32, 32, 28, 24, 25, 34, 37, 36, 34, 30, 26, 30, 37, 41, + 37, 36, 33, 27, 27, 29, 27, 27, 24, 20, 15, 26, 31, 30, 29, 26, 22, 18, 27, + 33, 32, 33, 30, 26, 22, 26, 35, 39, 36, 34, 29, 25, 31, 37, 43, 42, 38, 33, + 28, 35, 44, 48, 47, 40, 34, 30, 38, 45, 49, 49, 42, 37, 31, 35, 41, 38, 32, + 26, 23, 18, 36, 42, 41, 35, 29, 25, 22, 36, 40, 43, 38, 33, 29, 25, 36, 42, + 50, 43, 37, 34, 29, 39, 45, 52, 47, 42, 37, 31, 42, 47, 53, 54, 45, 39, 33, + 46, 51, 54, 54, 46, 40, 35, 1, 2, 3, 3, 3, 2, 2, 0, 2, 2, 3, 3, + 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 3, 4, + 4, 5, 4, 4, 7, 7, 7, 7, 5, 4, 4, 13, 12, 9, 7, 6, 4, 4, 1, + 2, 2, 3, 2, 2, 1, 2, 1, 2, 2, 2, 1, 0, 2, 0, 2, 2, 2, 1, + 2, 2, 2, 2, 2, 2, 3, 4, 5, 5, 5, 5, 5, 4, 4, 10, 9, 9, 8, + 6, 4, 4, 17, 14, 11, 8, 6, 5, 4, 2, 1, 1, 2, 2, 2, 5, 2, 1, + 1, 1, 1, 2, 6, 2, 2, 1, 2, 2, 2, 6, 5, 3, 4, 4, 5, 5, 7, + 8, 7, 8, 8, 8, 7, 7, 13, 12, 12, 11, 10, 9, 7, 20, 17, 15, 13, 11, + 10, 9, 2, 5, 6, 6, 6, 6, 9, 5, 6, 6, 7, 7, 7, 9, 8, 7, 8, + 8, 9, 9, 9, 11, 9, 11, 12, 12, 12, 11, 12, 15, 15, 16, 15, 15, 14, 14, + 20, 20, 20, 18, 17, 16, 19, 27, 24, 21, 20, 18, 17, 13, 14, 13, 14, 14, 13, + 9, 15, 15, 14, 15, 15, 14, 9, 15, 17, 17, 17, 17, 16, 12, 15, 21, 20, 20, + 21, 19, 16, 18, 25, 25, 24, 24, 23, 17, 22, 29, 30, 29, 26, 24, 19, 26, 32, + 33, 31, 29, 26, 21, 23, 24, 23, 22, 20, 15, 12, 23, 27, 25, 25, 21, 16, 13, + 23, 28, 28, 26, 23, 19, 15, 23, 30, 32, 31, 28, 22, 19, 26, 32, 36, 36, 31, + 26, 20, 29, 34, 41, 39, 34, 28, 23, 31, 38, 41, 42, 35, 30, 25, 31, 37, 35, + 29, 23, 18, 14, 31, 37, 38, 30, 25, 19, 15, 30, 36, 40, 33, 27, 23, 18, 30, + 37, 44, 37, 31, 26, 23, 33, 39, 45, 43, 36, 30, 24, 36, 42, 48, 47, 39, 31, + 27, 38, 43, 48, 49, 42, 34, 28, 2, 1, 2, 2, 2, 2, 1, 2, 0, 2, 3, + 2, 2, 1, 2, 1, 1, 2, 2, 1, 3, 2, 2, 2, 2, 3, 3, 5, 5, 5, + 5, 5, 5, 5, 4, 9, 8, 8, 8, 6, 5, 4, 15, 13, 10, 8, 7, 5, 4, + 2, 1, 2, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 3, 2, 2, 1, 1, 1, + 2, 5, 2, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 4, 6, 11, 10, 10, + 9, 7, 5, 6, 19, 15, 12, 9, 8, 7, 6, 2, 2, 2, 2, 2, 4, 7, 3, + 2, 3, 3, 3, 5, 7, 5, 2, 4, 5, 5, 5, 8, 9, 3, 7, 8, 8, 8, + 9, 12, 8, 11, 11, 12, 11, 10, 16, 13, 15, 15, 14, 12, 10, 21, 19, 18, 17, + 15, 14, 13, 5, 7, 8, 8, 9, 8, 11, 9, 7, 9, 10, 10, 10, 11, 12, 8, + 11, 11, 12, 12, 12, 16, 11, 15, 16, 16, 15, 14, 16, 17, 19, 19, 20, 19, 17, + 16, 23, 24, 23, 22, 20, 19, 21, 29, 27, 25, 23, 22, 20, 16, 16, 17, 16, 17, + 16, 10, 18, 18, 18, 18, 18, 17, 11, 18, 19, 20, 20, 21, 19, 16, 18, 24, 24, + 25, 25, 23, 20, 21, 29, 29, 28, 28, 26, 21, 24, 32, 34, 33, 31, 28, 24, 29, + 36, 38, 34, 33, 30, 25, 26, 28, 26, 26, 22, 18, 14, 25, 31, 28, 28, 23, 19, + 16, 26, 32, 31, 31, 27, 23, 19, 26, 33, 36, 33, 32, 26, 22, 29, 36, 40, 38, + 35, 30, 25, 33, 39, 45, 44, 36, 31, 27, 35, 42, 45, 46, 41, 33, 29, 35, 41, + 38, 31, 26, 21, 17, 35, 40, 41, 34, 27, 23, 19, 35, 41, 44, 37, 30, 26, 22, + 34, 41, 47, 41, 35, 31, 26, 37, 43, 50, 47, 40, 34, 29, 39, 46, 52, 51, 42, + 37, 30, 42, 49, 53, 53, 44, 39, 32, 2, 1, 1, 2, 2, 1, 2, 2, 2, 0, + 2, 2, 1, 3, 3, 2, 1, 1, 2, 2, 4, 3, 3, 3, 3, 3, 4, 5, 5, + 6, 6, 6, 6, 5, 5, 10, 10, 9, 8, 7, 5, 5, 17, 15, 11, 9, 7, 5, + 5, 3, 2, 1, 1, 1, 3, 5, 3, 2, 2, 1, 1, 3, 6, 3, 2, 2, 2, + 2, 4, 7, 6, 4, 4, 4, 5, 5, 8, 9, 7, 7, 8, 8, 5, 8, 13, 12, + 11, 11, 10, 9, 8, 20, 17, 13, 11, 11, 10, 8, 3, 2, 4, 5, 5, 6, 8, + 6, 3, 4, 6, 6, 6, 8, 10, 3, 5, 8, 8, 7, 10, 13, 4, 9, 11, 12, + 11, 12, 16, 9, 12, 15, 15, 15, 12, 20, 14, 16, 18, 17, 16, 12, 22, 20, 19, + 20, 19, 17, 16, 10, 7, 11, 11, 11, 9, 12, 13, 8, 11, 12, 13, 13, 13, 16, + 10, 13, 16, 16, 16, 15, 18, 13, 17, 19, 19, 19, 17, 20, 18, 22, 23, 24, 22, + 19, 20, 24, 27, 27, 25, 25, 22, 23, 30, 30, 28, 27, 26, 25, 19, 18, 19, 19, + 20, 18, 12, 21, 19, 20, 21, 21, 20, 13, 22, 21, 23, 24, 25, 23, 18, 21, 26, + 27, 28, 28, 27, 23, 24, 31, 33, 32, 33, 30, 25, 27, 36, 38, 36, 34, 31, 26, + 31, 39, 41, 38, 37, 34, 28, 28, 31, 30, 29, 25, 21, 17, 28, 33, 32, 31, 28, + 23, 19, 27, 35, 35, 34, 31, 26, 23, 28, 36, 40, 38, 35, 30, 27, 32, 41, 45, + 44, 39, 34, 29, 35, 43, 51, 48, 42, 36, 30, 39, 46, 51, 50, 44, 38, 32, 37, + 44, 41, 34, 29, 24, 20, 39, 44, 44, 37, 32, 26, 23, 38, 43, 47, 40, 36, 31, + 26, 38, 45, 50, 45, 39, 35, 30, 40, 48, 54, 50, 43, 37, 32, 44, 51, 56, 53, + 46, 40, 34, 46, 52, 57, 57, 49, 42, 37, 3, 2, 2, 0, 0, 2, 4, 3, 3, + 2, 0, 1, 2, 5, 3, 3, 2, 2, 2, 3, 6, 4, 4, 4, 4, 4, 5, 7, + 7, 7, 7, 7, 7, 6, 7, 12, 11, 11, 10, 8, 6, 7, 17, 15, 12, 10, 9, + 6, 7, 3, 3, 2, 2, 2, 5, 7, 3, 3, 2, 2, 2, 5, 8, 7, 3, 2, + 3, 5, 6, 9, 10, 4, 5, 6, 8, 7, 10, 13, 8, 9, 9, 12, 8, 10, 16, + 13, 13, 12, 13, 12, 10, 22, 18, 14, 13, 15, 14, 10, 7, 3, 5, 7, 7, 8, + 10, 11, 3, 5, 8, 9, 8, 11, 14, 4, 6, 11, 12, 9, 12, 17, 7, 9, 14, + 15, 15, 15, 19, 11, 13, 18, 19, 18, 15, 24, 16, 18, 20, 21, 20, 15, 25, 21, + 20, 22, 22, 21, 18, 14, 8, 13, 14, 14, 11, 15, 17, 10, 13, 15, 17, 16, 16, + 20, 12, 14, 18, 20, 20, 18, 22, 16, 19, 22, 23, 23, 19, 23, 21, 24, 26, 27, + 27, 23, 24, 26, 29, 30, 30, 28, 27, 25, 32, 32, 31, 31, 29, 29, 22, 20, 22, + 23, 23, 22, 15, 27, 21, 24, 24, 25, 24, 16, 25, 23, 26, 28, 28, 27, 21, 25, + 29, 30, 32, 33, 31, 27, 27, 34, 36, 37, 37, 34, 29, 30, 38, 42, 41, 38, 35, + 31, 32, 41, 45, 42, 42, 38, 33, 32, 33, 34, 32, 29, 25, 19, 31, 36, 35, 34, + 32, 27, 24, 31, 38, 37, 38, 34, 30, 27, 31, 39, 43, 42, 39, 35, 31, 35, 43, + 50, 47, 44, 39, 33, 39, 47, 55, 52, 46, 39, 34, 43, 50, 54, 55, 49, 42, 36, + 41, 46, 44, 38, 32, 27, 24, 41, 46, 46, 40, 34, 31, 27, 40, 48, 50, 44, 40, + 35, 30, 41, 47, 55, 48, 43, 39, 34, 44, 50, 58, 54, 48, 42, 37, 47, 54, 60, + 58, 52, 45, 37, 50, 55, 61, 60, 54, 47, 39, 2, 2, 2, 1, 1, 2, 4, 3, + 2, 2, 1, 0, 2, 5, 3, 2, 2, 2, 2, 4, 6, 4, 4, 4, 4, 4, 5, + 7, 8, 7, 7, 7, 7, 6, 7, 12, 11, 11, 10, 8, 6, 7, 17, 15, 13, 10, + 9, 6, 7, 3, 2, 2, 1, 3, 5, 8, 4, 2, 2, 2, 3, 5, 8, 7, 3, + 2, 3, 6, 6, 9, 11, 4, 5, 6, 9, 7, 10, 14, 8, 8, 9, 12, 8, 10, + 17, 13, 13, 12, 14, 12, 10, 22, 18, 14, 13, 15, 14, 10, 7, 3, 5, 8, 8, + 9, 11, 12, 3, 5, 8, 9, 8, 11, 15, 5, 5, 11, 12, 9, 13, 18, 8, 9, + 15, 16, 15, 15, 21, 12, 13, 18, 19, 19, 15, 25, 16, 18, 21, 21, 21, 15, 25, + 22, 20, 23, 23, 22, 19, 15, 8, 13, 15, 15, 12, 16, 18, 10, 14, 16, 17, 17, + 17, 21, 13, 14, 19, 20, 21, 18, 25, 17, 19, 23, 23, 24, 20, 25, 21, 24, 27, + 28, 27, 23, 25, 26, 29, 31, 30, 28, 26, 25, 32, 32, 32, 31, 31, 29, 23, 21, + 22, 24, 24, 23, 16, 26, 22, 23, 24, 26, 25, 17, 26, 24, 26, 28, 30, 28, 21, + 26, 28, 31, 33, 33, 32, 27, 27, 35, 36, 36, 38, 35, 30, 29, 38, 41, 42, 39, + 36, 31, 34, 41, 45, 43, 42, 38, 33, 32, 34, 34, 32, 30, 25, 20, 31, 35, 35, + 35, 32, 28, 23, 31, 38, 38, 38, 35, 31, 28, 31, 40, 44, 43, 39, 35, 32, 34, + 43, 49, 47, 43, 40, 32, 40, 46, 54, 52, 46, 39, 35, 43, 50, 55, 55, 48, 42, + 36, 42, 47, 45, 39, 33, 28, 24, 41, 47, 48, 40, 35, 31, 27, 41, 47, 50, 45, + 40, 35, 31, 42, 48, 56, 49, 44, 39, 35, 45, 51, 57, 55, 48, 42, 37, 48, 53, + 61, 59, 51, 44, 39, 50, 57, 61, 61, 54, 48, 40, 2, 1, 1, 3, 3, 1, 3, + 2, 1, 1, 2, 2, 0, 3, 2, 2, 1, 1, 2, 2, 4, 2, 3, 3, 3, 4, + 4, 5, 5, 6, 6, 6, 7, 6, 5, 10, 10, 9, 9, 8, 6, 5, 16, 14, 11, + 9, 8, 6, 5, 2, 2, 1, 1, 2, 4, 6, 2, 2, 1, 1, 2, 3, 5, 4, + 2, 1, 2, 3, 4, 6, 9, 3, 4, 4, 6, 5, 7, 11, 7, 7, 8, 9, 5, + 7, 14, 11, 11, 11, 11, 9, 7, 19, 16, 13, 11, 12, 11, 7, 5, 2, 4, 6, + 7, 7, 9, 9, 2, 4, 7, 7, 6, 8, 13, 2, 5, 9, 9, 6, 10, 15, 5, + 8, 12, 12, 12, 12, 18, 9, 11, 16, 16, 15, 12, 21, 14, 16, 19, 18, 17, 12, + 23, 20, 18, 20, 19, 18, 16, 13, 7, 11, 12, 13, 11, 14, 16, 8, 12, 14, 15, + 14, 13, 19, 10, 13, 16, 17, 18, 15, 21, 14, 17, 20, 20, 20, 16, 22, 19, 21, + 24, 24, 24, 20, 21, 24, 26, 27, 26, 26, 23, 22, 30, 29, 28, 28, 27, 26, 20, + 19, 20, 20, 22, 21, 14, 23, 20, 22, 23, 23, 21, 13, 23, 22, 24, 25, 26, 24, + 19, 24, 26, 28, 29, 29, 28, 23, 25, 31, 34, 33, 34, 32, 25, 28, 36, 39, 37, + 36, 33, 28, 30, 39, 41, 39, 38, 34, 30, 29, 32, 31, 31, 28, 23, 19, 28, 33, + 33, 32, 29, 24, 20, 28, 37, 35, 37, 32, 28, 24, 28, 37, 41, 40, 37, 33, 28, + 31, 39, 46, 43, 40, 35, 29, 37, 43, 51, 48, 42, 36, 31, 39, 46, 51, 51, 44, + 39, 33, 39, 44, 42, 36, 30, 26, 22, 39, 44, 45, 38, 32, 28, 24, 39, 44, 47, + 41, 35, 31, 27, 38, 47, 51, 45, 40, 35, 31, 41, 48, 54, 51, 44, 39, 33, 46, + 51, 56, 57, 47, 40, 35, 47, 53, 58, 58, 49, 43, 37, 1, 1, 3, 6, 6, 4, + 2, 1, 1, 3, 5, 5, 3, 0, 2, 1, 2, 3, 4, 3, 2, 2, 2, 2, 3, + 5, 5, 4, 4, 5, 5, 6, 8, 6, 4, 9, 8, 8, 8, 8, 6, 4, 14, 12, + 10, 8, 9, 6, 4, 2, 1, 2, 4, 3, 3, 5, 2, 1, 1, 3, 3, 2, 3, + 2, 1, 1, 1, 1, 2, 4, 3, 3, 3, 3, 3, 3, 4, 8, 6, 6, 6, 6, + 4, 4, 12, 10, 10, 9, 7, 6, 5, 18, 14, 11, 10, 8, 7, 5, 2, 1, 3, + 4, 5, 6, 8, 4, 2, 3, 5, 5, 5, 6, 9, 2, 4, 6, 6, 4, 6, 12, + 3, 7, 9, 9, 9, 8, 16, 8, 10, 12, 13, 12, 8, 18, 13, 14, 15, 14, 13, + 8, 20, 18, 16, 17, 16, 15, 13, 8, 6, 9, 10, 11, 9, 11, 13, 7, 10, 11, + 12, 12, 11, 15, 8, 11, 13, 13, 13, 11, 17, 11, 15, 16, 16, 16, 13, 19, 16, + 19, 21, 21, 20, 16, 18, 21, 23, 24, 23, 22, 19, 20, 27, 26, 25, 24, 23, 21, + 17, 17, 18, 18, 19, 18, 12, 21, 18, 19, 19, 20, 18, 11, 20, 20, 21, 22, 22, + 21, 15, 20, 24, 25, 25, 26, 24, 19, 22, 28, 29, 29, 30, 28, 22, 24, 33, 36, + 35, 32, 29, 24, 28, 36, 39, 36, 35, 31, 26, 27, 29, 27, 27, 24, 21, 17, 26, + 32, 30, 29, 25, 21, 16, 26, 33, 33, 31, 27, 23, 20, 25, 36, 36, 34, 32, 28, + 23, 29, 37, 42, 41, 34, 31, 26, 32, 40, 46, 44, 38, 33, 27, 37, 41, 47, 46, + 40, 34, 29, 36, 41, 39, 32, 27, 24, 19, 36, 41, 41, 35, 29, 24, 20, 35, 40, + 44, 37, 32, 27, 24, 36, 43, 47, 42, 37, 32, 27, 38, 44, 50, 47, 40, 34, 29, + 41, 47, 52, 49, 42, 37, 31, 43, 49, 52, 52, 46, 39, 33, 2, 2, 3, 3, 3, + 2, 2, 1, 2, 3, 3, 3, 2, 2, 0, 2, 2, 3, 2, 2, 1, 1, 1, 1, + 2, 2, 2, 3, 3, 3, 3, 4, 4, 3, 3, 7, 7, 7, 6, 5, 3, 3, 13, + 11, 9, 7, 5, 3, 3, 0, 2, 2, 3, 2, 2, 2, 1, 2, 2, 3, 2, 2, + 1, 2, 1, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 3, 4, 4, 4, 4, + 4, 3, 4, 9, 8, 8, 7, 5, 4, 4, 16, 13, 10, 8, 6, 4, 3, 2, 1, + 2, 2, 2, 1, 4, 2, 1, 1, 1, 1, 1, 4, 2, 1, 1, 0, 0, 1, 5, + 3, 2, 3, 3, 3, 3, 6, 7, 6, 6, 6, 7, 6, 6, 12, 11, 11, 10, 8, + 7, 6, 19, 17, 13, 12, 10, 9, 8, 2, 4, 4, 5, 5, 5, 8, 3, 5, 5, + 6, 6, 6, 8, 7, 6, 6, 7, 7, 7, 8, 10, 9, 10, 10, 10, 11, 10, 10, + 14, 14, 14, 14, 13, 13, 13, 19, 19, 18, 16, 15, 14, 18, 25, 22, 20, 18, 16, + 16, 12, 12, 12, 12, 12, 12, 8, 14, 14, 14, 13, 14, 13, 8, 14, 16, 15, 15, + 15, 14, 11, 14, 19, 19, 19, 19, 18, 14, 17, 23, 23, 23, 23, 20, 16, 21, 27, + 28, 27, 26, 23, 18, 25, 31, 32, 29, 28, 25, 20, 21, 23, 22, 21, 18, 14, 10, + 21, 25, 23, 23, 20, 16, 11, 21, 27, 26, 25, 22, 18, 14, 21, 27, 30, 29, 25, + 21, 18, 24, 30, 34, 34, 30, 25, 19, 27, 33, 39, 37, 32, 26, 21, 30, 36, 40, + 40, 35, 28, 23, 29, 34, 33, 27, 22, 17, 13, 29, 35, 37, 29, 23, 19, 14, 29, + 35, 39, 32, 25, 22, 17, 30, 35, 42, 35, 30, 25, 21, 31, 37, 44, 40, 35, 29, + 23, 33, 41, 46, 46, 36, 31, 25, 36, 43, 47, 46, 39, 32, 26, 1, 2, 2, 2, + 2, 2, 1, 2, 1, 2, 3, 2, 2, 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 4, 4, 8, 8, 8, 7, 5, 4, 4, + 14, 12, 9, 8, 6, 4, 4, 2, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, + 1, 2, 2, 2, 1, 2, 2, 1, 4, 2, 2, 2, 3, 2, 3, 5, 6, 5, 5, + 5, 5, 4, 5, 11, 10, 9, 8, 6, 5, 5, 18, 15, 11, 9, 7, 5, 5, 2, + 2, 1, 2, 1, 3, 6, 2, 2, 2, 2, 2, 4, 6, 4, 2, 3, 3, 4, 4, + 7, 7, 3, 6, 6, 6, 7, 9, 11, 7, 9, 10, 10, 10, 8, 15, 12, 14, 13, + 12, 11, 8, 20, 18, 17, 15, 14, 12, 11, 4, 6, 7, 7, 8, 7, 10, 8, 7, + 8, 8, 9, 9, 10, 11, 8, 10, 10, 11, 11, 11, 14, 10, 14, 14, 14, 14, 13, + 14, 16, 18, 18, 18, 17, 16, 15, 21, 22, 21, 20, 18, 18, 20, 28, 26, 24, 22, + 20, 19, 14, 15, 15, 15, 16, 15, 10, 17, 17, 16, 16, 17, 15, 10, 16, 18, 19, + 19, 19, 18, 14, 17, 22, 23, 23, 23, 21, 18, 19, 27, 27, 27, 27, 24, 20, 24, + 31, 34, 32, 29, 27, 21, 28, 34, 36, 33, 31, 28, 23, 24, 26, 24, 24, 21, 17, + 13, 24, 29, 27, 26, 23, 18, 14, 24, 30, 29, 28, 25, 21, 17, 24, 31, 34, 32, + 29, 25, 22, 29, 35, 38, 37, 34, 29, 23, 32, 37, 44, 42, 36, 31, 25, 34, 40, + 45, 44, 39, 33, 26, 33, 38, 37, 30, 24, 20, 16, 32, 39, 40, 32, 26, 21, 18, + 32, 38, 42, 35, 30, 25, 21, 33, 40, 46, 39, 33, 28, 24, 34, 41, 48, 43, 38, + 32, 27, 37, 43, 49, 49, 41, 35, 28, 40, 46, 49, 50, 44, 36, 30, 2, 1, 1, + 2, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2, 0, 2, 1, 2, 3, 2, + 3, 2, 3, 3, 4, 5, 5, 5, 6, 5, 6, 5, 5, 10, 9, 9, 8, 6, 5, + 5, 16, 14, 11, 8, 7, 5, 4, 2, 2, 1, 2, 1, 2, 5, 2, 2, 1, 1, + 1, 2, 5, 3, 2, 1, 1, 1, 3, 6, 4, 3, 3, 3, 4, 4, 7, 8, 6, + 7, 7, 7, 5, 7, 12, 11, 10, 10, 9, 7, 7, 19, 16, 13, 11, 10, 9, 7, + 2, 2, 4, 4, 5, 6, 8, 4, 2, 4, 5, 5, 6, 8, 8, 2, 5, 7, 7, + 6, 9, 11, 4, 8, 10, 10, 10, 11, 14, 8, 11, 14, 14, 14, 11, 18, 14, 16, + 17, 16, 15, 11, 21, 20, 18, 19, 18, 16, 14, 8, 7, 10, 11, 11, 9, 12, 11, + 8, 11, 11, 12, 12, 12, 14, 8, 12, 14, 14, 15, 14, 17, 12, 17, 18, 18, 17, + 15, 18, 17, 21, 21, 22, 21, 19, 18, 23, 26, 25, 24, 23, 21, 22, 30, 29, 27, + 26, 24, 23, 17, 18, 18, 18, 19, 18, 12, 19, 19, 19, 20, 20, 19, 12, 20, 20, + 21, 23, 23, 22, 17, 20, 25, 27, 26, 27, 26, 21, 22, 30, 32, 31, 31, 29, 23, + 26, 35, 37, 35, 33, 30, 25, 30, 37, 40, 37, 36, 32, 27, 28, 29, 28, 28, 25, + 20, 17, 27, 32, 31, 30, 26, 22, 18, 27, 34, 34, 34, 29, 25, 21, 27, 35, 38, + 37, 34, 30, 25, 31, 38, 43, 41, 38, 33, 27, 34, 41, 49, 47, 39, 33, 29, 38, + 44, 49, 49, 43, 36, 30, 36, 43, 41, 34, 28, 24, 20, 37, 43, 44, 36, 30, 25, + 21, 36, 43, 46, 38, 34, 29, 24, 37, 44, 49, 44, 38, 34, 29, 40, 46, 53, 49, + 42, 36, 30, 42, 49, 55, 54, 45, 38, 33, 45, 51, 55, 55, 48, 41, 34, 2, 2, + 1, 2, 2, 2, 4, 2, 2, 1, 2, 2, 1, 3, 3, 2, 2, 0, 1, 2, 4, + 3, 3, 3, 3, 2, 3, 5, 6, 6, 6, 6, 5, 4, 5, 10, 10, 9, 8, 6, + 4, 5, 16, 14, 11, 9, 7, 4, 5, 2, 2, 1, 2, 3, 5, 7, 3, 2, 2, + 2, 3, 4, 6, 4, 2, 2, 2, 3, 5, 7, 7, 3, 4, 4, 6, 6, 8, 10, + 7, 7, 8, 9, 6, 8, 14, 11, 11, 10, 11, 10, 8, 19, 16, 13, 11, 13, 11, + 8, 4, 2, 5, 7, 8, 9, 11, 8, 3, 4, 7, 8, 8, 10, 11, 3, 5, 9, + 10, 8, 11, 14, 5, 8, 12, 13, 13, 13, 18, 9, 12, 16, 17, 16, 13, 21, 14, + 16, 19, 19, 18, 13, 22, 20, 18, 21, 20, 19, 17, 11, 8, 12, 14, 14, 12, 16, + 15, 8, 13, 14, 15, 16, 15, 18, 10, 14, 17, 18, 17, 16, 20, 14, 18, 20, 21, + 21, 18, 21, 19, 23, 24, 25, 24, 21, 21, 24, 27, 28, 27, 27, 24, 23, 30, 31, + 29, 29, 27, 27, 20, 19, 21, 22, 23, 22, 16, 23, 21, 23, 23, 24, 22, 15, 23, + 23, 24, 26, 26, 25, 20, 23, 27, 29, 30, 31, 29, 25, 25, 32, 33, 34, 34, 32, + 27, 27, 36, 39, 38, 36, 34, 29, 31, 39, 43, 41, 39, 37, 30, 30, 33, 33, 32, + 29, 25, 20, 29, 34, 34, 34, 30, 25, 21, 29, 37, 37, 37, 33, 28, 25, 30, 39, + 41, 40, 37, 33, 29, 33, 42, 47, 45, 41, 38, 30, 36, 44, 51, 49, 44, 38, 33, + 40, 47, 52, 53, 46, 38, 34, 41, 46, 44, 37, 32, 28, 23, 40, 45, 46, 40, 33, + 29, 25, 40, 46, 49, 42, 37, 33, 28, 40, 47, 53, 47, 41, 36, 32, 43, 50, 55, + 52, 46, 40, 35, 45, 52, 57, 56, 49, 43, 36, 48, 54, 57, 58, 52, 44, 38, 2, + 1, 2, 2, 2, 4, 5, 2, 2, 2, 2, 2, 2, 4, 3, 2, 2, 1, 0, 2, + 5, 3, 3, 3, 2, 2, 3, 6, 7, 6, 6, 5, 5, 4, 6, 11, 9, 9, 8, + 6, 4, 6, 16, 13, 10, 8, 7, 4, 6, 3, 2, 2, 3, 4, 7, 9, 3, 2, + 2, 3, 4, 6, 8, 5, 2, 2, 2, 4, 5, 8, 9, 4, 4, 4, 7, 6, 9, + 13, 7, 7, 7, 10, 6, 9, 16, 11, 11, 10, 12, 11, 9, 20, 16, 12, 11, 13, + 12, 9, 5, 2, 5, 9, 9, 10, 13, 9, 3, 5, 9, 10, 9, 11, 13, 3, 5, + 10, 11, 8, 11, 15, 6, 8, 13, 14, 14, 14, 20, 11, 12, 16, 18, 18, 13, 23, + 15, 16, 19, 20, 18, 14, 23, 19, 18, 20, 21, 20, 18, 13, 8, 13, 15, 16, 14, + 18, 16, 9, 14, 16, 17, 17, 17, 19, 11, 14, 18, 18, 19, 17, 23, 15, 18, 21, + 22, 22, 19, 24, 20, 23, 25, 26, 25, 22, 24, 24, 27, 28, 28, 28, 25, 23, 30, + 31, 30, 30, 29, 27, 21, 20, 23, 23, 25, 24, 18, 25, 22, 24, 25, 26, 24, 17, + 24, 24, 27, 28, 28, 26, 21, 24, 28, 30, 31, 31, 29, 26, 26, 32, 35, 36, 36, + 33, 28, 28, 37, 40, 39, 39, 35, 29, 30, 40, 45, 42, 40, 37, 32, 31, 34, 33, + 34, 31, 27, 22, 31, 36, 35, 36, 32, 28, 23, 30, 38, 38, 38, 34, 30, 26, 30, + 41, 42, 42, 39, 33, 29, 34, 43, 48, 47, 42, 37, 31, 36, 45, 53, 51, 44, 40, + 34, 41, 47, 53, 54, 47, 40, 35, 41, 47, 45, 39, 34, 30, 26, 41, 47, 47, 41, + 35, 30, 26, 42, 48, 50, 44, 37, 34, 30, 42, 48, 54, 47, 42, 38, 33, 43, 51, + 56, 52, 47, 40, 35, 47, 53, 59, 57, 49, 42, 37, 50, 55, 59, 59, 52, 46, 39, + 1, 2, 2, 4, 4, 3, 4, 2, 1, 2, 4, 4, 2, 3, 2, 2, 2, 2, 3, + 0, 3, 2, 2, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 4, 4, 8, 8, 7, + 7, 6, 4, 4, 13, 11, 9, 7, 6, 4, 4, 2, 1, 2, 3, 4, 6, 7, 2, + 1, 2, 3, 4, 5, 6, 3, 2, 1, 1, 2, 3, 5, 6, 3, 2, 3, 4, 4, + 6, 10, 5, 5, 6, 7, 4, 6, 12, 9, 9, 8, 9, 7, 6, 17, 14, 10, 9, + 10, 9, 6, 2, 2, 5, 7, 8, 9, 11, 7, 2, 4, 8, 8, 8, 9, 11, 2, + 4, 7, 8, 6, 8, 14, 4, 7, 10, 10, 11, 10, 17, 8, 10, 14, 15, 14, 10, + 19, 12, 14, 16, 16, 15, 10, 20, 17, 15, 17, 18, 17, 15, 11, 7, 12, 14, 14, + 12, 15, 14, 8, 12, 15, 16, 15, 15, 17, 9, 12, 15, 16, 16, 14, 19, 12, 16, + 18, 19, 18, 15, 21, 17, 20, 22, 23, 22, 18, 20, 22, 24, 25, 25, 23, 22, 20, + 26, 26, 27, 26, 25, 24, 18, 18, 21, 22, 23, 22, 16, 21, 20, 22, 23, 24, 23, + 15, 22, 21, 24, 25, 24, 23, 18, 22, 26, 26, 28, 28, 27, 23, 23, 30, 31, 32, + 33, 29, 24, 26, 34, 38, 36, 34, 31, 26, 27, 36, 39, 37, 37, 34, 27, 28, 31, + 32, 32, 29, 25, 20, 29, 33, 33, 33, 29, 25, 21, 27, 36, 35, 34, 30, 27, 23, + 28, 38, 39, 37, 34, 29, 26, 31, 39, 43, 42, 38, 32, 28, 34, 41, 48, 46, 41, + 34, 30, 37, 44, 49, 49, 42, 37, 31, 39, 44, 42, 36, 31, 27, 23, 39, 45, 45, + 38, 33, 28, 23, 39, 45, 47, 40, 34, 30, 26, 40, 45, 52, 44, 38, 34, 30, 41, + 47, 52, 49, 42, 37, 33, 43, 48, 55, 53, 45, 39, 33, 46, 51, 56, 55, 48, 40, + 35, 2, 3, 5, 6, 6, 5, 4, 1, 2, 4, 6, 6, 4, 2, 1, 2, 3, 4, + 5, 3, 0, 1, 1, 1, 3, 4, 3, 2, 3, 3, 3, 4, 6, 4, 2, 7, 6, + 6, 6, 6, 4, 2, 11, 9, 7, 6, 6, 4, 2, 1, 2, 3, 5, 4, 5, 6, + 1, 2, 3, 4, 4, 4, 5, 2, 1, 2, 3, 2, 2, 3, 2, 1, 1, 1, 1, + 2, 4, 5, 4, 4, 4, 3, 2, 3, 9, 8, 7, 7, 5, 4, 4, 14, 11, 8, + 7, 7, 6, 4, 2, 1, 5, 5, 6, 8, 9, 2, 1, 4, 6, 6, 6, 8, 5, + 1, 4, 6, 6, 5, 6, 10, 2, 5, 7, 7, 7, 7, 13, 6, 8, 10, 11, 10, + 7, 15, 11, 11, 13, 13, 11, 7, 16, 14, 13, 14, 14, 13, 12, 6, 6, 11, 11, + 12, 11, 13, 11, 7, 11, 12, 13, 13, 12, 13, 7, 11, 13, 13, 13, 11, 16, 10, + 14, 15, 14, 15, 12, 17, 15, 17, 19, 19, 18, 15, 16, 19, 20, 21, 21, 20, 18, + 16, 22, 23, 23, 23, 21, 20, 15, 17, 18, 19, 20, 19, 13, 18, 18, 20, 20, 21, + 20, 12, 18, 19, 21, 21, 21, 19, 15, 18, 22, 24, 24, 24, 22, 18, 20, 27, 28, + 28, 28, 26, 20, 21, 30, 33, 31, 29, 28, 22, 24, 33, 34, 33, 32, 28, 24, 27, + 30, 29, 29, 26, 22, 17, 26, 31, 30, 31, 27, 22, 18, 26, 34, 33, 31, 27, 23, + 19, 26, 34, 35, 33, 31, 27, 22, 28, 36, 40, 38, 34, 29, 24, 31, 37, 43, 42, + 36, 30, 26, 33, 39, 45, 44, 39, 33, 27, 37, 41, 39, 34, 29, 25, 21, 36, 41, + 42, 36, 30, 25, 21, 37, 41, 45, 37, 31, 26, 22, 36, 42, 46, 41, 35, 31, 26, + 37, 43, 48, 44, 38, 31, 28, 39, 45, 50, 48, 41, 34, 29, 41, 46, 51, 51, 45, + 36, 29, 2, 2, 3, 4, 4, 3, 2, 2, 2, 3, 4, 4, 3, 2, 1, 2, 2, + 3, 3, 2, 1, 0, 2, 2, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 3, 7, + 6, 7, 6, 4, 3, 3, 12, 11, 8, 7, 5, 3, 3, 1, 2, 3, 3, 2, 2, + 2, 0, 2, 2, 3, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, + 2, 1, 3, 4, 3, 4, 4, 4, 3, 3, 9, 8, 8, 7, 5, 3, 3, 16, 13, + 10, 8, 6, 4, 3, 1, 2, 2, 2, 2, 2, 3, 2, 1, 1, 2, 2, 2, 3, + 2, 0, 1, 1, 1, 1, 3, 2, 2, 2, 2, 2, 2, 5, 6, 5, 5, 5, 5, + 4, 5, 12, 10, 10, 9, 7, 6, 5, 18, 17, 13, 10, 9, 7, 6, 2, 3, 3, + 4, 4, 4, 7, 2, 4, 4, 5, 5, 5, 8, 5, 5, 5, 6, 6, 6, 7, 8, + 8, 8, 9, 9, 9, 9, 9, 13, 13, 12, 13, 12, 11, 12, 19, 17, 16, 15, 14, + 13, 18, 24, 21, 18, 17, 15, 15, 11, 11, 11, 11, 11, 11, 8, 13, 13, 12, 13, + 13, 12, 8, 12, 15, 15, 14, 14, 13, 10, 13, 18, 18, 17, 18, 16, 13, 16, 23, + 22, 22, 22, 20, 15, 20, 26, 28, 26, 25, 21, 17, 24, 29, 30, 27, 27, 23, 18, + 20, 23, 21, 21, 17, 13, 10, 21, 24, 23, 22, 19, 15, 10, 21, 25, 26, 24, 21, + 17, 12, 21, 27, 28, 27, 25, 20, 17, 23, 29, 33, 33, 29, 23, 19, 25, 32, 38, + 36, 30, 26, 20, 29, 35, 39, 39, 34, 27, 21, 28, 34, 33, 25, 21, 17, 12, 28, + 34, 34, 29, 22, 17, 13, 28, 34, 38, 30, 25, 20, 16, 29, 34, 40, 33, 29, 24, + 20, 30, 37, 42, 38, 33, 26, 22, 33, 39, 44, 43, 36, 29, 24, 35, 41, 44, 44, + 38, 32, 26, 1, 2, 3, 4, 4, 3, 3, 2, 2, 3, 4, 4, 3, 2, 1, 2, + 3, 3, 3, 2, 1, 2, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 7, 6, 6, 6, 4, 3, 3, 13, 11, 8, 6, 5, 3, 3, 2, 2, 3, 3, 3, + 3, 3, 2, 1, 2, 3, 3, 2, 3, 2, 1, 2, 2, 2, 1, 1, 2, 1, 1, + 2, 1, 1, 3, 4, 4, 4, 4, 4, 3, 3, 9, 8, 8, 7, 5, 3, 3, 16, + 13, 10, 7, 5, 4, 3, 2, 1, 2, 2, 3, 4, 6, 2, 2, 2, 3, 3, 4, + 6, 2, 2, 2, 2, 3, 3, 6, 5, 2, 4, 4, 4, 5, 7, 8, 6, 8, 8, + 8, 7, 6, 13, 11, 12, 11, 10, 9, 7, 19, 16, 15, 13, 11, 10, 9, 2, 6, + 7, 8, 8, 7, 10, 5, 6, 8, 8, 9, 9, 10, 9, 7, 8, 9, 9, 9, 10, + 12, 9, 12, 12, 12, 12, 11, 12, 14, 15, 15, 16, 15, 14, 13, 20, 20, 19, 18, + 16, 15, 18, 26, 24, 21, 19, 18, 18, 13, 14, 15, 15, 16, 15, 10, 14, 16, 15, + 16, 17, 16, 10, 15, 18, 17, 17, 17, 16, 12, 15, 21, 21, 21, 21, 19, 16, 18, + 25, 25, 25, 25, 22, 17, 21, 28, 30, 28, 26, 24, 19, 25, 32, 34, 31, 30, 26, + 21, 24, 24, 25, 25, 21, 17, 13, 23, 27, 26, 25, 23, 18, 14, 23, 29, 28, 27, + 23, 19, 15, 23, 30, 31, 31, 27, 23, 19, 26, 32, 36, 35, 31, 26, 21, 29, 35, + 41, 41, 34, 28, 23, 31, 38, 42, 43, 35, 30, 24, 32, 38, 36, 30, 25, 20, 16, + 31, 38, 39, 32, 26, 21, 17, 31, 38, 41, 33, 27, 23, 19, 32, 37, 44, 36, 31, + 26, 23, 34, 39, 45, 42, 36, 30, 25, 35, 41, 47, 46, 39, 33, 26, 38, 44, 48, + 49, 42, 34, 29, 1, 2, 3, 4, 4, 4, 3, 2, 2, 3, 4, 4, 3, 2, 1, + 2, 2, 3, 3, 1, 1, 2, 2, 0, 2, 2, 2, 3, 4, 3, 3, 3, 3, 3, + 3, 7, 7, 7, 6, 4, 3, 3, 13, 11, 8, 6, 5, 3, 3, 2, 2, 2, 3, + 4, 4, 6, 2, 2, 2, 3, 3, 3, 5, 2, 1, 2, 2, 2, 2, 4, 2, 2, + 2, 1, 1, 2, 5, 5, 5, 4, 4, 4, 3, 5, 10, 9, 8, 7, 6, 4, 5, + 17, 14, 10, 8, 7, 6, 5, 2, 2, 4, 5, 5, 7, 9, 2, 2, 4, 5, 6, + 7, 8, 5, 2, 4, 5, 5, 6, 7, 8, 3, 6, 7, 7, 7, 9, 12, 6, 9, + 10, 11, 10, 9, 15, 11, 13, 14, 13, 12, 9, 19, 17, 16, 16, 14, 13, 12, 4, + 7, 10, 11, 12, 10, 13, 9, 7, 11, 12, 12, 12, 13, 12, 8, 11, 12, 12, 12, + 12, 14, 10, 14, 15, 15, 15, 13, 16, 15, 18, 18, 20, 18, 16, 15, 21, 23, 22, + 21, 20, 19, 19, 27, 26, 24, 22, 21, 20, 15, 17, 18, 19, 19, 18, 13, 17, 18, + 19, 20, 21, 19, 13, 18, 20, 21, 21, 20, 19, 15, 17, 24, 24, 24, 24, 23, 18, + 20, 27, 28, 29, 28, 26, 21, 23, 32, 34, 32, 30, 27, 22, 27, 35, 37, 35, 32, + 29, 23, 26, 29, 28, 28, 25, 21, 17, 27, 31, 30, 30, 26, 21, 17, 27, 33, 33, + 31, 27, 22, 19, 27, 34, 36, 34, 31, 26, 22, 28, 36, 41, 40, 36, 28, 24, 33, + 38, 45, 43, 37, 32, 26, 35, 41, 45, 45, 40, 34, 28, 35, 41, 40, 33, 29, 24, + 20, 35, 42, 43, 35, 29, 25, 20, 36, 41, 45, 37, 31, 26, 22, 36, 41, 47, 40, + 35, 30, 25, 37, 43, 48, 46, 40, 33, 27, 39, 44, 51, 51, 42, 35, 30, 43, 47, + 52, 52, 46, 38, 31, 2, 2, 3, 5, 5, 4, 5, 2, 2, 3, 4, 4, 3, 3, + 2, 2, 3, 3, 2, 1, 3, 2, 2, 2, 0, 2, 1, 3, 4, 4, 3, 3, 3, + 2, 3, 8, 7, 7, 6, 4, 2, 4, 13, 11, 8, 6, 5, 2, 3, 2, 2, 3, + 3, 5, 6, 8, 2, 2, 2, 3, 4, 5, 7, 2, 2, 2, 2, 3, 4, 6, 4, + 2, 2, 2, 3, 4, 6, 8, 5, 5, 5, 6, 4, 7, 11, 9, 9, 8, 8, 7, + 7, 17, 13, 10, 8, 10, 8, 7, 2, 2, 5, 7, 8, 10, 12, 4, 2, 5, 8, + 9, 9, 11, 8, 2, 5, 8, 8, 7, 9, 11, 3, 6, 10, 10, 10, 10, 15, 7, + 9, 13, 14, 13, 11, 18, 12, 13, 16, 15, 15, 11, 19, 17, 16, 17, 17, 16, 15, + 8, 8, 12, 14, 15, 13, 16, 12, 8, 13, 14, 16, 15, 15, 15, 8, 13, 15, 16, + 15, 15, 17, 12, 16, 17, 18, 18, 16, 19, 16, 20, 22, 22, 22, 18, 18, 22, 24, + 25, 24, 23, 22, 19, 26, 27, 26, 26, 24, 24, 17, 19, 21, 21, 23, 22, 16, 20, + 20, 22, 24, 24, 23, 16, 20, 22, 23, 24, 24, 22, 18, 20, 25, 27, 27, 27, 26, + 22, 22, 30, 31, 32, 31, 29, 24, 25, 34, 36, 36, 34, 30, 26, 29, 37, 40, 37, + 36, 33, 27, 28, 32, 32, 31, 29, 25, 20, 28, 34, 33, 33, 29, 25, 21, 28, 36, + 36, 35, 30, 25, 22, 29, 37, 39, 37, 33, 30, 25, 31, 39, 44, 43, 38, 33, 27, + 34, 41, 49, 46, 41, 35, 29, 39, 43, 49, 49, 42, 37, 31, 39, 46, 43, 37, 31, + 27, 23, 39, 45, 46, 39, 33, 28, 23, 39, 46, 49, 41, 34, 29, 25, 39, 45, 50, + 44, 37, 34, 29, 40, 47, 52, 49, 42, 37, 31, 43, 49, 54, 53, 46, 39, 32, 45, + 51, 54, 55, 49, 42, 34, 2, 3, 3, 4, 4, 6, 7, 2, 2, 3, 4, 3, 4, + 5, 2, 2, 3, 2, 2, 2, 4, 3, 2, 2, 2, 0, 2, 5, 5, 4, 4, 3, + 3, 3, 5, 9, 8, 7, 6, 4, 3, 5, 13, 10, 8, 6, 5, 3, 5, 2, 2, + 3, 4, 6, 9, 10, 3, 2, 3, 4, 6, 7, 9, 3, 2, 2, 3, 4, 6, 8, + 6, 3, 2, 2, 5, 5, 8, 10, 5, 5, 5, 8, 6, 8, 13, 9, 8, 8, 10, + 9, 8, 16, 13, 9, 8, 11, 11, 8, 3, 2, 6, 9, 11, 12, 14, 7, 2, 6, + 10, 11, 11, 13, 10, 3, 5, 9, 11, 10, 12, 13, 4, 7, 11, 12, 13, 12, 18, + 9, 10, 14, 16, 15, 13, 21, 12, 13, 17, 18, 17, 12, 20, 16, 15, 18, 19, 19, + 17, 10, 8, 14, 16, 17, 15, 18, 13, 8, 14, 17, 18, 18, 18, 16, 10, 14, 17, + 19, 19, 17, 20, 13, 17, 20, 21, 21, 18, 21, 18, 21, 23, 25, 24, 21, 21, 22, + 25, 26, 27, 25, 24, 20, 26, 27, 28, 28, 27, 26, 19, 20, 23, 25, 26, 25, 19, + 22, 22, 25, 26, 27, 25, 18, 23, 23, 26, 27, 27, 26, 21, 22, 26, 29, 30, 31, + 29, 24, 24, 31, 34, 34, 34, 31, 27, 26, 34, 38, 37, 36, 34, 28, 28, 36, 41, + 38, 38, 35, 30, 31, 35, 35, 35, 31, 28, 23, 31, 37, 36, 36, 33, 28, 24, 30, + 39, 38, 37, 33, 29, 25, 31, 38, 41, 40, 36, 32, 28, 32, 41, 46, 44, 40, 35, + 29, 35, 43, 52, 49, 42, 37, 32, 37, 45, 51, 51, 45, 39, 33, 40, 48, 45, 39, + 34, 31, 26, 42, 48, 48, 41, 36, 30, 26, 42, 48, 50, 43, 37, 32, 28, 41, 48, + 53, 46, 39, 35, 31, 43, 49, 54, 52, 45, 39, 33, 44, 52, 57, 56, 47, 42, 36, + 46, 53, 57, 58, 50, 43, 37, 3, 4, 4, 5, 5, 6, 7, 2, 3, 4, 5, 5, + 4, 5, 2, 3, 4, 3, 3, 2, 3, 2, 2, 2, 2, 2, 0, 3, 3, 2, 2, + 2, 3, 2, 3, 6, 5, 5, 4, 3, 2, 3, 9, 7, 5, 4, 3, 2, 3, 2, + 3, 4, 5, 6, 8, 9, 2, 3, 3, 5, 6, 6, 7, 2, 2, 3, 3, 4, 5, + 6, 4, 2, 1, 1, 3, 3, 5, 8, 3, 3, 4, 5, 3, 5, 10, 6, 6, 5, + 7, 6, 5, 12, 9, 6, 5, 8, 7, 5, 2, 2, 6, 8, 9, 11, 12, 5, 2, + 5, 9, 9, 9, 11, 9, 2, 5, 8, 9, 8, 10, 13, 2, 5, 8, 9, 9, 9, + 15, 6, 8, 11, 12, 12, 9, 16, 8, 10, 13, 14, 13, 9, 15, 12, 11, 15, 15, + 15, 13, 9, 7, 13, 15, 15, 14, 17, 14, 8, 13, 15, 16, 16, 16, 16, 8, 13, + 15, 16, 16, 15, 18, 10, 14, 17, 17, 17, 14, 19, 15, 18, 20, 20, 20, 17, 16, + 18, 21, 22, 22, 22, 20, 15, 21, 22, 24, 24, 23, 22, 17, 19, 22, 23, 24, 23, + 16, 20, 20, 23, 24, 25, 23, 16, 20, 21, 24, 25, 24, 23, 19, 20, 24, 25, 26, + 27, 25, 21, 21, 29, 30, 29, 30, 28, 23, 22, 30, 33, 33, 31, 29, 24, 22, 31, + 36, 35, 33, 31, 26, 28, 32, 32, 32, 30, 26, 21, 28, 34, 34, 34, 30, 25, 21, + 29, 36, 35, 35, 31, 26, 22, 28, 36, 38, 36, 32, 28, 24, 29, 38, 44, 40, 36, + 32, 26, 32, 40, 46, 43, 38, 33, 28, 33, 42, 46, 46, 41, 35, 30, 39, 46, 44, + 37, 32, 28, 24, 40, 45, 46, 40, 33, 29, 24, 40, 46, 48, 40, 33, 29, 24, 40, + 45, 50, 43, 37, 33, 28, 40, 45, 51, 47, 40, 34, 29, 41, 47, 52, 51, 43, 37, + 31, 43, 48, 53, 53, 46, 39, 32, 4, 5, 6, 7, 8, 6, 7, 4, 4, 5, 7, + 7, 5, 4, 3, 4, 4, 5, 6, 3, 2, 3, 3, 3, 3, 5, 3, 0, 2, 1, + 1, 2, 4, 2, 0, 3, 2, 2, 2, 3, 2, 0, 5, 3, 2, 2, 3, 2, 0, + 4, 4, 5, 6, 7, 8, 8, 3, 4, 4, 5, 6, 6, 6, 2, 4, 4, 4, 4, + 4, 4, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 2, 2, 1, 3, 4, 3, 2, + 2, 2, 2, 3, 8, 5, 3, 2, 4, 3, 3, 3, 4, 6, 7, 9, 10, 11, 2, + 3, 6, 8, 8, 8, 9, 5, 3, 6, 7, 7, 6, 8, 9, 2, 4, 7, 6, 7, + 6, 12, 3, 5, 7, 8, 8, 6, 13, 4, 6, 9, 9, 9, 6, 11, 8, 6, 9, + 10, 10, 10, 5, 7, 11, 12, 13, 13, 14, 10, 8, 12, 13, 14, 14, 13, 13, 8, + 12, 13, 14, 14, 12, 15, 8, 12, 14, 14, 14, 11, 15, 10, 13, 15, 16, 15, 14, + 13, 12, 15, 17, 17, 17, 16, 11, 15, 17, 18, 19, 18, 18, 15, 17, 20, 20, 21, + 21, 14, 18, 18, 21, 21, 21, 20, 13, 18, 20, 22, 22, 22, 20, 16, 18, 20, 22, + 22, 23, 21, 17, 16, 23, 26, 24, 24, 22, 18, 16, 24, 27, 28, 26, 24, 20, 17, + 25, 30, 28, 28, 26, 21, 27, 29, 30, 29, 26, 23, 18, 27, 32, 31, 31, 27, 22, + 18, 27, 33, 33, 32, 27, 23, 19, 27, 33, 35, 32, 29, 24, 19, 26, 33, 37, 35, + 31, 26, 22, 27, 34, 39, 37, 32, 28, 23, 27, 34, 40, 40, 35, 29, 24, 37, 42, + 41, 34, 29, 25, 21, 37, 42, 43, 35, 30, 25, 21, 37, 43, 44, 36, 31, 27, 22, + 37, 42, 46, 40, 32, 27, 23, 36, 41, 46, 41, 35, 28, 24, 36, 42, 46, 45, 37, + 31, 26, 36, 41, 46, 46, 39, 33, 27, 4, 5, 6, 8, 8, 6, 5, 4, 5, 6, + 7, 8, 6, 4, 3, 4, 5, 6, 7, 4, 3, 3, 3, 4, 4, 4, 3, 2, 0, + 2, 2, 2, 3, 2, 2, 4, 4, 4, 3, 3, 2, 2, 10, 8, 6, 4, 3, 2, + 2, 3, 4, 5, 6, 5, 5, 5, 3, 4, 5, 6, 6, 5, 4, 2, 4, 4, 5, + 4, 4, 3, 2, 2, 3, 3, 3, 2, 1, 2, 2, 2, 2, 2, 2, 1, 6, 5, + 6, 5, 2, 1, 1, 13, 11, 7, 5, 3, 1, 1, 2, 3, 4, 4, 5, 5, 5, + 2, 3, 4, 4, 5, 4, 5, 2, 2, 4, 3, 4, 4, 4, 2, 1, 1, 1, 1, + 1, 2, 3, 3, 2, 2, 3, 1, 2, 9, 8, 7, 6, 4, 3, 2, 15, 14, 10, + 7, 6, 4, 3, 2, 3, 5, 5, 6, 6, 8, 1, 4, 5, 6, 6, 6, 8, 3, + 5, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 7, 7, 6, 10, 9, 10, 10, 9, + 8, 9, 15, 14, 13, 12, 11, 10, 15, 21, 18, 15, 14, 12, 12, 11, 11, 11, 12, + 13, 11, 8, 12, 13, 13, 13, 14, 12, 8, 12, 14, 14, 14, 15, 13, 9, 12, 16, + 15, 15, 15, 14, 10, 14, 19, 19, 19, 19, 17, 12, 17, 23, 24, 23, 21, 19, 13, + 21, 26, 28, 25, 23, 21, 15, 20, 22, 21, 22, 19, 14, 10, 20, 24, 23, 24, 20, + 16, 11, 20, 26, 25, 25, 21, 16, 12, 20, 25, 26, 25, 22, 18, 14, 20, 26, 30, + 29, 25, 20, 15, 22, 29, 36, 33, 28, 23, 17, 25, 31, 35, 36, 30, 25, 19, 28, + 35, 32, 26, 22, 17, 13, 28, 35, 36, 29, 24, 18, 14, 28, 34, 38, 30, 25, 19, + 14, 28, 35, 38, 31, 26, 21, 17, 26, 33, 38, 36, 30, 26, 19, 29, 36, 40, 39, + 33, 28, 20, 32, 37, 40, 40, 33, 29, 23, 4, 5, 6, 7, 7, 7, 6, 3, 5, + 6, 7, 7, 6, 5, 3, 4, 5, 6, 6, 4, 3, 3, 3, 3, 4, 4, 2, 1, + 2, 0, 1, 2, 3, 2, 2, 4, 4, 4, 3, 2, 2, 1, 10, 8, 5, 4, 2, + 2, 1, 3, 4, 5, 7, 7, 7, 6, 3, 4, 5, 6, 6, 5, 5, 2, 3, 5, + 5, 5, 4, 3, 2, 2, 2, 2, 2, 2, 0, 2, 2, 1, 2, 1, 1, 0, 7, + 6, 5, 4, 2, 1, 0, 13, 11, 7, 5, 3, 1, 0, 3, 3, 4, 5, 6, 7, + 8, 2, 3, 4, 5, 6, 6, 7, 2, 2, 4, 4, 4, 4, 6, 2, 2, 2, 2, + 3, 3, 5, 5, 3, 5, 5, 5, 4, 5, 10, 8, 9, 8, 7, 6, 5, 15, 13, + 12, 10, 8, 7, 6, 2, 6, 7, 8, 9, 9, 11, 2, 7, 8, 8, 9, 9, 10, + 6, 7, 8, 9, 9, 9, 10, 9, 7, 9, 9, 9, 9, 9, 9, 11, 12, 12, 13, + 12, 11, 10, 17, 17, 16, 14, 13, 13, 16, 23, 20, 18, 16, 15, 14, 13, 14, 14, + 15, 16, 15, 11, 13, 16, 16, 16, 17, 16, 11, 14, 17, 17, 17, 17, 16, 12, 14, + 18, 17, 18, 18, 16, 13, 15, 22, 22, 21, 22, 19, 14, 19, 26, 27, 26, 24, 21, + 16, 23, 30, 31, 28, 26, 23, 18, 23, 25, 24, 24, 22, 17, 13, 23, 27, 26, 25, + 23, 18, 14, 23, 29, 29, 26, 23, 18, 14, 23, 28, 29, 28, 24, 20, 16, 23, 29, + 33, 32, 28, 23, 18, 26, 32, 39, 37, 31, 25, 19, 29, 33, 38, 39, 34, 27, 21, + 31, 37, 37, 29, 24, 20, 16, 32, 38, 39, 31, 26, 21, 17, 31, 37, 41, 33, 27, + 21, 17, 31, 36, 43, 34, 28, 24, 20, 30, 37, 42, 40, 32, 26, 21, 31, 38, 44, + 44, 35, 29, 23, 35, 40, 46, 46, 39, 31, 24, 4, 5, 6, 8, 8, 7, 6, 4, + 5, 6, 7, 7, 6, 5, 3, 4, 5, 6, 6, 4, 3, 3, 3, 3, 3, 4, 2, + 1, 2, 1, 0, 2, 2, 1, 1, 4, 4, 4, 3, 2, 1, 1, 10, 8, 5, 3, + 2, 1, 1, 4, 4, 5, 7, 7, 8, 8, 3, 4, 5, 6, 7, 6, 7, 3, 4, + 5, 5, 5, 4, 5, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 1, 0, 3, + 7, 6, 5, 4, 2, 1, 3, 13, 10, 7, 5, 4, 2, 3, 3, 4, 6, 7, 8, + 10, 10, 2, 3, 6, 7, 8, 8, 9, 3, 3, 6, 6, 6, 7, 8, 6, 2, 4, + 5, 5, 6, 7, 8, 4, 6, 7, 7, 7, 7, 12, 8, 10, 10, 9, 8, 7, 15, + 13, 13, 12, 10, 10, 8, 2, 7, 10, 11, 11, 12, 13, 6, 8, 10, 11, 12, 12, + 13, 10, 8, 11, 11, 12, 12, 12, 12, 8, 11, 12, 12, 12, 11, 12, 12, 14, 15, + 16, 14, 14, 12, 18, 20, 19, 17, 17, 15, 15, 23, 22, 21, 19, 18, 16, 14, 17, + 18, 18, 19, 18, 14, 15, 19, 19, 19, 19, 19, 13, 16, 19, 20, 20, 20, 19, 15, + 16, 21, 22, 21, 21, 20, 16, 16, 24, 25, 24, 24, 22, 17, 19, 27, 30, 29, 27, + 24, 19, 24, 32, 34, 31, 29, 26, 20, 26, 29, 28, 28, 25, 21, 16, 26, 31, 29, + 30, 26, 21, 16, 25, 32, 32, 30, 26, 21, 17, 26, 31, 33, 32, 27, 23, 19, 25, + 32, 37, 35, 31, 26, 20, 28, 34, 41, 39, 34, 27, 23, 32, 36, 42, 42, 36, 30, + 24, 35, 41, 39, 33, 28, 24, 19, 35, 41, 42, 35, 29, 24, 19, 35, 42, 45, 36, + 30, 24, 19, 35, 40, 46, 38, 31, 26, 22, 33, 40, 46, 43, 37, 29, 24, 35, 43, + 47, 47, 39, 32, 26, 39, 45, 49, 48, 41, 34, 29, 4, 5, 6, 8, 8, 7, 8, + 4, 5, 6, 7, 7, 6, 6, 3, 5, 6, 6, 5, 4, 4, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 0, 2, 1, 2, 5, 4, 4, 3, 2, 1, 2, 9, 7, 5, + 3, 2, 1, 2, 4, 5, 5, 7, 8, 10, 10, 3, 4, 5, 6, 7, 8, 8, 3, + 4, 5, 5, 5, 6, 6, 3, 2, 3, 3, 3, 4, 5, 4, 2, 2, 2, 3, 3, + 5, 8, 6, 5, 5, 5, 4, 5, 12, 9, 6, 5, 6, 5, 5, 3, 4, 7, 9, + 10, 12, 13, 3, 3, 7, 9, 9, 10, 11, 6, 3, 6, 8, 8, 8, 10, 9, 2, + 5, 7, 8, 8, 9, 11, 4, 7, 10, 10, 10, 9, 14, 8, 10, 12, 12, 11, 9, + 14, 11, 11, 14, 13, 12, 11, 6, 8, 12, 13, 14, 14, 16, 10, 9, 13, 14, 15, + 15, 16, 13, 9, 13, 14, 15, 15, 15, 15, 9, 13, 15, 15, 16, 14, 15, 13, 16, + 18, 18, 18, 17, 14, 18, 21, 21, 20, 19, 18, 14, 21, 23, 23, 22, 21, 20, 16, + 19, 20, 21, 22, 22, 16, 18, 20, 22, 23, 23, 22, 16, 18, 21, 23, 23, 24, 22, + 18, 18, 23, 24, 24, 25, 23, 19, 18, 27, 28, 27, 27, 25, 20, 21, 30, 33, 31, + 30, 27, 22, 24, 31, 35, 33, 32, 29, 23, 27, 32, 31, 31, 28, 24, 20, 28, 34, + 32, 33, 29, 24, 20, 27, 35, 36, 34, 29, 25, 20, 28, 35, 37, 36, 31, 27, 22, + 27, 34, 40, 39, 35, 29, 23, 31, 38, 44, 43, 37, 31, 25, 34, 39, 45, 46, 40, + 33, 27, 38, 45, 43, 37, 31, 26, 22, 39, 44, 46, 39, 33, 27, 23, 39, 45, 47, + 40, 33, 28, 23, 39, 45, 49, 41, 35, 30, 26, 37, 43, 49, 46, 39, 33, 27, 38, + 45, 51, 50, 43, 35, 29, 41, 46, 51, 51, 44, 38, 31, 5, 5, 6, 7, 7, 9, + 10, 5, 5, 6, 7, 7, 7, 8, 4, 5, 6, 5, 5, 5, 6, 4, 3, 3, 3, + 3, 3, 4, 3, 3, 2, 2, 0, 1, 4, 4, 3, 3, 2, 1, 1, 4, 6, 5, + 3, 2, 2, 2, 4, 4, 5, 6, 7, 9, 11, 12, 4, 5, 5, 7, 9, 10, 10, + 4, 4, 5, 5, 7, 8, 9, 5, 3, 3, 3, 5, 6, 7, 6, 3, 2, 3, 6, + 5, 7, 8, 4, 4, 4, 7, 7, 7, 10, 7, 4, 4, 8, 8, 7, 3, 5, 8, + 11, 12, 14, 15, 5, 4, 7, 11, 12, 12, 14, 8, 4, 7, 10, 11, 11, 13, 12, + 3, 5, 10, 11, 12, 11, 13, 4, 7, 12, 13, 13, 12, 14, 6, 8, 12, 14, 14, + 12, 14, 9, 9, 13, 16, 16, 15, 8, 9, 14, 17, 18, 17, 20, 12, 10, 15, 17, + 19, 19, 19, 15, 10, 16, 18, 19, 19, 18, 17, 10, 15, 18, 18, 19, 17, 16, 14, + 17, 20, 21, 21, 20, 15, 16, 20, 22, 23, 23, 22, 14, 18, 21, 23, 24, 24, 24, + 19, 21, 24, 25, 26, 26, 19, 21, 22, 25, 26, 28, 26, 19, 21, 24, 26, 28, 27, + 25, 21, 21, 25, 26, 27, 28, 27, 22, 20, 28, 30, 30, 31, 29, 24, 21, 29, 34, + 33, 32, 30, 25, 21, 30, 37, 35, 34, 33, 27, 30, 34, 35, 34, 32, 28, 24, 30, + 37, 37, 37, 33, 28, 24, 30, 39, 39, 37, 33, 29, 25, 31, 38, 40, 39, 35, 30, + 25, 30, 39, 43, 41, 36, 32, 27, 31, 40, 47, 44, 39, 33, 29, 32, 41, 45, 47, + 41, 36, 31, 42, 48, 47, 40, 35, 31, 26, 43, 49, 49, 42, 36, 32, 27, 42, 48, + 51, 44, 37, 32, 27, 43, 48, 53, 44, 39, 33, 29, 41, 47, 53, 49, 41, 35, 31, + 42, 48, 52, 50, 44, 38, 32, 43, 48, 53, 53, 46, 40, 33, 4, 5, 5, 6, 6, + 8, 8, 4, 5, 5, 6, 6, 6, 6, 3, 4, 5, 4, 4, 4, 4, 3, 3, 3, + 2, 3, 2, 3, 2, 2, 1, 1, 1, 0, 2, 3, 2, 2, 2, 1, 0, 2, 5, + 3, 2, 1, 1, 0, 2, 4, 4, 5, 6, 8, 10, 10, 3, 4, 5, 6, 7, 8, + 9, 3, 3, 4, 4, 5, 6, 7, 4, 2, 2, 2, 3, 4, 5, 6, 2, 2, 2, + 4, 3, 5, 7, 3, 2, 2, 5, 5, 5, 9, 5, 3, 2, 6, 6, 5, 3, 4, + 7, 9, 11, 12, 14, 5, 3, 7, 10, 10, 10, 12, 9, 3, 6, 9, 9, 9, 10, + 13, 2, 5, 8, 9, 10, 9, 13, 3, 5, 9, 10, 11, 9, 16, 5, 6, 10, 12, + 12, 9, 14, 8, 7, 11, 13, 13, 13, 9, 8, 13, 15, 16, 15, 17, 13, 8, 13, + 16, 16, 17, 17, 16, 8, 13, 16, 17, 16, 16, 18, 9, 14, 16, 17, 17, 14, 18, + 12, 15, 18, 19, 18, 17, 15, 13, 17, 19, 20, 20, 20, 14, 16, 19, 21, 21, 21, + 21, 16, 19, 22, 23, 24, 24, 18, 20, 20, 22, 24, 25, 23, 17, 20, 21, 25, 25, + 25, 24, 19, 20, 24, 25, 26, 26, 24, 20, 18, 25, 27, 28, 28, 25, 21, 18, 26, + 30, 30, 29, 27, 23, 18, 27, 32, 32, 31, 30, 25, 29, 33, 33, 32, 30, 26, 21, + 28, 35, 34, 34, 31, 26, 21, 29, 38, 37, 35, 31, 27, 22, 28, 36, 38, 37, 32, + 28, 23, 28, 36, 41, 39, 34, 29, 25, 29, 36, 42, 42, 35, 30, 26, 30, 37, 43, + 43, 38, 33, 27, 40, 47, 45, 37, 33, 28, 24, 40, 45, 46, 40, 34, 29, 25, 41, + 46, 49, 41, 34, 29, 25, 40, 45, 50, 42, 36, 31, 26, 39, 44, 49, 46, 38, 33, + 28, 39, 45, 50, 47, 40, 34, 30, 39, 46, 50, 49, 43, 36, 30, 4, 5, 6, 8, + 8, 6, 6, 4, 4, 5, 7, 7, 5, 4, 3, 4, 5, 5, 6, 4, 2, 3, 3, + 3, 3, 5, 3, 0, 2, 1, 1, 2, 4, 2, 0, 2, 2, 2, 2, 3, 2, 0, + 4, 3, 2, 2, 3, 2, 0, 4, 4, 5, 6, 6, 8, 8, 3, 4, 5, 5, 6, + 6, 6, 3, 4, 4, 4, 4, 4, 5, 2, 2, 2, 2, 2, 2, 3, 2, 2, 1, + 1, 1, 1, 3, 4, 2, 2, 2, 2, 2, 3, 7, 5, 2, 2, 3, 3, 3, 3, + 4, 6, 8, 9, 10, 11, 2, 3, 6, 8, 8, 8, 9, 5, 3, 6, 7, 7, 7, + 8, 9, 2, 4, 7, 6, 7, 6, 11, 2, 4, 7, 8, 8, 6, 13, 4, 5, 8, + 9, 9, 6, 10, 8, 6, 9, 10, 10, 10, 5, 7, 11, 12, 13, 13, 14, 10, 7, + 11, 13, 14, 14, 13, 13, 8, 12, 13, 14, 13, 12, 15, 7, 12, 14, 14, 14, 11, + 16, 10, 13, 15, 15, 15, 14, 12, 12, 15, 16, 17, 17, 16, 10, 15, 17, 18, 18, + 18, 18, 15, 17, 20, 20, 21, 20, 14, 18, 18, 21, 21, 22, 20, 13, 18, 19, 21, + 22, 22, 20, 17, 17, 21, 23, 23, 23, 21, 16, 16, 22, 25, 25, 25, 23, 18, 16, + 24, 27, 27, 25, 24, 20, 17, 25, 30, 28, 28, 26, 21, 25, 29, 30, 30, 26, 23, + 18, 27, 32, 32, 30, 27, 23, 18, 27, 34, 34, 33, 28, 23, 19, 27, 33, 34, 32, + 29, 25, 20, 26, 33, 37, 34, 30, 26, 21, 27, 33, 41, 38, 32, 28, 23, 27, 34, + 39, 41, 35, 29, 24, 36, 42, 39, 34, 29, 25, 21, 37, 43, 42, 36, 31, 26, 22, + 37, 43, 45, 38, 31, 26, 22, 38, 42, 47, 39, 32, 28, 23, 37, 40, 45, 42, 34, + 29, 24, 35, 41, 46, 44, 36, 30, 26, 36, 42, 46, 45, 40, 33, 27, 8, 9, 10, + 12, 12, 11, 10, 8, 9, 10, 12, 12, 10, 9, 7, 8, 9, 10, 11, 8, 7, 7, + 7, 7, 8, 8, 6, 3, 4, 4, 4, 5, 4, 3, 2, 0, 2, 2, 2, 3, 3, + 2, 6, 5, 2, 2, 2, 3, 2, 7, 8, 10, 11, 11, 11, 10, 7, 8, 9, 10, + 10, 10, 9, 6, 7, 9, 9, 9, 8, 7, 6, 6, 6, 7, 6, 5, 2, 3, 3, + 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 7, 4, 2, 1, 2, 2, + 6, 8, 9, 9, 10, 11, 10, 6, 7, 8, 9, 9, 9, 9, 5, 6, 7, 7, 8, + 8, 7, 5, 5, 5, 5, 5, 5, 3, 2, 1, 1, 2, 2, 2, 3, 5, 4, 3, + 2, 0, 2, 3, 11, 10, 6, 4, 2, 2, 3, 6, 7, 8, 9, 11, 12, 11, 5, + 7, 8, 10, 10, 10, 10, 4, 7, 8, 8, 8, 9, 8, 5, 6, 5, 6, 6, 6, + 6, 3, 6, 6, 6, 7, 7, 7, 5, 11, 10, 9, 8, 8, 8, 11, 16, 13, 12, + 10, 9, 10, 9, 10, 11, 11, 12, 12, 12, 11, 12, 12, 12, 13, 12, 10, 11, 13, + 14, 13, 13, 12, 8, 11, 15, 14, 14, 14, 13, 9, 11, 16, 16, 15, 15, 15, 10, + 12, 18, 21, 20, 18, 16, 11, 17, 21, 24, 21, 20, 18, 13, 18, 20, 20, 21, 18, + 14, 11, 19, 23, 23, 22, 19, 14, 10, 19, 24, 25, 24, 20, 15, 10, 18, 24, 25, + 26, 22, 16, 11, 18, 24, 27, 27, 23, 17, 13, 19, 24, 30, 29, 24, 20, 15, 21, + 27, 31, 31, 27, 21, 16, 27, 33, 33, 26, 21, 16, 12, 27, 33, 35, 27, 22, 17, + 13, 27, 33, 36, 29, 23, 18, 13, 28, 33, 37, 30, 25, 19, 15, 26, 33, 36, 33, + 26, 22, 16, 27, 32, 35, 34, 28, 23, 19, 28, 31, 36, 36, 31, 25, 20, 8, 9, + 10, 11, 11, 11, 10, 7, 8, 10, 11, 11, 10, 8, 7, 8, 9, 10, 9, 8, 6, + 6, 6, 7, 7, 7, 5, 2, 4, 4, 4, 4, 4, 2, 2, 2, 0, 2, 2, 2, + 2, 2, 6, 4, 2, 2, 2, 2, 2, 7, 8, 9, 11, 11, 11, 11, 6, 8, 9, + 10, 11, 9, 9, 6, 7, 8, 9, 8, 7, 6, 6, 5, 6, 6, 6, 5, 2, 3, + 3, 3, 3, 2, 2, 2, 3, 2, 2, 2, 1, 2, 2, 9, 7, 3, 2, 1, 2, + 2, 6, 7, 8, 9, 11, 11, 12, 6, 6, 8, 9, 10, 10, 10, 6, 6, 8, 8, + 8, 8, 8, 5, 5, 6, 6, 5, 5, 5, 3, 2, 3, 3, 3, 3, 4, 5, 5, + 5, 4, 3, 4, 5, 11, 9, 8, 6, 5, 5, 5, 6, 9, 9, 11, 12, 14, 13, + 5, 8, 10, 11, 12, 12, 11, 5, 8, 9, 9, 9, 10, 9, 8, 7, 8, 8, 8, + 9, 8, 6, 8, 9, 9, 10, 10, 10, 6, 13, 13, 12, 11, 11, 11, 11, 18, 16, + 14, 12, 12, 13, 12, 13, 14, 14, 15, 15, 13, 12, 15, 15, 16, 16, 14, 11, 13, + 16, 17, 16, 16, 15, 11, 13, 17, 17, 16, 17, 16, 12, 12, 19, 19, 18, 18, 17, + 13, 14, 22, 23, 21, 20, 18, 14, 19, 24, 26, 24, 22, 20, 16, 22, 24, 24, 24, + 21, 17, 13, 22, 26, 25, 25, 22, 17, 12, 22, 28, 28, 27, 22, 17, 13, 22, 27, + 29, 27, 24, 19, 14, 22, 27, 30, 30, 25, 20, 16, 21, 28, 34, 33, 27, 21, 17, + 25, 30, 34, 35, 30, 24, 18, 31, 37, 36, 29, 23, 19, 15, 30, 36, 39, 32, 25, + 20, 16, 30, 37, 40, 32, 26, 21, 17, 31, 35, 41, 33, 27, 22, 17, 29, 35, 41, + 36, 29, 23, 19, 29, 35, 41, 38, 32, 26, 20, 30, 37, 40, 42, 34, 27, 22, 8, + 9, 10, 12, 11, 11, 10, 7, 8, 10, 11, 11, 9, 8, 7, 8, 9, 9, 9, 7, + 6, 6, 6, 7, 7, 7, 5, 2, 4, 4, 3, 4, 3, 2, 2, 2, 2, 0, 2, + 2, 2, 2, 5, 3, 2, 1, 2, 2, 2, 7, 8, 9, 10, 11, 11, 12, 7, 8, + 9, 10, 11, 10, 10, 6, 7, 8, 8, 8, 7, 7, 6, 6, 6, 6, 5, 4, 4, + 3, 3, 3, 3, 2, 2, 4, 3, 2, 2, 1, 2, 2, 3, 7, 5, 3, 1, 1, + 2, 3, 6, 7, 9, 11, 12, 14, 14, 6, 7, 10, 11, 12, 12, 12, 6, 7, 9, + 10, 9, 9, 9, 5, 5, 7, 7, 7, 7, 6, 6, 2, 4, 5, 5, 5, 6, 8, + 4, 7, 7, 6, 6, 6, 8, 7, 8, 9, 7, 7, 8, 6, 10, 11, 12, 14, 15, + 15, 5, 9, 11, 12, 13, 13, 13, 8, 9, 11, 11, 12, 11, 11, 10, 8, 11, 11, + 11, 12, 10, 9, 9, 11, 12, 12, 12, 13, 8, 13, 15, 15, 14, 14, 14, 8, 16, + 17, 16, 15, 15, 15, 13, 16, 17, 17, 18, 18, 15, 15, 17, 18, 18, 19, 17, 13, + 15, 18, 20, 19, 19, 18, 14, 15, 20, 20, 20, 20, 19, 14, 13, 22, 22, 21, 21, + 20, 15, 16, 24, 26, 24, 23, 21, 17, 18, 25, 28, 27, 25, 23, 19, 24, 27, 27, + 27, 24, 20, 16, 26, 29, 29, 29, 25, 21, 16, 25, 31, 31, 30, 25, 21, 17, 24, + 31, 32, 30, 26, 22, 17, 24, 30, 34, 32, 28, 23, 18, 24, 31, 36, 36, 30, 24, + 20, 27, 33, 38, 39, 33, 27, 21, 35, 39, 39, 32, 27, 22, 18, 34, 41, 42, 34, + 28, 23, 19, 35, 41, 44, 36, 29, 24, 19, 34, 40, 44, 37, 30, 25, 21, 33, 39, + 44, 39, 32, 26, 22, 32, 39, 43, 43, 34, 29, 23, 34, 40, 45, 45, 39, 30, 25, + 7, 8, 9, 10, 10, 10, 11, 7, 7, 8, 10, 10, 9, 8, 6, 7, 8, 9, 8, + 7, 6, 6, 6, 6, 6, 6, 4, 3, 3, 3, 3, 3, 2, 1, 2, 2, 2, 2, + 0, 2, 2, 2, 4, 3, 2, 1, 1, 1, 2, 7, 7, 8, 9, 10, 12, 13, 6, + 7, 8, 9, 10, 10, 11, 6, 7, 7, 7, 8, 8, 8, 5, 5, 5, 5, 5, 5, + 5, 3, 2, 2, 2, 2, 3, 5, 3, 2, 2, 2, 2, 3, 4, 6, 4, 2, 2, + 3, 3, 4, 6, 7, 10, 11, 13, 14, 15, 5, 6, 9, 12, 12, 12, 12, 4, 6, + 9, 10, 10, 10, 10, 8, 4, 6, 8, 8, 8, 8, 10, 2, 4, 7, 8, 8, 8, + 11, 3, 5, 8, 9, 9, 8, 10, 7, 6, 10, 10, 10, 11, 5, 10, 13, 13, 15, + 15, 17, 8, 9, 12, 14, 14, 14, 15, 11, 9, 13, 13, 14, 14, 14, 13, 8, 13, + 14, 14, 15, 13, 13, 10, 14, 15, 16, 16, 16, 11, 12, 16, 16, 17, 16, 17, 10, + 15, 17, 18, 18, 18, 18, 15, 18, 20, 20, 22, 21, 17, 17, 20, 22, 22, 22, 21, + 15, 17, 20, 23, 22, 22, 22, 17, 17, 22, 23, 23, 23, 22, 17, 16, 24, 25, 25, + 25, 23, 19, 16, 25, 28, 27, 26, 24, 20, 17, 26, 30, 28, 29, 26, 22, 27, 31, + 31, 31, 27, 24, 19, 27, 32, 33, 33, 28, 24, 19, 27, 35, 35, 34, 29, 24, 20, + 27, 33, 35, 34, 29, 25, 21, 26, 33, 38, 36, 31, 26, 22, 27, 32, 39, 39, 33, + 27, 23, 28, 34, 39, 40, 35, 30, 25, 38, 44, 42, 36, 31, 26, 21, 38, 45, 45, + 38, 31, 27, 22, 37, 44, 47, 39, 32, 27, 22, 38, 43, 48, 40, 34, 28, 23, 37, + 42, 48, 43, 35, 30, 25, 36, 43, 47, 45, 37, 32, 27, 37, 42, 47, 47, 41, 33, + 28, 6, 6, 7, 8, 8, 9, 10, 5, 6, 7, 8, 8, 8, 8, 5, 6, 6, 6, + 6, 6, 6, 4, 4, 4, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 3, 3, 2, + 2, 2, 0, 1, 3, 5, 4, 2, 2, 1, 1, 3, 5, 6, 7, 8, 10, 12, 13, + 5, 5, 6, 8, 10, 10, 10, 4, 5, 6, 6, 7, 8, 8, 4, 3, 3, 4, 5, + 6, 7, 5, 3, 2, 2, 4, 4, 7, 6, 3, 3, 2, 5, 5, 7, 8, 5, 3, + 3, 6, 6, 7, 4, 5, 8, 11, 13, 14, 15, 4, 4, 8, 11, 12, 12, 14, 8, + 4, 8, 10, 10, 11, 12, 11, 3, 5, 9, 10, 11, 11, 12, 3, 5, 10, 11, 12, + 11, 13, 4, 7, 11, 13, 13, 11, 12, 8, 7, 12, 13, 14, 14, 8, 9, 14, 16, + 17, 17, 19, 11, 9, 14, 17, 18, 17, 18, 14, 9, 15, 17, 18, 18, 17, 16, 10, + 14, 17, 18, 19, 16, 16, 12, 16, 18, 20, 19, 19, 14, 14, 18, 20, 21, 21, 21, + 12, 16, 20, 22, 22, 22, 22, 17, 21, 23, 24, 25, 25, 19, 20, 21, 24, 25, 26, + 25, 18, 20, 22, 26, 26, 27, 25, 21, 20, 25, 26, 27, 27, 26, 21, 18, 26, 28, + 29, 29, 27, 22, 18, 27, 31, 32, 30, 29, 24, 19, 29, 33, 33, 33, 30, 25, 30, + 33, 34, 34, 31, 27, 23, 30, 37, 36, 35, 32, 27, 23, 30, 38, 38, 37, 33, 28, + 23, 30, 38, 39, 37, 33, 29, 24, 28, 37, 42, 39, 35, 30, 25, 30, 37, 44, 42, + 36, 32, 27, 31, 38, 43, 44, 38, 33, 29, 42, 48, 45, 40, 34, 30, 26, 41, 48, + 48, 41, 35, 30, 26, 42, 47, 50, 42, 36, 31, 27, 41, 47, 51, 44, 37, 32, 27, + 40, 45, 51, 46, 39, 34, 29, 40, 46, 50, 49, 42, 36, 30, 40, 46, 51, 51, 44, + 37, 32, 4, 5, 5, 6, 6, 8, 8, 4, 5, 5, 6, 6, 6, 6, 3, 4, 5, + 4, 4, 4, 4, 3, 3, 3, 2, 3, 2, 2, 2, 2, 1, 1, 2, 0, 2, 3, + 2, 2, 1, 2, 0, 2, 5, 3, 2, 1, 1, 0, 2, 4, 4, 5, 6, 8, 9, + 10, 3, 4, 5, 6, 8, 8, 8, 3, 4, 4, 4, 6, 6, 7, 4, 2, 2, 2, + 4, 4, 5, 6, 2, 2, 2, 4, 3, 5, 7, 3, 2, 2, 5, 5, 5, 9, 5, + 3, 2, 6, 6, 5, 3, 4, 7, 9, 10, 12, 14, 5, 3, 7, 10, 10, 10, 12, + 9, 3, 6, 8, 9, 9, 10, 13, 2, 5, 8, 9, 10, 9, 13, 3, 5, 9, 11, + 11, 9, 17, 5, 6, 10, 11, 12, 9, 14, 9, 7, 11, 13, 13, 13, 9, 8, 13, + 15, 15, 15, 17, 15, 8, 13, 16, 17, 17, 16, 16, 8, 14, 15, 16, 17, 16, 19, + 9, 13, 17, 17, 17, 14, 18, 12, 15, 18, 18, 19, 17, 15, 13, 17, 19, 20, 20, + 20, 15, 16, 19, 21, 21, 21, 22, 17, 19, 22, 23, 25, 23, 18, 20, 20, 23, 24, + 26, 23, 17, 20, 21, 25, 25, 26, 24, 19, 20, 23, 25, 25, 26, 24, 20, 19, 25, + 27, 28, 28, 26, 22, 18, 26, 30, 30, 29, 27, 23, 19, 27, 32, 32, 31, 28, 25, + 28, 32, 32, 33, 30, 26, 21, 29, 35, 35, 34, 31, 26, 22, 29, 37, 36, 36, 31, + 26, 22, 28, 36, 39, 37, 33, 28, 23, 29, 35, 40, 40, 33, 29, 24, 28, 36, 42, + 41, 36, 30, 26, 30, 37, 43, 44, 38, 33, 28, 40, 46, 44, 38, 32, 29, 25, 40, + 46, 47, 39, 33, 29, 24, 42, 45, 49, 41, 35, 30, 25, 39, 46, 50, 42, 36, 30, + 26, 39, 44, 49, 46, 39, 32, 28, 39, 45, 50, 48, 40, 34, 29, 39, 45, 50, 50, + 43, 37, 31, 4, 5, 6, 7, 7, 6, 6, 4, 4, 5, 7, 7, 5, 4, 3, 4, + 5, 5, 6, 4, 2, 3, 3, 3, 3, 5, 3, 0, 2, 1, 1, 2, 4, 2, 0, + 2, 2, 2, 2, 3, 2, 0, 4, 3, 2, 2, 3, 2, 0, 4, 4, 5, 6, 7, + 8, 8, 3, 4, 4, 5, 6, 6, 7, 3, 4, 4, 4, 4, 4, 4, 2, 2, 2, + 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 3, 4, 2, 2, 2, 2, 2, 3, 7, + 5, 2, 2, 4, 3, 3, 3, 4, 6, 8, 9, 10, 11, 2, 3, 7, 8, 8, 8, + 9, 5, 3, 6, 7, 6, 6, 8, 9, 2, 4, 7, 6, 6, 6, 11, 2, 4, 7, + 8, 8, 6, 12, 4, 5, 8, 9, 9, 6, 10, 8, 6, 9, 10, 10, 10, 5, 7, + 11, 13, 13, 13, 14, 10, 7, 11, 13, 14, 14, 13, 13, 8, 12, 13, 14, 13, 12, + 15, 8, 12, 14, 14, 14, 11, 15, 10, 13, 15, 15, 15, 14, 13, 12, 15, 16, 17, + 16, 17, 10, 15, 17, 18, 18, 18, 18, 15, 17, 19, 20, 21, 20, 15, 18, 19, 20, + 21, 22, 21, 13, 18, 20, 22, 22, 22, 20, 16, 18, 22, 22, 22, 23, 22, 17, 16, + 23, 24, 24, 25, 23, 18, 16, 24, 27, 27, 26, 23, 20, 17, 25, 30, 28, 28, 25, + 21, 27, 30, 29, 30, 27, 23, 19, 27, 32, 32, 31, 27, 23, 18, 26, 34, 34, 32, + 27, 23, 19, 27, 33, 34, 33, 29, 24, 19, 25, 33, 37, 35, 31, 26, 21, 27, 33, + 40, 38, 32, 26, 22, 27, 34, 40, 40, 34, 29, 24, 37, 43, 40, 34, 29, 26, 21, + 37, 42, 44, 36, 31, 25, 22, 36, 41, 46, 37, 30, 26, 22, 37, 42, 47, 39, 32, + 28, 23, 36, 41, 46, 42, 36, 29, 24, 36, 40, 45, 44, 36, 31, 25, 35, 41, 45, + 46, 40, 33, 28, 14, 15, 16, 18, 18, 17, 16, 13, 15, 16, 18, 17, 16, 14, 13, + 14, 16, 16, 16, 13, 11, 12, 13, 13, 13, 13, 9, 5, 10, 10, 10, 9, 6, 5, + 5, 6, 6, 5, 4, 5, 5, 4, 0, 2, 2, 3, 4, 5, 4, 13, 14, 16, 17, + 17, 17, 16, 12, 14, 15, 16, 17, 16, 14, 12, 13, 15, 15, 14, 13, 11, 11, 12, + 12, 12, 11, 9, 4, 9, 8, 8, 8, 5, 4, 4, 5, 4, 4, 3, 3, 4, 4, + 3, 2, 2, 2, 3, 4, 4, 12, 13, 15, 16, 17, 17, 17, 11, 13, 14, 15, 16, + 15, 15, 12, 12, 13, 13, 13, 12, 11, 11, 11, 10, 10, 10, 8, 4, 7, 7, 7, + 7, 3, 4, 4, 2, 2, 2, 2, 3, 3, 4, 5, 4, 1, 2, 3, 4, 5, 11, + 13, 14, 16, 17, 18, 18, 11, 13, 14, 16, 17, 16, 16, 10, 13, 14, 14, 14, 14, + 12, 7, 12, 11, 11, 11, 9, 9, 4, 8, 7, 7, 5, 5, 6, 3, 6, 6, 6, + 7, 6, 7, 5, 11, 8, 8, 8, 8, 8, 12, 12, 14, 15, 17, 18, 19, 10, 12, + 14, 15, 16, 16, 16, 10, 12, 13, 13, 13, 13, 12, 10, 12, 12, 12, 12, 10, 7, + 8, 13, 13, 13, 14, 13, 8, 8, 14, 16, 16, 16, 15, 10, 11, 17, 19, 18, 18, + 17, 11, 16, 18, 18, 19, 16, 17, 18, 16, 20, 20, 21, 17, 15, 15, 16, 22, 22, + 21, 17, 12, 11, 16, 21, 23, 23, 19, 14, 10, 15, 20, 25, 24, 20, 17, 11, 15, + 22, 27, 25, 23, 18, 13, 17, 23, 27, 28, 24, 20, 15, 25, 31, 30, 24, 18, 16, + 17, 25, 31, 32, 26, 20, 15, 14, 25, 31, 33, 27, 21, 16, 11, 25, 30, 35, 28, + 23, 18, 13, 24, 30, 32, 28, 24, 21, 15, 24, 28, 31, 30, 25, 21, 17, 24, 28, + 31, 31, 27, 23, 19, 12, 13, 15, 16, 16, 16, 15, 12, 13, 14, 15, 15, 14, 12, + 11, 12, 14, 14, 13, 11, 9, 11, 11, 11, 11, 10, 7, 3, 8, 8, 8, 7, 5, + 3, 3, 5, 4, 3, 3, 3, 3, 3, 2, 0, 2, 2, 3, 3, 3, 11, 12, 14, + 15, 16, 16, 15, 11, 12, 13, 15, 15, 14, 12, 11, 12, 13, 13, 12, 11, 9, 11, + 10, 10, 10, 9, 7, 3, 8, 7, 7, 7, 3, 3, 3, 4, 3, 3, 2, 2, 3, + 3, 3, 2, 2, 2, 2, 2, 3, 10, 12, 13, 14, 15, 16, 17, 10, 11, 13, 14, + 14, 14, 14, 11, 11, 12, 12, 12, 11, 10, 10, 10, 10, 10, 9, 7, 5, 5, 6, + 7, 6, 4, 4, 5, 3, 2, 3, 3, 3, 4, 5, 3, 2, 3, 3, 3, 4, 4, + 11, 13, 14, 15, 17, 18, 18, 9, 13, 14, 15, 16, 16, 15, 7, 13, 14, 13, 13, + 13, 11, 8, 11, 11, 11, 10, 9, 9, 6, 7, 8, 8, 8, 8, 8, 3, 8, 9, + 9, 9, 9, 10, 3, 11, 11, 11, 10, 11, 11, 12, 13, 14, 15, 17, 18, 17, 11, + 13, 14, 15, 16, 16, 15, 11, 14, 15, 15, 15, 14, 11, 11, 15, 15, 15, 15, 14, + 10, 10, 17, 17, 16, 17, 15, 12, 11, 17, 20, 19, 18, 17, 13, 13, 18, 22, 20, + 21, 19, 14, 20, 22, 22, 22, 19, 18, 17, 20, 24, 23, 24, 20, 16, 15, 20, 26, + 26, 25, 20, 16, 12, 20, 26, 27, 25, 22, 17, 13, 19, 24, 28, 28, 24, 19, 14, + 19, 25, 31, 30, 25, 20, 16, 20, 25, 31, 33, 27, 22, 17, 28, 34, 33, 27, 22, + 18, 17, 29, 36, 36, 29, 23, 18, 14, 28, 35, 39, 30, 25, 19, 14, 29, 34, 39, + 31, 25, 20, 16, 27, 33, 38, 34, 28, 22, 18, 28, 33, 37, 36, 30, 25, 19, 27, + 34, 38, 39, 33, 26, 21, 9, 11, 12, 13, 13, 13, 12, 9, 10, 11, 13, 12, 11, + 9, 9, 9, 11, 11, 10, 9, 7, 8, 8, 8, 8, 8, 5, 2, 6, 6, 5, 5, + 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 9, 9, + 11, 12, 12, 13, 13, 9, 9, 10, 12, 12, 11, 11, 8, 9, 10, 10, 9, 9, 8, + 8, 7, 7, 7, 7, 5, 3, 5, 5, 4, 4, 2, 2, 3, 2, 2, 1, 1, 2, + 2, 3, 4, 2, 2, 1, 2, 2, 3, 8, 9, 11, 12, 13, 15, 15, 8, 8, 11, + 12, 13, 13, 13, 8, 8, 11, 11, 10, 10, 10, 6, 7, 8, 8, 8, 7, 6, 5, + 3, 5, 6, 4, 5, 6, 6, 2, 4, 5, 5, 5, 6, 5, 4, 5, 6, 6, 6, + 7, 8, 11, 12, 13, 15, 16, 16, 5, 11, 12, 14, 14, 14, 14, 7, 11, 12, 12, + 12, 12, 11, 10, 9, 10, 10, 10, 10, 10, 8, 7, 10, 11, 11, 12, 12, 6, 10, + 13, 12, 13, 13, 13, 5, 13, 14, 14, 14, 14, 15, 12, 15, 16, 16, 17, 18, 16, + 14, 16, 17, 18, 18, 17, 14, 13, 18, 19, 19, 19, 17, 13, 13, 19, 18, 19, 18, + 18, 14, 13, 20, 20, 20, 20, 19, 15, 13, 21, 22, 22, 22, 20, 16, 16, 22, 26, + 24, 24, 22, 18, 23, 26, 25, 25, 23, 19, 16, 24, 28, 28, 28, 24, 19, 15, 24, + 30, 30, 29, 24, 20, 15, 23, 29, 30, 29, 25, 21, 16, 23, 29, 33, 31, 27, 22, + 17, 24, 29, 35, 34, 29, 23, 19, 23, 29, 34, 36, 32, 26, 21, 33, 39, 38, 31, + 25, 21, 18, 33, 40, 41, 33, 27, 22, 18, 33, 39, 43, 35, 29, 22, 18, 33, 39, + 44, 36, 29, 24, 19, 32, 37, 43, 38, 30, 25, 20, 31, 36, 43, 41, 33, 27, 22, + 31, 37, 43, 42, 36, 30, 24, 7, 8, 10, 11, 11, 11, 11, 7, 8, 9, 11, 10, + 9, 8, 7, 8, 9, 9, 8, 7, 6, 6, 6, 6, 6, 6, 4, 2, 4, 3, 3, + 3, 2, 2, 2, 2, 2, 1, 1, 2, 1, 2, 3, 2, 1, 0, 2, 1, 2, 7, + 8, 8, 10, 11, 12, 13, 7, 7, 8, 9, 10, 10, 10, 6, 7, 8, 8, 8, 8, + 8, 6, 6, 5, 5, 5, 5, 4, 3, 3, 2, 3, 2, 3, 4, 3, 2, 2, 1, + 2, 2, 4, 6, 3, 2, 2, 2, 3, 4, 6, 7, 10, 11, 13, 14, 14, 6, 7, + 10, 11, 12, 12, 12, 4, 6, 9, 10, 10, 10, 9, 6, 5, 7, 8, 8, 7, 8, + 8, 2, 4, 7, 7, 7, 8, 9, 3, 5, 8, 8, 8, 8, 8, 6, 6, 9, 9, + 9, 10, 5, 10, 12, 13, 14, 15, 16, 7, 9, 12, 13, 14, 14, 14, 10, 9, 12, + 13, 13, 13, 13, 13, 8, 12, 13, 13, 14, 12, 12, 9, 13, 14, 15, 15, 15, 9, + 12, 15, 16, 16, 16, 16, 8, 15, 17, 18, 17, 16, 18, 14, 18, 19, 19, 21, 20, + 16, 16, 19, 20, 21, 21, 20, 14, 16, 20, 22, 22, 21, 20, 16, 16, 22, 23, 22, + 23, 21, 17, 15, 23, 24, 24, 23, 22, 18, 15, 23, 27, 26, 25, 24, 19, 17, 24, + 29, 27, 27, 26, 20, 26, 30, 29, 30, 27, 22, 18, 26, 31, 31, 31, 28, 22, 18, + 27, 34, 33, 33, 28, 23, 19, 26, 32, 35, 34, 29, 24, 19, 27, 33, 36, 35, 30, + 25, 21, 25, 33, 40, 38, 33, 26, 22, 27, 33, 40, 39, 34, 29, 24, 37, 43, 41, + 34, 29, 25, 21, 37, 43, 43, 37, 30, 26, 21, 36, 43, 46, 38, 32, 26, 21, 38, + 41, 48, 40, 33, 27, 23, 35, 41, 47, 42, 35, 29, 24, 35, 42, 47, 44, 37, 31, + 26, 35, 41, 47, 46, 39, 32, 27, 6, 7, 8, 9, 9, 10, 11, 6, 7, 7, 9, + 9, 8, 8, 5, 6, 7, 7, 7, 6, 6, 5, 5, 5, 5, 5, 3, 3, 3, 2, + 2, 2, 2, 1, 3, 3, 2, 2, 1, 1, 1, 3, 4, 3, 2, 2, 0, 1, 3, + 5, 6, 7, 8, 10, 12, 13, 5, 6, 7, 8, 10, 10, 10, 4, 6, 6, 7, 8, + 8, 8, 4, 4, 4, 4, 5, 6, 6, 4, 2, 2, 2, 3, 3, 6, 5, 3, 2, + 2, 4, 4, 6, 7, 4, 3, 2, 5, 5, 6, 5, 6, 9, 11, 12, 14, 14, 4, + 5, 9, 11, 12, 12, 13, 7, 5, 8, 10, 10, 10, 11, 10, 3, 6, 9, 9, 9, + 10, 12, 3, 5, 9, 10, 10, 10, 13, 4, 6, 10, 11, 11, 10, 11, 8, 7, 11, + 12, 13, 13, 6, 9, 13, 15, 16, 16, 18, 10, 9, 13, 15, 17, 17, 17, 14, 9, + 14, 15, 16, 17, 16, 16, 9, 14, 16, 17, 17, 15, 15, 11, 15, 17, 18, 18, 18, + 13, 13, 17, 19, 19, 19, 19, 12, 16, 18, 20, 20, 21, 21, 16, 19, 22, 23, 24, + 23, 18, 19, 20, 23, 24, 25, 23, 17, 19, 22, 25, 25, 25, 23, 19, 18, 24, 25, + 26, 26, 25, 20, 17, 26, 27, 27, 27, 26, 21, 17, 25, 29, 30, 29, 27, 23, 19, + 28, 33, 31, 30, 29, 24, 29, 32, 33, 32, 30, 25, 21, 29, 35, 35, 34, 31, 26, + 22, 28, 37, 36, 35, 30, 26, 22, 29, 36, 38, 37, 32, 27, 22, 28, 35, 40, 38, + 34, 29, 23, 29, 36, 42, 41, 36, 31, 26, 30, 36, 43, 44, 38, 32, 27, 40, 46, + 44, 38, 33, 28, 24, 41, 46, 47, 40, 34, 29, 24, 40, 46, 50, 41, 35, 29, 25, + 39, 46, 49, 42, 36, 30, 26, 39, 45, 49, 46, 38, 33, 27, 38, 45, 49, 48, 40, + 34, 29, 39, 45, 49, 48, 43, 36, 30, 4, 5, 5, 6, 6, 8, 8, 4, 5, 5, + 6, 6, 6, 6, 3, 4, 5, 4, 4, 4, 4, 3, 3, 3, 2, 3, 2, 2, 2, + 2, 1, 1, 2, 0, 2, 3, 2, 2, 2, 1, 0, 2, 5, 3, 2, 1, 1, 0, + 2, 4, 4, 5, 6, 8, 10, 10, 3, 4, 5, 6, 8, 8, 8, 3, 4, 4, 4, + 5, 6, 7, 4, 2, 2, 2, 3, 4, 5, 6, 2, 2, 2, 4, 3, 5, 7, 3, + 2, 2, 5, 4, 5, 10, 5, 3, 2, 6, 6, 5, 3, 4, 7, 9, 10, 12, 14, + 5, 3, 7, 10, 10, 10, 12, 9, 3, 6, 8, 9, 9, 10, 13, 2, 5, 8, 9, + 10, 9, 14, 3, 5, 9, 11, 10, 9, 15, 5, 6, 10, 12, 11, 9, 14, 8, 7, + 11, 13, 13, 13, 10, 8, 13, 15, 16, 15, 18, 14, 8, 13, 15, 17, 17, 16, 16, + 9, 14, 16, 16, 17, 16, 18, 9, 14, 16, 17, 17, 14, 18, 12, 15, 18, 18, 19, + 17, 16, 13, 17, 19, 20, 20, 19, 14, 16, 19, 20, 21, 21, 21, 17, 19, 22, 23, + 24, 23, 18, 19, 20, 23, 24, 26, 23, 17, 20, 21, 25, 25, 25, 24, 19, 20, 23, + 25, 26, 26, 24, 20, 18, 26, 28, 28, 28, 26, 21, 18, 26, 31, 31, 29, 27, 23, + 19, 27, 33, 32, 32, 28, 24, 28, 33, 33, 32, 30, 26, 22, 29, 34, 35, 35, 31, + 27, 22, 28, 38, 37, 35, 31, 26, 23, 29, 37, 37, 37, 32, 27, 23, 28, 35, 40, + 39, 34, 29, 24, 29, 35, 43, 41, 36, 31, 27, 29, 38, 43, 44, 38, 32, 27, 40, + 46, 44, 37, 32, 28, 24, 39, 45, 46, 40, 33, 29, 24, 41, 45, 49, 41, 34, 30, + 25, 40, 45, 50, 42, 35, 31, 26, 39, 44, 49, 45, 38, 33, 28, 39, 46, 50, 47, + 41, 35, 29, 40, 44, 50, 50, 43, 36, 31, 4, 5, 6, 8, 8, 6, 6, 4, 4, + 5, 7, 7, 5, 4, 3, 4, 5, 5, 6, 4, 2, 3, 3, 3, 4, 5, 3, 0, + 2, 2, 1, 2, 4, 2, 0, 2, 2, 2, 2, 3, 2, 0, 4, 3, 2, 2, 3, + 2, 0, 4, 4, 5, 6, 6, 8, 8, 3, 4, 4, 5, 6, 6, 7, 3, 4, 4, + 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 3, 4, + 3, 2, 2, 2, 2, 3, 7, 5, 2, 2, 3, 3, 3, 3, 4, 6, 8, 9, 10, + 11, 2, 3, 6, 8, 8, 8, 9, 5, 3, 6, 7, 6, 6, 8, 9, 2, 4, 7, + 6, 6, 6, 11, 2, 4, 7, 8, 8, 6, 12, 4, 5, 8, 9, 9, 6, 10, 8, + 6, 9, 10, 10, 10, 5, 7, 11, 12, 13, 13, 14, 10, 7, 12, 13, 13, 14, 13, + 14, 8, 12, 13, 13, 13, 12, 14, 8, 12, 14, 14, 14, 11, 15, 10, 13, 15, 15, + 15, 14, 14, 12, 15, 16, 17, 16, 16, 10, 15, 17, 18, 18, 18, 18, 15, 18, 19, + 20, 21, 20, 14, 18, 18, 20, 21, 22, 20, 13, 18, 20, 22, 22, 21, 20, 16, 18, + 22, 23, 22, 23, 22, 17, 16, 24, 24, 24, 24, 22, 18, 16, 24, 27, 27, 26, 24, + 20, 17, 25, 30, 29, 28, 26, 21, 26, 29, 30, 29, 26, 22, 18, 26, 32, 30, 30, + 27, 23, 19, 27, 33, 33, 32, 27, 23, 19, 26, 33, 34, 32, 28, 24, 20, 27, 34, + 36, 35, 31, 25, 21, 27, 34, 40, 38, 33, 27, 23, 28, 34, 39, 39, 35, 29, 24, + 36, 42, 40, 34, 29, 25, 21, 37, 43, 43, 36, 30, 25, 21, 36, 42, 45, 37, 32, + 27, 21, 37, 41, 46, 38, 32, 27, 23, 35, 40, 45, 41, 35, 28, 24, 36, 42, 46, + 44, 37, 32, 25, 37, 41, 46, 46, 38, 33, 27, 2, 2, 3, 3, 3, 2, 2, 1, + 2, 3, 3, 3, 2, 2, 0, 2, 2, 3, 3, 2, 1, 1, 2, 2, 2, 2, 2, + 4, 3, 3, 3, 4, 4, 3, 4, 7, 7, 7, 6, 5, 4, 4, 13, 11, 9, 7, + 5, 4, 4, 0, 2, 2, 3, 2, 2, 1, 1, 2, 2, 3, 2, 2, 1, 2, 1, + 2, 2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 3, 4, 4, 4, 5, 4, 4, 4, + 9, 9, 9, 7, 5, 4, 4, 16, 14, 10, 8, 6, 4, 4, 2, 1, 2, 1, 2, + 1, 4, 2, 1, 2, 1, 1, 1, 4, 2, 1, 0, 0, 1, 0, 5, 3, 2, 3, + 3, 3, 3, 6, 7, 6, 6, 6, 7, 6, 7, 12, 11, 11, 10, 9, 7, 7, 19, + 17, 14, 12, 10, 9, 8, 2, 4, 5, 5, 5, 5, 8, 3, 5, 5, 6, 6, 6, + 8, 7, 6, 6, 7, 7, 8, 8, 10, 9, 10, 10, 10, 11, 10, 10, 14, 14, 14, + 14, 14, 12, 13, 20, 19, 17, 16, 15, 14, 19, 26, 22, 20, 18, 16, 15, 12, 13, + 12, 13, 12, 12, 8, 13, 14, 14, 14, 14, 13, 8, 14, 16, 16, 15, 16, 15, 11, + 13, 20, 19, 19, 19, 18, 14, 17, 25, 24, 22, 23, 21, 16, 21, 27, 30, 26, 25, + 23, 17, 25, 31, 32, 29, 27, 25, 20, 21, 23, 22, 21, 18, 15, 11, 21, 26, 24, + 23, 20, 16, 11, 22, 27, 26, 25, 22, 18, 14, 22, 28, 30, 29, 25, 22, 18, 25, + 31, 35, 34, 30, 25, 20, 27, 33, 40, 38, 33, 26, 22, 31, 37, 41, 41, 35, 28, + 23, 29, 35, 34, 27, 22, 17, 13, 29, 35, 36, 29, 23, 19, 15, 30, 35, 38, 31, + 26, 21, 17, 30, 36, 41, 35, 30, 25, 21, 31, 37, 43, 40, 35, 28, 24, 34, 40, + 46, 45, 38, 31, 25, 37, 42, 46, 46, 39, 33, 27, 1, 2, 2, 2, 2, 2, 1, + 2, 1, 2, 3, 2, 2, 1, 2, 0, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, + 3, 4, 4, 4, 4, 5, 5, 4, 4, 8, 8, 8, 7, 6, 4, 4, 14, 13, 9, + 8, 6, 4, 4, 2, 0, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, + 2, 1, 2, 2, 1, 4, 2, 2, 2, 3, 2, 3, 5, 6, 5, 5, 6, 5, 4, + 5, 11, 10, 10, 8, 6, 5, 5, 18, 15, 11, 9, 7, 5, 5, 2, 2, 1, 1, + 1, 3, 6, 2, 2, 2, 2, 2, 4, 6, 3, 2, 3, 3, 4, 4, 7, 7, 3, + 6, 6, 7, 7, 9, 11, 7, 10, 10, 11, 9, 9, 15, 12, 14, 13, 12, 11, 9, + 20, 18, 17, 16, 14, 12, 12, 4, 6, 7, 8, 8, 7, 10, 7, 7, 8, 8, 9, + 9, 10, 11, 8, 10, 10, 11, 11, 11, 14, 10, 13, 14, 14, 14, 13, 14, 16, 18, + 18, 18, 17, 15, 15, 22, 23, 21, 21, 19, 18, 20, 28, 26, 24, 22, 20, 19, 15, + 15, 15, 15, 16, 14, 10, 17, 17, 17, 17, 17, 15, 10, 17, 19, 19, 19, 19, 18, + 14, 17, 22, 23, 23, 23, 22, 18, 20, 27, 28, 26, 28, 25, 20, 24, 30, 34, 32, + 29, 27, 21, 29, 34, 35, 33, 31, 28, 22, 25, 26, 24, 25, 21, 17, 13, 24, 29, + 27, 26, 23, 18, 14, 25, 31, 30, 29, 25, 22, 17, 25, 32, 34, 33, 29, 25, 22, + 28, 34, 38, 38, 34, 28, 23, 31, 37, 45, 42, 36, 30, 25, 34, 39, 45, 45, 38, + 32, 27, 33, 38, 36, 30, 25, 20, 16, 33, 39, 40, 32, 26, 21, 18, 34, 39, 43, + 34, 30, 26, 21, 33, 39, 46, 39, 33, 29, 25, 35, 40, 48, 44, 38, 31, 27, 38, + 44, 50, 48, 42, 34, 29, 40, 46, 51, 51, 44, 37, 30, 2, 1, 2, 2, 2, 2, + 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 3, 2, 3, 2, 3, + 3, 4, 5, 5, 5, 6, 5, 6, 5, 5, 10, 9, 9, 8, 7, 5, 5, 16, 13, + 11, 8, 7, 5, 5, 2, 2, 0, 2, 1, 2, 4, 3, 2, 1, 2, 1, 2, 5, + 3, 2, 1, 1, 1, 3, 6, 4, 3, 3, 3, 3, 4, 7, 8, 7, 7, 7, 7, + 5, 7, 12, 11, 11, 10, 9, 7, 7, 20, 16, 13, 11, 10, 9, 7, 3, 2, 4, + 4, 4, 5, 7, 5, 2, 4, 4, 5, 5, 8, 8, 3, 5, 7, 7, 6, 9, 11, + 4, 8, 10, 10, 10, 11, 15, 9, 11, 14, 14, 13, 11, 18, 14, 16, 17, 16, 15, + 11, 21, 19, 19, 19, 18, 16, 15, 8, 7, 10, 10, 10, 8, 11, 12, 8, 11, 11, + 12, 12, 12, 15, 9, 12, 14, 14, 15, 14, 17, 12, 17, 18, 18, 18, 15, 18, 17, + 20, 21, 22, 22, 19, 18, 24, 26, 25, 23, 23, 21, 22, 30, 28, 28, 25, 24, 23, + 17, 18, 19, 18, 19, 17, 12, 20, 19, 20, 19, 20, 19, 12, 20, 20, 22, 23, 23, + 22, 17, 20, 24, 26, 27, 27, 26, 22, 23, 29, 31, 31, 31, 29, 24, 25, 33, 36, + 35, 33, 30, 25, 30, 38, 40, 38, 36, 31, 27, 28, 29, 28, 27, 24, 21, 15, 27, + 32, 31, 30, 26, 22, 18, 27, 33, 33, 32, 30, 25, 22, 28, 35, 39, 37, 33, 29, + 25, 31, 38, 43, 42, 38, 32, 27, 35, 42, 48, 46, 40, 34, 28, 38, 44, 49, 49, + 43, 36, 30, 37, 42, 39, 34, 27, 23, 19, 37, 42, 43, 36, 30, 25, 21, 37, 42, + 46, 39, 33, 29, 25, 37, 44, 50, 42, 38, 32, 28, 39, 45, 52, 49, 42, 36, 31, + 43, 48, 54, 54, 46, 39, 33, 44, 50, 55, 55, 48, 41, 33, 2, 2, 1, 2, 2, + 1, 3, 3, 2, 2, 2, 1, 1, 4, 3, 2, 2, 2, 3, 3, 5, 3, 3, 4, + 3, 4, 5, 6, 6, 6, 7, 7, 7, 6, 6, 11, 11, 11, 10, 8, 6, 6, 17, + 15, 12, 10, 8, 6, 6, 3, 2, 2, 0, 1, 4, 6, 3, 2, 2, 1, 1, 4, + 6, 5, 3, 2, 3, 3, 5, 8, 8, 4, 4, 5, 7, 6, 9, 11, 7, 8, 9, + 10, 7, 9, 15, 12, 12, 12, 12, 10, 9, 21, 18, 14, 12, 13, 12, 9, 5, 3, + 5, 6, 6, 7, 8, 8, 3, 5, 7, 7, 6, 9, 11, 3, 5, 9, 10, 8, 11, + 15, 5, 9, 13, 13, 13, 13, 18, 10, 12, 17, 18, 16, 13, 21, 16, 17, 20, 19, + 18, 13, 24, 21, 20, 21, 21, 19, 17, 11, 8, 12, 12, 13, 10, 13, 15, 9, 12, + 14, 15, 14, 15, 18, 11, 14, 17, 18, 19, 16, 20, 14, 18, 20, 21, 21, 18, 21, + 20, 22, 24, 25, 24, 21, 22, 25, 29, 28, 26, 27, 24, 23, 31, 31, 31, 29, 29, + 27, 20, 19, 20, 21, 21, 20, 13, 24, 20, 21, 23, 23, 22, 14, 23, 22, 24, 26, + 27, 25, 20, 24, 26, 29, 30, 30, 29, 25, 24, 33, 35, 35, 35, 31, 27, 28, 37, + 40, 39, 37, 33, 28, 32, 40, 44, 40, 40, 37, 32, 29, 32, 31, 32, 27, 23, 18, + 29, 35, 33, 33, 30, 26, 22, 29, 36, 36, 37, 32, 28, 25, 29, 37, 41, 41, 37, + 33, 29, 33, 41, 47, 46, 42, 36, 31, 36, 45, 52, 50, 44, 38, 31, 40, 46, 53, + 53, 46, 40, 34, 40, 45, 43, 37, 30, 26, 22, 40, 46, 45, 38, 32, 28, 25, 39, + 45, 49, 43, 38, 32, 28, 39, 46, 53, 46, 41, 36, 33, 44, 49, 54, 52, 46, 40, + 35, 45, 52, 58, 57, 48, 43, 36, 48, 54, 60, 59, 52, 44, 38, 2, 1, 1, 3, + 3, 1, 2, 2, 2, 1, 2, 3, 2, 3, 2, 2, 1, 3, 4, 4, 4, 2, 3, + 4, 5, 6, 6, 6, 6, 7, 7, 8, 10, 8, 6, 11, 11, 11, 10, 10, 8, 7, + 17, 15, 13, 11, 10, 8, 7, 2, 2, 1, 1, 0, 2, 4, 2, 2, 1, 1, 1, + 3, 5, 5, 2, 2, 2, 3, 4, 6, 9, 3, 4, 5, 6, 5, 8, 11, 7, 8, + 9, 10, 6, 8, 15, 13, 13, 12, 11, 10, 8, 21, 18, 15, 13, 13, 12, 8, 5, + 2, 4, 5, 5, 5, 7, 10, 2, 4, 6, 7, 5, 8, 13, 2, 5, 9, 10, 6, + 10, 15, 5, 8, 12, 13, 12, 12, 17, 10, 12, 16, 17, 16, 12, 21, 16, 17, 19, + 19, 17, 12, 24, 21, 20, 21, 20, 19, 16, 13, 7, 11, 12, 11, 8, 11, 16, 9, + 11, 12, 14, 13, 13, 19, 11, 13, 16, 17, 17, 15, 21, 14, 17, 20, 20, 21, 17, + 21, 19, 22, 24, 23, 24, 21, 22, 25, 27, 28, 27, 26, 23, 24, 31, 31, 30, 28, + 27, 26, 21, 18, 19, 20, 20, 19, 11, 24, 19, 21, 21, 22, 22, 13, 25, 21, 23, + 25, 26, 24, 19, 24, 26, 27, 30, 29, 28, 24, 25, 31, 33, 34, 35, 33, 26, 27, + 36, 39, 38, 36, 34, 28, 32, 41, 42, 41, 39, 35, 30, 28, 30, 30, 28, 25, 22, + 16, 29, 33, 31, 31, 28, 24, 20, 28, 35, 34, 35, 31, 28, 24, 29, 37, 40, 39, + 37, 31, 28, 32, 40, 45, 45, 41, 35, 29, 36, 44, 51, 48, 42, 37, 32, 39, 48, + 51, 50, 45, 39, 33, 38, 43, 41, 34, 28, 24, 21, 38, 43, 43, 37, 31, 28, 24, + 37, 44, 46, 39, 36, 31, 28, 37, 45, 51, 45, 39, 36, 31, 41, 49, 54, 51, 45, + 39, 33, 44, 51, 57, 56, 47, 41, 34, 47, 52, 57, 58, 50, 43, 37, 2, 1, 3, + 5, 5, 3, 2, 2, 1, 3, 4, 6, 4, 3, 2, 1, 2, 5, 7, 6, 5, 2, + 3, 4, 6, 8, 8, 8, 5, 6, 7, 9, 11, 10, 8, 11, 11, 11, 12, 12, 10, + 8, 17, 15, 13, 12, 12, 10, 8, 2, 1, 2, 4, 2, 0, 2, 2, 2, 2, 3, + 3, 1, 4, 2, 2, 1, 4, 4, 3, 5, 5, 3, 4, 6, 6, 6, 6, 8, 7, + 8, 9, 9, 7, 7, 14, 13, 12, 12, 10, 8, 6, 21, 18, 15, 12, 10, 9, 7, + 2, 2, 3, 2, 2, 3, 5, 6, 2, 3, 3, 4, 4, 6, 10, 2, 4, 6, 7, + 5, 7, 13, 3, 8, 10, 10, 10, 10, 15, 9, 12, 14, 14, 13, 10, 19, 15, 17, + 17, 16, 15, 10, 23, 22, 19, 19, 17, 16, 14, 10, 7, 9, 9, 9, 6, 8, 14, + 7, 10, 10, 11, 11, 10, 16, 9, 11, 13, 14, 15, 12, 19, 12, 16, 18, 18, 18, + 14, 18, 17, 20, 22, 22, 21, 17, 19, 24, 25, 25, 25, 24, 21, 23, 30, 29, 28, + 26, 24, 23, 19, 16, 17, 17, 17, 16, 9, 23, 18, 18, 18, 20, 18, 10, 23, 20, + 21, 22, 23, 21, 16, 22, 24, 26, 27, 27, 26, 22, 22, 29, 31, 31, 31, 29, 23, + 25, 35, 37, 36, 34, 31, 25, 31, 38, 39, 37, 35, 32, 26, 27, 28, 27, 26, 23, + 18, 14, 28, 31, 27, 27, 25, 21, 18, 26, 32, 32, 32, 29, 25, 21, 26, 34, 37, + 36, 32, 29, 25, 30, 38, 43, 42, 39, 31, 28, 35, 42, 49, 46, 39, 33, 28, 39, + 44, 49, 49, 42, 38, 30, 35, 41, 36, 31, 25, 21, 18, 34, 39, 39, 32, 27, 25, + 20, 36, 40, 41, 36, 33, 29, 25, 35, 42, 47, 42, 36, 32, 29, 39, 44, 52, 49, + 41, 37, 31, 42, 48, 54, 52, 44, 38, 32, 45, 50, 53, 54, 47, 41, 34, 1, 4, + 5, 7, 7, 5, 3, 1, 3, 5, 7, 8, 6, 5, 1, 2, 5, 7, 9, 8, 6, + 2, 3, 6, 8, 10, 9, 8, 5, 6, 8, 10, 12, 10, 8, 10, 10, 12, 13, 12, + 10, 8, 16, 15, 13, 13, 13, 10, 8, 1, 2, 4, 5, 4, 2, 0, 2, 1, 4, + 5, 4, 3, 2, 2, 1, 3, 6, 5, 4, 4, 2, 3, 5, 7, 7, 6, 6, 6, + 7, 8, 10, 10, 8, 6, 12, 12, 12, 13, 10, 8, 6, 20, 17, 14, 13, 11, 9, + 6, 2, 1, 1, 1, 2, 2, 3, 2, 2, 1, 1, 1, 2, 4, 5, 2, 2, 3, + 3, 3, 5, 10, 3, 6, 7, 6, 7, 7, 12, 8, 10, 11, 11, 10, 7, 17, 14, + 15, 14, 12, 11, 7, 22, 20, 18, 16, 14, 13, 11, 5, 6, 6, 6, 6, 5, 7, + 11, 6, 7, 7, 8, 8, 7, 14, 7, 9, 10, 11, 11, 9, 16, 10, 14, 14, 14, + 15, 11, 16, 16, 18, 18, 18, 18, 15, 17, 23, 23, 22, 21, 19, 18, 22, 30, 26, + 24, 22, 21, 20, 16, 14, 14, 13, 14, 13, 7, 18, 15, 15, 15, 16, 15, 7, 18, + 18, 18, 19, 19, 17, 13, 19, 22, 22, 23, 23, 22, 18, 20, 27, 28, 28, 28, 25, + 20, 24, 31, 34, 32, 29, 26, 22, 29, 34, 37, 34, 32, 29, 23, 24, 24, 23, 23, + 19, 15, 11, 24, 28, 25, 24, 21, 18, 14, 24, 30, 28, 27, 26, 21, 18, 24, 31, + 33, 32, 29, 26, 22, 27, 34, 39, 36, 33, 29, 23, 32, 38, 44, 42, 35, 30, 25, + 34, 41, 45, 45, 39, 33, 26, 30, 37, 33, 27, 22, 18, 14, 32, 36, 35, 29, 24, + 21, 18, 32, 36, 38, 32, 28, 25, 21, 31, 37, 44, 38, 33, 29, 25, 34, 40, 46, + 42, 38, 32, 27, 38, 44, 48, 48, 41, 34, 29, 42, 48, 50, 50, 43, 35, 30, 2, + 2, 3, 4, 4, 3, 2, 2, 2, 3, 4, 4, 2, 2, 1, 2, 2, 3, 3, 2, + 1, 0, 2, 2, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 3, 7, 6, 7, 6, + 5, 3, 3, 13, 11, 9, 7, 5, 3, 3, 1, 2, 3, 3, 2, 2, 2, 0, 2, + 2, 3, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 3, + 4, 4, 4, 4, 4, 3, 3, 9, 8, 8, 7, 5, 4, 3, 16, 13, 10, 8, 6, + 4, 3, 1, 2, 2, 2, 2, 2, 3, 2, 2, 2, 1, 2, 1, 3, 2, 1, 1, + 1, 1, 1, 4, 2, 2, 2, 2, 2, 2, 6, 6, 6, 5, 5, 6, 5, 5, 12, + 11, 10, 9, 7, 6, 5, 18, 16, 13, 11, 9, 7, 7, 2, 3, 4, 4, 4, 4, + 8, 2, 5, 4, 5, 5, 5, 8, 5, 5, 6, 6, 6, 7, 8, 8, 8, 9, 9, + 9, 10, 9, 9, 13, 13, 13, 13, 12, 12, 12, 18, 17, 16, 15, 14, 13, 18, 24, + 21, 19, 16, 15, 15, 11, 11, 12, 12, 12, 11, 7, 13, 13, 13, 13, 13, 12, 8, + 13, 15, 14, 15, 14, 13, 10, 13, 19, 18, 18, 18, 17, 14, 16, 23, 22, 21, 23, + 20, 15, 20, 26, 27, 26, 24, 22, 17, 24, 29, 31, 28, 26, 24, 19, 20, 22, 21, + 21, 18, 14, 9, 21, 24, 23, 22, 19, 15, 10, 21, 26, 25, 25, 21, 17, 13, 21, + 27, 29, 28, 25, 20, 17, 23, 28, 33, 32, 29, 23, 18, 26, 31, 38, 37, 32, 25, + 20, 29, 35, 38, 39, 34, 28, 22, 28, 35, 33, 26, 21, 17, 12, 28, 34, 35, 28, + 23, 18, 14, 28, 34, 38, 30, 25, 20, 16, 28, 34, 40, 35, 29, 24, 20, 30, 36, + 43, 39, 32, 28, 23, 32, 38, 43, 42, 36, 29, 24, 34, 40, 44, 46, 38, 32, 26, + 0, 2, 2, 3, 3, 2, 2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 2, 2, 2, + 1, 2, 2, 1, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 4, 4, 8, 8, 8, + 7, 5, 4, 4, 14, 12, 9, 7, 6, 4, 4, 2, 1, 2, 3, 2, 2, 1, 2, + 0, 2, 2, 2, 1, 1, 2, 1, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 3, + 4, 5, 5, 5, 5, 5, 4, 4, 10, 9, 9, 8, 6, 4, 4, 17, 15, 11, 9, + 7, 5, 4, 2, 1, 1, 1, 1, 2, 6, 2, 2, 1, 1, 1, 3, 6, 2, 2, + 2, 2, 2, 3, 7, 6, 3, 5, 5, 5, 6, 8, 9, 7, 9, 9, 9, 8, 8, + 14, 12, 13, 12, 11, 10, 8, 20, 18, 16, 14, 12, 11, 10, 3, 6, 6, 6, 7, + 6, 9, 6, 7, 7, 8, 8, 8, 9, 9, 7, 9, 9, 10, 10, 10, 12, 10, 12, + 13, 13, 13, 12, 13, 15, 16, 17, 17, 16, 14, 14, 21, 21, 20, 19, 17, 16, 20, + 28, 24, 22, 20, 19, 18, 14, 15, 14, 14, 15, 13, 9, 16, 17, 16, 15, 16, 15, + 10, 16, 17, 18, 18, 18, 17, 13, 15, 22, 21, 21, 22, 20, 17, 19, 26, 27, 26, + 26, 23, 19, 23, 31, 32, 30, 28, 25, 20, 27, 33, 35, 31, 29, 27, 21, 24, 25, + 24, 24, 20, 16, 12, 23, 27, 25, 25, 22, 18, 14, 24, 30, 28, 27, 25, 20, 17, + 23, 30, 33, 31, 28, 24, 20, 27, 33, 38, 36, 32, 28, 22, 30, 36, 42, 41, 34, + 29, 24, 33, 39, 43, 42, 37, 31, 26, 32, 37, 36, 29, 23, 19, 15, 32, 37, 38, + 30, 25, 20, 17, 31, 36, 40, 33, 28, 23, 20, 32, 38, 44, 38, 32, 28, 24, 34, + 41, 46, 44, 37, 31, 25, 36, 43, 48, 49, 40, 34, 28, 39, 45, 49, 50, 42, 35, + 30, 2, 0, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, + 2, 2, 3, 2, 2, 2, 2, 3, 3, 4, 5, 5, 5, 5, 5, 5, 4, 9, 9, + 9, 8, 6, 5, 4, 15, 13, 10, 8, 7, 5, 4, 2, 2, 1, 2, 1, 1, 4, + 2, 2, 0, 2, 1, 1, 4, 2, 2, 1, 1, 1, 2, 5, 3, 3, 3, 3, 3, + 4, 6, 7, 6, 6, 6, 6, 4, 6, 11, 11, 11, 9, 7, 6, 6, 19, 16, 12, + 10, 9, 7, 6, 3, 2, 3, 3, 3, 5, 7, 3, 2, 3, 4, 4, 5, 7, 7, + 2, 4, 6, 6, 5, 8, 10, 3, 7, 9, 9, 9, 10, 13, 8, 11, 12, 13, 12, + 10, 17, 13, 15, 16, 15, 13, 10, 21, 19, 18, 17, 16, 15, 14, 7, 7, 9, 9, + 10, 8, 11, 11, 8, 10, 10, 11, 11, 11, 13, 8, 11, 12, 13, 13, 12, 16, 11, + 15, 16, 16, 17, 14, 17, 17, 20, 20, 20, 19, 18, 18, 23, 24, 24, 23, 21, 20, + 21, 30, 27, 25, 24, 22, 22, 17, 17, 17, 17, 18, 16, 11, 19, 18, 18, 18, 18, + 18, 11, 19, 20, 21, 21, 22, 20, 16, 19, 23, 25, 25, 25, 24, 20, 21, 30, 30, + 29, 29, 26, 22, 25, 34, 35, 34, 31, 29, 24, 30, 36, 39, 35, 34, 31, 26, 26, + 28, 27, 27, 23, 19, 15, 26, 31, 29, 28, 25, 21, 17, 26, 32, 32, 31, 28, 24, + 20, 26, 34, 37, 35, 31, 28, 23, 30, 36, 41, 40, 36, 30, 26, 33, 41, 46, 45, + 38, 32, 27, 37, 42, 48, 48, 41, 35, 28, 35, 41, 39, 32, 26, 22, 18, 35, 41, + 42, 34, 29, 24, 20, 36, 42, 45, 37, 33, 27, 23, 36, 42, 49, 41, 37, 31, 27, + 38, 45, 50, 47, 42, 35, 29, 41, 48, 53, 52, 44, 37, 31, 44, 50, 53, 54, 46, + 40, 32, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, 1, 3, 3, 2, 1, + 2, 3, 3, 4, 3, 3, 3, 3, 4, 5, 5, 6, 6, 7, 6, 7, 6, 5, 10, + 10, 10, 9, 8, 6, 5, 17, 15, 12, 10, 8, 6, 5, 3, 2, 2, 1, 1, 3, + 5, 3, 2, 2, 0, 1, 3, 6, 3, 2, 2, 2, 2, 4, 7, 6, 4, 4, 5, + 5, 5, 8, 10, 7, 8, 8, 9, 6, 8, 14, 12, 12, 11, 10, 9, 8, 20, 17, + 14, 12, 12, 11, 8, 3, 2, 4, 5, 5, 6, 8, 7, 3, 4, 6, 6, 6, 9, + 10, 3, 5, 8, 9, 7, 10, 14, 5, 9, 12, 12, 12, 12, 16, 9, 12, 15, 16, + 15, 12, 20, 15, 16, 19, 18, 17, 12, 23, 21, 20, 21, 19, 18, 16, 10, 7, 11, + 12, 12, 9, 13, 14, 8, 12, 13, 14, 13, 13, 17, 10, 13, 16, 16, 17, 15, 19, + 13, 17, 20, 20, 20, 17, 20, 18, 22, 24, 24, 23, 20, 20, 24, 26, 28, 26, 25, + 23, 23, 30, 30, 29, 27, 26, 25, 19, 19, 20, 20, 20, 19, 13, 23, 20, 21, 22, + 22, 21, 13, 22, 22, 23, 25, 26, 24, 19, 22, 26, 28, 28, 29, 28, 24, 24, 32, + 33, 33, 33, 31, 25, 27, 37, 39, 38, 35, 32, 27, 31, 40, 42, 39, 39, 35, 29, + 28, 31, 30, 29, 27, 22, 17, 29, 33, 32, 31, 28, 24, 20, 28, 35, 34, 35, 32, + 27, 23, 28, 37, 40, 39, 36, 31, 27, 32, 41, 46, 44, 41, 34, 29, 36, 43, 50, + 49, 42, 37, 32, 40, 47, 51, 51, 45, 38, 32, 38, 44, 41, 35, 28, 25, 20, 38, + 44, 44, 37, 32, 28, 24, 39, 44, 47, 41, 36, 31, 27, 38, 45, 52, 46, 40, 36, + 31, 41, 48, 55, 52, 44, 39, 34, 45, 51, 57, 56, 47, 40, 35, 48, 53, 56, 58, + 51, 43, 37, 2, 1, 1, 3, 3, 1, 2, 2, 1, 1, 2, 3, 2, 3, 2, 2, + 1, 3, 4, 4, 4, 2, 3, 3, 4, 6, 6, 6, 5, 6, 7, 7, 9, 8, 6, + 11, 11, 11, 10, 10, 8, 6, 17, 15, 12, 10, 9, 8, 6, 2, 2, 1, 1, 1, + 3, 4, 2, 2, 1, 1, 0, 3, 5, 4, 2, 1, 2, 2, 4, 6, 8, 3, 4, + 5, 5, 5, 7, 10, 7, 8, 9, 9, 6, 7, 14, 12, 12, 12, 11, 9, 7, 21, + 17, 14, 12, 12, 11, 7, 4, 2, 4, 5, 5, 6, 8, 9, 2, 4, 6, 6, 5, + 8, 13, 2, 5, 8, 9, 6, 10, 15, 5, 8, 12, 12, 12, 12, 17, 10, 12, 16, + 17, 16, 12, 21, 15, 17, 19, 19, 17, 12, 24, 21, 19, 20, 19, 18, 16, 13, 7, + 11, 12, 11, 9, 12, 16, 8, 11, 12, 14, 13, 13, 19, 11, 12, 15, 17, 17, 14, + 21, 14, 17, 20, 20, 20, 16, 20, 19, 22, 23, 25, 24, 19, 22, 25, 27, 27, 27, + 25, 24, 23, 31, 30, 30, 28, 27, 26, 21, 17, 19, 20, 20, 19, 12, 24, 19, 21, + 21, 22, 21, 13, 24, 21, 23, 24, 25, 24, 18, 24, 26, 27, 28, 30, 28, 24, 25, + 32, 32, 34, 33, 32, 25, 27, 34, 39, 38, 36, 33, 27, 32, 39, 43, 39, 38, 36, + 29, 28, 29, 29, 29, 26, 22, 16, 28, 33, 31, 31, 27, 24, 20, 28, 36, 35, 33, + 31, 27, 24, 28, 37, 39, 38, 35, 31, 27, 32, 39, 45, 44, 40, 34, 30, 35, 43, + 51, 47, 41, 36, 31, 39, 48, 52, 52, 45, 38, 33, 38, 43, 40, 34, 29, 24, 21, + 38, 43, 43, 37, 32, 27, 24, 37, 43, 46, 40, 36, 32, 27, 37, 44, 50, 44, 40, + 34, 31, 41, 48, 53, 51, 43, 39, 33, 45, 51, 55, 56, 48, 40, 34, 47, 53, 55, + 57, 51, 41, 37, 1, 1, 4, 6, 5, 4, 2, 1, 1, 3, 5, 5, 3, 2, 2, + 1, 2, 4, 6, 5, 4, 2, 2, 3, 5, 7, 6, 6, 5, 5, 6, 8, 10, 8, + 6, 10, 9, 9, 10, 10, 8, 6, 15, 14, 11, 10, 10, 8, 6, 2, 1, 2, 4, + 3, 1, 3, 2, 1, 1, 3, 3, 0, 3, 2, 2, 1, 3, 3, 2, 4, 4, 3, + 4, 5, 5, 4, 5, 7, 6, 7, 8, 7, 6, 5, 12, 11, 11, 10, 8, 6, 5, + 19, 16, 12, 10, 9, 8, 5, 2, 1, 3, 2, 3, 4, 6, 4, 2, 3, 3, 4, + 3, 5, 8, 2, 4, 6, 6, 4, 6, 13, 3, 7, 9, 9, 9, 8, 14, 8, 11, + 13, 13, 12, 8, 18, 14, 15, 16, 15, 13, 8, 21, 19, 18, 18, 16, 15, 13, 9, + 6, 9, 9, 9, 7, 10, 13, 7, 9, 10, 10, 10, 9, 16, 8, 11, 13, 13, 13, + 11, 18, 11, 15, 16, 17, 17, 13, 18, 17, 19, 20, 21, 19, 16, 18, 23, 25, 23, + 23, 21, 19, 21, 28, 27, 26, 24, 23, 22, 18, 16, 17, 16, 17, 17, 10, 21, 18, + 18, 18, 19, 17, 9, 21, 19, 20, 22, 21, 20, 15, 21, 23, 24, 25, 25, 24, 20, + 22, 29, 30, 30, 30, 27, 22, 25, 33, 35, 34, 32, 29, 24, 29, 37, 38, 35, 34, + 31, 26, 26, 28, 27, 26, 22, 19, 14, 26, 30, 28, 27, 25, 21, 17, 25, 32, 31, + 30, 28, 24, 20, 26, 34, 36, 35, 32, 28, 24, 28, 36, 41, 40, 36, 31, 26, 33, + 41, 47, 43, 38, 31, 27, 37, 41, 47, 47, 40, 34, 29, 35, 40, 37, 30, 26, 22, + 18, 34, 40, 40, 33, 27, 24, 20, 35, 40, 43, 36, 31, 27, 24, 34, 42, 46, 41, + 36, 32, 28, 37, 43, 48, 46, 40, 35, 30, 41, 46, 52, 51, 42, 36, 31, 44, 49, + 53, 52, 45, 39, 32, 1, 5, 6, 8, 8, 6, 4, 0, 3, 6, 8, 8, 5, 3, + 1, 2, 5, 6, 8, 6, 5, 1, 3, 5, 7, 9, 7, 6, 4, 5, 7, 8, 10, + 9, 6, 8, 8, 10, 11, 11, 9, 7, 14, 12, 11, 11, 10, 8, 7, 1, 2, 5, + 7, 5, 4, 2, 1, 1, 4, 6, 5, 3, 0, 2, 1, 3, 5, 4, 3, 2, 2, + 2, 4, 5, 5, 4, 4, 5, 6, 7, 8, 7, 6, 4, 11, 10, 10, 10, 8, 6, + 4, 17, 14, 12, 10, 8, 6, 4, 1, 1, 1, 2, 3, 3, 5, 2, 1, 0, 1, + 2, 2, 3, 3, 1, 2, 2, 2, 2, 4, 7, 2, 5, 5, 5, 5, 5, 11, 7, + 9, 9, 9, 8, 5, 15, 12, 13, 12, 11, 9, 5, 19, 17, 15, 14, 12, 10, 9, + 3, 5, 6, 6, 7, 6, 8, 8, 6, 7, 7, 8, 8, 7, 11, 7, 8, 9, 9, + 9, 8, 14, 9, 13, 13, 13, 13, 10, 15, 14, 17, 16, 17, 16, 13, 15, 20, 21, + 20, 19, 17, 16, 20, 26, 24, 22, 21, 19, 18, 14, 14, 14, 14, 15, 14, 8, 17, + 16, 15, 15, 16, 14, 7, 17, 17, 18, 18, 18, 17, 12, 16, 21, 22, 21, 22, 20, + 16, 19, 27, 27, 26, 26, 24, 18, 22, 30, 31, 30, 27, 25, 21, 27, 33, 35, 32, + 30, 27, 22, 24, 25, 24, 23, 20, 17, 12, 24, 27, 25, 24, 21, 17, 12, 23, 29, + 27, 27, 24, 20, 16, 24, 31, 31, 30, 27, 24, 20, 26, 33, 37, 35, 32, 27, 21, + 30, 36, 43, 39, 33, 29, 24, 33, 39, 43, 41, 36, 29, 25, 31, 35, 33, 27, 23, + 19, 15, 32, 36, 35, 28, 24, 20, 16, 32, 37, 38, 32, 27, 24, 20, 30, 37, 41, + 36, 31, 27, 23, 34, 39, 44, 41, 36, 30, 25, 37, 41, 47, 46, 39, 32, 28, 39, + 45, 48, 47, 41, 34, 29, 2, 2, 4, 8, 8, 6, 2, 2, 2, 3, 7, 8, 4, + 2, 2, 2, 3, 4, 5, 3, 2, 1, 2, 2, 2, 3, 2, 2, 2, 2, 3, 3, + 3, 3, 3, 6, 6, 6, 6, 4, 3, 2, 12, 10, 8, 6, 4, 3, 3, 2, 2, + 3, 5, 5, 2, 2, 1, 2, 3, 4, 4, 2, 2, 0, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 2, 1, 1, 3, 3, 3, 4, 4, 3, 3, 3, 8, 7, 8, 7, 4, + 3, 3, 15, 13, 10, 7, 5, 3, 3, 0, 2, 2, 2, 2, 2, 1, 2, 2, 2, + 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 4, 5, + 5, 4, 4, 5, 3, 4, 11, 10, 9, 8, 6, 4, 4, 17, 16, 12, 9, 7, 6, + 5, 2, 2, 2, 3, 3, 3, 7, 2, 3, 3, 4, 4, 4, 7, 4, 4, 4, 5, + 5, 5, 7, 7, 7, 7, 7, 8, 8, 8, 7, 11, 11, 11, 12, 11, 10, 11, 17, + 16, 15, 14, 12, 12, 18, 22, 19, 17, 16, 14, 13, 10, 10, 10, 10, 11, 10, 7, + 12, 12, 12, 11, 12, 11, 7, 12, 14, 13, 13, 13, 12, 8, 12, 17, 16, 17, 16, + 15, 12, 15, 21, 20, 20, 20, 19, 13, 18, 24, 26, 24, 24, 21, 15, 22, 28, 29, + 26, 25, 23, 17, 19, 21, 20, 20, 16, 12, 8, 19, 23, 22, 22, 18, 13, 9, 20, + 25, 24, 24, 20, 15, 11, 19, 25, 27, 27, 23, 19, 15, 21, 28, 31, 31, 28, 22, + 17, 25, 30, 36, 35, 30, 24, 18, 27, 33, 38, 36, 31, 27, 21, 27, 32, 31, 25, + 20, 16, 11, 27, 33, 34, 27, 22, 16, 12, 27, 32, 36, 29, 24, 19, 15, 27, 33, + 38, 32, 27, 23, 19, 28, 35, 40, 36, 32, 26, 21, 31, 36, 41, 40, 33, 28, 22, + 34, 37, 42, 41, 35, 31, 24, 1, 2, 3, 3, 3, 2, 2, 0, 2, 2, 3, 3, + 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 1, 1, 2, 2, 2, 4, 4, 3, 4, + 4, 4, 4, 4, 7, 7, 7, 7, 5, 4, 4, 13, 11, 9, 7, 6, 4, 4, 1, + 2, 2, 3, 2, 2, 1, 2, 1, 2, 2, 2, 1, 1, 2, 0, 2, 2, 2, 1, + 1, 2, 2, 2, 2, 2, 2, 4, 5, 4, 4, 5, 4, 4, 3, 9, 9, 8, 8, + 5, 4, 4, 17, 14, 10, 8, 6, 4, 3, 2, 0, 1, 1, 2, 2, 5, 2, 2, + 1, 1, 1, 2, 5, 2, 2, 1, 1, 1, 1, 6, 4, 2, 4, 4, 4, 4, 7, + 8, 6, 7, 8, 8, 7, 7, 13, 11, 12, 11, 9, 8, 7, 19, 17, 15, 13, 11, + 10, 9, 2, 5, 5, 6, 6, 5, 8, 5, 6, 6, 7, 7, 7, 9, 8, 7, 7, + 8, 8, 8, 9, 11, 9, 11, 11, 11, 11, 11, 11, 14, 15, 15, 15, 14, 13, 13, + 20, 20, 19, 18, 16, 15, 19, 26, 23, 20, 19, 17, 17, 12, 13, 13, 13, 14, 12, + 8, 14, 15, 15, 15, 15, 13, 8, 14, 17, 16, 16, 16, 15, 12, 14, 21, 20, 19, + 20, 19, 15, 18, 26, 24, 24, 25, 22, 17, 21, 29, 30, 29, 26, 23, 19, 26, 31, + 33, 30, 29, 26, 20, 22, 24, 22, 22, 19, 15, 11, 23, 26, 24, 23, 21, 16, 12, + 22, 28, 27, 26, 22, 19, 15, 22, 28, 31, 30, 26, 22, 19, 26, 32, 35, 35, 31, + 26, 21, 28, 34, 40, 39, 32, 28, 23, 32, 37, 42, 41, 36, 29, 25, 30, 36, 35, + 28, 22, 18, 14, 30, 36, 37, 29, 23, 19, 15, 30, 36, 39, 32, 27, 22, 19, 31, + 38, 42, 36, 31, 26, 23, 32, 39, 44, 42, 34, 30, 24, 34, 40, 47, 45, 38, 32, + 27, 37, 42, 48, 48, 41, 34, 27, 1, 1, 2, 2, 2, 2, 1, 2, 1, 2, 2, + 2, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 3, 4, 4, 5, + 4, 5, 5, 4, 4, 9, 8, 8, 7, 6, 4, 4, 15, 13, 10, 8, 6, 4, 4, + 2, 1, 1, 2, 1, 1, 3, 2, 1, 1, 2, 1, 1, 3, 2, 2, 0, 1, 2, + 1, 5, 2, 3, 2, 3, 3, 3, 5, 6, 6, 6, 6, 5, 4, 5, 11, 10, 10, + 9, 6, 5, 5, 18, 15, 12, 9, 8, 6, 5, 2, 2, 2, 2, 2, 5, 7, 2, + 2, 3, 3, 3, 5, 7, 5, 2, 4, 4, 5, 5, 8, 8, 3, 7, 7, 8, 8, + 9, 12, 7, 10, 11, 11, 10, 9, 15, 13, 15, 15, 13, 12, 9, 21, 19, 17, 16, + 15, 13, 12, 5, 7, 8, 9, 9, 8, 11, 9, 7, 9, 10, 10, 10, 11, 11, 8, + 11, 11, 12, 12, 12, 14, 10, 15, 15, 15, 15, 13, 15, 16, 18, 19, 19, 18, 17, + 16, 22, 23, 22, 21, 20, 19, 21, 28, 27, 25, 23, 22, 21, 15, 16, 16, 16, 17, + 16, 11, 17, 18, 18, 18, 18, 17, 11, 17, 19, 20, 21, 21, 19, 15, 17, 23, 24, + 23, 24, 22, 19, 20, 29, 28, 28, 28, 25, 21, 24, 33, 34, 33, 31, 27, 23, 29, + 35, 37, 33, 32, 30, 24, 26, 27, 26, 26, 23, 18, 14, 25, 30, 28, 27, 24, 20, + 15, 26, 31, 31, 31, 26, 23, 19, 25, 33, 34, 35, 31, 26, 22, 28, 35, 40, 38, + 36, 29, 24, 32, 39, 45, 43, 37, 32, 26, 36, 41, 46, 46, 40, 34, 28, 34, 41, + 38, 32, 26, 22, 17, 34, 41, 41, 34, 27, 22, 19, 34, 40, 43, 37, 31, 26, 22, + 34, 41, 47, 41, 35, 30, 26, 36, 43, 49, 44, 40, 33, 28, 39, 45, 52, 51, 43, + 35, 30, 42, 48, 52, 51, 45, 38, 32, 2, 1, 2, 4, 3, 3, 3, 2, 1, 2, + 3, 3, 2, 1, 2, 2, 1, 2, 2, 1, 3, 2, 2, 2, 2, 3, 3, 4, 5, + 5, 5, 5, 5, 4, 4, 9, 9, 8, 8, 6, 4, 4, 15, 13, 10, 8, 7, 4, + 4, 2, 2, 1, 3, 3, 4, 6, 2, 2, 1, 2, 2, 3, 5, 2, 2, 1, 0, + 0, 3, 6, 4, 3, 3, 3, 3, 4, 7, 8, 6, 6, 7, 6, 4, 7, 12, 10, + 10, 9, 8, 7, 7, 19, 16, 12, 10, 10, 9, 7, 2, 2, 4, 5, 6, 7, 9, + 4, 2, 4, 6, 6, 6, 8, 7, 2, 4, 6, 7, 6, 9, 11, 3, 7, 10, 10, + 10, 10, 14, 8, 11, 14, 14, 13, 10, 18, 13, 15, 17, 15, 15, 10, 21, 18, 18, + 18, 17, 16, 14, 7, 7, 10, 11, 12, 10, 14, 11, 8, 11, 12, 13, 13, 13, 14, + 8, 12, 13, 14, 14, 13, 17, 12, 16, 17, 18, 18, 15, 17, 17, 20, 21, 22, 21, + 19, 18, 23, 26, 24, 23, 22, 21, 21, 29, 28, 27, 25, 23, 24, 17, 18, 19, 19, + 20, 20, 14, 20, 19, 21, 21, 21, 20, 13, 19, 20, 22, 23, 23, 22, 17, 20, 25, + 26, 27, 27, 26, 21, 22, 31, 30, 31, 32, 29, 23, 25, 35, 36, 35, 33, 30, 25, + 30, 37, 40, 37, 36, 32, 26, 27, 30, 29, 29, 26, 22, 18, 27, 32, 31, 30, 27, + 23, 18, 28, 34, 34, 33, 30, 25, 21, 27, 36, 39, 38, 33, 29, 25, 30, 39, 42, + 41, 37, 32, 27, 34, 41, 47, 46, 40, 34, 29, 38, 42, 49, 50, 43, 35, 30, 36, + 44, 41, 34, 29, 25, 20, 38, 43, 43, 36, 30, 26, 21, 38, 44, 47, 40, 34, 29, + 25, 37, 44, 50, 44, 38, 33, 29, 39, 45, 52, 50, 42, 36, 30, 42, 49, 54, 54, + 46, 37, 33, 47, 51, 56, 55, 49, 41, 34, 2, 1, 3, 6, 6, 4, 3, 2, 1, + 2, 5, 6, 3, 1, 2, 2, 1, 3, 4, 2, 2, 2, 2, 2, 3, 4, 4, 4, + 4, 5, 5, 5, 7, 5, 4, 9, 8, 8, 8, 7, 5, 4, 14, 12, 10, 7, 8, + 5, 4, 2, 2, 1, 3, 3, 4, 5, 2, 2, 1, 2, 2, 3, 4, 2, 2, 1, + 0, 0, 2, 4, 4, 3, 3, 3, 3, 3, 5, 8, 6, 6, 6, 6, 3, 5, 12, + 10, 10, 9, 8, 7, 5, 18, 15, 11, 9, 9, 8, 5, 2, 2, 4, 5, 5, 6, + 8, 5, 2, 3, 6, 6, 6, 7, 8, 2, 4, 6, 7, 4, 7, 12, 3, 7, 10, + 10, 9, 9, 15, 8, 10, 13, 14, 13, 9, 18, 12, 14, 17, 16, 14, 9, 21, 18, + 16, 18, 17, 16, 14, 9, 6, 10, 11, 12, 10, 13, 12, 7, 10, 12, 13, 12, 12, + 15, 8, 12, 13, 14, 14, 12, 16, 11, 15, 17, 17, 17, 14, 18, 16, 19, 21, 22, + 21, 17, 18, 22, 24, 24, 24, 22, 21, 20, 27, 27, 26, 25, 24, 23, 17, 17, 19, + 19, 20, 19, 13, 20, 19, 20, 20, 21, 20, 12, 20, 20, 22, 23, 23, 22, 16, 20, + 23, 26, 26, 27, 25, 21, 22, 29, 31, 31, 30, 28, 23, 25, 34, 37, 35, 33, 29, + 25, 29, 37, 40, 37, 35, 32, 26, 27, 30, 29, 29, 26, 22, 17, 26, 32, 31, 30, + 27, 22, 18, 26, 34, 34, 33, 29, 25, 21, 27, 35, 39, 37, 33, 29, 25, 30, 39, + 44, 41, 37, 32, 26, 34, 41, 48, 46, 39, 33, 29, 37, 44, 48, 48, 43, 36, 30, + 37, 42, 40, 33, 29, 25, 21, 37, 42, 42, 36, 29, 25, 21, 37, 42, 45, 38, 34, + 29, 24, 37, 44, 49, 43, 36, 33, 28, 38, 46, 50, 48, 42, 35, 30, 42, 49, 53, + 52, 45, 38, 32, 45, 49, 55, 55, 47, 40, 34, 1, 3, 5, 7, 7, 5, 3, 1, + 1, 4, 6, 6, 4, 2, 2, 1, 3, 5, 5, 3, 2, 2, 1, 2, 4, 6, 5, + 4, 4, 4, 4, 6, 8, 6, 4, 8, 7, 7, 8, 8, 6, 4, 13, 11, 9, 8, + 8, 6, 4, 1, 1, 3, 5, 4, 3, 4, 1, 1, 2, 4, 4, 2, 3, 2, 1, + 1, 3, 2, 0, 3, 2, 2, 2, 3, 3, 2, 4, 6, 5, 5, 6, 5, 4, 4, + 11, 9, 9, 8, 6, 4, 3, 16, 13, 10, 8, 7, 6, 3, 2, 1, 3, 4, 4, + 6, 7, 2, 2, 4, 4, 5, 5, 6, 5, 2, 3, 4, 4, 3, 5, 10, 3, 6, + 7, 7, 7, 7, 13, 7, 9, 11, 11, 10, 7, 16, 12, 13, 14, 12, 12, 7, 19, + 17, 15, 15, 14, 13, 12, 5, 6, 9, 10, 11, 9, 11, 11, 7, 9, 11, 11, 11, + 10, 14, 7, 11, 11, 11, 11, 10, 16, 10, 14, 14, 15, 15, 11, 17, 15, 18, 19, + 19, 18, 14, 16, 20, 22, 22, 20, 20, 18, 18, 25, 25, 24, 23, 21, 20, 15, 16, + 17, 18, 18, 17, 11, 19, 17, 19, 19, 20, 18, 10, 19, 19, 20, 20, 20, 18, 14, + 19, 22, 23, 23, 24, 22, 18, 21, 28, 28, 28, 28, 25, 20, 23, 31, 34, 32, 30, + 27, 23, 26, 34, 36, 35, 32, 29, 24, 26, 28, 27, 27, 24, 19, 16, 25, 30, 28, + 28, 25, 21, 16, 25, 32, 30, 29, 25, 22, 18, 25, 33, 34, 34, 30, 26, 22, 28, + 35, 40, 38, 34, 29, 23, 31, 40, 45, 41, 36, 30, 26, 35, 40, 44, 45, 39, 33, + 27, 36, 40, 37, 31, 25, 23, 19, 35, 40, 40, 33, 28, 23, 19, 35, 40, 42, 35, + 30, 26, 22, 34, 41, 45, 39, 32, 30, 26, 37, 43, 48, 44, 37, 33, 28, 38, 44, + 50, 49, 41, 35, 29, 42, 47, 49, 50, 44, 37, 31, 3, 5, 7, 9, 9, 7, 5, + 2, 5, 7, 8, 9, 6, 4, 1, 4, 6, 7, 8, 5, 3, 1, 1, 4, 6, 8, + 6, 5, 3, 3, 5, 6, 9, 7, 4, 7, 6, 7, 8, 8, 7, 4, 10, 9, 8, + 8, 8, 7, 5, 1, 4, 6, 8, 7, 5, 4, 1, 3, 5, 7, 6, 4, 2, 1, + 1, 5, 6, 4, 3, 0, 2, 1, 3, 4, 3, 3, 2, 4, 4, 4, 6, 5, 4, + 2, 9, 8, 7, 8, 6, 4, 2, 14, 11, 8, 8, 6, 4, 2, 1, 1, 3, 3, + 4, 5, 6, 2, 1, 3, 3, 3, 4, 5, 2, 1, 2, 2, 2, 2, 3, 4, 2, + 4, 4, 3, 3, 4, 9, 6, 7, 7, 7, 6, 4, 12, 10, 10, 9, 9, 8, 4, + 16, 13, 12, 11, 10, 9, 8, 2, 6, 7, 8, 8, 8, 9, 5, 6, 8, 8, 9, + 9, 8, 9, 6, 8, 9, 9, 9, 7, 12, 8, 11, 11, 10, 11, 8, 13, 13, 15, + 14, 15, 14, 12, 12, 17, 18, 17, 17, 15, 14, 16, 22, 21, 19, 19, 17, 16, 13, + 14, 15, 15, 16, 15, 9, 15, 15, 16, 17, 17, 16, 8, 15, 17, 18, 17, 17, 15, + 12, 15, 20, 20, 20, 20, 18, 15, 17, 25, 24, 25, 24, 21, 16, 20, 27, 29, 27, + 26, 23, 18, 23, 29, 32, 29, 28, 25, 20, 23, 25, 24, 23, 21, 17, 14, 24, 27, + 26, 25, 23, 18, 13, 23, 29, 28, 26, 22, 18, 14, 23, 30, 31, 29, 26, 22, 18, + 26, 32, 36, 33, 29, 25, 20, 29, 35, 39, 37, 32, 26, 21, 31, 36, 40, 39, 33, + 28, 23, 31, 37, 34, 28, 23, 20, 17, 32, 36, 35, 29, 25, 20, 16, 32, 37, 39, + 31, 25, 22, 17, 32, 36, 40, 35, 29, 26, 21, 33, 38, 43, 39, 33, 28, 23, 36, + 40, 43, 44, 36, 30, 25, 38, 42, 45, 45, 39, 32, 26, 2, 3, 7, 11, 11, 10, + 6, 2, 2, 6, 10, 11, 9, 3, 2, 2, 4, 7, 9, 6, 2, 2, 2, 2, 4, + 6, 4, 2, 2, 2, 2, 3, 5, 4, 2, 6, 6, 6, 5, 4, 4, 2, 11, 11, + 8, 6, 4, 4, 2, 2, 2, 4, 8, 9, 5, 2, 1, 2, 3, 6, 8, 3, 2, + 1, 2, 2, 4, 4, 2, 2, 0, 2, 2, 2, 2, 1, 2, 3, 3, 3, 3, 3, + 2, 2, 8, 7, 8, 7, 4, 3, 2, 15, 13, 10, 7, 5, 3, 2, 1, 2, 2, + 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1, 2, 0, 2, + 1, 1, 1, 1, 1, 2, 5, 4, 4, 4, 4, 3, 2, 11, 10, 9, 8, 6, 3, + 2, 17, 16, 12, 9, 6, 5, 3, 1, 1, 1, 1, 1, 2, 6, 1, 2, 3, 3, + 3, 3, 6, 3, 3, 3, 4, 4, 4, 6, 6, 6, 6, 6, 7, 7, 8, 6, 10, + 10, 10, 10, 10, 9, 11, 15, 15, 14, 12, 11, 10, 17, 21, 18, 16, 15, 13, 12, + 9, 9, 9, 10, 10, 9, 6, 11, 11, 11, 11, 11, 10, 6, 11, 12, 12, 12, 13, + 11, 7, 11, 16, 15, 15, 15, 14, 10, 14, 20, 19, 19, 20, 18, 12, 17, 23, 25, + 23, 22, 20, 14, 21, 27, 28, 26, 24, 22, 16, 18, 19, 19, 20, 16, 12, 7, 18, + 22, 21, 21, 18, 13, 9, 18, 23, 23, 23, 19, 15, 10, 18, 24, 27, 25, 22, 18, + 14, 20, 27, 30, 27, 26, 21, 16, 23, 28, 34, 31, 28, 24, 18, 27, 31, 35, 34, + 30, 25, 20, 26, 32, 29, 24, 20, 15, 10, 26, 31, 32, 26, 21, 16, 11, 26, 32, + 33, 28, 23, 18, 14, 25, 31, 36, 29, 26, 22, 18, 26, 31, 37, 34, 29, 25, 20, + 30, 34, 38, 36, 30, 26, 22, 31, 36, 37, 37, 32, 29, 24, 2, 3, 4, 4, 4, + 4, 3, 2, 3, 4, 4, 4, 3, 3, 1, 2, 3, 4, 4, 3, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 6, 6, 6, 5, 3, 2, 2, 11, + 10, 7, 6, 4, 2, 2, 1, 3, 3, 4, 3, 3, 3, 1, 2, 3, 4, 3, 3, + 2, 1, 2, 3, 3, 3, 2, 1, 2, 0, 1, 2, 2, 1, 2, 3, 3, 3, 3, + 3, 2, 2, 8, 7, 7, 6, 4, 2, 2, 15, 12, 9, 7, 5, 3, 2, 1, 2, + 2, 3, 3, 3, 5, 2, 1, 2, 3, 3, 3, 5, 2, 1, 2, 2, 2, 2, 4, + 2, 1, 2, 2, 2, 2, 5, 6, 5, 5, 5, 5, 5, 5, 11, 10, 10, 9, 7, + 6, 5, 17, 15, 12, 10, 9, 7, 6, 2, 4, 5, 5, 6, 6, 9, 2, 5, 6, + 7, 7, 7, 8, 6, 6, 7, 7, 7, 8, 9, 9, 8, 9, 9, 9, 9, 9, 9, + 13, 13, 13, 13, 13, 11, 11, 18, 17, 16, 15, 14, 13, 17, 25, 20, 19, 17, 15, + 14, 12, 12, 13, 13, 14, 12, 9, 13, 14, 14, 14, 15, 13, 9, 13, 15, 16, 16, + 16, 14, 10, 13, 18, 18, 18, 18, 17, 13, 16, 23, 22, 22, 22, 20, 15, 20, 26, + 27, 26, 24, 22, 16, 24, 29, 31, 27, 26, 24, 17, 22, 23, 22, 22, 20, 15, 11, + 21, 25, 24, 24, 21, 16, 12, 21, 27, 26, 26, 21, 17, 13, 22, 27, 29, 27, 24, + 20, 16, 23, 29, 34, 32, 28, 23, 18, 26, 32, 39, 37, 32, 26, 20, 29, 35, 40, + 40, 34, 27, 22, 29, 36, 35, 28, 22, 18, 14, 29, 36, 38, 30, 24, 19, 15, 30, + 37, 39, 31, 25, 20, 17, 30, 34, 41, 34, 29, 24, 20, 29, 37, 42, 39, 34, 28, + 22, 32, 38, 44, 43, 37, 30, 24, 35, 41, 45, 46, 39, 32, 25, 2, 3, 4, 5, + 5, 5, 4, 2, 3, 4, 5, 5, 4, 3, 2, 2, 3, 4, 4, 2, 1, 2, 1, + 2, 2, 2, 1, 2, 3, 2, 2, 3, 3, 2, 2, 6, 6, 6, 5, 3, 2, 2, + 12, 10, 7, 5, 4, 2, 2, 2, 2, 3, 4, 4, 4, 5, 2, 2, 3, 4, 4, + 3, 4, 2, 2, 2, 3, 3, 2, 2, 2, 2, 0, 1, 2, 1, 3, 4, 3, 3, + 3, 3, 2, 4, 9, 8, 7, 6, 4, 2, 4, 16, 13, 9, 7, 5, 3, 3, 2, + 2, 3, 4, 5, 6, 8, 2, 2, 3, 4, 5, 5, 8, 2, 2, 3, 4, 4, 4, + 6, 5, 2, 4, 5, 5, 5, 7, 9, 5, 8, 8, 8, 7, 7, 12, 10, 12, 11, + 10, 9, 7, 17, 16, 15, 13, 11, 10, 9, 2, 6, 8, 9, 10, 9, 11, 5, 7, + 9, 10, 11, 11, 12, 9, 8, 10, 10, 10, 11, 11, 12, 9, 12, 12, 12, 13, 11, + 12, 14, 15, 15, 16, 16, 14, 13, 20, 21, 20, 18, 17, 16, 18, 26, 24, 22, 19, + 18, 17, 13, 15, 16, 17, 18, 17, 11, 15, 17, 17, 18, 19, 17, 11, 15, 18, 19, + 18, 19, 18, 13, 15, 22, 21, 20, 21, 20, 16, 17, 26, 26, 25, 25, 23, 17, 22, + 30, 31, 30, 27, 24, 19, 26, 33, 34, 32, 29, 26, 21, 25, 27, 26, 26, 23, 20, + 15, 24, 29, 28, 27, 24, 20, 16, 25, 31, 30, 30, 25, 20, 16, 24, 31, 32, 32, + 28, 23, 19, 26, 32, 36, 36, 32, 26, 21, 29, 35, 42, 41, 35, 28, 23, 33, 38, + 42, 42, 37, 30, 25, 33, 40, 37, 32, 27, 22, 18, 32, 39, 40, 33, 27, 22, 18, + 34, 40, 43, 35, 28, 23, 19, 33, 38, 44, 38, 32, 28, 23, 34, 40, 45, 43, 36, + 31, 25, 36, 43, 48, 47, 40, 33, 26, 38, 44, 49, 49, 42, 35, 28, 2, 3, 5, + 6, 6, 6, 4, 2, 3, 4, 6, 6, 4, 3, 2, 2, 3, 4, 4, 2, 1, 2, + 2, 1, 2, 2, 1, 2, 3, 2, 2, 3, 3, 2, 2, 7, 6, 6, 5, 4, 2, + 2, 12, 10, 8, 5, 4, 2, 2, 2, 3, 3, 5, 5, 6, 7, 2, 2, 3, 5, + 5, 4, 5, 2, 2, 3, 3, 3, 3, 4, 2, 2, 2, 0, 0, 2, 5, 5, 4, + 3, 4, 3, 3, 4, 9, 8, 7, 7, 5, 4, 5, 15, 13, 9, 8, 7, 5, 5, + 2, 2, 5, 6, 7, 8, 10, 2, 2, 5, 6, 7, 7, 9, 4, 2, 5, 6, 6, + 6, 8, 8, 2, 5, 7, 7, 7, 8, 11, 6, 8, 10, 11, 10, 8, 15, 11, 12, + 13, 12, 11, 8, 17, 15, 15, 16, 14, 13, 11, 4, 7, 11, 11, 12, 11, 14, 8, + 7, 11, 12, 13, 13, 14, 11, 8, 12, 13, 13, 13, 13, 14, 10, 14, 14, 15, 14, + 13, 14, 14, 17, 18, 18, 18, 16, 15, 20, 22, 21, 20, 19, 18, 17, 26, 25, 24, + 22, 21, 20, 15, 17, 18, 19, 20, 19, 14, 17, 19, 20, 21, 21, 20, 14, 17, 20, + 21, 22, 22, 20, 16, 17, 23, 24, 24, 23, 23, 19, 19, 27, 28, 28, 28, 26, 20, + 22, 31, 33, 32, 30, 27, 22, 27, 34, 37, 34, 32, 29, 23, 27, 29, 29, 28, 26, + 22, 18, 27, 32, 30, 30, 27, 22, 18, 27, 33, 33, 32, 28, 23, 18, 27, 33, 35, + 34, 30, 25, 21, 28, 36, 40, 38, 35, 29, 24, 31, 38, 45, 43, 36, 30, 26, 34, + 40, 45, 46, 39, 34, 27, 37, 42, 41, 35, 29, 25, 20, 36, 42, 43, 37, 30, 25, + 21, 36, 43, 45, 38, 31, 26, 22, 37, 42, 48, 41, 35, 30, 25, 37, 43, 49, 46, + 39, 33, 28, 38, 46, 51, 50, 42, 35, 30, 41, 47, 52, 53, 45, 38, 32, 2, 3, + 6, 9, 9, 7, 5, 2, 3, 5, 8, 9, 6, 3, 2, 2, 3, 6, 7, 4, 1, + 2, 1, 1, 3, 5, 3, 2, 3, 2, 2, 3, 5, 3, 2, 6, 6, 6, 5, 5, + 4, 2, 11, 9, 7, 5, 5, 3, 2, 2, 2, 3, 7, 6, 6, 7, 2, 2, 3, + 5, 6, 5, 5, 2, 2, 3, 3, 3, 3, 4, 2, 2, 2, 0, 0, 1, 4, 5, + 3, 3, 3, 3, 2, 4, 9, 7, 7, 6, 5, 4, 4, 14, 11, 8, 7, 6, 5, + 4, 1, 2, 5, 6, 7, 8, 9, 2, 2, 5, 6, 7, 7, 8, 5, 2, 4, 6, + 6, 5, 7, 8, 2, 5, 7, 7, 7, 7, 12, 5, 8, 10, 11, 10, 7, 15, 11, + 11, 13, 12, 11, 7, 16, 14, 13, 14, 14, 13, 11, 5, 6, 10, 11, 12, 11, 13, + 9, 7, 11, 12, 13, 13, 12, 11, 7, 11, 12, 13, 13, 11, 14, 9, 13, 14, 14, + 14, 12, 15, 14, 17, 19, 19, 18, 15, 14, 18, 21, 22, 21, 19, 18, 16, 23, 23, + 22, 22, 21, 20, 15, 16, 18, 19, 20, 19, 14, 18, 18, 20, 21, 21, 20, 13, 18, + 19, 21, 22, 21, 19, 15, 17, 22, 24, 24, 23, 22, 18, 19, 26, 28, 27, 28, 25, + 20, 21, 30, 32, 31, 30, 27, 22, 24, 34, 36, 34, 32, 29, 23, 26, 29, 29, 29, + 26, 22, 17, 26, 31, 31, 30, 27, 22, 17, 26, 33, 33, 32, 27, 22, 18, 26, 33, + 35, 34, 30, 25, 21, 28, 35, 39, 38, 35, 29, 24, 31, 37, 44, 42, 37, 31, 25, + 34, 38, 44, 45, 39, 34, 27, 36, 42, 41, 33, 29, 25, 20, 37, 43, 43, 36, 30, + 25, 21, 36, 42, 45, 38, 31, 26, 22, 36, 42, 46, 41, 34, 29, 25, 37, 43, 48, + 45, 39, 33, 27, 38, 46, 51, 50, 42, 35, 29, 40, 47, 51, 51, 43, 36, 31, 3, + 4, 6, 8, 8, 6, 4, 3, 3, 5, 7, 7, 5, 3, 2, 3, 4, 6, 6, 4, + 2, 1, 1, 2, 4, 5, 3, 2, 2, 2, 2, 4, 6, 4, 2, 6, 5, 5, 5, + 6, 4, 2, 9, 7, 5, 5, 6, 4, 2, 2, 3, 4, 6, 5, 6, 6, 2, 3, + 4, 5, 5, 4, 4, 1, 2, 3, 4, 3, 2, 3, 1, 1, 1, 2, 1, 0, 3, + 4, 3, 3, 3, 3, 2, 3, 8, 6, 5, 5, 3, 2, 2, 11, 8, 6, 5, 5, + 4, 3, 1, 2, 5, 5, 6, 8, 9, 2, 2, 5, 6, 6, 6, 7, 3, 1, 5, + 5, 5, 5, 6, 8, 1, 4, 5, 5, 5, 5, 11, 5, 7, 9, 9, 8, 5, 12, + 9, 9, 11, 10, 9, 5, 13, 11, 10, 12, 11, 11, 10, 3, 6, 10, 11, 11, 11, + 12, 8, 7, 11, 12, 12, 12, 11, 11, 7, 11, 12, 12, 12, 10, 14, 8, 12, 13, + 13, 13, 10, 15, 13, 15, 17, 17, 16, 13, 12, 16, 18, 19, 18, 18, 16, 13, 19, + 21, 20, 19, 19, 18, 14, 16, 18, 19, 20, 19, 13, 17, 18, 19, 20, 20, 19, 12, + 17, 18, 21, 20, 20, 19, 15, 17, 21, 22, 22, 23, 21, 17, 19, 26, 26, 26, 25, + 24, 18, 20, 28, 30, 29, 27, 25, 20, 21, 29, 32, 30, 29, 27, 21, 25, 28, 28, + 28, 24, 21, 17, 26, 30, 29, 29, 26, 21, 17, 26, 32, 31, 29, 26, 21, 18, 25, + 32, 34, 31, 27, 24, 20, 28, 33, 38, 35, 31, 27, 22, 29, 35, 41, 39, 33, 28, + 24, 30, 36, 42, 40, 36, 31, 26, 35, 40, 39, 32, 27, 23, 19, 35, 40, 41, 34, + 29, 24, 20, 36, 41, 43, 35, 29, 25, 20, 36, 39, 43, 38, 33, 28, 23, 35, 42, + 45, 42, 36, 30, 26, 38, 43, 47, 45, 39, 32, 27, 38, 43, 47, 47, 41, 33, 29, + 4, 7, 8, 11, 10, 9, 6, 4, 6, 8, 10, 10, 7, 5, 3, 5, 7, 8, 9, + 6, 3, 3, 3, 5, 7, 8, 5, 3, 1, 0, 3, 5, 7, 5, 3, 2, 2, 4, + 5, 7, 5, 3, 4, 3, 3, 4, 6, 5, 3, 4, 5, 7, 9, 8, 6, 7, 3, + 4, 6, 8, 7, 5, 4, 2, 3, 5, 7, 5, 3, 2, 2, 2, 3, 5, 4, 3, + 0, 1, 1, 2, 4, 3, 2, 0, 4, 3, 3, 4, 2, 2, 0, 7, 4, 3, 3, + 3, 1, 0, 3, 4, 4, 5, 7, 8, 8, 2, 3, 5, 6, 6, 6, 6, 2, 3, + 5, 4, 4, 4, 5, 3, 2, 3, 3, 2, 3, 3, 6, 2, 4, 4, 4, 4, 3, + 7, 4, 5, 5, 5, 5, 3, 8, 6, 6, 7, 6, 6, 6, 2, 7, 8, 8, 9, + 10, 11, 3, 7, 9, 9, 10, 10, 9, 8, 7, 9, 9, 10, 10, 8, 11, 7, 10, + 10, 10, 10, 7, 10, 9, 11, 11, 12, 11, 11, 7, 11, 13, 13, 13, 13, 12, 8, + 14, 15, 15, 14, 14, 14, 12, 15, 15, 16, 17, 16, 11, 14, 16, 17, 18, 17, 15, + 9, 14, 18, 18, 18, 18, 16, 12, 14, 20, 19, 18, 18, 17, 13, 14, 21, 22, 21, + 20, 18, 14, 14, 22, 24, 23, 22, 20, 15, 16, 22, 27, 25, 23, 21, 17, 24, 27, + 24, 24, 22, 18, 14, 24, 28, 27, 26, 23, 18, 14, 24, 29, 29, 26, 22, 19, 15, + 24, 30, 30, 27, 24, 20, 15, 23, 30, 32, 30, 25, 21, 17, 24, 30, 36, 33, 27, + 23, 19, 25, 30, 35, 34, 30, 25, 20, 32, 37, 34, 29, 24, 20, 17, 33, 37, 37, + 30, 26, 21, 16, 32, 38, 39, 32, 26, 22, 17, 32, 37, 40, 33, 27, 23, 19, 31, + 37, 40, 36, 30, 24, 20, 31, 37, 41, 38, 32, 27, 21, 33, 36, 42, 40, 34, 28, + 23, 5, 7, 10, 14, 14, 11, 8, 5, 6, 9, 13, 14, 11, 8, 4, 6, 8, 11, + 13, 10, 6, 4, 4, 5, 8, 11, 8, 2, 2, 2, 2, 4, 6, 6, 2, 3, 3, + 3, 3, 5, 6, 2, 9, 8, 5, 3, 4, 6, 2, 4, 6, 8, 11, 11, 8, 6, + 4, 5, 7, 9, 10, 7, 5, 3, 5, 6, 8, 8, 6, 4, 3, 3, 4, 5, 5, + 4, 1, 0, 2, 2, 2, 2, 2, 1, 5, 5, 5, 4, 2, 2, 1, 12, 10, 7, + 5, 2, 2, 1, 4, 5, 5, 6, 7, 6, 5, 3, 4, 5, 5, 5, 5, 5, 2, + 4, 4, 4, 4, 4, 4, 2, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 2, 1, + 1, 8, 7, 7, 5, 3, 1, 1, 14, 14, 9, 6, 4, 1, 1, 2, 4, 4, 5, + 5, 6, 6, 2, 3, 5, 5, 5, 5, 6, 2, 3, 4, 5, 5, 5, 6, 3, 4, + 4, 4, 5, 5, 6, 3, 7, 7, 7, 7, 7, 6, 8, 13, 12, 11, 9, 8, 8, + 14, 18, 15, 13, 11, 10, 9, 9, 9, 10, 10, 11, 9, 6, 10, 11, 11, 11, 12, + 10, 6, 10, 12, 12, 12, 13, 12, 7, 10, 14, 13, 13, 14, 12, 8, 11, 17, 17, + 16, 16, 15, 9, 14, 19, 21, 20, 19, 16, 11, 18, 22, 24, 21, 20, 19, 13, 17, + 20, 20, 20, 17, 12, 8, 18, 22, 21, 21, 18, 13, 9, 17, 23, 23, 22, 19, 15, + 10, 18, 22, 24, 23, 20, 16, 11, 17, 23, 26, 24, 22, 19, 13, 19, 25, 28, 27, + 23, 20, 15, 22, 26, 29, 27, 24, 21, 17, 25, 30, 28, 25, 20, 15, 11, 26, 30, + 31, 26, 22, 16, 12, 26, 31, 33, 27, 22, 18, 13, 26, 30, 33, 27, 23, 19, 15, + 24, 29, 32, 29, 24, 21, 17, 25, 28, 32, 31, 26, 22, 19, 27, 30, 32, 32, 28, + 23, 20, 5, 6, 7, 8, 8, 7, 7, 5, 6, 7, 8, 8, 7, 6, 4, 5, 6, + 7, 7, 5, 4, 3, 4, 5, 5, 5, 3, 2, 1, 2, 2, 2, 3, 2, 1, 3, + 3, 3, 2, 3, 2, 1, 9, 7, 5, 3, 2, 2, 2, 4, 5, 7, 7, 7, 7, + 7, 4, 5, 6, 7, 7, 6, 5, 3, 4, 6, 6, 6, 5, 4, 3, 3, 3, 4, + 3, 3, 1, 2, 0, 2, 2, 2, 1, 1, 5, 4, 4, 3, 1, 2, 1, 12, 9, + 6, 4, 2, 1, 1, 3, 5, 5, 6, 7, 7, 8, 3, 4, 5, 6, 6, 6, 7, + 2, 3, 4, 5, 5, 5, 5, 3, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, + 2, 3, 8, 7, 6, 5, 4, 3, 3, 14, 12, 9, 7, 5, 4, 4, 3, 5, 6, + 7, 8, 9, 10, 2, 5, 6, 7, 8, 8, 9, 3, 6, 6, 6, 7, 7, 8, 6, + 6, 7, 7, 7, 8, 8, 6, 10, 9, 10, 10, 9, 9, 8, 15, 14, 13, 12, 10, + 10, 14, 21, 18, 15, 13, 12, 11, 11, 12, 12, 13, 14, 13, 10, 12, 14, 14, 14, + 15, 14, 9, 12, 15, 15, 15, 15, 14, 9, 13, 17, 16, 15, 16, 15, 11, 13, 20, + 19, 19, 19, 17, 12, 17, 22, 24, 23, 20, 18, 13, 21, 26, 28, 25, 23, 21, 15, + 21, 22, 21, 23, 20, 16, 11, 21, 24, 24, 24, 21, 16, 12, 21, 26, 27, 25, 22, + 17, 12, 21, 26, 27, 26, 22, 17, 13, 20, 26, 29, 29, 25, 20, 15, 22, 28, 35, + 34, 28, 22, 17, 25, 33, 36, 36, 31, 25, 18, 29, 36, 35, 28, 22, 19, 14, 29, + 35, 37, 29, 24, 19, 15, 30, 36, 39, 30, 25, 20, 15, 29, 35, 39, 32, 26, 21, + 17, 28, 34, 38, 36, 31, 24, 19, 29, 35, 41, 40, 32, 27, 21, 32, 37, 43, 41, + 35, 28, 23, 5, 7, 8, 9, 9, 9, 8, 5, 6, 7, 9, 9, 7, 6, 4, 5, + 7, 7, 7, 5, 4, 4, 4, 4, 5, 5, 3, 1, 2, 1, 2, 2, 2, 2, 1, + 3, 3, 3, 2, 2, 2, 1, 8, 7, 4, 2, 2, 2, 1, 4, 5, 7, 8, 8, + 8, 8, 4, 5, 7, 8, 8, 7, 7, 4, 5, 6, 6, 6, 5, 4, 3, 3, 3, + 4, 3, 3, 2, 2, 2, 0, 1, 1, 1, 2, 5, 4, 4, 3, 1, 1, 2, 12, + 9, 6, 3, 2, 1, 2, 4, 5, 6, 7, 8, 10, 10, 3, 4, 6, 7, 8, 8, + 9, 3, 4, 6, 6, 6, 6, 7, 3, 3, 4, 4, 4, 5, 6, 5, 2, 4, 5, + 5, 4, 5, 9, 7, 9, 8, 6, 5, 6, 14, 12, 11, 9, 8, 7, 7, 3, 7, + 8, 9, 10, 12, 12, 3, 7, 9, 10, 10, 10, 11, 7, 8, 9, 10, 10, 10, 11, + 10, 7, 10, 10, 10, 10, 10, 9, 11, 12, 12, 12, 12, 11, 9, 16, 17, 15, 14, + 13, 13, 14, 22, 20, 18, 16, 15, 14, 13, 15, 15, 16, 17, 16, 12, 14, 16, 17, + 17, 18, 16, 11, 14, 18, 19, 18, 17, 17, 13, 14, 19, 19, 19, 19, 17, 13, 14, + 23, 21, 21, 20, 19, 14, 18, 25, 27, 25, 23, 21, 16, 23, 28, 31, 28, 25, 23, + 18, 24, 25, 26, 26, 22, 18, 14, 23, 29, 26, 28, 24, 19, 15, 24, 29, 30, 28, + 24, 20, 15, 24, 29, 30, 30, 26, 20, 16, 23, 29, 33, 32, 28, 23, 17, 26, 31, + 38, 37, 30, 24, 19, 28, 34, 39, 38, 33, 26, 21, 33, 39, 38, 31, 26, 20, 17, + 33, 39, 41, 32, 27, 22, 17, 33, 40, 42, 34, 27, 23, 18, 33, 38, 43, 36, 29, + 24, 19, 31, 37, 42, 39, 33, 28, 21, 32, 37, 44, 44, 35, 29, 23, 34, 41, 45, + 45, 38, 32, 25, 5, 6, 9, 10, 10, 9, 8, 5, 6, 8, 9, 9, 8, 6, 4, + 5, 7, 8, 7, 6, 4, 4, 4, 4, 5, 6, 4, 2, 2, 2, 2, 2, 3, 2, + 1, 3, 3, 3, 2, 2, 2, 1, 8, 7, 4, 2, 2, 2, 1, 4, 6, 7, 9, + 9, 9, 10, 4, 5, 6, 8, 9, 8, 8, 4, 5, 6, 6, 6, 6, 6, 3, 3, + 3, 4, 3, 3, 3, 2, 2, 2, 0, 0, 1, 4, 6, 5, 4, 3, 2, 2, 4, + 11, 8, 6, 4, 3, 2, 4, 4, 5, 7, 9, 10, 11, 12, 3, 4, 8, 9, 9, + 10, 10, 3, 4, 7, 8, 8, 8, 8, 6, 3, 5, 6, 6, 6, 7, 8, 3, 5, + 7, 7, 6, 7, 11, 7, 9, 10, 8, 8, 7, 13, 11, 11, 12, 10, 9, 9, 3, + 8, 10, 11, 12, 13, 14, 6, 8, 11, 12, 13, 13, 13, 9, 8, 11, 12, 13, 12, + 13, 12, 8, 12, 12, 13, 13, 11, 11, 11, 14, 14, 15, 14, 14, 11, 16, 18, 18, + 16, 16, 16, 13, 20, 21, 20, 18, 17, 17, 13, 17, 18, 19, 19, 19, 15, 16, 18, + 19, 20, 21, 19, 13, 15, 19, 21, 21, 21, 19, 15, 16, 21, 22, 21, 22, 20, 15, + 15, 24, 25, 24, 24, 22, 17, 19, 27, 29, 28, 26, 23, 18, 22, 28, 32, 30, 29, + 25, 20, 26, 29, 28, 28, 26, 22, 17, 27, 31, 31, 30, 26, 22, 17, 26, 34, 33, + 32, 27, 22, 18, 26, 33, 34, 32, 27, 23, 18, 25, 32, 36, 35, 31, 25, 20, 27, + 35, 40, 39, 33, 28, 22, 30, 36, 41, 42, 35, 30, 24, 37, 42, 40, 34, 28, 24, + 20, 36, 43, 43, 35, 30, 23, 20, 36, 42, 45, 37, 31, 24, 20, 36, 41, 46, 39, + 32, 26, 22, 35, 40, 45, 42, 34, 30, 24, 35, 42, 47, 46, 38, 32, 25, 38, 43, + 48, 48, 41, 34, 27, 5, 6, 9, 12, 13, 10, 8, 5, 6, 8, 12, 12, 9, 6, + 4, 5, 7, 9, 10, 7, 3, 4, 4, 4, 6, 8, 5, 2, 2, 1, 1, 3, 6, + 4, 1, 3, 2, 2, 2, 4, 4, 1, 5, 3, 2, 2, 3, 4, 1, 4, 5, 7, + 10, 10, 9, 9, 4, 5, 6, 9, 9, 7, 7, 3, 4, 5, 7, 6, 5, 5, 3, + 3, 3, 3, 3, 3, 3, 2, 2, 1, 0, 0, 1, 3, 4, 3, 2, 2, 2, 1, + 3, 7, 4, 3, 2, 3, 2, 3, 4, 5, 7, 8, 10, 11, 11, 3, 4, 7, 9, + 9, 9, 9, 3, 4, 7, 7, 7, 7, 8, 7, 2, 4, 6, 6, 6, 6, 9, 2, + 5, 7, 7, 7, 6, 9, 4, 6, 9, 9, 8, 6, 9, 7, 7, 10, 9, 9, 9, + 3, 7, 11, 11, 12, 13, 14, 8, 7, 11, 12, 13, 13, 13, 11, 8, 12, 12, 13, + 12, 12, 12, 7, 12, 13, 13, 13, 11, 12, 10, 14, 14, 15, 15, 14, 10, 12, 15, + 16, 16, 16, 15, 9, 15, 18, 18, 17, 17, 17, 14, 17, 18, 19, 20, 20, 14, 16, + 18, 20, 20, 21, 19, 13, 16, 19, 21, 21, 21, 19, 15, 16, 21, 21, 22, 22, 20, + 16, 15, 24, 24, 24, 24, 22, 17, 16, 24, 28, 27, 26, 23, 18, 18, 27, 30, 28, + 27, 25, 20, 27, 30, 28, 28, 25, 22, 18, 26, 31, 30, 31, 27, 22, 17, 26, 34, + 33, 31, 26, 22, 18, 26, 32, 34, 32, 28, 23, 18, 25, 32, 37, 35, 31, 26, 20, + 26, 33, 39, 38, 32, 28, 22, 27, 34, 40, 40, 35, 29, 24, 37, 43, 40, 34, 30, + 24, 21, 37, 42, 43, 36, 30, 25, 20, 37, 42, 45, 36, 30, 26, 21, 36, 41, 46, + 38, 31, 27, 22, 35, 41, 44, 40, 34, 28, 24, 36, 42, 46, 45, 38, 31, 26, 35, + 41, 46, 45, 40, 33, 28, 4, 5, 6, 8, 8, 7, 6, 4, 4, 5, 8, 8, 5, + 4, 3, 4, 5, 6, 6, 4, 2, 3, 3, 3, 4, 6, 3, 1, 2, 1, 0, 2, + 5, 3, 1, 2, 2, 2, 3, 4, 3, 1, 4, 3, 2, 3, 3, 3, 1, 4, 4, + 5, 6, 6, 7, 8, 3, 4, 5, 6, 6, 6, 6, 3, 4, 4, 4, 3, 4, 4, + 2, 2, 2, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 2, 3, 2, 2, 2, 1, + 1, 2, 7, 4, 2, 2, 3, 2, 2, 3, 4, 6, 7, 8, 9, 10, 2, 3, 6, + 7, 7, 8, 9, 3, 3, 6, 6, 6, 6, 7, 7, 2, 4, 6, 6, 5, 5, 9, + 2, 4, 6, 7, 7, 5, 10, 4, 5, 7, 8, 8, 5, 9, 7, 6, 8, 9, 9, + 9, 3, 7, 10, 11, 12, 12, 13, 8, 7, 11, 12, 13, 12, 12, 12, 8, 12, 12, + 12, 12, 11, 14, 7, 11, 13, 13, 13, 10, 14, 10, 12, 14, 14, 14, 13, 11, 12, + 14, 15, 16, 16, 15, 9, 15, 16, 17, 17, 17, 17, 14, 17, 19, 19, 20, 19, 13, + 17, 18, 19, 20, 20, 19, 12, 17, 19, 20, 21, 20, 19, 15, 17, 21, 21, 21, 22, + 20, 15, 16, 22, 24, 24, 23, 22, 17, 15, 23, 26, 26, 24, 22, 18, 16, 24, 28, + 27, 26, 24, 20, 26, 29, 28, 28, 25, 21, 17, 26, 31, 30, 30, 26, 22, 17, 26, + 33, 32, 31, 26, 22, 17, 26, 32, 33, 32, 27, 23, 18, 25, 32, 35, 33, 30, 25, + 20, 26, 33, 38, 36, 30, 26, 21, 26, 33, 38, 39, 33, 27, 23, 36, 41, 38, 32, + 27, 24, 20, 35, 41, 42, 34, 29, 25, 20, 35, 41, 44, 36, 30, 25, 20, 35, 40, + 45, 37, 31, 26, 22, 35, 40, 44, 40, 33, 27, 23, 34, 40, 44, 43, 36, 30, 25, + 35, 40, 45, 45, 37, 31, 25, 4, 6, 9, 11, 10, 9, 6, 4, 6, 8, 10, 10, + 7, 4, 3, 5, 7, 8, 9, 6, 4, 3, 3, 5, 7, 8, 5, 3, 1, 0, 3, + 5, 7, 5, 3, 2, 2, 4, 5, 7, 5, 3, 4, 3, 3, 4, 6, 5, 3, 4, + 5, 7, 9, 8, 7, 6, 3, 4, 6, 8, 7, 5, 4, 3, 4, 5, 6, 5, 3, + 2, 2, 2, 4, 5, 4, 3, 0, 1, 1, 2, 3, 3, 2, 0, 3, 2, 3, 4, + 2, 2, 0, 6, 4, 3, 3, 2, 1, 0, 3, 4, 4, 5, 7, 8, 8, 2, 3, + 5, 6, 6, 6, 6, 2, 3, 5, 4, 4, 4, 5, 3, 2, 3, 3, 3, 3, 3, + 6, 2, 4, 4, 4, 4, 3, 7, 4, 5, 5, 5, 5, 3, 9, 7, 6, 6, 6, + 6, 6, 2, 7, 8, 9, 9, 10, 11, 3, 7, 9, 9, 10, 10, 9, 8, 7, 9, + 9, 10, 9, 8, 11, 7, 10, 10, 9, 10, 7, 10, 9, 11, 11, 12, 11, 10, 8, + 11, 13, 13, 13, 13, 12, 8, 14, 15, 15, 14, 14, 13, 13, 15, 16, 16, 16, 16, + 11, 14, 17, 17, 17, 18, 16, 10, 14, 18, 18, 18, 18, 16, 12, 14, 20, 19, 18, + 18, 17, 13, 14, 21, 21, 20, 20, 18, 14, 15, 22, 24, 23, 21, 19, 15, 16, 23, + 26, 24, 24, 20, 17, 24, 25, 24, 24, 21, 18, 14, 24, 28, 27, 25, 22, 18, 14, + 24, 30, 29, 27, 22, 19, 15, 23, 29, 30, 27, 23, 20, 15, 23, 29, 32, 30, 26, + 22, 17, 24, 30, 36, 33, 28, 23, 18, 25, 30, 35, 35, 29, 25, 20, 32, 37, 34, + 29, 23, 20, 17, 32, 37, 36, 30, 25, 21, 17, 33, 37, 39, 31, 26, 22, 17, 32, + 37, 40, 33, 27, 23, 18, 31, 38, 39, 36, 29, 25, 20, 31, 36, 40, 39, 32, 26, + 20, 32, 36, 41, 40, 34, 28, 23, 10, 12, 14, 17, 18, 16, 13, 10, 11, 13, 17, + 17, 14, 12, 9, 11, 12, 14, 15, 12, 10, 9, 9, 10, 11, 14, 9, 4, 6, 7, + 7, 8, 8, 7, 4, 2, 2, 3, 3, 6, 7, 4, 5, 4, 2, 3, 5, 8, 4, + 9, 11, 12, 15, 15, 14, 12, 9, 10, 12, 14, 14, 12, 11, 8, 10, 11, 12, 12, + 11, 9, 8, 8, 9, 9, 9, 8, 3, 5, 5, 5, 5, 4, 4, 3, 0, 2, 2, + 2, 3, 3, 3, 8, 6, 3, 2, 2, 3, 3, 8, 10, 11, 11, 13, 13, 12, 8, + 9, 11, 11, 12, 12, 11, 7, 8, 10, 10, 10, 10, 9, 7, 7, 7, 7, 8, 7, + 4, 3, 3, 4, 4, 3, 3, 3, 3, 2, 2, 1, 2, 2, 3, 9, 9, 5, 2, + 1, 3, 3, 7, 9, 10, 11, 12, 13, 13, 7, 8, 10, 11, 12, 12, 12, 6, 8, + 9, 10, 10, 10, 10, 4, 7, 7, 7, 7, 7, 5, 2, 3, 4, 4, 4, 4, 5, + 3, 8, 7, 7, 6, 6, 6, 9, 13, 11, 9, 7, 7, 8, 7, 8, 9, 11, 12, + 13, 13, 8, 9, 9, 10, 11, 11, 12, 8, 10, 11, 11, 11, 9, 9, 9, 12, 12, + 11, 12, 11, 6, 8, 13, 13, 14, 14, 13, 8, 9, 15, 16, 15, 15, 15, 10, 13, + 17, 18, 16, 16, 16, 12, 16, 18, 19, 19, 15, 12, 13, 16, 20, 20, 20, 16, 12, + 11, 16, 22, 22, 21, 18, 12, 9, 16, 21, 21, 21, 19, 14, 10, 15, 21, 22, 21, + 18, 16, 12, 16, 20, 22, 21, 19, 16, 13, 17, 21, 23, 22, 20, 17, 15, 24, 28, + 27, 23, 18, 14, 12, 24, 28, 28, 24, 20, 15, 10, 24, 28, 30, 23, 21, 16, 11, + 24, 27, 29, 25, 20, 18, 13, 22, 26, 28, 25, 20, 18, 15, 22, 25, 27, 26, 20, + 18, 16, 22, 24, 27, 28, 22, 19, 16, 9, 11, 12, 13, 13, 13, 12, 9, 10, 12, + 13, 13, 11, 10, 8, 10, 11, 11, 11, 10, 8, 8, 8, 9, 9, 9, 6, 3, 5, + 6, 6, 6, 4, 3, 2, 2, 2, 2, 2, 3, 3, 3, 4, 3, 2, 2, 3, 3, + 3, 8, 10, 11, 12, 13, 13, 12, 8, 9, 10, 12, 12, 11, 10, 7, 9, 10, 10, + 10, 9, 7, 7, 7, 7, 8, 7, 6, 2, 5, 4, 4, 5, 3, 2, 2, 2, 0, + 1, 2, 2, 2, 2, 7, 5, 2, 2, 2, 2, 2, 8, 9, 10, 11, 12, 13, 13, + 7, 8, 10, 11, 11, 11, 11, 7, 8, 9, 9, 9, 9, 8, 7, 7, 6, 6, 7, + 6, 4, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 2, 2, 3, 3, 9, 8, 5, + 3, 3, 3, 4, 7, 9, 10, 11, 13, 14, 14, 7, 9, 10, 11, 12, 12, 12, 5, + 9, 10, 10, 10, 10, 9, 6, 8, 7, 7, 8, 7, 7, 4, 6, 7, 7, 7, 7, + 8, 3, 10, 10, 9, 9, 9, 9, 9, 16, 13, 11, 10, 10, 11, 10, 11, 11, 12, + 13, 14, 14, 10, 12, 13, 13, 14, 12, 12, 11, 14, 14, 14, 14, 12, 9, 11, 15, + 15, 15, 15, 13, 9, 10, 17, 16, 16, 17, 15, 11, 12, 18, 20, 18, 18, 16, 12, + 16, 21, 23, 20, 20, 18, 14, 19, 21, 21, 21, 18, 15, 14, 20, 23, 23, 23, 19, + 15, 12, 19, 25, 25, 24, 20, 15, 11, 19, 25, 26, 25, 21, 17, 12, 18, 23, 29, + 27, 23, 18, 14, 19, 25, 31, 30, 25, 20, 15, 21, 27, 32, 32, 27, 22, 17, 29, + 34, 33, 27, 21, 17, 14, 28, 34, 36, 29, 23, 18, 13, 28, 34, 39, 30, 24, 19, + 14, 28, 34, 38, 30, 25, 20, 15, 27, 33, 39, 35, 28, 22, 17, 26, 32, 37, 37, + 29, 24, 18, 27, 33, 36, 37, 32, 26, 20, 9, 11, 12, 13, 13, 13, 12, 9, 10, + 11, 13, 13, 11, 10, 8, 9, 11, 11, 10, 9, 7, 8, 8, 8, 9, 8, 6, 2, + 6, 5, 5, 5, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, 2, 2, + 2, 2, 8, 10, 11, 12, 13, 13, 13, 8, 9, 10, 12, 12, 11, 10, 8, 8, 10, + 10, 9, 9, 7, 8, 7, 7, 7, 7, 5, 3, 5, 4, 4, 4, 2, 2, 2, 2, + 1, 0, 2, 2, 2, 2, 6, 4, 2, 1, 2, 2, 3, 8, 9, 10, 11, 13, 14, + 15, 8, 8, 10, 12, 12, 12, 12, 7, 8, 10, 10, 10, 10, 9, 6, 7, 8, 8, + 8, 6, 5, 4, 3, 5, 5, 4, 4, 5, 5, 3, 5, 4, 4, 4, 5, 7, 6, + 7, 6, 5, 5, 5, 8, 11, 12, 13, 14, 16, 15, 6, 10, 12, 13, 14, 14, 13, + 6, 10, 12, 11, 11, 11, 10, 9, 9, 9, 9, 9, 9, 9, 7, 7, 9, 10, 10, + 10, 11, 5, 12, 12, 12, 12, 12, 12, 7, 15, 15, 14, 13, 13, 13, 11, 14, 15, + 15, 16, 16, 16, 13, 15, 16, 16, 16, 15, 13, 12, 16, 17, 17, 17, 15, 12, 13, + 18, 18, 18, 18, 17, 13, 12, 19, 19, 19, 19, 18, 13, 13, 22, 23, 22, 20, 19, + 15, 17, 22, 26, 24, 22, 21, 16, 22, 24, 25, 24, 22, 18, 16, 22, 26, 26, 27, + 23, 18, 13, 22, 29, 28, 27, 23, 18, 14, 22, 27, 28, 28, 24, 19, 15, 22, 28, + 31, 31, 26, 21, 16, 22, 28, 34, 32, 27, 22, 18, 24, 29, 35, 36, 30, 24, 20, + 32, 38, 37, 29, 24, 21, 16, 31, 38, 38, 32, 26, 21, 16, 31, 37, 41, 32, 27, + 21, 17, 31, 37, 42, 34, 28, 23, 18, 30, 35, 42, 38, 30, 24, 19, 29, 35, 41, + 40, 33, 26, 21, 30, 36, 40, 41, 34, 28, 22, 8, 9, 11, 12, 13, 12, 11, 8, + 9, 11, 12, 12, 11, 9, 7, 8, 10, 10, 10, 8, 6, 7, 7, 7, 8, 8, 5, + 2, 5, 4, 4, 5, 3, 2, 2, 2, 2, 1, 2, 2, 2, 2, 3, 2, 1, 1, + 2, 2, 2, 8, 8, 10, 12, 12, 12, 13, 7, 8, 9, 11, 12, 10, 10, 7, 8, + 9, 10, 9, 8, 8, 6, 6, 6, 7, 6, 5, 4, 4, 3, 3, 3, 2, 2, 4, + 2, 2, 2, 0, 1, 2, 4, 5, 3, 2, 1, 2, 3, 4, 7, 8, 10, 11, 13, + 14, 15, 6, 7, 10, 12, 12, 13, 12, 6, 7, 10, 10, 10, 10, 10, 5, 6, 7, + 8, 8, 7, 6, 6, 2, 4, 5, 5, 6, 6, 7, 2, 5, 6, 6, 7, 6, 6, + 5, 6, 8, 7, 8, 8, 6, 10, 12, 13, 14, 16, 15, 5, 10, 12, 13, 14, 14, + 13, 8, 10, 12, 12, 12, 12, 11, 11, 8, 11, 11, 11, 12, 11, 10, 8, 12, 12, + 12, 13, 13, 8, 11, 14, 14, 14, 14, 14, 6, 14, 15, 16, 15, 15, 16, 13, 16, + 17, 18, 19, 18, 15, 15, 18, 19, 19, 19, 18, 13, 15, 18, 20, 19, 20, 18, 14, + 14, 20, 21, 20, 21, 20, 15, 14, 21, 22, 22, 22, 20, 16, 14, 23, 25, 24, 24, + 22, 17, 16, 23, 27, 26, 25, 23, 19, 25, 27, 27, 27, 24, 21, 17, 25, 31, 29, + 30, 25, 20, 16, 25, 31, 31, 30, 26, 21, 16, 25, 31, 32, 31, 27, 22, 18, 23, + 31, 34, 33, 29, 24, 18, 24, 31, 36, 34, 31, 25, 20, 26, 32, 37, 38, 33, 27, + 22, 35, 40, 40, 33, 27, 23, 19, 35, 41, 42, 34, 29, 24, 19, 35, 40, 44, 36, + 30, 25, 19, 35, 41, 45, 37, 31, 26, 20, 33, 39, 44, 40, 33, 27, 23, 33, 39, + 45, 42, 35, 30, 23, 33, 39, 44, 44, 38, 30, 25, 6, 8, 11, 14, 14, 12, 9, + 6, 7, 10, 13, 13, 11, 7, 5, 6, 9, 11, 12, 9, 5, 5, 5, 6, 8, 10, + 7, 2, 2, 2, 2, 5, 7, 5, 2, 2, 1, 1, 2, 5, 5, 2, 3, 2, 2, + 2, 4, 5, 2, 5, 6, 8, 11, 11, 10, 10, 5, 6, 7, 10, 11, 8, 8, 4, + 5, 6, 8, 8, 6, 6, 4, 4, 4, 5, 5, 3, 2, 2, 1, 1, 2, 2, 1, + 2, 3, 2, 2, 1, 0, 1, 2, 6, 3, 2, 2, 1, 1, 2, 5, 6, 8, 9, + 10, 11, 12, 4, 5, 8, 9, 10, 10, 9, 3, 5, 8, 8, 8, 8, 7, 5, 3, + 5, 5, 5, 5, 5, 8, 2, 4, 5, 6, 6, 5, 9, 3, 5, 7, 7, 7, 5, + 8, 6, 6, 8, 8, 8, 8, 3, 8, 10, 10, 11, 13, 14, 6, 8, 10, 11, 12, + 12, 13, 10, 8, 11, 12, 12, 12, 11, 12, 7, 11, 12, 11, 12, 10, 12, 8, 12, + 13, 13, 13, 13, 9, 11, 13, 14, 14, 14, 15, 8, 14, 16, 16, 15, 15, 16, 13, + 16, 17, 18, 20, 18, 14, 15, 17, 19, 19, 20, 19, 12, 15, 19, 20, 20, 20, 19, + 14, 15, 20, 20, 21, 21, 19, 14, 14, 21, 22, 22, 22, 20, 16, 14, 23, 25, 24, + 23, 22, 17, 16, 24, 28, 26, 27, 24, 19, 26, 29, 27, 28, 24, 21, 16, 25, 30, + 29, 29, 26, 21, 17, 25, 33, 33, 31, 26, 22, 17, 25, 32, 33, 31, 27, 23, 17, + 25, 31, 35, 33, 28, 24, 18, 25, 32, 36, 36, 30, 24, 20, 26, 32, 38, 39, 33, + 27, 22, 35, 41, 39, 33, 28, 23, 19, 36, 41, 42, 35, 29, 24, 19, 36, 40, 45, + 36, 30, 24, 20, 35, 40, 45, 37, 31, 25, 21, 34, 40, 44, 40, 33, 27, 22, 34, + 39, 43, 43, 35, 29, 23, 35, 39, 44, 44, 38, 31, 25, 4, 6, 10, 12, 13, 11, + 8, 4, 5, 9, 12, 12, 9, 6, 4, 5, 7, 10, 10, 8, 4, 3, 3, 4, 7, + 9, 6, 2, 1, 1, 1, 4, 6, 4, 2, 2, 2, 2, 3, 5, 4, 2, 4, 3, + 2, 2, 4, 5, 2, 4, 5, 7, 10, 10, 8, 8, 4, 5, 6, 9, 9, 6, 6, + 3, 4, 5, 7, 7, 4, 4, 3, 2, 2, 4, 4, 2, 2, 2, 2, 1, 2, 1, + 1, 2, 3, 2, 2, 2, 1, 0, 2, 6, 4, 2, 2, 2, 1, 2, 3, 4, 6, + 7, 8, 10, 10, 3, 4, 6, 7, 8, 8, 8, 2, 3, 6, 6, 6, 6, 7, 6, + 2, 4, 5, 5, 5, 5, 8, 2, 4, 6, 6, 6, 5, 9, 4, 5, 7, 7, 7, + 5, 8, 7, 6, 8, 8, 8, 8, 2, 7, 10, 10, 11, 12, 13, 7, 7, 11, 11, + 12, 12, 12, 11, 7, 11, 12, 11, 12, 10, 12, 7, 11, 12, 12, 12, 10, 12, 9, + 13, 13, 13, 13, 13, 9, 11, 14, 14, 15, 15, 14, 9, 14, 16, 17, 16, 16, 16, + 13, 16, 18, 18, 18, 18, 13, 15, 17, 19, 20, 20, 18, 12, 15, 19, 20, 20, 20, + 18, 14, 15, 20, 21, 21, 20, 19, 15, 15, 22, 23, 22, 23, 21, 16, 15, 23, 27, + 24, 24, 21, 18, 16, 24, 28, 27, 25, 23, 19, 25, 28, 27, 27, 25, 20, 16, 26, + 30, 29, 29, 25, 21, 16, 25, 32, 32, 31, 26, 21, 17, 26, 32, 33, 31, 26, 22, + 18, 24, 31, 35, 33, 29, 23, 19, 25, 32, 37, 35, 30, 25, 21, 25, 32, 37, 38, + 32, 27, 22, 35, 40, 39, 32, 27, 23, 19, 36, 40, 41, 34, 27, 24, 19, 35, 39, + 43, 35, 30, 24, 19, 36, 39, 44, 36, 31, 26, 21, 34, 39, 44, 38, 32, 27, 23, + 34, 39, 43, 42, 35, 29, 24, 34, 40, 43, 44, 37, 30, 25, 4, 6, 8, 11, 11, + 9, 6, 4, 6, 8, 10, 10, 7, 4, 3, 5, 7, 8, 9, 6, 4, 3, 3, 5, + 7, 8, 5, 3, 1, 0, 3, 5, 7, 5, 3, 2, 2, 4, 4, 7, 5, 3, 4, + 3, 3, 4, 6, 5, 3, 4, 5, 7, 9, 8, 6, 6, 3, 4, 6, 8, 7, 5, + 4, 3, 4, 5, 7, 5, 4, 2, 2, 2, 4, 5, 4, 3, 0, 1, 1, 2, 4, + 3, 2, 0, 3, 2, 3, 4, 2, 2, 0, 7, 4, 3, 3, 3, 1, 0, 3, 4, + 5, 5, 7, 8, 8, 2, 3, 5, 6, 6, 6, 6, 2, 3, 5, 4, 4, 4, 5, + 3, 2, 3, 3, 2, 3, 3, 6, 2, 4, 4, 4, 4, 3, 7, 4, 5, 5, 5, + 5, 3, 8, 7, 6, 6, 6, 6, 6, 2, 7, 8, 8, 9, 10, 11, 3, 7, 9, + 9, 10, 10, 10, 9, 7, 10, 9, 10, 10, 8, 11, 7, 10, 10, 9, 10, 7, 10, + 9, 11, 11, 12, 11, 11, 7, 11, 13, 12, 13, 13, 12, 8, 14, 15, 14, 14, 14, + 14, 12, 16, 16, 16, 17, 16, 11, 14, 16, 17, 17, 18, 16, 10, 15, 18, 18, 18, + 17, 16, 12, 14, 20, 19, 19, 19, 17, 12, 14, 21, 21, 21, 20, 18, 14, 15, 22, + 24, 22, 21, 19, 15, 16, 23, 26, 25, 23, 21, 17, 24, 26, 24, 25, 21, 18, 14, + 24, 28, 26, 25, 22, 18, 14, 24, 30, 29, 27, 23, 19, 14, 24, 29, 30, 28, 25, + 19, 15, 23, 29, 32, 30, 25, 21, 17, 24, 30, 35, 32, 27, 23, 18, 25, 30, 35, + 35, 30, 25, 20, 32, 37, 35, 28, 24, 21, 16, 32, 37, 38, 31, 25, 20, 17, 33, + 37, 39, 32, 27, 22, 17, 32, 37, 40, 33, 27, 22, 18, 31, 36, 41, 37, 30, 24, + 20, 31, 35, 40, 40, 32, 26, 21, 32, 37, 40, 41, 34, 28, 23, 17, 19, 20, 23, + 22, 21, 20, 17, 19, 20, 22, 22, 20, 18, 16, 18, 19, 19, 20, 17, 14, 16, 16, + 16, 17, 17, 12, 7, 13, 13, 13, 12, 10, 10, 7, 9, 9, 7, 6, 8, 9, 7, + 3, 3, 4, 6, 7, 9, 7, 16, 18, 19, 21, 21, 21, 20, 15, 18, 19, 20, 20, + 19, 17, 15, 17, 18, 19, 18, 17, 14, 14, 15, 15, 16, 14, 11, 7, 12, 12, 12, + 11, 7, 7, 7, 8, 7, 6, 5, 6, 6, 6, 0, 2, 4, 4, 5, 6, 6, 15, + 17, 18, 19, 21, 21, 20, 14, 16, 17, 19, 19, 19, 17, 15, 16, 17, 17, 17, 16, + 13, 15, 14, 14, 14, 13, 11, 6, 10, 10, 10, 9, 5, 6, 6, 3, 5, 5, 4, + 5, 6, 6, 2, 2, 2, 4, 5, 5, 6, 15, 16, 17, 18, 20, 21, 21, 14, 16, + 18, 19, 19, 19, 19, 12, 16, 17, 17, 17, 16, 15, 9, 15, 14, 14, 13, 10, 10, + 6, 11, 10, 9, 5, 5, 7, 4, 4, 4, 4, 4, 5, 6, 2, 7, 5, 5, 5, + 5, 6, 14, 15, 17, 19, 19, 21, 21, 12, 15, 16, 18, 19, 18, 19, 11, 14, 15, + 15, 16, 15, 14, 12, 12, 12, 12, 11, 10, 6, 9, 10, 10, 10, 11, 11, 6, 6, + 11, 13, 12, 12, 12, 7, 7, 12, 14, 13, 13, 12, 9, 13, 15, 16, 17, 17, 19, + 21, 13, 17, 17, 18, 16, 17, 18, 13, 19, 18, 18, 14, 14, 13, 13, 18, 19, 18, + 16, 11, 8, 12, 17, 19, 18, 15, 12, 9, 12, 16, 19, 17, 15, 13, 11, 13, 15, + 18, 18, 16, 14, 12, 21, 25, 24, 21, 16, 18, 19, 21, 25, 25, 21, 17, 16, 16, + 21, 24, 26, 22, 18, 13, 12, 21, 23, 25, 21, 18, 14, 11, 19, 21, 24, 20, 16, + 14, 12, 18, 21, 22, 21, 16, 15, 13, 17, 19, 22, 22, 18, 15, 13, 15, 16, 17, + 19, 18, 18, 17, 14, 16, 17, 18, 18, 17, 15, 13, 15, 16, 16, 16, 14, 11, 13, + 14, 14, 13, 12, 9, 5, 11, 11, 10, 9, 6, 5, 4, 7, 7, 5, 4, 5, 5, + 5, 2, 2, 2, 3, 5, 5, 4, 14, 15, 16, 18, 18, 18, 17, 14, 15, 16, 17, + 18, 16, 14, 13, 14, 15, 16, 15, 13, 10, 13, 12, 13, 12, 11, 9, 4, 10, 9, + 9, 8, 4, 4, 4, 6, 5, 4, 3, 3, 4, 4, 2, 0, 2, 2, 3, 4, 4, + 13, 14, 15, 16, 18, 18, 18, 13, 13, 15, 16, 16, 16, 15, 13, 13, 14, 14, 14, + 13, 11, 12, 12, 11, 11, 10, 8, 5, 8, 8, 8, 8, 3, 4, 4, 3, 4, 4, + 3, 3, 4, 4, 2, 2, 1, 2, 3, 4, 5, 13, 15, 15, 17, 19, 19, 19, 12, + 15, 16, 17, 17, 18, 16, 10, 15, 15, 15, 15, 14, 13, 7, 14, 13, 13, 12, 9, + 9, 5, 10, 9, 8, 6, 6, 7, 3, 6, 6, 7, 7, 7, 8, 2, 9, 9, 8, + 8, 9, 9, 13, 14, 15, 17, 18, 19, 20, 11, 14, 15, 16, 17, 17, 17, 12, 13, + 14, 14, 15, 14, 12, 11, 13, 12, 12, 13, 12, 8, 9, 13, 14, 14, 14, 14, 9, + 8, 15, 16, 17, 16, 15, 11, 10, 16, 19, 19, 19, 17, 12, 16, 19, 19, 20, 17, + 18, 19, 16, 21, 21, 21, 18, 16, 16, 16, 23, 23, 22, 18, 14, 12, 17, 22, 24, + 23, 19, 15, 11, 15, 22, 25, 25, 22, 17, 12, 16, 22, 28, 28, 24, 19, 14, 17, + 23, 28, 29, 25, 21, 16, 26, 32, 31, 24, 20, 17, 18, 25, 31, 33, 26, 21, 16, + 15, 26, 31, 35, 27, 22, 17, 12, 25, 31, 36, 29, 23, 18, 14, 24, 30, 35, 32, + 25, 21, 15, 24, 31, 35, 33, 28, 23, 17, 24, 31, 35, 33, 29, 24, 19, 11, 12, + 14, 15, 15, 15, 14, 10, 12, 13, 15, 14, 13, 11, 10, 11, 13, 13, 12, 10, 8, + 10, 10, 10, 10, 9, 6, 3, 7, 7, 7, 6, 4, 3, 2, 4, 3, 3, 2, 3, + 3, 2, 2, 1, 1, 2, 3, 3, 2, 10, 11, 13, 14, 15, 14, 14, 10, 11, 12, + 13, 14, 12, 12, 10, 10, 11, 12, 11, 10, 8, 10, 9, 9, 9, 8, 6, 3, 7, + 6, 6, 6, 3, 2, 3, 3, 2, 2, 2, 2, 2, 3, 4, 2, 0, 2, 2, 2, + 3, 10, 10, 11, 13, 14, 16, 16, 10, 10, 12, 13, 13, 14, 14, 10, 10, 11, 12, + 11, 11, 10, 9, 8, 9, 9, 9, 6, 5, 4, 5, 6, 6, 4, 3, 5, 3, 2, + 3, 3, 3, 4, 5, 4, 3, 4, 4, 4, 5, 5, 10, 13, 13, 14, 16, 17, 17, + 8, 12, 13, 14, 15, 15, 14, 6, 12, 13, 13, 13, 12, 11, 8, 11, 10, 10, 10, + 9, 9, 6, 7, 8, 9, 9, 10, 9, 4, 9, 10, 10, 11, 11, 11, 4, 12, 12, + 12, 12, 12, 12, 11, 13, 14, 15, 16, 17, 17, 11, 14, 15, 15, 16, 15, 14, 11, + 15, 16, 16, 16, 14, 11, 11, 17, 17, 16, 17, 15, 11, 11, 18, 17, 18, 18, 17, + 12, 12, 19, 21, 20, 20, 18, 14, 14, 20, 23, 21, 22, 20, 16, 21, 23, 23, 23, + 20, 17, 17, 21, 25, 25, 25, 21, 17, 14, 21, 28, 27, 26, 22, 17, 13, 21, 25, + 29, 27, 22, 19, 14, 20, 27, 31, 29, 25, 20, 15, 20, 26, 33, 32, 26, 21, 17, + 22, 27, 32, 34, 29, 24, 18, 30, 35, 35, 28, 23, 19, 16, 30, 36, 38, 31, 24, + 19, 15, 30, 36, 39, 32, 26, 20, 15, 30, 35, 40, 32, 27, 22, 17, 28, 35, 40, + 35, 29, 23, 19, 28, 35, 40, 38, 30, 26, 20, 29, 35, 40, 41, 33, 28, 21, 9, + 10, 12, 13, 13, 13, 12, 8, 9, 11, 13, 13, 11, 9, 8, 9, 11, 11, 11, 9, + 7, 8, 7, 8, 9, 8, 5, 2, 5, 5, 5, 5, 4, 2, 2, 2, 2, 1, 2, + 3, 2, 2, 3, 2, 1, 2, 2, 2, 2, 8, 9, 11, 12, 13, 12, 13, 8, 9, + 10, 12, 12, 10, 10, 7, 8, 9, 10, 10, 8, 8, 7, 7, 7, 8, 7, 5, 4, + 5, 4, 3, 4, 3, 2, 3, 2, 2, 1, 1, 2, 2, 3, 4, 2, 2, 0, 1, + 2, 3, 8, 8, 10, 11, 13, 14, 14, 7, 8, 10, 12, 12, 12, 12, 7, 7, 10, + 10, 10, 10, 9, 5, 6, 8, 8, 8, 6, 6, 5, 3, 5, 5, 5, 5, 6, 6, + 2, 5, 5, 5, 6, 6, 5, 4, 5, 7, 7, 7, 7, 7, 11, 12, 13, 14, 16, + 15, 5, 10, 12, 14, 13, 13, 13, 7, 10, 11, 11, 12, 12, 11, 10, 9, 10, 11, + 11, 11, 10, 9, 8, 11, 11, 12, 12, 12, 7, 10, 13, 13, 13, 13, 14, 5, 13, + 14, 15, 14, 14, 15, 12, 15, 16, 17, 18, 17, 15, 14, 16, 18, 18, 19, 17, 13, + 14, 17, 19, 19, 18, 17, 13, 14, 20, 19, 19, 20, 18, 14, 13, 21, 21, 20, 20, + 19, 15, 14, 22, 23, 23, 22, 21, 17, 16, 22, 26, 25, 25, 23, 18, 24, 27, 26, + 26, 23, 19, 16, 24, 29, 28, 28, 24, 21, 15, 24, 31, 31, 29, 26, 20, 16, 24, + 30, 31, 30, 27, 21, 17, 23, 30, 33, 31, 27, 22, 18, 23, 30, 35, 34, 29, 24, + 19, 25, 30, 35, 36, 32, 27, 21, 33, 40, 39, 32, 26, 22, 18, 34, 40, 42, 34, + 28, 23, 18, 33, 40, 43, 35, 29, 23, 18, 34, 40, 44, 36, 30, 25, 19, 32, 38, + 44, 39, 32, 26, 21, 33, 38, 43, 42, 34, 28, 23, 32, 39, 42, 43, 36, 30, 24, + 7, 9, 13, 15, 15, 14, 10, 6, 8, 11, 15, 15, 12, 9, 6, 7, 10, 12, 13, + 10, 7, 6, 5, 7, 10, 11, 8, 4, 3, 3, 4, 6, 8, 6, 3, 1, 1, 2, + 3, 6, 6, 3, 3, 2, 2, 2, 5, 6, 3, 6, 7, 10, 13, 13, 10, 10, 6, + 7, 9, 12, 12, 9, 8, 5, 6, 8, 10, 10, 7, 6, 5, 5, 5, 7, 6, 5, + 3, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 1, 2, 3, 5, 3, 2, 1, + 0, 1, 2, 5, 6, 8, 9, 11, 12, 12, 5, 6, 8, 9, 10, 10, 10, 4, 5, + 8, 8, 8, 8, 8, 4, 4, 5, 6, 6, 5, 5, 6, 2, 3, 4, 4, 4, 4, + 8, 3, 4, 5, 5, 5, 5, 7, 5, 5, 7, 7, 7, 7, 5, 8, 10, 10, 12, + 13, 13, 4, 8, 10, 11, 11, 11, 11, 7, 8, 10, 10, 10, 10, 10, 10, 7, 10, + 11, 11, 11, 9, 10, 8, 11, 11, 12, 11, 12, 8, 10, 13, 13, 13, 13, 13, 7, + 13, 15, 15, 15, 14, 15, 12, 16, 16, 17, 18, 17, 14, 14, 16, 18, 18, 19, 17, + 12, 14, 18, 19, 19, 18, 17, 13, 14, 19, 19, 19, 19, 18, 13, 13, 21, 21, 21, + 21, 19, 15, 13, 22, 23, 23, 22, 20, 16, 15, 23, 26, 25, 24, 22, 18, 24, 27, + 26, 26, 23, 19, 15, 24, 30, 28, 28, 25, 20, 15, 24, 31, 30, 29, 24, 20, 16, + 25, 31, 31, 30, 25, 21, 16, 24, 30, 34, 32, 27, 23, 17, 24, 30, 36, 35, 28, + 23, 20, 24, 31, 35, 36, 31, 26, 20, 34, 39, 39, 32, 26, 21, 18, 34, 40, 39, + 33, 28, 23, 18, 34, 41, 43, 35, 28, 23, 18, 33, 39, 44, 35, 30, 24, 19, 32, + 39, 42, 39, 31, 26, 20, 32, 39, 43, 41, 34, 28, 23, 32, 38, 42, 43, 36, 30, + 24, 5, 8, 11, 15, 15, 13, 9, 5, 7, 10, 14, 14, 11, 7, 4, 5, 9, 11, + 13, 9, 6, 4, 4, 6, 8, 11, 7, 3, 1, 1, 2, 5, 8, 6, 3, 2, 2, + 2, 3, 6, 6, 3, 4, 3, 2, 3, 5, 6, 3, 4, 5, 9, 12, 12, 9, 9, + 4, 5, 8, 11, 11, 8, 7, 3, 5, 6, 8, 8, 6, 4, 3, 3, 3, 6, 5, + 4, 1, 2, 1, 1, 2, 2, 2, 1, 3, 2, 2, 3, 1, 1, 1, 7, 4, 2, + 2, 1, 0, 1, 4, 5, 6, 7, 9, 10, 10, 3, 4, 7, 7, 8, 8, 8, 3, + 4, 6, 6, 6, 6, 6, 4, 2, 4, 4, 4, 4, 4, 7, 2, 4, 5, 5, 4, + 4, 8, 3, 5, 6, 6, 6, 4, 8, 6, 6, 7, 7, 7, 7, 3, 7, 9, 9, + 10, 11, 12, 5, 7, 10, 10, 11, 11, 11, 8, 7, 10, 10, 10, 11, 10, 11, 7, + 10, 11, 11, 11, 8, 10, 9, 11, 12, 12, 12, 12, 8, 11, 13, 13, 14, 13, 13, + 8, 14, 15, 15, 14, 14, 15, 13, 16, 16, 17, 18, 17, 12, 15, 16, 17, 18, 19, + 17, 11, 15, 18, 19, 19, 19, 18, 13, 15, 20, 20, 20, 20, 18, 13, 14, 21, 21, + 21, 21, 19, 15, 14, 22, 25, 23, 22, 21, 16, 16, 24, 27, 25, 25, 23, 18, 24, + 28, 27, 26, 23, 19, 15, 24, 29, 28, 27, 24, 19, 15, 24, 32, 31, 29, 25, 20, + 16, 24, 31, 31, 29, 26, 21, 16, 23, 29, 33, 31, 27, 22, 18, 24, 30, 37, 34, + 28, 24, 19, 25, 30, 37, 36, 31, 26, 21, 34, 39, 37, 31, 26, 22, 18, 35, 40, + 39, 33, 27, 22, 18, 34, 39, 42, 34, 29, 24, 18, 34, 37, 42, 34, 29, 24, 19, + 33, 38, 42, 37, 31, 26, 21, 34, 38, 41, 41, 34, 27, 23, 33, 38, 42, 42, 35, + 28, 24, 4, 6, 8, 11, 11, 9, 6, 4, 6, 8, 10, 10, 7, 4, 3, 5, 7, + 8, 9, 6, 4, 3, 3, 5, 6, 8, 5, 3, 1, 0, 3, 5, 8, 5, 3, 2, + 2, 4, 5, 7, 5, 3, 4, 3, 3, 4, 6, 5, 3, 4, 5, 7, 9, 8, 7, + 6, 3, 4, 6, 8, 7, 5, 4, 3, 4, 5, 7, 5, 4, 2, 2, 2, 3, 5, + 4, 3, 0, 1, 1, 2, 4, 3, 2, 0, 3, 2, 3, 4, 2, 2, 0, 7, 4, + 3, 3, 3, 1, 0, 3, 4, 5, 5, 7, 8, 8, 2, 3, 5, 6, 6, 6, 6, + 2, 3, 5, 4, 4, 4, 5, 3, 2, 3, 3, 3, 3, 3, 5, 2, 4, 4, 4, + 4, 3, 7, 4, 5, 5, 5, 5, 3, 8, 7, 6, 6, 6, 6, 6, 2, 7, 8, + 9, 9, 10, 11, 3, 7, 9, 9, 10, 10, 9, 9, 7, 10, 9, 9, 10, 8, 11, + 7, 10, 10, 10, 10, 7, 9, 9, 11, 11, 11, 11, 11, 8, 11, 13, 13, 13, 13, + 12, 8, 14, 15, 14, 14, 14, 13, 12, 15, 16, 16, 16, 16, 11, 14, 17, 17, 17, + 18, 16, 10, 14, 17, 18, 18, 18, 16, 12, 14, 19, 18, 19, 18, 17, 12, 14, 21, + 21, 20, 19, 19, 14, 15, 22, 24, 23, 21, 19, 16, 16, 22, 26, 24, 23, 21, 17, + 24, 26, 24, 24, 21, 18, 14, 24, 28, 27, 26, 23, 18, 14, 24, 30, 28, 27, 23, + 19, 15, 24, 29, 31, 27, 24, 20, 16, 23, 28, 32, 30, 25, 21, 17, 24, 30, 34, + 33, 28, 23, 19, 24, 30, 35, 34, 30, 24, 20, 32, 37, 35, 28, 24, 20, 17, 33, + 37, 36, 30, 25, 21, 16, 33, 37, 39, 31, 26, 22, 17, 32, 37, 40, 33, 27, 23, + 19, 31, 36, 39, 36, 30, 23, 20, 31, 36, 40, 38, 32, 26, 21, 33, 36, 41, 40, + 34, 28, 22, 2, 3, 4, 8, 8, 6, 2, 2, 2, 3, 7, 8, 4, 2, 2, 2, + 2, 4, 5, 2, 2, 1, 2, 2, 2, 3, 2, 3, 2, 3, 3, 3, 4, 3, 3, + 6, 6, 6, 6, 4, 3, 3, 12, 11, 8, 6, 5, 3, 3, 2, 2, 3, 5, 5, + 2, 2, 1, 2, 3, 3, 4, 2, 1, 0, 2, 2, 2, 2, 2, 1, 1, 1, 2, + 2, 1, 1, 3, 4, 3, 4, 4, 4, 3, 3, 8, 8, 8, 7, 5, 3, 3, 15, + 13, 10, 7, 5, 4, 3, 0, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, + 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 2, 1, 2, 2, 4, 6, 5, 5, 5, + 5, 4, 4, 11, 10, 9, 8, 6, 5, 4, 18, 16, 12, 9, 7, 6, 5, 2, 2, + 2, 3, 3, 3, 7, 2, 3, 4, 4, 4, 4, 7, 4, 4, 5, 5, 5, 5, 7, + 7, 7, 7, 7, 8, 8, 8, 8, 12, 11, 11, 12, 11, 10, 12, 17, 16, 15, 14, + 13, 12, 18, 23, 20, 17, 15, 14, 13, 10, 10, 10, 10, 11, 10, 7, 12, 12, 12, + 11, 12, 11, 7, 12, 13, 13, 14, 13, 12, 8, 12, 17, 16, 16, 17, 15, 12, 15, + 21, 21, 20, 20, 19, 14, 19, 24, 25, 25, 23, 20, 15, 22, 27, 30, 27, 25, 22, + 17, 19, 21, 20, 20, 17, 13, 8, 19, 22, 22, 22, 18, 14, 10, 19, 24, 24, 24, + 19, 15, 11, 19, 25, 27, 27, 23, 19, 15, 22, 28, 32, 31, 28, 23, 17, 24, 30, + 36, 35, 30, 25, 18, 27, 34, 37, 37, 32, 26, 20, 27, 32, 32, 25, 20, 16, 11, + 27, 33, 34, 28, 22, 17, 13, 26, 34, 36, 29, 24, 19, 15, 28, 34, 38, 32, 27, + 23, 19, 29, 35, 40, 36, 32, 27, 21, 31, 37, 40, 40, 33, 27, 23, 33, 38, 42, + 42, 36, 30, 25, 1, 2, 3, 3, 3, 2, 2, 1, 2, 2, 3, 3, 2, 1, 1, + 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 4, 4, 3, 4, 4, 4, 4, + 4, 8, 7, 7, 7, 5, 4, 4, 13, 12, 9, 7, 6, 4, 4, 1, 2, 2, 3, + 2, 2, 1, 2, 1, 2, 2, 2, 1, 1, 2, 0, 2, 2, 2, 1, 1, 2, 2, + 2, 2, 2, 2, 4, 5, 5, 5, 5, 5, 4, 4, 10, 9, 9, 8, 6, 4, 4, + 17, 14, 11, 8, 6, 5, 4, 2, 0, 1, 2, 2, 1, 5, 2, 1, 1, 1, 1, + 1, 5, 2, 2, 1, 1, 1, 1, 6, 4, 2, 4, 4, 4, 4, 7, 8, 6, 7, + 7, 8, 7, 7, 13, 12, 12, 11, 10, 8, 7, 19, 17, 15, 13, 11, 10, 9, 2, + 5, 5, 6, 6, 6, 9, 5, 6, 6, 7, 7, 7, 9, 8, 7, 7, 8, 8, 8, + 9, 11, 10, 11, 11, 11, 12, 11, 11, 15, 15, 15, 15, 15, 14, 13, 20, 20, 18, + 17, 16, 15, 19, 26, 23, 21, 18, 18, 17, 13, 14, 13, 13, 13, 13, 9, 14, 15, + 14, 15, 15, 14, 9, 14, 17, 16, 17, 16, 15, 12, 15, 21, 20, 20, 20, 19, 16, + 18, 25, 25, 24, 24, 22, 17, 22, 28, 30, 29, 26, 24, 19, 26, 31, 33, 30, 29, + 26, 20, 22, 24, 23, 23, 19, 15, 11, 23, 26, 25, 24, 21, 16, 12, 23, 28, 27, + 26, 23, 19, 15, 23, 29, 31, 30, 27, 22, 19, 25, 32, 36, 34, 31, 26, 21, 29, + 34, 41, 39, 34, 27, 22, 32, 37, 42, 41, 36, 30, 24, 31, 36, 34, 28, 23, 18, + 14, 30, 37, 37, 30, 23, 20, 15, 31, 36, 39, 33, 26, 22, 19, 30, 36, 42, 36, + 31, 27, 23, 32, 39, 45, 41, 35, 29, 24, 34, 40, 47, 45, 39, 31, 26, 38, 43, + 47, 46, 41, 34, 28, 1, 3, 4, 5, 5, 4, 3, 1, 2, 4, 5, 5, 4, 3, + 2, 1, 4, 4, 5, 5, 5, 2, 2, 4, 5, 6, 6, 6, 4, 4, 6, 7, 8, + 7, 6, 8, 8, 9, 10, 8, 7, 6, 14, 13, 10, 10, 9, 7, 6, 2, 1, 3, + 4, 4, 3, 1, 2, 1, 3, 4, 4, 3, 1, 2, 2, 2, 4, 4, 3, 3, 2, + 3, 3, 5, 5, 5, 5, 5, 5, 6, 7, 7, 6, 4, 11, 10, 10, 10, 8, 6, + 4, 18, 15, 12, 10, 8, 6, 4, 2, 1, 0, 1, 1, 2, 5, 2, 2, 1, 1, + 1, 2, 4, 3, 2, 2, 2, 3, 3, 6, 7, 3, 6, 6, 6, 6, 8, 10, 7, + 9, 9, 9, 9, 8, 15, 12, 13, 13, 11, 10, 7, 21, 19, 16, 14, 13, 11, 10, + 3, 6, 6, 6, 7, 6, 8, 8, 6, 7, 7, 8, 8, 9, 10, 7, 9, 9, 10, + 10, 10, 12, 10, 13, 13, 13, 13, 11, 13, 15, 17, 17, 17, 16, 14, 15, 22, 22, + 21, 19, 18, 17, 20, 27, 25, 22, 21, 20, 19, 14, 15, 15, 14, 15, 13, 8, 16, + 15, 16, 16, 15, 14, 8, 16, 17, 18, 19, 18, 17, 13, 16, 22, 22, 22, 22, 21, + 17, 19, 27, 27, 26, 26, 24, 18, 23, 31, 33, 31, 29, 25, 21, 28, 34, 35, 32, + 31, 28, 22, 23, 25, 24, 23, 20, 16, 12, 23, 28, 26, 25, 21, 17, 13, 24, 29, + 28, 28, 25, 21, 17, 24, 31, 33, 32, 28, 24, 21, 27, 33, 39, 36, 33, 27, 21, + 31, 37, 42, 41, 36, 29, 24, 33, 40, 45, 44, 38, 31, 26, 32, 38, 36, 29, 24, + 19, 15, 32, 37, 38, 30, 25, 21, 17, 31, 38, 40, 35, 29, 24, 19, 32, 39, 45, + 39, 32, 28, 24, 34, 41, 46, 44, 37, 31, 25, 37, 44, 48, 48, 41, 33, 28, 40, + 45, 49, 50, 43, 36, 30, 1, 3, 6, 8, 8, 6, 3, 1, 2, 5, 7, 8, 6, + 4, 1, 2, 4, 7, 8, 7, 5, 2, 2, 5, 7, 9, 8, 7, 4, 5, 7, 9, + 11, 9, 8, 9, 9, 10, 11, 11, 9, 8, 16, 14, 12, 11, 11, 9, 7, 1, 1, + 4, 6, 5, 3, 1, 2, 1, 3, 5, 5, 2, 2, 2, 1, 2, 5, 5, 4, 3, + 2, 3, 4, 6, 6, 5, 5, 6, 6, 7, 9, 8, 7, 5, 12, 11, 11, 11, 9, + 7, 5, 19, 17, 13, 11, 9, 7, 5, 2, 2, 1, 0, 1, 2, 4, 2, 2, 1, + 1, 1, 2, 4, 5, 2, 3, 3, 3, 3, 6, 8, 3, 6, 7, 7, 7, 7, 11, + 8, 10, 10, 10, 10, 8, 16, 13, 15, 14, 13, 11, 8, 21, 20, 18, 16, 14, 12, + 11, 5, 6, 7, 7, 7, 5, 7, 9, 6, 7, 8, 8, 8, 8, 12, 7, 9, 10, + 11, 11, 10, 14, 10, 14, 15, 14, 14, 12, 15, 15, 18, 18, 18, 18, 15, 16, 23, + 22, 21, 21, 19, 17, 22, 29, 26, 24, 22, 20, 20, 15, 14, 14, 14, 14, 13, 7, + 18, 15, 16, 15, 16, 15, 8, 18, 17, 18, 19, 19, 17, 14, 17, 22, 23, 23, 23, + 22, 18, 20, 28, 28, 27, 27, 25, 20, 23, 32, 34, 32, 28, 26, 22, 28, 35, 37, + 34, 32, 28, 23, 24, 26, 24, 23, 20, 16, 12, 24, 28, 26, 26, 22, 18, 14, 24, + 30, 29, 29, 25, 21, 18, 24, 32, 34, 33, 30, 25, 22, 28, 35, 40, 38, 34, 29, + 23, 32, 37, 45, 42, 36, 30, 25, 36, 42, 45, 45, 39, 33, 27, 32, 38, 35, 29, + 23, 19, 15, 32, 38, 37, 31, 26, 21, 18, 33, 38, 41, 35, 29, 26, 21, 32, 40, + 45, 39, 35, 29, 25, 36, 43, 48, 44, 39, 33, 26, 38, 45, 50, 50, 41, 35, 29, + 41, 47, 51, 51, 44, 37, 30, 1, 3, 6, 8, 8, 6, 3, 2, 2, 5, 7, 8, + 6, 5, 2, 1, 5, 8, 9, 8, 6, 2, 3, 5, 8, 10, 9, 8, 5, 6, 8, + 10, 12, 10, 9, 10, 11, 12, 13, 13, 10, 9, 17, 15, 13, 12, 12, 10, 9, 2, + 1, 4, 6, 5, 2, 2, 2, 1, 3, 5, 5, 3, 2, 2, 2, 2, 6, 5, 4, + 4, 2, 3, 5, 7, 7, 6, 7, 7, 7, 8, 10, 10, 8, 7, 13, 12, 13, 13, + 10, 9, 7, 21, 18, 14, 13, 11, 9, 7, 2, 2, 1, 1, 0, 2, 4, 3, 2, + 1, 1, 2, 3, 5, 7, 2, 3, 4, 5, 4, 6, 10, 3, 7, 8, 8, 8, 8, + 13, 9, 11, 12, 12, 11, 8, 17, 15, 16, 15, 14, 13, 8, 23, 21, 19, 17, 15, + 14, 13, 6, 6, 7, 7, 7, 4, 7, 11, 7, 8, 8, 9, 9, 8, 13, 7, 10, + 11, 12, 12, 11, 16, 10, 15, 16, 16, 16, 13, 16, 17, 19, 20, 20, 19, 16, 18, + 24, 25, 23, 22, 21, 19, 23, 30, 28, 25, 23, 22, 22, 16, 15, 15, 15, 15, 13, + 7, 19, 17, 16, 16, 18, 16, 8, 19, 18, 19, 20, 21, 19, 15, 19, 23, 23, 25, + 25, 24, 20, 20, 28, 30, 29, 29, 26, 21, 24, 33, 35, 33, 31, 29, 23, 30, 37, + 38, 35, 33, 30, 25, 25, 26, 25, 24, 20, 16, 12, 24, 28, 26, 25, 22, 19, 15, + 24, 30, 29, 30, 27, 23, 19, 25, 32, 35, 34, 31, 27, 23, 28, 36, 41, 39, 35, + 30, 25, 33, 40, 46, 43, 38, 32, 27, 37, 42, 47, 46, 40, 34, 28, 32, 38, 35, + 28, 23, 19, 16, 33, 37, 38, 31, 26, 22, 19, 34, 38, 40, 35, 31, 27, 22, 33, + 40, 45, 40, 35, 31, 27, 35, 43, 47, 46, 39, 34, 29, 41, 46, 50, 50, 42, 36, + 30, 43, 48, 50, 53, 45, 38, 32, 3, 5, 7, 8, 8, 6, 5, 2, 4, 6, 8, + 9, 7, 6, 1, 3, 6, 9, 10, 9, 8, 2, 4, 7, 9, 12, 11, 10, 5, 7, + 10, 11, 14, 12, 10, 11, 12, 13, 14, 14, 12, 10, 17, 16, 15, 14, 14, 12, 10, + 1, 4, 5, 7, 5, 3, 2, 2, 2, 5, 6, 6, 4, 3, 2, 2, 5, 7, 7, + 6, 5, 2, 3, 6, 8, 8, 7, 8, 6, 7, 10, 11, 11, 9, 8, 13, 13, 14, + 14, 11, 10, 8, 21, 18, 15, 14, 12, 10, 8, 2, 1, 2, 2, 2, 0, 2, 2, + 2, 1, 1, 2, 1, 4, 4, 2, 1, 3, 3, 3, 5, 9, 3, 5, 6, 6, 7, + 7, 11, 9, 10, 10, 10, 10, 7, 17, 15, 15, 14, 12, 11, 7, 23, 21, 17, 15, + 14, 12, 11, 4, 5, 5, 5, 5, 3, 5, 9, 6, 6, 6, 7, 7, 7, 12, 7, + 8, 9, 10, 11, 9, 15, 10, 13, 14, 14, 14, 11, 15, 15, 18, 18, 18, 17, 15, + 17, 23, 23, 22, 20, 19, 17, 24, 30, 26, 24, 22, 20, 19, 15, 13, 13, 12, 13, + 11, 5, 18, 15, 14, 14, 15, 14, 7, 19, 16, 17, 19, 19, 18, 13, 19, 21, 22, + 23, 23, 21, 18, 19, 27, 28, 27, 27, 24, 19, 23, 31, 34, 31, 29, 25, 21, 29, + 35, 36, 33, 31, 28, 23, 23, 24, 22, 20, 18, 14, 10, 23, 26, 24, 22, 20, 17, + 13, 23, 28, 27, 27, 23, 21, 17, 23, 30, 32, 30, 29, 24, 21, 27, 34, 37, 36, + 32, 28, 23, 31, 38, 43, 42, 35, 30, 25, 35, 40, 44, 43, 37, 31, 26, 31, 33, + 30, 25, 20, 17, 14, 30, 33, 33, 27, 23, 20, 17, 31, 33, 36, 31, 27, 25, 21, + 30, 35, 42, 36, 32, 28, 25, 34, 39, 44, 43, 37, 32, 27, 38, 42, 47, 47, 40, + 33, 28, 41, 46, 49, 48, 42, 36, 30, 6, 7, 9, 10, 10, 8, 6, 5, 6, 8, + 10, 11, 9, 8, 4, 6, 8, 11, 13, 11, 9, 3, 6, 9, 12, 14, 12, 11, 5, + 8, 10, 13, 15, 14, 11, 11, 13, 14, 14, 16, 14, 11, 17, 17, 15, 15, 14, 13, + 11, 4, 6, 7, 9, 7, 5, 3, 3, 5, 7, 8, 7, 6, 5, 1, 5, 7, 9, + 8, 7, 6, 1, 5, 8, 10, 9, 9, 8, 5, 8, 10, 12, 11, 10, 8, 12, 13, + 15, 15, 12, 10, 8, 20, 18, 16, 14, 12, 10, 8, 1, 5, 5, 4, 4, 2, 0, + 2, 3, 5, 4, 3, 3, 2, 2, 2, 4, 5, 4, 5, 4, 4, 3, 6, 6, 6, + 6, 6, 8, 8, 10, 10, 10, 8, 6, 15, 15, 15, 13, 11, 9, 6, 22, 20, 17, + 14, 11, 9, 8, 2, 2, 2, 2, 1, 2, 3, 5, 3, 3, 2, 3, 3, 4, 8, + 5, 4, 6, 6, 6, 6, 11, 7, 9, 10, 10, 10, 8, 12, 14, 14, 14, 14, 13, + 11, 15, 20, 19, 17, 16, 15, 13, 22, 26, 22, 20, 18, 16, 15, 12, 10, 9, 9, + 9, 8, 3, 15, 12, 11, 11, 11, 10, 4, 15, 14, 13, 14, 14, 13, 10, 14, 18, + 18, 18, 19, 17, 14, 17, 25, 23, 23, 23, 20, 15, 22, 28, 30, 27, 24, 21, 17, + 26, 31, 33, 29, 26, 23, 19, 20, 19, 18, 16, 14, 10, 6, 19, 22, 18, 17, 15, + 13, 9, 19, 23, 22, 21, 19, 16, 13, 20, 25, 26, 26, 23, 20, 17, 23, 30, 33, + 30, 28, 23, 19, 27, 33, 38, 35, 29, 25, 20, 32, 35, 40, 38, 32, 27, 22, 24, + 28, 25, 19, 15, 13, 10, 25, 28, 27, 21, 17, 15, 13, 25, 28, 29, 25, 22, 19, + 16, 25, 29, 35, 31, 27, 23, 20, 28, 35, 39, 36, 31, 27, 22, 32, 37, 41, 41, + 34, 28, 23, 36, 40, 42, 43, 37, 30, 26, 2, 3, 8, 12, 12, 10, 7, 2, 3, + 6, 11, 11, 9, 4, 2, 2, 4, 8, 9, 7, 2, 2, 2, 2, 4, 7, 5, 2, + 2, 2, 2, 3, 5, 5, 2, 6, 6, 6, 5, 4, 5, 2, 11, 11, 8, 6, 4, + 5, 2, 2, 2, 5, 8, 9, 6, 2, 1, 2, 3, 7, 9, 4, 2, 2, 2, 2, + 4, 5, 2, 2, 0, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 7, + 7, 8, 6, 4, 3, 2, 15, 13, 10, 7, 5, 3, 2, 1, 2, 2, 2, 3, 2, + 2, 0, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, + 1, 1, 2, 5, 4, 4, 4, 4, 3, 2, 11, 9, 9, 7, 5, 3, 2, 17, 16, + 12, 9, 6, 4, 3, 1, 1, 1, 1, 1, 1, 5, 2, 2, 2, 3, 3, 3, 6, + 2, 3, 3, 3, 4, 4, 6, 5, 5, 6, 6, 6, 7, 7, 6, 10, 10, 10, 10, + 9, 9, 11, 15, 14, 14, 12, 11, 10, 17, 21, 18, 16, 14, 13, 12, 9, 9, 9, + 9, 10, 9, 6, 11, 11, 10, 11, 11, 10, 6, 11, 12, 12, 12, 12, 11, 7, 11, + 15, 14, 15, 15, 14, 11, 13, 20, 19, 19, 19, 18, 12, 17, 23, 25, 24, 21, 20, + 14, 21, 26, 27, 24, 24, 21, 16, 18, 20, 19, 19, 16, 12, 7, 18, 21, 21, 21, + 18, 12, 9, 18, 23, 22, 22, 18, 14, 10, 18, 24, 26, 25, 22, 18, 14, 20, 25, + 30, 28, 25, 21, 16, 22, 28, 33, 31, 27, 23, 18, 25, 31, 34, 34, 29, 25, 19, + 26, 31, 29, 24, 19, 15, 10, 26, 31, 31, 26, 21, 16, 11, 26, 31, 33, 27, 23, + 18, 14, 25, 31, 35, 30, 26, 21, 18, 27, 32, 35, 33, 28, 24, 20, 29, 35, 37, + 36, 31, 27, 22, 32, 34, 36, 37, 31, 28, 23, 2, 2, 3, 3, 3, 2, 2, 1, + 2, 3, 3, 3, 2, 2, 1, 2, 2, 3, 3, 2, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 4, 3, 3, 7, 6, 7, 6, 5, 3, 3, 13, 11, 8, 7, + 5, 3, 3, 1, 2, 2, 3, 2, 2, 2, 1, 2, 2, 3, 2, 2, 1, 2, 2, + 2, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 3, 4, 4, 4, 4, 4, 3, 3, + 9, 8, 8, 7, 5, 4, 3, 16, 14, 10, 8, 6, 4, 3, 2, 1, 2, 2, 2, + 2, 3, 2, 0, 1, 1, 1, 2, 3, 2, 1, 1, 0, 1, 0, 4, 3, 2, 2, + 2, 3, 3, 6, 7, 6, 6, 6, 6, 5, 6, 12, 11, 10, 9, 8, 7, 6, 18, + 17, 13, 11, 9, 8, 7, 2, 4, 4, 4, 5, 4, 8, 3, 5, 5, 5, 6, 6, + 8, 6, 6, 6, 6, 7, 7, 8, 9, 9, 9, 10, 10, 10, 10, 10, 13, 13, 13, + 13, 13, 12, 12, 19, 18, 16, 16, 15, 14, 18, 25, 22, 19, 18, 16, 15, 12, 12, + 12, 12, 12, 12, 8, 14, 14, 13, 13, 14, 12, 8, 13, 15, 15, 15, 15, 14, 11, + 13, 19, 19, 18, 19, 18, 14, 17, 24, 23, 23, 23, 20, 16, 20, 27, 29, 27, 25, + 22, 17, 25, 30, 31, 29, 28, 25, 19, 21, 23, 22, 21, 18, 14, 10, 21, 25, 23, + 23, 20, 15, 11, 20, 26, 27, 26, 22, 17, 13, 21, 27, 28, 28, 25, 21, 17, 24, + 30, 34, 33, 30, 24, 19, 27, 33, 40, 37, 32, 26, 21, 30, 36, 40, 39, 34, 29, + 22, 29, 36, 33, 27, 20, 17, 13, 29, 35, 35, 28, 23, 18, 14, 29, 35, 38, 31, + 25, 20, 16, 29, 34, 42, 35, 30, 25, 21, 31, 37, 43, 40, 34, 29, 22, 33, 40, + 45, 43, 37, 30, 25, 35, 42, 46, 46, 39, 32, 27, 1, 3, 4, 5, 5, 4, 3, + 1, 3, 4, 5, 5, 4, 3, 1, 2, 4, 4, 5, 4, 4, 1, 2, 4, 5, 5, + 5, 6, 4, 4, 6, 7, 7, 6, 6, 8, 8, 10, 10, 8, 7, 6, 14, 12, 11, + 10, 9, 7, 6, 1, 2, 4, 5, 4, 3, 1, 1, 1, 3, 4, 4, 3, 0, 2, + 1, 3, 4, 3, 4, 3, 2, 2, 3, 5, 5, 5, 5, 5, 5, 6, 8, 7, 6, + 5, 10, 10, 10, 11, 8, 6, 5, 18, 15, 11, 10, 8, 7, 5, 2, 1, 1, 1, + 1, 1, 4, 2, 1, 0, 1, 1, 1, 4, 2, 1, 2, 2, 2, 2, 5, 5, 3, + 5, 5, 5, 5, 7, 9, 7, 8, 8, 8, 8, 7, 14, 12, 13, 11, 10, 9, 7, + 20, 18, 15, 14, 12, 10, 9, 2, 5, 6, 6, 6, 5, 8, 6, 6, 6, 7, 7, + 7, 8, 9, 7, 8, 8, 9, 9, 9, 11, 9, 12, 12, 12, 12, 11, 12, 15, 16, + 16, 16, 16, 14, 14, 21, 20, 19, 18, 17, 16, 20, 27, 24, 21, 20, 18, 17, 13, + 13, 13, 14, 14, 13, 8, 15, 15, 14, 15, 15, 14, 8, 15, 17, 17, 17, 17, 16, + 12, 15, 22, 21, 20, 21, 20, 16, 18, 26, 25, 24, 25, 23, 18, 23, 30, 32, 29, + 28, 24, 20, 26, 33, 35, 31, 30, 26, 21, 23, 25, 23, 23, 19, 15, 11, 23, 27, + 25, 24, 20, 16, 12, 23, 28, 27, 28, 24, 19, 16, 22, 30, 32, 31, 28, 23, 19, + 26, 33, 36, 35, 31, 26, 21, 29, 35, 41, 40, 34, 29, 22, 33, 38, 43, 43, 36, + 30, 24, 30, 37, 35, 28, 22, 18, 14, 31, 36, 37, 30, 24, 20, 16, 31, 36, 40, + 33, 28, 22, 19, 30, 38, 44, 38, 31, 27, 23, 33, 39, 45, 42, 36, 31, 25, 35, + 41, 48, 46, 39, 32, 27, 40, 44, 48, 51, 41, 35, 29, 1, 4, 6, 9, 9, 7, + 4, 1, 3, 5, 8, 8, 7, 5, 1, 2, 5, 7, 9, 8, 6, 1, 3, 5, 8, + 10, 8, 8, 5, 5, 7, 9, 11, 10, 8, 9, 9, 11, 12, 11, 9, 8, 15, 14, + 12, 12, 11, 10, 8, 1, 2, 4, 7, 6, 3, 1, 1, 1, 4, 6, 6, 3, 1, + 2, 1, 3, 6, 5, 4, 3, 2, 3, 4, 6, 6, 6, 6, 5, 6, 7, 9, 9, + 7, 6, 11, 11, 11, 12, 9, 8, 6, 19, 16, 13, 12, 9, 8, 6, 2, 1, 1, + 1, 2, 1, 3, 2, 1, 1, 0, 1, 1, 4, 3, 2, 2, 2, 2, 3, 5, 7, + 3, 5, 6, 5, 6, 7, 10, 8, 9, 9, 10, 8, 7, 15, 13, 14, 13, 11, 10, + 7, 21, 20, 17, 15, 13, 11, 10, 3, 5, 6, 6, 6, 4, 7, 8, 6, 7, 7, + 7, 7, 7, 11, 7, 8, 9, 10, 10, 9, 13, 9, 13, 13, 13, 13, 11, 13, 15, + 17, 16, 17, 17, 14, 16, 22, 22, 21, 19, 18, 16, 21, 28, 26, 23, 21, 20, 18, + 14, 14, 14, 14, 14, 13, 7, 16, 15, 15, 15, 15, 14, 7, 16, 17, 17, 18, 18, + 17, 13, 16, 21, 22, 22, 22, 21, 17, 19, 27, 27, 27, 26, 24, 19, 23, 30, 32, + 31, 28, 26, 20, 28, 33, 35, 32, 31, 28, 22, 23, 24, 23, 23, 19, 16, 11, 22, + 27, 25, 24, 21, 17, 13, 23, 30, 28, 28, 24, 21, 17, 23, 31, 33, 32, 28, 24, + 21, 28, 34, 36, 36, 33, 27, 22, 31, 36, 44, 42, 36, 29, 24, 34, 39, 43, 45, + 37, 32, 26, 31, 36, 35, 28, 22, 18, 14, 31, 37, 37, 31, 25, 20, 17, 31, 37, + 41, 33, 29, 25, 19, 31, 38, 45, 39, 33, 28, 24, 35, 39, 46, 44, 36, 32, 26, + 38, 45, 51, 50, 40, 33, 28, 40, 46, 50, 51, 43, 35, 30, 1, 4, 7, 10, 10, + 8, 4, 1, 3, 6, 9, 9, 7, 5, 1, 2, 5, 8, 10, 8, 6, 2, 3, 6, + 8, 11, 9, 8, 5, 6, 8, 10, 12, 10, 8, 10, 10, 12, 12, 12, 10, 8, 16, + 14, 12, 12, 12, 10, 8, 1, 2, 5, 7, 7, 4, 1, 1, 1, 4, 6, 6, 4, + 2, 2, 1, 3, 6, 6, 5, 3, 2, 3, 5, 7, 7, 6, 6, 5, 6, 8, 9, + 9, 7, 6, 12, 11, 12, 12, 9, 8, 6, 19, 17, 13, 12, 10, 8, 6, 2, 1, + 1, 1, 2, 2, 3, 2, 2, 1, 1, 0, 1, 4, 4, 2, 2, 3, 3, 2, 5, + 8, 3, 6, 6, 6, 6, 7, 11, 8, 9, 10, 10, 9, 7, 16, 14, 14, 13, 12, + 10, 7, 21, 20, 17, 15, 13, 12, 11, 4, 5, 6, 6, 6, 4, 7, 8, 6, 7, + 7, 7, 7, 7, 12, 6, 8, 10, 10, 10, 9, 13, 9, 13, 13, 14, 14, 11, 14, + 15, 17, 17, 18, 17, 14, 16, 22, 22, 21, 20, 18, 17, 21, 28, 25, 23, 22, 20, + 19, 15, 14, 14, 14, 14, 13, 7, 17, 15, 15, 15, 15, 14, 7, 16, 17, 17, 19, + 19, 17, 13, 17, 21, 23, 23, 22, 21, 17, 19, 27, 27, 27, 27, 24, 19, 24, 32, + 34, 31, 30, 26, 20, 28, 36, 36, 34, 31, 29, 23, 23, 25, 23, 23, 20, 16, 11, + 23, 27, 25, 24, 22, 17, 14, 23, 29, 28, 28, 24, 20, 17, 23, 31, 34, 33, 29, + 25, 21, 27, 34, 38, 37, 33, 28, 22, 30, 38, 44, 42, 36, 30, 24, 35, 40, 44, + 44, 37, 32, 26, 32, 35, 34, 27, 22, 18, 14, 31, 37, 36, 29, 24, 21, 17, 31, + 36, 38, 33, 29, 24, 21, 32, 39, 43, 38, 33, 28, 24, 35, 42, 46, 44, 37, 32, + 27, 37, 43, 49, 48, 42, 34, 28, 41, 46, 49, 51, 44, 36, 30, 3, 5, 6, 8, + 8, 6, 4, 2, 5, 6, 8, 8, 6, 5, 1, 4, 6, 8, 9, 8, 6, 2, 4, + 7, 9, 11, 9, 8, 4, 6, 8, 10, 12, 10, 8, 10, 10, 12, 12, 12, 10, 8, + 15, 15, 13, 12, 12, 10, 8, 1, 4, 5, 7, 5, 4, 2, 1, 3, 5, 6, 5, + 3, 2, 2, 2, 5, 6, 6, 5, 4, 2, 3, 5, 7, 7, 6, 6, 5, 6, 8, + 10, 9, 7, 6, 12, 11, 12, 12, 10, 8, 6, 19, 16, 14, 12, 10, 8, 6, 2, + 1, 2, 2, 3, 1, 3, 2, 1, 1, 1, 1, 0, 3, 3, 1, 1, 2, 2, 2, + 4, 7, 3, 5, 5, 5, 5, 5, 11, 8, 9, 9, 9, 8, 5, 15, 14, 13, 12, + 11, 9, 5, 21, 18, 16, 14, 12, 11, 9, 2, 5, 5, 5, 5, 4, 6, 7, 6, + 6, 6, 6, 6, 6, 11, 6, 7, 8, 9, 9, 7, 14, 9, 12, 12, 12, 12, 10, + 14, 14, 17, 16, 17, 16, 13, 16, 21, 21, 20, 19, 17, 16, 21, 27, 25, 22, 20, + 18, 18, 14, 13, 13, 13, 13, 13, 6, 16, 15, 14, 14, 14, 13, 6, 17, 16, 16, + 17, 17, 16, 12, 17, 21, 21, 21, 22, 19, 15, 19, 27, 27, 26, 25, 23, 18, 23, + 30, 32, 30, 27, 25, 20, 27, 33, 34, 31, 29, 27, 21, 23, 23, 22, 21, 18, 15, + 10, 23, 26, 23, 22, 19, 16, 12, 23, 28, 26, 25, 23, 19, 16, 23, 29, 32, 29, + 27, 23, 19, 26, 33, 37, 34, 31, 26, 21, 31, 37, 40, 40, 33, 28, 23, 33, 38, + 42, 42, 35, 29, 24, 30, 34, 30, 25, 20, 16, 13, 29, 34, 33, 27, 22, 20, 16, + 30, 34, 36, 30, 26, 23, 19, 29, 36, 40, 34, 30, 27, 23, 33, 39, 43, 41, 35, + 30, 25, 37, 41, 46, 46, 37, 31, 27, 40, 44, 47, 47, 40, 34, 28, 6, 7, 9, + 12, 11, 9, 6, 5, 6, 8, 11, 11, 8, 6, 4, 6, 8, 10, 11, 9, 8, 3, + 6, 9, 10, 13, 11, 9, 5, 7, 9, 11, 14, 12, 9, 9, 10, 11, 12, 14, 12, + 9, 15, 14, 12, 12, 13, 12, 9, 4, 6, 7, 9, 8, 6, 4, 3, 6, 7, 8, + 7, 5, 3, 1, 5, 7, 8, 7, 6, 5, 1, 4, 8, 9, 8, 8, 6, 5, 7, + 9, 10, 9, 9, 6, 11, 11, 12, 12, 10, 8, 6, 18, 16, 13, 12, 10, 8, 6, + 1, 5, 5, 4, 5, 4, 2, 1, 3, 4, 4, 4, 3, 0, 1, 2, 4, 4, 3, + 3, 2, 2, 3, 5, 5, 4, 4, 4, 7, 8, 8, 7, 8, 6, 4, 14, 13, 12, + 10, 8, 7, 4, 20, 17, 14, 11, 9, 7, 5, 1, 2, 2, 2, 2, 3, 5, 2, + 3, 2, 2, 3, 3, 3, 7, 4, 4, 5, 5, 5, 4, 10, 7, 8, 8, 8, 8, + 6, 10, 13, 12, 12, 12, 11, 9, 14, 19, 17, 15, 14, 13, 11, 19, 23, 20, 17, + 15, 14, 13, 11, 10, 9, 9, 10, 9, 5, 13, 12, 11, 10, 11, 9, 3, 13, 13, + 13, 14, 13, 11, 8, 13, 18, 17, 16, 17, 15, 12, 16, 23, 22, 21, 21, 18, 13, + 20, 26, 27, 25, 22, 20, 15, 23, 28, 31, 26, 24, 22, 16, 19, 19, 17, 16, 15, + 11, 8, 19, 22, 18, 17, 15, 11, 8, 19, 23, 21, 20, 17, 14, 12, 20, 25, 25, + 24, 22, 18, 15, 22, 28, 31, 28, 25, 22, 17, 27, 31, 36, 33, 27, 23, 19, 29, + 34, 38, 35, 29, 25, 20, 25, 27, 25, 19, 16, 13, 10, 25, 27, 27, 20, 17, 14, + 11, 25, 28, 29, 24, 21, 18, 15, 25, 29, 34, 29, 25, 21, 18, 28, 33, 36, 34, + 30, 24, 20, 31, 35, 40, 38, 32, 26, 21, 35, 38, 41, 41, 34, 28, 23, 3, 7, + 12, 15, 16, 14, 11, 2, 5, 10, 14, 15, 14, 8, 2, 4, 8, 11, 13, 11, 6, + 2, 2, 5, 8, 10, 10, 5, 2, 2, 3, 6, 8, 9, 5, 5, 6, 6, 5, 7, + 9, 5, 12, 11, 8, 4, 7, 9, 5, 2, 4, 8, 12, 13, 11, 5, 2, 3, 7, + 10, 12, 9, 3, 2, 2, 5, 7, 8, 6, 2, 1, 2, 2, 4, 5, 3, 2, 2, + 3, 3, 3, 3, 3, 2, 7, 7, 7, 6, 3, 2, 2, 15, 13, 9, 7, 4, 3, + 2, 2, 2, 3, 5, 6, 4, 2, 1, 2, 2, 3, 4, 3, 1, 0, 2, 2, 2, + 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 3, 2, 10, 9, + 9, 8, 5, 3, 2, 17, 16, 12, 9, 6, 4, 2, 0, 1, 1, 1, 2, 2, 4, + 1, 1, 1, 1, 1, 1, 5, 1, 2, 2, 3, 3, 3, 5, 4, 4, 5, 5, 5, + 6, 7, 5, 9, 8, 9, 9, 8, 7, 11, 14, 13, 13, 11, 10, 9, 17, 20, 17, + 15, 13, 12, 11, 8, 8, 8, 9, 9, 8, 5, 10, 10, 9, 10, 10, 9, 5, 10, + 11, 11, 11, 12, 11, 6, 10, 14, 13, 14, 14, 13, 9, 12, 18, 18, 18, 18, 17, + 11, 16, 21, 22, 21, 20, 19, 13, 19, 24, 24, 22, 21, 20, 16, 17, 18, 18, 18, + 15, 11, 7, 17, 20, 19, 19, 16, 12, 7, 17, 22, 22, 21, 19, 14, 9, 17, 22, + 23, 22, 20, 17, 13, 18, 24, 26, 24, 23, 20, 15, 21, 26, 29, 28, 24, 21, 17, + 23, 28, 30, 29, 26, 22, 18, 25, 28, 26, 22, 19, 14, 9, 24, 28, 28, 24, 20, + 16, 10, 24, 29, 31, 24, 21, 17, 13, 24, 29, 31, 26, 23, 20, 17, 25, 28, 32, + 30, 25, 22, 18, 27, 29, 33, 32, 27, 23, 20, 28, 31, 33, 34, 29, 24, 21, 2, + 2, 3, 5, 5, 3, 2, 2, 2, 3, 4, 5, 2, 2, 2, 2, 2, 3, 3, 2, + 1, 0, 2, 2, 2, 3, 2, 3, 2, 2, 3, 3, 4, 3, 3, 6, 6, 7, 6, + 4, 3, 3, 12, 11, 8, 6, 5, 3, 3, 1, 2, 3, 3, 3, 2, 2, 1, 2, + 2, 3, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 1, 3, + 4, 3, 4, 4, 4, 3, 3, 9, 8, 8, 7, 5, 3, 3, 16, 13, 10, 8, 5, + 4, 3, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 1, + 1, 1, 1, 3, 2, 2, 2, 1, 2, 2, 5, 6, 5, 5, 5, 5, 4, 5, 12, + 10, 10, 8, 7, 5, 5, 18, 17, 12, 10, 8, 7, 6, 2, 3, 3, 3, 4, 4, + 7, 2, 4, 4, 5, 5, 5, 8, 5, 5, 5, 5, 6, 6, 7, 8, 8, 8, 8, + 9, 9, 9, 9, 13, 12, 12, 13, 12, 11, 12, 18, 16, 16, 15, 13, 12, 18, 23, + 20, 18, 17, 15, 14, 11, 11, 11, 11, 11, 11, 7, 12, 13, 12, 13, 13, 12, 7, + 12, 14, 14, 14, 14, 13, 9, 13, 18, 17, 17, 18, 16, 13, 16, 22, 22, 21, 22, + 19, 14, 19, 26, 27, 26, 24, 22, 16, 24, 29, 31, 28, 26, 23, 18, 19, 21, 20, + 20, 17, 13, 9, 20, 23, 22, 23, 19, 14, 10, 20, 25, 25, 24, 20, 16, 12, 20, + 26, 28, 28, 24, 20, 16, 23, 28, 32, 32, 29, 23, 18, 26, 32, 37, 37, 31, 25, + 20, 28, 34, 39, 39, 33, 28, 22, 28, 34, 32, 26, 20, 16, 12, 28, 34, 34, 27, + 22, 17, 13, 27, 34, 38, 30, 24, 20, 16, 28, 34, 39, 34, 28, 23, 20, 30, 36, + 41, 39, 32, 28, 22, 32, 38, 44, 41, 36, 30, 24, 34, 40, 45, 43, 38, 31, 25, + 2, 4, 5, 6, 6, 5, 4, 1, 4, 5, 6, 6, 5, 4, 0, 3, 5, 5, 5, + 4, 4, 1, 2, 4, 5, 5, 5, 6, 3, 4, 6, 6, 7, 6, 6, 8, 8, 9, + 9, 8, 6, 6, 13, 12, 11, 9, 8, 6, 6, 0, 3, 5, 5, 5, 4, 2, 1, + 2, 4, 5, 5, 4, 2, 1, 1, 4, 4, 4, 3, 2, 2, 2, 3, 5, 4, 5, + 5, 5, 4, 6, 7, 7, 6, 5, 9, 9, 10, 10, 8, 6, 5, 17, 14, 11, 10, + 8, 6, 5, 1, 1, 2, 3, 3, 1, 4, 2, 1, 2, 2, 2, 1, 4, 2, 1, + 0, 0, 0, 0, 5, 4, 2, 3, 3, 3, 3, 6, 8, 6, 7, 7, 7, 6, 6, + 13, 11, 11, 10, 9, 7, 6, 19, 18, 14, 12, 10, 9, 8, 2, 4, 5, 5, 5, + 5, 7, 4, 5, 5, 6, 6, 6, 8, 8, 6, 7, 7, 7, 8, 8, 10, 9, 10, + 10, 11, 11, 10, 11, 14, 14, 15, 15, 14, 13, 13, 20, 19, 18, 17, 15, 15, 19, + 26, 22, 20, 18, 17, 16, 12, 13, 12, 13, 13, 12, 7, 13, 14, 14, 14, 14, 13, + 8, 14, 16, 16, 16, 16, 15, 11, 13, 20, 19, 19, 20, 18, 15, 18, 25, 24, 24, + 24, 21, 16, 22, 28, 30, 28, 26, 23, 18, 26, 31, 33, 29, 28, 25, 20, 22, 23, + 22, 22, 18, 14, 10, 22, 25, 24, 24, 20, 16, 12, 22, 27, 26, 26, 23, 18, 14, + 21, 29, 30, 29, 26, 22, 18, 26, 31, 36, 34, 30, 25, 20, 27, 34, 39, 38, 33, + 27, 21, 31, 37, 41, 41, 34, 28, 23, 29, 35, 34, 27, 22, 17, 13, 29, 36, 36, + 29, 24, 19, 14, 29, 36, 39, 32, 26, 22, 17, 30, 36, 42, 35, 30, 26, 22, 31, + 38, 44, 41, 33, 29, 24, 34, 40, 47, 47, 38, 30, 26, 37, 43, 47, 47, 39, 33, + 27, 2, 6, 9, 11, 11, 10, 7, 2, 5, 8, 11, 11, 9, 6, 0, 3, 7, 9, + 10, 7, 6, 1, 2, 5, 7, 9, 8, 7, 3, 4, 6, 8, 10, 9, 7, 7, 8, + 10, 10, 10, 9, 7, 14, 13, 11, 10, 10, 9, 7, 0, 3, 7, 10, 9, 6, 3, + 1, 2, 5, 8, 9, 6, 2, 1, 1, 4, 6, 6, 4, 2, 2, 2, 4, 6, 6, + 5, 4, 4, 5, 6, 8, 7, 6, 4, 10, 9, 10, 10, 8, 6, 4, 17, 14, 11, + 11, 8, 6, 4, 1, 1, 2, 3, 4, 3, 5, 2, 0, 2, 2, 3, 2, 4, 2, + 1, 0, 0, 0, 0, 3, 4, 2, 3, 3, 3, 3, 5, 8, 6, 7, 7, 7, 6, + 5, 13, 11, 11, 10, 9, 7, 5, 19, 17, 14, 12, 10, 9, 8, 2, 4, 5, 5, + 6, 6, 8, 5, 5, 6, 6, 7, 7, 7, 10, 6, 7, 7, 7, 7, 7, 11, 9, + 10, 11, 11, 10, 9, 12, 14, 14, 15, 14, 14, 12, 13, 20, 19, 18, 17, 16, 14, + 19, 26, 23, 21, 18, 17, 16, 12, 13, 12, 13, 14, 13, 8, 15, 14, 14, 15, 15, + 14, 7, 14, 16, 16, 16, 15, 14, 11, 14, 20, 19, 19, 20, 17, 14, 17, 25, 24, + 23, 24, 21, 16, 21, 28, 30, 28, 26, 23, 18, 25, 31, 33, 30, 27, 25, 20, 22, + 24, 22, 22, 19, 16, 12, 21, 26, 24, 24, 20, 16, 12, 22, 28, 26, 26, 21, 18, + 14, 22, 29, 30, 30, 26, 22, 18, 25, 33, 36, 34, 30, 25, 19, 28, 34, 41, 38, + 33, 27, 22, 31, 37, 42, 41, 36, 29, 23, 30, 35, 34, 28, 23, 18, 14, 29, 36, + 36, 30, 23, 19, 14, 30, 35, 38, 32, 26, 21, 17, 29, 37, 41, 35, 31, 25, 21, + 32, 39, 45, 39, 34, 29, 23, 34, 41, 47, 46, 38, 31, 26, 37, 43, 47, 46, 40, + 33, 27, 3, 6, 9, 13, 13, 10, 7, 2, 5, 8, 12, 12, 9, 6, 0, 4, 7, + 10, 11, 8, 6, 1, 3, 5, 8, 10, 9, 7, 4, 4, 6, 8, 11, 9, 7, 7, + 8, 10, 10, 10, 9, 7, 13, 12, 10, 10, 10, 9, 7, 1, 4, 7, 10, 10, 7, + 3, 1, 2, 6, 9, 9, 6, 2, 1, 1, 5, 7, 7, 4, 2, 1, 2, 4, 6, + 6, 5, 4, 4, 5, 6, 8, 7, 5, 4, 10, 9, 10, 10, 7, 6, 4, 16, 14, + 11, 10, 8, 6, 4, 1, 1, 3, 4, 5, 3, 4, 1, 1, 2, 2, 3, 2, 3, + 2, 1, 0, 0, 0, 1, 3, 4, 2, 3, 3, 3, 3, 4, 8, 6, 7, 7, 7, + 6, 4, 13, 12, 11, 10, 9, 7, 4, 19, 17, 14, 12, 10, 9, 8, 1, 5, 5, + 5, 6, 6, 8, 5, 6, 6, 6, 7, 7, 7, 9, 6, 7, 7, 7, 7, 6, 11, + 8, 11, 11, 10, 11, 8, 12, 14, 15, 15, 15, 14, 12, 13, 19, 19, 18, 17, 15, + 14, 19, 26, 23, 20, 19, 17, 16, 12, 13, 13, 13, 14, 13, 8, 14, 15, 14, 14, + 15, 13, 7, 15, 16, 16, 16, 16, 14, 11, 14, 20, 20, 20, 20, 18, 14, 17, 25, + 25, 24, 23, 21, 16, 22, 29, 30, 28, 26, 23, 18, 26, 32, 33, 31, 28, 25, 20, + 22, 23, 23, 23, 20, 16, 11, 22, 26, 24, 24, 21, 16, 12, 23, 29, 27, 26, 22, + 17, 14, 23, 29, 31, 29, 26, 22, 18, 25, 32, 37, 34, 30, 25, 19, 28, 35, 41, + 38, 33, 27, 22, 31, 36, 41, 40, 34, 30, 23, 31, 35, 33, 27, 22, 18, 14, 30, + 36, 36, 29, 23, 18, 14, 29, 36, 38, 31, 25, 21, 17, 31, 36, 40, 35, 30, 26, + 22, 32, 38, 43, 40, 34, 29, 23, 36, 41, 45, 45, 37, 31, 25, 37, 43, 46, 46, + 40, 34, 27, 3, 6, 8, 9, 9, 7, 5, 2, 6, 7, 9, 9, 6, 4, 1, 4, + 6, 8, 8, 6, 5, 1, 3, 5, 7, 9, 8, 6, 4, 4, 7, 8, 11, 9, 6, + 8, 8, 10, 10, 10, 9, 6, 13, 12, 10, 10, 10, 9, 6, 0, 4, 6, 8, 7, + 5, 3, 1, 3, 5, 7, 6, 4, 2, 1, 1, 5, 6, 4, 3, 2, 2, 2, 4, + 6, 5, 5, 4, 5, 5, 6, 8, 7, 6, 4, 10, 9, 10, 10, 7, 6, 4, 16, + 13, 11, 10, 8, 6, 4, 1, 1, 3, 3, 4, 3, 5, 2, 1, 2, 3, 3, 2, + 3, 2, 1, 0, 0, 0, 0, 2, 4, 2, 3, 3, 3, 3, 4, 9, 7, 7, 7, + 7, 6, 4, 14, 11, 11, 10, 9, 7, 4, 18, 16, 13, 11, 10, 9, 8, 2, 5, + 5, 6, 6, 6, 8, 5, 6, 6, 6, 7, 7, 6, 9, 6, 7, 7, 8, 7, 6, + 11, 8, 11, 11, 10, 11, 8, 12, 14, 15, 14, 15, 14, 11, 13, 20, 19, 18, 16, + 16, 14, 18, 25, 22, 20, 18, 17, 16, 13, 13, 13, 13, 14, 13, 8, 15, 15, 14, + 15, 15, 13, 7, 15, 16, 16, 16, 16, 14, 10, 15, 20, 20, 20, 20, 18, 15, 18, + 25, 24, 23, 24, 21, 16, 22, 28, 29, 28, 26, 23, 18, 25, 30, 32, 29, 28, 25, + 20, 23, 24, 23, 22, 19, 16, 11, 23, 26, 24, 22, 20, 16, 11, 23, 28, 26, 24, + 21, 18, 14, 22, 29, 31, 28, 25, 22, 18, 25, 31, 35, 34, 29, 24, 19, 28, 33, + 39, 37, 31, 26, 22, 31, 35, 41, 39, 33, 27, 23, 29, 34, 32, 26, 22, 18, 14, + 30, 34, 33, 27, 22, 18, 14, 29, 33, 36, 29, 24, 21, 17, 29, 34, 39, 34, 29, + 26, 21, 32, 37, 42, 38, 34, 27, 23, 34, 40, 44, 44, 35, 29, 25, 37, 41, 45, + 45, 37, 31, 27, 7, 9, 11, 13, 13, 11, 8, 6, 8, 10, 12, 13, 10, 6, 5, + 7, 9, 11, 11, 8, 6, 3, 6, 7, 10, 12, 10, 8, 4, 6, 8, 10, 13, 10, + 8, 7, 8, 9, 10, 12, 10, 7, 11, 10, 9, 9, 11, 11, 8, 5, 7, 9, 11, + 10, 7, 5, 4, 6, 8, 10, 9, 6, 4, 1, 6, 7, 9, 7, 5, 3, 0, 4, + 6, 8, 7, 6, 5, 4, 5, 7, 8, 8, 7, 5, 9, 8, 9, 10, 7, 7, 5, + 13, 11, 10, 9, 8, 6, 5, 2, 6, 6, 6, 6, 5, 4, 0, 4, 5, 5, 5, + 4, 2, 1, 3, 5, 3, 3, 3, 0, 1, 2, 3, 3, 3, 3, 2, 6, 6, 6, + 5, 5, 4, 2, 12, 10, 8, 8, 6, 4, 2, 15, 13, 10, 8, 6, 5, 3, 1, + 2, 3, 3, 4, 5, 6, 1, 3, 3, 4, 4, 4, 5, 4, 5, 4, 4, 4, 4, + 4, 7, 7, 7, 6, 6, 6, 5, 8, 12, 11, 10, 10, 9, 8, 12, 16, 14, 13, + 12, 11, 10, 15, 20, 16, 14, 14, 12, 11, 11, 10, 10, 10, 11, 10, 6, 12, 12, + 11, 11, 12, 10, 5, 12, 14, 13, 12, 12, 10, 7, 12, 17, 15, 15, 15, 13, 10, + 15, 22, 20, 19, 18, 16, 12, 19, 23, 25, 22, 20, 18, 13, 20, 25, 27, 24, 22, + 19, 15, 19, 19, 18, 17, 15, 12, 9, 19, 22, 19, 18, 16, 12, 8, 19, 23, 21, + 19, 16, 13, 10, 19, 23, 24, 22, 19, 17, 13, 21, 27, 29, 27, 23, 20, 15, 24, + 28, 34, 29, 25, 20, 17, 26, 30, 34, 34, 27, 23, 18, 25, 28, 26, 20, 17, 14, + 11, 25, 28, 28, 22, 18, 14, 11, 25, 28, 30, 23, 19, 16, 12, 25, 29, 32, 27, + 23, 19, 16, 27, 31, 36, 33, 27, 22, 18, 29, 33, 38, 36, 29, 24, 20, 30, 36, + 38, 38, 32, 26, 21, 6, 10, 15, 18, 18, 17, 15, 5, 9, 13, 16, 17, 15, 12, + 3, 7, 11, 14, 15, 13, 10, 2, 5, 8, 11, 13, 13, 9, 2, 2, 6, 9, 11, + 13, 10, 5, 5, 5, 8, 11, 13, 10, 11, 10, 6, 6, 10, 13, 9, 3, 7, 12, + 15, 15, 13, 10, 2, 6, 10, 13, 15, 13, 7, 2, 4, 8, 11, 12, 10, 4, 2, + 2, 5, 8, 8, 8, 3, 2, 3, 3, 6, 7, 7, 3, 7, 7, 6, 5, 5, 6, + 3, 14, 12, 9, 5, 4, 4, 3, 2, 4, 7, 9, 10, 9, 4, 2, 3, 5, 7, + 8, 7, 2, 1, 2, 4, 5, 4, 4, 1, 0, 2, 1, 1, 2, 1, 2, 4, 4, + 4, 4, 4, 3, 2, 10, 10, 9, 8, 6, 3, 2, 16, 15, 11, 9, 7, 4, 2, + 1, 1, 1, 2, 2, 3, 3, 0, 1, 1, 1, 1, 1, 4, 1, 1, 2, 2, 2, + 2, 4, 3, 3, 3, 4, 4, 4, 5, 5, 8, 7, 8, 8, 7, 6, 10, 13, 12, + 12, 10, 9, 8, 16, 18, 15, 13, 12, 11, 10, 7, 7, 8, 8, 9, 7, 3, 9, + 9, 9, 10, 9, 8, 4, 9, 10, 11, 11, 11, 10, 5, 9, 13, 13, 13, 13, 12, + 8, 11, 16, 16, 16, 15, 15, 10, 14, 19, 19, 18, 17, 16, 12, 18, 21, 21, 19, + 18, 17, 14, 16, 16, 16, 16, 14, 11, 6, 16, 19, 17, 17, 15, 12, 7, 16, 20, + 19, 18, 16, 13, 8, 15, 20, 20, 19, 17, 15, 12, 17, 21, 23, 21, 19, 17, 14, + 19, 22, 25, 24, 21, 18, 15, 21, 23, 27, 25, 22, 18, 16, 21, 25, 23, 19, 17, + 14, 9, 21, 25, 26, 20, 17, 15, 10, 22, 25, 27, 21, 18, 15, 12, 21, 24, 28, + 22, 18, 17, 15, 20, 25, 29, 26, 21, 19, 16, 22, 26, 29, 28, 23, 20, 17, 24, + 27, 30, 30, 24, 21, 18, 3, 3, 5, 8, 8, 6, 3, 2, 3, 4, 7, 8, 5, + 3, 2, 3, 4, 5, 6, 4, 2, 2, 2, 3, 3, 4, 2, 2, 1, 2, 2, 2, + 3, 2, 2, 5, 5, 5, 4, 3, 2, 2, 11, 9, 7, 5, 3, 2, 2, 2, 3, + 4, 6, 5, 4, 3, 2, 3, 4, 5, 5, 3, 2, 1, 2, 3, 3, 3, 3, 2, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 7, 6, 7, 6, 3, + 2, 2, 14, 12, 8, 6, 4, 2, 2, 1, 2, 3, 3, 3, 3, 3, 1, 2, 3, + 3, 3, 3, 3, 1, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 2, 4, + 4, 3, 3, 4, 2, 3, 10, 9, 8, 7, 5, 3, 3, 17, 15, 11, 8, 6, 5, + 4, 2, 3, 3, 4, 4, 4, 7, 2, 4, 4, 5, 5, 5, 8, 3, 5, 5, 6, + 6, 6, 8, 5, 6, 6, 6, 7, 7, 8, 6, 10, 10, 10, 10, 10, 9, 10, 16, + 15, 14, 13, 11, 11, 16, 21, 18, 16, 14, 13, 12, 10, 11, 11, 11, 12, 11, 7, + 11, 12, 12, 12, 13, 12, 8, 12, 13, 14, 14, 14, 13, 9, 12, 16, 16, 15, 15, + 15, 11, 14, 20, 19, 19, 19, 17, 12, 17, 23, 25, 24, 22, 20, 14, 20, 27, 29, + 26, 24, 22, 16, 19, 21, 21, 20, 18, 14, 9, 20, 23, 23, 23, 19, 14, 10, 19, + 25, 25, 24, 21, 16, 11, 19, 24, 26, 26, 22, 18, 14, 21, 26, 31, 29, 27, 21, + 16, 23, 29, 34, 34, 28, 24, 17, 26, 31, 35, 34, 31, 25, 20, 28, 34, 32, 26, + 22, 17, 12, 27, 34, 34, 28, 23, 18, 13, 27, 33, 37, 30, 24, 19, 14, 28, 33, + 38, 31, 26, 22, 18, 27, 34, 39, 36, 30, 25, 19, 29, 36, 39, 39, 33, 27, 22, + 33, 37, 39, 41, 34, 30, 24, 5, 8, 9, 10, 10, 9, 8, 4, 7, 9, 10, 9, + 8, 7, 3, 6, 8, 8, 8, 7, 5, 2, 4, 6, 6, 7, 5, 4, 1, 2, 4, + 5, 5, 5, 4, 5, 5, 7, 6, 5, 5, 4, 10, 10, 8, 7, 6, 5, 4, 3, + 6, 8, 9, 8, 8, 6, 2, 5, 7, 9, 8, 7, 5, 1, 4, 7, 7, 7, 6, + 4, 1, 2, 4, 5, 5, 4, 3, 2, 2, 4, 5, 4, 4, 3, 7, 6, 8, 7, + 5, 4, 3, 14, 11, 9, 8, 5, 4, 3, 2, 4, 6, 6, 7, 5, 6, 1, 2, + 5, 5, 6, 5, 5, 1, 2, 3, 3, 3, 3, 3, 1, 1, 0, 0, 0, 0, 3, + 5, 4, 3, 3, 3, 3, 3, 10, 9, 8, 7, 5, 4, 3, 16, 15, 11, 8, 7, + 6, 5, 1, 4, 5, 5, 6, 6, 9, 2, 5, 5, 6, 7, 7, 8, 4, 6, 6, + 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 11, 11, 11, 11, 10, 10, 10, + 17, 16, 14, 13, 12, 11, 16, 22, 19, 17, 15, 14, 13, 11, 12, 12, 12, 13, 12, + 8, 12, 13, 14, 14, 14, 13, 8, 12, 15, 15, 15, 15, 13, 9, 12, 17, 16, 16, + 16, 15, 11, 15, 21, 21, 20, 20, 18, 13, 18, 25, 26, 25, 22, 19, 14, 23, 27, + 29, 26, 25, 22, 16, 21, 22, 22, 22, 19, 15, 11, 21, 25, 24, 24, 20, 15, 11, + 21, 26, 25, 25, 20, 16, 12, 21, 26, 27, 26, 23, 18, 14, 21, 28, 31, 31, 27, + 21, 16, 24, 30, 37, 35, 29, 23, 18, 28, 33, 37, 38, 31, 25, 20, 29, 33, 34, + 27, 22, 18, 13, 28, 36, 36, 29, 23, 18, 14, 28, 35, 38, 30, 24, 19, 14, 28, + 34, 39, 32, 26, 22, 18, 29, 35, 42, 38, 32, 26, 20, 31, 37, 43, 41, 34, 27, + 22, 33, 39, 44, 44, 37, 30, 23, 5, 9, 12, 15, 15, 13, 10, 4, 8, 11, 14, + 15, 12, 9, 3, 6, 10, 13, 13, 10, 7, 2, 4, 7, 10, 11, 8, 7, 1, 2, + 5, 8, 10, 9, 7, 5, 5, 7, 8, 9, 8, 7, 10, 10, 8, 8, 8, 8, 7, + 3, 7, 10, 13, 12, 10, 7, 2, 5, 9, 12, 12, 9, 5, 1, 4, 8, 10, 10, + 7, 4, 1, 2, 5, 7, 7, 5, 3, 3, 2, 4, 6, 6, 6, 3, 7, 6, 8, + 8, 6, 5, 3, 13, 12, 9, 8, 6, 4, 3, 1, 4, 6, 7, 8, 6, 6, 1, + 2, 5, 6, 6, 5, 4, 1, 1, 3, 3, 3, 3, 3, 1, 1, 0, 0, 0, 0, + 3, 5, 4, 3, 3, 3, 3, 3, 10, 8, 8, 7, 5, 4, 3, 16, 14, 11, 9, + 7, 5, 5, 1, 4, 5, 5, 6, 7, 8, 1, 5, 6, 6, 7, 7, 7, 5, 6, + 6, 6, 6, 7, 7, 8, 7, 7, 7, 7, 7, 6, 9, 11, 11, 11, 11, 11, 9, + 11, 17, 16, 15, 13, 12, 11, 16, 22, 19, 17, 15, 14, 12, 11, 12, 12, 13, 14, + 13, 9, 12, 14, 13, 14, 15, 13, 8, 12, 15, 15, 14, 15, 13, 9, 12, 17, 16, + 16, 16, 15, 11, 15, 22, 20, 20, 20, 18, 12, 18, 25, 27, 25, 22, 19, 14, 23, + 28, 29, 27, 25, 22, 16, 21, 22, 22, 22, 19, 15, 11, 21, 24, 24, 24, 20, 15, + 11, 21, 26, 26, 25, 20, 16, 11, 21, 26, 28, 26, 22, 18, 15, 22, 27, 31, 30, + 26, 21, 16, 25, 31, 37, 35, 29, 23, 18, 28, 33, 37, 37, 32, 25, 20, 29, 35, + 33, 27, 22, 18, 14, 29, 36, 36, 30, 23, 19, 14, 30, 35, 38, 30, 24, 19, 14, + 29, 35, 40, 33, 27, 22, 18, 28, 35, 40, 38, 31, 25, 20, 31, 37, 43, 40, 34, + 27, 22, 33, 40, 44, 43, 37, 29, 23, 6, 9, 13, 16, 16, 14, 10, 5, 8, 11, + 15, 15, 12, 9, 3, 6, 10, 13, 14, 11, 7, 2, 4, 7, 10, 12, 9, 6, 1, + 3, 5, 8, 11, 9, 6, 5, 6, 7, 8, 10, 9, 6, 10, 9, 8, 8, 9, 9, + 6, 3, 7, 10, 13, 13, 10, 7, 2, 6, 9, 12, 12, 9, 5, 1, 4, 8, 10, + 10, 7, 3, 1, 2, 5, 7, 7, 5, 2, 3, 2, 4, 6, 6, 5, 2, 7, 6, + 8, 8, 5, 5, 2, 13, 10, 9, 8, 6, 4, 3, 1, 4, 6, 7, 8, 6, 6, + 1, 3, 5, 6, 6, 5, 4, 1, 2, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, + 0, 3, 5, 4, 4, 4, 4, 3, 3, 11, 9, 8, 7, 6, 4, 3, 15, 13, 10, + 9, 7, 6, 5, 1, 5, 5, 6, 6, 7, 9, 2, 6, 6, 6, 7, 7, 7, 5, + 6, 7, 7, 7, 7, 6, 8, 7, 8, 7, 7, 7, 6, 9, 11, 12, 11, 12, 10, + 9, 11, 17, 16, 15, 13, 12, 11, 15, 21, 19, 17, 15, 14, 13, 11, 13, 13, 13, + 14, 13, 9, 12, 14, 14, 14, 15, 13, 8, 12, 16, 15, 15, 15, 13, 10, 13, 18, + 17, 17, 16, 15, 11, 14, 22, 21, 21, 21, 18, 13, 19, 26, 27, 25, 22, 20, 15, + 22, 27, 29, 27, 25, 22, 16, 21, 24, 22, 22, 19, 16, 11, 22, 26, 25, 24, 21, + 16, 11, 21, 28, 26, 25, 20, 16, 12, 21, 27, 27, 27, 23, 19, 15, 23, 28, 34, + 31, 27, 22, 16, 25, 31, 37, 35, 28, 24, 18, 28, 33, 37, 37, 32, 26, 19, 31, + 35, 33, 29, 22, 18, 14, 30, 36, 36, 30, 23, 18, 15, 29, 35, 37, 31, 24, 20, + 14, 31, 36, 39, 33, 28, 22, 18, 29, 35, 40, 37, 32, 26, 20, 31, 38, 42, 41, + 34, 27, 22, 34, 39, 44, 43, 37, 31, 24, 6, 9, 12, 16, 16, 13, 11, 5, 8, + 12, 15, 16, 12, 9, 3, 7, 10, 13, 14, 11, 7, 2, 5, 8, 10, 13, 9, 6, + 1, 3, 6, 8, 12, 10, 7, 5, 5, 7, 8, 11, 10, 6, 8, 7, 7, 7, 9, + 9, 7, 3, 7, 10, 13, 13, 10, 7, 2, 6, 9, 12, 12, 9, 5, 1, 4, 8, + 10, 10, 7, 3, 1, 2, 5, 7, 7, 5, 3, 3, 2, 4, 6, 6, 5, 3, 7, + 6, 7, 7, 5, 5, 3, 11, 8, 7, 7, 5, 4, 3, 2, 5, 6, 7, 8, 6, + 6, 1, 3, 5, 6, 6, 5, 4, 1, 2, 4, 3, 3, 3, 3, 2, 1, 0, 0, + 0, 0, 2, 6, 4, 4, 4, 4, 3, 2, 9, 8, 6, 6, 5, 4, 2, 13, 10, + 8, 7, 7, 6, 5, 1, 5, 5, 6, 6, 7, 9, 2, 6, 6, 7, 7, 7, 7, + 6, 6, 7, 7, 7, 7, 6, 8, 7, 8, 8, 7, 8, 6, 9, 12, 12, 11, 11, + 10, 9, 10, 15, 15, 14, 13, 12, 11, 12, 18, 17, 15, 14, 14, 13, 12, 13, 13, + 13, 14, 13, 9, 13, 14, 14, 15, 15, 13, 7, 13, 16, 16, 15, 15, 13, 10, 13, + 18, 17, 16, 17, 15, 11, 15, 23, 21, 21, 20, 18, 13, 18, 24, 26, 24, 22, 20, + 14, 20, 25, 28, 25, 23, 22, 16, 22, 24, 22, 21, 19, 15, 11, 22, 25, 24, 23, + 20, 16, 12, 22, 28, 26, 24, 20, 16, 12, 22, 26, 27, 25, 22, 19, 15, 23, 29, + 33, 30, 25, 22, 16, 25, 30, 35, 33, 28, 23, 18, 26, 31, 36, 36, 30, 25, 20, + 30, 34, 31, 26, 22, 18, 14, 30, 33, 33, 28, 22, 19, 14, 29, 33, 35, 28, 23, + 19, 15, 29, 34, 37, 30, 26, 22, 18, 29, 34, 39, 36, 29, 24, 21, 31, 36, 40, + 39, 32, 27, 21, 32, 37, 40, 40, 33, 27, 23, 8, 11, 13, 15, 15, 13, 10, 7, + 10, 12, 15, 15, 12, 8, 6, 8, 11, 13, 14, 10, 7, 5, 7, 9, 10, 12, 9, + 6, 2, 5, 7, 9, 12, 9, 6, 3, 5, 6, 8, 11, 9, 6, 4, 5, 6, 8, + 10, 9, 6, 6, 8, 11, 13, 12, 10, 7, 6, 8, 10, 12, 12, 8, 5, 4, 7, + 9, 10, 9, 7, 4, 2, 5, 7, 8, 7, 5, 3, 1, 3, 6, 7, 6, 5, 3, + 3, 4, 5, 6, 6, 5, 3, 6, 5, 5, 6, 5, 4, 3, 4, 7, 7, 7, 8, + 7, 6, 2, 6, 7, 7, 6, 5, 4, 1, 5, 5, 5, 4, 4, 2, 2, 2, 3, + 3, 3, 2, 0, 3, 3, 2, 2, 2, 1, 0, 5, 4, 3, 2, 3, 1, 0, 9, + 5, 4, 3, 2, 2, 2, 2, 4, 4, 5, 6, 8, 8, 1, 5, 4, 5, 6, 5, + 6, 1, 6, 5, 5, 5, 5, 5, 6, 6, 5, 5, 5, 5, 4, 5, 8, 7, 7, + 7, 7, 6, 6, 10, 9, 8, 8, 8, 7, 9, 14, 12, 10, 10, 9, 9, 11, 11, + 11, 11, 12, 11, 8, 12, 13, 12, 12, 12, 11, 6, 12, 14, 14, 13, 12, 11, 7, + 12, 16, 14, 13, 13, 12, 8, 13, 18, 16, 16, 15, 14, 9, 14, 19, 20, 18, 16, + 14, 10, 15, 20, 22, 21, 18, 16, 12, 19, 21, 18, 18, 16, 13, 9, 19, 22, 20, + 19, 17, 13, 9, 20, 24, 22, 20, 16, 13, 10, 20, 24, 23, 21, 17, 15, 11, 19, + 24, 26, 24, 21, 16, 12, 20, 24, 30, 27, 23, 17, 14, 21, 26, 29, 30, 25, 19, + 14, 26, 30, 27, 22, 18, 14, 12, 26, 30, 30, 23, 18, 15, 12, 26, 30, 32, 24, + 19, 16, 12, 26, 30, 33, 26, 21, 16, 14, 25, 29, 34, 30, 24, 19, 15, 25, 30, + 35, 34, 27, 21, 16, 27, 32, 36, 35, 29, 23, 17, 9, 13, 17, 22, 21, 18, 16, + 8, 12, 16, 20, 21, 18, 15, 7, 10, 14, 18, 20, 17, 13, 6, 9, 12, 15, 17, + 15, 11, 4, 5, 8, 11, 13, 14, 12, 2, 3, 6, 10, 12, 14, 12, 7, 5, 5, + 8, 12, 13, 11, 7, 10, 15, 18, 18, 15, 13, 6, 9, 13, 16, 17, 15, 11, 5, + 8, 11, 14, 15, 13, 9, 5, 6, 9, 11, 12, 11, 6, 2, 3, 5, 8, 9, 10, + 6, 3, 3, 4, 6, 8, 8, 6, 10, 8, 4, 5, 6, 6, 5, 5, 8, 10, 11, + 13, 11, 8, 5, 7, 9, 10, 11, 10, 7, 4, 6, 7, 8, 9, 8, 6, 4, 4, + 5, 5, 5, 6, 3, 0, 2, 1, 1, 1, 2, 3, 6, 6, 5, 4, 1, 2, 3, + 11, 10, 7, 5, 2, 1, 2, 5, 6, 6, 7, 7, 8, 7, 4, 5, 6, 6, 7, + 7, 7, 3, 5, 6, 6, 6, 6, 6, 2, 3, 3, 4, 4, 4, 3, 2, 3, 4, + 4, 4, 3, 3, 6, 8, 7, 7, 6, 5, 5, 11, 13, 9, 8, 8, 7, 6, 6, + 7, 7, 7, 8, 7, 7, 7, 8, 8, 9, 9, 7, 7, 7, 10, 10, 10, 11, 9, + 6, 7, 11, 10, 10, 10, 10, 5, 7, 11, 10, 10, 10, 10, 6, 9, 13, 13, 12, + 11, 10, 8, 12, 15, 15, 13, 12, 11, 9, 14, 15, 14, 14, 13, 9, 7, 14, 16, + 15, 15, 14, 11, 6, 14, 17, 16, 16, 14, 11, 7, 14, 16, 16, 15, 14, 11, 8, + 13, 15, 17, 16, 14, 11, 9, 13, 16, 20, 18, 14, 12, 10, 15, 18, 20, 19, 16, + 13, 10, 18, 23, 21, 17, 15, 12, 8, 18, 22, 23, 18, 16, 13, 9, 18, 23, 24, + 18, 16, 13, 10, 19, 22, 24, 19, 15, 13, 10, 17, 20, 23, 20, 16, 13, 11, 17, + 20, 23, 22, 18, 14, 11, 18, 22, 24, 24, 19, 15, 12, 7, 8, 10, 12, 12, 11, + 9, 6, 8, 9, 12, 12, 9, 8, 6, 7, 8, 10, 11, 8, 6, 6, 6, 6, 7, + 9, 6, 3, 3, 3, 4, 4, 4, 3, 2, 1, 2, 2, 2, 3, 3, 2, 7, 6, + 3, 2, 3, 3, 2, 6, 7, 8, 10, 10, 9, 8, 6, 7, 8, 10, 9, 8, 7, + 5, 6, 7, 8, 8, 7, 5, 4, 5, 5, 6, 5, 5, 2, 2, 2, 2, 3, 2, + 2, 2, 3, 3, 3, 2, 2, 2, 2, 10, 8, 5, 3, 1, 2, 2, 5, 6, 7, + 8, 9, 9, 8, 4, 6, 7, 8, 8, 8, 8, 4, 5, 6, 6, 6, 6, 6, 4, + 4, 4, 4, 4, 4, 3, 2, 0, 1, 1, 1, 2, 3, 6, 5, 5, 3, 1, 1, + 2, 12, 11, 7, 4, 2, 1, 2, 4, 6, 7, 8, 9, 9, 9, 4, 5, 7, 8, + 8, 8, 9, 3, 5, 6, 7, 7, 7, 7, 4, 4, 5, 5, 5, 5, 5, 3, 6, + 6, 6, 7, 7, 7, 6, 12, 11, 10, 9, 7, 8, 12, 17, 14, 12, 10, 9, 9, + 9, 10, 10, 10, 11, 10, 9, 10, 11, 11, 12, 12, 11, 9, 11, 12, 13, 13, 13, + 12, 8, 10, 14, 13, 14, 14, 13, 8, 11, 16, 16, 16, 16, 14, 9, 13, 19, 21, + 20, 19, 16, 11, 17, 22, 24, 22, 20, 18, 12, 18, 20, 20, 20, 17, 13, 9, 18, + 22, 22, 22, 19, 14, 9, 18, 24, 24, 24, 19, 15, 10, 19, 23, 25, 24, 21, 16, + 11, 17, 23, 27, 25, 23, 18, 13, 19, 25, 31, 28, 25, 20, 14, 23, 28, 31, 30, + 26, 22, 16, 27, 33, 32, 26, 21, 16, 11, 26, 32, 33, 28, 23, 17, 12, 27, 32, + 35, 28, 23, 18, 13, 26, 32, 36, 29, 25, 19, 14, 26, 31, 33, 31, 26, 22, 16, + 25, 30, 35, 33, 28, 23, 18, 27, 31, 34, 35, 30, 25, 20, 9, 11, 12, 14, 13, + 13, 12, 8, 11, 12, 13, 13, 11, 10, 6, 10, 11, 12, 12, 10, 8, 5, 8, 9, + 10, 10, 8, 5, 2, 5, 6, 6, 6, 5, 4, 1, 3, 4, 5, 5, 5, 4, 7, + 7, 5, 4, 5, 5, 4, 6, 10, 11, 13, 12, 12, 10, 5, 9, 11, 12, 12, 11, + 9, 4, 7, 10, 11, 10, 9, 7, 4, 5, 7, 8, 8, 7, 4, 2, 2, 4, 5, + 5, 4, 4, 4, 3, 5, 4, 4, 4, 4, 10, 8, 6, 5, 3, 4, 4, 5, 7, + 9, 10, 11, 10, 10, 4, 6, 8, 9, 10, 8, 8, 4, 5, 7, 7, 7, 7, 6, + 4, 3, 3, 3, 4, 4, 2, 2, 1, 0, 0, 0, 1, 2, 6, 5, 4, 3, 2, + 1, 2, 12, 10, 7, 5, 4, 3, 2, 4, 6, 7, 8, 10, 11, 10, 3, 6, 7, + 8, 9, 9, 9, 3, 6, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 7, 6, 4, + 8, 7, 8, 8, 8, 8, 7, 13, 12, 11, 10, 9, 9, 12, 18, 15, 13, 11, 10, + 10, 11, 12, 12, 12, 13, 12, 10, 11, 13, 13, 13, 14, 12, 9, 12, 14, 14, 14, + 14, 13, 9, 11, 16, 15, 15, 15, 14, 9, 12, 18, 17, 17, 17, 15, 11, 14, 20, + 21, 21, 19, 16, 12, 18, 23, 26, 23, 21, 18, 13, 20, 22, 22, 22, 19, 15, 11, + 19, 24, 23, 24, 19, 15, 11, 20, 26, 24, 24, 20, 15, 11, 20, 25, 26, 26, 21, + 17, 12, 19, 25, 29, 27, 23, 18, 13, 20, 26, 32, 32, 26, 19, 14, 23, 29, 33, + 35, 28, 22, 16, 27, 35, 33, 28, 21, 17, 13, 29, 34, 36, 29, 23, 18, 13, 28, + 35, 38, 30, 24, 19, 14, 29, 34, 38, 30, 25, 20, 15, 27, 34, 38, 34, 28, 22, + 17, 27, 34, 39, 38, 31, 24, 19, 30, 36, 40, 41, 34, 26, 21, 9, 13, 16, 19, + 18, 17, 14, 8, 11, 15, 18, 18, 16, 13, 6, 10, 14, 16, 16, 13, 10, 5, 8, + 11, 13, 14, 11, 8, 2, 5, 7, 10, 11, 9, 7, 2, 3, 5, 7, 10, 9, 7, + 7, 6, 6, 7, 9, 9, 7, 7, 10, 14, 16, 16, 14, 11, 5, 9, 12, 15, 16, + 13, 9, 4, 7, 11, 13, 13, 11, 7, 4, 5, 8, 10, 10, 9, 4, 2, 2, 4, + 7, 7, 7, 4, 4, 3, 5, 5, 5, 6, 4, 9, 7, 6, 5, 4, 5, 4, 5, + 7, 9, 10, 12, 10, 9, 4, 6, 8, 9, 10, 9, 8, 4, 5, 7, 7, 7, 7, + 5, 4, 3, 3, 3, 4, 4, 2, 1, 1, 0, 0, 0, 1, 2, 6, 5, 4, 3, + 2, 1, 2, 11, 9, 7, 5, 3, 2, 2, 4, 6, 7, 8, 9, 11, 10, 4, 6, + 7, 8, 8, 9, 8, 3, 6, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 5, + 5, 8, 7, 7, 8, 8, 7, 7, 13, 12, 11, 10, 9, 9, 11, 17, 15, 13, 11, + 10, 10, 11, 12, 12, 12, 13, 13, 10, 11, 13, 13, 14, 14, 13, 8, 11, 14, 15, + 14, 14, 12, 9, 11, 17, 15, 15, 15, 13, 9, 11, 18, 17, 17, 17, 15, 10, 15, + 21, 22, 21, 19, 16, 12, 19, 23, 25, 23, 21, 18, 13, 21, 22, 22, 21, 19, 15, + 11, 20, 24, 24, 23, 20, 15, 10, 21, 26, 26, 24, 20, 15, 11, 20, 26, 26, 25, + 21, 16, 12, 19, 25, 29, 27, 23, 18, 13, 21, 26, 33, 32, 25, 20, 15, 24, 30, + 33, 33, 28, 22, 16, 28, 35, 33, 27, 21, 17, 13, 29, 35, 36, 29, 22, 18, 13, + 29, 35, 39, 30, 23, 18, 14, 29, 34, 38, 32, 25, 19, 14, 28, 33, 39, 34, 27, + 22, 17, 28, 33, 39, 38, 30, 24, 18, 29, 34, 39, 40, 33, 26, 20, 9, 13, 16, + 20, 20, 18, 15, 8, 12, 15, 19, 20, 17, 13, 7, 10, 14, 17, 18, 14, 11, 5, + 8, 11, 14, 16, 13, 8, 3, 5, 7, 10, 13, 10, 8, 2, 3, 5, 8, 11, 10, + 8, 3, 4, 4, 7, 10, 11, 8, 7, 10, 14, 17, 16, 14, 11, 5, 9, 13, 17, + 16, 12, 9, 5, 8, 11, 14, 14, 11, 7, 4, 6, 8, 11, 10, 9, 4, 2, 2, + 5, 7, 7, 7, 4, 3, 2, 4, 5, 6, 6, 4, 6, 3, 3, 5, 4, 5, 4, + 5, 8, 10, 11, 12, 10, 10, 4, 6, 8, 9, 10, 9, 8, 4, 5, 7, 7, 7, + 7, 5, 4, 4, 3, 4, 4, 4, 2, 1, 1, 0, 0, 0, 1, 2, 5, 3, 3, + 2, 2, 1, 2, 7, 5, 4, 4, 3, 2, 2, 4, 6, 7, 8, 9, 11, 10, 4, + 6, 7, 8, 9, 9, 8, 3, 6, 7, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, + 5, 5, 8, 8, 8, 8, 7, 7, 5, 10, 10, 10, 10, 8, 8, 7, 13, 12, 11, + 11, 10, 10, 11, 12, 12, 13, 13, 12, 10, 12, 13, 13, 14, 14, 13, 8, 12, 15, + 15, 14, 14, 13, 9, 11, 17, 15, 15, 15, 13, 9, 12, 18, 17, 17, 16, 15, 10, + 14, 19, 21, 19, 19, 16, 12, 15, 20, 23, 21, 21, 18, 13, 22, 22, 22, 21, 19, + 15, 11, 21, 24, 23, 23, 19, 15, 11, 20, 26, 25, 24, 20, 15, 11, 21, 25, 26, + 26, 21, 16, 12, 20, 25, 30, 27, 23, 18, 13, 21, 26, 32, 31, 25, 19, 15, 21, + 26, 32, 31, 27, 21, 16, 29, 35, 32, 26, 22, 17, 13, 29, 34, 35, 29, 23, 18, + 14, 29, 35, 37, 30, 23, 18, 14, 29, 34, 38, 31, 25, 20, 15, 28, 32, 37, 33, + 27, 22, 16, 28, 34, 38, 36, 30, 24, 18, 29, 34, 39, 39, 32, 26, 20, 8, 12, + 16, 19, 20, 17, 14, 7, 11, 15, 19, 19, 16, 12, 6, 9, 13, 16, 17, 14, 10, + 4, 7, 10, 13, 15, 12, 8, 1, 4, 7, 9, 13, 11, 8, 2, 3, 5, 8, 12, + 11, 8, 4, 4, 4, 7, 10, 11, 8, 6, 10, 13, 16, 16, 14, 10, 5, 8, 12, + 15, 16, 12, 8, 3, 7, 11, 13, 13, 10, 6, 3, 5, 8, 10, 9, 8, 4, 1, + 2, 4, 7, 7, 7, 4, 3, 3, 4, 6, 5, 6, 4, 6, 4, 3, 5, 4, 4, + 4, 4, 7, 9, 10, 11, 9, 8, 3, 5, 8, 9, 9, 8, 6, 3, 4, 6, 6, + 6, 6, 4, 3, 2, 3, 3, 3, 3, 1, 2, 2, 1, 1, 1, 0, 1, 4, 3, + 3, 2, 2, 2, 1, 8, 6, 4, 3, 3, 2, 2, 3, 5, 6, 7, 8, 10, 9, + 2, 6, 6, 7, 7, 8, 7, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 5, 6, 8, 8, 8, 8, 8, 7, 5, 10, 10, 9, 9, 8, 8, 8, 14, 12, + 11, 10, 10, 10, 11, 12, 12, 12, 13, 13, 9, 12, 14, 13, 14, 14, 12, 7, 12, + 15, 15, 14, 14, 13, 8, 12, 17, 15, 15, 15, 13, 9, 13, 19, 17, 17, 16, 15, + 10, 14, 19, 20, 18, 18, 16, 11, 14, 20, 23, 21, 19, 18, 13, 21, 23, 22, 21, + 18, 14, 10, 22, 25, 23, 23, 19, 15, 11, 21, 26, 25, 23, 19, 15, 11, 21, 25, + 26, 24, 21, 16, 11, 20, 25, 28, 26, 22, 17, 13, 21, 26, 30, 28, 23, 19, 15, + 21, 27, 30, 30, 25, 20, 16, 28, 33, 30, 25, 21, 17, 13, 28, 33, 33, 26, 22, + 18, 13, 29, 33, 35, 27, 22, 18, 14, 29, 32, 35, 29, 23, 19, 15, 27, 32, 36, + 31, 25, 20, 16, 28, 32, 35, 34, 27, 23, 18, 27, 31, 36, 35, 29, 23, 19, 8, + 10, 13, 16, 15, 13, 10, 7, 10, 12, 15, 15, 12, 8, 6, 8, 11, 13, 14, 10, + 7, 5, 6, 9, 10, 13, 9, 6, 2, 5, 7, 9, 12, 9, 6, 3, 5, 6, 8, + 11, 10, 6, 4, 4, 6, 8, 10, 9, 6, 6, 9, 11, 13, 12, 10, 7, 5, 8, + 10, 13, 12, 8, 5, 4, 7, 9, 10, 9, 7, 4, 2, 5, 7, 8, 7, 6, 3, + 1, 3, 5, 7, 6, 5, 3, 3, 3, 5, 6, 5, 5, 3, 6, 4, 5, 6, 5, + 4, 3, 4, 7, 8, 8, 9, 7, 6, 2, 6, 7, 7, 7, 5, 4, 2, 5, 6, + 5, 4, 4, 2, 2, 3, 3, 3, 3, 2, 0, 3, 3, 2, 2, 2, 1, 0, 5, + 4, 3, 2, 2, 1, 0, 8, 5, 3, 3, 2, 2, 1, 2, 4, 4, 5, 7, 8, + 8, 1, 5, 4, 5, 6, 6, 6, 1, 6, 5, 5, 5, 5, 5, 5, 6, 5, 5, + 5, 5, 4, 5, 8, 7, 7, 7, 6, 6, 5, 10, 9, 8, 8, 8, 7, 8, 13, + 12, 10, 9, 9, 9, 11, 11, 11, 11, 12, 11, 8, 12, 12, 12, 13, 12, 11, 6, + 12, 14, 14, 13, 12, 11, 7, 12, 16, 14, 13, 13, 12, 8, 13, 18, 16, 16, 15, + 13, 9, 14, 19, 20, 17, 16, 14, 10, 15, 20, 23, 20, 18, 16, 12, 20, 21, 19, + 18, 15, 13, 9, 20, 22, 20, 18, 16, 13, 9, 20, 24, 22, 20, 16, 13, 10, 20, + 24, 23, 21, 17, 14, 11, 19, 23, 26, 24, 20, 16, 12, 20, 24, 30, 28, 23, 17, + 14, 21, 26, 29, 30, 25, 19, 14, 26, 30, 28, 22, 17, 15, 12, 26, 30, 29, 24, + 18, 15, 11, 26, 30, 32, 25, 19, 16, 12, 25, 29, 33, 26, 21, 17, 13, 25, 29, + 33, 30, 24, 20, 15, 26, 31, 35, 34, 27, 20, 16, 27, 32, 35, 35, 29, 23, 17, + 14, 17, 21, 24, 24, 22, 19, 13, 16, 20, 24, 25, 21, 18, 12, 15, 18, 21, 23, + 19, 15, 12, 13, 15, 17, 21, 16, 12, 9, 9, 11, 14, 14, 15, 12, 5, 5, 8, + 11, 13, 14, 12, 2, 3, 6, 9, 13, 15, 12, 13, 15, 19, 21, 22, 19, 17, 12, + 14, 17, 20, 21, 18, 14, 11, 13, 15, 18, 18, 16, 12, 11, 11, 13, 14, 15, 12, + 7, 8, 8, 9, 10, 9, 10, 7, 3, 3, 5, 7, 9, 9, 7, 3, 3, 3, 6, + 8, 8, 7, 11, 13, 14, 16, 18, 17, 15, 11, 12, 14, 15, 16, 15, 14, 10, 11, + 13, 13, 13, 13, 12, 10, 10, 10, 10, 11, 9, 5, 6, 6, 6, 6, 5, 5, 5, + 0, 2, 1, 2, 4, 4, 5, 4, 4, 2, 1, 3, 4, 5, 10, 11, 13, 14, 15, + 16, 15, 10, 11, 12, 14, 14, 15, 14, 9, 10, 12, 12, 12, 13, 12, 6, 9, 9, + 9, 10, 9, 7, 4, 5, 4, 5, 5, 4, 4, 0, 2, 2, 2, 3, 3, 5, 4, + 6, 3, 3, 3, 4, 5, 9, 10, 12, 13, 14, 15, 15, 8, 9, 11, 12, 13, 13, + 14, 8, 9, 10, 10, 11, 11, 12, 8, 8, 8, 8, 9, 8, 5, 5, 8, 7, 7, + 7, 6, 5, 4, 7, 7, 7, 7, 7, 5, 5, 8, 9, 8, 8, 8, 5, 11, 12, + 12, 13, 12, 14, 15, 11, 13, 13, 13, 12, 12, 13, 11, 14, 14, 13, 11, 10, 11, + 11, 13, 13, 13, 11, 9, 5, 9, 11, 13, 12, 10, 8, 5, 8, 11, 14, 13, 11, + 8, 6, 8, 12, 15, 15, 11, 9, 7, 15, 19, 18, 15, 13, 13, 14, 15, 19, 20, + 16, 13, 11, 12, 15, 18, 21, 16, 14, 11, 9, 15, 18, 20, 15, 13, 9, 6, 14, + 16, 19, 16, 11, 9, 7, 13, 15, 18, 17, 13, 10, 8, 12, 16, 19, 19, 14, 11, + 8, 12, 14, 15, 17, 17, 16, 14, 12, 13, 15, 16, 17, 14, 13, 11, 12, 14, 15, + 15, 12, 11, 10, 11, 11, 12, 12, 8, 4, 8, 8, 8, 8, 6, 5, 4, 4, 4, + 4, 3, 4, 5, 4, 2, 2, 2, 3, 4, 5, 4, 11, 13, 14, 15, 16, 15, 14, + 10, 12, 13, 15, 15, 14, 12, 10, 11, 13, 13, 13, 12, 10, 9, 10, 10, 10, 11, + 9, 4, 7, 7, 7, 7, 4, 4, 4, 2, 3, 3, 3, 3, 4, 4, 5, 4, 2, + 2, 3, 3, 4, 10, 11, 13, 14, 15, 15, 15, 9, 10, 12, 13, 14, 14, 13, 9, + 10, 12, 12, 12, 11, 10, 9, 9, 9, 9, 9, 8, 4, 5, 5, 5, 5, 3, 3, + 4, 2, 0, 1, 2, 2, 3, 4, 7, 6, 2, 0, 3, 3, 4, 10, 11, 12, 13, + 15, 16, 16, 9, 11, 12, 13, 14, 14, 14, 8, 11, 12, 12, 12, 12, 11, 5, 9, + 9, 9, 9, 8, 7, 3, 5, 5, 5, 5, 5, 5, 2, 7, 7, 6, 6, 6, 7, + 7, 13, 10, 8, 8, 8, 8, 10, 11, 12, 13, 14, 16, 16, 9, 10, 11, 13, 14, + 14, 14, 9, 11, 11, 11, 12, 12, 11, 9, 12, 11, 12, 12, 11, 7, 8, 13, 14, + 13, 14, 13, 9, 9, 15, 17, 17, 16, 15, 10, 12, 17, 19, 18, 18, 16, 11, 16, + 19, 18, 19, 16, 15, 16, 16, 21, 21, 21, 17, 13, 13, 16, 22, 23, 21, 17, 12, + 10, 16, 22, 23, 23, 19, 14, 10, 15, 21, 25, 23, 21, 17, 11, 16, 22, 27, 25, + 21, 18, 13, 18, 22, 26, 25, 23, 20, 15, 25, 30, 29, 25, 19, 15, 14, 25, 30, + 31, 26, 20, 15, 12, 25, 30, 33, 26, 21, 16, 11, 25, 30, 34, 28, 22, 18, 14, + 24, 29, 32, 27, 23, 20, 16, 24, 27, 30, 29, 24, 21, 17, 23, 27, 30, 30, 25, + 22, 19, 13, 16, 17, 18, 18, 17, 16, 12, 15, 17, 18, 18, 16, 14, 11, 14, 16, + 16, 15, 13, 11, 10, 12, 13, 13, 13, 10, 5, 7, 9, 10, 10, 8, 6, 5, 3, + 5, 7, 5, 6, 6, 5, 2, 3, 5, 5, 6, 6, 5, 11, 14, 16, 17, 17, 17, + 15, 10, 13, 15, 16, 17, 15, 13, 9, 12, 15, 15, 14, 13, 10, 9, 9, 12, 13, + 11, 9, 5, 7, 6, 8, 9, 6, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 3, + 3, 5, 4, 5, 5, 9, 12, 14, 15, 16, 15, 14, 9, 10, 12, 14, 15, 13, 12, + 9, 10, 11, 11, 11, 11, 9, 9, 8, 8, 8, 8, 7, 3, 5, 5, 5, 4, 3, + 3, 3, 1, 1, 0, 1, 2, 3, 3, 6, 5, 3, 1, 2, 3, 3, 9, 11, 11, + 13, 15, 15, 15, 9, 11, 12, 13, 14, 14, 13, 7, 11, 11, 11, 11, 11, 10, 5, + 9, 8, 8, 8, 7, 7, 3, 5, 5, 6, 6, 6, 6, 2, 8, 8, 7, 7, 8, + 8, 6, 12, 11, 9, 9, 9, 9, 10, 10, 11, 13, 14, 15, 15, 9, 11, 12, 13, + 13, 13, 13, 10, 12, 13, 13, 13, 11, 9, 10, 13, 13, 13, 13, 12, 8, 9, 15, + 14, 15, 15, 14, 9, 10, 16, 18, 17, 17, 15, 11, 13, 18, 21, 18, 18, 17, 13, + 18, 20, 20, 20, 17, 15, 15, 18, 22, 21, 21, 18, 13, 12, 18, 24, 24, 23, 18, + 14, 10, 18, 23, 25, 24, 20, 15, 11, 18, 23, 27, 26, 21, 17, 13, 17, 23, 29, + 28, 24, 18, 14, 19, 25, 29, 31, 26, 20, 16, 27, 33, 32, 25, 20, 16, 14, 26, + 32, 34, 27, 22, 17, 12, 27, 33, 36, 28, 22, 17, 12, 27, 32, 37, 29, 24, 19, + 14, 25, 31, 37, 32, 26, 20, 16, 25, 31, 36, 35, 28, 22, 17, 26, 32, 37, 37, + 30, 24, 19, 12, 16, 19, 22, 22, 20, 18, 12, 15, 18, 21, 21, 19, 15, 10, 13, + 17, 19, 19, 17, 13, 8, 11, 14, 16, 17, 13, 8, 6, 8, 10, 12, 12, 10, 8, + 2, 4, 7, 9, 11, 10, 8, 2, 3, 5, 8, 10, 10, 8, 10, 13, 17, 20, 20, + 17, 14, 9, 12, 16, 19, 19, 16, 12, 8, 11, 14, 17, 16, 14, 9, 8, 9, 11, + 13, 13, 11, 5, 5, 5, 8, 10, 8, 8, 5, 1, 2, 4, 6, 6, 7, 5, 4, + 3, 3, 5, 5, 6, 5, 8, 11, 13, 14, 16, 13, 13, 8, 9, 12, 13, 14, 12, + 11, 7, 8, 10, 10, 10, 10, 7, 8, 7, 7, 7, 7, 6, 2, 4, 3, 3, 3, + 2, 2, 2, 2, 2, 1, 0, 1, 2, 2, 4, 3, 2, 2, 1, 2, 2, 8, 9, + 10, 11, 13, 14, 14, 8, 9, 10, 11, 12, 12, 11, 5, 9, 10, 9, 9, 9, 8, + 5, 8, 7, 6, 7, 6, 6, 3, 6, 6, 6, 6, 6, 6, 2, 8, 8, 7, 7, + 7, 7, 4, 11, 10, 9, 9, 9, 9, 9, 11, 11, 12, 13, 13, 13, 9, 11, 12, + 12, 13, 12, 11, 10, 13, 14, 13, 13, 11, 8, 10, 15, 13, 14, 14, 12, 8, 10, + 16, 15, 15, 15, 13, 9, 11, 16, 18, 17, 16, 14, 11, 12, 17, 20, 19, 18, 17, + 12, 19, 21, 20, 20, 18, 14, 13, 18, 23, 22, 22, 18, 14, 10, 19, 24, 24, 23, + 19, 14, 10, 19, 24, 25, 23, 20, 15, 10, 18, 24, 28, 26, 21, 17, 12, 18, 24, + 30, 29, 23, 18, 13, 18, 24, 30, 30, 25, 19, 15, 27, 34, 32, 26, 20, 16, 12, + 27, 34, 34, 28, 22, 17, 12, 27, 34, 37, 28, 22, 17, 13, 28, 33, 37, 30, 23, + 18, 14, 26, 32, 36, 33, 25, 19, 15, 26, 31, 36, 34, 28, 21, 17, 26, 31, 36, + 37, 29, 24, 18, 11, 15, 18, 21, 22, 20, 16, 10, 14, 17, 21, 22, 18, 14, 8, + 12, 16, 19, 20, 16, 12, 7, 10, 13, 16, 18, 14, 9, 4, 7, 9, 12, 14, 12, + 9, 0, 3, 6, 9, 13, 12, 9, 3, 3, 5, 8, 11, 12, 9, 8, 12, 16, 19, + 18, 16, 12, 7, 11, 14, 18, 18, 14, 10, 6, 10, 13, 16, 15, 13, 9, 6, 7, + 10, 12, 12, 10, 5, 3, 4, 6, 9, 9, 8, 5, 2, 2, 4, 6, 7, 7, 5, + 5, 4, 3, 6, 5, 6, 5, 6, 10, 11, 13, 14, 12, 11, 5, 8, 10, 11, 12, + 11, 8, 5, 7, 9, 9, 9, 9, 6, 6, 5, 5, 5, 6, 5, 3, 1, 1, 2, + 2, 2, 2, 2, 4, 3, 2, 1, 0, 1, 2, 7, 4, 3, 2, 1, 1, 2, 6, + 7, 8, 9, 10, 12, 11, 5, 7, 8, 9, 9, 9, 9, 4, 7, 7, 7, 7, 7, + 6, 5, 6, 6, 5, 5, 5, 5, 3, 7, 6, 6, 6, 6, 6, 4, 9, 8, 8, + 8, 7, 7, 7, 12, 10, 9, 9, 9, 9, 10, 11, 11, 11, 12, 12, 11, 11, 12, + 12, 13, 13, 11, 9, 11, 14, 14, 13, 13, 11, 8, 11, 15, 14, 13, 14, 12, 8, + 11, 17, 16, 15, 15, 13, 9, 12, 17, 18, 17, 16, 15, 10, 13, 17, 20, 19, 18, + 16, 12, 20, 21, 20, 21, 18, 14, 11, 20, 23, 23, 23, 19, 14, 9, 19, 25, 24, + 23, 19, 14, 10, 20, 24, 26, 24, 20, 15, 11, 18, 24, 27, 26, 21, 16, 12, 19, + 23, 30, 29, 23, 18, 14, 19, 24, 29, 31, 25, 20, 15, 28, 34, 32, 26, 21, 16, + 12, 27, 34, 34, 27, 21, 17, 12, 27, 33, 36, 29, 23, 18, 13, 28, 32, 37, 29, + 24, 19, 13, 26, 32, 36, 33, 25, 20, 15, 26, 32, 37, 33, 28, 22, 17, 27, 32, + 35, 36, 30, 23, 18, 10, 14, 18, 21, 21, 18, 15, 9, 12, 16, 20, 21, 17, 13, + 7, 11, 15, 18, 19, 16, 11, 6, 9, 12, 14, 16, 14, 9, 3, 6, 8, 11, 14, + 12, 9, 2, 4, 6, 9, 13, 12, 9, 4, 4, 5, 8, 11, 12, 9, 7, 11, 14, + 18, 18, 15, 11, 6, 10, 13, 17, 17, 13, 9, 5, 8, 12, 14, 14, 12, 8, 4, + 6, 9, 11, 11, 10, 5, 1, 3, 5, 8, 8, 8, 5, 2, 3, 4, 7, 7, 7, + 5, 6, 4, 4, 6, 5, 6, 5, 5, 8, 10, 11, 13, 11, 9, 3, 7, 9, 10, + 11, 9, 7, 3, 6, 7, 8, 7, 7, 4, 3, 3, 4, 4, 4, 4, 1, 2, 1, + 1, 1, 1, 2, 1, 4, 3, 2, 2, 1, 0, 1, 8, 6, 3, 3, 2, 1, 1, + 3, 5, 6, 7, 8, 10, 9, 3, 5, 6, 7, 8, 8, 7, 2, 5, 6, 6, 5, + 6, 5, 5, 6, 6, 5, 5, 5, 4, 4, 8, 7, 6, 7, 6, 6, 4, 10, 8, + 8, 8, 8, 7, 8, 12, 11, 10, 9, 9, 9, 11, 11, 11, 11, 12, 12, 9, 12, + 13, 12, 13, 13, 12, 7, 12, 14, 14, 13, 12, 11, 8, 11, 16, 14, 14, 14, 12, + 8, 12, 18, 17, 15, 16, 13, 9, 13, 18, 19, 18, 16, 15, 11, 14, 18, 21, 19, + 19, 16, 12, 20, 21, 20, 20, 17, 14, 10, 20, 23, 22, 22, 18, 14, 9, 20, 25, + 24, 23, 19, 14, 10, 20, 25, 24, 23, 20, 15, 10, 19, 25, 26, 25, 21, 16, 12, + 20, 25, 29, 28, 22, 18, 14, 20, 25, 29, 30, 24, 19, 15, 28, 33, 29, 24, 20, + 16, 12, 28, 32, 31, 26, 21, 16, 12, 28, 32, 34, 27, 23, 17, 13, 27, 31, 35, + 28, 23, 18, 14, 26, 31, 34, 31, 24, 20, 15, 26, 31, 35, 33, 26, 21, 17, 27, + 30, 35, 35, 29, 22, 18, 8, 11, 12, 16, 15, 13, 10, 7, 10, 12, 15, 15, 12, + 8, 6, 8, 11, 13, 14, 10, 7, 5, 6, 9, 10, 12, 9, 6, 2, 5, 7, 9, + 12, 9, 6, 3, 5, 6, 8, 11, 9, 6, 4, 5, 6, 8, 10, 9, 6, 6, 9, + 11, 13, 12, 10, 7, 5, 8, 10, 12, 12, 8, 5, 4, 7, 9, 10, 9, 7, 4, + 2, 5, 7, 8, 7, 6, 3, 1, 3, 5, 7, 6, 5, 3, 3, 3, 5, 6, 5, + 5, 3, 6, 4, 5, 6, 5, 4, 3, 4, 7, 8, 8, 9, 7, 6, 2, 6, 7, + 7, 7, 5, 4, 2, 5, 6, 5, 4, 4, 2, 2, 3, 3, 3, 3, 2, 0, 3, + 2, 2, 2, 2, 1, 0, 5, 4, 3, 2, 2, 1, 0, 8, 6, 3, 2, 2, 2, + 1, 2, 4, 4, 5, 6, 7, 8, 1, 4, 4, 5, 6, 5, 6, 1, 6, 5, 5, + 5, 5, 5, 5, 6, 5, 5, 5, 5, 4, 5, 8, 7, 7, 7, 7, 6, 5, 10, + 9, 8, 8, 8, 7, 8, 13, 12, 10, 9, 9, 9, 11, 11, 11, 11, 12, 11, 8, + 12, 12, 13, 12, 12, 11, 6, 12, 14, 14, 13, 12, 11, 7, 12, 16, 14, 13, 13, + 12, 8, 12, 18, 17, 15, 15, 13, 9, 13, 19, 20, 18, 16, 14, 10, 14, 20, 23, + 20, 18, 16, 11, 20, 20, 19, 17, 15, 13, 9, 20, 22, 20, 19, 16, 13, 9, 20, + 23, 22, 20, 17, 13, 10, 19, 24, 24, 21, 17, 14, 11, 19, 24, 26, 24, 20, 16, + 12, 20, 24, 30, 27, 22, 17, 13, 21, 25, 30, 29, 24, 19, 14, 26, 30, 27, 21, + 17, 14, 12, 26, 30, 29, 23, 18, 15, 12, 26, 30, 32, 25, 19, 16, 12, 26, 29, + 33, 26, 21, 17, 13, 25, 29, 33, 30, 24, 19, 15, 25, 31, 34, 34, 27, 21, 16, + 27, 32, 35, 35, 29, 23, 17, 20, 21, 23, 25, 26, 24, 23, 20, 21, 23, 24, 25, + 23, 20, 19, 21, 21, 23, 24, 20, 16, 18, 19, 19, 19, 20, 15, 11, 15, 15, 15, + 14, 14, 15, 10, 11, 11, 8, 10, 12, 14, 10, 5, 3, 5, 8, 11, 14, 10, 19, + 20, 22, 24, 24, 23, 22, 18, 20, 21, 23, 24, 22, 20, 17, 19, 20, 20, 21, 18, + 16, 17, 17, 18, 18, 16, 13, 8, 14, 14, 14, 12, 9, 9, 8, 9, 9, 7, 6, + 8, 8, 8, 2, 2, 4, 5, 7, 8, 8, 17, 19, 20, 21, 23, 24, 22, 17, 18, + 20, 21, 22, 21, 19, 17, 18, 19, 19, 19, 18, 15, 16, 16, 16, 16, 15, 12, 9, + 11, 12, 12, 11, 7, 8, 8, 4, 7, 6, 4, 6, 8, 8, 0, 2, 2, 4, 6, + 6, 8, 17, 18, 20, 21, 22, 23, 23, 16, 18, 20, 20, 21, 21, 21, 14, 19, 19, + 19, 18, 18, 17, 10, 17, 16, 16, 15, 11, 11, 8, 12, 12, 10, 6, 7, 8, 5, + 5, 5, 3, 4, 6, 7, 0, 3, 3, 3, 4, 5, 6, 15, 17, 19, 20, 21, 23, + 23, 12, 17, 18, 20, 20, 20, 21, 12, 16, 16, 17, 17, 16, 15, 12, 13, 13, 13, + 12, 10, 7, 9, 9, 8, 8, 7, 6, 6, 6, 7, 7, 6, 7, 7, 6, 4, 6, + 8, 7, 7, 8, 6, 13, 14, 15, 16, 18, 21, 23, 13, 14, 15, 16, 17, 19, 19, + 13, 14, 15, 15, 14, 15, 14, 13, 13, 13, 13, 12, 9, 6, 10, 12, 13, 12, 9, + 8, 6, 9, 10, 13, 13, 10, 8, 6, 7, 10, 14, 14, 11, 8, 7, 16, 19, 18, + 16, 17, 20, 21, 16, 19, 20, 17, 15, 17, 18, 16, 18, 21, 16, 14, 13, 13, 16, + 17, 20, 15, 12, 10, 7, 14, 16, 18, 15, 11, 9, 7, 12, 15, 17, 16, 12, 10, + 8, 11, 15, 18, 17, 13, 10, 8, 18, 19, 21, 22, 22, 21, 21, 18, 19, 20, 22, + 22, 19, 18, 17, 18, 19, 20, 19, 17, 14, 17, 17, 17, 17, 15, 12, 8, 14, 13, + 13, 11, 9, 8, 8, 10, 10, 7, 7, 8, 9, 8, 4, 2, 4, 6, 8, 8, 8, + 17, 19, 20, 21, 22, 21, 20, 16, 18, 19, 20, 21, 19, 17, 16, 17, 19, 19, 18, + 16, 13, 16, 16, 16, 16, 14, 11, 7, 14, 12, 12, 11, 7, 7, 7, 9, 8, 6, + 5, 6, 7, 7, 2, 2, 3, 4, 6, 6, 7, 16, 17, 18, 20, 21, 21, 21, 16, + 17, 18, 19, 20, 19, 18, 15, 17, 17, 17, 16, 16, 13, 15, 15, 14, 14, 13, 10, + 6, 10, 11, 11, 9, 5, 6, 6, 4, 6, 5, 3, 4, 5, 6, 2, 0, 2, 3, + 4, 5, 6, 16, 17, 18, 19, 21, 22, 22, 15, 17, 19, 19, 20, 19, 19, 13, 17, + 18, 18, 17, 16, 15, 9, 16, 15, 15, 14, 10, 11, 7, 12, 11, 10, 5, 5, 7, + 4, 6, 5, 5, 5, 5, 6, 2, 7, 6, 6, 6, 6, 7, 15, 17, 18, 20, 20, + 22, 22, 12, 16, 18, 18, 19, 19, 19, 12, 15, 16, 16, 16, 15, 13, 12, 13, 13, + 13, 12, 10, 6, 10, 10, 11, 11, 13, 11, 7, 7, 11, 14, 14, 15, 13, 8, 8, + 13, 16, 16, 16, 15, 10, 14, 16, 17, 17, 19, 21, 21, 14, 18, 18, 19, 17, 18, + 18, 14, 19, 20, 19, 16, 14, 13, 14, 19, 21, 21, 17, 12, 8, 12, 18, 22, 21, + 18, 16, 10, 12, 19, 22, 20, 19, 17, 12, 14, 19, 22, 21, 20, 17, 13, 22, 27, + 27, 22, 18, 20, 20, 22, 28, 29, 24, 18, 17, 17, 22, 27, 30, 24, 19, 14, 12, + 22, 26, 30, 24, 20, 16, 12, 20, 25, 29, 24, 19, 17, 14, 20, 25, 26, 25, 20, + 18, 15, 21, 23, 25, 25, 22, 19, 17, 16, 19, 19, 21, 20, 20, 19, 15, 18, 19, + 20, 20, 18, 16, 14, 16, 18, 19, 18, 15, 13, 13, 15, 16, 15, 15, 11, 7, 10, + 11, 12, 11, 9, 7, 6, 6, 8, 8, 6, 7, 7, 6, 1, 3, 5, 6, 7, 7, + 6, 14, 17, 19, 19, 20, 19, 18, 13, 16, 18, 19, 19, 17, 15, 12, 14, 18, 17, + 16, 15, 12, 12, 12, 14, 15, 13, 10, 6, 9, 9, 11, 10, 7, 6, 6, 5, 5, + 7, 6, 6, 6, 6, 2, 1, 4, 5, 5, 6, 6, 12, 15, 16, 18, 19, 18, 17, + 12, 13, 16, 17, 17, 16, 14, 12, 12, 14, 14, 14, 13, 10, 11, 11, 10, 11, 10, + 8, 4, 7, 7, 7, 7, 4, 4, 3, 2, 2, 3, 2, 3, 3, 3, 2, 2, 0, + 2, 3, 4, 4, 12, 13, 14, 16, 17, 18, 17, 11, 13, 14, 15, 16, 16, 14, 9, + 13, 13, 14, 13, 13, 11, 6, 12, 11, 11, 10, 8, 8, 4, 8, 7, 7, 5, 5, + 6, 2, 6, 6, 6, 6, 6, 6, 2, 8, 8, 7, 7, 7, 8, 12, 12, 14, 15, + 16, 17, 17, 10, 12, 13, 14, 15, 15, 15, 10, 12, 12, 12, 12, 12, 10, 10, 12, + 11, 12, 12, 10, 7, 8, 13, 13, 13, 14, 12, 8, 8, 14, 16, 16, 16, 14, 9, + 10, 15, 18, 17, 18, 16, 11, 16, 19, 18, 19, 16, 17, 17, 15, 20, 20, 20, 16, + 14, 14, 15, 22, 22, 20, 17, 12, 10, 16, 21, 22, 23, 18, 13, 10, 15, 21, 25, + 24, 20, 16, 11, 15, 21, 27, 27, 22, 17, 12, 17, 22, 29, 30, 24, 19, 14, 24, + 31, 30, 24, 19, 16, 16, 25, 31, 33, 26, 19, 15, 13, 24, 30, 35, 27, 21, 16, + 11, 24, 30, 35, 27, 22, 17, 13, 24, 29, 35, 31, 24, 19, 14, 24, 29, 34, 34, + 27, 21, 16, 24, 30, 34, 35, 29, 23, 18, 14, 18, 21, 23, 23, 22, 19, 13, 17, + 20, 22, 23, 20, 17, 11, 15, 19, 20, 20, 18, 15, 10, 13, 16, 18, 18, 14, 9, + 7, 10, 12, 14, 14, 11, 9, 4, 6, 8, 10, 12, 11, 9, 2, 3, 6, 9, 11, + 11, 9, 12, 15, 19, 21, 21, 19, 16, 11, 14, 18, 21, 20, 17, 13, 9, 12, 16, + 18, 18, 15, 11, 9, 10, 13, 16, 14, 12, 7, 6, 7, 9, 11, 10, 9, 6, 2, + 3, 6, 8, 8, 8, 6, 4, 2, 4, 7, 7, 7, 6, 9, 13, 14, 16, 17, 16, + 14, 9, 11, 13, 15, 15, 13, 11, 9, 10, 12, 12, 12, 11, 8, 9, 8, 8, 9, + 9, 7, 3, 5, 4, 5, 5, 4, 3, 2, 1, 0, 1, 1, 2, 3, 2, 4, 3, + 2, 0, 2, 2, 3, 9, 10, 11, 12, 13, 14, 14, 9, 10, 11, 12, 13, 12, 12, + 7, 10, 10, 10, 10, 10, 9, 4, 9, 7, 7, 7, 6, 6, 2, 5, 4, 5, 5, + 5, 5, 1, 7, 6, 6, 6, 6, 6, 4, 9, 9, 8, 7, 7, 8, 9, 10, 10, + 12, 13, 14, 14, 9, 10, 11, 12, 12, 12, 12, 9, 12, 12, 12, 12, 10, 8, 9, + 13, 12, 12, 13, 11, 7, 8, 14, 13, 13, 13, 12, 8, 10, 15, 17, 16, 15, 13, + 9, 11, 16, 19, 17, 17, 15, 10, 17, 19, 18, 18, 16, 14, 14, 17, 21, 21, 20, + 17, 12, 11, 17, 23, 22, 21, 18, 13, 9, 17, 22, 24, 22, 19, 14, 9, 17, 21, + 26, 24, 20, 16, 10, 16, 22, 28, 27, 22, 16, 12, 16, 23, 28, 29, 24, 18, 13, + 26, 32, 31, 24, 19, 15, 13, 26, 31, 33, 26, 20, 15, 11, 25, 31, 34, 27, 21, + 16, 11, 26, 31, 36, 29, 22, 17, 12, 24, 30, 35, 32, 23, 18, 14, 25, 30, 35, + 33, 26, 21, 15, 25, 30, 35, 35, 29, 23, 17, 12, 16, 20, 23, 23, 20, 18, 12, + 15, 19, 22, 23, 19, 16, 10, 14, 17, 20, 21, 17, 14, 9, 11, 14, 17, 19, 15, + 10, 5, 8, 10, 13, 15, 13, 10, 2, 5, 7, 10, 13, 13, 10, 3, 3, 6, 9, + 12, 12, 10, 10, 14, 17, 21, 20, 17, 14, 9, 12, 16, 19, 20, 16, 12, 7, 11, + 15, 17, 17, 14, 10, 6, 8, 11, 13, 13, 12, 6, 4, 5, 8, 10, 9, 9, 6, + 1, 3, 5, 7, 8, 8, 6, 5, 3, 4, 6, 6, 7, 6, 7, 11, 13, 14, 15, + 13, 11, 6, 9, 12, 13, 13, 12, 9, 6, 8, 10, 10, 10, 10, 6, 6, 6, 7, + 7, 7, 7, 2, 2, 2, 3, 3, 3, 3, 2, 3, 3, 2, 1, 1, 2, 2, 5, + 4, 3, 2, 0, 1, 2, 6, 7, 8, 9, 11, 12, 11, 6, 7, 8, 9, 10, 10, + 9, 5, 7, 7, 7, 7, 7, 6, 3, 6, 5, 5, 5, 4, 5, 2, 6, 5, 5, + 5, 5, 5, 3, 8, 7, 7, 7, 6, 6, 5, 11, 9, 8, 8, 8, 8, 9, 10, + 10, 11, 11, 12, 11, 10, 11, 11, 12, 12, 11, 9, 10, 12, 13, 12, 12, 11, 7, + 10, 14, 13, 12, 13, 11, 7, 10, 16, 14, 14, 14, 12, 8, 11, 16, 17, 16, 15, + 13, 9, 12, 16, 20, 18, 17, 15, 11, 18, 20, 20, 19, 16, 13, 11, 18, 22, 21, + 21, 18, 13, 9, 19, 24, 24, 22, 18, 13, 9, 19, 23, 25, 23, 19, 14, 10, 17, + 23, 26, 25, 20, 15, 11, 18, 23, 28, 27, 22, 17, 13, 18, 24, 29, 29, 24, 19, + 14, 27, 32, 31, 25, 19, 15, 11, 27, 32, 33, 26, 21, 16, 11, 27, 33, 35, 27, + 22, 17, 12, 26, 32, 36, 29, 22, 18, 12, 26, 31, 36, 32, 24, 19, 14, 25, 30, + 36, 34, 26, 20, 16, 25, 30, 35, 36, 29, 23, 17, 11, 15, 19, 22, 22, 20, 17, + 10, 14, 17, 21, 22, 18, 15, 9, 12, 16, 19, 20, 17, 12, 7, 10, 13, 16, 18, + 15, 10, 4, 7, 9, 12, 15, 13, 10, 2, 5, 7, 10, 14, 13, 10, 4, 4, 6, + 9, 12, 13, 10, 9, 12, 16, 20, 19, 16, 12, 7, 11, 15, 18, 18, 15, 11, 6, + 9, 13, 16, 16, 13, 9, 5, 7, 10, 13, 12, 11, 6, 1, 4, 7, 9, 9, 9, + 6, 3, 3, 5, 8, 8, 8, 6, 5, 4, 5, 7, 7, 7, 6, 6, 10, 12, 12, + 14, 12, 9, 4, 8, 10, 12, 12, 11, 7, 4, 7, 9, 9, 9, 9, 5, 4, 5, + 6, 5, 6, 6, 2, 1, 1, 3, 2, 2, 2, 2, 4, 3, 3, 2, 1, 1, 2, + 7, 5, 4, 2, 1, 0, 1, 4, 5, 6, 7, 9, 10, 9, 4, 5, 6, 7, 8, + 8, 7, 4, 5, 6, 5, 5, 5, 5, 4, 5, 4, 4, 4, 4, 3, 2, 6, 5, + 5, 5, 5, 5, 4, 8, 7, 7, 7, 6, 6, 7, 12, 9, 9, 8, 8, 8, 10, + 10, 10, 11, 11, 11, 9, 11, 12, 11, 12, 12, 10, 7, 11, 13, 13, 12, 12, 10, + 7, 11, 15, 13, 13, 13, 11, 7, 11, 16, 15, 14, 14, 12, 8, 12, 17, 17, 16, + 16, 13, 9, 13, 17, 21, 18, 17, 16, 11, 20, 20, 19, 19, 16, 13, 9, 19, 22, + 21, 20, 18, 13, 9, 19, 24, 23, 22, 17, 13, 9, 19, 23, 25, 22, 18, 14, 9, + 18, 23, 26, 24, 20, 16, 11, 18, 23, 28, 27, 21, 17, 13, 19, 23, 29, 29, 24, + 19, 14, 27, 31, 29, 24, 20, 16, 11, 26, 30, 31, 25, 20, 16, 12, 27, 32, 33, + 27, 21, 16, 11, 27, 31, 34, 28, 22, 17, 12, 26, 29, 34, 30, 23, 19, 14, 25, + 30, 34, 32, 25, 21, 16, 25, 30, 35, 34, 28, 22, 17, 10, 14, 17, 19, 19, 17, + 14, 9, 13, 15, 18, 19, 16, 13, 8, 11, 14, 16, 18, 15, 11, 7, 9, 12, 15, + 17, 13, 10, 3, 6, 9, 12, 15, 13, 10, 3, 5, 8, 10, 14, 13, 10, 5, 4, + 7, 10, 12, 13, 10, 8, 11, 15, 17, 16, 14, 11, 7, 10, 14, 16, 15, 13, 10, + 5, 9, 12, 15, 13, 12, 8, 4, 6, 9, 12, 11, 10, 6, 1, 4, 7, 9, 9, + 9, 6, 3, 4, 5, 8, 8, 8, 6, 7, 5, 5, 7, 7, 7, 6, 5, 9, 11, + 11, 12, 11, 8, 3, 7, 10, 10, 11, 9, 5, 2, 6, 8, 8, 8, 8, 3, 2, + 4, 5, 5, 5, 5, 2, 2, 2, 3, 2, 2, 2, 1, 5, 4, 3, 2, 2, 1, + 1, 8, 6, 4, 3, 2, 1, 0, 2, 4, 4, 6, 7, 9, 8, 2, 3, 4, 6, + 6, 6, 6, 1, 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 3, 3, 8, + 6, 5, 5, 5, 5, 5, 10, 8, 7, 7, 6, 6, 8, 13, 10, 9, 8, 8, 7, + 10, 10, 10, 10, 11, 10, 8, 11, 12, 11, 11, 11, 10, 6, 12, 13, 12, 12, 11, + 10, 6, 12, 15, 13, 12, 12, 11, 6, 12, 17, 15, 14, 13, 12, 8, 13, 17, 18, + 16, 15, 13, 9, 13, 18, 20, 17, 16, 14, 10, 19, 19, 18, 17, 15, 12, 8, 19, + 20, 19, 18, 16, 12, 8, 19, 23, 21, 19, 15, 12, 8, 19, 23, 22, 19, 16, 13, + 9, 18, 22, 24, 22, 18, 14, 10, 19, 23, 27, 25, 20, 15, 12, 18, 23, 28, 27, + 22, 17, 13, 25, 28, 25, 20, 17, 14, 11, 24, 28, 27, 22, 17, 14, 11, 24, 28, + 29, 22, 17, 14, 11, 25, 27, 30, 24, 19, 16, 12, 23, 27, 31, 28, 22, 17, 13, + 24, 28, 32, 31, 24, 19, 14, 25, 28, 32, 32, 26, 20, 15, 3, 7, 11, 15, 16, + 13, 11, 2, 5, 10, 14, 15, 13, 8, 2, 4, 8, 11, 13, 10, 5, 2, 2, 5, + 8, 10, 9, 5, 2, 2, 2, 5, 8, 10, 5, 5, 6, 6, 5, 8, 9, 5, 12, + 10, 8, 5, 6, 9, 5, 2, 4, 8, 11, 13, 10, 5, 2, 3, 7, 10, 13, 8, + 3, 2, 2, 5, 7, 9, 5, 2, 1, 2, 2, 4, 5, 3, 2, 2, 3, 3, 3, + 3, 3, 2, 7, 7, 8, 6, 3, 2, 2, 15, 13, 10, 7, 5, 3, 2, 2, 2, + 3, 5, 6, 4, 2, 1, 2, 2, 3, 4, 3, 1, 0, 2, 2, 2, 2, 2, 1, + 1, 2, 1, 1, 1, 1, 2, 4, 4, 4, 4, 4, 3, 2, 10, 10, 9, 8, 6, + 4, 2, 17, 16, 12, 9, 6, 4, 2, 0, 1, 1, 1, 2, 2, 5, 1, 2, 2, + 2, 2, 2, 5, 2, 2, 3, 3, 3, 3, 5, 4, 4, 5, 5, 5, 6, 7, 6, + 9, 9, 9, 9, 8, 7, 10, 15, 14, 13, 11, 10, 9, 17, 20, 17, 15, 13, 12, + 11, 8, 8, 8, 9, 9, 8, 5, 10, 10, 10, 10, 10, 9, 5, 10, 11, 11, 12, + 12, 10, 6, 10, 14, 14, 14, 14, 13, 9, 13, 18, 18, 18, 18, 17, 11, 15, 21, + 23, 21, 20, 18, 13, 20, 24, 25, 23, 21, 20, 15, 17, 18, 18, 18, 16, 11, 7, + 17, 20, 20, 19, 17, 12, 7, 17, 22, 21, 20, 19, 14, 9, 17, 23, 22, 22, 20, + 17, 14, 18, 24, 26, 25, 23, 20, 15, 21, 26, 29, 28, 24, 20, 17, 24, 28, 29, + 30, 25, 23, 18, 24, 29, 27, 22, 19, 15, 9, 24, 28, 29, 23, 20, 16, 11, 24, + 29, 30, 25, 21, 17, 13, 24, 29, 30, 26, 22, 20, 17, 25, 28, 32, 29, 25, 23, + 19, 26, 30, 33, 32, 26, 24, 20, 28, 32, 34, 33, 28, 25, 22, 6, 7, 8, 8, + 9, 7, 7, 5, 7, 8, 9, 9, 7, 6, 4, 6, 7, 8, 8, 7, 6, 3, 6, + 7, 7, 8, 7, 7, 3, 6, 7, 8, 9, 8, 7, 7, 9, 10, 9, 9, 8, 7, + 13, 13, 11, 10, 9, 8, 7, 4, 6, 7, 7, 7, 6, 5, 3, 6, 7, 7, 7, + 6, 5, 2, 5, 7, 7, 6, 6, 6, 1, 4, 7, 7, 6, 6, 7, 4, 5, 7, + 8, 7, 7, 6, 9, 9, 11, 10, 8, 7, 7, 16, 14, 12, 11, 8, 7, 7, 2, + 5, 6, 6, 6, 5, 2, 1, 4, 5, 5, 5, 5, 2, 1, 3, 4, 4, 5, 5, + 2, 1, 3, 4, 4, 5, 5, 4, 6, 6, 6, 6, 6, 5, 4, 11, 11, 11, 9, + 7, 5, 4, 18, 17, 13, 10, 7, 5, 4, 1, 0, 1, 1, 1, 2, 4, 1, 2, + 2, 2, 2, 2, 4, 2, 3, 2, 2, 3, 3, 4, 5, 5, 5, 6, 6, 6, 6, + 6, 10, 9, 9, 10, 9, 8, 12, 15, 14, 13, 11, 11, 9, 19, 21, 18, 15, 13, + 12, 11, 9, 8, 8, 8, 9, 7, 4, 10, 10, 9, 9, 10, 8, 4, 10, 11, 11, + 11, 11, 10, 6, 10, 15, 14, 14, 14, 13, 10, 13, 19, 18, 18, 19, 17, 11, 17, + 22, 24, 23, 21, 19, 13, 20, 26, 28, 25, 24, 21, 15, 17, 18, 17, 17, 14, 10, + 6, 17, 21, 19, 19, 16, 11, 7, 17, 21, 22, 21, 17, 13, 9, 17, 24, 25, 25, + 21, 17, 13, 20, 25, 31, 30, 25, 20, 15, 22, 28, 35, 33, 28, 22, 16, 25, 31, + 35, 36, 30, 24, 18, 25, 31, 29, 22, 17, 13, 9, 25, 30, 32, 25, 19, 15, 10, + 25, 31, 34, 27, 21, 17, 13, 24, 31, 37, 30, 26, 21, 17, 27, 33, 38, 36, 31, + 25, 18, 28, 36, 40, 40, 33, 27, 20, 32, 38, 41, 41, 35, 29, 23, 6, 9, 12, + 13, 13, 11, 9, 5, 8, 11, 13, 13, 11, 10, 4, 7, 10, 12, 13, 12, 10, 3, + 7, 10, 12, 14, 12, 11, 5, 7, 9, 12, 14, 13, 11, 8, 9, 11, 12, 14, 13, + 11, 14, 14, 12, 12, 13, 13, 11, 5, 7, 10, 12, 11, 9, 6, 4, 6, 9, 11, + 11, 9, 6, 2, 5, 8, 10, 10, 9, 7, 1, 5, 8, 11, 10, 10, 8, 4, 6, + 8, 10, 10, 11, 8, 10, 11, 11, 12, 10, 10, 8, 17, 16, 13, 12, 10, 9, 8, + 2, 5, 6, 7, 7, 5, 2, 1, 4, 5, 6, 6, 5, 2, 1, 3, 5, 5, 5, + 5, 3, 1, 3, 5, 5, 5, 6, 4, 6, 7, 7, 7, 7, 6, 4, 13, 12, 12, + 10, 8, 6, 4, 20, 18, 14, 11, 8, 6, 4, 1, 1, 0, 1, 1, 1, 3, 1, + 2, 1, 1, 1, 1, 3, 4, 3, 3, 3, 3, 3, 4, 7, 6, 6, 6, 6, 7, + 6, 8, 11, 10, 10, 10, 10, 8, 13, 16, 15, 14, 12, 11, 10, 19, 22, 19, 16, + 14, 13, 12, 9, 8, 8, 8, 8, 7, 3, 11, 10, 9, 9, 9, 8, 3, 10, 12, + 12, 12, 11, 10, 7, 10, 16, 15, 14, 15, 14, 10, 14, 21, 20, 20, 19, 17, 12, + 18, 24, 25, 23, 21, 18, 14, 22, 27, 28, 26, 24, 21, 15, 17, 19, 17, 17, 13, + 9, 5, 17, 21, 19, 18, 15, 11, 6, 17, 22, 22, 21, 17, 13, 10, 18, 24, 26, + 25, 21, 17, 13, 20, 27, 30, 30, 26, 20, 15, 23, 29, 36, 35, 29, 23, 17, 27, + 32, 37, 37, 31, 25, 19, 25, 30, 29, 22, 16, 12, 8, 25, 31, 31, 24, 18, 14, + 10, 25, 30, 35, 27, 22, 17, 13, 26, 31, 37, 31, 26, 21, 17, 27, 34, 39, 37, + 30, 25, 19, 30, 37, 43, 41, 33, 27, 20, 33, 38, 43, 43, 36, 29, 23, 7, 9, + 12, 15, 15, 13, 10, 6, 8, 11, 14, 15, 13, 10, 5, 7, 10, 13, 15, 14, 11, + 4, 7, 11, 14, 16, 14, 12, 5, 8, 11, 13, 17, 15, 12, 9, 11, 12, 13, 16, + 14, 12, 16, 15, 14, 13, 15, 15, 12, 5, 8, 10, 13, 12, 9, 6, 4, 7, 9, + 12, 12, 9, 6, 3, 5, 9, 11, 11, 10, 8, 1, 5, 9, 11, 11, 11, 9, 5, + 7, 9, 11, 11, 11, 9, 11, 12, 13, 13, 11, 10, 8, 19, 17, 14, 13, 10, 10, + 8, 3, 6, 6, 6, 7, 5, 2, 1, 4, 6, 6, 6, 5, 2, 1, 3, 5, 5, + 5, 6, 3, 2, 4, 5, 5, 6, 6, 5, 7, 8, 8, 8, 8, 7, 5, 14, 13, + 13, 11, 9, 7, 5, 21, 19, 15, 12, 9, 7, 6, 1, 1, 1, 0, 1, 1, 3, + 2, 2, 2, 1, 2, 1, 3, 5, 3, 3, 4, 4, 4, 5, 8, 6, 7, 7, 7, + 7, 7, 9, 12, 11, 11, 12, 10, 9, 14, 18, 16, 15, 14, 12, 11, 21, 24, 20, + 17, 15, 13, 12, 10, 9, 8, 8, 8, 7, 3, 11, 10, 9, 9, 9, 8, 3, 11, + 12, 12, 13, 12, 11, 7, 11, 16, 16, 16, 16, 15, 11, 15, 22, 21, 20, 21, 18, + 13, 19, 25, 26, 25, 22, 20, 14, 23, 28, 30, 27, 25, 21, 16, 18, 19, 17, 17, + 14, 9, 5, 18, 21, 19, 19, 15, 11, 7, 18, 23, 22, 22, 18, 14, 11, 18, 25, + 27, 25, 23, 19, 15, 21, 28, 32, 32, 26, 21, 16, 24, 32, 37, 36, 29, 23, 18, + 28, 34, 38, 38, 32, 26, 20, 26, 31, 29, 22, 17, 12, 8, 25, 31, 31, 24, 19, + 15, 11, 25, 30, 33, 28, 24, 18, 14, 26, 31, 37, 32, 27, 22, 18, 29, 35, 40, + 38, 31, 26, 20, 31, 38, 42, 42, 34, 28, 22, 34, 39, 44, 44, 37, 30, 24, 7, + 10, 12, 15, 15, 12, 10, 6, 9, 11, 14, 15, 13, 11, 5, 7, 11, 15, 16, 15, + 12, 4, 8, 11, 14, 17, 16, 13, 6, 9, 11, 14, 18, 16, 13, 11, 12, 14, 14, + 17, 16, 13, 17, 17, 15, 14, 16, 15, 13, 5, 8, 10, 13, 11, 9, 6, 4, 7, + 10, 12, 12, 9, 7, 3, 6, 9, 12, 12, 10, 8, 2, 6, 10, 12, 12, 11, 9, + 5, 8, 10, 12, 12, 12, 9, 12, 13, 14, 15, 12, 11, 9, 20, 19, 16, 14, 12, + 10, 9, 3, 6, 7, 6, 7, 5, 1, 1, 5, 6, 6, 6, 5, 2, 2, 4, 5, + 6, 6, 6, 4, 2, 4, 6, 6, 6, 6, 6, 7, 9, 9, 9, 10, 8, 6, 15, + 15, 14, 12, 10, 9, 6, 22, 21, 17, 14, 11, 9, 7, 2, 1, 1, 1, 0, 1, + 3, 3, 2, 2, 2, 2, 2, 3, 7, 3, 3, 4, 5, 5, 5, 9, 6, 8, 9, + 9, 8, 7, 10, 12, 12, 12, 13, 12, 10, 16, 19, 17, 16, 15, 14, 12, 22, 25, + 21, 18, 16, 15, 14, 10, 9, 8, 8, 8, 7, 2, 13, 11, 10, 9, 10, 9, 3, + 13, 12, 12, 13, 13, 12, 9, 13, 17, 17, 18, 17, 16, 12, 16, 23, 22, 22, 22, + 19, 14, 21, 27, 28, 26, 24, 21, 16, 24, 29, 31, 28, 27, 23, 17, 18, 19, 18, + 17, 13, 9, 5, 19, 21, 19, 18, 15, 12, 8, 18, 23, 22, 23, 19, 16, 12, 19, + 24, 28, 27, 23, 19, 16, 22, 29, 32, 31, 28, 23, 17, 27, 32, 39, 36, 29, 24, + 19, 30, 36, 38, 39, 33, 27, 21, 25, 29, 26, 21, 16, 12, 8, 25, 30, 29, 23, + 19, 16, 12, 26, 30, 31, 26, 23, 19, 15, 25, 32, 35, 31, 27, 24, 20, 29, 35, + 39, 38, 32, 26, 21, 32, 38, 43, 42, 35, 29, 23, 35, 40, 43, 45, 37, 31, 25, + 6, 8, 10, 12, 12, 9, 8, 6, 8, 9, 11, 12, 11, 9, 5, 7, 9, 12, 14, + 12, 11, 4, 7, 10, 13, 16, 14, 13, 6, 9, 12, 14, 18, 15, 13, 11, 13, 15, + 16, 17, 15, 13, 18, 18, 16, 15, 16, 15, 13, 5, 7, 8, 10, 8, 6, 5, 4, + 6, 8, 9, 9, 7, 6, 3, 6, 8, 10, 10, 9, 8, 2, 6, 9, 11, 11, 11, + 10, 6, 9, 11, 13, 13, 12, 9, 13, 14, 16, 15, 13, 12, 10, 22, 19, 17, 16, + 13, 11, 10, 3, 6, 5, 5, 5, 3, 2, 2, 5, 5, 4, 4, 4, 3, 2, 4, + 5, 5, 6, 6, 5, 3, 4, 6, 7, 7, 7, 8, 8, 9, 10, 11, 11, 10, 8, + 16, 17, 15, 14, 12, 10, 8, 23, 22, 18, 14, 12, 10, 8, 2, 2, 1, 1, 1, + 0, 2, 4, 2, 2, 2, 2, 3, 4, 8, 4, 3, 5, 6, 6, 6, 11, 6, 8, + 9, 9, 10, 8, 11, 13, 13, 14, 14, 12, 11, 16, 20, 18, 17, 16, 14, 13, 23, + 26, 22, 19, 17, 16, 15, 11, 9, 8, 8, 8, 7, 2, 14, 11, 10, 9, 10, 9, + 4, 14, 13, 12, 13, 14, 12, 9, 14, 17, 17, 17, 17, 17, 13, 16, 23, 23, 23, + 22, 19, 15, 21, 27, 28, 26, 23, 21, 17, 26, 31, 31, 28, 26, 22, 18, 18, 17, + 15, 13, 12, 9, 6, 18, 19, 16, 14, 12, 12, 9, 18, 21, 18, 19, 17, 15, 13, + 18, 23, 25, 24, 22, 19, 17, 22, 29, 31, 29, 26, 23, 18, 26, 33, 37, 34, 28, + 23, 20, 30, 36, 38, 37, 30, 25, 21, 22, 25, 22, 17, 13, 10, 9, 22, 25, 24, + 18, 15, 14, 12, 22, 25, 27, 22, 20, 18, 15, 22, 27, 33, 29, 25, 22, 20, 27, + 31, 37, 34, 30, 25, 21, 31, 36, 40, 40, 32, 27, 22, 35, 39, 42, 41, 35, 29, + 24, 9, 11, 13, 16, 16, 13, 10, 9, 11, 12, 15, 16, 14, 12, 8, 9, 12, 16, + 17, 15, 13, 8, 10, 13, 16, 19, 16, 14, 8, 11, 13, 17, 20, 18, 14, 11, 13, + 15, 16, 19, 18, 15, 18, 17, 16, 16, 18, 17, 14, 8, 10, 12, 13, 11, 8, 7, + 8, 9, 11, 13, 12, 10, 8, 7, 8, 11, 14, 13, 11, 9, 6, 8, 11, 14, 13, + 12, 11, 6, 10, 12, 14, 14, 13, 11, 13, 14, 16, 15, 14, 13, 11, 22, 19, 17, + 15, 13, 12, 11, 7, 8, 8, 7, 7, 5, 3, 6, 8, 8, 7, 7, 6, 4, 5, + 7, 7, 8, 8, 8, 6, 3, 7, 8, 8, 9, 9, 8, 7, 9, 10, 10, 10, 9, + 8, 16, 16, 15, 13, 11, 9, 8, 23, 22, 18, 14, 11, 9, 8, 5, 4, 3, 3, + 3, 3, 0, 2, 2, 3, 2, 2, 2, 2, 6, 2, 2, 3, 3, 3, 4, 10, 3, + 5, 6, 6, 6, 6, 9, 10, 10, 10, 10, 9, 7, 15, 18, 16, 14, 12, 10, 8, + 24, 25, 19, 15, 13, 11, 9, 4, 3, 2, 2, 2, 2, 0, 6, 3, 3, 2, 3, + 3, 2, 6, 4, 4, 5, 6, 6, 5, 6, 8, 9, 10, 10, 9, 8, 9, 14, 15, + 15, 15, 13, 9, 16, 20, 22, 20, 17, 14, 10, 22, 25, 25, 21, 19, 15, 11, 8, + 7, 6, 5, 3, 2, 1, 7, 10, 7, 6, 4, 4, 3, 8, 11, 10, 11, 9, 8, + 7, 8, 14, 17, 17, 14, 12, 10, 12, 19, 23, 23, 20, 16, 11, 18, 24, 30, 28, + 22, 17, 13, 24, 28, 31, 30, 24, 19, 14, 13, 16, 14, 8, 5, 3, 2, 13, 16, + 16, 10, 7, 6, 5, 13, 16, 19, 15, 12, 10, 8, 13, 18, 25, 21, 18, 15, 13, + 17, 24, 30, 28, 23, 19, 14, 22, 28, 34, 34, 27, 21, 15, 27, 32, 35, 35, 29, + 23, 17, 6, 10, 15, 18, 18, 16, 15, 5, 9, 14, 17, 18, 15, 13, 3, 8, 11, + 15, 16, 14, 11, 2, 5, 9, 11, 13, 13, 10, 1, 2, 6, 10, 12, 14, 10, 5, + 5, 5, 8, 11, 14, 10, 11, 9, 5, 7, 10, 14, 10, 3, 7, 12, 15, 16, 14, + 10, 2, 6, 11, 14, 15, 13, 8, 2, 5, 9, 11, 12, 11, 5, 2, 2, 6, 8, + 9, 8, 3, 2, 2, 3, 6, 7, 8, 3, 7, 7, 6, 5, 6, 6, 4, 15, 12, + 8, 5, 4, 5, 4, 2, 5, 7, 9, 11, 9, 5, 2, 3, 6, 8, 8, 8, 2, + 1, 2, 4, 5, 5, 5, 1, 0, 2, 2, 1, 2, 1, 1, 4, 4, 4, 4, 4, + 2, 1, 10, 9, 9, 8, 5, 3, 1, 16, 15, 11, 9, 6, 4, 2, 1, 1, 1, + 2, 3, 4, 2, 0, 1, 1, 2, 2, 1, 3, 1, 1, 1, 1, 1, 1, 3, 3, + 3, 3, 3, 4, 4, 4, 5, 7, 7, 7, 8, 7, 6, 9, 13, 11, 11, 10, 9, + 8, 16, 18, 14, 13, 12, 10, 9, 7, 7, 7, 8, 8, 7, 3, 8, 8, 9, 9, + 9, 8, 3, 8, 10, 10, 10, 11, 9, 5, 8, 13, 12, 13, 13, 12, 8, 11, 16, + 15, 15, 15, 14, 10, 14, 18, 19, 17, 16, 16, 12, 17, 20, 21, 18, 18, 16, 13, + 16, 16, 16, 16, 14, 10, 5, 15, 18, 17, 16, 14, 11, 7, 15, 19, 18, 17, 16, + 13, 8, 15, 19, 19, 18, 16, 15, 11, 16, 20, 22, 21, 18, 16, 13, 18, 22, 25, + 23, 20, 17, 14, 20, 24, 25, 25, 21, 18, 15, 21, 25, 22, 19, 16, 14, 8, 21, + 25, 25, 20, 16, 14, 10, 20, 25, 27, 21, 17, 15, 11, 21, 24, 27, 22, 18, 17, + 15, 21, 25, 28, 26, 21, 18, 16, 21, 25, 29, 28, 23, 19, 17, 24, 26, 29, 29, + 24, 20, 17, 7, 8, 9, 11, 11, 9, 7, 6, 7, 8, 10, 10, 8, 7, 5, 7, + 8, 9, 9, 8, 7, 4, 6, 7, 8, 8, 8, 8, 4, 7, 8, 8, 9, 8, 8, + 7, 8, 9, 9, 9, 8, 8, 13, 13, 11, 9, 9, 8, 7, 5, 7, 8, 9, 9, + 7, 6, 4, 7, 8, 8, 8, 7, 6, 3, 6, 7, 7, 7, 7, 6, 2, 5, 7, + 8, 7, 7, 7, 3, 5, 7, 8, 7, 7, 7, 8, 9, 10, 10, 8, 7, 7, 16, + 15, 12, 10, 8, 7, 7, 3, 6, 6, 6, 7, 6, 3, 2, 5, 6, 6, 6, 6, + 3, 1, 4, 5, 5, 6, 6, 3, 1, 4, 5, 5, 6, 6, 5, 5, 6, 6, 6, + 6, 6, 5, 11, 11, 11, 9, 7, 5, 5, 18, 17, 13, 10, 7, 5, 3, 2, 2, + 2, 2, 2, 2, 2, 1, 0, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, + 4, 4, 4, 4, 4, 4, 5, 6, 8, 8, 8, 8, 7, 6, 11, 14, 13, 12, 10, + 9, 8, 18, 20, 16, 14, 12, 10, 9, 7, 7, 7, 7, 7, 6, 2, 9, 9, 8, + 8, 8, 7, 3, 9, 10, 10, 10, 10, 8, 4, 9, 13, 13, 12, 13, 12, 8, 12, + 18, 17, 17, 18, 15, 10, 15, 21, 23, 21, 20, 17, 11, 19, 24, 26, 23, 22, 18, + 13, 16, 17, 17, 16, 13, 9, 5, 15, 20, 18, 18, 14, 10, 6, 15, 21, 20, 20, + 16, 12, 8, 16, 22, 24, 23, 19, 15, 11, 18, 24, 29, 28, 24, 19, 13, 20, 27, + 32, 31, 27, 21, 15, 25, 30, 34, 32, 28, 23, 17, 23, 29, 28, 22, 16, 12, 7, + 23, 29, 30, 24, 18, 13, 9, 23, 30, 33, 26, 20, 15, 11, 24, 29, 34, 29, 24, + 20, 15, 24, 31, 35, 34, 28, 23, 17, 27, 33, 37, 36, 30, 25, 19, 30, 35, 39, + 38, 33, 27, 22, 7, 10, 12, 14, 14, 12, 10, 7, 9, 12, 13, 14, 12, 10, 5, + 8, 10, 13, 13, 12, 11, 4, 8, 10, 12, 14, 13, 12, 5, 8, 10, 13, 15, 13, + 12, 8, 10, 11, 13, 14, 13, 11, 14, 14, 13, 12, 13, 13, 12, 5, 8, 11, 12, + 11, 10, 7, 5, 7, 10, 12, 11, 10, 7, 3, 6, 9, 11, 11, 10, 8, 3, 6, + 9, 11, 11, 11, 9, 5, 6, 8, 11, 11, 11, 9, 10, 11, 12, 12, 10, 10, 9, + 17, 16, 13, 12, 10, 9, 9, 4, 6, 7, 7, 8, 6, 3, 2, 5, 6, 7, 7, + 6, 3, 1, 4, 5, 5, 6, 6, 3, 1, 4, 5, 6, 6, 6, 4, 6, 7, 7, + 7, 7, 6, 5, 12, 12, 11, 10, 8, 6, 4, 19, 19, 14, 11, 8, 6, 5, 2, + 2, 1, 1, 2, 2, 3, 1, 1, 0, 1, 1, 1, 3, 2, 2, 2, 2, 2, 2, + 4, 6, 5, 5, 5, 5, 5, 5, 7, 9, 9, 9, 9, 9, 7, 12, 15, 14, 13, + 11, 10, 9, 19, 21, 17, 15, 13, 11, 11, 8, 7, 7, 7, 7, 6, 3, 9, 9, + 8, 8, 8, 7, 3, 9, 10, 10, 10, 10, 9, 5, 9, 14, 14, 14, 14, 13, 9, + 13, 19, 19, 18, 18, 16, 11, 17, 22, 24, 23, 20, 18, 12, 21, 26, 28, 24, 23, + 20, 14, 16, 18, 17, 16, 13, 9, 4, 16, 20, 18, 18, 14, 9, 6, 17, 21, 21, + 20, 16, 12, 8, 17, 24, 25, 24, 21, 16, 12, 20, 25, 30, 29, 25, 19, 14, 22, + 28, 35, 32, 28, 21, 16, 25, 31, 35, 36, 28, 23, 18, 24, 30, 27, 21, 16, 12, + 7, 24, 30, 30, 23, 18, 13, 9, 24, 30, 33, 26, 21, 16, 12, 24, 31, 36, 30, + 24, 20, 16, 25, 32, 38, 34, 29, 23, 18, 28, 34, 39, 40, 33, 26, 20, 31, 37, + 41, 41, 35, 28, 21, 8, 10, 13, 16, 16, 13, 11, 7, 9, 12, 15, 16, 14, 11, + 6, 8, 11, 14, 16, 14, 12, 5, 9, 11, 14, 17, 15, 13, 6, 8, 11, 14, 17, + 16, 13, 10, 11, 12, 14, 17, 16, 13, 16, 15, 13, 13, 15, 15, 13, 6, 8, 11, + 14, 12, 10, 7, 5, 8, 10, 13, 12, 10, 7, 4, 7, 10, 12, 12, 10, 9, 3, + 7, 10, 12, 12, 12, 9, 5, 7, 9, 12, 12, 12, 9, 11, 11, 13, 13, 11, 12, + 9, 19, 17, 15, 13, 10, 10, 9, 4, 7, 7, 7, 8, 6, 2, 3, 5, 7, 7, + 7, 6, 2, 1, 5, 6, 6, 6, 6, 4, 1, 5, 6, 6, 7, 7, 5, 7, 8, + 8, 8, 8, 7, 5, 14, 14, 13, 11, 9, 7, 5, 21, 20, 15, 12, 9, 7, 5, + 2, 1, 1, 1, 2, 2, 2, 2, 1, 1, 0, 1, 1, 3, 3, 2, 2, 2, 3, + 3, 4, 6, 5, 6, 6, 6, 6, 6, 8, 11, 10, 10, 10, 9, 8, 14, 17, 15, + 14, 12, 11, 9, 21, 23, 18, 16, 14, 12, 11, 8, 8, 7, 7, 7, 6, 3, 10, + 9, 8, 8, 8, 7, 3, 10, 11, 11, 11, 11, 10, 6, 10, 15, 15, 15, 15, 14, + 10, 13, 20, 20, 19, 19, 16, 11, 18, 25, 25, 24, 21, 18, 13, 22, 27, 28, 26, + 23, 20, 15, 17, 18, 17, 16, 12, 8, 4, 17, 20, 18, 17, 14, 10, 6, 17, 22, + 22, 21, 17, 13, 9, 17, 24, 26, 25, 21, 17, 13, 20, 26, 30, 30, 25, 20, 15, + 23, 29, 36, 33, 28, 22, 17, 27, 32, 36, 37, 30, 24, 19, 24, 30, 28, 21, 16, + 11, 7, 24, 29, 29, 23, 18, 13, 10, 24, 30, 33, 27, 21, 17, 13, 24, 31, 37, + 30, 25, 21, 17, 28, 33, 39, 36, 31, 24, 19, 30, 36, 41, 41, 33, 27, 20, 33, + 38, 43, 43, 36, 28, 22, 8, 11, 14, 17, 17, 15, 12, 7, 10, 13, 17, 17, 14, + 12, 6, 9, 12, 15, 18, 15, 13, 5, 9, 12, 15, 19, 16, 14, 6, 9, 12, 15, + 19, 17, 14, 10, 12, 13, 14, 18, 17, 14, 16, 15, 14, 14, 16, 16, 14, 6, 9, + 11, 15, 14, 11, 8, 5, 8, 11, 13, 13, 10, 8, 4, 7, 10, 13, 13, 11, 9, + 3, 7, 11, 13, 13, 12, 10, 5, 8, 10, 12, 13, 12, 10, 12, 12, 14, 14, 12, + 12, 10, 19, 17, 15, 14, 11, 11, 10, 4, 7, 8, 8, 9, 7, 3, 3, 6, 7, + 7, 7, 6, 3, 1, 5, 6, 7, 7, 7, 4, 1, 5, 7, 7, 7, 7, 6, 7, + 8, 9, 8, 8, 7, 6, 14, 14, 14, 12, 9, 7, 6, 21, 20, 16, 12, 10, 8, + 6, 2, 2, 1, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 2, 4, 2, 2, 3, + 3, 3, 3, 7, 5, 6, 6, 6, 6, 5, 8, 11, 10, 10, 11, 9, 8, 14, 17, + 15, 14, 12, 11, 10, 21, 23, 19, 16, 14, 12, 11, 8, 7, 7, 7, 7, 6, 2, + 10, 9, 8, 8, 8, 7, 2, 10, 11, 10, 11, 11, 10, 6, 10, 15, 15, 15, 15, + 14, 10, 14, 21, 20, 20, 19, 17, 12, 18, 24, 26, 24, 21, 18, 13, 23, 28, 29, + 26, 24, 21, 15, 17, 18, 17, 15, 12, 9, 4, 16, 19, 18, 17, 13, 10, 6, 17, + 22, 21, 21, 18, 13, 9, 16, 24, 26, 25, 22, 18, 13, 20, 27, 30, 30, 26, 21, + 15, 24, 30, 37, 35, 28, 23, 17, 28, 32, 37, 37, 30, 24, 19, 24, 28, 25, 20, + 15, 11, 7, 24, 28, 28, 22, 17, 13, 10, 24, 29, 31, 25, 21, 17, 13, 24, 30, + 35, 31, 25, 21, 17, 28, 33, 38, 35, 30, 24, 19, 30, 35, 41, 40, 32, 27, 21, + 34, 39, 41, 42, 35, 29, 23, 8, 11, 14, 17, 17, 15, 11, 7, 10, 13, 16, 16, + 14, 12, 6, 9, 12, 15, 17, 16, 13, 5, 9, 12, 16, 18, 16, 14, 6, 9, 12, + 15, 18, 17, 14, 10, 12, 13, 14, 18, 17, 14, 17, 16, 14, 14, 16, 17, 14, 6, + 9, 12, 14, 13, 11, 8, 5, 8, 11, 13, 13, 10, 8, 4, 7, 10, 14, 13, 11, + 9, 3, 7, 11, 13, 13, 12, 10, 5, 8, 10, 13, 13, 12, 10, 11, 12, 14, 13, + 12, 12, 10, 19, 17, 15, 14, 11, 11, 9, 4, 7, 8, 8, 9, 7, 3, 3, 6, + 7, 7, 7, 6, 3, 2, 5, 6, 7, 7, 7, 4, 1, 5, 7, 7, 7, 7, 6, + 6, 8, 9, 9, 8, 7, 6, 14, 14, 13, 11, 9, 8, 6, 21, 19, 15, 12, 10, + 8, 6, 2, 2, 1, 1, 2, 3, 2, 1, 1, 1, 1, 0, 0, 2, 5, 2, 2, + 3, 3, 3, 3, 7, 5, 6, 6, 6, 6, 5, 9, 11, 10, 11, 10, 10, 8, 14, + 17, 16, 14, 13, 11, 10, 21, 23, 19, 16, 14, 13, 12, 9, 8, 7, 6, 7, 6, + 2, 11, 10, 8, 8, 8, 7, 2, 11, 11, 10, 11, 11, 10, 6, 10, 15, 15, 15, + 15, 14, 10, 14, 21, 20, 20, 19, 16, 12, 18, 24, 25, 23, 21, 18, 13, 23, 27, + 29, 25, 22, 20, 15, 16, 16, 14, 13, 11, 8, 5, 16, 18, 15, 13, 12, 10, 6, + 16, 20, 17, 17, 15, 12, 10, 17, 21, 23, 21, 19, 17, 13, 20, 26, 28, 26, 23, + 20, 15, 24, 29, 33, 30, 25, 21, 17, 27, 33, 34, 33, 26, 23, 19, 21, 23, 20, + 15, 13, 10, 7, 21, 24, 23, 17, 14, 13, 9, 21, 24, 25, 21, 18, 16, 13, 21, + 25, 30, 25, 22, 19, 16, 25, 29, 34, 32, 27, 23, 19, 29, 33, 37, 36, 29, 24, + 20, 32, 35, 37, 38, 32, 26, 21, 9, 11, 14, 17, 17, 14, 11, 9, 11, 13, 16, + 17, 13, 11, 8, 10, 12, 15, 17, 15, 12, 8, 10, 13, 16, 18, 15, 13, 8, 10, + 13, 15, 19, 17, 13, 11, 11, 13, 15, 18, 16, 13, 16, 15, 14, 14, 16, 17, 13, + 8, 10, 12, 14, 13, 10, 7, 8, 9, 11, 13, 13, 9, 7, 7, 8, 11, 13, 12, + 10, 8, 6, 9, 12, 14, 13, 12, 9, 6, 9, 11, 13, 13, 12, 10, 11, 12, 13, + 13, 12, 11, 10, 19, 17, 14, 13, 11, 11, 10, 7, 9, 9, 8, 9, 7, 4, 6, + 8, 8, 7, 7, 6, 3, 5, 8, 8, 7, 7, 6, 5, 4, 7, 8, 8, 7, 7, + 6, 7, 9, 9, 8, 8, 7, 6, 14, 14, 13, 11, 9, 7, 6, 21, 19, 14, 11, + 9, 7, 6, 5, 4, 3, 3, 3, 4, 2, 3, 3, 3, 2, 2, 2, 0, 2, 2, + 2, 3, 2, 2, 2, 7, 3, 4, 5, 4, 4, 4, 8, 9, 9, 8, 8, 7, 5, + 14, 15, 14, 11, 10, 8, 6, 20, 21, 16, 13, 11, 9, 7, 5, 3, 2, 2, 2, + 2, 2, 6, 4, 3, 2, 3, 2, 0, 5, 5, 4, 4, 4, 4, 3, 5, 8, 8, + 8, 8, 8, 6, 9, 14, 13, 13, 13, 10, 7, 14, 19, 20, 18, 15, 12, 8, 20, + 23, 23, 19, 17, 14, 9, 9, 9, 7, 6, 4, 3, 2, 9, 11, 9, 8, 5, 3, + 2, 8, 12, 11, 11, 9, 6, 5, 9, 14, 17, 16, 13, 10, 8, 12, 18, 22, 21, + 18, 14, 9, 17, 23, 27, 25, 20, 15, 11, 22, 26, 29, 28, 23, 17, 12, 14, 18, + 15, 10, 6, 3, 2, 13, 18, 18, 12, 8, 5, 3, 14, 18, 20, 15, 12, 9, 6, + 14, 19, 25, 21, 17, 13, 11, 17, 23, 28, 26, 22, 17, 12, 22, 26, 32, 32, 25, + 19, 14, 26, 30, 33, 33, 27, 20, 15, 10, 14, 18, 22, 22, 20, 17, 8, 12, 17, + 20, 22, 19, 16, 7, 11, 14, 17, 20, 17, 13, 5, 9, 12, 15, 16, 15, 13, 3, + 6, 10, 13, 15, 16, 14, 4, 5, 8, 11, 14, 16, 13, 10, 7, 7, 11, 13, 15, + 14, 7, 11, 15, 18, 20, 17, 13, 5, 9, 14, 17, 19, 15, 12, 4, 8, 12, 13, + 15, 14, 9, 3, 6, 9, 11, 12, 13, 8, 2, 3, 7, 10, 12, 12, 8, 6, 5, + 6, 8, 10, 11, 8, 12, 10, 6, 8, 8, 8, 8, 4, 8, 10, 12, 13, 12, 9, + 2, 7, 9, 11, 11, 11, 7, 1, 5, 8, 9, 9, 10, 4, 1, 3, 4, 5, 5, + 5, 1, 3, 3, 3, 3, 3, 3, 1, 9, 8, 7, 5, 4, 2, 1, 14, 13, 9, + 7, 5, 4, 1, 2, 2, 4, 5, 7, 8, 6, 1, 1, 2, 3, 4, 5, 2, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 6, 5, + 4, 9, 10, 9, 8, 8, 7, 6, 14, 15, 11, 10, 9, 8, 8, 6, 6, 6, 6, + 6, 4, 6, 7, 7, 8, 8, 8, 6, 3, 7, 9, 8, 8, 9, 8, 3, 7, 10, + 10, 10, 10, 9, 6, 9, 13, 12, 12, 12, 11, 8, 11, 15, 15, 14, 13, 12, 9, + 14, 17, 17, 15, 14, 13, 10, 13, 13, 13, 13, 11, 8, 5, 12, 15, 14, 13, 12, + 9, 6, 12, 16, 15, 14, 12, 10, 7, 13, 15, 16, 15, 13, 11, 9, 13, 16, 18, + 17, 16, 12, 10, 14, 18, 22, 20, 17, 14, 11, 16, 20, 22, 21, 18, 15, 12, 17, + 20, 19, 16, 13, 11, 6, 18, 21, 21, 16, 13, 11, 8, 17, 21, 23, 17, 14, 11, + 9, 17, 21, 23, 19, 15, 13, 11, 17, 21, 24, 21, 18, 15, 12, 18, 22, 25, 25, + 19, 16, 13, 20, 23, 26, 25, 21, 16, 14, 7, 8, 10, 13, 13, 11, 9, 7, 8, + 10, 12, 13, 10, 8, 6, 8, 9, 10, 11, 9, 7, 5, 7, 8, 9, 10, 8, 8, + 5, 7, 8, 9, 10, 9, 8, 7, 8, 9, 9, 9, 8, 8, 13, 13, 11, 9, 9, + 8, 8, 7, 8, 9, 10, 11, 9, 7, 6, 7, 8, 10, 11, 8, 7, 4, 7, 8, + 8, 8, 7, 6, 3, 6, 7, 8, 7, 7, 7, 3, 6, 8, 8, 8, 8, 7, 8, + 9, 10, 9, 7, 7, 7, 16, 15, 12, 10, 8, 7, 7, 4, 7, 7, 7, 7, 7, + 5, 3, 6, 7, 7, 7, 6, 4, 2, 5, 6, 6, 6, 6, 5, 1, 5, 6, 6, + 6, 6, 6, 5, 6, 6, 6, 6, 6, 6, 11, 11, 10, 9, 7, 5, 6, 18, 17, + 13, 10, 7, 5, 4, 2, 3, 3, 3, 3, 4, 2, 1, 1, 2, 2, 2, 2, 2, + 1, 0, 1, 1, 1, 1, 2, 3, 2, 2, 3, 3, 3, 3, 5, 7, 6, 6, 7, + 6, 5, 11, 12, 12, 11, 9, 8, 7, 18, 20, 15, 13, 11, 9, 8, 6, 6, 6, + 6, 6, 5, 2, 7, 7, 7, 7, 7, 6, 2, 8, 9, 9, 8, 9, 7, 3, 8, + 12, 11, 11, 12, 11, 7, 10, 16, 16, 15, 17, 14, 9, 13, 19, 22, 20, 19, 16, + 11, 18, 23, 24, 22, 20, 18, 12, 14, 16, 15, 16, 12, 8, 4, 14, 18, 17, 18, + 14, 9, 5, 14, 20, 19, 20, 16, 11, 7, 14, 20, 22, 22, 19, 14, 10, 16, 22, + 27, 24, 22, 18, 12, 19, 25, 30, 28, 24, 20, 14, 23, 28, 31, 30, 26, 22, 16, + 22, 28, 26, 20, 16, 11, 6, 22, 28, 28, 23, 18, 12, 8, 22, 27, 31, 24, 19, + 14, 10, 22, 27, 32, 25, 22, 18, 14, 23, 28, 33, 30, 25, 22, 16, 26, 30, 34, + 32, 28, 24, 18, 28, 31, 34, 35, 29, 25, 21, 9, 12, 14, 14, 15, 13, 12, 8, + 10, 13, 14, 15, 13, 11, 6, 10, 12, 14, 14, 12, 11, 5, 8, 11, 13, 14, 13, + 12, 6, 8, 11, 14, 15, 14, 12, 8, 9, 11, 13, 15, 14, 12, 14, 14, 12, 12, + 13, 14, 12, 6, 10, 12, 13, 13, 11, 9, 6, 9, 11, 13, 13, 11, 8, 4, 7, + 10, 12, 12, 10, 9, 3, 7, 10, 12, 11, 11, 9, 4, 6, 9, 11, 11, 12, 10, + 9, 10, 12, 12, 11, 11, 9, 17, 15, 13, 12, 10, 10, 9, 4, 7, 9, 9, 9, + 8, 4, 3, 6, 8, 8, 8, 7, 4, 2, 5, 7, 7, 7, 7, 4, 2, 5, 6, + 6, 7, 7, 5, 6, 6, 7, 6, 7, 6, 5, 12, 12, 11, 10, 7, 6, 5, 19, + 18, 14, 10, 8, 6, 4, 2, 2, 3, 3, 3, 3, 2, 1, 1, 2, 2, 2, 2, + 2, 1, 1, 0, 0, 0, 0, 2, 4, 3, 3, 4, 4, 4, 5, 6, 8, 7, 7, + 8, 7, 6, 12, 14, 12, 11, 10, 8, 7, 19, 20, 16, 13, 11, 10, 9, 7, 6, + 6, 6, 6, 5, 2, 8, 8, 7, 7, 8, 6, 2, 8, 9, 9, 9, 9, 7, 4, + 8, 13, 12, 12, 12, 11, 7, 11, 17, 17, 16, 16, 14, 9, 15, 21, 23, 20, 19, + 16, 11, 19, 24, 26, 23, 21, 18, 13, 15, 17, 15, 16, 12, 8, 4, 15, 18, 18, + 17, 13, 9, 5, 15, 20, 19, 19, 15, 11, 7, 15, 21, 23, 23, 19, 15, 11, 18, + 25, 28, 26, 23, 18, 12, 20, 26, 33, 31, 26, 19, 14, 23, 29, 33, 33, 28, 22, + 16, 22, 28, 27, 21, 15, 11, 6, 22, 28, 30, 22, 17, 12, 8, 23, 28, 32, 25, + 19, 15, 11, 23, 29, 34, 28, 22, 18, 15, 24, 31, 37, 34, 28, 21, 16, 27, 34, + 39, 37, 31, 25, 18, 30, 35, 40, 40, 33, 26, 20, 9, 13, 16, 19, 19, 17, 14, + 8, 12, 15, 18, 19, 16, 13, 7, 10, 14, 17, 18, 15, 13, 6, 9, 12, 15, 17, + 15, 13, 6, 9, 11, 15, 17, 15, 13, 8, 9, 11, 14, 16, 16, 13, 14, 14, 12, + 13, 16, 15, 13, 7, 11, 14, 17, 16, 13, 10, 6, 9, 13, 16, 16, 13, 9, 5, + 8, 11, 14, 14, 11, 8, 4, 7, 10, 12, 12, 12, 9, 5, 7, 10, 12, 12, 12, + 9, 9, 10, 11, 12, 11, 11, 9, 17, 15, 13, 11, 10, 10, 9, 5, 8, 9, 10, + 11, 9, 6, 4, 6, 8, 9, 10, 9, 5, 3, 5, 7, 7, 7, 7, 4, 2, 6, + 6, 6, 6, 7, 5, 6, 7, 7, 6, 6, 6, 5, 12, 12, 11, 9, 7, 5, 5, + 19, 17, 13, 10, 7, 5, 4, 3, 2, 3, 4, 4, 5, 3, 1, 2, 2, 3, 3, + 3, 3, 1, 1, 0, 0, 0, 0, 2, 4, 3, 3, 3, 3, 3, 4, 6, 8, 7, + 7, 7, 7, 5, 12, 14, 12, 11, 10, 8, 7, 19, 20, 16, 13, 11, 10, 8, 7, + 6, 6, 7, 7, 6, 3, 8, 8, 7, 8, 8, 7, 3, 8, 9, 9, 9, 9, 7, + 4, 8, 13, 12, 12, 12, 11, 7, 11, 17, 17, 16, 16, 14, 9, 15, 21, 22, 21, + 18, 16, 11, 19, 24, 25, 23, 21, 18, 12, 15, 17, 16, 16, 13, 9, 5, 15, 19, + 18, 17, 14, 9, 5, 15, 20, 19, 18, 14, 11, 7, 15, 22, 24, 22, 19, 15, 10, + 18, 24, 28, 26, 23, 18, 12, 21, 26, 34, 32, 25, 20, 14, 24, 29, 34, 33, 27, + 22, 16, 23, 28, 27, 21, 16, 12, 7, 23, 29, 29, 22, 17, 12, 8, 23, 28, 32, + 24, 19, 15, 10, 22, 29, 35, 29, 22, 18, 14, 23, 30, 36, 34, 27, 22, 16, 27, + 32, 39, 38, 31, 24, 18, 30, 36, 40, 40, 33, 26, 20, 10, 14, 18, 20, 21, 19, + 15, 8, 12, 16, 20, 21, 17, 13, 7, 10, 15, 18, 19, 16, 13, 6, 9, 12, 15, + 19, 16, 13, 6, 9, 12, 15, 18, 16, 14, 8, 9, 11, 14, 18, 17, 13, 14, 13, + 12, 13, 16, 17, 14, 7, 11, 15, 18, 17, 14, 11, 6, 10, 13, 16, 17, 13, 9, + 5, 8, 12, 14, 14, 11, 9, 4, 7, 10, 13, 13, 12, 10, 5, 7, 10, 12, 12, + 12, 9, 10, 10, 11, 12, 12, 11, 10, 17, 15, 12, 12, 10, 11, 9, 5, 8, 10, + 11, 12, 10, 6, 4, 7, 9, 10, 10, 9, 5, 3, 6, 7, 7, 7, 7, 4, 1, + 6, 6, 6, 7, 7, 5, 6, 7, 7, 6, 6, 6, 5, 13, 12, 11, 9, 7, 6, + 5, 19, 17, 13, 10, 7, 5, 4, 3, 3, 3, 4, 5, 6, 3, 1, 1, 2, 3, + 3, 3, 2, 1, 1, 0, 0, 0, 0, 1, 4, 3, 4, 3, 3, 3, 3, 6, 8, + 7, 7, 7, 6, 5, 13, 14, 12, 11, 9, 8, 6, 19, 21, 15, 13, 11, 9, 8, + 7, 6, 6, 6, 7, 6, 3, 9, 8, 7, 7, 8, 6, 2, 9, 10, 9, 8, 8, + 7, 3, 9, 13, 12, 12, 12, 11, 7, 12, 18, 17, 16, 16, 13, 8, 15, 21, 22, + 20, 18, 15, 10, 19, 24, 26, 23, 21, 17, 12, 15, 16, 15, 15, 12, 9, 4, 15, + 19, 17, 17, 13, 9, 4, 15, 20, 19, 18, 14, 10, 7, 15, 21, 23, 21, 18, 14, + 10, 18, 24, 29, 26, 23, 17, 12, 20, 27, 33, 31, 25, 19, 14, 24, 29, 33, 33, + 28, 21, 15, 22, 27, 26, 20, 15, 11, 7, 23, 27, 27, 21, 16, 12, 7, 22, 27, + 29, 23, 18, 14, 10, 23, 28, 33, 27, 23, 18, 13, 25, 30, 35, 33, 26, 22, 16, + 27, 32, 38, 38, 30, 23, 18, 29, 34, 38, 37, 32, 25, 20, 10, 14, 17, 21, 21, + 18, 15, 9, 12, 15, 20, 20, 17, 13, 7, 11, 14, 17, 19, 15, 13, 6, 9, 12, + 16, 18, 16, 14, 6, 9, 12, 15, 19, 17, 14, 9, 10, 11, 14, 18, 17, 14, 14, + 13, 12, 14, 17, 17, 13, 7, 11, 15, 18, 17, 15, 11, 6, 10, 13, 16, 17, 13, + 9, 5, 8, 12, 15, 14, 11, 9, 4, 8, 11, 13, 13, 12, 9, 5, 7, 10, 12, + 13, 12, 10, 10, 10, 11, 12, 12, 12, 10, 16, 14, 12, 12, 11, 11, 10, 5, 8, + 10, 11, 12, 10, 6, 4, 7, 9, 10, 10, 9, 5, 3, 6, 7, 8, 7, 7, 4, + 2, 6, 7, 7, 7, 7, 5, 6, 7, 7, 7, 7, 6, 5, 13, 12, 11, 9, 7, + 5, 5, 17, 16, 12, 10, 7, 5, 4, 3, 3, 3, 4, 5, 6, 4, 1, 1, 2, + 3, 3, 3, 2, 1, 1, 0, 0, 0, 0, 1, 4, 4, 4, 3, 3, 3, 3, 7, + 9, 8, 7, 8, 6, 5, 13, 14, 12, 10, 9, 8, 6, 18, 19, 15, 13, 11, 9, + 8, 7, 6, 6, 6, 7, 6, 4, 9, 8, 7, 7, 8, 6, 2, 9, 10, 9, 8, + 8, 7, 3, 9, 14, 13, 12, 12, 10, 7, 12, 18, 17, 16, 16, 14, 9, 15, 21, + 22, 20, 18, 15, 10, 18, 23, 24, 22, 19, 17, 12, 15, 15, 14, 13, 11, 9, 4, + 16, 17, 15, 14, 12, 9, 4, 15, 19, 17, 15, 12, 10, 7, 15, 20, 21, 18, 16, + 14, 10, 18, 23, 26, 23, 20, 17, 12, 21, 25, 31, 27, 22, 18, 14, 23, 28, 31, + 29, 24, 20, 15, 20, 23, 20, 15, 13, 11, 7, 21, 23, 22, 17, 13, 11, 7, 20, + 23, 23, 19, 15, 13, 10, 20, 24, 28, 22, 18, 17, 14, 23, 26, 30, 28, 23, 19, + 16, 26, 29, 33, 32, 25, 21, 17, 28, 31, 34, 34, 27, 22, 18, 11, 13, 16, 19, + 19, 16, 13, 10, 12, 15, 18, 18, 15, 11, 8, 11, 14, 16, 17, 14, 11, 7, 9, + 12, 15, 17, 15, 12, 8, 10, 12, 15, 18, 15, 12, 8, 9, 12, 14, 17, 16, 12, + 12, 12, 11, 13, 16, 16, 12, 9, 11, 14, 16, 15, 12, 9, 7, 10, 12, 15, 14, + 11, 8, 7, 9, 12, 13, 12, 10, 7, 6, 9, 11, 13, 12, 10, 8, 6, 8, 10, + 12, 12, 11, 9, 10, 9, 10, 12, 11, 11, 8, 15, 13, 11, 11, 10, 9, 8, 7, + 9, 10, 10, 11, 9, 6, 6, 8, 9, 9, 9, 7, 4, 4, 7, 8, 7, 6, 6, + 4, 4, 8, 7, 7, 6, 6, 5, 6, 8, 7, 7, 6, 6, 5, 12, 11, 10, 8, + 6, 5, 5, 16, 15, 11, 9, 6, 5, 4, 5, 4, 4, 4, 5, 6, 4, 3, 3, + 4, 4, 3, 3, 2, 2, 2, 2, 2, 1, 1, 0, 4, 2, 3, 3, 2, 2, 2, + 7, 7, 6, 6, 6, 5, 3, 12, 13, 11, 9, 7, 6, 4, 17, 18, 13, 10, 8, + 7, 5, 4, 4, 3, 3, 3, 4, 4, 5, 5, 3, 3, 3, 3, 2, 6, 5, 4, + 4, 4, 3, 2, 5, 9, 8, 7, 7, 6, 4, 8, 14, 13, 12, 12, 9, 5, 13, + 17, 18, 16, 14, 11, 7, 16, 20, 21, 18, 15, 13, 8, 10, 10, 9, 9, 7, 4, + 3, 9, 12, 11, 10, 8, 4, 2, 9, 13, 12, 12, 8, 5, 3, 9, 15, 16, 15, + 12, 9, 6, 13, 18, 22, 20, 17, 12, 8, 16, 21, 27, 24, 19, 14, 10, 20, 24, + 27, 27, 21, 16, 11, 15, 19, 18, 13, 9, 6, 3, 15, 20, 20, 15, 10, 6, 3, + 15, 20, 22, 16, 12, 8, 5, 15, 20, 25, 20, 16, 13, 9, 18, 23, 28, 26, 21, + 16, 11, 21, 26, 31, 30, 23, 17, 13, 24, 29, 31, 32, 25, 20, 14, 13, 16, 20, + 25, 25, 24, 19, 11, 14, 18, 23, 25, 21, 17, 10, 14, 17, 20, 23, 19, 16, 8, + 12, 14, 17, 20, 18, 15, 6, 9, 12, 15, 17, 18, 15, 5, 8, 11, 13, 16, 18, + 15, 7, 8, 9, 13, 15, 18, 15, 9, 14, 17, 20, 21, 19, 15, 8, 13, 15, 19, + 21, 18, 14, 7, 11, 14, 17, 17, 15, 12, 6, 9, 12, 14, 14, 14, 11, 3, 7, + 10, 12, 13, 14, 11, 4, 6, 9, 11, 12, 12, 11, 9, 7, 8, 10, 10, 11, 11, + 7, 11, 13, 14, 16, 15, 11, 5, 10, 11, 13, 13, 14, 9, 4, 8, 10, 11, 11, + 11, 7, 3, 5, 7, 8, 8, 8, 5, 2, 4, 6, 6, 6, 6, 5, 6, 6, 5, + 5, 5, 5, 5, 10, 9, 7, 4, 3, 4, 4, 4, 6, 7, 7, 9, 11, 11, 3, + 4, 6, 6, 7, 8, 7, 1, 3, 4, 4, 4, 4, 3, 0, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 2, 6, 7, 6, 5, 4, 4, 3, 10, 12, 8, 6, + 5, 4, 4, 4, 4, 4, 4, 6, 8, 10, 4, 5, 5, 5, 5, 5, 7, 4, 5, + 6, 5, 5, 5, 2, 4, 7, 6, 6, 6, 5, 3, 5, 9, 8, 8, 8, 7, 4, + 7, 11, 11, 11, 9, 8, 5, 10, 13, 13, 12, 11, 9, 6, 9, 10, 9, 9, 8, + 6, 8, 9, 11, 10, 10, 8, 6, 4, 9, 12, 11, 11, 9, 6, 4, 9, 12, 12, + 12, 10, 7, 5, 9, 13, 15, 14, 12, 9, 6, 11, 14, 18, 16, 13, 10, 7, 13, + 16, 18, 18, 14, 11, 8, 14, 17, 16, 12, 10, 7, 6, 14, 18, 17, 14, 10, 7, + 5, 14, 17, 19, 14, 11, 8, 5, 13, 16, 20, 15, 12, 9, 7, 13, 17, 20, 17, + 15, 11, 8, 14, 18, 21, 20, 16, 12, 9, 16, 19, 22, 22, 17, 14, 10, 10, 11, + 14, 17, 17, 14, 12, 9, 11, 13, 16, 17, 14, 11, 9, 11, 12, 13, 14, 13, 10, + 8, 9, 10, 12, 13, 10, 8, 6, 7, 8, 9, 11, 9, 8, 6, 7, 8, 8, 10, + 9, 8, 12, 12, 9, 8, 9, 9, 8, 9, 10, 12, 14, 14, 12, 10, 8, 10, 11, + 13, 14, 11, 9, 7, 9, 10, 11, 11, 10, 8, 6, 8, 9, 9, 9, 8, 7, 4, + 6, 7, 8, 7, 7, 7, 7, 8, 9, 8, 7, 7, 7, 15, 13, 11, 8, 6, 7, + 7, 7, 9, 10, 9, 10, 9, 8, 5, 8, 9, 9, 9, 9, 7, 4, 8, 9, 9, + 8, 8, 7, 3, 6, 6, 7, 7, 7, 6, 3, 4, 5, 6, 6, 6, 6, 9, 9, + 10, 8, 6, 6, 6, 17, 16, 12, 9, 6, 5, 5, 4, 5, 6, 6, 6, 7, 3, + 3, 4, 5, 5, 5, 5, 3, 2, 2, 3, 3, 4, 4, 2, 0, 0, 0, 0, 0, + 0, 0, 4, 5, 4, 4, 4, 4, 3, 9, 11, 10, 9, 7, 5, 4, 17, 19, 14, + 10, 9, 7, 6, 5, 5, 6, 6, 6, 5, 3, 6, 7, 7, 7, 8, 6, 3, 6, + 8, 9, 9, 9, 7, 3, 6, 10, 9, 9, 10, 9, 4, 8, 14, 14, 14, 14, 12, + 6, 11, 17, 19, 17, 16, 14, 8, 16, 21, 21, 19, 17, 16, 10, 13, 16, 16, 16, + 13, 8, 3, 14, 18, 17, 17, 14, 9, 5, 14, 19, 20, 18, 15, 10, 6, 14, 19, + 20, 19, 17, 13, 8, 14, 20, 22, 21, 18, 16, 10, 17, 21, 26, 23, 21, 17, 12, + 20, 23, 26, 25, 21, 19, 14, 22, 26, 25, 20, 16, 11, 6, 21, 26, 26, 21, 17, + 13, 8, 22, 26, 28, 23, 19, 14, 9, 21, 26, 28, 23, 19, 16, 12, 21, 25, 28, + 25, 20, 18, 14, 22, 26, 29, 28, 23, 19, 16, 23, 26, 30, 28, 24, 21, 17, 13, + 16, 18, 20, 19, 17, 16, 11, 14, 17, 19, 20, 17, 15, 10, 14, 17, 18, 18, 15, + 13, 8, 11, 14, 16, 17, 14, 12, 6, 9, 12, 13, 15, 13, 12, 5, 8, 11, 13, + 15, 14, 12, 11, 11, 10, 13, 14, 14, 12, 10, 13, 16, 18, 17, 16, 13, 9, 12, + 16, 18, 17, 16, 13, 7, 11, 14, 16, 16, 14, 11, 6, 9, 12, 14, 13, 12, 10, + 4, 7, 10, 12, 12, 12, 10, 7, 8, 9, 11, 11, 11, 10, 14, 12, 10, 10, 10, + 10, 10, 7, 11, 13, 14, 15, 13, 9, 6, 10, 12, 13, 13, 12, 8, 5, 8, 11, + 11, 11, 11, 7, 3, 6, 7, 7, 8, 8, 5, 3, 5, 6, 6, 6, 7, 5, 9, + 9, 9, 7, 5, 5, 5, 16, 15, 11, 8, 5, 5, 4, 5, 5, 6, 7, 8, 8, + 5, 3, 4, 5, 6, 6, 6, 4, 2, 2, 3, 4, 4, 4, 3, 0, 0, 0, 0, + 0, 0, 0, 4, 4, 4, 4, 4, 3, 2, 9, 11, 9, 8, 6, 5, 4, 16, 18, + 12, 9, 8, 6, 5, 5, 5, 6, 6, 7, 6, 5, 7, 7, 7, 7, 8, 6, 4, + 7, 8, 8, 8, 8, 6, 3, 7, 10, 9, 9, 9, 7, 4, 8, 14, 13, 13, 13, + 11, 5, 11, 17, 18, 17, 15, 12, 7, 15, 20, 21, 19, 17, 15, 9, 14, 15, 15, + 16, 13, 8, 5, 14, 17, 17, 16, 14, 9, 4, 14, 20, 19, 18, 14, 9, 5, 14, + 19, 21, 19, 15, 11, 7, 14, 20, 24, 23, 19, 14, 9, 17, 23, 29, 28, 22, 16, + 11, 20, 25, 30, 30, 24, 19, 13, 22, 28, 27, 21, 16, 11, 7, 22, 28, 29, 23, + 16, 12, 7, 22, 28, 32, 24, 17, 12, 8, 22, 28, 33, 25, 20, 15, 11, 21, 27, + 33, 30, 24, 19, 13, 23, 30, 35, 34, 27, 21, 15, 25, 31, 35, 36, 29, 23, 17, + 13, 16, 20, 23, 24, 21, 18, 11, 15, 19, 23, 23, 19, 16, 10, 14, 17, 21, 21, + 19, 15, 9, 11, 15, 18, 20, 16, 14, 6, 9, 12, 15, 18, 16, 13, 6, 8, 11, + 14, 17, 16, 14, 11, 11, 11, 13, 16, 16, 13, 10, 14, 17, 20, 20, 17, 14, 9, + 13, 16, 20, 20, 16, 13, 7, 11, 15, 18, 17, 15, 11, 6, 9, 12, 14, 14, 13, + 10, 4, 7, 10, 13, 13, 13, 10, 7, 7, 9, 11, 12, 12, 10, 14, 12, 10, 11, + 11, 11, 10, 8, 11, 13, 14, 15, 14, 9, 6, 10, 12, 13, 14, 13, 8, 5, 8, + 11, 10, 11, 11, 7, 4, 6, 7, 7, 8, 8, 5, 4, 5, 6, 6, 6, 6, 5, + 9, 9, 8, 7, 5, 5, 5, 16, 14, 10, 7, 5, 4, 4, 5, 6, 6, 7, 8, + 9, 6, 3, 4, 5, 6, 6, 6, 5, 2, 3, 3, 4, 3, 4, 3, 0, 0, 0, + 0, 0, 0, 0, 4, 5, 4, 4, 4, 3, 2, 9, 11, 9, 7, 6, 5, 3, 16, + 17, 12, 9, 7, 6, 5, 6, 6, 6, 6, 7, 6, 6, 7, 7, 7, 7, 8, 6, + 5, 7, 8, 8, 8, 8, 6, 3, 7, 10, 9, 9, 9, 7, 4, 9, 14, 13, 13, + 13, 10, 5, 11, 17, 19, 17, 15, 12, 7, 15, 19, 22, 19, 17, 14, 9, 14, 15, + 15, 15, 12, 9, 6, 14, 18, 17, 16, 13, 9, 4, 14, 19, 19, 18, 14, 9, 5, + 14, 19, 20, 19, 15, 11, 7, 14, 20, 25, 23, 19, 14, 9, 17, 23, 29, 28, 21, + 16, 10, 20, 26, 30, 30, 24, 18, 12, 22, 27, 26, 20, 15, 11, 7, 22, 28, 29, + 22, 16, 12, 7, 21, 28, 31, 23, 17, 12, 7, 22, 27, 31, 24, 19, 15, 11, 21, + 28, 33, 29, 24, 18, 12, 24, 29, 35, 34, 27, 20, 14, 26, 31, 36, 36, 29, 22, + 16, 13, 17, 21, 24, 24, 21, 18, 12, 15, 19, 23, 24, 20, 16, 10, 14, 17, 21, + 22, 18, 15, 9, 12, 15, 18, 21, 17, 14, 6, 9, 12, 15, 19, 17, 14, 6, 8, + 11, 14, 18, 17, 14, 11, 10, 10, 13, 16, 16, 14, 10, 14, 18, 22, 20, 18, 14, + 9, 13, 17, 20, 20, 16, 12, 8, 11, 15, 18, 17, 14, 11, 7, 9, 12, 14, 14, + 13, 9, 5, 7, 10, 12, 13, 12, 10, 7, 8, 9, 11, 12, 12, 10, 13, 11, 10, + 11, 11, 11, 10, 8, 11, 13, 14, 15, 14, 10, 6, 10, 12, 13, 14, 12, 8, 5, + 9, 10, 11, 10, 11, 6, 4, 7, 7, 7, 7, 7, 5, 4, 5, 6, 6, 6, 6, + 5, 10, 9, 8, 7, 5, 5, 5, 15, 13, 10, 7, 5, 4, 4, 5, 6, 6, 7, + 8, 9, 6, 4, 4, 5, 6, 6, 6, 4, 2, 3, 4, 3, 3, 3, 2, 0, 0, + 0, 0, 0, 0, 0, 4, 5, 4, 4, 4, 3, 2, 9, 11, 9, 7, 6, 5, 3, + 15, 16, 12, 9, 7, 6, 5, 6, 6, 6, 6, 7, 6, 6, 7, 7, 7, 7, 8, + 6, 4, 7, 8, 8, 8, 8, 6, 2, 7, 10, 9, 9, 9, 7, 4, 9, 14, 14, + 12, 13, 10, 5, 12, 17, 19, 17, 15, 12, 7, 15, 20, 22, 19, 17, 14, 9, 14, + 16, 15, 15, 12, 8, 6, 15, 18, 17, 17, 14, 9, 4, 15, 19, 19, 18, 14, 9, + 5, 14, 19, 20, 19, 15, 10, 7, 15, 21, 24, 23, 19, 14, 9, 17, 23, 30, 27, + 21, 16, 11, 20, 25, 30, 29, 24, 18, 12, 22, 27, 26, 20, 15, 11, 7, 22, 27, + 27, 21, 16, 11, 7, 22, 27, 30, 23, 17, 12, 7, 22, 27, 30, 24, 19, 15, 11, + 22, 26, 32, 29, 23, 18, 13, 24, 29, 34, 34, 26, 20, 14, 26, 31, 35, 35, 28, + 22, 16, 13, 17, 20, 24, 25, 22, 19, 12, 16, 19, 24, 24, 21, 16, 10, 14, 18, + 21, 23, 19, 15, 9, 12, 15, 19, 21, 17, 14, 7, 10, 12, 16, 19, 16, 14, 6, + 9, 11, 15, 18, 18, 14, 9, 9, 10, 13, 17, 17, 14, 11, 14, 18, 21, 21, 18, + 14, 9, 13, 17, 20, 20, 17, 13, 8, 11, 15, 17, 18, 15, 11, 7, 9, 12, 15, + 14, 13, 9, 5, 8, 10, 13, 13, 13, 10, 7, 7, 9, 12, 12, 12, 10, 10, 9, + 9, 11, 11, 11, 10, 8, 12, 13, 15, 16, 14, 10, 7, 10, 12, 13, 14, 12, 8, + 5, 9, 11, 11, 10, 10, 6, 4, 7, 8, 7, 7, 8, 5, 4, 5, 7, 6, 6, + 6, 5, 9, 8, 7, 6, 5, 5, 5, 11, 10, 8, 6, 4, 4, 4, 6, 6, 6, + 7, 9, 9, 6, 4, 4, 5, 6, 6, 7, 4, 2, 3, 4, 4, 3, 3, 2, 0, + 0, 0, 0, 0, 0, 0, 4, 5, 4, 4, 4, 3, 2, 9, 9, 8, 6, 6, 5, + 3, 12, 13, 10, 8, 7, 6, 5, 6, 6, 6, 6, 7, 6, 6, 7, 7, 7, 8, + 8, 6, 4, 7, 9, 8, 8, 8, 6, 2, 7, 11, 9, 9, 9, 7, 3, 9, 15, + 13, 13, 13, 10, 5, 12, 16, 17, 16, 14, 12, 7, 13, 18, 19, 18, 16, 13, 8, + 14, 15, 14, 13, 12, 8, 6, 15, 17, 15, 14, 12, 9, 4, 15, 18, 17, 15, 12, + 9, 5, 14, 18, 18, 15, 14, 11, 7, 15, 20, 22, 20, 17, 13, 8, 17, 22, 25, + 22, 18, 15, 10, 18, 23, 26, 24, 21, 16, 12, 20, 22, 20, 15, 13, 10, 7, 20, + 23, 22, 17, 14, 11, 7, 20, 23, 23, 17, 14, 11, 7, 20, 23, 24, 19, 16, 14, + 10, 20, 23, 27, 24, 20, 16, 12, 22, 26, 29, 29, 22, 18, 14, 24, 27, 29, 29, + 24, 19, 15, 12, 15, 18, 21, 20, 18, 15, 11, 13, 17, 20, 20, 17, 13, 10, 13, + 15, 18, 18, 15, 12, 9, 11, 13, 15, 18, 14, 11, 7, 9, 11, 14, 17, 14, 11, + 6, 8, 10, 12, 16, 14, 11, 8, 9, 10, 12, 14, 14, 11, 11, 13, 16, 18, 17, + 15, 11, 10, 12, 14, 17, 16, 13, 10, 8, 11, 14, 15, 14, 11, 8, 8, 9, 11, + 13, 12, 10, 7, 6, 8, 10, 11, 11, 10, 7, 5, 7, 9, 11, 10, 10, 7, 10, + 9, 9, 10, 9, 9, 7, 8, 11, 12, 12, 13, 11, 8, 8, 10, 11, 11, 11, 10, + 6, 7, 9, 10, 9, 8, 8, 5, 5, 8, 7, 6, 6, 6, 4, 3, 5, 6, 5, + 5, 5, 4, 7, 7, 7, 6, 5, 4, 4, 11, 11, 8, 6, 5, 3, 3, 7, 6, + 6, 6, 7, 8, 6, 4, 5, 5, 6, 6, 5, 4, 2, 3, 4, 4, 3, 3, 2, + 0, 0, 0, 0, 0, 0, 0, 3, 4, 3, 3, 3, 3, 2, 7, 9, 7, 6, 5, + 4, 3, 12, 13, 10, 8, 6, 5, 4, 4, 4, 5, 5, 6, 6, 6, 5, 6, 5, + 6, 6, 5, 4, 6, 7, 7, 6, 6, 5, 2, 6, 8, 7, 7, 7, 6, 3, 7, + 12, 11, 11, 11, 8, 4, 10, 15, 16, 14, 12, 10, 6, 13, 17, 19, 16, 14, 12, + 7, 11, 13, 12, 12, 10, 7, 6, 11, 14, 13, 13, 10, 7, 4, 12, 16, 16, 14, + 11, 7, 4, 11, 16, 16, 15, 12, 9, 6, 12, 17, 21, 19, 15, 11, 7, 15, 20, + 24, 23, 18, 13, 8, 17, 21, 25, 25, 20, 15, 10, 18, 22, 21, 16, 12, 9, 5, + 18, 22, 23, 17, 13, 9, 5, 18, 22, 25, 18, 13, 10, 6, 18, 22, 26, 21, 16, + 12, 9, 18, 23, 27, 24, 19, 15, 10, 20, 25, 30, 28, 21, 16, 11, 22, 26, 30, + 30, 24, 18, 13, 13, 17, 21, 26, 25, 22, 19, 11, 15, 19, 23, 25, 22, 19, 10, + 14, 18, 21, 24, 21, 17, 9, 12, 15, 18, 21, 19, 15, 6, 9, 12, 15, 16, 18, + 15, 3, 6, 10, 13, 16, 17, 15, 4, 6, 8, 12, 15, 18, 15, 10, 14, 18, 21, + 21, 18, 16, 9, 13, 16, 20, 21, 18, 14, 7, 11, 15, 17, 18, 18, 12, 6, 9, + 12, 15, 15, 15, 10, 3, 6, 9, 12, 12, 14, 10, 2, 4, 7, 10, 12, 11, 10, + 6, 5, 6, 9, 10, 10, 10, 7, 11, 14, 15, 16, 15, 12, 6, 10, 12, 13, 15, + 14, 10, 5, 8, 11, 11, 12, 12, 8, 5, 6, 8, 8, 9, 9, 5, 1, 3, 4, + 5, 5, 6, 5, 4, 3, 3, 3, 3, 4, 5, 8, 7, 4, 2, 2, 2, 3, 6, + 6, 8, 9, 10, 11, 9, 5, 6, 7, 8, 8, 9, 8, 4, 5, 6, 6, 6, 7, + 7, 3, 4, 4, 4, 4, 4, 3, 0, 2, 1, 1, 2, 1, 3, 4, 5, 4, 3, + 2, 2, 3, 8, 9, 6, 4, 3, 2, 3, 4, 6, 6, 6, 7, 8, 9, 5, 6, + 6, 6, 7, 7, 8, 5, 6, 7, 7, 7, 6, 6, 5, 7, 6, 6, 6, 5, 3, + 4, 7, 6, 6, 6, 5, 3, 5, 9, 9, 8, 7, 6, 4, 8, 11, 11, 9, 9, + 7, 4, 9, 11, 11, 11, 9, 7, 8, 9, 12, 11, 12, 10, 7, 7, 10, 13, 12, + 12, 10, 8, 6, 9, 12, 12, 12, 9, 7, 4, 8, 11, 13, 12, 10, 7, 5, 9, + 12, 16, 15, 11, 8, 5, 11, 13, 16, 16, 12, 9, 6, 14, 18, 17, 14, 11, 8, + 7, 14, 18, 19, 14, 12, 9, 7, 14, 19, 21, 14, 12, 9, 7, 14, 17, 20, 15, + 11, 8, 5, 13, 16, 19, 16, 12, 9, 6, 13, 17, 19, 18, 14, 10, 7, 14, 17, + 20, 19, 15, 11, 8, 15, 17, 19, 22, 22, 19, 17, 15, 16, 18, 21, 22, 19, 16, + 14, 16, 18, 19, 20, 18, 14, 13, 14, 15, 17, 18, 15, 10, 10, 11, 12, 13, 14, + 12, 10, 6, 8, 9, 9, 12, 12, 10, 8, 8, 8, 9, 11, 12, 10, 13, 16, 17, + 19, 19, 18, 16, 13, 14, 17, 18, 18, 16, 15, 11, 14, 16, 17, 16, 15, 13, 10, + 12, 14, 14, 14, 13, 9, 7, 9, 10, 11, 10, 9, 9, 3, 6, 7, 8, 9, 9, + 9, 10, 9, 7, 8, 8, 8, 9, 12, 14, 16, 15, 16, 16, 14, 10, 13, 15, 15, + 15, 15, 13, 9, 13, 14, 14, 14, 13, 12, 7, 10, 11, 11, 12, 11, 9, 3, 6, + 8, 8, 8, 8, 8, 5, 5, 5, 6, 7, 7, 8, 12, 12, 8, 5, 6, 6, 8, + 9, 10, 11, 12, 12, 13, 10, 7, 8, 9, 10, 11, 11, 9, 6, 7, 8, 8, 8, + 9, 8, 3, 4, 4, 5, 5, 5, 4, 2, 0, 0, 0, 0, 2, 3, 5, 7, 6, + 4, 2, 1, 3, 12, 14, 9, 6, 4, 3, 3, 4, 5, 7, 8, 9, 9, 10, 5, + 6, 6, 7, 8, 8, 9, 5, 7, 7, 7, 7, 6, 7, 5, 8, 8, 8, 8, 6, + 3, 4, 10, 10, 10, 10, 9, 3, 7, 12, 13, 12, 12, 10, 5, 12, 14, 15, 13, + 12, 11, 7, 12, 14, 14, 15, 11, 8, 9, 12, 16, 15, 16, 13, 8, 8, 12, 18, + 18, 17, 14, 9, 6, 12, 16, 18, 16, 14, 10, 5, 12, 16, 17, 16, 14, 11, 7, + 12, 16, 19, 17, 15, 12, 9, 14, 17, 19, 18, 15, 13, 10, 20, 23, 22, 19, 14, + 10, 8, 19, 23, 23, 19, 15, 12, 7, 19, 23, 25, 20, 16, 12, 7, 19, 22, 25, + 19, 16, 13, 9, 18, 21, 23, 20, 16, 14, 10, 17, 19, 23, 22, 17, 13, 12, 18, + 21, 23, 23, 18, 14, 12, 17, 20, 22, 25, 24, 23, 20, 15, 19, 21, 24, 24, 21, + 19, 14, 17, 21, 22, 22, 20, 17, 13, 15, 18, 20, 21, 18, 13, 9, 12, 15, 17, + 17, 15, 13, 6, 9, 11, 14, 16, 15, 13, 7, 8, 10, 13, 15, 15, 13, 14, 17, + 20, 22, 21, 20, 18, 13, 16, 21, 22, 21, 19, 16, 11, 15, 18, 19, 20, 17, 15, + 10, 12, 16, 17, 17, 16, 11, 7, 9, 12, 14, 13, 12, 11, 4, 7, 9, 12, 12, + 12, 11, 10, 9, 8, 11, 11, 12, 11, 11, 15, 17, 18, 19, 18, 14, 10, 13, 16, + 17, 18, 16, 12, 8, 12, 14, 14, 15, 15, 11, 7, 10, 11, 11, 11, 11, 7, 4, + 6, 7, 8, 7, 8, 7, 4, 5, 5, 6, 6, 7, 7, 11, 11, 7, 4, 5, 5, + 6, 9, 9, 10, 11, 13, 13, 10, 7, 8, 9, 10, 10, 11, 9, 6, 7, 7, 7, + 7, 8, 6, 3, 4, 4, 4, 4, 4, 3, 1, 0, 0, 0, 0, 1, 2, 5, 6, + 5, 4, 2, 2, 2, 11, 13, 8, 6, 4, 3, 3, 4, 5, 6, 8, 9, 10, 10, + 6, 6, 6, 7, 8, 8, 9, 6, 7, 7, 7, 7, 6, 6, 6, 9, 8, 8, 8, + 6, 2, 5, 10, 10, 9, 9, 8, 3, 7, 13, 14, 13, 12, 9, 5, 11, 16, 18, + 15, 14, 11, 6, 13, 15, 15, 15, 11, 9, 10, 12, 16, 16, 16, 12, 8, 8, 13, + 18, 18, 17, 13, 9, 5, 13, 18, 19, 18, 15, 10, 5, 12, 18, 21, 20, 16, 11, + 6, 12, 19, 25, 24, 19, 13, 8, 16, 21, 26, 26, 21, 15, 10, 20, 27, 26, 20, + 15, 10, 9, 21, 27, 28, 22, 16, 11, 7, 20, 28, 31, 23, 17, 12, 7, 21, 26, + 31, 24, 18, 13, 8, 20, 25, 31, 27, 21, 15, 10, 20, 26, 31, 31, 23, 17, 11, + 22, 28, 32, 32, 25, 19, 13, 17, 21, 24, 28, 27, 25, 22, 15, 20, 23, 26, 26, + 24, 20, 14, 18, 21, 24, 25, 22, 19, 13, 16, 19, 21, 23, 20, 15, 9, 12, 15, + 18, 20, 18, 15, 6, 9, 12, 15, 18, 17, 15, 7, 7, 11, 14, 17, 18, 14, 14, + 18, 21, 25, 24, 22, 18, 13, 16, 21, 24, 24, 21, 17, 11, 15, 18, 21, 21, 18, + 14, 10, 13, 15, 17, 18, 16, 11, 7, 10, 12, 14, 15, 14, 11, 4, 7, 10, 12, + 13, 13, 11, 9, 8, 9, 11, 11, 12, 11, 11, 15, 17, 18, 20, 18, 14, 10, 14, + 16, 17, 18, 16, 12, 8, 12, 14, 14, 15, 15, 10, 8, 10, 11, 11, 11, 11, 7, + 4, 6, 7, 7, 8, 7, 7, 5, 5, 6, 6, 6, 6, 7, 11, 10, 7, 4, 5, + 5, 6, 9, 9, 10, 11, 13, 13, 10, 7, 8, 9, 10, 10, 10, 8, 6, 6, 7, + 7, 7, 7, 6, 3, 4, 4, 4, 4, 4, 3, 1, 0, 0, 0, 0, 1, 2, 5, + 6, 5, 4, 2, 2, 2, 10, 11, 8, 5, 4, 3, 3, 5, 5, 6, 8, 8, 10, + 10, 6, 6, 6, 7, 8, 8, 8, 6, 7, 8, 7, 7, 6, 5, 6, 9, 8, 8, + 8, 6, 2, 5, 10, 10, 9, 9, 7, 3, 7, 13, 14, 13, 11, 9, 4, 10, 15, + 18, 15, 13, 11, 6, 13, 14, 14, 15, 11, 9, 10, 13, 17, 16, 16, 12, 8, 7, + 13, 19, 18, 17, 13, 8, 5, 13, 18, 19, 18, 14, 9, 4, 12, 17, 21, 19, 15, + 10, 6, 13, 19, 24, 23, 18, 12, 8, 16, 22, 26, 26, 20, 14, 9, 21, 27, 26, + 20, 15, 10, 8, 21, 27, 28, 21, 16, 11, 6, 20, 26, 31, 22, 17, 12, 6, 20, + 26, 31, 23, 18, 13, 7, 19, 26, 30, 27, 20, 14, 9, 20, 25, 31, 30, 23, 16, + 11, 22, 27, 32, 32, 25, 19, 12, 17, 20, 24, 28, 29, 26, 23, 16, 20, 24, 28, + 28, 24, 20, 14, 18, 22, 25, 26, 23, 19, 13, 16, 19, 22, 25, 21, 15, 10, 13, + 15, 19, 21, 19, 15, 7, 9, 13, 15, 20, 18, 16, 5, 8, 12, 15, 17, 19, 15, + 14, 18, 22, 26, 25, 22, 19, 13, 17, 20, 24, 24, 21, 17, 11, 15, 19, 22, 21, + 19, 15, 10, 13, 16, 18, 18, 17, 12, 7, 10, 12, 14, 15, 14, 11, 4, 7, 10, + 12, 13, 14, 12, 5, 6, 9, 12, 12, 12, 11, 11, 16, 17, 18, 20, 18, 14, 10, + 14, 16, 17, 18, 16, 12, 9, 13, 15, 14, 15, 14, 10, 8, 11, 11, 11, 12, 11, + 7, 4, 7, 8, 8, 8, 8, 7, 4, 5, 6, 6, 6, 6, 7, 6, 5, 5, 5, + 5, 5, 6, 9, 9, 10, 12, 13, 14, 10, 8, 8, 9, 10, 10, 10, 8, 7, 7, + 8, 7, 7, 7, 6, 3, 4, 4, 4, 4, 4, 3, 2, 0, 0, 0, 0, 1, 2, + 5, 5, 3, 2, 2, 1, 1, 6, 7, 4, 4, 3, 2, 2, 5, 5, 6, 8, 9, + 10, 10, 6, 6, 6, 7, 8, 8, 8, 6, 7, 7, 7, 7, 5, 5, 6, 9, 8, + 7, 8, 6, 2, 6, 11, 9, 9, 9, 7, 3, 7, 12, 13, 12, 10, 8, 4, 7, + 12, 15, 14, 12, 10, 5, 13, 15, 14, 14, 11, 9, 10, 13, 17, 16, 15, 12, 8, + 7, 13, 19, 18, 16, 13, 8, 4, 13, 18, 19, 18, 13, 9, 4, 13, 17, 20, 19, + 15, 10, 5, 13, 18, 24, 22, 18, 11, 7, 13, 18, 24, 25, 19, 14, 8, 20, 26, + 24, 19, 14, 10, 9, 20, 26, 27, 21, 15, 10, 6, 21, 26, 28, 21, 16, 11, 6, + 21, 25, 29, 23, 17, 12, 7, 20, 25, 28, 25, 19, 14, 9, 20, 26, 30, 27, 21, + 15, 10, 20, 26, 30, 30, 24, 17, 12, 16, 20, 24, 28, 28, 26, 21, 15, 19, 23, + 27, 28, 24, 20, 13, 17, 21, 24, 26, 22, 18, 12, 15, 18, 21, 24, 20, 15, 9, + 12, 15, 17, 21, 18, 15, 7, 10, 12, 16, 19, 18, 16, 5, 8, 11, 15, 18, 18, + 15, 14, 17, 21, 25, 24, 21, 18, 12, 16, 20, 23, 23, 20, 16, 11, 14, 18, 20, + 21, 18, 14, 9, 12, 15, 18, 18, 16, 11, 7, 9, 11, 14, 14, 14, 11, 4, 7, + 10, 13, 13, 14, 11, 5, 6, 9, 12, 12, 12, 11, 11, 15, 17, 17, 19, 17, 13, + 9, 13, 15, 16, 17, 16, 11, 8, 12, 14, 14, 14, 14, 9, 7, 10, 10, 10, 11, + 11, 7, 3, 6, 7, 7, 7, 8, 6, 4, 5, 6, 6, 6, 6, 7, 7, 5, 5, + 5, 5, 5, 5, 8, 9, 10, 11, 12, 13, 9, 7, 7, 8, 9, 10, 9, 7, 5, + 6, 7, 7, 6, 6, 5, 3, 4, 3, 3, 3, 3, 3, 1, 2, 1, 1, 1, 0, + 1, 4, 5, 3, 3, 2, 2, 1, 7, 8, 5, 4, 3, 2, 2, 5, 5, 5, 7, + 8, 9, 9, 7, 6, 6, 7, 7, 7, 7, 7, 8, 7, 7, 7, 5, 4, 7, 10, + 8, 7, 7, 6, 2, 6, 11, 10, 9, 9, 7, 2, 8, 12, 12, 11, 10, 8, 4, + 8, 12, 15, 12, 11, 10, 5, 14, 14, 13, 12, 11, 8, 9, 14, 16, 15, 14, 11, + 8, 6, 14, 18, 16, 14, 11, 8, 4, 14, 18, 17, 14, 12, 8, 4, 12, 17, 19, + 16, 13, 10, 5, 13, 17, 21, 18, 14, 11, 7, 14, 18, 21, 20, 15, 12, 8, 19, + 22, 19, 15, 12, 10, 7, 19, 22, 21, 17, 14, 10, 6, 20, 22, 23, 17, 13, 10, + 6, 19, 22, 23, 18, 14, 11, 7, 18, 21, 23, 20, 16, 12, 8, 18, 21, 23, 23, + 17, 13, 10, 19, 22, 24, 24, 19, 15, 11, 14, 18, 21, 23, 24, 21, 18, 14, 17, + 20, 23, 23, 20, 16, 12, 15, 19, 21, 22, 18, 15, 11, 14, 16, 19, 20, 17, 14, + 8, 11, 13, 16, 20, 18, 14, 7, 10, 13, 15, 19, 18, 14, 6, 8, 12, 15, 18, + 17, 14, 13, 16, 18, 21, 20, 18, 15, 11, 15, 17, 20, 19, 16, 13, 10, 13, 16, + 18, 17, 15, 12, 9, 11, 14, 16, 15, 14, 11, 6, 9, 12, 14, 14, 13, 10, 5, + 8, 11, 13, 13, 12, 11, 7, 7, 9, 12, 12, 12, 11, 10, 14, 15, 15, 16, 14, + 11, 8, 12, 14, 15, 14, 13, 10, 7, 11, 13, 12, 12, 12, 8, 6, 9, 9, 9, + 9, 9, 6, 3, 7, 8, 7, 7, 7, 6, 4, 5, 6, 6, 6, 6, 6, 8, 7, + 6, 5, 5, 5, 5, 8, 8, 9, 9, 10, 11, 7, 6, 6, 7, 8, 8, 8, 5, + 4, 5, 6, 5, 5, 5, 3, 2, 3, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, + 1, 0, 5, 5, 4, 3, 2, 2, 1, 7, 10, 6, 4, 3, 2, 2, 4, 4, 4, + 5, 6, 7, 7, 5, 5, 4, 4, 5, 5, 5, 5, 4, 4, 3, 3, 2, 2, 4, + 6, 4, 4, 4, 3, 1, 5, 8, 8, 7, 7, 5, 2, 6, 11, 12, 11, 9, 7, + 3, 9, 13, 15, 12, 11, 8, 4, 8, 9, 9, 9, 7, 6, 7, 8, 11, 10, 10, + 7, 4, 4, 8, 12, 12, 11, 7, 4, 2, 8, 12, 13, 12, 9, 6, 3, 9, 13, + 17, 15, 12, 8, 4, 11, 16, 21, 19, 14, 10, 5, 13, 18, 21, 21, 16, 11, 7, + 15, 19, 17, 13, 9, 6, 6, 14, 18, 19, 14, 9, 6, 3, 14, 19, 21, 15, 10, + 6, 3, 14, 18, 22, 16, 12, 9, 6, 14, 18, 23, 21, 16, 11, 7, 16, 21, 25, + 25, 19, 13, 8, 19, 23, 25, 26, 20, 15, 10, 14, 17, 22, 25, 25, 23, 20, 13, + 16, 20, 24, 25, 22, 18, 13, 15, 18, 21, 24, 19, 16, 12, 13, 16, 19, 21, 17, + 14, 9, 10, 12, 14, 15, 16, 13, 5, 6, 8, 11, 13, 15, 13, 3, 3, 6, 9, + 13, 15, 13, 13, 15, 18, 22, 22, 19, 17, 12, 14, 17, 21, 21, 18, 16, 11, 13, + 16, 18, 18, 16, 12, 11, 11, 13, 15, 15, 13, 7, 8, 8, 9, 11, 10, 11, 8, + 3, 3, 5, 8, 9, 9, 8, 4, 3, 4, 7, 8, 8, 7, 12, 13, 15, 16, 17, + 17, 16, 11, 13, 14, 15, 16, 16, 14, 10, 12, 13, 13, 13, 14, 12, 10, 10, 10, + 10, 11, 10, 6, 6, 6, 6, 6, 5, 5, 5, 0, 2, 1, 2, 4, 4, 5, 5, + 4, 2, 1, 3, 4, 5, 11, 12, 13, 13, 15, 16, 16, 10, 11, 12, 14, 14, 15, + 14, 9, 10, 12, 12, 13, 13, 12, 6, 9, 9, 9, 9, 9, 7, 4, 5, 5, 5, + 5, 4, 4, 0, 2, 2, 1, 2, 3, 5, 5, 6, 3, 2, 3, 3, 4, 9, 11, + 12, 13, 14, 15, 16, 8, 9, 11, 12, 13, 14, 14, 8, 9, 10, 11, 11, 12, 12, + 8, 8, 8, 8, 8, 8, 5, 5, 7, 7, 6, 6, 5, 4, 3, 6, 7, 7, 7, + 6, 4, 5, 8, 9, 8, 8, 7, 5, 10, 11, 12, 12, 12, 14, 15, 10, 12, 12, + 13, 12, 12, 14, 10, 13, 13, 13, 11, 10, 11, 10, 12, 13, 12, 11, 8, 5, 8, + 11, 12, 12, 9, 7, 5, 7, 10, 14, 13, 10, 8, 5, 8, 11, 14, 14, 11, 9, + 6, 14, 19, 17, 15, 12, 12, 14, 15, 19, 19, 16, 13, 11, 12, 15, 19, 21, 15, + 13, 10, 9, 15, 18, 21, 15, 12, 9, 6, 13, 16, 18, 15, 11, 9, 7, 12, 15, + 18, 17, 13, 9, 7, 12, 16, 18, 19, 14, 11, 8, 21, 23, 24, 27, 27, 25, 23, + 20, 23, 25, 26, 26, 23, 21, 20, 22, 23, 24, 24, 22, 18, 18, 20, 21, 21, 21, + 18, 12, 15, 17, 18, 17, 16, 13, 12, 11, 13, 13, 12, 13, 13, 12, 6, 8, 10, + 12, 13, 13, 12, 19, 22, 23, 25, 25, 24, 23, 18, 21, 23, 25, 24, 22, 21, 17, + 21, 22, 22, 21, 20, 18, 16, 19, 20, 20, 19, 16, 11, 12, 15, 16, 16, 12, 12, + 11, 8, 11, 12, 10, 11, 11, 11, 4, 6, 9, 10, 10, 11, 11, 17, 20, 21, 23, + 23, 23, 20, 15, 19, 21, 22, 22, 21, 18, 14, 18, 20, 20, 19, 20, 16, 13, 15, + 16, 16, 16, 15, 11, 8, 12, 13, 13, 10, 10, 10, 2, 7, 8, 8, 9, 9, 10, + 5, 6, 6, 7, 8, 9, 10, 14, 15, 17, 18, 19, 20, 18, 12, 13, 16, 17, 17, + 17, 16, 10, 12, 13, 14, 14, 14, 13, 7, 11, 11, 11, 11, 9, 9, 4, 7, 6, + 6, 4, 5, 5, 2, 0, 0, 2, 3, 4, 6, 5, 7, 3, 2, 2, 3, 4, 11, + 12, 13, 15, 16, 17, 18, 8, 11, 13, 14, 15, 15, 16, 8, 10, 11, 11, 12, 13, + 12, 8, 8, 8, 8, 8, 7, 5, 6, 7, 7, 7, 8, 6, 4, 3, 8, 9, 8, + 8, 8, 3, 5, 8, 9, 9, 9, 8, 5, 10, 12, 12, 13, 13, 16, 18, 10, 14, + 14, 15, 12, 14, 14, 10, 15, 15, 14, 11, 10, 11, 9, 14, 15, 13, 12, 7, 3, + 9, 13, 14, 13, 10, 9, 5, 9, 12, 14, 13, 11, 9, 7, 9, 11, 14, 14, 12, + 10, 8, 17, 20, 19, 17, 13, 14, 16, 17, 20, 20, 18, 14, 11, 13, 17, 20, 22, + 17, 14, 9, 9, 17, 19, 21, 16, 13, 11, 7, 15, 17, 19, 16, 12, 10, 8, 13, + 16, 18, 17, 13, 10, 8, 12, 15, 18, 18, 14, 11, 9, 21, 24, 28, 30, 29, 29, + 26, 20, 24, 27, 28, 30, 27, 23, 18, 23, 26, 27, 27, 24, 20, 17, 20, 23, 24, + 25, 21, 15, 14, 17, 20, 21, 19, 17, 15, 10, 13, 15, 16, 18, 17, 15, 6, 9, + 12, 15, 17, 17, 15, 19, 23, 25, 28, 28, 26, 23, 17, 21, 25, 27, 27, 24, 21, + 16, 19, 24, 25, 24, 22, 18, 15, 17, 21, 22, 21, 18, 13, 12, 14, 17, 18, 15, + 14, 13, 7, 10, 12, 14, 14, 14, 13, 4, 6, 10, 13, 13, 13, 13, 16, 20, 22, + 23, 25, 22, 18, 15, 18, 20, 22, 22, 21, 17, 14, 17, 19, 19, 19, 19, 14, 12, + 15, 16, 16, 15, 14, 9, 7, 11, 12, 12, 10, 10, 9, 2, 7, 7, 8, 8, 8, + 9, 5, 5, 6, 6, 7, 7, 8, 14, 14, 15, 16, 18, 18, 16, 12, 13, 14, 15, + 16, 16, 13, 9, 12, 12, 12, 12, 12, 10, 6, 10, 9, 9, 9, 7, 8, 4, 6, + 5, 5, 3, 3, 4, 1, 0, 0, 1, 2, 3, 3, 5, 6, 3, 2, 2, 2, 2, + 10, 11, 12, 13, 14, 15, 16, 7, 10, 11, 12, 13, 13, 14, 7, 9, 10, 10, 10, + 10, 10, 7, 7, 7, 7, 7, 6, 3, 5, 7, 7, 7, 8, 6, 2, 3, 8, 10, + 9, 9, 8, 3, 5, 11, 13, 11, 11, 10, 5, 10, 13, 13, 13, 12, 14, 15, 10, + 14, 14, 15, 11, 12, 13, 10, 16, 16, 16, 11, 9, 8, 10, 15, 17, 17, 12, 7, + 3, 9, 15, 19, 18, 15, 10, 5, 9, 15, 22, 21, 17, 11, 7, 11, 17, 22, 23, + 20, 14, 8, 18, 25, 24, 18, 13, 13, 14, 19, 25, 26, 19, 14, 11, 11, 18, 24, + 29, 21, 15, 10, 7, 18, 25, 29, 22, 17, 11, 6, 18, 23, 28, 25, 19, 13, 8, + 17, 23, 28, 27, 21, 15, 10, 18, 23, 28, 29, 22, 18, 12, 20, 24, 27, 31, 31, + 28, 26, 19, 23, 27, 30, 30, 27, 23, 18, 21, 25, 27, 29, 26, 21, 16, 19, 22, + 25, 26, 23, 17, 13, 16, 18, 21, 22, 19, 16, 10, 12, 15, 17, 20, 19, 16, 6, + 9, 12, 16, 18, 19, 16, 18, 21, 25, 28, 28, 26, 22, 16, 20, 24, 27, 27, 23, + 19, 15, 18, 22, 24, 24, 22, 17, 14, 16, 19, 22, 21, 19, 13, 11, 13, 16, 18, + 16, 15, 13, 7, 9, 12, 14, 14, 14, 12, 4, 7, 10, 13, 13, 14, 12, 15, 18, + 21, 22, 24, 21, 18, 14, 17, 20, 21, 21, 19, 16, 13, 16, 18, 18, 18, 17, 13, + 11, 13, 15, 14, 15, 14, 8, 7, 10, 11, 11, 10, 9, 8, 2, 6, 7, 7, 8, + 8, 8, 3, 5, 6, 6, 7, 7, 7, 13, 13, 14, 15, 16, 17, 14, 11, 11, 13, + 14, 14, 14, 11, 8, 10, 11, 11, 11, 10, 9, 5, 8, 7, 7, 7, 6, 6, 3, + 4, 4, 4, 2, 2, 3, 1, 2, 1, 0, 1, 2, 3, 3, 4, 2, 2, 2, 2, + 2, 9, 9, 10, 11, 12, 14, 13, 6, 8, 9, 10, 11, 11, 11, 6, 8, 8, 8, + 9, 9, 8, 6, 7, 6, 6, 6, 5, 3, 4, 8, 8, 8, 8, 6, 2, 3, 9, + 10, 10, 9, 7, 3, 5, 9, 12, 11, 11, 9, 5, 11, 13, 13, 13, 11, 12, 13, + 11, 15, 15, 15, 11, 10, 10, 11, 16, 16, 16, 11, 8, 7, 11, 16, 17, 16, 12, + 8, 3, 10, 15, 19, 17, 14, 9, 5, 10, 15, 22, 21, 16, 10, 6, 11, 16, 21, + 23, 18, 13, 8, 19, 25, 24, 18, 13, 11, 12, 19, 25, 27, 20, 14, 9, 9, 18, + 25, 29, 21, 15, 10, 6, 19, 24, 29, 22, 16, 11, 6, 18, 24, 29, 24, 18, 13, + 8, 18, 23, 29, 27, 20, 14, 9, 18, 24, 30, 29, 22, 16, 11, 19, 23, 26, 31, + 30, 27, 24, 17, 22, 26, 29, 30, 27, 22, 16, 20, 23, 27, 28, 25, 21, 15, 17, + 21, 24, 27, 23, 17, 12, 15, 17, 20, 22, 20, 17, 8, 11, 13, 17, 21, 20, 16, + 6, 9, 13, 16, 19, 20, 17, 16, 20, 24, 28, 27, 25, 21, 15, 19, 22, 26, 27, + 23, 19, 14, 18, 21, 24, 23, 21, 17, 12, 15, 18, 20, 20, 18, 13, 9, 12, 14, + 17, 16, 16, 13, 6, 9, 12, 14, 14, 15, 12, 4, 7, 10, 13, 13, 14, 13, 14, + 18, 19, 20, 22, 20, 17, 12, 15, 19, 19, 20, 19, 14, 11, 15, 17, 16, 16, 17, + 12, 10, 13, 13, 13, 13, 13, 8, 6, 9, 10, 10, 9, 9, 8, 3, 6, 7, 7, + 8, 8, 8, 4, 5, 6, 6, 7, 7, 7, 11, 12, 12, 14, 15, 16, 12, 10, 10, + 11, 12, 13, 13, 10, 8, 9, 10, 9, 9, 9, 7, 4, 7, 6, 6, 6, 6, 5, + 2, 2, 2, 2, 2, 2, 3, 2, 4, 2, 1, 0, 1, 2, 4, 6, 3, 2, 2, + 1, 2, 6, 7, 8, 9, 10, 11, 12, 5, 6, 7, 9, 9, 9, 10, 5, 6, 7, + 6, 6, 7, 6, 5, 7, 6, 6, 6, 5, 3, 4, 9, 8, 7, 7, 5, 2, 5, + 9, 10, 9, 9, 7, 3, 6, 10, 12, 11, 10, 9, 4, 11, 13, 13, 13, 10, 10, + 11, 12, 15, 14, 14, 11, 8, 9, 11, 17, 16, 15, 11, 7, 5, 11, 16, 17, 16, + 12, 8, 3, 11, 16, 19, 18, 14, 9, 4, 11, 16, 22, 20, 15, 10, 6, 11, 16, + 22, 22, 17, 12, 7, 19, 25, 23, 17, 13, 9, 10, 19, 25, 25, 19, 14, 9, 7, + 20, 25, 27, 20, 15, 10, 5, 19, 24, 28, 22, 16, 11, 6, 18, 24, 28, 23, 17, + 12, 7, 18, 23, 27, 25, 20, 14, 9, 18, 23, 27, 28, 22, 16, 10, 18, 22, 26, + 29, 29, 26, 23, 16, 20, 24, 29, 29, 25, 21, 15, 19, 23, 25, 28, 23, 19, 14, + 16, 19, 23, 25, 22, 16, 10, 13, 16, 19, 23, 20, 16, 8, 11, 14, 17, 21, 20, + 17, 7, 10, 13, 16, 19, 20, 16, 15, 19, 23, 26, 26, 23, 19, 14, 17, 22, 25, + 25, 21, 18, 12, 16, 20, 22, 23, 20, 16, 11, 14, 16, 19, 19, 17, 13, 8, 11, + 13, 16, 16, 15, 13, 6, 9, 12, 14, 14, 14, 13, 5, 7, 11, 13, 13, 13, 13, + 13, 16, 18, 19, 21, 19, 15, 11, 15, 17, 18, 19, 17, 13, 10, 13, 16, 15, 16, + 15, 11, 9, 11, 12, 12, 12, 12, 8, 5, 8, 9, 9, 9, 9, 8, 3, 6, 7, + 8, 7, 7, 8, 5, 5, 6, 6, 7, 7, 7, 10, 10, 11, 12, 14, 14, 10, 9, + 9, 10, 11, 11, 11, 8, 7, 8, 8, 8, 8, 8, 6, 3, 5, 5, 5, 5, 5, + 4, 2, 1, 2, 2, 1, 2, 2, 3, 4, 3, 2, 1, 0, 1, 5, 7, 4, 3, + 2, 2, 2, 4, 4, 6, 7, 8, 9, 10, 5, 5, 5, 7, 7, 7, 8, 5, 6, + 6, 6, 5, 5, 5, 5, 8, 7, 6, 6, 5, 1, 5, 9, 8, 7, 8, 5, 2, + 6, 10, 11, 10, 9, 7, 3, 7, 10, 13, 11, 11, 9, 4, 12, 13, 12, 12, 10, + 8, 9, 12, 15, 14, 13, 11, 7, 7, 12, 17, 16, 13, 11, 6, 4, 13, 16, 16, + 14, 12, 7, 3, 11, 16, 18, 15, 13, 9, 4, 11, 16, 20, 18, 14, 10, 6, 12, + 16, 21, 20, 15, 12, 7, 18, 21, 19, 15, 12, 9, 8, 18, 21, 20, 16, 13, 9, + 5, 18, 21, 23, 16, 13, 9, 5, 18, 21, 23, 17, 14, 10, 6, 18, 20, 23, 20, + 15, 12, 8, 18, 20, 23, 21, 17, 13, 9, 18, 21, 23, 23, 18, 13, 10, 17, 20, + 24, 27, 27, 24, 21, 16, 19, 23, 26, 27, 23, 20, 14, 18, 21, 24, 26, 22, 18, + 13, 16, 18, 21, 24, 21, 17, 10, 12, 15, 18, 22, 20, 16, 8, 11, 14, 17, 21, + 20, 16, 7, 10, 13, 16, 20, 19, 17, 14, 17, 21, 24, 23, 21, 18, 13, 17, 20, + 23, 23, 20, 16, 11, 15, 19, 21, 20, 18, 14, 10, 13, 16, 19, 17, 16, 12, 7, + 11, 13, 15, 16, 15, 12, 6, 9, 12, 14, 15, 14, 12, 6, 8, 11, 13, 13, 13, + 12, 12, 15, 17, 17, 19, 17, 13, 10, 13, 16, 17, 17, 16, 11, 9, 12, 14, 14, + 14, 14, 10, 8, 10, 11, 11, 11, 11, 7, 5, 8, 9, 9, 8, 8, 7, 5, 7, + 8, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 9, 9, 10, 11, 12, 13, 8, + 8, 8, 9, 9, 9, 10, 6, 6, 7, 7, 7, 6, 6, 4, 3, 4, 4, 3, 3, + 3, 3, 3, 3, 2, 2, 1, 1, 1, 5, 5, 4, 2, 2, 1, 0, 7, 7, 4, + 3, 2, 2, 2, 3, 3, 4, 5, 6, 8, 8, 4, 4, 4, 5, 5, 5, 6, 4, + 5, 4, 3, 3, 3, 3, 4, 6, 4, 3, 3, 3, 0, 5, 6, 5, 4, 4, 3, + 2, 6, 8, 9, 7, 6, 4, 2, 7, 10, 11, 8, 7, 5, 2, 6, 6, 6, 6, + 5, 7, 7, 6, 8, 7, 7, 5, 4, 5, 6, 9, 8, 7, 4, 2, 2, 6, 8, + 9, 8, 5, 3, 2, 7, 10, 13, 12, 9, 5, 2, 8, 12, 17, 15, 11, 7, 3, + 10, 14, 18, 17, 12, 8, 4, 11, 15, 14, 9, 6, 6, 6, 10, 15, 16, 10, 6, + 3, 3, 10, 15, 18, 11, 7, 3, 2, 10, 14, 18, 12, 8, 5, 3, 10, 15, 20, + 17, 12, 8, 4, 12, 17, 22, 20, 15, 10, 5, 14, 20, 23, 22, 17, 11, 7, 20, + 21, 23, 26, 26, 25, 23, 19, 21, 23, 25, 26, 23, 21, 18, 20, 21, 23, 23, 19, + 16, 18, 18, 19, 19, 20, 15, 11, 15, 15, 15, 14, 14, 14, 10, 11, 11, 8, 10, + 12, 14, 10, 5, 3, 5, 8, 11, 14, 10, 19, 20, 22, 23, 24, 23, 22, 18, 20, + 21, 24, 24, 21, 19, 18, 19, 21, 21, 20, 19, 16, 17, 17, 18, 18, 16, 13, 8, + 14, 14, 14, 13, 9, 9, 8, 9, 9, 7, 6, 8, 9, 9, 2, 2, 4, 5, 7, + 8, 8, 18, 20, 20, 21, 23, 23, 22, 17, 18, 20, 21, 22, 21, 19, 17, 18, 19, + 20, 19, 18, 16, 16, 17, 16, 16, 15, 12, 9, 11, 12, 12, 11, 7, 8, 8, 4, + 7, 6, 4, 6, 8, 8, 0, 2, 2, 4, 6, 6, 8, 17, 18, 19, 21, 23, 24, + 23, 16, 18, 20, 20, 21, 21, 20, 14, 18, 19, 19, 19, 18, 17, 10, 17, 16, 16, + 15, 12, 12, 7, 12, 11, 11, 6, 7, 8, 5, 5, 5, 3, 4, 5, 6, 0, 3, + 3, 3, 4, 5, 6, 15, 17, 19, 20, 22, 23, 23, 12, 16, 18, 19, 20, 20, 21, + 12, 16, 17, 17, 17, 17, 15, 12, 13, 13, 13, 12, 10, 7, 10, 9, 8, 8, 7, + 6, 6, 6, 7, 7, 6, 7, 7, 5, 4, 6, 8, 7, 7, 8, 6, 13, 14, 15, + 16, 19, 22, 23, 13, 14, 14, 16, 17, 18, 19, 13, 15, 15, 14, 14, 15, 14, 13, + 13, 13, 13, 12, 9, 6, 11, 12, 13, 12, 9, 8, 6, 8, 10, 13, 13, 10, 8, + 7, 7, 10, 13, 14, 11, 8, 7, 16, 19, 18, 16, 17, 20, 21, 16, 18, 19, 17, + 16, 17, 18, 16, 18, 20, 16, 14, 13, 13, 16, 17, 20, 15, 12, 10, 7, 14, 16, + 18, 16, 11, 8, 7, 12, 15, 17, 17, 12, 10, 8, 11, 15, 18, 18, 14, 10, 8, + 27, 30, 31, 32, 32, 31, 30, 26, 29, 31, 32, 32, 29, 27, 25, 28, 29, 30, 29, + 26, 23, 24, 26, 27, 27, 25, 21, 15, 21, 24, 23, 21, 18, 16, 15, 17, 19, 16, + 15, 17, 17, 15, 11, 11, 13, 15, 16, 16, 15, 25, 28, 30, 31, 30, 30, 29, 24, + 27, 30, 31, 30, 29, 26, 22, 26, 29, 28, 27, 25, 22, 22, 24, 25, 25, 23, 20, + 14, 18, 20, 22, 20, 15, 15, 14, 13, 16, 15, 14, 14, 14, 14, 7, 9, 12, 13, + 13, 14, 14, 23, 26, 27, 29, 30, 29, 26, 21, 25, 27, 29, 29, 27, 23, 20, 24, + 26, 26, 25, 24, 20, 18, 21, 22, 22, 21, 18, 14, 13, 17, 18, 17, 14, 14, 13, + 6, 13, 12, 10, 12, 12, 13, 3, 7, 8, 10, 11, 11, 13, 20, 21, 22, 24, 25, + 26, 25, 18, 20, 22, 23, 23, 22, 21, 15, 20, 20, 21, 20, 19, 18, 11, 19, 17, + 17, 16, 12, 13, 9, 14, 13, 11, 7, 8, 9, 6, 7, 6, 4, 6, 7, 7, 3, + 0, 3, 4, 5, 6, 8, 16, 19, 20, 21, 22, 24, 24, 12, 18, 20, 21, 21, 21, + 21, 12, 18, 18, 18, 18, 17, 16, 12, 14, 15, 14, 13, 10, 8, 10, 8, 9, 8, + 5, 4, 7, 6, 5, 5, 5, 5, 4, 6, 3, 3, 5, 5, 6, 5, 5, 13, 14, + 16, 17, 20, 22, 24, 13, 13, 14, 16, 18, 19, 20, 13, 13, 13, 14, 15, 16, 14, + 13, 12, 12, 12, 10, 9, 6, 10, 10, 11, 9, 7, 5, 5, 7, 8, 10, 9, 7, + 6, 4, 5, 7, 10, 10, 8, 7, 4, 14, 17, 16, 15, 18, 21, 22, 14, 16, 17, + 15, 16, 18, 18, 14, 17, 18, 14, 13, 13, 13, 14, 15, 17, 13, 11, 8, 4, 12, + 13, 15, 12, 8, 6, 5, 10, 12, 14, 13, 9, 7, 5, 8, 11, 14, 14, 10, 8, + 6, 25, 28, 31, 33, 33, 32, 29, 23, 27, 30, 32, 33, 30, 26, 21, 26, 29, 30, + 30, 27, 23, 21, 23, 26, 27, 28, 22, 17, 17, 20, 22, 23, 21, 19, 16, 13, 16, + 17, 17, 20, 19, 17, 8, 11, 14, 17, 19, 19, 16, 22, 25, 29, 31, 31, 29, 27, + 20, 25, 28, 30, 29, 28, 24, 19, 23, 26, 28, 27, 25, 21, 18, 21, 24, 25, 23, + 20, 15, 15, 17, 19, 20, 17, 16, 15, 11, 13, 15, 15, 15, 16, 15, 5, 9, 12, + 14, 15, 15, 15, 20, 23, 26, 27, 28, 26, 22, 18, 22, 24, 25, 26, 24, 20, 17, + 21, 23, 22, 22, 22, 17, 15, 18, 19, 19, 19, 17, 11, 9, 14, 15, 15, 12, 12, + 12, 3, 10, 11, 10, 10, 11, 11, 3, 6, 8, 8, 9, 9, 10, 17, 18, 18, 19, + 21, 22, 19, 14, 16, 17, 18, 19, 19, 16, 11, 15, 16, 16, 15, 15, 13, 8, 13, + 12, 12, 11, 10, 10, 6, 9, 8, 8, 5, 5, 6, 3, 3, 3, 2, 3, 4, 4, + 3, 3, 0, 2, 3, 4, 5, 12, 14, 15, 16, 17, 18, 19, 8, 13, 14, 15, 16, + 16, 16, 8, 12, 13, 13, 13, 13, 11, 8, 10, 10, 10, 9, 7, 4, 6, 6, 5, + 5, 6, 4, 4, 4, 6, 8, 8, 8, 6, 3, 2, 7, 10, 10, 10, 8, 3, 9, + 11, 11, 13, 15, 17, 18, 9, 12, 12, 13, 13, 15, 16, 9, 14, 14, 14, 11, 11, + 10, 9, 13, 15, 15, 11, 7, 3, 7, 12, 17, 17, 13, 8, 3, 7, 13, 19, 19, + 15, 10, 5, 8, 14, 20, 20, 17, 12, 6, 16, 22, 22, 16, 13, 16, 17, 16, 23, + 24, 18, 12, 13, 14, 17, 23, 26, 19, 13, 9, 10, 17, 22, 26, 20, 14, 9, 5, + 15, 21, 25, 23, 17, 12, 6, 15, 21, 25, 23, 18, 14, 8, 16, 21, 24, 24, 20, + 15, 10, 23, 26, 30, 33, 32, 30, 27, 21, 25, 29, 32, 32, 29, 26, 19, 24, 27, + 31, 31, 27, 22, 18, 21, 24, 27, 28, 24, 18, 15, 18, 20, 23, 23, 21, 18, 11, + 14, 17, 18, 22, 21, 18, 8, 11, 14, 17, 20, 21, 18, 19, 23, 27, 31, 29, 27, + 25, 18, 22, 26, 30, 29, 25, 22, 17, 20, 25, 26, 26, 24, 19, 16, 19, 22, 24, + 23, 20, 15, 13, 15, 18, 19, 18, 17, 14, 9, 11, 14, 16, 16, 16, 14, 5, 8, + 12, 15, 15, 15, 14, 17, 21, 23, 24, 26, 23, 20, 16, 19, 22, 23, 23, 21, 18, + 15, 18, 20, 20, 20, 20, 15, 13, 16, 16, 17, 17, 15, 10, 8, 12, 13, 13, 12, + 11, 10, 3, 8, 9, 9, 9, 10, 10, 3, 6, 7, 8, 8, 9, 8, 15, 15, 16, + 17, 19, 19, 15, 13, 14, 15, 16, 17, 17, 13, 10, 12, 13, 13, 13, 13, 10, 6, + 10, 9, 9, 9, 8, 8, 4, 6, 6, 6, 4, 3, 4, 2, 2, 2, 2, 2, 3, + 3, 3, 4, 2, 0, 2, 2, 3, 9, 10, 11, 12, 13, 15, 15, 6, 10, 11, 12, + 13, 13, 13, 6, 9, 9, 9, 10, 9, 9, 6, 7, 6, 6, 6, 5, 3, 4, 6, + 6, 6, 6, 4, 3, 2, 7, 9, 8, 8, 6, 2, 4, 8, 11, 10, 9, 8, 3, + 9, 11, 11, 12, 12, 14, 15, 9, 13, 13, 13, 11, 11, 11, 9, 15, 15, 14, 10, + 8, 8, 9, 14, 15, 15, 11, 6, 2, 8, 13, 18, 16, 12, 8, 3, 8, 14, 20, + 19, 14, 9, 5, 9, 14, 20, 21, 16, 11, 6, 17, 23, 22, 17, 11, 12, 13, 17, + 23, 24, 18, 12, 10, 10, 17, 23, 27, 19, 13, 8, 7, 17, 22, 27, 20, 15, 9, + 5, 16, 21, 27, 22, 16, 11, 6, 16, 22, 27, 25, 18, 13, 8, 16, 22, 27, 27, + 21, 15, 9, 20, 25, 28, 32, 32, 30, 27, 20, 23, 27, 31, 32, 27, 24, 17, 22, + 25, 29, 30, 26, 22, 17, 19, 22, 25, 28, 24, 18, 14, 16, 19, 21, 24, 22, 18, + 10, 12, 15, 18, 22, 21, 18, 8, 10, 14, 17, 20, 21, 18, 18, 22, 26, 29, 29, + 25, 22, 17, 20, 23, 27, 28, 24, 20, 15, 19, 23, 25, 25, 22, 19, 14, 17, 20, + 22, 22, 20, 14, 11, 14, 15, 18, 18, 17, 14, 7, 10, 13, 15, 16, 17, 14, 5, + 8, 12, 14, 15, 15, 14, 16, 19, 20, 22, 24, 22, 18, 14, 17, 20, 21, 22, 20, + 15, 13, 17, 18, 18, 19, 17, 13, 12, 15, 15, 14, 15, 14, 10, 8, 11, 11, 11, + 11, 10, 9, 3, 8, 9, 9, 9, 9, 9, 4, 6, 7, 7, 8, 8, 8, 13, 14, + 14, 15, 17, 18, 13, 12, 12, 13, 14, 14, 14, 11, 9, 11, 11, 11, 11, 11, 8, + 5, 9, 8, 7, 7, 7, 6, 3, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, + 2, 2, 4, 5, 3, 2, 0, 1, 2, 7, 7, 8, 9, 11, 12, 12, 5, 7, 8, + 9, 9, 10, 10, 5, 6, 7, 7, 7, 7, 7, 5, 6, 5, 5, 5, 4, 2, 3, + 7, 6, 6, 6, 4, 2, 3, 8, 9, 8, 8, 6, 2, 4, 8, 11, 10, 10, 7, + 3, 10, 12, 12, 11, 9, 11, 12, 10, 14, 13, 13, 10, 8, 9, 10, 16, 15, 14, + 10, 6, 6, 10, 15, 16, 15, 11, 6, 2, 9, 14, 18, 17, 12, 8, 3, 9, 15, + 20, 19, 14, 9, 5, 10, 15, 20, 21, 16, 11, 6, 18, 24, 23, 16, 12, 10, 10, + 18, 23, 24, 18, 13, 8, 8, 18, 24, 26, 19, 13, 8, 5, 18, 23, 28, 21, 15, + 10, 4, 17, 22, 27, 23, 16, 11, 6, 17, 22, 27, 26, 18, 13, 8, 17, 22, 27, + 27, 21, 15, 9, 20, 24, 27, 31, 30, 28, 25, 18, 22, 25, 29, 30, 27, 23, 16, + 20, 24, 27, 28, 25, 21, 15, 18, 21, 24, 27, 23, 18, 12, 15, 17, 21, 24, 21, + 18, 9, 12, 15, 18, 22, 21, 18, 8, 11, 14, 17, 21, 21, 18, 17, 20, 24, 28, + 28, 25, 21, 15, 20, 23, 26, 27, 23, 19, 14, 17, 21, 24, 24, 21, 17, 13, 15, + 19, 20, 20, 19, 14, 10, 12, 15, 17, 17, 17, 14, 7, 10, 13, 15, 16, 16, 14, + 6, 9, 12, 15, 14, 14, 14, 14, 17, 20, 21, 22, 20, 16, 13, 16, 18, 19, 20, + 19, 14, 12, 15, 17, 17, 17, 16, 12, 11, 13, 13, 13, 14, 13, 9, 7, 9, 10, + 10, 10, 10, 9, 4, 8, 9, 9, 9, 9, 9, 5, 7, 7, 7, 8, 8, 8, 12, + 12, 13, 14, 15, 16, 11, 10, 11, 11, 12, 13, 13, 9, 9, 9, 10, 10, 9, 9, + 7, 5, 7, 6, 6, 6, 6, 5, 2, 3, 3, 3, 2, 3, 3, 3, 3, 2, 2, + 1, 1, 2, 5, 6, 4, 3, 1, 0, 1, 5, 5, 6, 8, 8, 10, 11, 4, 5, + 6, 7, 8, 8, 9, 4, 5, 5, 5, 5, 5, 5, 4, 6, 5, 5, 5, 3, 2, + 3, 8, 7, 6, 6, 4, 1, 4, 9, 10, 8, 8, 6, 2, 5, 9, 12, 10, 10, + 8, 3, 10, 12, 11, 11, 9, 9, 10, 10, 14, 13, 12, 10, 7, 7, 10, 16, 14, + 13, 10, 5, 4, 10, 15, 15, 14, 10, 6, 2, 10, 14, 17, 15, 12, 8, 3, 10, + 15, 19, 17, 13, 9, 5, 10, 15, 20, 19, 15, 11, 6, 17, 21, 19, 15, 11, 8, + 8, 17, 21, 20, 16, 12, 8, 6, 18, 21, 22, 16, 12, 8, 4, 17, 20, 22, 17, + 13, 9, 5, 17, 20, 23, 20, 15, 11, 6, 16, 20, 23, 21, 16, 13, 8, 16, 20, + 23, 23, 18, 13, 9, 19, 23, 26, 29, 30, 28, 24, 17, 21, 24, 29, 29, 26, 22, + 16, 20, 23, 27, 27, 24, 20, 14, 17, 20, 24, 26, 22, 18, 11, 14, 16, 20, 23, + 21, 18, 10, 13, 15, 19, 22, 21, 18, 8, 11, 15, 18, 21, 21, 18, 16, 20, 23, + 27, 26, 23, 20, 14, 19, 22, 26, 25, 22, 18, 13, 17, 20, 23, 23, 20, 16, 12, + 15, 17, 21, 20, 18, 14, 9, 12, 14, 17, 17, 17, 14, 8, 11, 13, 16, 16, 16, + 14, 6, 9, 12, 15, 15, 15, 14, 13, 17, 19, 20, 21, 19, 15, 12, 16, 18, 19, + 19, 18, 13, 11, 14, 16, 16, 16, 16, 11, 10, 12, 13, 12, 13, 13, 9, 6, 9, + 10, 10, 10, 10, 9, 5, 8, 9, 9, 9, 9, 9, 6, 7, 8, 8, 8, 8, 8, + 11, 11, 12, 13, 14, 15, 9, 9, 9, 10, 11, 12, 11, 7, 8, 8, 9, 9, 8, + 8, 6, 4, 6, 5, 5, 5, 5, 4, 3, 3, 3, 3, 3, 3, 2, 4, 4, 3, + 2, 2, 2, 2, 6, 8, 5, 3, 2, 1, 0, 2, 3, 5, 6, 7, 8, 9, 2, + 3, 4, 5, 6, 6, 7, 2, 3, 3, 3, 3, 4, 4, 2, 5, 3, 2, 2, 2, + 1, 3, 7, 5, 4, 4, 3, 0, 5, 8, 7, 5, 3, 3, 2, 7, 8, 8, 6, + 5, 3, 2, 6, 6, 5, 5, 6, 7, 9, 6, 8, 5, 5, 5, 5, 6, 6, 8, + 6, 5, 3, 3, 3, 6, 7, 7, 5, 4, 3, 1, 7, 9, 10, 8, 6, 3, 2, + 8, 10, 13, 11, 7, 4, 3, 9, 11, 14, 14, 9, 5, 3, 8, 11, 10, 6, 5, + 7, 7, 8, 11, 11, 7, 4, 4, 4, 8, 11, 13, 7, 4, 3, 2, 8, 11, 14, + 9, 6, 4, 3, 9, 11, 15, 13, 8, 5, 3, 9, 13, 18, 16, 11, 6, 3, 11, + 15, 18, 17, 12, 7, 4, 14, 17, 20, 24, 23, 22, 19, 13, 16, 19, 23, 23, 21, + 17, 12, 14, 17, 20, 21, 18, 16, 11, 13, 15, 17, 20, 18, 15, 11, 13, 14, 15, + 19, 17, 15, 9, 11, 13, 15, 17, 17, 15, 12, 12, 12, 14, 16, 17, 15, 12, 15, + 17, 20, 21, 19, 16, 11, 13, 16, 19, 21, 18, 14, 11, 13, 15, 17, 18, 16, 13, + 9, 12, 14, 15, 15, 14, 13, 9, 11, 13, 14, 14, 14, 13, 7, 10, 11, 13, 13, + 13, 13, 14, 14, 11, 12, 12, 12, 12, 10, 13, 14, 15, 16, 15, 12, 9, 12, 13, + 13, 15, 14, 11, 8, 11, 12, 12, 12, 13, 11, 7, 10, 11, 11, 12, 11, 11, 6, + 9, 11, 11, 11, 11, 11, 9, 10, 10, 9, 10, 11, 11, 15, 16, 12, 9, 9, 10, + 11, 8, 8, 9, 10, 10, 11, 4, 7, 7, 8, 8, 8, 9, 5, 6, 6, 6, 7, + 7, 7, 4, 4, 5, 5, 6, 6, 6, 4, 4, 4, 4, 5, 5, 5, 4, 9, 11, + 10, 8, 6, 3, 3, 15, 16, 12, 9, 7, 4, 2, 0, 1, 1, 2, 2, 2, 4, + 2, 2, 2, 2, 2, 1, 5, 2, 3, 3, 3, 4, 2, 4, 2, 6, 5, 6, 6, + 5, 2, 4, 9, 8, 7, 7, 7, 3, 9, 11, 11, 9, 9, 8, 4, 14, 14, 13, + 10, 9, 8, 6, 8, 8, 8, 8, 7, 2, 3, 8, 10, 9, 9, 7, 3, 2, 7, + 11, 10, 9, 8, 5, 0, 8, 10, 11, 10, 8, 7, 4, 8, 11, 14, 13, 11, 8, + 6, 10, 13, 17, 15, 12, 9, 7, 12, 15, 17, 16, 13, 10, 8, 12, 16, 14, 11, + 8, 6, 2, 12, 16, 16, 12, 9, 6, 2, 12, 16, 18, 12, 9, 7, 4, 12, 15, + 19, 14, 11, 8, 7, 12, 16, 19, 17, 13, 10, 7, 13, 17, 20, 19, 15, 11, 8, + 15, 18, 20, 21, 16, 12, 9, 15, 17, 19, 20, 21, 18, 17, 14, 16, 18, 20, 20, + 19, 17, 12, 15, 18, 19, 20, 18, 17, 11, 14, 17, 18, 20, 19, 17, 11, 14, 17, + 19, 21, 19, 17, 10, 14, 16, 18, 20, 19, 17, 13, 13, 15, 18, 20, 19, 17, 13, + 15, 18, 19, 18, 16, 14, 12, 15, 17, 19, 18, 16, 14, 11, 14, 16, 17, 17, 16, + 14, 9, 13, 16, 17, 17, 17, 15, 9, 12, 15, 17, 17, 17, 15, 8, 11, 14, 16, + 16, 16, 15, 16, 14, 13, 15, 15, 15, 15, 10, 14, 14, 15, 15, 13, 10, 9, 12, + 14, 14, 14, 13, 10, 8, 11, 12, 13, 13, 13, 10, 7, 11, 12, 12, 13, 13, 11, + 7, 10, 11, 12, 12, 12, 11, 10, 11, 10, 11, 11, 11, 11, 17, 17, 12, 10, 10, + 10, 10, 8, 8, 8, 9, 9, 9, 3, 7, 7, 7, 7, 8, 8, 3, 6, 6, 6, + 6, 6, 6, 4, 4, 5, 5, 6, 6, 6, 4, 6, 6, 5, 5, 5, 5, 4, 10, + 12, 10, 9, 6, 5, 3, 17, 19, 14, 10, 7, 5, 3, 1, 0, 1, 1, 2, 2, + 3, 2, 2, 1, 2, 2, 1, 3, 2, 3, 3, 3, 3, 1, 3, 2, 7, 6, 6, + 6, 5, 3, 5, 11, 10, 10, 11, 8, 3, 10, 14, 16, 15, 13, 10, 5, 16, 19, + 20, 16, 15, 12, 7, 9, 10, 10, 10, 7, 2, 2, 8, 12, 12, 11, 8, 3, 2, + 8, 14, 14, 14, 9, 5, 1, 8, 15, 17, 17, 13, 9, 5, 11, 17, 22, 21, 17, + 12, 7, 14, 20, 26, 25, 20, 15, 9, 18, 23, 27, 25, 21, 17, 11, 17, 22, 21, + 15, 10, 5, 1, 16, 22, 24, 17, 12, 6, 2, 16, 22, 25, 18, 13, 9, 4, 16, + 22, 27, 22, 17, 13, 9, 18, 24, 29, 26, 21, 17, 11, 20, 26, 30, 29, 23, 18, + 13, 23, 28, 30, 30, 25, 21, 15, 14, 17, 20, 22, 23, 20, 18, 13, 16, 19, 22, + 23, 20, 18, 12, 15, 18, 21, 23, 20, 18, 11, 14, 17, 21, 23, 22, 19, 12, 14, + 18, 20, 24, 23, 19, 11, 14, 17, 20, 23, 22, 19, 14, 14, 16, 19, 22, 21, 19, + 12, 15, 18, 21, 19, 17, 14, 11, 14, 18, 19, 19, 16, 14, 10, 13, 16, 19, 18, + 17, 15, 9, 13, 16, 18, 18, 18, 16, 10, 13, 15, 18, 18, 18, 15, 10, 11, 15, + 17, 18, 18, 16, 17, 16, 14, 16, 17, 16, 16, 10, 13, 15, 15, 15, 13, 9, 9, + 12, 13, 13, 14, 12, 9, 8, 11, 12, 12, 12, 13, 10, 8, 11, 12, 12, 12, 13, + 11, 7, 10, 12, 12, 12, 12, 11, 12, 12, 11, 11, 11, 11, 11, 19, 18, 14, 10, + 10, 10, 10, 8, 8, 8, 8, 8, 8, 2, 7, 7, 7, 7, 7, 7, 2, 6, 6, + 6, 6, 6, 6, 3, 4, 6, 6, 6, 6, 6, 4, 6, 7, 6, 6, 6, 5, 4, + 12, 13, 12, 10, 8, 6, 4, 19, 20, 15, 11, 8, 6, 5, 1, 1, 0, 1, 1, + 1, 2, 2, 2, 2, 1, 2, 1, 2, 2, 4, 3, 4, 4, 2, 3, 2, 7, 7, + 7, 7, 6, 4, 6, 12, 12, 11, 11, 9, 5, 11, 15, 17, 16, 14, 11, 6, 18, + 21, 20, 17, 16, 13, 7, 9, 11, 9, 9, 6, 2, 2, 9, 13, 11, 11, 7, 3, + 1, 9, 14, 14, 14, 10, 6, 2, 9, 16, 18, 17, 14, 10, 6, 12, 18, 23, 21, + 18, 13, 7, 15, 21, 28, 26, 20, 15, 9, 19, 25, 29, 27, 23, 17, 11, 16, 22, + 21, 15, 9, 5, 1, 17, 22, 23, 16, 11, 6, 2, 16, 22, 26, 19, 13, 9, 5, + 16, 23, 29, 23, 18, 14, 10, 18, 25, 31, 28, 22, 17, 11, 22, 28, 33, 33, 26, + 19, 13, 25, 30, 34, 34, 28, 21, 15, 14, 17, 21, 23, 24, 20, 18, 14, 16, 19, + 23, 24, 21, 18, 12, 15, 18, 22, 23, 22, 19, 11, 15, 18, 22, 25, 23, 20, 12, + 15, 18, 22, 26, 23, 20, 11, 14, 17, 21, 25, 23, 20, 16, 15, 17, 20, 23, 22, + 19, 12, 15, 18, 20, 20, 17, 14, 12, 14, 17, 20, 19, 17, 14, 10, 13, 17, 19, + 19, 18, 15, 9, 13, 17, 20, 19, 18, 16, 10, 13, 16, 18, 19, 19, 16, 11, 12, + 15, 18, 18, 18, 16, 18, 17, 15, 17, 17, 17, 16, 10, 13, 14, 15, 15, 12, 9, + 9, 12, 13, 13, 14, 12, 9, 9, 11, 13, 13, 13, 13, 10, 8, 11, 13, 13, 13, + 14, 11, 7, 10, 12, 12, 12, 12, 11, 13, 13, 13, 12, 12, 11, 11, 20, 19, 15, + 12, 10, 11, 10, 9, 8, 8, 8, 8, 8, 2, 8, 7, 7, 7, 7, 6, 2, 6, + 6, 6, 7, 6, 6, 3, 4, 6, 6, 6, 6, 6, 5, 6, 8, 8, 8, 8, 6, + 5, 13, 15, 13, 11, 9, 7, 5, 21, 21, 16, 12, 9, 7, 6, 2, 1, 1, 0, + 1, 1, 2, 3, 2, 2, 2, 2, 0, 2, 2, 4, 4, 4, 4, 3, 3, 2, 8, + 8, 8, 8, 7, 5, 7, 13, 12, 12, 13, 10, 6, 13, 17, 18, 17, 14, 12, 7, + 19, 22, 22, 19, 17, 14, 8, 9, 11, 9, 9, 6, 2, 2, 10, 12, 11, 11, 7, + 3, 2, 10, 15, 14, 14, 11, 6, 3, 9, 17, 18, 18, 15, 10, 7, 13, 19, 24, + 22, 18, 13, 8, 16, 22, 29, 27, 21, 16, 10, 21, 26, 30, 30, 25, 17, 12, 17, + 22, 20, 14, 9, 5, 1, 17, 22, 23, 16, 11, 6, 3, 17, 22, 25, 19, 14, 10, + 6, 17, 24, 29, 24, 18, 14, 10, 20, 26, 31, 29, 23, 18, 12, 23, 30, 35, 33, + 26, 19, 14, 25, 32, 35, 36, 28, 22, 16, 15, 18, 21, 24, 24, 21, 18, 14, 17, + 19, 23, 24, 22, 19, 12, 15, 19, 23, 25, 23, 20, 11, 16, 19, 22, 26, 24, 20, + 12, 16, 19, 23, 26, 24, 21, 12, 15, 18, 22, 26, 24, 21, 17, 17, 18, 20, 24, + 24, 21, 12, 16, 19, 22, 20, 17, 14, 12, 15, 18, 20, 20, 17, 15, 10, 14, 17, + 20, 20, 19, 16, 10, 14, 17, 20, 20, 19, 16, 10, 14, 17, 19, 20, 20, 17, 12, + 14, 16, 19, 19, 19, 17, 20, 18, 16, 18, 18, 18, 17, 10, 14, 15, 14, 15, 13, + 9, 10, 12, 13, 14, 14, 13, 10, 9, 12, 13, 14, 14, 14, 11, 9, 12, 14, 14, + 14, 14, 12, 8, 11, 13, 13, 13, 13, 12, 14, 14, 14, 13, 13, 12, 12, 22, 20, + 16, 12, 11, 11, 10, 9, 8, 8, 8, 8, 8, 2, 9, 7, 7, 7, 7, 7, 3, + 6, 6, 6, 7, 7, 7, 4, 6, 6, 7, 7, 7, 7, 6, 7, 8, 9, 9, 9, + 8, 6, 14, 16, 14, 12, 10, 8, 6, 22, 22, 17, 13, 10, 8, 7, 2, 2, 1, + 1, 0, 1, 2, 3, 2, 2, 2, 2, 1, 3, 3, 4, 4, 5, 5, 4, 3, 3, + 8, 8, 9, 9, 7, 6, 7, 14, 13, 13, 13, 11, 7, 14, 18, 19, 18, 15, 12, + 8, 20, 23, 23, 19, 18, 14, 9, 10, 10, 9, 8, 5, 2, 2, 10, 12, 10, 9, + 7, 4, 2, 10, 13, 12, 13, 10, 7, 4, 10, 15, 17, 16, 15, 11, 7, 13, 19, + 23, 21, 18, 14, 9, 17, 23, 28, 26, 20, 16, 11, 21, 27, 29, 28, 23, 18, 13, + 15, 17, 14, 10, 8, 4, 1, 15, 17, 15, 11, 9, 7, 3, 15, 17, 18, 15, 13, + 11, 7, 15, 19, 23, 20, 17, 15, 11, 18, 23, 27, 25, 22, 18, 13, 23, 27, 31, + 30, 24, 19, 15, 27, 30, 32, 32, 26, 21, 17, 13, 16, 20, 23, 23, 20, 17, 13, + 16, 18, 22, 23, 21, 19, 12, 14, 18, 22, 25, 22, 19, 11, 15, 19, 22, 26, 23, + 20, 12, 15, 18, 21, 25, 23, 20, 12, 15, 18, 21, 25, 23, 20, 18, 18, 17, 20, + 23, 23, 20, 12, 15, 17, 20, 18, 15, 13, 11, 14, 17, 19, 19, 17, 14, 10, 13, + 16, 19, 20, 17, 15, 9, 12, 16, 20, 19, 18, 16, 9, 13, 16, 19, 20, 19, 16, + 13, 14, 16, 18, 18, 18, 15, 21, 19, 17, 17, 17, 17, 16, 10, 13, 13, 13, 14, + 11, 8, 9, 12, 12, 12, 13, 12, 9, 8, 11, 12, 13, 13, 13, 10, 7, 11, 12, + 13, 13, 13, 11, 7, 11, 12, 13, 13, 13, 11, 15, 16, 15, 13, 12, 12, 11, 23, + 22, 17, 14, 11, 10, 10, 8, 7, 7, 7, 7, 7, 2, 7, 6, 6, 6, 6, 6, + 2, 4, 5, 5, 6, 6, 6, 4, 8, 5, 6, 6, 6, 7, 6, 8, 9, 10, 10, + 10, 9, 7, 15, 17, 16, 14, 11, 9, 8, 23, 24, 18, 15, 12, 10, 8, 2, 2, + 2, 1, 1, 0, 2, 4, 2, 2, 2, 2, 2, 2, 4, 3, 3, 4, 5, 5, 4, + 4, 7, 7, 8, 8, 8, 8, 8, 13, 13, 13, 13, 11, 8, 15, 19, 19, 17, 14, + 12, 9, 22, 24, 22, 18, 15, 13, 10, 6, 6, 4, 3, 3, 2, 1, 6, 7, 5, + 4, 3, 3, 2, 6, 9, 6, 7, 6, 6, 6, 6, 11, 12, 12, 11, 10, 9, 11, + 15, 19, 17, 15, 13, 10, 17, 21, 25, 22, 17, 13, 11, 22, 25, 26, 24, 19, 15, + 12, 10, 12, 8, 5, 3, 2, 2, 10, 12, 10, 6, 4, 4, 4, 10, 12, 13, 9, + 9, 8, 7, 10, 14, 18, 16, 13, 12, 10, 14, 18, 23, 22, 18, 15, 12, 19, 23, + 27, 27, 21, 16, 13, 24, 27, 28, 29, 23, 18, 13, 9, 11, 13, 15, 16, 13, 11, + 9, 11, 12, 15, 16, 14, 12, 8, 10, 12, 16, 18, 15, 13, 7, 10, 13, 16, 19, + 17, 15, 8, 11, 14, 17, 20, 17, 14, 11, 13, 15, 16, 19, 17, 14, 18, 18, 16, + 16, 18, 17, 15, 8, 10, 11, 14, 11, 9, 7, 7, 9, 11, 13, 12, 10, 8, 7, + 8, 11, 14, 13, 11, 10, 6, 9, 12, 14, 13, 12, 11, 6, 10, 12, 14, 14, 13, + 11, 13, 14, 15, 16, 14, 13, 11, 21, 19, 17, 15, 13, 12, 11, 7, 9, 8, 7, + 7, 5, 3, 6, 8, 8, 7, 7, 7, 5, 5, 7, 7, 8, 8, 8, 6, 3, 7, + 8, 9, 9, 9, 8, 7, 10, 10, 10, 10, 9, 8, 16, 16, 15, 13, 11, 9, 8, + 23, 22, 18, 14, 12, 10, 8, 5, 4, 3, 3, 3, 2, 0, 3, 2, 3, 2, 2, + 3, 2, 6, 2, 2, 3, 3, 3, 4, 10, 3, 5, 6, 6, 6, 6, 9, 10, 10, + 10, 10, 9, 7, 16, 18, 16, 14, 12, 10, 8, 23, 24, 19, 15, 12, 11, 9, 4, + 3, 2, 2, 2, 2, 0, 6, 4, 3, 2, 2, 3, 2, 6, 4, 4, 5, 5, 5, + 5, 6, 8, 8, 9, 10, 9, 8, 9, 15, 15, 15, 15, 12, 9, 15, 21, 21, 19, + 16, 14, 10, 22, 25, 25, 21, 18, 15, 11, 8, 7, 5, 5, 3, 2, 1, 8, 10, + 7, 6, 4, 4, 3, 8, 11, 10, 11, 9, 7, 6, 8, 13, 16, 16, 15, 12, 10, + 12, 19, 23, 22, 19, 16, 11, 18, 24, 30, 27, 22, 16, 13, 23, 28, 31, 30, 24, + 18, 14, 12, 16, 14, 8, 5, 3, 2, 13, 16, 16, 10, 6, 5, 4, 12, 16, 19, + 15, 12, 10, 8, 13, 18, 25, 21, 18, 15, 12, 17, 23, 29, 28, 23, 19, 14, 22, + 27, 33, 33, 26, 20, 16, 27, 32, 34, 34, 28, 23, 17, 16, 19, 23, 26, 26, 25, + 22, 15, 19, 22, 25, 26, 23, 21, 14, 17, 20, 23, 24, 22, 19, 13, 15, 17, 20, + 22, 20, 18, 12, 14, 16, 18, 21, 19, 18, 10, 12, 15, 17, 20, 20, 18, 10, 11, + 13, 16, 19, 20, 18, 14, 17, 20, 24, 24, 23, 18, 13, 16, 19, 22, 24, 22, 17, + 12, 14, 18, 20, 20, 18, 15, 11, 13, 15, 17, 18, 16, 14, 10, 12, 14, 15, 16, + 17, 14, 8, 11, 13, 14, 15, 15, 15, 11, 11, 12, 13, 14, 15, 14, 12, 14, 16, + 17, 19, 19, 14, 11, 13, 15, 16, 16, 17, 13, 10, 12, 14, 14, 15, 15, 12, 9, + 12, 12, 12, 12, 13, 12, 7, 10, 12, 12, 11, 12, 12, 8, 9, 10, 10, 11, 11, + 12, 12, 12, 10, 9, 10, 11, 12, 10, 10, 11, 11, 12, 14, 6, 8, 9, 9, 10, + 10, 11, 6, 7, 7, 8, 8, 9, 9, 5, 4, 6, 7, 7, 7, 7, 6, 5, 5, + 5, 6, 6, 7, 4, 8, 8, 7, 6, 5, 5, 4, 12, 12, 8, 6, 5, 4, 2, + 2, 2, 2, 2, 3, 4, 6, 0, 1, 1, 2, 1, 2, 5, 0, 2, 2, 1, 1, + 1, 4, 0, 2, 2, 1, 1, 1, 4, 2, 4, 3, 3, 4, 2, 2, 5, 7, 7, + 6, 5, 3, 2, 9, 10, 9, 7, 6, 4, 2, 4, 5, 5, 5, 3, 2, 4, 4, + 6, 6, 6, 3, 1, 3, 4, 7, 7, 6, 4, 1, 2, 4, 7, 8, 7, 5, 3, + 2, 4, 8, 10, 9, 7, 4, 2, 6, 10, 14, 11, 9, 6, 2, 9, 12, 14, 13, + 10, 6, 3, 9, 12, 11, 8, 5, 2, 2, 9, 12, 12, 8, 5, 2, 1, 9, 12, + 14, 9, 6, 3, 1, 9, 12, 15, 10, 7, 5, 2, 9, 12, 15, 13, 10, 7, 4, + 10, 13, 17, 16, 11, 8, 5, 12, 15, 16, 17, 13, 9, 6, 16, 19, 20, 22, 22, + 20, 18, 15, 18, 20, 21, 22, 20, 17, 14, 16, 18, 21, 22, 19, 18, 13, 15, 19, + 20, 22, 20, 18, 13, 16, 18, 20, 22, 21, 19, 11, 15, 18, 19, 21, 20, 18, 12, + 13, 17, 19, 20, 20, 18, 14, 17, 19, 21, 19, 18, 16, 13, 16, 18, 20, 19, 18, + 16, 12, 15, 17, 19, 18, 17, 16, 11, 14, 17, 18, 17, 18, 16, 11, 14, 17, 19, + 18, 18, 17, 9, 12, 15, 17, 18, 18, 16, 15, 14, 14, 16, 16, 17, 16, 12, 15, + 16, 16, 16, 15, 12, 11, 14, 15, 15, 15, 15, 12, 10, 13, 14, 14, 15, 15, 12, + 9, 12, 14, 13, 14, 14, 12, 8, 11, 13, 13, 13, 13, 12, 10, 10, 11, 12, 13, + 13, 12, 17, 16, 12, 10, 11, 11, 12, 10, 9, 10, 10, 10, 11, 4, 9, 8, 9, + 9, 9, 9, 4, 7, 7, 7, 8, 8, 8, 5, 5, 7, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 5, 10, 11, 10, 9, 6, 5, 4, 17, 18, 13, 10, 7, 5, + 3, 2, 2, 2, 2, 2, 2, 4, 1, 0, 1, 1, 1, 2, 4, 1, 2, 2, 2, + 1, 0, 4, 1, 5, 5, 5, 5, 4, 3, 4, 9, 9, 9, 9, 7, 3, 9, 13, + 15, 14, 12, 9, 4, 16, 18, 18, 15, 14, 11, 5, 7, 9, 8, 9, 5, 1, 3, + 7, 11, 10, 10, 7, 2, 3, 7, 13, 13, 12, 8, 3, 2, 7, 13, 15, 15, 12, + 7, 4, 9, 16, 19, 18, 16, 11, 5, 12, 18, 22, 20, 17, 13, 7, 17, 21, 23, + 22, 18, 15, 9, 15, 20, 18, 14, 9, 4, 2, 15, 19, 20, 15, 11, 5, 1, 15, + 19, 21, 16, 12, 7, 3, 15, 20, 23, 19, 16, 12, 7, 16, 21, 24, 22, 18, 15, + 9, 18, 22, 25, 24, 20, 16, 12, 21, 23, 26, 25, 21, 18, 13, 16, 19, 21, 24, + 24, 22, 19, 15, 18, 20, 23, 25, 21, 19, 13, 17, 20, 23, 24, 21, 20, 13, 16, + 19, 22, 24, 22, 20, 13, 16, 19, 22, 25, 23, 20, 12, 15, 18, 21, 24, 23, 21, + 13, 14, 17, 20, 23, 24, 21, 13, 17, 20, 22, 21, 18, 16, 12, 16, 18, 21, 20, + 18, 15, 12, 14, 17, 20, 20, 18, 16, 10, 14, 17, 21, 19, 19, 17, 11, 14, 17, + 19, 20, 20, 17, 9, 13, 16, 18, 19, 19, 17, 16, 15, 15, 18, 17, 18, 17, 11, + 14, 16, 16, 16, 14, 11, 10, 13, 15, 15, 15, 14, 11, 10, 12, 14, 13, 14, 14, + 11, 9, 12, 14, 14, 14, 14, 12, 8, 11, 13, 13, 13, 13, 12, 11, 11, 12, 12, + 12, 12, 12, 18, 17, 13, 11, 11, 11, 11, 10, 9, 9, 9, 10, 9, 3, 9, 8, + 8, 8, 8, 8, 3, 8, 7, 7, 7, 7, 7, 3, 5, 7, 7, 7, 7, 7, 5, + 6, 6, 6, 6, 6, 6, 4, 11, 13, 11, 9, 7, 5, 4, 18, 20, 14, 10, 8, + 6, 4, 2, 1, 2, 2, 2, 2, 3, 1, 1, 0, 1, 1, 1, 3, 1, 2, 2, + 2, 2, 1, 3, 1, 6, 6, 6, 6, 5, 4, 5, 10, 10, 10, 10, 8, 4, 11, + 14, 16, 14, 12, 9, 5, 17, 19, 19, 16, 14, 12, 6, 7, 9, 8, 8, 5, 1, + 2, 7, 11, 10, 10, 6, 2, 2, 7, 13, 12, 12, 8, 4, 2, 8, 14, 16, 16, + 12, 8, 5, 10, 17, 21, 20, 16, 11, 6, 13, 20, 26, 25, 19, 13, 8, 17, 23, + 26, 27, 22, 16, 9, 15, 20, 19, 13, 8, 4, 1, 16, 21, 22, 15, 10, 5, 0, + 15, 20, 24, 17, 12, 8, 4, 15, 22, 27, 21, 16, 12, 8, 17, 24, 29, 27, 21, + 15, 10, 20, 26, 31, 32, 24, 18, 12, 23, 29, 33, 33, 26, 19, 14, 16, 19, 22, + 25, 25, 22, 20, 15, 18, 21, 25, 25, 22, 19, 13, 16, 20, 23, 26, 22, 21, 13, + 16, 19, 23, 26, 24, 21, 13, 16, 19, 22, 26, 25, 21, 12, 16, 19, 22, 25, 24, + 22, 15, 15, 17, 21, 25, 25, 21, 14, 16, 20, 22, 21, 19, 15, 13, 15, 19, 21, + 21, 19, 15, 12, 14, 17, 20, 21, 19, 17, 11, 15, 18, 21, 21, 20, 17, 12, 14, + 17, 20, 20, 21, 17, 11, 13, 16, 19, 20, 19, 17, 18, 16, 15, 18, 18, 18, 17, + 12, 14, 16, 16, 17, 14, 11, 11, 13, 15, 15, 15, 14, 10, 10, 12, 14, 15, 14, + 15, 11, 9, 13, 14, 14, 15, 15, 12, 9, 12, 13, 14, 14, 14, 12, 12, 13, 12, + 12, 12, 13, 12, 19, 18, 14, 11, 12, 12, 11, 10, 9, 9, 9, 9, 9, 2, 9, + 8, 8, 8, 8, 8, 2, 8, 7, 7, 8, 7, 8, 3, 5, 7, 7, 7, 7, 7, + 6, 7, 7, 7, 7, 7, 7, 4, 13, 14, 13, 11, 8, 6, 5, 19, 21, 16, 12, + 9, 7, 5, 2, 2, 1, 2, 2, 2, 2, 2, 1, 1, 0, 1, 1, 3, 2, 2, + 2, 3, 3, 2, 3, 2, 6, 6, 6, 7, 5, 5, 6, 12, 11, 11, 11, 8, 5, + 12, 16, 17, 15, 13, 10, 6, 18, 21, 20, 17, 15, 12, 7, 8, 9, 8, 8, 5, + 1, 2, 8, 11, 10, 9, 6, 2, 2, 8, 13, 13, 13, 9, 5, 3, 8, 15, 17, + 17, 13, 9, 6, 11, 18, 22, 21, 17, 12, 7, 14, 20, 26, 26, 19, 14, 9, 19, + 24, 28, 28, 22, 16, 10, 15, 21, 19, 13, 8, 3, 1, 15, 20, 21, 15, 9, 5, + 1, 15, 21, 24, 18, 13, 9, 5, 15, 22, 28, 23, 17, 13, 9, 18, 24, 30, 27, + 21, 16, 11, 20, 27, 32, 32, 24, 18, 12, 24, 30, 34, 34, 27, 20, 14, 16, 19, + 23, 26, 26, 23, 20, 15, 18, 21, 25, 26, 23, 20, 14, 17, 20, 23, 25, 24, 22, + 13, 17, 20, 24, 26, 25, 22, 14, 17, 20, 24, 27, 25, 21, 12, 16, 18, 23, 27, + 25, 22, 16, 16, 18, 22, 25, 25, 22, 14, 17, 20, 23, 22, 19, 16, 13, 16, 19, + 22, 22, 18, 16, 12, 15, 18, 21, 20, 20, 17, 11, 15, 18, 22, 21, 20, 17, 12, + 15, 18, 20, 21, 21, 17, 11, 14, 17, 20, 20, 20, 18, 18, 17, 16, 19, 18, 19, + 17, 12, 15, 15, 16, 17, 15, 11, 11, 14, 15, 15, 15, 14, 11, 10, 13, 14, 15, + 15, 15, 12, 10, 13, 15, 15, 15, 15, 12, 9, 13, 14, 14, 14, 14, 12, 13, 14, + 14, 13, 13, 13, 12, 20, 19, 15, 12, 12, 12, 12, 10, 9, 9, 9, 10, 10, 3, + 9, 8, 8, 8, 8, 8, 3, 8, 8, 8, 8, 8, 8, 3, 5, 7, 8, 8, 8, + 8, 6, 7, 8, 8, 8, 8, 7, 4, 13, 15, 13, 11, 9, 7, 5, 20, 21, 16, + 12, 10, 8, 6, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0, 2, 3, 1, + 2, 3, 3, 3, 2, 3, 1, 6, 7, 7, 7, 6, 5, 6, 11, 11, 11, 11, 8, + 6, 12, 17, 18, 16, 13, 10, 7, 19, 21, 21, 17, 16, 12, 7, 8, 9, 8, 7, + 4, 1, 2, 8, 11, 9, 8, 6, 2, 2, 8, 12, 11, 12, 9, 5, 3, 8, 14, + 16, 15, 13, 9, 6, 11, 17, 21, 20, 18, 13, 7, 15, 21, 27, 25, 19, 14, 9, + 20, 24, 28, 26, 21, 16, 11, 14, 16, 14, 10, 7, 3, 1, 13, 16, 15, 11, 9, + 5, 2, 14, 16, 18, 14, 12, 9, 5, 14, 18, 23, 19, 16, 12, 9, 17, 22, 25, + 24, 20, 16, 11, 21, 25, 29, 29, 23, 18, 13, 24, 29, 31, 30, 25, 19, 14, 15, + 18, 21, 26, 25, 22, 18, 14, 17, 20, 24, 25, 22, 19, 13, 16, 19, 23, 24, 23, + 19, 12, 15, 19, 23, 25, 23, 20, 13, 15, 19, 22, 26, 24, 21, 11, 14, 17, 21, + 25, 24, 20, 16, 15, 16, 20, 23, 23, 21, 13, 16, 18, 22, 21, 19, 15, 12, 15, + 17, 21, 21, 17, 14, 11, 14, 17, 20, 19, 18, 15, 10, 13, 17, 20, 20, 19, 16, + 10, 14, 16, 19, 19, 19, 16, 11, 13, 16, 18, 18, 18, 16, 18, 17, 16, 17, 16, + 17, 16, 11, 14, 15, 15, 16, 14, 10, 10, 12, 13, 13, 14, 13, 9, 9, 11, 13, + 14, 13, 13, 10, 8, 12, 13, 13, 13, 13, 11, 7, 11, 12, 12, 12, 13, 11, 14, + 14, 13, 12, 11, 11, 11, 20, 19, 15, 12, 10, 10, 10, 9, 8, 8, 8, 9, 9, + 3, 8, 7, 7, 7, 7, 7, 2, 6, 6, 6, 7, 6, 6, 2, 5, 6, 6, 6, + 6, 6, 5, 7, 8, 8, 8, 8, 7, 5, 14, 16, 13, 11, 9, 7, 5, 21, 22, + 16, 12, 10, 8, 6, 1, 1, 1, 0, 1, 2, 3, 2, 2, 1, 1, 2, 0, 2, + 2, 3, 3, 4, 3, 3, 3, 2, 6, 6, 6, 6, 6, 5, 7, 12, 11, 10, 10, + 8, 6, 13, 16, 17, 14, 11, 9, 7, 19, 21, 20, 15, 13, 10, 7, 6, 6, 4, + 3, 3, 2, 2, 6, 7, 5, 4, 3, 2, 2, 6, 9, 6, 6, 4, 4, 3, 6, + 10, 10, 9, 8, 7, 7, 9, 13, 16, 14, 13, 10, 8, 14, 19, 22, 19, 14, 11, + 9, 19, 22, 23, 21, 16, 12, 9, 10, 11, 8, 5, 3, 2, 1, 10, 12, 10, 5, + 4, 3, 2, 10, 12, 12, 8, 7, 5, 5, 10, 13, 16, 13, 10, 9, 8, 12, 15, + 20, 19, 15, 12, 9, 16, 20, 24, 24, 17, 13, 10, 20, 24, 25, 25, 19, 14, 11, + 9, 11, 14, 17, 17, 14, 11, 9, 11, 13, 16, 17, 13, 11, 8, 10, 12, 15, 17, + 15, 12, 8, 10, 13, 16, 18, 16, 14, 8, 11, 13, 16, 19, 16, 13, 10, 11, 13, + 15, 18, 17, 13, 16, 15, 14, 15, 17, 17, 13, 8, 10, 12, 14, 13, 11, 7, 8, + 9, 11, 13, 13, 9, 7, 7, 8, 11, 13, 12, 10, 8, 6, 9, 12, 14, 13, 12, + 9, 6, 9, 11, 13, 13, 12, 10, 12, 12, 13, 13, 12, 12, 10, 19, 17, 14, 13, + 11, 11, 10, 7, 9, 8, 8, 9, 7, 4, 6, 8, 8, 7, 7, 6, 4, 5, 8, + 7, 8, 7, 7, 5, 4, 7, 8, 8, 7, 7, 6, 7, 9, 9, 8, 8, 8, 6, + 14, 14, 13, 11, 9, 7, 6, 21, 19, 15, 12, 9, 7, 6, 5, 4, 3, 3, 3, + 4, 2, 3, 3, 3, 3, 2, 2, 0, 3, 2, 2, 3, 2, 2, 2, 7, 3, 4, + 5, 4, 4, 4, 8, 9, 9, 8, 8, 7, 5, 14, 16, 14, 12, 10, 8, 6, 21, + 22, 16, 13, 10, 9, 7, 5, 3, 2, 2, 3, 2, 2, 5, 4, 3, 2, 3, 2, + 0, 5, 5, 4, 4, 4, 4, 3, 5, 8, 8, 8, 8, 8, 6, 9, 14, 14, 13, + 13, 10, 7, 14, 18, 19, 18, 14, 11, 8, 20, 22, 23, 19, 16, 13, 9, 9, 9, + 7, 6, 4, 3, 2, 8, 10, 8, 7, 5, 3, 2, 9, 12, 11, 11, 9, 6, 4, + 9, 14, 16, 16, 13, 10, 8, 12, 18, 22, 20, 18, 14, 9, 16, 22, 28, 26, 20, + 15, 10, 21, 26, 29, 28, 22, 17, 12, 14, 18, 15, 10, 6, 3, 2, 13, 17, 18, + 12, 8, 5, 3, 13, 17, 20, 15, 12, 9, 6, 14, 19, 25, 21, 16, 14, 10, 18, + 23, 28, 26, 21, 17, 12, 21, 27, 32, 32, 25, 19, 14, 26, 30, 32, 33, 26, 21, + 15, 16, 19, 23, 26, 26, 25, 23, 15, 18, 21, 25, 26, 23, 21, 14, 17, 20, 23, + 24, 22, 19, 13, 15, 17, 20, 22, 20, 18, 12, 14, 15, 18, 21, 20, 18, 11, 12, + 14, 17, 20, 20, 17, 10, 11, 13, 16, 19, 20, 18, 13, 17, 21, 24, 24, 23, 18, + 13, 15, 19, 22, 24, 21, 17, 12, 14, 17, 20, 21, 18, 15, 10, 13, 15, 17, 17, + 17, 15, 10, 12, 14, 15, 15, 17, 14, 8, 11, 13, 15, 15, 15, 14, 11, 11, 12, + 14, 14, 15, 14, 12, 14, 16, 18, 19, 19, 15, 11, 13, 15, 16, 17, 17, 13, 10, + 13, 13, 15, 14, 15, 12, 9, 12, 12, 12, 13, 13, 12, 7, 10, 11, 11, 11, 12, + 12, 8, 9, 9, 10, 11, 11, 12, 12, 12, 10, 9, 10, 11, 12, 10, 10, 10, 11, + 13, 13, 6, 8, 9, 9, 10, 10, 10, 5, 7, 7, 8, 8, 9, 9, 5, 4, 6, + 6, 7, 7, 7, 6, 5, 5, 6, 6, 6, 7, 5, 8, 8, 7, 6, 5, 5, 4, + 12, 12, 8, 6, 5, 4, 2, 2, 2, 2, 3, 3, 4, 6, 0, 1, 1, 2, 1, + 2, 5, 0, 2, 2, 1, 1, 1, 5, 0, 2, 2, 1, 2, 1, 3, 2, 4, 4, + 3, 4, 2, 2, 5, 7, 7, 6, 5, 3, 2, 9, 10, 10, 7, 6, 4, 2, 4, + 5, 4, 5, 3, 2, 4, 4, 6, 6, 6, 3, 1, 3, 4, 7, 7, 6, 4, 1, + 2, 4, 7, 8, 7, 5, 3, 2, 4, 8, 10, 9, 7, 4, 2, 6, 10, 13, 12, + 9, 6, 2, 9, 12, 14, 13, 10, 7, 3, 9, 12, 11, 8, 5, 2, 2, 9, 12, + 13, 8, 5, 2, 1, 9, 13, 14, 9, 6, 3, 1, 9, 12, 15, 10, 7, 5, 2, + 9, 12, 15, 13, 10, 7, 3, 10, 14, 17, 16, 11, 8, 5, 12, 15, 17, 17, 13, + 9, 6, 18, 19, 22, 24, 24, 22, 19, 17, 20, 21, 24, 24, 22, 19, 15, 18, 20, + 22, 24, 22, 20, 15, 18, 20, 21, 23, 22, 19, 14, 17, 19, 21, 24, 22, 21, 13, + 16, 19, 21, 23, 22, 20, 12, 14, 17, 20, 22, 22, 20, 15, 18, 20, 23, 22, 20, + 17, 14, 17, 20, 22, 20, 19, 17, 13, 17, 19, 21, 21, 18, 18, 12, 16, 18, 20, + 19, 18, 17, 12, 15, 18, 19, 19, 20, 18, 11, 13, 17, 19, 18, 19, 17, 14, 13, + 15, 17, 18, 18, 18, 13, 17, 17, 18, 18, 17, 14, 12, 15, 16, 16, 17, 16, 13, + 11, 14, 16, 16, 16, 17, 14, 10, 13, 15, 15, 16, 16, 14, 9, 12, 14, 14, 15, + 15, 14, 9, 11, 12, 13, 13, 14, 14, 16, 16, 12, 12, 13, 13, 13, 11, 11, 12, + 12, 12, 13, 4, 10, 10, 11, 11, 11, 11, 5, 9, 9, 9, 9, 10, 10, 5, 5, + 8, 8, 8, 8, 9, 7, 6, 7, 7, 7, 8, 8, 5, 9, 10, 9, 8, 6, 6, + 5, 16, 18, 13, 9, 6, 5, 3, 3, 3, 4, 4, 4, 3, 4, 1, 2, 2, 2, + 2, 2, 5, 1, 0, 1, 1, 1, 2, 5, 1, 3, 3, 3, 4, 2, 5, 3, 8, + 8, 8, 8, 6, 3, 8, 13, 14, 12, 10, 8, 3, 15, 17, 16, 13, 11, 9, 4, + 6, 8, 8, 8, 4, 2, 4, 6, 10, 9, 9, 6, 1, 4, 6, 11, 11, 10, 7, + 2, 3, 6, 12, 12, 12, 10, 6, 4, 8, 13, 15, 14, 12, 9, 4, 11, 15, 18, + 16, 13, 11, 6, 15, 17, 19, 17, 14, 12, 8, 13, 16, 15, 12, 8, 2, 2, 13, + 16, 16, 12, 9, 4, 2, 13, 16, 18, 13, 10, 6, 1, 13, 16, 19, 14, 12, 10, + 6, 13, 16, 20, 17, 14, 12, 8, 15, 17, 21, 20, 15, 13, 10, 17, 19, 22, 21, + 17, 14, 11, 18, 21, 24, 26, 26, 24, 21, 17, 20, 23, 26, 26, 24, 21, 15, 19, + 22, 26, 25, 23, 22, 14, 17, 21, 24, 26, 24, 22, 14, 17, 21, 23, 26, 25, 22, + 13, 16, 20, 23, 26, 25, 21, 13, 15, 18, 21, 24, 24, 22, 15, 19, 21, 24, 23, + 21, 17, 15, 18, 21, 24, 23, 20, 17, 13, 17, 20, 22, 22, 20, 17, 12, 16, 19, + 22, 22, 20, 18, 12, 15, 18, 21, 21, 22, 18, 11, 14, 17, 20, 21, 20, 18, 15, + 14, 16, 19, 19, 19, 18, 13, 17, 18, 18, 19, 17, 13, 12, 15, 17, 17, 17, 17, + 13, 11, 14, 16, 16, 16, 16, 13, 10, 13, 15, 15, 16, 16, 13, 10, 13, 15, 15, + 15, 15, 14, 10, 11, 13, 13, 14, 14, 13, 16, 16, 12, 12, 13, 13, 13, 11, 11, + 11, 11, 12, 12, 4, 10, 10, 10, 11, 10, 11, 4, 8, 9, 9, 9, 9, 9, 5, + 6, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 4, 10, 11, 10, 8, 7, + 6, 4, 17, 18, 13, 9, 7, 5, 3, 3, 3, 3, 4, 4, 3, 4, 2, 2, 2, + 2, 2, 3, 4, 2, 1, 0, 0, 0, 2, 4, 2, 4, 3, 3, 4, 3, 4, 4, + 8, 8, 8, 8, 6, 3, 9, 13, 14, 12, 10, 7, 4, 15, 18, 18, 14, 12, 9, + 5, 5, 7, 7, 7, 3, 2, 3, 5, 9, 9, 8, 5, 1, 3, 5, 11, 11, 10, + 6, 2, 3, 6, 12, 14, 14, 10, 6, 4, 8, 14, 19, 18, 15, 9, 5, 11, 17, + 24, 23, 18, 11, 6, 16, 21, 25, 26, 20, 13, 7, 13, 19, 18, 12, 7, 2, 2, + 13, 19, 20, 14, 9, 3, 2, 13, 19, 23, 16, 11, 6, 2, 13, 20, 25, 19, 15, + 10, 6, 15, 21, 26, 25, 19, 14, 8, 17, 24, 29, 28, 21, 16, 10, 20, 26, 30, + 31, 24, 17, 11, 18, 22, 26, 29, 29, 26, 23, 17, 20, 25, 28, 29, 26, 22, 15, + 19, 23, 26, 28, 24, 22, 14, 17, 20, 24, 27, 25, 22, 14, 17, 20, 23, 27, 25, + 22, 13, 16, 20, 23, 26, 25, 22, 13, 14, 18, 22, 25, 25, 22, 15, 19, 23, 26, + 25, 22, 19, 14, 18, 22, 25, 24, 21, 18, 13, 16, 20, 23, 22, 20, 17, 13, 16, + 19, 21, 22, 21, 18, 12, 15, 18, 21, 21, 21, 18, 11, 14, 17, 20, 20, 21, 18, + 15, 14, 17, 19, 19, 19, 18, 13, 17, 19, 19, 21, 18, 14, 12, 15, 17, 19, 19, + 17, 13, 11, 14, 16, 16, 16, 16, 12, 10, 14, 15, 15, 15, 15, 12, 10, 13, 14, + 14, 14, 15, 13, 10, 11, 13, 13, 13, 13, 13, 17, 16, 12, 12, 12, 12, 12, 11, + 11, 12, 12, 13, 13, 5, 11, 10, 10, 11, 11, 11, 4, 9, 9, 9, 9, 8, 8, + 4, 5, 9, 8, 8, 8, 8, 6, 7, 7, 7, 7, 7, 7, 3, 10, 11, 10, 9, + 6, 6, 3, 17, 18, 13, 9, 7, 5, 3, 3, 3, 4, 4, 5, 4, 5, 1, 2, + 2, 3, 3, 4, 4, 1, 1, 0, 0, 0, 2, 3, 1, 4, 4, 3, 4, 3, 3, + 4, 8, 8, 8, 8, 5, 3, 10, 13, 14, 12, 10, 7, 4, 15, 18, 17, 14, 12, + 9, 4, 6, 7, 7, 7, 4, 3, 4, 6, 10, 8, 9, 6, 2, 3, 6, 11, 10, + 10, 6, 2, 2, 6, 12, 14, 13, 10, 6, 4, 9, 15, 18, 18, 14, 9, 4, 12, + 17, 24, 22, 17, 11, 6, 16, 21, 24, 25, 19, 13, 7, 14, 19, 18, 12, 7, 3, + 4, 13, 19, 20, 14, 8, 3, 2, 13, 19, 22, 15, 10, 6, 2, 14, 20, 25, 19, + 14, 10, 5, 15, 21, 27, 24, 19, 13, 8, 17, 24, 29, 29, 22, 15, 9, 21, 27, + 30, 30, 23, 17, 11, 18, 22, 26, 29, 30, 27, 23, 17, 21, 24, 28, 30, 26, 21, + 15, 19, 23, 26, 27, 24, 21, 14, 17, 21, 24, 27, 25, 22, 14, 17, 20, 23, 27, + 25, 22, 14, 16, 19, 23, 26, 25, 21, 13, 15, 18, 21, 25, 25, 22, 15, 19, 23, + 26, 26, 23, 20, 14, 18, 22, 25, 25, 22, 18, 13, 16, 20, 23, 23, 20, 17, 12, + 15, 19, 21, 22, 21, 17, 13, 15, 18, 21, 21, 20, 17, 11, 13, 17, 19, 20, 20, + 17, 15, 15, 15, 18, 18, 18, 18, 13, 16, 18, 19, 21, 19, 15, 12, 15, 18, 18, + 19, 17, 13, 12, 14, 16, 16, 15, 16, 11, 11, 14, 14, 15, 15, 15, 12, 10, 13, + 14, 14, 14, 14, 12, 10, 12, 13, 13, 13, 13, 12, 17, 16, 13, 12, 12, 12, 11, + 12, 11, 11, 12, 13, 13, 6, 11, 9, 10, 11, 11, 11, 4, 9, 9, 9, 8, 8, + 8, 4, 5, 9, 8, 8, 8, 8, 6, 7, 7, 7, 7, 7, 7, 3, 11, 12, 10, + 8, 6, 5, 3, 17, 18, 13, 10, 7, 5, 3, 4, 3, 4, 4, 5, 5, 5, 1, + 1, 2, 3, 3, 3, 4, 1, 1, 0, 0, 0, 1, 2, 1, 4, 4, 3, 4, 3, + 3, 5, 9, 8, 8, 8, 6, 3, 10, 14, 14, 12, 10, 7, 4, 15, 18, 17, 13, + 12, 9, 5, 6, 7, 7, 7, 4, 4, 5, 6, 9, 8, 8, 5, 2, 3, 6, 11, + 10, 9, 6, 2, 2, 6, 13, 13, 12, 10, 6, 4, 9, 15, 18, 17, 14, 9, 5, + 12, 18, 23, 21, 16, 11, 6, 16, 20, 24, 23, 18, 13, 7, 13, 15, 13, 10, 7, + 3, 4, 13, 16, 15, 11, 8, 3, 1, 12, 15, 17, 11, 9, 6, 2, 12, 17, 20, + 16, 13, 9, 6, 15, 19, 23, 21, 18, 13, 7, 18, 23, 26, 26, 20, 15, 9, 21, + 25, 28, 28, 22, 17, 11, 17, 20, 25, 28, 28, 25, 21, 16, 19, 23, 28, 28, 24, + 21, 14, 18, 21, 25, 27, 23, 20, 13, 16, 19, 22, 26, 23, 20, 13, 16, 19, 22, + 26, 24, 21, 12, 15, 18, 22, 25, 24, 21, 13, 14, 17, 21, 23, 24, 21, 14, 18, + 21, 25, 24, 22, 18, 13, 17, 20, 24, 23, 20, 16, 12, 16, 19, 22, 21, 19, 15, + 11, 14, 17, 20, 20, 19, 16, 12, 14, 17, 20, 19, 19, 16, 9, 12, 15, 18, 18, + 19, 16, 16, 14, 14, 17, 17, 17, 16, 12, 15, 17, 18, 19, 17, 13, 11, 14, 16, + 17, 17, 16, 11, 11, 13, 15, 14, 15, 14, 10, 10, 13, 13, 13, 13, 13, 11, 9, + 12, 12, 12, 12, 12, 11, 11, 12, 11, 11, 12, 11, 11, 17, 16, 12, 10, 10, 10, + 10, 10, 10, 10, 11, 12, 12, 6, 9, 8, 9, 9, 10, 10, 4, 8, 7, 7, 7, + 7, 7, 3, 5, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 6, 5, 2, 11, 12, + 10, 9, 7, 5, 3, 17, 17, 13, 10, 7, 5, 3, 2, 1, 2, 3, 4, 5, 5, + 1, 0, 1, 2, 2, 3, 3, 1, 2, 2, 2, 1, 0, 2, 1, 5, 4, 4, 4, + 3, 3, 5, 9, 8, 8, 8, 6, 3, 11, 14, 14, 11, 9, 7, 4, 16, 17, 17, + 13, 10, 8, 5, 5, 5, 4, 3, 3, 3, 5, 5, 7, 5, 4, 3, 2, 2, 5, + 7, 5, 4, 2, 2, 1, 5, 8, 8, 7, 6, 5, 4, 8, 11, 13, 11, 10, 8, + 5, 12, 15, 18, 16, 11, 8, 6, 16, 18, 19, 18, 13, 9, 7, 8, 9, 7, 5, + 3, 3, 3, 8, 9, 8, 6, 3, 2, 1, 8, 9, 10, 6, 4, 3, 2, 7, 10, + 13, 10, 8, 6, 6, 10, 13, 17, 16, 12, 9, 7, 13, 17, 20, 19, 14, 10, 8, + 17, 20, 21, 21, 16, 11, 8, 13, 16, 19, 22, 22, 20, 16, 12, 15, 18, 22, 22, + 19, 15, 11, 15, 18, 20, 21, 18, 15, 10, 12, 15, 18, 21, 19, 16, 9, 12, 15, + 18, 21, 20, 16, 8, 11, 14, 17, 21, 19, 16, 11, 11, 13, 16, 20, 19, 16, 11, + 14, 17, 20, 18, 17, 14, 10, 13, 16, 19, 18, 15, 12, 8, 12, 15, 17, 16, 14, + 12, 7, 10, 13, 16, 16, 14, 12, 7, 10, 12, 15, 15, 15, 12, 9, 10, 11, 14, + 14, 14, 12, 14, 12, 11, 13, 13, 13, 12, 8, 12, 13, 14, 15, 13, 10, 7, 10, + 13, 13, 13, 13, 8, 6, 9, 11, 11, 11, 10, 7, 5, 9, 9, 9, 9, 9, 7, + 6, 8, 9, 9, 9, 8, 7, 12, 11, 9, 8, 7, 7, 7, 15, 13, 10, 8, 7, + 6, 6, 6, 6, 7, 8, 9, 9, 5, 5, 4, 5, 6, 6, 7, 3, 3, 3, 4, + 4, 3, 3, 2, 2, 3, 3, 3, 2, 2, 2, 6, 7, 6, 5, 5, 4, 2, 12, + 12, 9, 8, 6, 5, 3, 15, 16, 11, 9, 7, 5, 4, 4, 3, 3, 2, 3, 4, + 5, 4, 4, 3, 3, 3, 3, 3, 4, 5, 4, 3, 2, 2, 0, 4, 8, 5, 5, + 4, 4, 3, 8, 12, 9, 9, 8, 6, 4, 11, 14, 14, 12, 10, 7, 5, 15, 17, + 17, 14, 12, 9, 5, 8, 7, 6, 5, 4, 4, 4, 7, 9, 6, 6, 4, 3, 2, + 8, 11, 8, 7, 5, 3, 2, 8, 11, 12, 11, 9, 6, 5, 10, 14, 17, 16, 13, + 9, 5, 13, 18, 22, 20, 15, 10, 7, 16, 20, 23, 22, 17, 12, 8, 12, 15, 13, + 9, 5, 4, 3, 11, 15, 16, 11, 6, 3, 2, 12, 15, 18, 12, 8, 5, 3, 12, + 16, 21, 16, 12, 9, 6, 14, 19, 24, 21, 16, 12, 8, 16, 21, 26, 26, 19, 13, + 9, 20, 24, 27, 27, 22, 15, 10, 15, 19, 23, 26, 26, 25, 22, 14, 18, 22, 25, + 25, 23, 21, 13, 17, 20, 23, 24, 21, 19, 13, 15, 18, 20, 22, 20, 18, 12, 14, + 16, 18, 21, 20, 18, 10, 12, 15, 17, 20, 20, 18, 10, 11, 13, 15, 19, 19, 18, + 14, 17, 20, 23, 24, 23, 19, 13, 16, 19, 22, 24, 21, 17, 12, 14, 17, 20, 20, + 19, 15, 11, 13, 16, 17, 17, 17, 15, 10, 12, 14, 16, 16, 17, 14, 8, 11, 12, + 14, 14, 15, 15, 11, 11, 12, 14, 14, 14, 14, 12, 14, 16, 17, 19, 19, 15, 11, + 13, 15, 16, 17, 17, 12, 10, 13, 14, 14, 14, 15, 12, 9, 12, 12, 12, 13, 13, + 12, 7, 10, 12, 12, 12, 12, 12, 8, 9, 9, 10, 11, 12, 12, 12, 13, 10, 9, + 10, 11, 11, 10, 10, 10, 11, 13, 14, 6, 8, 9, 9, 10, 10, 11, 5, 7, 8, + 8, 8, 9, 9, 5, 4, 6, 6, 7, 7, 7, 5, 5, 5, 6, 6, 6, 7, 5, + 8, 8, 7, 6, 5, 5, 4, 12, 12, 8, 6, 5, 4, 2, 2, 2, 2, 2, 3, + 4, 6, 0, 1, 1, 2, 1, 2, 5, 0, 1, 1, 1, 1, 1, 5, 0, 2, 2, + 1, 2, 1, 4, 2, 4, 4, 3, 4, 2, 2, 5, 7, 7, 6, 5, 3, 2, 9, + 10, 10, 7, 6, 4, 2, 4, 5, 4, 5, 3, 2, 5, 4, 6, 6, 5, 3, 1, + 3, 4, 7, 7, 6, 4, 1, 2, 4, 7, 8, 7, 5, 3, 2, 4, 8, 11, 9, + 7, 4, 2, 6, 10, 14, 12, 9, 6, 2, 9, 12, 14, 13, 10, 7, 3, 9, 12, + 11, 7, 5, 2, 2, 9, 12, 13, 8, 5, 2, 1, 9, 12, 14, 9, 6, 3, 1, + 9, 12, 15, 10, 7, 5, 2, 8, 12, 15, 13, 9, 7, 4, 10, 14, 17, 16, 11, + 8, 5, 12, 15, 17, 17, 13, 9, 6, 21, 24, 26, 29, 28, 27, 25, 21, 23, 26, + 28, 29, 26, 23, 19, 22, 25, 26, 27, 25, 23, 18, 21, 23, 26, 27, 24, 21, 16, + 19, 21, 23, 25, 23, 22, 15, 19, 21, 22, 24, 23, 21, 12, 15, 19, 22, 24, 23, + 22, 20, 23, 25, 27, 26, 24, 22, 18, 21, 24, 26, 26, 23, 21, 17, 20, 23, 25, + 23, 23, 20, 16, 18, 21, 23, 22, 21, 19, 14, 17, 19, 22, 21, 21, 19, 12, 15, + 18, 20, 21, 20, 19, 12, 12, 17, 19, 20, 19, 20, 17, 21, 22, 22, 22, 21, 18, + 15, 20, 21, 22, 21, 20, 17, 14, 18, 20, 20, 20, 20, 17, 12, 16, 17, 17, 18, + 18, 16, 11, 14, 16, 16, 17, 17, 16, 8, 12, 14, 14, 16, 16, 16, 13, 13, 11, + 13, 15, 15, 15, 14, 15, 16, 16, 17, 17, 8, 13, 13, 14, 15, 15, 15, 8, 10, + 12, 13, 13, 13, 14, 8, 7, 10, 10, 10, 10, 11, 9, 7, 8, 9, 9, 9, 10, + 6, 8, 8, 7, 7, 7, 8, 6, 13, 14, 10, 7, 6, 6, 5, 6, 6, 7, 8, + 8, 6, 8, 2, 5, 6, 6, 6, 6, 8, 2, 3, 4, 4, 4, 5, 9, 2, 0, + 0, 0, 0, 2, 6, 3, 5, 4, 5, 5, 3, 5, 5, 9, 9, 8, 6, 4, 3, + 11, 12, 11, 8, 6, 5, 2, 4, 6, 6, 6, 3, 5, 7, 4, 7, 7, 7, 4, + 5, 6, 4, 8, 8, 8, 6, 3, 6, 4, 8, 8, 7, 5, 3, 3, 4, 8, 9, + 8, 7, 5, 2, 7, 9, 12, 11, 8, 6, 3, 11, 12, 13, 12, 9, 6, 4, 9, + 12, 11, 9, 6, 3, 6, 9, 12, 13, 9, 7, 3, 5, 9, 13, 15, 10, 7, 4, + 3, 10, 12, 15, 9, 7, 6, 3, 8, 11, 14, 12, 8, 6, 5, 9, 13, 15, 14, + 10, 7, 6, 11, 14, 16, 16, 12, 8, 6, 22, 26, 28, 31, 31, 29, 26, 21, 24, + 28, 31, 31, 28, 25, 19, 23, 26, 29, 29, 27, 23, 18, 20, 24, 27, 29, 26, 22, + 15, 18, 21, 24, 27, 25, 22, 14, 16, 20, 23, 27, 25, 22, 12, 15, 18, 22, 25, + 25, 22, 19, 23, 26, 30, 27, 26, 22, 18, 21, 25, 28, 28, 24, 22, 16, 20, 24, + 27, 25, 24, 20, 15, 18, 21, 23, 23, 21, 19, 13, 16, 19, 22, 22, 21, 19, 11, + 15, 17, 21, 21, 21, 19, 12, 12, 16, 19, 20, 20, 19, 16, 20, 22, 23, 24, 22, + 18, 15, 18, 21, 22, 22, 21, 17, 14, 17, 20, 20, 20, 20, 15, 13, 15, 16, 16, + 17, 17, 14, 10, 13, 15, 15, 15, 16, 14, 8, 12, 13, 14, 14, 14, 14, 13, 13, + 12, 12, 13, 13, 13, 13, 14, 15, 16, 17, 17, 9, 12, 13, 14, 15, 15, 15, 8, + 9, 11, 12, 13, 12, 13, 8, 6, 9, 9, 9, 9, 9, 7, 6, 8, 8, 8, 8, + 8, 4, 8, 8, 7, 6, 6, 7, 4, 13, 15, 10, 7, 5, 5, 3, 5, 6, 7, + 8, 8, 7, 8, 2, 5, 5, 6, 7, 6, 8, 2, 3, 3, 4, 4, 4, 5, 2, + 0, 0, 0, 0, 2, 4, 3, 5, 5, 4, 5, 3, 3, 6, 10, 11, 9, 7, 4, + 2, 12, 15, 14, 11, 9, 6, 2, 4, 6, 7, 7, 4, 6, 7, 4, 8, 8, 9, + 5, 5, 6, 4, 10, 10, 10, 6, 2, 4, 4, 10, 11, 11, 7, 3, 2, 5, 11, + 15, 15, 12, 6, 2, 8, 14, 20, 19, 14, 8, 3, 13, 17, 21, 21, 16, 10, 4, + 12, 19, 18, 12, 7, 5, 6, 13, 19, 21, 14, 8, 3, 5, 13, 19, 23, 15, 10, + 4, 2, 13, 18, 23, 17, 11, 7, 3, 12, 18, 23, 21, 16, 10, 4, 14, 20, 25, + 24, 19, 12, 6, 17, 23, 25, 25, 20, 14, 8, 22, 26, 29, 32, 33, 30, 26, 20, + 24, 28, 33, 33, 29, 26, 19, 23, 27, 30, 31, 28, 23, 18, 20, 24, 27, 30, 26, + 23, 15, 18, 21, 24, 28, 26, 23, 14, 17, 19, 23, 27, 26, 22, 12, 15, 18, 22, + 26, 25, 22, 19, 23, 27, 29, 29, 27, 23, 18, 21, 26, 29, 29, 25, 22, 16, 20, + 24, 27, 26, 24, 20, 15, 18, 21, 24, 23, 22, 19, 13, 16, 19, 21, 22, 21, 19, + 12, 15, 18, 20, 21, 21, 18, 12, 12, 17, 19, 20, 19, 19, 16, 20, 22, 23, 24, + 22, 19, 15, 18, 20, 22, 23, 22, 17, 13, 17, 19, 19, 20, 19, 15, 13, 15, 15, + 16, 16, 17, 13, 10, 13, 15, 15, 14, 15, 13, 8, 12, 13, 14, 14, 13, 13, 13, + 13, 12, 12, 13, 13, 12, 14, 14, 15, 16, 17, 18, 10, 13, 13, 14, 15, 15, 15, + 8, 10, 11, 12, 12, 12, 12, 7, 6, 10, 9, 9, 9, 9, 7, 6, 8, 8, 8, + 7, 7, 4, 8, 8, 7, 6, 6, 6, 3, 13, 14, 9, 6, 5, 5, 2, 6, 6, + 7, 8, 9, 8, 9, 1, 5, 6, 6, 7, 6, 8, 1, 3, 3, 3, 4, 4, 5, + 1, 0, 0, 0, 0, 2, 3, 3, 5, 4, 4, 4, 2, 2, 6, 10, 11, 9, 6, + 3, 2, 12, 15, 14, 10, 9, 5, 2, 4, 6, 7, 7, 5, 7, 8, 4, 8, 8, + 8, 5, 5, 6, 4, 10, 10, 9, 5, 2, 3, 4, 9, 11, 10, 6, 2, 2, 5, + 11, 15, 14, 11, 5, 2, 8, 14, 20, 18, 13, 7, 2, 12, 17, 21, 21, 15, 10, + 4, 13, 19, 17, 12, 7, 5, 7, 13, 18, 20, 13, 8, 3, 4, 13, 19, 21, 14, + 9, 4, 1, 13, 17, 22, 16, 10, 6, 2, 12, 17, 24, 21, 15, 9, 4, 14, 20, + 25, 25, 18, 11, 6, 17, 22, 26, 26, 20, 14, 8, 22, 26, 30, 34, 33, 30, 28, + 21, 24, 29, 33, 33, 30, 26, 19, 23, 27, 31, 32, 28, 24, 18, 20, 24, 28, 30, + 27, 23, 15, 18, 21, 25, 29, 26, 23, 14, 17, 20, 23, 27, 27, 23, 12, 15, 19, + 23, 26, 26, 22, 19, 23, 28, 30, 29, 26, 24, 18, 21, 25, 29, 30, 26, 22, 17, + 20, 24, 27, 27, 23, 20, 15, 18, 21, 23, 24, 22, 18, 14, 16, 19, 22, 22, 22, + 18, 12, 15, 17, 20, 20, 21, 19, 12, 13, 17, 20, 19, 20, 18, 17, 20, 22, 23, + 24, 23, 18, 15, 19, 21, 22, 23, 21, 17, 15, 17, 20, 19, 20, 19, 15, 13, 16, + 16, 17, 17, 16, 13, 10, 14, 15, 15, 15, 15, 13, 9, 12, 14, 14, 14, 14, 13, + 12, 12, 12, 12, 13, 13, 12, 15, 15, 15, 16, 17, 18, 10, 13, 13, 14, 15, 15, + 15, 8, 10, 12, 12, 12, 12, 12, 7, 6, 10, 9, 9, 9, 9, 7, 6, 8, 8, + 8, 7, 8, 4, 8, 8, 7, 7, 6, 6, 3, 12, 12, 9, 6, 5, 5, 2, 6, + 6, 7, 8, 9, 8, 10, 2, 5, 6, 7, 7, 6, 8, 1, 4, 4, 4, 4, 4, + 4, 1, 0, 0, 0, 0, 1, 3, 3, 5, 4, 4, 4, 2, 2, 6, 10, 10, 8, + 6, 3, 2, 11, 13, 13, 10, 8, 5, 1, 5, 7, 7, 7, 5, 7, 8, 5, 9, + 8, 8, 5, 5, 6, 5, 10, 9, 8, 5, 2, 3, 5, 10, 10, 9, 6, 2, 2, + 5, 11, 14, 13, 10, 5, 1, 8, 14, 19, 17, 12, 7, 2, 12, 16, 20, 20, 14, + 9, 3, 12, 15, 13, 10, 6, 6, 7, 12, 15, 15, 11, 7, 4, 4, 12, 15, 16, + 11, 8, 3, 2, 12, 15, 17, 13, 10, 6, 2, 11, 16, 19, 17, 14, 9, 4, 14, + 19, 23, 23, 16, 11, 5, 16, 21, 24, 23, 19, 13, 7, 21, 24, 28, 32, 33, 29, + 25, 19, 23, 27, 31, 32, 28, 25, 18, 21, 25, 29, 30, 27, 23, 17, 20, 22, 25, + 28, 25, 21, 14, 17, 20, 23, 27, 24, 21, 13, 16, 18, 22, 26, 25, 21, 11, 14, + 17, 21, 24, 24, 21, 17, 22, 25, 29, 28, 26, 23, 17, 20, 24, 28, 28, 24, 20, + 15, 19, 22, 26, 26, 23, 18, 14, 16, 20, 22, 22, 21, 17, 12, 15, 18, 20, 20, + 20, 17, 10, 13, 16, 19, 19, 19, 17, 10, 12, 15, 18, 18, 18, 17, 16, 19, 21, + 21, 24, 21, 17, 14, 17, 20, 21, 21, 20, 15, 13, 16, 18, 18, 18, 18, 14, 12, + 14, 15, 15, 15, 15, 11, 10, 13, 14, 13, 13, 13, 12, 8, 11, 12, 12, 12, 12, + 11, 10, 10, 10, 11, 11, 11, 11, 13, 13, 14, 15, 16, 17, 9, 11, 12, 13, 14, + 14, 14, 7, 9, 11, 10, 11, 10, 10, 6, 5, 9, 8, 7, 7, 7, 6, 5, 6, + 6, 6, 6, 6, 3, 8, 7, 6, 5, 4, 5, 3, 10, 10, 7, 5, 4, 3, 2, + 5, 5, 6, 7, 8, 8, 9, 1, 4, 5, 5, 6, 6, 7, 1, 2, 3, 3, 3, + 3, 4, 1, 2, 2, 2, 1, 0, 2, 2, 6, 5, 4, 4, 2, 2, 6, 9, 9, + 7, 5, 3, 1, 9, 11, 10, 7, 6, 4, 2, 5, 4, 4, 4, 5, 7, 8, 5, + 6, 4, 4, 4, 4, 6, 5, 8, 5, 4, 2, 2, 3, 5, 7, 7, 4, 3, 2, + 1, 5, 8, 10, 8, 6, 4, 2, 8, 11, 13, 10, 7, 5, 3, 10, 12, 13, 12, + 8, 6, 3, 9, 11, 8, 5, 5, 6, 6, 9, 11, 9, 5, 4, 4, 4, 9, 11, + 11, 6, 4, 2, 1, 8, 11, 11, 7, 5, 3, 2, 8, 10, 13, 11, 8, 5, 4, + 10, 13, 15, 14, 9, 7, 4, 11, 14, 15, 15, 11, 7, 5, 17, 21, 24, 28, 27, + 25, 22, 16, 20, 24, 27, 27, 23, 20, 14, 18, 21, 24, 26, 23, 18, 13, 16, 19, + 22, 25, 20, 17, 10, 13, 15, 19, 22, 20, 17, 9, 11, 14, 18, 22, 21, 17, 7, + 10, 14, 16, 20, 20, 17, 14, 18, 21, 25, 24, 22, 18, 13, 17, 21, 24, 23, 20, + 16, 12, 15, 20, 21, 21, 19, 14, 11, 13, 16, 19, 18, 17, 13, 8, 11, 13, 16, + 16, 16, 13, 7, 9, 12, 15, 15, 15, 12, 6, 8, 12, 14, 13, 14, 13, 12, 16, + 17, 18, 19, 18, 14, 10, 14, 16, 17, 17, 16, 12, 9, 13, 15, 14, 14, 14, 10, + 9, 11, 11, 11, 11, 11, 8, 5, 8, 9, 9, 9, 9, 8, 5, 7, 8, 8, 8, + 8, 8, 6, 6, 7, 6, 7, 7, 6, 10, 10, 10, 11, 12, 13, 9, 8, 8, 9, + 10, 10, 10, 6, 6, 7, 7, 7, 7, 7, 4, 3, 4, 4, 3, 4, 4, 3, 3, + 3, 2, 2, 2, 2, 2, 5, 5, 3, 3, 2, 1, 0, 6, 7, 4, 3, 2, 2, + 1, 2, 3, 4, 5, 6, 8, 8, 4, 3, 4, 5, 5, 5, 6, 4, 5, 4, 3, + 3, 3, 3, 4, 6, 4, 3, 3, 2, 0, 4, 6, 5, 4, 4, 2, 1, 6, 7, + 8, 7, 5, 3, 2, 7, 9, 11, 8, 7, 5, 2, 7, 6, 5, 5, 5, 7, 7, + 7, 8, 6, 6, 4, 4, 5, 7, 8, 7, 7, 4, 2, 2, 7, 8, 8, 8, 5, + 3, 2, 6, 9, 12, 11, 8, 5, 2, 7, 11, 16, 15, 10, 6, 3, 9, 13, 17, + 17, 12, 7, 3, 10, 14, 13, 8, 5, 6, 6, 10, 14, 15, 10, 6, 3, 3, 10, + 14, 17, 10, 6, 3, 2, 10, 13, 17, 12, 8, 5, 2, 10, 14, 19, 16, 11, 8, + 4, 12, 16, 21, 20, 14, 9, 5, 14, 18, 22, 22, 16, 11, 6, 19, 22, 24, 28, + 28, 25, 22, 18, 21, 23, 26, 28, 25, 22, 17, 20, 22, 24, 26, 23, 20, 16, 18, + 20, 22, 24, 21, 17, 13, 15, 17, 18, 21, 19, 16, 11, 12, 14, 16, 19, 18, 16, + 8, 10, 12, 15, 17, 18, 16, 17, 20, 23, 25, 25, 23, 20, 17, 19, 22, 24, 24, + 22, 19, 15, 18, 21, 22, 22, 20, 18, 14, 16, 18, 19, 19, 18, 14, 10, 13, 14, + 15, 15, 15, 14, 8, 10, 12, 14, 14, 15, 14, 9, 9, 11, 12, 13, 13, 14, 15, + 18, 19, 20, 20, 20, 16, 13, 17, 18, 19, 19, 18, 16, 12, 16, 17, 17, 17, 17, + 15, 11, 14, 15, 15, 15, 15, 13, 7, 10, 12, 11, 12, 12, 13, 5, 8, 9, 10, + 11, 12, 12, 10, 10, 8, 8, 10, 11, 11, 12, 14, 14, 15, 15, 16, 9, 11, 12, + 13, 13, 13, 14, 9, 9, 10, 11, 11, 12, 12, 9, 6, 8, 8, 9, 9, 9, 7, + 4, 5, 5, 5, 6, 6, 6, 5, 6, 5, 4, 4, 5, 5, 10, 10, 6, 4, 3, + 3, 3, 4, 5, 6, 7, 7, 8, 9, 2, 4, 5, 6, 6, 7, 9, 2, 3, 4, + 4, 4, 5, 8, 2, 3, 3, 3, 3, 2, 4, 0, 3, 2, 2, 2, 1, 3, 3, + 4, 5, 4, 3, 1, 1, 7, 7, 7, 5, 4, 3, 1, 5, 6, 6, 7, 5, 6, + 8, 5, 7, 7, 7, 5, 5, 7, 5, 8, 8, 8, 6, 4, 6, 5, 7, 8, 7, + 5, 2, 1, 3, 6, 9, 8, 5, 2, 1, 4, 8, 11, 10, 7, 4, 1, 6, 10, + 12, 11, 8, 5, 2, 10, 13, 13, 9, 6, 5, 6, 10, 14, 14, 10, 7, 5, 6, + 10, 14, 15, 10, 7, 5, 3, 10, 13, 15, 10, 7, 4, 1, 9, 11, 14, 12, 8, + 5, 2, 8, 12, 15, 14, 9, 6, 3, 10, 13, 15, 15, 11, 7, 4, 27, 29, 32, + 35, 35, 32, 30, 25, 29, 31, 34, 34, 31, 28, 25, 27, 31, 32, 33, 30, 26, 22, + 26, 28, 30, 32, 28, 24, 20, 23, 25, 26, 28, 26, 23, 16, 19, 21, 24, 26, 25, + 23, 13, 17, 21, 23, 26, 26, 23, 24, 28, 31, 33, 32, 29, 28, 23, 26, 29, 32, + 32, 29, 26, 21, 25, 28, 30, 30, 28, 25, 20, 23, 26, 28, 26, 25, 21, 16, 20, + 22, 24, 24, 22, 21, 14, 17, 20, 21, 22, 22, 21, 10, 13, 18, 21, 21, 21, 21, + 21, 25, 28, 28, 28, 27, 24, 20, 24, 26, 27, 27, 27, 23, 18, 22, 24, 25, 26, + 25, 22, 16, 20, 21, 22, 22, 23, 18, 11, 16, 17, 18, 18, 18, 18, 7, 13, 16, + 16, 16, 17, 18, 9, 10, 13, 15, 15, 16, 17, 18, 19, 21, 22, 22, 22, 15, 16, + 18, 20, 20, 20, 21, 14, 13, 16, 17, 18, 18, 18, 14, 9, 14, 14, 14, 15, 15, + 12, 7, 10, 10, 10, 10, 11, 8, 7, 7, 7, 8, 9, 9, 6, 9, 9, 6, 6, + 7, 8, 7, 9, 11, 12, 14, 14, 13, 14, 4, 9, 11, 12, 12, 11, 14, 4, 7, + 8, 8, 9, 9, 12, 4, 5, 5, 5, 5, 6, 6, 3, 0, 0, 0, 0, 3, 6, + 3, 3, 3, 2, 1, 1, 6, 6, 6, 5, 2, 2, 2, 5, 4, 5, 6, 6, 9, + 12, 13, 4, 5, 6, 6, 8, 10, 11, 4, 6, 6, 6, 5, 7, 9, 4, 5, 5, + 5, 3, 3, 6, 2, 3, 5, 4, 2, 2, 4, 2, 4, 7, 6, 3, 2, 2, 5, + 5, 8, 7, 4, 2, 1, 7, 10, 9, 7, 7, 10, 12, 7, 10, 11, 8, 6, 8, + 10, 7, 10, 12, 7, 5, 5, 6, 7, 9, 12, 7, 4, 2, 2, 5, 8, 10, 7, + 4, 2, 1, 4, 7, 10, 9, 5, 2, 1, 5, 9, 11, 11, 7, 3, 2, 27, 30, + 34, 37, 37, 34, 32, 25, 29, 32, 36, 36, 34, 29, 23, 27, 32, 34, 35, 32, 28, + 22, 25, 28, 31, 33, 29, 24, 19, 22, 25, 27, 30, 28, 24, 16, 19, 21, 24, 29, + 27, 24, 13, 17, 20, 24, 27, 27, 24, 24, 27, 31, 34, 33, 31, 28, 22, 26, 30, + 33, 33, 31, 27, 20, 24, 29, 31, 30, 29, 25, 19, 22, 25, 28, 28, 27, 22, 16, + 18, 22, 25, 24, 23, 21, 13, 16, 19, 23, 22, 23, 21, 10, 14, 18, 21, 21, 21, + 21, 21, 24, 27, 29, 29, 28, 23, 19, 23, 26, 27, 28, 26, 22, 18, 21, 24, 24, + 25, 24, 20, 16, 20, 20, 20, 21, 22, 17, 10, 16, 17, 17, 17, 18, 16, 7, 13, + 15, 16, 16, 16, 16, 8, 11, 13, 13, 15, 15, 15, 18, 19, 20, 21, 22, 23, 15, + 15, 17, 19, 20, 19, 19, 14, 12, 16, 17, 17, 17, 17, 13, 8, 13, 13, 13, 14, + 14, 11, 6, 9, 9, 9, 9, 9, 8, 6, 7, 7, 8, 8, 8, 5, 8, 9, 5, + 6, 6, 7, 5, 8, 10, 12, 13, 13, 13, 15, 3, 9, 10, 11, 11, 11, 14, 3, + 8, 8, 8, 8, 8, 9, 3, 5, 4, 4, 4, 5, 5, 2, 0, 0, 0, 0, 2, + 4, 3, 5, 6, 5, 3, 1, 4, 7, 10, 10, 6, 5, 2, 4, 4, 5, 6, 7, + 9, 11, 13, 4, 7, 7, 7, 8, 9, 11, 4, 9, 9, 8, 5, 7, 8, 4, 8, + 10, 10, 5, 3, 4, 2, 7, 12, 12, 7, 2, 3, 3, 9, 15, 15, 10, 4, 2, + 8, 12, 16, 16, 12, 6, 1, 11, 17, 16, 11, 7, 10, 12, 11, 18, 19, 13, 7, + 8, 9, 11, 17, 21, 14, 8, 4, 6, 11, 17, 21, 15, 9, 4, 2, 10, 16, 21, + 17, 12, 6, 1, 10, 16, 20, 19, 14, 8, 2, 13, 18, 20, 20, 16, 10, 4, 27, + 30, 33, 37, 36, 35, 31, 25, 29, 32, 36, 37, 35, 30, 23, 27, 31, 35, 35, 32, + 28, 22, 25, 29, 31, 34, 30, 24, 19, 22, 24, 27, 31, 28, 25, 16, 18, 21, 25, + 29, 28, 25, 13, 16, 20, 23, 27, 27, 25, 23, 28, 30, 34, 33, 31, 29, 22, 26, + 30, 33, 34, 29, 26, 20, 24, 28, 30, 31, 28, 23, 19, 22, 24, 27, 28, 26, 20, + 17, 19, 21, 24, 24, 23, 20, 14, 16, 19, 22, 21, 22, 20, 10, 14, 18, 20, 21, + 21, 21, 20, 24, 26, 27, 29, 27, 23, 19, 22, 25, 26, 26, 25, 21, 18, 21, 23, + 24, 24, 24, 19, 15, 20, 20, 20, 21, 20, 16, 10, 16, 16, 17, 16, 16, 16, 7, + 14, 14, 15, 15, 15, 16, 8, 11, 13, 14, 14, 14, 14, 18, 18, 19, 20, 22, 22, + 15, 15, 17, 18, 19, 20, 20, 13, 11, 16, 16, 16, 16, 16, 12, 8, 14, 12, 13, + 13, 13, 11, 6, 10, 9, 9, 9, 9, 7, 6, 7, 7, 7, 7, 8, 4, 8, 8, + 5, 6, 6, 6, 4, 7, 10, 12, 13, 13, 13, 14, 3, 9, 10, 11, 11, 10, 13, + 3, 8, 8, 8, 8, 8, 9, 3, 5, 4, 4, 4, 4, 4, 2, 0, 0, 0, 0, + 2, 3, 3, 5, 6, 4, 2, 1, 3, 6, 9, 9, 6, 4, 2, 2, 4, 5, 6, + 7, 9, 12, 13, 4, 7, 7, 7, 8, 9, 10, 4, 8, 9, 8, 5, 6, 7, 4, + 8, 9, 9, 5, 3, 3, 2, 7, 11, 11, 7, 2, 3, 3, 9, 15, 15, 9, 3, + 2, 7, 12, 17, 17, 11, 5, 1, 11, 17, 16, 11, 7, 10, 11, 11, 17, 19, 12, + 7, 8, 9, 11, 17, 20, 14, 8, 4, 5, 11, 17, 21, 14, 9, 3, 2, 10, 15, + 21, 17, 11, 5, 1, 10, 16, 21, 21, 14, 7, 2, 12, 18, 22, 22, 16, 10, 4, + 26, 30, 33, 39, 37, 35, 31, 25, 29, 32, 37, 37, 33, 30, 23, 26, 32, 34, 36, + 32, 28, 22, 24, 28, 31, 33, 30, 25, 19, 21, 25, 27, 30, 28, 25, 16, 19, 21, + 25, 28, 28, 25, 14, 17, 20, 24, 27, 28, 25, 23, 28, 30, 34, 34, 31, 27, 22, + 26, 29, 32, 33, 30, 26, 21, 24, 28, 30, 31, 28, 24, 20, 22, 25, 28, 29, 26, + 20, 17, 19, 21, 23, 24, 23, 20, 14, 16, 19, 21, 22, 23, 20, 12, 15, 18, 21, + 21, 21, 20, 21, 24, 27, 27, 29, 27, 23, 19, 23, 26, 26, 26, 25, 21, 18, 22, + 23, 23, 24, 24, 19, 15, 20, 20, 20, 20, 20, 15, 10, 16, 17, 17, 17, 16, 15, + 7, 14, 15, 15, 15, 15, 14, 7, 12, 14, 14, 14, 14, 14, 18, 19, 20, 20, 22, + 21, 15, 15, 17, 18, 20, 20, 19, 13, 12, 16, 16, 16, 16, 16, 12, 8, 14, 13, + 12, 13, 13, 11, 6, 10, 9, 9, 9, 9, 7, 6, 8, 8, 7, 7, 8, 4, 7, + 5, 6, 6, 6, 6, 4, 7, 11, 12, 12, 13, 13, 15, 4, 9, 10, 11, 11, 10, + 13, 4, 8, 8, 8, 8, 8, 8, 4, 5, 5, 4, 4, 4, 4, 2, 0, 0, 0, + 0, 2, 3, 3, 4, 4, 3, 2, 2, 3, 4, 5, 5, 4, 4, 2, 2, 4, 5, + 6, 7, 9, 11, 13, 4, 7, 7, 7, 8, 9, 10, 4, 9, 8, 7, 5, 6, 7, + 4, 8, 9, 8, 5, 3, 3, 2, 7, 11, 9, 6, 2, 2, 3, 9, 14, 12, 8, + 3, 2, 4, 9, 14, 14, 10, 5, 1, 10, 14, 12, 9, 8, 10, 11, 10, 14, 14, + 10, 7, 8, 8, 10, 14, 15, 10, 7, 4, 5, 10, 13, 15, 11, 8, 3, 2, 10, + 13, 16, 14, 10, 5, 1, 10, 15, 18, 17, 12, 7, 2, 11, 15, 18, 18, 13, 9, + 3, 24, 27, 31, 35, 36, 33, 29, 22, 26, 30, 34, 36, 32, 28, 21, 25, 28, 32, + 33, 29, 25, 19, 22, 26, 29, 31, 27, 23, 17, 19, 21, 25, 29, 26, 23, 15, 17, + 19, 23, 27, 26, 22, 13, 16, 19, 22, 26, 26, 23, 21, 25, 28, 32, 31, 28, 25, + 20, 22, 27, 31, 31, 28, 23, 19, 22, 26, 28, 28, 25, 21, 17, 20, 23, 25, 25, + 23, 18, 15, 17, 19, 22, 22, 21, 18, 13, 15, 17, 20, 20, 21, 19, 10, 14, 17, + 19, 19, 19, 18, 19, 22, 23, 25, 27, 24, 20, 18, 21, 23, 24, 24, 23, 18, 17, + 19, 21, 22, 21, 20, 16, 15, 17, 18, 18, 18, 18, 13, 10, 14, 15, 14, 14, 15, + 13, 6, 13, 14, 13, 13, 13, 13, 6, 12, 12, 12, 12, 12, 12, 17, 17, 17, 18, + 19, 19, 13, 14, 15, 16, 16, 17, 17, 10, 11, 14, 14, 14, 14, 13, 9, 7, 12, + 11, 10, 10, 10, 9, 5, 8, 8, 7, 7, 7, 5, 5, 6, 6, 6, 6, 6, 3, + 6, 4, 4, 4, 4, 4, 3, 7, 8, 9, 10, 11, 11, 13, 2, 7, 8, 8, 9, + 8, 10, 2, 6, 6, 5, 6, 6, 6, 2, 3, 3, 2, 2, 3, 3, 1, 3, 2, + 2, 2, 0, 2, 2, 5, 5, 4, 2, 1, 2, 3, 6, 7, 4, 3, 2, 2, 3, + 4, 5, 7, 8, 10, 11, 3, 4, 5, 6, 7, 7, 8, 3, 6, 5, 4, 4, 4, + 5, 3, 5, 5, 3, 2, 1, 2, 3, 7, 7, 5, 4, 2, 1, 5, 7, 10, 7, + 4, 3, 0, 6, 8, 10, 8, 5, 3, 1, 6, 8, 7, 5, 7, 8, 9, 6, 8, + 7, 6, 6, 6, 6, 6, 8, 9, 5, 3, 3, 3, 6, 8, 10, 7, 4, 2, 0, + 7, 10, 11, 8, 5, 3, 2, 8, 10, 11, 10, 6, 4, 2, 9, 10, 11, 11, 7, + 4, 3, 19, 22, 26, 30, 30, 27, 23, 17, 21, 25, 29, 29, 25, 22, 16, 20, 23, + 26, 28, 24, 20, 15, 17, 21, 24, 26, 23, 18, 12, 14, 17, 20, 24, 22, 18, 10, + 13, 16, 19, 22, 22, 18, 8, 11, 15, 18, 20, 21, 18, 16, 20, 23, 27, 25, 23, + 20, 15, 18, 22, 26, 26, 22, 18, 14, 17, 21, 23, 23, 20, 16, 12, 15, 18, 21, + 20, 19, 14, 9, 12, 15, 17, 17, 17, 14, 8, 11, 14, 16, 16, 16, 14, 6, 9, + 13, 15, 14, 15, 14, 14, 17, 19, 19, 21, 20, 15, 12, 15, 17, 18, 19, 18, 13, + 11, 14, 16, 16, 16, 16, 11, 10, 12, 13, 12, 13, 13, 9, 6, 9, 10, 10, 10, + 10, 9, 5, 8, 9, 9, 9, 9, 9, 6, 7, 8, 8, 8, 8, 8, 11, 11, 12, + 13, 14, 15, 9, 10, 10, 10, 11, 11, 12, 7, 8, 9, 9, 9, 8, 8, 5, 4, + 6, 5, 5, 5, 5, 4, 3, 3, 3, 3, 3, 2, 2, 4, 3, 2, 2, 2, 2, + 1, 6, 7, 4, 3, 2, 1, 0, 3, 3, 5, 6, 7, 8, 9, 2, 3, 4, 5, + 6, 6, 7, 2, 3, 3, 3, 3, 3, 4, 2, 5, 3, 2, 2, 2, 1, 3, 6, + 4, 3, 3, 2, 0, 4, 7, 6, 4, 3, 2, 2, 6, 8, 8, 6, 4, 3, 2, + 6, 6, 5, 5, 6, 7, 8, 6, 7, 5, 5, 5, 5, 5, 6, 8, 6, 4, 3, + 2, 2, 6, 8, 6, 5, 4, 3, 1, 6, 7, 9, 8, 5, 3, 2, 7, 9, 13, + 11, 7, 4, 2, 8, 10, 14, 13, 9, 5, 3, 8, 11, 9, 6, 5, 7, 7, 8, + 11, 11, 7, 4, 4, 4, 8, 11, 13, 7, 4, 3, 2, 8, 10, 14, 8, 5, 3, + 2, 8, 11, 15, 13, 8, 5, 3, 9, 13, 17, 17, 10, 6, 3, 11, 15, 18, 18, + 12, 7, 4, 23, 25, 27, 31, 31, 29, 25, 23, 24, 26, 29, 30, 27, 25, 21, 24, + 27, 27, 28, 25, 22, 20, 21, 24, 25, 26, 22, 16, 17, 19, 20, 21, 20, 18, 16, + 12, 14, 16, 16, 18, 18, 16, 8, 11, 14, 16, 18, 18, 16, 21, 24, 25, 28, 27, + 26, 24, 20, 23, 25, 27, 27, 24, 23, 18, 22, 25, 24, 25, 22, 20, 17, 20, 22, + 22, 21, 20, 15, 14, 16, 18, 19, 16, 15, 14, 9, 12, 14, 15, 14, 15, 15, 6, + 8, 12, 14, 14, 15, 15, 19, 22, 23, 24, 24, 24, 21, 16, 20, 22, 23, 24, 23, + 21, 15, 19, 21, 22, 22, 21, 19, 14, 17, 18, 18, 18, 19, 14, 9, 13, 14, 15, + 14, 14, 13, 4, 9, 10, 11, 12, 13, 13, 7, 7, 8, 10, 11, 12, 13, 15, 17, + 18, 20, 20, 21, 16, 14, 15, 16, 18, 18, 18, 14, 11, 13, 15, 15, 15, 15, 12, + 7, 11, 11, 11, 12, 11, 10, 5, 7, 7, 7, 6, 7, 6, 3, 3, 3, 3, 5, + 6, 6, 6, 6, 4, 2, 3, 4, 5, 8, 10, 11, 13, 14, 15, 16, 5, 9, 10, + 12, 12, 13, 15, 5, 8, 9, 9, 10, 10, 11, 5, 6, 6, 6, 6, 6, 5, 3, + 3, 3, 3, 3, 2, 4, 0, 3, 3, 2, 2, 2, 5, 4, 4, 5, 3, 3, 3, + 3, 7, 8, 8, 9, 11, 14, 15, 7, 9, 8, 9, 9, 11, 13, 7, 9, 9, 9, + 7, 8, 10, 7, 8, 8, 8, 6, 5, 5, 5, 7, 9, 7, 5, 3, 2, 3, 5, + 10, 8, 6, 3, 2, 4, 7, 10, 10, 7, 4, 2, 10, 13, 13, 10, 9, 12, 13, + 10, 14, 14, 11, 9, 9, 11, 10, 13, 16, 11, 8, 7, 8, 10, 13, 15, 10, 8, + 6, 2, 9, 11, 14, 11, 7, 4, 2, 7, 10, 13, 12, 8, 5, 3, 7, 11, 13, + 13, 9, 6, 3, 30, 34, 36, 38, 39, 38, 34, 29, 33, 36, 38, 38, 35, 33, 27, + 31, 33, 36, 37, 34, 30, 26, 29, 31, 35, 35, 30, 24, 23, 26, 27, 30, 29, 27, + 24, 18, 22, 23, 25, 27, 26, 24, 14, 18, 21, 24, 26, 26, 24, 27, 31, 35, 37, + 36, 35, 31, 25, 30, 33, 36, 36, 33, 29, 24, 28, 31, 34, 34, 31, 28, 23, 26, + 30, 32, 29, 28, 22, 19, 23, 25, 27, 25, 24, 22, 15, 18, 20, 22, 23, 24, 22, + 11, 15, 19, 22, 22, 22, 22, 24, 29, 30, 32, 33, 32, 28, 22, 26, 30, 31, 30, + 31, 26, 22, 25, 28, 28, 28, 28, 23, 19, 23, 24, 25, 25, 25, 18, 13, 19, 21, + 21, 19, 19, 19, 7, 15, 16, 16, 18, 18, 19, 7, 11, 14, 15, 16, 17, 17, 21, + 23, 24, 26, 27, 27, 21, 18, 21, 22, 24, 24, 24, 19, 14, 20, 20, 21, 21, 21, + 17, 11, 17, 17, 17, 17, 17, 15, 9, 12, 12, 13, 12, 12, 11, 6, 8, 8, 9, + 9, 10, 8, 7, 5, 6, 7, 8, 8, 8, 11, 14, 16, 17, 18, 19, 20, 7, 13, + 14, 16, 17, 16, 19, 7, 13, 13, 13, 14, 14, 15, 7, 9, 10, 9, 9, 9, 8, + 5, 3, 5, 5, 4, 5, 7, 3, 0, 2, 2, 1, 3, 7, 3, 3, 3, 2, 2, + 2, 5, 7, 9, 10, 12, 15, 18, 20, 7, 7, 9, 11, 13, 16, 16, 7, 8, 8, + 8, 10, 12, 12, 7, 7, 7, 7, 6, 7, 6, 5, 5, 6, 5, 3, 2, 5, 2, + 3, 5, 4, 3, 2, 4, 3, 5, 6, 6, 4, 2, 3, 9, 11, 11, 9, 12, 16, + 17, 9, 11, 12, 10, 10, 13, 15, 9, 11, 13, 9, 7, 9, 11, 9, 10, 12, 8, + 6, 5, 4, 7, 9, 10, 8, 4, 2, 3, 5, 7, 9, 8, 4, 3, 2, 4, 6, + 9, 9, 5, 3, 2, 32, 36, 40, 42, 43, 41, 37, 31, 35, 39, 42, 42, 39, 35, + 29, 33, 38, 40, 41, 37, 33, 28, 30, 35, 37, 39, 34, 27, 25, 27, 30, 32, 33, + 30, 27, 21, 23, 26, 28, 31, 31, 27, 16, 20, 24, 27, 30, 30, 27, 29, 34, 37, + 39, 39, 37, 34, 28, 33, 35, 38, 39, 35, 32, 26, 30, 34, 36, 36, 33, 28, 25, + 28, 31, 33, 34, 30, 24, 21, 24, 27, 29, 27, 26, 24, 16, 20, 23, 25, 25, 27, + 24, 13, 17, 21, 24, 24, 25, 24, 26, 30, 32, 34, 35, 34, 29, 25, 28, 31, 33, + 33, 31, 26, 22, 26, 30, 30, 29, 29, 24, 19, 25, 26, 26, 27, 25, 20, 13, 21, + 22, 23, 20, 21, 20, 8, 17, 18, 18, 18, 19, 20, 7, 14, 16, 16, 17, 17, 18, + 23, 24, 25, 26, 28, 29, 21, 19, 22, 24, 25, 26, 26, 19, 15, 21, 22, 22, 22, + 22, 18, 11, 18, 18, 18, 18, 17, 16, 9, 13, 15, 14, 13, 12, 12, 7, 8, 10, + 10, 10, 11, 9, 7, 5, 8, 9, 9, 10, 7, 11, 16, 17, 18, 19, 19, 21, 7, + 15, 16, 17, 18, 17, 20, 7, 13, 14, 14, 14, 14, 14, 7, 9, 11, 10, 10, 9, + 8, 5, 3, 6, 6, 4, 5, 6, 3, 2, 0, 2, 3, 4, 6, 4, 3, 3, 2, + 2, 3, 5, 7, 10, 12, 13, 16, 18, 20, 7, 9, 11, 12, 14, 16, 16, 7, 7, + 9, 9, 11, 13, 12, 7, 6, 7, 7, 7, 7, 6, 5, 4, 9, 9, 5, 3, 5, + 3, 5, 11, 11, 7, 2, 5, 1, 7, 11, 12, 9, 4, 4, 9, 15, 14, 10, 14, + 17, 18, 8, 15, 16, 10, 12, 14, 14, 9, 14, 18, 11, 8, 10, 11, 8, 14, 18, + 12, 7, 5, 5, 7, 13, 17, 14, 9, 4, 4, 7, 13, 16, 14, 11, 6, 3, 8, + 13, 15, 15, 12, 8, 2, 30, 33, 38, 42, 43, 38, 36, 29, 33, 37, 41, 41, 38, + 35, 28, 31, 35, 39, 40, 36, 31, 26, 29, 33, 35, 38, 33, 27, 23, 26, 28, 30, + 32, 30, 27, 19, 22, 25, 27, 31, 30, 27, 16, 19, 22, 26, 30, 29, 27, 27, 31, + 34, 39, 38, 35, 32, 26, 30, 34, 38, 37, 34, 30, 26, 29, 32, 35, 34, 31, 26, + 23, 25, 30, 32, 31, 29, 23, 20, 23, 26, 28, 26, 26, 22, 16, 19, 22, 23, 23, + 25, 23, 12, 17, 20, 23, 23, 24, 23, 25, 29, 30, 31, 34, 32, 27, 23, 27, 29, + 31, 31, 29, 25, 22, 26, 28, 28, 28, 27, 22, 18, 23, 25, 25, 25, 23, 18, 12, + 20, 21, 21, 20, 19, 18, 7, 16, 17, 17, 17, 18, 18, 6, 14, 16, 16, 16, 16, + 16, 21, 23, 24, 25, 26, 26, 20, 18, 22, 23, 23, 24, 23, 17, 14, 20, 21, 20, + 21, 21, 16, 10, 17, 17, 17, 17, 16, 14, 8, 12, 13, 13, 12, 11, 11, 7, 8, + 10, 10, 9, 10, 7, 6, 5, 8, 8, 8, 8, 5, 9, 15, 15, 17, 17, 17, 19, + 6, 13, 14, 15, 15, 14, 17, 6, 12, 12, 12, 12, 11, 12, 6, 8, 9, 9, 8, + 7, 7, 4, 2, 5, 4, 3, 4, 5, 2, 2, 2, 0, 2, 3, 4, 3, 2, 3, + 2, 2, 2, 4, 6, 9, 10, 11, 13, 16, 17, 6, 7, 9, 10, 12, 13, 14, 6, + 7, 7, 8, 9, 10, 9, 6, 6, 7, 7, 5, 6, 4, 4, 5, 9, 9, 4, 2, + 3, 2, 5, 11, 11, 6, 1, 3, 2, 6, 11, 13, 8, 3, 3, 9, 15, 14, 9, + 12, 14, 15, 9, 15, 17, 10, 10, 12, 12, 9, 15, 18, 11, 7, 9, 9, 9, 14, + 19, 12, 7, 4, 3, 7, 13, 19, 15, 8, 3, 2, 7, 13, 18, 17, 10, 5, 2, + 8, 14, 19, 18, 13, 7, 2, 29, 31, 36, 40, 40, 38, 34, 27, 30, 35, 39, 38, + 36, 32, 25, 29, 33, 37, 38, 33, 30, 24, 27, 31, 34, 36, 32, 26, 21, 24, 26, + 30, 32, 30, 25, 18, 20, 23, 27, 30, 28, 26, 16, 18, 22, 25, 29, 29, 26, 26, + 29, 33, 37, 35, 34, 30, 25, 28, 32, 35, 36, 32, 27, 22, 27, 30, 33, 33, 30, + 25, 22, 24, 26, 30, 30, 27, 21, 19, 21, 23, 26, 25, 25, 22, 16, 18, 20, 23, + 24, 24, 21, 12, 16, 19, 22, 22, 23, 21, 23, 26, 28, 29, 31, 29, 25, 22, 25, + 27, 29, 28, 27, 23, 20, 24, 26, 26, 26, 25, 20, 17, 22, 22, 22, 23, 22, 16, + 11, 18, 19, 19, 18, 18, 16, 7, 16, 17, 16, 16, 17, 16, 7, 15, 15, 15, 15, + 16, 15, 20, 21, 21, 22, 24, 24, 17, 17, 20, 20, 21, 21, 21, 15, 13, 19, 19, + 18, 18, 18, 13, 9, 16, 15, 15, 15, 14, 12, 7, 11, 11, 11, 10, 10, 9, 7, + 8, 10, 9, 9, 9, 6, 7, 5, 8, 8, 8, 8, 4, 8, 13, 14, 14, 15, 14, + 16, 5, 12, 12, 13, 13, 11, 15, 5, 10, 10, 10, 10, 9, 10, 5, 6, 7, 6, + 6, 5, 5, 3, 1, 3, 2, 2, 2, 3, 2, 1, 3, 2, 0, 2, 3, 4, 2, + 4, 2, 2, 1, 3, 4, 6, 7, 9, 10, 13, 14, 4, 5, 6, 8, 9, 10, 11, + 4, 7, 7, 6, 7, 7, 7, 4, 6, 7, 7, 3, 4, 3, 2, 5, 10, 8, 5, + 1, 2, 0, 6, 11, 11, 6, 2, 2, 3, 7, 12, 12, 8, 3, 2, 9, 12, 11, + 8, 9, 11, 12, 9, 13, 12, 9, 8, 9, 9, 9, 13, 14, 9, 6, 6, 7, 9, + 12, 14, 10, 7, 2, 2, 8, 12, 15, 13, 8, 3, 2, 8, 13, 16, 15, 10, 5, + 1, 8, 13, 16, 16, 11, 7, 2, 26, 28, 32, 36, 37, 34, 31, 24, 27, 31, 36, + 36, 33, 29, 23, 26, 29, 33, 34, 32, 27, 21, 24, 27, 31, 33, 29, 24, 18, 21, + 24, 27, 31, 27, 24, 16, 18, 22, 25, 28, 27, 24, 15, 17, 21, 23, 27, 27, 24, + 23, 27, 30, 35, 33, 31, 27, 21, 26, 29, 32, 32, 28, 25, 21, 23, 28, 30, 31, + 28, 23, 20, 22, 24, 27, 27, 25, 20, 17, 18, 21, 24, 24, 23, 20, 15, 17, 19, + 22, 22, 22, 20, 12, 16, 18, 20, 20, 21, 19, 21, 24, 25, 27, 28, 27, 22, 19, + 22, 25, 25, 26, 24, 20, 18, 21, 23, 23, 23, 22, 18, 16, 19, 20, 20, 20, 19, + 15, 10, 16, 16, 16, 16, 16, 14, 7, 15, 16, 15, 15, 15, 14, 7, 14, 14, 13, + 14, 14, 13, 18, 19, 18, 20, 21, 21, 14, 15, 17, 18, 18, 19, 18, 12, 12, 16, + 16, 16, 15, 15, 11, 8, 14, 13, 12, 12, 11, 10, 6, 10, 9, 9, 8, 8, 7, + 6, 8, 8, 7, 7, 7, 4, 7, 4, 6, 6, 6, 6, 3, 8, 10, 11, 12, 12, + 12, 13, 3, 9, 9, 10, 11, 9, 11, 3, 8, 7, 7, 7, 7, 7, 3, 4, 4, + 3, 3, 3, 3, 1, 1, 1, 1, 2, 1, 2, 2, 3, 4, 3, 2, 0, 3, 3, + 5, 5, 3, 3, 2, 2, 3, 5, 6, 7, 8, 10, 11, 3, 4, 6, 7, 7, 8, + 8, 3, 4, 4, 4, 5, 5, 6, 3, 4, 4, 3, 2, 2, 2, 2, 5, 6, 4, + 3, 2, 2, 3, 6, 8, 6, 3, 2, 1, 5, 7, 8, 7, 4, 3, 0, 5, 7, + 6, 6, 8, 9, 10, 5, 7, 7, 6, 6, 7, 7, 6, 7, 8, 4, 3, 4, 4, + 5, 7, 8, 5, 3, 2, 1, 5, 8, 9, 7, 4, 2, 0, 6, 8, 10, 9, 5, + 3, 2, 7, 9, 10, 10, 6, 4, 3, 20, 24, 29, 32, 32, 29, 25, 20, 23, 27, + 31, 31, 28, 25, 18, 21, 25, 29, 30, 25, 22, 16, 19, 22, 26, 28, 23, 20, 13, + 16, 19, 22, 26, 23, 19, 11, 14, 17, 20, 24, 23, 20, 10, 13, 16, 19, 22, 23, + 20, 18, 21, 25, 29, 28, 26, 22, 16, 20, 24, 28, 28, 24, 20, 15, 19, 23, 25, + 24, 23, 18, 14, 17, 20, 22, 22, 20, 16, 11, 13, 16, 18, 19, 18, 16, 10, 12, + 15, 17, 18, 17, 15, 7, 11, 14, 16, 16, 16, 16, 15, 19, 21, 21, 23, 21, 17, + 14, 17, 20, 21, 21, 20, 15, 13, 16, 18, 17, 18, 18, 14, 12, 14, 15, 15, 15, + 15, 11, 8, 11, 12, 12, 12, 12, 11, 5, 10, 11, 10, 10, 10, 11, 5, 8, 9, + 9, 10, 9, 9, 14, 13, 14, 14, 16, 17, 10, 11, 11, 12, 13, 13, 14, 8, 9, + 10, 11, 11, 10, 10, 7, 5, 8, 7, 7, 7, 7, 6, 4, 5, 5, 4, 4, 4, + 3, 5, 3, 3, 3, 3, 3, 3, 6, 5, 3, 2, 2, 2, 2, 4, 5, 6, 7, + 8, 9, 10, 2, 4, 5, 6, 6, 7, 8, 2, 3, 4, 4, 4, 4, 5, 2, 3, + 2, 2, 2, 1, 2, 1, 6, 4, 3, 3, 2, 2, 4, 7, 7, 5, 3, 2, 0, + 6, 8, 8, 5, 4, 3, 1, 5, 5, 5, 5, 6, 8, 9, 4, 6, 5, 5, 5, + 6, 6, 5, 7, 5, 4, 3, 3, 3, 5, 7, 7, 5, 4, 3, 0, 6, 8, 8, + 6, 4, 3, 1, 7, 9, 10, 8, 5, 3, 2, 8, 9, 11, 10, 6, 4, 2, 8, + 10, 7, 5, 6, 7, 7, 8, 9, 9, 6, 5, 5, 5, 8, 10, 10, 5, 4, 2, + 2, 8, 10, 11, 7, 5, 3, 2, 9, 10, 12, 10, 6, 4, 3, 9, 10, 14, 13, + 8, 5, 3, 9, 11, 14, 14, 9, 5, 3, 27, 30, 32, 34, 33, 31, 30, 26, 29, + 32, 33, 33, 30, 28, 25, 29, 30, 31, 31, 27, 24, 24, 25, 27, 28, 28, 23, 17, + 20, 23, 24, 23, 21, 18, 17, 17, 19, 19, 17, 19, 18, 17, 11, 13, 16, 18, 18, + 18, 17, 25, 27, 31, 32, 31, 30, 30, 24, 28, 30, 31, 31, 29, 26, 22, 25, 28, + 30, 28, 26, 23, 21, 24, 26, 26, 25, 21, 16, 18, 20, 22, 22, 17, 16, 16, 13, + 16, 17, 16, 16, 16, 16, 7, 11, 14, 16, 15, 16, 16, 22, 26, 28, 29, 30, 29, + 26, 21, 25, 27, 28, 28, 27, 24, 19, 23, 25, 26, 26, 25, 20, 18, 21, 22, 22, + 22, 20, 15, 11, 17, 18, 18, 15, 15, 14, 5, 12, 13, 13, 13, 13, 15, 4, 7, + 10, 11, 12, 13, 13, 19, 20, 22, 23, 25, 25, 22, 17, 19, 20, 22, 23, 23, 20, + 14, 18, 19, 19, 19, 18, 16, 11, 16, 15, 15, 15, 13, 13, 8, 11, 11, 10, 8, + 8, 9, 5, 5, 5, 5, 6, 7, 7, 4, 3, 2, 4, 5, 5, 7, 13, 16, 18, + 19, 20, 22, 22, 9, 15, 17, 18, 18, 19, 20, 9, 15, 15, 16, 16, 16, 14, 9, + 11, 12, 12, 11, 9, 7, 7, 6, 7, 6, 4, 3, 7, 4, 3, 4, 3, 4, 3, + 6, 0, 3, 4, 3, 4, 4, 4, 10, 11, 13, 14, 17, 20, 21, 10, 10, 12, 13, + 16, 17, 18, 10, 11, 11, 11, 12, 14, 13, 10, 10, 10, 9, 8, 7, 6, 8, 8, + 9, 8, 5, 4, 5, 5, 7, 9, 8, 5, 4, 3, 4, 5, 8, 9, 7, 5, 3, + 12, 14, 14, 13, 15, 19, 20, 12, 14, 15, 13, 13, 15, 17, 12, 14, 16, 12, 10, + 11, 11, 12, 13, 15, 11, 9, 6, 3, 10, 12, 14, 11, 7, 4, 3, 9, 10, 13, + 12, 8, 5, 4, 7, 10, 12, 13, 9, 6, 4, 34, 37, 39, 42, 42, 40, 38, 32, + 35, 39, 42, 42, 39, 36, 31, 34, 37, 39, 39, 36, 31, 29, 32, 34, 37, 36, 31, + 25, 26, 29, 30, 31, 30, 27, 25, 22, 24, 25, 25, 28, 27, 25, 16, 19, 21, 25, + 27, 27, 25, 30, 34, 38, 41, 40, 37, 35, 29, 33, 37, 39, 40, 36, 33, 27, 32, + 35, 37, 36, 33, 30, 26, 29, 33, 34, 32, 28, 23, 23, 26, 28, 29, 27, 24, 23, + 17, 21, 23, 22, 24, 24, 23, 11, 16, 20, 22, 23, 24, 23, 27, 31, 34, 35, 36, + 35, 30, 26, 29, 33, 34, 35, 33, 29, 23, 29, 31, 31, 31, 30, 25, 21, 26, 27, + 28, 27, 25, 20, 15, 22, 24, 23, 20, 20, 20, 9, 18, 18, 17, 17, 18, 20, 6, + 13, 15, 15, 16, 17, 18, 25, 26, 27, 28, 30, 31, 25, 20, 24, 26, 27, 27, 27, + 23, 17, 23, 24, 24, 24, 23, 21, 13, 20, 20, 20, 20, 18, 17, 11, 14, 15, 15, + 12, 12, 13, 8, 8, 11, 9, 10, 11, 10, 6, 4, 7, 7, 8, 9, 9, 13, 19, + 20, 22, 22, 24, 25, 10, 19, 19, 21, 21, 21, 22, 10, 17, 18, 18, 18, 17, 17, + 10, 12, 15, 14, 13, 11, 9, 7, 6, 10, 9, 5, 6, 7, 4, 3, 3, 2, 2, + 5, 8, 3, 0, 3, 2, 2, 3, 7, 10, 14, 15, 17, 20, 22, 24, 10, 12, 14, + 16, 18, 19, 20, 10, 10, 12, 12, 15, 16, 14, 10, 9, 8, 9, 10, 9, 7, 8, + 7, 7, 6, 4, 3, 7, 5, 5, 7, 5, 4, 2, 6, 2, 4, 6, 6, 4, 3, + 5, 10, 13, 13, 13, 17, 21, 22, 10, 13, 13, 12, 16, 18, 19, 10, 13, 14, 11, + 11, 13, 13, 10, 12, 13, 10, 8, 7, 6, 8, 10, 11, 9, 5, 3, 5, 7, 8, + 9, 8, 5, 3, 3, 5, 7, 9, 9, 6, 4, 2, 36, 39, 42, 47, 46, 43, 40, + 33, 38, 41, 46, 46, 42, 38, 33, 35, 40, 43, 43, 39, 35, 31, 33, 37, 39, 41, + 36, 31, 27, 30, 34, 35, 35, 32, 30, 23, 26, 28, 30, 33, 33, 30, 19, 22, 26, + 29, 32, 32, 30, 32, 36, 41, 44, 42, 41, 38, 31, 34, 39, 42, 42, 39, 35, 29, + 34, 37, 39, 40, 38, 32, 28, 31, 35, 36, 36, 32, 26, 23, 27, 30, 32, 30, 29, + 26, 18, 23, 26, 27, 27, 27, 27, 13, 20, 23, 26, 26, 26, 26, 30, 34, 35, 37, + 38, 38, 32, 27, 31, 35, 36, 36, 35, 30, 25, 30, 34, 34, 33, 32, 27, 21, 28, + 29, 29, 29, 28, 22, 15, 24, 26, 25, 23, 23, 22, 9, 20, 21, 20, 20, 21, 22, + 8, 17, 18, 19, 19, 20, 20, 25, 28, 29, 31, 31, 32, 26, 20, 26, 28, 29, 29, + 29, 23, 17, 24, 25, 26, 25, 25, 21, 14, 21, 22, 21, 22, 20, 18, 11, 15, 18, + 18, 15, 14, 14, 9, 10, 13, 13, 13, 13, 11, 8, 5, 10, 10, 11, 12, 8, 13, + 20, 20, 22, 23, 22, 25, 10, 18, 19, 21, 21, 20, 23, 9, 16, 18, 17, 17, 17, + 17, 10, 11, 14, 13, 13, 10, 10, 7, 5, 10, 9, 6, 7, 8, 5, 3, 3, 3, + 3, 5, 8, 4, 3, 0, 2, 3, 5, 7, 8, 14, 15, 17, 19, 22, 23, 9, 12, + 14, 15, 17, 19, 19, 9, 9, 12, 12, 14, 15, 14, 9, 8, 8, 8, 10, 9, 7, + 6, 5, 7, 7, 3, 5, 7, 4, 3, 8, 7, 5, 4, 7, 2, 4, 8, 8, 6, + 2, 5, 9, 12, 12, 13, 17, 20, 21, 9, 12, 14, 11, 15, 17, 18, 9, 12, 15, + 9, 11, 13, 13, 9, 11, 14, 10, 7, 7, 6, 7, 10, 13, 11, 6, 2, 5, 5, + 10, 11, 10, 7, 4, 4, 5, 8, 10, 10, 8, 6, 3, 32, 36, 39, 43, 44, 41, + 38, 31, 35, 38, 43, 44, 39, 35, 29, 33, 37, 40, 40, 38, 33, 28, 30, 34, 37, + 38, 34, 29, 25, 28, 30, 33, 35, 31, 29, 22, 24, 26, 29, 32, 31, 28, 18, 21, + 24, 28, 31, 32, 29, 29, 34, 38, 40, 41, 37, 34, 28, 32, 35, 39, 39, 36, 31, + 27, 30, 35, 38, 37, 33, 29, 25, 28, 31, 34, 33, 31, 24, 21, 25, 27, 29, 28, + 27, 24, 17, 21, 23, 25, 26, 27, 24, 13, 18, 22, 24, 24, 25, 25, 27, 30, 33, + 34, 35, 33, 29, 25, 29, 31, 33, 34, 32, 27, 23, 28, 30, 30, 30, 29, 24, 19, + 25, 25, 26, 26, 26, 20, 13, 21, 22, 23, 21, 20, 19, 8, 17, 19, 19, 19, 19, + 19, 7, 16, 17, 18, 18, 19, 18, 23, 25, 26, 27, 29, 28, 21, 18, 23, 24, 26, + 26, 25, 19, 15, 22, 23, 22, 22, 21, 18, 12, 19, 19, 19, 18, 17, 16, 9, 13, + 15, 15, 13, 12, 12, 8, 9, 11, 11, 11, 11, 9, 8, 5, 10, 9, 10, 10, 6, + 11, 16, 18, 19, 20, 18, 21, 7, 15, 16, 17, 17, 16, 19, 7, 12, 14, 14, 13, + 13, 14, 7, 8, 11, 10, 10, 7, 8, 5, 2, 6, 6, 4, 4, 6, 3, 2, 2, + 2, 2, 3, 5, 3, 2, 2, 0, 2, 3, 4, 6, 10, 11, 13, 15, 16, 19, 6, + 9, 10, 11, 13, 14, 15, 6, 7, 8, 9, 10, 11, 10, 6, 5, 6, 5, 6, 7, + 5, 4, 3, 7, 7, 3, 3, 4, 2, 3, 10, 10, 5, 2, 4, 1, 4, 10, 12, + 7, 2, 3, 7, 13, 12, 10, 13, 16, 16, 7, 13, 15, 9, 11, 13, 13, 7, 13, + 17, 10, 8, 10, 10, 7, 12, 17, 11, 5, 5, 4, 6, 11, 17, 13, 7, 2, 3, + 5, 12, 17, 16, 9, 4, 3, 6, 12, 17, 17, 11, 6, 2, 30, 35, 39, 42, 42, + 39, 36, 29, 34, 38, 41, 42, 38, 34, 28, 31, 36, 39, 41, 36, 33, 27, 28, 32, + 36, 38, 33, 28, 24, 25, 29, 33, 34, 31, 28, 20, 22, 26, 28, 32, 31, 28, 18, + 20, 24, 27, 30, 31, 28, 28, 31, 35, 40, 39, 35, 32, 26, 30, 34, 38, 39, 34, + 30, 25, 28, 32, 36, 36, 32, 27, 24, 26, 29, 33, 33, 30, 23, 20, 23, 26, 28, + 28, 26, 23, 16, 20, 23, 25, 26, 26, 24, 13, 19, 21, 24, 24, 24, 23, 25, 29, + 30, 32, 33, 31, 27, 23, 27, 29, 31, 30, 30, 25, 21, 26, 28, 29, 28, 27, 22, + 18, 25, 25, 25, 25, 24, 18, 12, 20, 22, 21, 21, 19, 18, 8, 18, 18, 19, 19, + 18, 18, 8, 16, 18, 17, 18, 18, 16, 20, 24, 24, 25, 26, 25, 19, 17, 22, 22, + 23, 24, 22, 17, 14, 20, 21, 20, 20, 20, 15, 11, 17, 17, 17, 17, 16, 14, 8, + 12, 14, 14, 13, 12, 11, 7, 9, 11, 11, 11, 11, 7, 7, 6, 10, 9, 9, 10, + 5, 9, 15, 16, 17, 18, 15, 18, 6, 14, 15, 15, 16, 13, 16, 6, 11, 12, 12, + 12, 10, 12, 6, 6, 9, 9, 8, 6, 7, 4, 2, 5, 4, 4, 3, 4, 3, 2, + 2, 2, 2, 2, 4, 4, 2, 3, 2, 0, 2, 3, 5, 8, 9, 10, 12, 14, 16, + 5, 6, 8, 9, 11, 11, 12, 5, 5, 6, 6, 8, 9, 8, 4, 4, 6, 5, 4, + 5, 4, 2, 4, 7, 7, 3, 2, 3, 2, 4, 10, 9, 4, 1, 3, 2, 5, 10, + 11, 6, 2, 2, 7, 11, 10, 7, 11, 13, 14, 7, 11, 11, 8, 9, 11, 11, 7, + 11, 13, 8, 6, 7, 8, 7, 11, 13, 9, 5, 3, 3, 6, 10, 14, 12, 7, 2, + 3, 6, 11, 15, 14, 8, 3, 2, 7, 12, 15, 15, 10, 5, 1, 27, 31, 36, 39, + 39, 36, 33, 27, 30, 34, 38, 39, 36, 32, 24, 27, 34, 36, 37, 33, 30, 24, 26, + 29, 32, 36, 32, 26, 21, 23, 26, 29, 32, 29, 26, 18, 20, 23, 26, 30, 29, 26, + 17, 19, 22, 25, 28, 29, 26, 24, 28, 32, 37, 35, 33, 29, 24, 27, 32, 34, 36, + 30, 27, 23, 26, 29, 32, 31, 30, 25, 22, 23, 27, 29, 29, 27, 22, 18, 20, 23, + 26, 25, 24, 21, 16, 18, 20, 23, 23, 24, 22, 12, 17, 20, 22, 22, 23, 21, 23, + 26, 28, 29, 30, 28, 23, 21, 25, 27, 28, 28, 27, 22, 20, 23, 26, 25, 26, 25, + 20, 17, 22, 21, 21, 21, 21, 16, 11, 18, 18, 18, 18, 18, 16, 8, 16, 17, 16, + 17, 16, 16, 8, 15, 15, 15, 15, 15, 14, 20, 21, 21, 22, 23, 23, 15, 16, 19, + 20, 20, 21, 19, 14, 13, 18, 18, 18, 17, 17, 12, 9, 15, 14, 14, 13, 13, 12, + 7, 11, 11, 10, 10, 10, 8, 7, 9, 10, 9, 9, 9, 5, 8, 5, 8, 8, 8, + 8, 3, 8, 12, 13, 14, 14, 13, 15, 4, 11, 12, 12, 12, 10, 13, 4, 9, 9, + 9, 9, 8, 9, 4, 5, 6, 5, 5, 4, 5, 3, 2, 2, 2, 2, 2, 3, 3, + 2, 3, 2, 1, 2, 3, 4, 3, 5, 3, 2, 0, 3, 3, 6, 7, 8, 9, 11, + 13, 3, 5, 7, 8, 8, 9, 10, 3, 4, 5, 5, 6, 6, 6, 3, 3, 3, 2, + 2, 3, 3, 1, 4, 6, 4, 3, 0, 3, 2, 6, 8, 5, 4, 2, 2, 4, 7, + 8, 7, 4, 2, 2, 4, 6, 6, 7, 9, 10, 11, 4, 6, 7, 6, 7, 8, 8, + 4, 6, 7, 4, 4, 4, 6, 4, 6, 8, 4, 2, 1, 2, 3, 8, 9, 7, 4, + 2, 2, 6, 9, 9, 9, 5, 3, 0, 7, 9, 9, 9, 6, 4, 2, 22, 26, 29, + 33, 33, 30, 27, 21, 24, 29, 33, 32, 29, 26, 19, 23, 27, 30, 32, 28, 24, 18, + 21, 24, 27, 30, 26, 21, 15, 17, 21, 24, 27, 24, 21, 13, 15, 18, 22, 25, 25, + 21, 12, 15, 18, 20, 24, 24, 21, 20, 23, 27, 31, 29, 26, 23, 18, 22, 26, 29, + 29, 26, 21, 17, 20, 24, 27, 27, 24, 20, 16, 18, 21, 24, 23, 22, 17, 13, 15, + 17, 20, 20, 20, 17, 12, 13, 16, 18, 19, 19, 16, 9, 12, 16, 18, 17, 18, 17, + 18, 20, 23, 24, 25, 23, 19, 17, 19, 21, 22, 22, 21, 17, 15, 18, 20, 20, 20, + 19, 15, 14, 16, 16, 16, 16, 16, 12, 9, 13, 14, 13, 13, 13, 12, 6, 12, 13, + 12, 12, 12, 12, 6, 10, 10, 11, 11, 11, 10, 15, 15, 16, 17, 18, 18, 11, 14, + 14, 14, 15, 15, 15, 9, 11, 12, 13, 12, 12, 11, 8, 6, 11, 9, 9, 9, 9, + 7, 4, 7, 6, 6, 5, 5, 4, 5, 5, 5, 5, 4, 4, 2, 6, 4, 3, 3, + 3, 3, 2, 6, 7, 7, 8, 9, 10, 11, 2, 5, 6, 7, 7, 8, 9, 2, 4, + 5, 4, 5, 5, 5, 2, 2, 2, 2, 1, 2, 2, 1, 4, 3, 3, 2, 1, 2, + 3, 5, 5, 3, 3, 2, 1, 4, 7, 6, 4, 3, 3, 0, 4, 4, 5, 6, 7, + 8, 10, 3, 5, 5, 6, 6, 6, 7, 4, 6, 5, 4, 4, 3, 4, 4, 6, 5, + 4, 3, 2, 1, 4, 7, 8, 5, 4, 3, 0, 5, 7, 9, 7, 4, 3, 2, 6, + 8, 9, 8, 5, 3, 2, 7, 9, 7, 5, 6, 8, 8, 7, 9, 8, 5, 5, 5, + 5, 7, 9, 9, 5, 3, 2, 3, 7, 8, 11, 6, 4, 3, 1, 8, 9, 11, 9, + 5, 3, 2, 8, 9, 11, 11, 6, 4, 2, 8, 10, 12, 12, 8, 5, 3, 24, 27, + 29, 32, 31, 29, 26, 23, 26, 28, 30, 32, 29, 25, 22, 24, 27, 29, 31, 29, 25, + 21, 23, 26, 28, 31, 28, 27, 20, 23, 25, 28, 31, 29, 26, 19, 23, 25, 27, 30, + 29, 27, 16, 20, 23, 26, 29, 28, 27, 22, 24, 27, 30, 28, 25, 24, 21, 24, 26, + 29, 28, 26, 24, 19, 22, 25, 28, 27, 25, 24, 18, 22, 24, 27, 26, 25, 23, 18, + 21, 24, 27, 26, 26, 24, 16, 19, 22, 24, 25, 25, 24, 13, 16, 21, 24, 25, 24, + 24, 19, 22, 23, 24, 24, 23, 19, 18, 20, 23, 23, 24, 23, 19, 17, 20, 22, 22, + 22, 23, 19, 16, 19, 21, 21, 22, 23, 20, 14, 18, 19, 20, 21, 22, 19, 11, 16, + 18, 19, 19, 20, 20, 13, 14, 16, 17, 19, 19, 18, 17, 18, 17, 18, 18, 17, 8, + 15, 15, 16, 16, 17, 16, 9, 13, 14, 15, 15, 15, 15, 10, 9, 14, 14, 14, 15, + 15, 11, 9, 12, 12, 13, 13, 14, 8, 10, 10, 10, 11, 11, 12, 6, 13, 13, 10, + 9, 10, 10, 6, 8, 9, 9, 9, 10, 6, 8, 4, 7, 7, 8, 8, 6, 9, 4, + 6, 5, 6, 6, 5, 7, 4, 4, 4, 4, 5, 5, 7, 5, 4, 4, 4, 4, 3, + 6, 7, 7, 7, 6, 4, 3, 4, 10, 10, 8, 6, 5, 3, 4, 0, 2, 2, 2, + 2, 5, 7, 0, 3, 2, 2, 1, 4, 8, 0, 4, 3, 2, 1, 3, 6, 0, 3, + 3, 2, 1, 2, 5, 2, 3, 5, 5, 3, 3, 4, 5, 6, 9, 8, 5, 3, 3, + 8, 9, 10, 9, 6, 4, 3, 4, 7, 6, 3, 2, 3, 6, 4, 7, 7, 4, 2, + 2, 5, 4, 7, 9, 4, 2, 0, 5, 4, 7, 10, 6, 3, 2, 3, 4, 7, 11, + 9, 5, 3, 3, 5, 9, 12, 11, 7, 4, 3, 7, 11, 12, 13, 8, 5, 3, 25, + 29, 32, 33, 34, 31, 29, 25, 27, 31, 34, 34, 32, 29, 23, 26, 29, 32, 34, 31, + 29, 21, 24, 28, 32, 34, 33, 30, 21, 24, 28, 32, 35, 33, 30, 20, 23, 27, 31, + 34, 33, 30, 18, 23, 25, 30, 33, 33, 31, 23, 25, 29, 31, 30, 27, 25, 21, 25, + 28, 31, 30, 27, 25, 21, 24, 27, 30, 29, 27, 25, 19, 22, 27, 28, 29, 29, 25, + 20, 22, 26, 29, 29, 28, 26, 19, 21, 24, 28, 28, 28, 25, 15, 19, 23, 27, 27, + 27, 26, 21, 25, 25, 26, 26, 24, 19, 19, 22, 25, 24, 25, 24, 19, 18, 22, 23, + 23, 24, 24, 20, 17, 21, 22, 23, 23, 23, 20, 14, 20, 22, 21, 22, 22, 21, 12, + 18, 20, 21, 21, 22, 20, 13, 16, 18, 19, 20, 20, 18, 19, 19, 19, 19, 19, 18, + 7, 16, 17, 18, 17, 18, 16, 9, 13, 16, 16, 17, 16, 15, 10, 10, 16, 16, 15, + 16, 15, 12, 11, 14, 15, 15, 14, 14, 9, 11, 12, 13, 13, 13, 13, 6, 14, 14, + 10, 11, 12, 12, 6, 8, 10, 10, 11, 10, 6, 7, 5, 9, 9, 9, 9, 6, 9, + 5, 8, 7, 7, 7, 5, 6, 5, 6, 6, 6, 7, 4, 6, 6, 5, 5, 5, 5, + 4, 6, 8, 9, 10, 9, 6, 5, 5, 11, 14, 14, 11, 8, 6, 4, 2, 0, 1, + 1, 3, 5, 6, 2, 2, 2, 2, 2, 4, 6, 2, 4, 4, 4, 1, 4, 7, 2, + 5, 7, 7, 4, 3, 5, 3, 7, 12, 11, 9, 6, 4, 6, 12, 16, 13, 11, 7, + 4, 12, 16, 16, 14, 12, 8, 5, 6, 11, 11, 6, 1, 3, 5, 6, 12, 12, 8, + 2, 3, 5, 6, 11, 13, 9, 4, 2, 5, 6, 12, 14, 12, 8, 4, 4, 8, 13, + 16, 15, 12, 8, 5, 10, 15, 17, 16, 13, 10, 6, 14, 17, 18, 17, 14, 11, 7, + 24, 27, 31, 33, 34, 31, 28, 23, 27, 29, 33, 34, 31, 28, 22, 25, 29, 32, 33, + 31, 28, 21, 25, 28, 31, 35, 32, 29, 22, 24, 28, 31, 35, 33, 30, 21, 24, 26, + 30, 34, 33, 29, 18, 21, 25, 29, 33, 33, 30, 21, 24, 28, 31, 29, 26, 24, 21, + 24, 27, 30, 30, 26, 23, 20, 23, 26, 28, 30, 27, 25, 19, 22, 26, 29, 29, 28, + 24, 20, 22, 26, 28, 28, 28, 25, 18, 21, 24, 27, 28, 27, 25, 16, 19, 23, 26, + 26, 27, 24, 20, 23, 24, 24, 24, 22, 17, 19, 21, 23, 24, 23, 22, 17, 18, 21, + 22, 23, 23, 21, 18, 16, 21, 22, 22, 23, 22, 18, 14, 20, 22, 22, 22, 22, 18, + 12, 18, 20, 20, 21, 21, 19, 15, 17, 19, 19, 19, 19, 17, 18, 17, 17, 17, 18, + 15, 6, 16, 16, 16, 16, 17, 14, 7, 12, 15, 16, 15, 15, 14, 9, 9, 16, 15, + 15, 15, 14, 12, 10, 14, 14, 15, 14, 13, 9, 12, 12, 12, 13, 13, 12, 6, 15, + 16, 11, 11, 12, 11, 5, 8, 10, 10, 10, 9, 4, 6, 4, 9, 8, 8, 8, 4, + 7, 4, 8, 7, 7, 7, 4, 6, 4, 6, 7, 6, 7, 4, 5, 6, 6, 6, 6, + 6, 5, 5, 8, 10, 12, 10, 7, 6, 5, 12, 16, 15, 12, 9, 7, 5, 2, 1, + 0, 1, 2, 3, 4, 2, 2, 2, 2, 2, 3, 4, 2, 4, 4, 4, 1, 3, 5, + 2, 6, 8, 8, 5, 4, 5, 4, 8, 13, 13, 9, 7, 5, 8, 13, 19, 18, 12, + 8, 5, 13, 18, 20, 19, 14, 9, 6, 6, 12, 11, 5, 1, 2, 4, 6, 12, 13, + 7, 1, 2, 4, 6, 12, 15, 9, 5, 2, 4, 6, 13, 18, 13, 9, 6, 5, 9, + 15, 21, 19, 13, 9, 6, 12, 18, 24, 23, 16, 10, 7, 16, 21, 25, 25, 18, 12, + 8, 24, 27, 30, 33, 33, 31, 26, 23, 26, 30, 33, 33, 31, 27, 21, 24, 28, 32, + 33, 31, 28, 21, 24, 29, 32, 35, 32, 29, 21, 24, 28, 31, 35, 33, 30, 20, 23, + 27, 30, 34, 32, 28, 19, 21, 26, 29, 33, 33, 29, 21, 25, 27, 31, 28, 26, 22, + 21, 23, 27, 30, 28, 26, 23, 19, 22, 26, 28, 29, 28, 23, 19, 23, 26, 29, 29, + 28, 24, 20, 23, 25, 28, 29, 28, 25, 18, 22, 24, 28, 28, 27, 25, 16, 19, 23, + 27, 27, 26, 24, 20, 23, 23, 24, 23, 21, 16, 19, 21, 23, 23, 23, 21, 16, 18, + 20, 22, 22, 22, 22, 17, 16, 21, 22, 22, 22, 22, 18, 15, 20, 22, 22, 22, 21, + 17, 13, 19, 20, 20, 21, 20, 18, 16, 18, 19, 19, 19, 19, 17, 18, 17, 17, 17, + 17, 14, 5, 16, 17, 16, 16, 15, 13, 6, 13, 15, 16, 15, 15, 13, 9, 9, 16, + 15, 15, 15, 13, 12, 11, 15, 14, 15, 14, 13, 8, 12, 13, 13, 13, 13, 12, 6, + 16, 17, 13, 11, 12, 11, 5, 8, 10, 10, 9, 8, 3, 5, 5, 9, 8, 8, 7, + 3, 6, 5, 8, 7, 7, 7, 3, 5, 5, 6, 7, 7, 7, 4, 5, 6, 6, 7, + 7, 7, 7, 5, 9, 12, 13, 11, 9, 7, 5, 14, 17, 17, 13, 10, 8, 6, 2, + 1, 1, 0, 2, 3, 4, 2, 3, 2, 2, 2, 3, 3, 2, 4, 4, 5, 2, 3, + 4, 2, 6, 9, 9, 6, 5, 5, 4, 9, 14, 13, 10, 8, 6, 9, 14, 20, 18, + 12, 9, 7, 15, 19, 21, 20, 15, 10, 7, 6, 9, 7, 4, 0, 2, 3, 6, 9, + 8, 5, 2, 2, 3, 6, 9, 10, 8, 5, 3, 4, 6, 11, 15, 12, 9, 7, 6, + 10, 14, 19, 18, 14, 10, 8, 13, 19, 23, 23, 16, 11, 8, 18, 22, 24, 24, 19, + 13, 9, 20, 23, 27, 30, 30, 28, 24, 19, 23, 26, 29, 29, 27, 24, 18, 21, 25, + 28, 31, 29, 26, 17, 21, 25, 28, 31, 29, 26, 18, 22, 24, 28, 32, 29, 26, 18, + 21, 24, 27, 32, 29, 25, 16, 19, 23, 26, 29, 29, 26, 18, 21, 24, 27, 27, 22, + 19, 18, 20, 23, 26, 26, 23, 20, 17, 19, 22, 26, 26, 24, 21, 16, 19, 23, 26, + 26, 25, 22, 17, 20, 23, 26, 25, 25, 21, 15, 18, 22, 24, 24, 24, 21, 17, 18, + 20, 23, 23, 23, 21, 17, 19, 19, 20, 21, 17, 13, 16, 18, 19, 19, 19, 18, 14, + 15, 18, 19, 20, 20, 19, 14, 15, 18, 20, 19, 20, 19, 15, 13, 17, 19, 18, 19, + 19, 16, 12, 16, 17, 18, 17, 18, 15, 19, 19, 16, 16, 17, 16, 15, 15, 14, 13, + 14, 14, 12, 3, 14, 13, 13, 13, 12, 11, 4, 11, 12, 12, 13, 12, 11, 7, 8, + 13, 13, 12, 12, 12, 9, 9, 12, 12, 11, 11, 10, 7, 12, 14, 12, 11, 10, 10, + 5, 19, 20, 15, 12, 9, 9, 6, 7, 6, 6, 6, 5, 2, 3, 3, 5, 5, 4, + 4, 3, 4, 3, 4, 3, 4, 4, 3, 4, 3, 3, 4, 5, 5, 5, 5, 5, 9, + 9, 9, 9, 8, 6, 10, 15, 16, 13, 10, 8, 6, 17, 20, 19, 15, 12, 9, 7, + 2, 3, 2, 2, 0, 2, 3, 2, 4, 3, 2, 2, 2, 3, 2, 6, 4, 4, 4, + 3, 4, 2, 7, 8, 8, 7, 6, 6, 7, 12, 14, 13, 12, 9, 7, 12, 16, 20, + 18, 13, 10, 8, 18, 21, 22, 19, 15, 11, 8, 7, 9, 5, 3, 2, 1, 2, 7, + 9, 7, 3, 2, 2, 3, 7, 9, 9, 6, 5, 5, 4, 7, 9, 13, 11, 9, 8, + 8, 9, 14, 17, 17, 14, 11, 8, 15, 18, 21, 22, 16, 13, 9, 19, 23, 23, 23, + 18, 14, 10, 16, 20, 23, 26, 25, 23, 20, 15, 18, 21, 25, 25, 24, 20, 14, 17, + 21, 25, 26, 24, 21, 14, 18, 21, 24, 28, 25, 22, 14, 18, 20, 25, 28, 26, 22, + 13, 17, 20, 23, 27, 26, 23, 17, 17, 19, 22, 25, 26, 22, 14, 17, 20, 23, 22, + 19, 15, 14, 16, 19, 22, 22, 20, 17, 12, 15, 18, 22, 22, 20, 17, 12, 15, 19, + 22, 22, 21, 18, 12, 16, 18, 21, 22, 21, 18, 12, 15, 18, 21, 21, 20, 18, 19, + 18, 17, 19, 19, 20, 18, 13, 15, 16, 16, 17, 14, 11, 12, 14, 15, 15, 16, 15, + 11, 11, 13, 14, 16, 16, 16, 12, 11, 13, 15, 15, 15, 15, 13, 9, 13, 15, 14, + 15, 15, 13, 14, 15, 14, 14, 14, 14, 13, 22, 20, 17, 13, 13, 13, 12, 11, 10, + 9, 9, 9, 9, 2, 10, 9, 9, 8, 9, 8, 3, 8, 8, 8, 9, 9, 9, 4, + 6, 8, 8, 9, 9, 8, 7, 7, 8, 9, 9, 9, 8, 6, 14, 16, 14, 13, 10, + 8, 7, 21, 23, 18, 13, 11, 9, 7, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 1, 2, 3, 2, 2, 2, 3, 4, 3, 4, 2, 5, 6, 7, 7, 7, 7, 6, + 11, 12, 11, 11, 9, 7, 13, 18, 19, 15, 13, 10, 8, 20, 22, 21, 17, 14, 11, + 9, 5, 5, 3, 3, 2, 0, 2, 5, 6, 4, 3, 2, 2, 3, 5, 8, 6, 6, + 5, 5, 4, 5, 9, 11, 10, 9, 9, 8, 9, 14, 17, 15, 14, 12, 8, 15, 19, + 23, 20, 15, 12, 10, 21, 23, 24, 21, 17, 13, 10, 9, 11, 7, 4, 3, 2, 1, + 9, 11, 9, 5, 3, 3, 3, 9, 11, 11, 8, 7, 6, 6, 9, 12, 15, 13, 11, + 10, 10, 12, 16, 20, 19, 16, 13, 11, 17, 21, 24, 24, 19, 15, 11, 21, 24, 25, + 25, 20, 16, 12, 12, 15, 18, 20, 20, 17, 15, 11, 14, 17, 20, 20, 18, 16, 10, + 13, 16, 20, 21, 20, 17, 10, 13, 17, 20, 23, 20, 18, 10, 14, 16, 20, 24, 21, + 18, 11, 13, 16, 19, 23, 22, 18, 18, 17, 16, 18, 21, 22, 18, 11, 13, 16, 18, + 17, 14, 11, 9, 12, 15, 17, 16, 15, 13, 8, 11, 15, 18, 17, 16, 14, 7, 11, + 15, 18, 17, 17, 14, 8, 11, 14, 17, 17, 16, 14, 12, 14, 15, 16, 16, 16, 14, + 20, 19, 17, 16, 15, 15, 14, 8, 11, 12, 12, 12, 10, 7, 7, 10, 11, 11, 11, + 10, 7, 7, 9, 10, 11, 11, 11, 8, 6, 9, 11, 11, 11, 11, 9, 7, 10, 11, + 11, 11, 11, 9, 16, 16, 15, 13, 11, 9, 9, 22, 21, 17, 14, 11, 9, 8, 6, + 6, 5, 5, 5, 6, 1, 6, 5, 4, 4, 4, 4, 2, 5, 3, 4, 5, 4, 4, + 3, 8, 3, 5, 6, 6, 6, 6, 8, 9, 9, 10, 10, 9, 7, 16, 17, 15, 14, + 11, 9, 7, 23, 24, 18, 15, 12, 10, 8, 3, 2, 2, 2, 2, 1, 1, 5, 3, + 2, 2, 2, 2, 2, 4, 4, 3, 4, 5, 5, 4, 5, 7, 7, 8, 9, 8, 7, + 8, 13, 13, 13, 12, 11, 8, 15, 19, 20, 17, 14, 12, 9, 22, 24, 23, 18, 16, + 13, 10, 7, 6, 4, 3, 3, 2, 0, 7, 8, 5, 4, 3, 3, 3, 7, 10, 7, + 8, 7, 6, 6, 7, 11, 13, 13, 11, 10, 9, 11, 16, 20, 19, 16, 13, 10, 17, + 21, 26, 24, 19, 14, 11, 22, 25, 28, 25, 21, 16, 12, 10, 13, 10, 6, 3, 2, + 2, 11, 13, 12, 7, 4, 4, 4, 11, 13, 16, 11, 9, 8, 7, 11, 15, 21, 17, + 14, 12, 11, 14, 21, 24, 24, 20, 16, 12, 19, 24, 30, 30, 22, 17, 13, 25, 29, + 31, 30, 25, 19, 14, 23, 27, 29, 32, 32, 30, 27, 22, 25, 28, 31, 31, 29, 26, + 21, 24, 27, 29, 31, 28, 26, 20, 23, 26, 29, 30, 29, 27, 20, 23, 26, 28, 30, + 29, 26, 19, 21, 25, 27, 30, 28, 27, 16, 20, 23, 27, 29, 28, 27, 22, 24, 27, + 29, 29, 26, 24, 20, 24, 27, 28, 28, 26, 24, 20, 22, 26, 28, 26, 25, 22, 18, + 22, 24, 27, 26, 26, 24, 18, 21, 24, 26, 26, 26, 24, 16, 19, 22, 24, 25, 25, + 24, 13, 17, 21, 24, 24, 24, 24, 19, 22, 23, 25, 25, 23, 20, 18, 21, 22, 23, + 23, 23, 19, 17, 20, 22, 22, 22, 22, 19, 15, 19, 21, 21, 22, 22, 20, 14, 18, + 20, 20, 21, 21, 20, 11, 16, 18, 18, 19, 20, 20, 13, 14, 16, 17, 18, 19, 19, + 17, 17, 17, 18, 18, 18, 8, 15, 15, 16, 16, 17, 16, 9, 13, 15, 15, 15, 16, + 15, 9, 9, 13, 14, 14, 14, 14, 12, 9, 12, 13, 13, 13, 13, 8, 10, 10, 10, + 11, 12, 12, 6, 13, 13, 9, 9, 10, 10, 6, 7, 9, 9, 9, 10, 6, 7, 4, + 7, 8, 8, 8, 6, 9, 4, 6, 6, 6, 6, 5, 7, 4, 4, 4, 4, 5, 4, + 7, 5, 4, 4, 4, 4, 3, 6, 7, 7, 7, 6, 4, 3, 5, 10, 10, 8, 6, + 5, 3, 3, 0, 2, 2, 2, 2, 5, 7, 0, 3, 2, 2, 2, 4, 8, 0, 4, + 3, 2, 1, 3, 6, 0, 3, 3, 2, 1, 2, 5, 2, 3, 5, 5, 3, 3, 3, + 5, 6, 9, 8, 5, 3, 3, 8, 8, 10, 9, 6, 4, 3, 4, 7, 6, 3, 2, + 3, 6, 4, 7, 7, 4, 2, 2, 5, 4, 7, 9, 4, 2, 0, 4, 4, 7, 10, + 5, 3, 2, 3, 4, 7, 11, 9, 5, 3, 3, 5, 9, 12, 11, 7, 4, 3, 7, + 11, 12, 12, 8, 5, 3, 28, 31, 34, 36, 36, 33, 31, 26, 29, 33, 36, 37, 35, + 32, 25, 29, 32, 35, 37, 34, 31, 24, 27, 31, 34, 36, 34, 32, 24, 27, 31, 34, + 37, 36, 31, 23, 25, 30, 33, 36, 35, 32, 20, 24, 28, 32, 35, 35, 32, 25, 29, + 32, 34, 34, 31, 27, 24, 27, 30, 33, 32, 30, 27, 22, 26, 29, 32, 32, 30, 28, + 22, 25, 29, 32, 32, 31, 28, 23, 24, 28, 32, 31, 31, 28, 20, 24, 27, 30, 30, + 31, 29, 17, 20, 25, 29, 29, 29, 28, 23, 26, 27, 28, 28, 26, 21, 22, 25, 27, + 26, 27, 25, 21, 21, 24, 25, 26, 25, 27, 22, 18, 23, 26, 24, 26, 25, 22, 16, + 22, 24, 24, 25, 24, 23, 13, 20, 22, 23, 23, 24, 22, 14, 17, 20, 22, 22, 23, + 21, 20, 20, 21, 22, 22, 19, 10, 18, 19, 20, 20, 21, 19, 11, 15, 18, 18, 18, + 19, 17, 12, 11, 18, 18, 18, 18, 17, 14, 12, 16, 17, 17, 17, 16, 11, 12, 14, + 14, 15, 15, 15, 8, 14, 13, 12, 13, 14, 13, 8, 10, 12, 13, 13, 12, 7, 10, + 6, 11, 11, 11, 11, 7, 10, 6, 10, 9, 9, 9, 7, 9, 6, 8, 8, 8, 9, + 6, 7, 7, 5, 7, 7, 7, 4, 7, 8, 7, 9, 8, 5, 4, 6, 10, 12, 12, + 9, 7, 5, 5, 3, 2, 2, 3, 4, 6, 8, 3, 0, 1, 1, 3, 7, 8, 3, + 2, 2, 2, 2, 5, 8, 3, 3, 5, 5, 2, 3, 6, 4, 5, 8, 7, 7, 5, + 5, 5, 9, 11, 9, 8, 6, 4, 11, 13, 12, 10, 8, 7, 4, 4, 8, 7, 4, + 3, 4, 7, 4, 8, 7, 5, 2, 4, 7, 4, 7, 9, 6, 2, 4, 6, 4, 8, + 10, 7, 6, 4, 4, 6, 9, 10, 9, 8, 7, 4, 8, 10, 12, 12, 9, 7, 5, + 11, 12, 13, 13, 10, 8, 6, 26, 29, 33, 35, 36, 33, 29, 25, 29, 32, 35, 35, + 33, 30, 23, 27, 31, 33, 35, 35, 30, 22, 26, 30, 34, 37, 34, 31, 23, 25, 29, + 33, 37, 34, 31, 23, 25, 29, 33, 37, 35, 31, 20, 24, 27, 32, 34, 34, 31, 23, + 27, 30, 33, 32, 28, 25, 23, 26, 29, 32, 32, 29, 25, 22, 24, 28, 31, 31, 29, + 26, 21, 25, 28, 31, 31, 29, 27, 21, 23, 27, 31, 31, 30, 26, 20, 23, 26, 29, + 30, 30, 26, 17, 21, 25, 27, 28, 29, 27, 22, 25, 26, 26, 26, 23, 19, 21, 24, + 25, 25, 25, 24, 18, 20, 22, 24, 24, 24, 24, 19, 17, 23, 24, 24, 25, 24, 20, + 15, 22, 23, 23, 24, 23, 20, 13, 20, 22, 22, 22, 22, 20, 15, 18, 20, 21, 21, + 21, 19, 19, 19, 19, 19, 19, 16, 7, 17, 18, 18, 18, 18, 15, 9, 13, 17, 17, + 17, 17, 15, 10, 10, 17, 17, 17, 17, 15, 13, 12, 16, 16, 16, 16, 14, 10, 12, + 14, 14, 14, 15, 14, 7, 15, 15, 12, 13, 13, 13, 5, 9, 11, 12, 11, 10, 5, + 7, 6, 11, 10, 10, 9, 5, 8, 6, 9, 9, 9, 8, 5, 7, 5, 7, 8, 8, + 8, 4, 6, 7, 5, 7, 7, 7, 5, 5, 9, 9, 11, 9, 7, 6, 5, 12, 14, + 14, 10, 8, 7, 5, 2, 2, 2, 2, 3, 4, 5, 2, 1, 0, 1, 2, 4, 5, + 2, 2, 2, 2, 2, 4, 6, 2, 4, 6, 6, 4, 4, 5, 4, 7, 11, 11, 9, + 7, 5, 7, 12, 17, 15, 11, 8, 5, 12, 16, 19, 18, 13, 9, 6, 4, 10, 9, + 4, 2, 3, 4, 4, 10, 12, 6, 1, 3, 4, 4, 10, 14, 8, 3, 3, 4, 4, + 11, 17, 12, 7, 5, 5, 7, 13, 19, 17, 12, 9, 6, 10, 17, 22, 21, 15, 10, + 7, 15, 19, 23, 23, 17, 11, 8, 26, 28, 32, 35, 35, 32, 29, 25, 27, 31, 34, + 35, 31, 29, 23, 26, 30, 34, 35, 33, 29, 22, 25, 30, 33, 36, 34, 31, 23, 25, + 29, 33, 37, 35, 29, 23, 25, 28, 32, 35, 34, 32, 20, 23, 27, 31, 34, 34, 31, + 23, 26, 29, 32, 31, 27, 23, 22, 25, 29, 32, 30, 27, 24, 22, 24, 28, 31, 31, + 29, 25, 21, 24, 27, 31, 31, 30, 25, 21, 24, 27, 30, 30, 29, 26, 20, 23, 26, + 30, 29, 29, 25, 18, 21, 24, 28, 27, 28, 25, 22, 24, 25, 25, 25, 23, 17, 20, + 22, 25, 25, 24, 22, 17, 19, 22, 24, 24, 24, 22, 17, 17, 23, 23, 23, 24, 23, + 19, 15, 23, 23, 24, 23, 23, 19, 13, 20, 22, 22, 22, 22, 19, 15, 19, 20, 20, + 21, 21, 18, 20, 19, 18, 18, 18, 15, 6, 17, 18, 18, 17, 17, 14, 8, 13, 17, + 17, 17, 16, 14, 10, 10, 17, 17, 17, 17, 14, 13, 12, 16, 16, 16, 15, 14, 10, + 13, 14, 14, 14, 14, 13, 7, 16, 16, 13, 13, 13, 13, 5, 9, 12, 11, 11, 9, + 4, 6, 6, 10, 10, 9, 8, 4, 8, 6, 9, 8, 9, 8, 4, 6, 5, 7, 9, + 8, 8, 4, 6, 7, 6, 7, 7, 7, 6, 5, 9, 10, 12, 10, 8, 7, 5, 13, + 16, 15, 12, 9, 8, 6, 2, 2, 2, 2, 2, 3, 4, 2, 1, 1, 0, 2, 3, + 4, 2, 2, 3, 3, 2, 3, 4, 2, 4, 7, 7, 5, 5, 5, 4, 8, 12, 11, + 9, 8, 6, 8, 13, 18, 16, 11, 8, 6, 14, 18, 20, 18, 13, 9, 7, 5, 8, + 7, 3, 1, 2, 3, 5, 8, 8, 4, 0, 2, 4, 5, 8, 10, 7, 4, 3, 4, + 5, 10, 14, 11, 8, 6, 6, 8, 13, 18, 17, 12, 9, 7, 11, 17, 22, 22, 15, + 11, 8, 16, 21, 23, 23, 18, 12, 8, 22, 25, 28, 31, 32, 29, 26, 21, 23, 27, + 31, 32, 27, 25, 19, 23, 26, 29, 32, 29, 27, 19, 23, 26, 30, 32, 30, 27, 20, + 22, 26, 29, 32, 31, 28, 19, 22, 25, 29, 32, 30, 27, 17, 20, 24, 27, 31, 31, + 27, 20, 23, 26, 29, 28, 24, 21, 18, 22, 25, 28, 27, 24, 21, 18, 20, 24, 27, + 27, 26, 21, 17, 21, 25, 27, 26, 25, 22, 19, 21, 24, 26, 26, 26, 22, 16, 20, + 22, 25, 26, 26, 23, 16, 18, 21, 24, 25, 24, 22, 18, 20, 21, 22, 23, 19, 15, + 17, 19, 21, 21, 21, 20, 15, 17, 19, 20, 20, 20, 20, 15, 15, 19, 20, 20, 21, + 20, 16, 14, 19, 20, 20, 20, 19, 16, 12, 17, 18, 19, 19, 18, 16, 17, 17, 17, + 17, 17, 17, 16, 16, 15, 15, 15, 16, 13, 4, 14, 14, 14, 14, 14, 12, 5, 12, + 14, 13, 14, 13, 12, 8, 8, 14, 14, 13, 13, 12, 10, 10, 13, 13, 13, 12, 11, + 7, 12, 12, 11, 11, 11, 11, 5, 17, 18, 14, 10, 10, 10, 5, 7, 8, 7, 7, + 7, 3, 4, 3, 7, 6, 6, 6, 3, 5, 3, 6, 5, 6, 5, 3, 4, 3, 4, + 5, 5, 5, 4, 4, 5, 7, 8, 8, 8, 7, 5, 9, 13, 14, 12, 9, 7, 6, + 15, 18, 18, 13, 11, 8, 6, 1, 2, 2, 2, 2, 2, 3, 2, 3, 2, 2, 0, + 3, 3, 2, 4, 3, 3, 3, 2, 3, 2, 6, 8, 7, 6, 5, 5, 6, 10, 13, + 12, 10, 8, 6, 11, 16, 19, 16, 12, 9, 7, 16, 20, 21, 18, 14, 10, 7, 6, + 7, 5, 3, 1, 2, 2, 6, 7, 7, 3, 2, 2, 3, 5, 7, 8, 5, 4, 3, + 3, 6, 8, 12, 10, 8, 7, 7, 9, 12, 16, 16, 13, 10, 7, 13, 17, 20, 21, + 15, 12, 8, 18, 21, 21, 21, 17, 13, 9, 17, 21, 24, 28, 28, 26, 22, 17, 19, + 24, 28, 28, 24, 21, 15, 19, 22, 25, 27, 25, 22, 15, 18, 21, 25, 29, 26, 22, + 15, 18, 21, 24, 28, 26, 23, 14, 17, 20, 24, 28, 26, 23, 15, 16, 19, 23, 25, + 27, 23, 16, 19, 22, 25, 24, 22, 18, 14, 18, 21, 23, 23, 21, 16, 13, 16, 20, + 22, 22, 20, 18, 13, 16, 20, 23, 22, 22, 19, 13, 16, 19, 22, 22, 21, 19, 12, + 14, 18, 21, 21, 21, 19, 17, 16, 17, 19, 20, 20, 18, 14, 16, 17, 18, 19, 17, + 13, 13, 15, 16, 17, 17, 16, 12, 12, 14, 15, 16, 16, 16, 12, 11, 14, 16, 16, + 16, 16, 13, 11, 14, 15, 15, 15, 15, 13, 12, 13, 14, 14, 14, 14, 13, 19, 18, + 14, 13, 13, 13, 12, 12, 11, 10, 11, 12, 12, 4, 11, 10, 10, 10, 10, 10, 3, + 9, 9, 9, 9, 9, 9, 4, 6, 9, 9, 9, 9, 9, 7, 7, 8, 8, 8, 8, + 7, 4, 12, 14, 12, 10, 8, 7, 4, 18, 20, 14, 12, 9, 7, 5, 4, 3, 3, + 3, 4, 3, 4, 1, 2, 2, 2, 2, 2, 3, 1, 1, 1, 2, 2, 2, 3, 1, + 5, 5, 5, 5, 4, 4, 5, 10, 9, 9, 9, 7, 5, 12, 15, 16, 13, 10, 8, + 6, 17, 20, 18, 14, 11, 9, 6, 4, 5, 3, 3, 2, 2, 3, 4, 6, 4, 3, + 2, 0, 2, 4, 7, 5, 5, 3, 3, 2, 4, 8, 9, 8, 7, 6, 5, 8, 12, + 14, 13, 11, 9, 6, 12, 16, 20, 17, 12, 10, 7, 18, 21, 21, 19, 14, 11, 8, + 8, 10, 6, 4, 3, 2, 2, 8, 10, 8, 5, 3, 2, 1, 8, 10, 10, 7, 5, + 4, 3, 9, 10, 14, 11, 9, 8, 7, 10, 14, 17, 16, 14, 11, 8, 14, 18, 21, + 21, 16, 12, 9, 19, 21, 23, 22, 18, 13, 10, 14, 16, 21, 24, 24, 21, 18, 13, + 16, 19, 23, 24, 20, 17, 11, 14, 18, 21, 23, 20, 18, 10, 14, 18, 21, 24, 21, + 18, 11, 14, 17, 20, 24, 22, 18, 10, 13, 16, 19, 23, 22, 18, 15, 14, 15, 18, + 22, 21, 18, 11, 14, 18, 21, 20, 17, 14, 11, 14, 17, 20, 20, 16, 13, 9, 12, + 15, 18, 18, 16, 14, 9, 12, 15, 18, 17, 17, 14, 9, 12, 15, 17, 17, 17, 14, + 11, 12, 13, 16, 16, 16, 14, 18, 16, 14, 15, 15, 15, 14, 10, 12, 14, 14, 16, + 13, 9, 9, 11, 12, 13, 13, 12, 8, 7, 10, 12, 11, 11, 12, 8, 7, 10, 11, + 11, 11, 11, 9, 6, 9, 11, 11, 10, 10, 9, 13, 13, 12, 10, 9, 9, 9, 19, + 17, 15, 11, 9, 8, 8, 8, 7, 6, 7, 8, 9, 3, 7, 6, 6, 6, 6, 6, + 2, 6, 5, 5, 5, 4, 4, 2, 4, 5, 4, 4, 4, 4, 4, 7, 8, 8, 7, + 7, 6, 4, 14, 15, 13, 11, 8, 7, 5, 19, 20, 15, 12, 9, 7, 6, 2, 2, + 1, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, + 3, 6, 6, 6, 6, 5, 5, 7, 11, 11, 10, 9, 8, 5, 13, 16, 16, 13, 11, + 9, 7, 19, 20, 19, 15, 12, 10, 7, 7, 6, 4, 3, 3, 3, 3, 7, 7, 5, + 4, 3, 2, 0, 7, 9, 6, 6, 4, 3, 3, 7, 10, 10, 10, 8, 7, 6, 9, + 14, 16, 15, 12, 10, 7, 15, 18, 22, 20, 14, 10, 8, 19, 21, 23, 21, 16, 12, + 9, 10, 12, 9, 5, 3, 3, 2, 10, 12, 11, 6, 3, 2, 2, 10, 12, 13, 9, + 6, 5, 4, 10, 13, 17, 13, 11, 9, 8, 13, 16, 21, 20, 16, 12, 9, 16, 21, + 25, 24, 18, 13, 10, 20, 23, 25, 26, 20, 15, 11, 24, 26, 29, 32, 32, 30, 26, + 23, 25, 28, 31, 31, 29, 26, 22, 24, 27, 29, 31, 28, 26, 20, 23, 26, 29, 30, + 29, 27, 20, 23, 26, 29, 31, 28, 27, 19, 22, 24, 27, 30, 29, 26, 16, 20, 24, + 26, 29, 29, 27, 22, 24, 27, 29, 28, 26, 23, 21, 24, 27, 29, 27, 25, 24, 19, + 23, 25, 27, 27, 25, 23, 18, 21, 25, 27, 25, 25, 25, 18, 21, 24, 27, 26, 25, + 25, 16, 19, 23, 25, 25, 25, 24, 13, 16, 20, 24, 24, 25, 24, 19, 23, 23, 24, + 25, 23, 19, 18, 21, 22, 23, 24, 22, 20, 17, 20, 22, 22, 22, 23, 19, 15, 19, + 21, 21, 22, 22, 20, 14, 19, 19, 20, 21, 22, 20, 11, 17, 18, 19, 20, 20, 19, + 13, 14, 16, 17, 18, 19, 19, 17, 17, 17, 18, 18, 18, 7, 15, 16, 16, 16, 17, + 16, 8, 13, 15, 15, 15, 15, 15, 10, 9, 14, 14, 14, 14, 14, 12, 9, 12, 12, + 13, 13, 14, 8, 10, 10, 10, 11, 11, 12, 6, 13, 13, 9, 9, 10, 10, 6, 8, + 8, 9, 10, 10, 6, 8, 4, 7, 7, 8, 8, 6, 9, 4, 6, 6, 5, 6, 5, + 8, 4, 4, 4, 4, 5, 5, 6, 5, 4, 4, 4, 4, 3, 6, 7, 7, 7, 6, + 4, 3, 5, 10, 10, 8, 6, 4, 3, 4, 0, 2, 2, 2, 2, 5, 7, 0, 3, + 2, 2, 2, 4, 8, 0, 4, 2, 2, 1, 4, 6, 0, 3, 3, 2, 1, 2, 5, + 2, 3, 5, 5, 3, 3, 4, 5, 6, 9, 8, 5, 3, 3, 8, 9, 10, 9, 6, + 4, 3, 4, 7, 6, 3, 2, 3, 6, 4, 7, 8, 4, 2, 2, 5, 4, 7, 9, + 4, 2, 0, 5, 4, 7, 10, 6, 3, 2, 3, 4, 7, 10, 9, 5, 4, 3, 5, + 9, 12, 11, 7, 4, 3, 7, 11, 12, 12, 8, 5, 3, 30, 32, 35, 39, 38, 37, + 32, 28, 32, 34, 37, 39, 36, 33, 27, 31, 33, 37, 38, 36, 32, 26, 29, 32, 35, + 38, 37, 34, 25, 28, 33, 36, 38, 37, 35, 24, 27, 31, 35, 38, 37, 35, 22, 25, + 31, 34, 36, 37, 34, 27, 31, 33, 36, 36, 32, 29, 26, 29, 33, 35, 34, 32, 28, + 24, 28, 32, 34, 35, 33, 30, 24, 27, 31, 34, 34, 33, 30, 23, 26, 29, 33, 32, + 33, 30, 21, 25, 29, 32, 32, 33, 30, 19, 22, 27, 30, 31, 31, 30, 24, 28, 28, + 29, 30, 28, 23, 23, 27, 28, 29, 29, 28, 22, 22, 25, 27, 28, 28, 28, 23, 20, + 25, 26, 27, 28, 27, 25, 17, 24, 25, 26, 26, 26, 24, 14, 23, 24, 24, 25, 26, + 24, 15, 19, 21, 23, 24, 25, 23, 22, 23, 23, 23, 23, 21, 11, 19, 21, 21, 21, + 22, 20, 12, 16, 20, 20, 20, 20, 19, 13, 12, 20, 19, 20, 19, 19, 16, 13, 17, + 18, 19, 19, 18, 12, 13, 15, 16, 17, 17, 17, 9, 15, 13, 14, 15, 16, 16, 8, + 10, 14, 14, 14, 14, 9, 11, 7, 12, 13, 13, 12, 9, 12, 7, 11, 11, 11, 11, + 7, 10, 7, 8, 10, 10, 10, 8, 9, 8, 6, 9, 8, 9, 6, 8, 9, 8, 8, + 7, 7, 4, 7, 11, 10, 9, 7, 5, 3, 6, 4, 3, 4, 4, 6, 8, 10, 4, + 2, 2, 2, 4, 7, 9, 4, 0, 1, 1, 3, 6, 8, 4, 1, 2, 1, 2, 4, + 7, 4, 3, 4, 4, 4, 3, 7, 6, 6, 8, 6, 5, 4, 5, 8, 9, 9, 6, + 5, 4, 4, 2, 5, 3, 2, 3, 6, 9, 2, 5, 4, 3, 2, 5, 9, 2, 5, + 5, 3, 0, 4, 7, 2, 5, 6, 2, 2, 3, 5, 2, 4, 7, 5, 4, 4, 4, + 5, 6, 8, 8, 5, 4, 4, 8, 8, 9, 9, 6, 5, 4, 29, 33, 36, 39, 39, + 36, 33, 28, 31, 34, 38, 38, 36, 32, 26, 29, 34, 37, 38, 35, 32, 25, 28, 31, + 36, 39, 36, 33, 25, 29, 31, 36, 39, 37, 34, 24, 27, 30, 34, 38, 37, 33, 22, + 26, 29, 33, 36, 37, 33, 26, 29, 34, 36, 34, 32, 29, 25, 29, 32, 36, 35, 32, + 27, 24, 27, 30, 34, 34, 31, 28, 23, 26, 30, 33, 33, 32, 28, 24, 27, 30, 32, + 32, 31, 29, 22, 25, 29, 32, 32, 32, 29, 19, 23, 27, 30, 30, 30, 28, 24, 27, + 28, 29, 30, 26, 22, 23, 25, 28, 28, 28, 27, 21, 22, 25, 27, 26, 27, 26, 21, + 18, 25, 25, 25, 26, 25, 21, 16, 24, 25, 25, 26, 25, 22, 13, 22, 24, 24, 24, + 24, 22, 15, 20, 22, 23, 23, 23, 20, 22, 22, 22, 22, 23, 19, 10, 18, 20, 21, + 22, 21, 18, 11, 15, 20, 20, 20, 19, 17, 12, 11, 19, 19, 19, 18, 16, 15, 13, + 17, 18, 18, 19, 16, 11, 13, 15, 16, 16, 16, 15, 8, 15, 14, 14, 15, 15, 14, + 6, 10, 14, 14, 14, 12, 6, 10, 7, 13, 12, 13, 11, 6, 11, 7, 11, 11, 11, + 10, 5, 8, 7, 8, 10, 10, 9, 5, 8, 8, 6, 9, 9, 8, 5, 6, 9, 8, + 9, 7, 7, 5, 6, 11, 12, 12, 9, 6, 5, 5, 3, 4, 4, 5, 4, 5, 7, + 3, 2, 2, 3, 3, 5, 6, 3, 1, 0, 0, 3, 5, 7, 2, 2, 4, 4, 2, + 4, 5, 4, 5, 9, 8, 8, 5, 5, 6, 10, 15, 13, 10, 6, 4, 10, 14, 17, + 15, 11, 8, 4, 2, 8, 8, 2, 3, 4, 6, 2, 8, 10, 4, 2, 4, 6, 2, + 8, 12, 5, 1, 3, 5, 2, 9, 14, 9, 5, 4, 5, 5, 11, 16, 14, 10, 8, + 4, 8, 14, 19, 18, 13, 9, 5, 13, 18, 19, 19, 15, 10, 6, 28, 32, 36, 38, + 38, 35, 33, 27, 30, 35, 37, 39, 36, 31, 26, 29, 33, 36, 39, 34, 32, 24, 27, + 31, 35, 37, 35, 32, 25, 27, 31, 35, 37, 36, 33, 23, 26, 30, 33, 37, 35, 33, + 21, 25, 29, 31, 35, 35, 32, 25, 29, 33, 37, 35, 31, 27, 25, 29, 31, 36, 34, + 32, 27, 24, 26, 31, 33, 33, 30, 26, 23, 25, 29, 32, 32, 30, 26, 22, 25, 29, + 32, 32, 31, 26, 21, 25, 27, 31, 30, 29, 27, 19, 22, 26, 30, 29, 28, 27, 24, + 26, 29, 29, 30, 27, 20, 22, 25, 28, 28, 28, 26, 20, 21, 23, 26, 26, 26, 24, + 19, 18, 25, 25, 24, 25, 23, 19, 16, 23, 24, 24, 24, 23, 20, 13, 22, 23, 23, + 23, 23, 20, 15, 20, 21, 21, 21, 22, 18, 20, 21, 21, 22, 23, 18, 11, 18, 20, + 20, 21, 21, 17, 11, 14, 19, 18, 19, 18, 15, 12, 11, 18, 18, 17, 18, 15, 14, + 12, 16, 17, 17, 17, 14, 11, 13, 15, 16, 16, 16, 13, 7, 14, 14, 14, 14, 15, + 13, 5, 9, 14, 13, 15, 12, 7, 11, 6, 13, 12, 13, 12, 6, 11, 6, 10, 11, + 10, 9, 4, 7, 6, 7, 10, 9, 8, 4, 7, 8, 6, 8, 8, 7, 4, 4, 9, + 8, 9, 8, 6, 4, 4, 11, 12, 12, 9, 6, 5, 4, 2, 4, 4, 5, 4, 6, + 8, 2, 2, 2, 3, 3, 5, 6, 2, 1, 0, 0, 3, 3, 5, 2, 2, 4, 4, + 2, 3, 4, 4, 5, 9, 8, 7, 5, 4, 6, 10, 15, 13, 9, 6, 4, 10, 14, + 16, 15, 10, 7, 4, 3, 7, 6, 2, 3, 5, 6, 3, 7, 7, 4, 2, 3, 4, + 3, 7, 8, 5, 1, 2, 4, 3, 8, 11, 9, 4, 4, 4, 5, 11, 15, 14, 9, + 7, 4, 8, 14, 19, 19, 12, 8, 5, 13, 17, 20, 20, 14, 9, 6, 24, 29, 32, + 35, 36, 33, 29, 23, 27, 31, 34, 35, 32, 28, 22, 25, 28, 33, 34, 31, 27, 20, + 22, 26, 30, 32, 30, 28, 21, 23, 26, 30, 34, 31, 27, 20, 22, 26, 29, 33, 31, + 27, 17, 21, 24, 27, 31, 32, 28, 22, 25, 30, 33, 31, 28, 25, 21, 23, 27, 31, + 32, 28, 23, 20, 22, 27, 29, 28, 26, 22, 19, 21, 24, 27, 27, 26, 22, 20, 21, + 24, 27, 27, 27, 22, 18, 20, 23, 25, 26, 26, 23, 14, 18, 22, 25, 25, 24, 22, + 20, 23, 24, 25, 27, 23, 19, 19, 21, 24, 24, 25, 22, 17, 18, 21, 22, 22, 22, + 21, 16, 16, 20, 21, 21, 21, 21, 16, 14, 20, 20, 20, 20, 19, 16, 11, 17, 19, + 19, 19, 19, 16, 14, 15, 17, 17, 18, 18, 15, 18, 18, 17, 18, 19, 17, 9, 15, + 16, 16, 17, 17, 15, 9, 12, 16, 15, 15, 14, 12, 8, 9, 16, 14, 13, 13, 12, + 11, 10, 14, 13, 13, 12, 11, 8, 11, 11, 11, 11, 11, 10, 4, 14, 14, 10, 10, + 10, 10, 3, 7, 9, 10, 10, 10, 6, 9, 4, 9, 8, 9, 9, 4, 9, 4, 7, + 6, 6, 6, 3, 5, 4, 6, 6, 5, 5, 2, 4, 6, 5, 5, 5, 5, 4, 3, + 7, 10, 11, 9, 6, 5, 3, 12, 14, 14, 10, 8, 6, 4, 1, 1, 1, 2, 4, + 5, 7, 1, 2, 2, 2, 3, 3, 4, 1, 3, 4, 3, 0, 2, 4, 1, 5, 5, + 4, 4, 3, 3, 3, 7, 10, 9, 8, 6, 4, 8, 12, 16, 13, 9, 6, 4, 13, + 16, 18, 15, 11, 7, 5, 5, 6, 5, 3, 2, 4, 5, 4, 6, 6, 4, 2, 2, + 3, 4, 6, 7, 3, 2, 1, 2, 4, 7, 9, 7, 6, 4, 4, 6, 9, 13, 13, + 10, 7, 5, 10, 14, 17, 17, 13, 9, 6, 15, 18, 18, 18, 14, 10, 6, 20, 24, + 28, 32, 32, 29, 25, 19, 23, 26, 31, 31, 28, 24, 17, 21, 25, 28, 30, 26, 23, + 17, 19, 23, 26, 29, 26, 23, 16, 18, 21, 25, 29, 27, 23, 15, 18, 21, 24, 27, + 26, 23, 12, 16, 19, 23, 26, 27, 23, 17, 21, 25, 29, 28, 24, 21, 16, 20, 24, + 28, 27, 24, 20, 16, 18, 23, 25, 25, 21, 18, 15, 17, 20, 23, 22, 22, 19, 14, + 17, 20, 22, 22, 22, 18, 12, 16, 18, 21, 21, 21, 18, 13, 14, 17, 20, 20, 20, + 19, 15, 18, 21, 22, 23, 20, 16, 14, 17, 19, 21, 21, 19, 15, 14, 16, 18, 18, + 18, 18, 13, 13, 16, 16, 16, 16, 16, 13, 12, 15, 16, 16, 16, 15, 13, 10, 12, + 14, 14, 14, 14, 13, 15, 15, 12, 12, 13, 13, 12, 14, 13, 13, 14, 15, 15, 7, + 13, 12, 12, 13, 13, 13, 6, 10, 11, 11, 10, 10, 10, 5, 6, 10, 9, 9, 9, + 9, 7, 7, 9, 8, 8, 8, 8, 4, 10, 10, 9, 7, 7, 7, 2, 15, 16, 11, + 8, 6, 5, 3, 5, 5, 6, 6, 7, 6, 7, 1, 3, 4, 5, 5, 4, 6, 1, + 2, 2, 2, 2, 2, 3, 1, 3, 2, 2, 2, 2, 2, 4, 7, 7, 6, 6, 4, + 2, 9, 12, 12, 10, 7, 5, 3, 14, 16, 15, 11, 9, 6, 4, 3, 4, 3, 3, + 3, 5, 6, 3, 5, 4, 3, 3, 3, 3, 3, 6, 5, 4, 2, 0, 2, 4, 6, + 6, 5, 4, 3, 3, 6, 9, 11, 10, 8, 6, 4, 10, 13, 16, 14, 10, 7, 4, + 14, 16, 18, 15, 11, 8, 5, 7, 8, 7, 4, 3, 4, 4, 6, 8, 8, 5, 3, + 2, 2, 7, 8, 9, 5, 3, 2, 1, 7, 8, 11, 8, 6, 5, 4, 8, 11, 14, + 14, 11, 8, 5, 12, 15, 18, 18, 13, 9, 6, 16, 18, 19, 19, 14, 10, 7, 17, + 20, 25, 28, 28, 26, 21, 15, 19, 23, 27, 28, 25, 20, 14, 18, 21, 25, 27, 22, + 19, 12, 16, 19, 22, 24, 22, 19, 12, 14, 17, 21, 24, 23, 19, 10, 14, 16, 20, + 23, 22, 19, 11, 12, 15, 19, 22, 22, 19, 14, 17, 22, 25, 24, 22, 17, 13, 16, + 20, 24, 23, 20, 16, 12, 15, 19, 21, 21, 18, 15, 10, 13, 16, 18, 19, 17, 14, + 10, 13, 15, 18, 18, 18, 15, 9, 11, 14, 17, 17, 17, 14, 13, 12, 13, 15, 16, + 16, 14, 12, 15, 16, 18, 19, 17, 13, 10, 13, 16, 16, 17, 16, 12, 9, 12, 14, + 14, 14, 14, 10, 8, 11, 12, 12, 12, 12, 10, 7, 10, 11, 11, 11, 11, 10, 11, + 10, 10, 10, 10, 10, 9, 14, 13, 10, 9, 9, 9, 8, 9, 9, 10, 11, 12, 13, + 7, 8, 8, 9, 9, 10, 10, 5, 7, 6, 7, 7, 6, 7, 3, 4, 6, 5, 5, + 5, 5, 4, 6, 6, 5, 4, 5, 4, 2, 11, 11, 9, 7, 5, 4, 2, 14, 14, + 10, 8, 6, 4, 3, 0, 1, 2, 3, 4, 5, 6, 2, 2, 2, 3, 3, 3, 4, + 2, 3, 3, 2, 2, 1, 2, 2, 6, 4, 3, 3, 3, 2, 6, 9, 8, 7, 6, + 5, 2, 10, 12, 12, 9, 7, 6, 3, 13, 14, 14, 11, 8, 6, 4, 6, 6, 5, + 4, 4, 4, 6, 6, 8, 6, 4, 3, 2, 3, 6, 8, 7, 5, 3, 2, 0, 6, + 9, 8, 6, 5, 4, 3, 8, 11, 13, 11, 9, 6, 4, 11, 14, 17, 15, 10, 7, + 5, 14, 16, 18, 16, 12, 8, 6, 9, 10, 8, 6, 4, 4, 4, 10, 10, 10, 6, + 4, 2, 2, 9, 10, 11, 6, 4, 3, 2, 9, 11, 14, 10, 7, 6, 5, 10, 13, + 17, 15, 11, 8, 6, 13, 16, 20, 19, 13, 9, 6, 16, 19, 20, 20, 15, 11, 7, + 24, 27, 29, 31, 31, 31, 27, 23, 26, 28, 31, 32, 28, 27, 21, 24, 27, 30, 31, + 28, 25, 20, 24, 27, 29, 30, 29, 27, 20, 23, 26, 28, 30, 28, 26, 18, 22, 24, + 27, 31, 29, 26, 16, 20, 24, 26, 29, 28, 26, 21, 24, 28, 29, 28, 26, 23, 21, + 23, 25, 28, 28, 26, 23, 19, 23, 26, 28, 26, 26, 24, 18, 21, 25, 26, 26, 26, + 25, 17, 21, 24, 26, 25, 26, 24, 16, 19, 22, 25, 26, 25, 24, 13, 16, 21, 24, + 24, 25, 24, 19, 23, 24, 24, 25, 23, 20, 18, 21, 22, 23, 23, 23, 19, 17, 21, + 22, 22, 22, 23, 19, 15, 20, 21, 21, 22, 22, 20, 14, 18, 20, 20, 21, 21, 20, + 11, 16, 18, 19, 20, 20, 20, 13, 14, 16, 17, 18, 19, 19, 17, 17, 18, 18, 18, + 18, 8, 15, 15, 16, 17, 17, 16, 9, 13, 15, 15, 15, 15, 15, 10, 9, 13, 14, + 14, 15, 15, 12, 9, 12, 13, 13, 13, 14, 8, 10, 10, 10, 11, 11, 12, 6, 13, + 13, 9, 9, 10, 11, 6, 8, 8, 9, 9, 10, 6, 8, 4, 7, 8, 8, 8, 6, + 9, 4, 6, 5, 6, 6, 5, 7, 4, 4, 4, 4, 5, 5, 7, 5, 4, 4, 4, + 4, 3, 6, 7, 7, 7, 6, 4, 3, 5, 10, 10, 8, 6, 4, 3, 4, 0, 2, + 2, 2, 2, 5, 7, 0, 3, 2, 2, 2, 4, 8, 0, 4, 3, 2, 1, 4, 6, + 0, 3, 3, 2, 1, 2, 5, 2, 3, 5, 5, 3, 3, 4, 5, 6, 9, 8, 4, + 3, 3, 8, 9, 10, 9, 6, 4, 3, 4, 7, 6, 3, 2, 3, 6, 4, 7, 8, + 4, 2, 2, 5, 4, 7, 9, 4, 2, 0, 5, 4, 7, 10, 6, 3, 2, 3, 4, + 7, 11, 9, 5, 3, 3, 5, 9, 12, 12, 7, 4, 3, 7, 10, 12, 13, 8, 5, + 3, 30, 34, 37, 40, 39, 38, 34, 29, 34, 37, 40, 40, 38, 34, 28, 32, 35, 39, + 38, 38, 34, 27, 29, 34, 37, 39, 36, 33, 25, 28, 32, 35, 39, 37, 33, 23, 28, + 31, 34, 38, 37, 34, 21, 25, 29, 33, 36, 36, 34, 28, 32, 35, 37, 37, 34, 31, + 26, 31, 34, 37, 36, 33, 31, 25, 29, 33, 34, 35, 33, 30, 24, 28, 31, 33, 33, + 33, 30, 23, 26, 29, 32, 33, 32, 30, 20, 24, 28, 31, 32, 32, 30, 18, 22, 26, + 30, 30, 30, 28, 25, 30, 32, 32, 32, 30, 25, 24, 27, 30, 31, 32, 30, 25, 22, + 26, 28, 29, 29, 28, 24, 20, 25, 26, 27, 27, 27, 24, 16, 23, 25, 26, 26, 27, + 24, 13, 22, 24, 23, 25, 25, 24, 13, 18, 21, 22, 23, 23, 22, 23, 24, 24, 25, + 26, 23, 14, 19, 22, 22, 23, 23, 22, 14, 16, 21, 21, 21, 23, 20, 15, 12, 19, + 19, 19, 19, 18, 15, 12, 17, 18, 18, 18, 17, 12, 12, 14, 15, 16, 16, 16, 9, + 14, 12, 13, 14, 15, 15, 7, 10, 15, 16, 16, 15, 11, 13, 7, 13, 14, 15, 14, + 10, 13, 7, 11, 12, 12, 12, 8, 12, 7, 8, 10, 10, 10, 7, 8, 7, 5, 8, + 8, 8, 5, 8, 8, 7, 6, 6, 6, 3, 8, 10, 9, 8, 6, 4, 3, 6, 3, + 5, 6, 6, 7, 9, 11, 3, 3, 4, 4, 6, 8, 10, 3, 1, 2, 2, 4, 6, + 9, 3, 0, 2, 2, 2, 5, 7, 3, 2, 3, 3, 3, 3, 6, 5, 5, 7, 5, + 3, 3, 4, 7, 8, 7, 5, 4, 3, 3, 2, 4, 4, 2, 5, 7, 10, 2, 4, + 5, 3, 4, 6, 9, 2, 5, 6, 3, 2, 5, 6, 2, 4, 5, 3, 1, 2, 5, + 2, 4, 6, 5, 3, 3, 3, 4, 5, 7, 7, 4, 3, 3, 7, 7, 8, 9, 5, + 3, 3, 33, 36, 41, 43, 44, 41, 38, 31, 35, 39, 43, 44, 41, 37, 30, 35, 37, + 41, 43, 38, 35, 29, 33, 35, 39, 41, 38, 34, 27, 29, 33, 38, 40, 37, 33, 25, + 28, 32, 36, 40, 38, 34, 23, 26, 32, 34, 37, 38, 35, 30, 34, 38, 40, 40, 37, + 33, 29, 33, 36, 40, 40, 37, 32, 26, 32, 35, 39, 38, 35, 32, 26, 29, 32, 36, + 35, 33, 31, 25, 27, 30, 34, 34, 33, 29, 22, 26, 29, 33, 32, 32, 30, 19, 24, + 27, 31, 31, 32, 29, 27, 31, 34, 34, 34, 32, 27, 26, 29, 32, 33, 33, 32, 26, + 24, 28, 30, 31, 31, 30, 24, 20, 27, 27, 28, 28, 27, 23, 16, 25, 26, 27, 27, + 26, 23, 13, 24, 24, 25, 25, 26, 23, 14, 21, 23, 23, 24, 24, 22, 23, 25, 26, + 27, 28, 25, 17, 20, 24, 25, 26, 25, 22, 16, 15, 23, 23, 23, 23, 21, 17, 12, + 20, 20, 20, 19, 18, 16, 12, 17, 19, 19, 19, 16, 13, 13, 14, 17, 17, 17, 16, + 9, 14, 12, 15, 16, 16, 15, 7, 11, 17, 18, 19, 17, 12, 16, 8, 15, 16, 17, + 16, 10, 16, 8, 12, 14, 14, 13, 8, 12, 8, 8, 11, 11, 10, 7, 9, 8, 5, + 10, 10, 9, 5, 6, 8, 7, 7, 7, 7, 4, 8, 10, 9, 8, 6, 6, 3, 5, + 3, 7, 8, 9, 8, 10, 13, 3, 5, 6, 7, 7, 9, 10, 3, 2, 4, 4, 5, + 6, 8, 3, 2, 0, 0, 3, 6, 6, 3, 2, 5, 5, 4, 3, 5, 5, 6, 11, + 10, 6, 3, 5, 7, 11, 13, 11, 8, 4, 4, 1, 7, 7, 4, 7, 9, 10, 1, + 7, 9, 3, 6, 7, 9, 1, 7, 11, 4, 3, 5, 6, 1, 7, 11, 6, 1, 2, + 5, 1, 7, 12, 10, 7, 4, 3, 4, 10, 13, 13, 10, 5, 3, 9, 13, 14, 15, + 11, 7, 3, 33, 36, 40, 42, 44, 41, 37, 30, 34, 38, 44, 43, 40, 35, 29, 33, + 38, 41, 42, 38, 34, 28, 31, 35, 37, 40, 37, 32, 26, 28, 32, 35, 39, 36, 33, + 25, 27, 30, 34, 38, 36, 33, 23, 26, 30, 33, 36, 36, 33, 29, 33, 36, 41, 38, + 36, 32, 28, 32, 36, 39, 38, 35, 31, 26, 30, 33, 37, 36, 33, 29, 25, 27, 32, + 34, 34, 31, 28, 24, 26, 30, 32, 33, 32, 28, 22, 25, 28, 31, 31, 31, 28, 18, + 23, 27, 29, 30, 30, 27, 27, 31, 33, 33, 34, 31, 25, 25, 28, 31, 32, 32, 30, + 23, 22, 27, 29, 30, 30, 28, 22, 19, 25, 26, 26, 27, 26, 21, 15, 25, 25, 26, + 25, 24, 21, 12, 23, 24, 24, 24, 23, 21, 13, 20, 21, 22, 23, 22, 19, 22, 24, + 25, 25, 27, 23, 16, 18, 22, 24, 24, 24, 21, 15, 14, 21, 23, 22, 21, 18, 15, + 12, 19, 19, 19, 19, 15, 15, 12, 16, 19, 18, 17, 14, 12, 13, 14, 16, 16, 16, + 14, 8, 13, 12, 14, 15, 15, 14, 5, 10, 17, 17, 18, 16, 12, 16, 7, 15, 16, + 16, 15, 9, 16, 7, 11, 14, 13, 12, 7, 11, 7, 7, 11, 10, 9, 4, 7, 7, + 5, 10, 9, 8, 3, 5, 8, 7, 7, 7, 7, 3, 5, 10, 9, 8, 5, 5, 2, + 4, 2, 7, 8, 8, 8, 10, 13, 2, 5, 6, 7, 7, 8, 10, 2, 1, 4, 4, + 4, 5, 6, 2, 2, 0, 0, 2, 4, 5, 3, 2, 5, 5, 4, 2, 4, 5, 6, + 11, 10, 6, 3, 3, 7, 10, 13, 12, 7, 4, 3, 2, 6, 6, 4, 7, 9, 10, + 1, 6, 7, 3, 6, 6, 7, 1, 6, 8, 4, 2, 3, 5, 1, 6, 8, 5, 1, + 2, 3, 1, 7, 11, 11, 6, 4, 3, 4, 10, 15, 15, 9, 5, 2, 9, 13, 16, + 16, 11, 6, 3, 28, 32, 36, 40, 41, 36, 33, 27, 31, 35, 39, 40, 35, 32, 26, + 29, 34, 36, 39, 35, 30, 24, 27, 31, 34, 36, 32, 29, 22, 25, 28, 31, 34, 32, + 29, 21, 24, 26, 30, 33, 32, 29, 19, 22, 25, 28, 33, 31, 29, 26, 29, 34, 37, + 35, 33, 29, 25, 28, 32, 36, 35, 32, 28, 23, 27, 31, 34, 33, 30, 25, 22, 25, + 28, 30, 30, 28, 24, 20, 22, 25, 28, 28, 27, 23, 19, 22, 24, 27, 27, 27, 24, + 16, 19, 23, 26, 25, 26, 24, 23, 26, 29, 29, 31, 28, 23, 22, 26, 28, 28, 29, + 26, 21, 20, 23, 26, 25, 26, 25, 19, 17, 22, 22, 22, 23, 22, 18, 13, 21, 21, + 21, 21, 21, 17, 11, 19, 20, 20, 20, 19, 17, 12, 17, 18, 19, 19, 19, 16, 20, + 21, 22, 22, 24, 22, 15, 16, 20, 20, 21, 22, 19, 13, 13, 18, 19, 18, 18, 16, + 13, 10, 16, 15, 15, 15, 13, 12, 9, 14, 15, 14, 14, 12, 9, 10, 12, 12, 12, + 12, 11, 6, 12, 10, 11, 11, 11, 11, 4, 8, 14, 14, 15, 14, 11, 14, 5, 12, + 12, 13, 13, 8, 13, 5, 10, 10, 10, 10, 6, 8, 5, 5, 7, 6, 6, 3, 5, + 5, 4, 5, 5, 5, 2, 3, 6, 6, 7, 5, 3, 2, 4, 8, 9, 9, 6, 4, + 2, 3, 1, 4, 5, 6, 8, 9, 12, 1, 2, 4, 5, 6, 7, 8, 1, 2, 2, + 2, 4, 4, 5, 1, 2, 4, 2, 0, 3, 4, 2, 4, 6, 6, 4, 2, 3, 4, + 8, 12, 10, 6, 3, 2, 8, 11, 13, 11, 7, 4, 2, 4, 5, 4, 4, 6, 8, + 9, 4, 5, 5, 4, 5, 6, 6, 4, 6, 6, 3, 2, 3, 3, 3, 7, 8, 4, + 3, 1, 2, 4, 6, 9, 9, 7, 4, 2, 6, 10, 13, 13, 9, 5, 2, 11, 13, + 14, 14, 10, 6, 3, 25, 28, 32, 36, 36, 34, 29, 23, 26, 31, 35, 35, 31, 28, + 22, 25, 29, 33, 33, 30, 25, 20, 23, 27, 30, 33, 28, 24, 17, 20, 23, 26, 29, + 27, 24, 16, 19, 22, 25, 28, 27, 24, 14, 17, 21, 24, 28, 27, 24, 21, 25, 29, + 32, 32, 28, 25, 21, 24, 28, 31, 32, 27, 23, 18, 22, 27, 29, 29, 25, 22, 19, + 20, 24, 27, 26, 24, 20, 16, 18, 20, 23, 23, 22, 20, 14, 17, 19, 22, 22, 22, + 19, 11, 14, 18, 21, 21, 21, 20, 19, 22, 25, 26, 27, 25, 20, 18, 21, 24, 25, + 24, 23, 19, 17, 20, 22, 22, 22, 22, 16, 15, 18, 18, 18, 19, 19, 14, 11, 16, + 16, 16, 16, 16, 14, 9, 14, 15, 15, 15, 15, 14, 9, 12, 13, 13, 14, 14, 13, + 17, 17, 18, 18, 20, 19, 12, 15, 15, 17, 17, 17, 16, 10, 11, 15, 15, 15, 14, + 14, 9, 7, 12, 11, 11, 11, 11, 9, 7, 10, 9, 9, 9, 8, 6, 8, 7, 8, + 8, 8, 7, 3, 9, 9, 6, 6, 6, 6, 3, 7, 9, 9, 10, 11, 10, 12, 3, + 8, 8, 9, 9, 7, 10, 3, 6, 6, 6, 6, 5, 6, 3, 3, 3, 2, 2, 2, + 3, 2, 4, 3, 3, 3, 1, 3, 5, 7, 7, 6, 4, 2, 2, 7, 9, 9, 7, + 5, 3, 2, 2, 3, 4, 5, 6, 8, 10, 2, 3, 4, 5, 5, 6, 7, 2, 4, + 4, 3, 3, 3, 4, 2, 5, 5, 4, 3, 0, 2, 2, 6, 8, 6, 5, 3, 2, + 6, 9, 12, 9, 6, 4, 1, 9, 11, 12, 11, 7, 5, 2, 6, 8, 6, 4, 6, + 7, 8, 6, 8, 7, 5, 5, 5, 5, 6, 8, 9, 4, 2, 2, 3, 6, 9, 11, + 5, 3, 2, 1, 6, 8, 10, 10, 7, 5, 2, 8, 11, 13, 12, 8, 5, 3, 10, + 13, 14, 14, 10, 6, 4, 20, 24, 28, 32, 31, 29, 25, 19, 23, 27, 31, 31, 28, + 24, 18, 21, 25, 28, 31, 27, 22, 17, 19, 22, 26, 28, 25, 19, 13, 16, 19, 22, + 26, 23, 20, 11, 15, 17, 20, 24, 23, 19, 10, 13, 16, 19, 23, 23, 20, 18, 22, + 25, 29, 28, 25, 21, 17, 21, 24, 27, 28, 24, 20, 15, 19, 23, 25, 24, 22, 18, + 14, 17, 19, 22, 22, 20, 16, 11, 14, 16, 18, 19, 19, 15, 10, 12, 15, 18, 18, + 18, 15, 7, 10, 14, 16, 16, 16, 15, 15, 19, 20, 22, 23, 21, 17, 14, 17, 20, + 21, 21, 19, 15, 13, 16, 18, 18, 18, 18, 13, 12, 14, 15, 14, 14, 14, 10, 9, + 11, 12, 12, 12, 11, 10, 5, 10, 11, 10, 11, 11, 11, 6, 8, 10, 9, 9, 9, + 9, 13, 13, 14, 15, 16, 16, 10, 12, 12, 12, 13, 13, 13, 8, 9, 10, 11, 10, + 10, 10, 7, 5, 8, 7, 7, 7, 7, 6, 4, 5, 5, 4, 4, 4, 3, 5, 4, + 3, 3, 3, 3, 2, 6, 6, 3, 2, 2, 2, 1, 4, 5, 6, 7, 7, 9, 10, + 2, 4, 5, 6, 6, 7, 8, 2, 3, 4, 4, 4, 4, 5, 2, 3, 3, 2, 2, + 1, 2, 1, 6, 4, 3, 3, 2, 1, 5, 6, 6, 4, 3, 2, 0, 5, 7, 7, + 5, 4, 3, 1, 5, 5, 5, 5, 6, 8, 9, 5, 6, 5, 5, 5, 5, 6, 5, + 7, 5, 4, 3, 3, 3, 5, 7, 6, 5, 4, 3, 0, 6, 8, 8, 6, 4, 3, + 1, 6, 9, 11, 8, 5, 3, 2, 7, 9, 11, 10, 6, 4, 2, 7, 9, 7, 5, + 6, 7, 7, 8, 10, 9, 5, 5, 5, 5, 8, 10, 10, 5, 3, 2, 2, 8, 9, + 11, 7, 4, 3, 2, 8, 9, 12, 10, 6, 4, 2, 8, 10, 14, 13, 8, 4, 3, + 9, 12, 14, 14, 9, 5, 3, 27, 31, 32, 35, 35, 33, 30, 25, 29, 33, 35, 35, + 32, 29, 23, 27, 30, 33, 34, 31, 29, 23, 26, 28, 31, 33, 28, 26, 20, 23, 25, + 28, 30, 28, 26, 18, 22, 24, 27, 30, 28, 26, 15, 19, 22, 26, 28, 28, 26, 24, + 28, 30, 33, 32, 30, 27, 23, 27, 30, 31, 31, 29, 26, 21, 25, 28, 31, 30, 28, + 26, 20, 24, 27, 28, 28, 25, 23, 18, 20, 23, 25, 25, 26, 23, 16, 18, 22, 25, + 25, 24, 23, 12, 15, 20, 23, 24, 24, 23, 22, 25, 27, 27, 28, 26, 23, 20, 24, + 26, 28, 28, 26, 22, 18, 23, 25, 25, 24, 26, 22, 17, 20, 22, 22, 22, 24, 20, + 12, 18, 19, 20, 20, 21, 19, 9, 15, 17, 18, 19, 20, 19, 10, 12, 15, 16, 17, + 19, 19, 18, 20, 20, 22, 22, 22, 12, 16, 18, 19, 20, 21, 20, 13, 13, 17, 17, + 18, 18, 18, 13, 9, 14, 14, 14, 15, 15, 12, 8, 12, 12, 12, 12, 13, 8, 9, + 9, 9, 10, 11, 11, 6, 10, 10, 7, 8, 9, 9, 7, 9, 11, 12, 13, 13, 10, + 12, 4, 9, 10, 11, 11, 9, 12, 4, 8, 8, 8, 9, 8, 10, 4, 4, 5, 5, + 5, 6, 6, 3, 2, 2, 2, 2, 3, 6, 5, 5, 5, 4, 2, 2, 6, 8, 8, + 6, 4, 2, 1, 5, 2, 3, 4, 4, 7, 9, 11, 2, 4, 4, 4, 6, 8, 9, + 2, 4, 4, 4, 3, 6, 8, 2, 3, 3, 3, 2, 2, 6, 0, 3, 4, 3, 2, + 1, 5, 3, 4, 7, 5, 2, 1, 3, 6, 7, 8, 7, 3, 2, 1, 5, 8, 7, + 5, 5, 8, 9, 5, 8, 9, 6, 4, 6, 9, 5, 8, 10, 6, 4, 3, 6, 5, + 7, 10, 5, 2, 2, 3, 4, 6, 9, 7, 3, 2, 1, 4, 7, 10, 9, 5, 2, + 1, 5, 9, 10, 10, 6, 3, 1, 34, 37, 40, 44, 42, 41, 38, 33, 35, 39, 43, + 43, 40, 37, 30, 34, 38, 41, 43, 39, 36, 29, 32, 35, 39, 41, 37, 33, 26, 30, + 32, 35, 39, 34, 33, 23, 26, 30, 33, 36, 37, 33, 21, 25, 29, 33, 36, 36, 34, + 31, 35, 38, 42, 40, 37, 35, 29, 33, 37, 40, 41, 36, 33, 28, 31, 34, 38, 38, + 36, 31, 26, 29, 33, 35, 35, 34, 29, 23, 26, 29, 32, 31, 31, 28, 20, 24, 27, + 30, 31, 33, 29, 17, 21, 26, 29, 30, 30, 29, 27, 31, 33, 36, 36, 33, 29, 26, + 30, 32, 34, 34, 33, 28, 24, 28, 31, 32, 33, 32, 27, 21, 27, 27, 28, 29, 28, + 24, 15, 23, 25, 25, 25, 25, 25, 12, 21, 23, 24, 24, 24, 24, 12, 18, 21, 22, + 22, 23, 22, 25, 26, 27, 29, 28, 28, 19, 20, 23, 26, 26, 27, 24, 18, 16, 22, + 24, 24, 24, 23, 17, 12, 20, 20, 20, 21, 20, 17, 11, 16, 17, 17, 17, 17, 13, + 11, 13, 15, 15, 16, 15, 10, 12, 10, 12, 14, 14, 14, 8, 12, 17, 18, 19, 20, + 16, 19, 8, 15, 17, 18, 18, 13, 18, 8, 13, 15, 15, 15, 11, 15, 8, 8, 11, + 10, 11, 8, 9, 6, 3, 8, 7, 8, 6, 7, 7, 5, 4, 5, 5, 5, 8, 8, + 7, 5, 3, 3, 4, 7, 3, 7, 8, 10, 11, 14, 16, 3, 6, 7, 8, 10, 12, + 13, 3, 3, 5, 5, 7, 9, 11, 3, 2, 2, 2, 4, 6, 8, 3, 0, 3, 2, + 1, 4, 7, 3, 3, 4, 3, 2, 3, 7, 5, 6, 5, 4, 2, 1, 5, 4, 6, + 6, 6, 10, 12, 14, 4, 6, 7, 5, 8, 10, 11, 3, 6, 7, 4, 4, 7, 9, + 4, 5, 7, 3, 2, 3, 5, 2, 4, 5, 4, 2, 1, 5, 3, 4, 6, 5, 3, + 2, 4, 4, 5, 6, 6, 3, 2, 2, 38, 41, 46, 49, 49, 47, 45, 37, 41, 44, + 48, 50, 45, 41, 35, 38, 43, 46, 48, 44, 40, 33, 36, 39, 43, 46, 43, 36, 31, + 33, 37, 40, 43, 41, 36, 27, 30, 35, 38, 41, 40, 36, 25, 28, 33, 37, 40, 40, + 37, 35, 40, 42, 46, 46, 42, 37, 33, 37, 42, 46, 46, 41, 37, 31, 36, 40, 43, + 44, 40, 35, 30, 33, 37, 39, 40, 38, 33, 25, 30, 33, 36, 37, 36, 32, 22, 27, + 32, 34, 35, 35, 32, 18, 25, 30, 33, 33, 34, 32, 31, 36, 38, 39, 41, 37, 32, + 29, 35, 37, 38, 39, 36, 31, 27, 33, 34, 36, 36, 35, 29, 23, 31, 32, 32, 33, + 31, 25, 17, 27, 28, 28, 28, 27, 25, 14, 25, 26, 27, 27, 27, 26, 13, 22, 25, + 25, 26, 26, 24, 26, 30, 31, 32, 33, 31, 23, 22, 28, 30, 31, 30, 29, 22, 19, + 25, 27, 28, 28, 26, 22, 15, 22, 24, 24, 24, 22, 20, 13, 17, 21, 21, 21, 18, + 17, 13, 14, 18, 19, 19, 18, 13, 13, 11, 17, 17, 18, 17, 10, 14, 21, 22, 24, + 23, 19, 23, 10, 19, 21, 21, 21, 15, 22, 10, 15, 19, 18, 18, 13, 17, 10, 9, + 15, 15, 15, 10, 12, 8, 5, 12, 12, 11, 7, 9, 9, 6, 9, 9, 9, 7, 8, + 9, 7, 7, 7, 7, 7, 7, 5, 11, 13, 13, 14, 17, 20, 5, 8, 11, 12, 13, + 14, 16, 5, 4, 9, 9, 10, 11, 12, 5, 3, 5, 5, 6, 8, 8, 4, 3, 0, + 0, 3, 6, 7, 4, 3, 6, 5, 1, 5, 8, 6, 5, 7, 6, 2, 4, 6, 4, + 5, 5, 9, 13, 15, 16, 4, 6, 7, 8, 11, 13, 14, 4, 5, 9, 5, 8, 9, + 11, 4, 5, 9, 4, 3, 6, 7, 2, 4, 7, 5, 2, 3, 7, 2, 5, 8, 7, + 4, 3, 5, 4, 7, 8, 8, 5, 1, 4, 36, 40, 45, 47, 48, 45, 42, 35, 40, + 43, 48, 47, 44, 40, 33, 37, 42, 45, 46, 43, 39, 32, 35, 39, 43, 44, 40, 35, + 30, 32, 35, 39, 41, 38, 35, 27, 29, 32, 36, 40, 38, 34, 23, 28, 32, 34, 38, + 38, 34, 34, 38, 41, 45, 46, 41, 37, 33, 35, 40, 44, 44, 38, 35, 31, 35, 39, + 42, 42, 38, 33, 28, 32, 35, 39, 38, 35, 31, 24, 29, 32, 34, 36, 33, 30, 20, + 27, 30, 33, 33, 32, 30, 17, 24, 29, 32, 31, 31, 30, 31, 35, 36, 38, 38, 37, + 30, 28, 34, 36, 36, 38, 35, 29, 25, 32, 35, 34, 34, 33, 26, 21, 29, 31, 31, + 30, 30, 23, 15, 26, 27, 28, 27, 25, 24, 12, 23, 26, 27, 25, 25, 24, 12, 21, + 24, 24, 24, 24, 22, 25, 30, 29, 32, 31, 29, 23, 20, 27, 29, 29, 29, 26, 21, + 17, 26, 27, 26, 26, 23, 20, 14, 21, 23, 23, 22, 20, 19, 12, 17, 20, 20, 19, + 16, 15, 12, 13, 18, 18, 18, 15, 12, 12, 10, 16, 16, 17, 15, 8, 12, 20, 22, + 22, 21, 17, 22, 9, 18, 19, 21, 20, 14, 21, 9, 14, 18, 17, 17, 11, 16, 9, + 8, 15, 14, 13, 8, 11, 8, 4, 12, 11, 9, 5, 8, 7, 5, 9, 9, 8, 4, + 6, 8, 6, 7, 7, 7, 4, 5, 5, 11, 12, 13, 13, 15, 19, 5, 7, 11, 11, + 12, 13, 14, 5, 4, 9, 8, 9, 10, 11, 5, 3, 5, 5, 6, 6, 6, 3, 2, + 0, 0, 2, 4, 5, 3, 3, 6, 5, 1, 3, 5, 5, 5, 7, 7, 2, 3, 4, + 4, 5, 5, 9, 12, 14, 15, 4, 5, 5, 8, 10, 12, 12, 4, 5, 6, 5, 7, + 8, 9, 4, 4, 6, 3, 3, 4, 5, 2, 4, 7, 6, 1, 3, 4, 1, 5, 11, + 11, 4, 1, 4, 4, 8, 12, 12, 6, 1, 3, 33, 37, 41, 43, 44, 41, 38, 31, + 35, 39, 43, 44, 39, 36, 29, 34, 37, 42, 42, 38, 33, 28, 31, 34, 39, 41, 36, + 30, 26, 28, 31, 35, 37, 33, 31, 23, 24, 28, 32, 35, 34, 30, 21, 24, 27, 30, + 35, 34, 30, 30, 33, 38, 41, 40, 37, 32, 29, 31, 36, 40, 41, 37, 31, 28, 30, + 35, 37, 37, 34, 29, 26, 28, 31, 34, 34, 32, 26, 22, 25, 27, 30, 31, 29, 25, + 19, 23, 26, 29, 29, 28, 25, 14, 21, 25, 27, 27, 27, 25, 28, 31, 33, 34, 35, + 33, 28, 26, 30, 32, 33, 33, 31, 25, 22, 28, 30, 29, 30, 29, 23, 19, 27, 27, + 26, 28, 25, 19, 13, 22, 24, 23, 23, 22, 19, 10, 20, 22, 21, 21, 21, 20, 9, + 18, 20, 20, 20, 20, 18, 23, 26, 26, 27, 27, 27, 20, 18, 24, 25, 25, 26, 23, + 18, 15, 22, 23, 23, 22, 21, 17, 12, 19, 19, 19, 20, 17, 15, 10, 14, 16, 15, + 15, 13, 12, 9, 10, 15, 14, 14, 12, 9, 9, 7, 13, 13, 13, 12, 6, 11, 18, + 18, 19, 19, 15, 19, 7, 16, 16, 18, 17, 12, 18, 7, 12, 15, 14, 14, 10, 13, + 7, 7, 11, 11, 10, 6, 8, 5, 2, 7, 7, 6, 4, 5, 5, 3, 5, 4, 5, + 3, 4, 5, 4, 3, 3, 3, 3, 4, 3, 9, 9, 10, 12, 13, 17, 3, 7, 9, + 9, 11, 11, 12, 3, 4, 8, 7, 8, 8, 9, 3, 3, 4, 4, 4, 5, 4, 2, + 1, 3, 2, 0, 3, 4, 2, 3, 5, 4, 2, 2, 4, 3, 4, 5, 5, 3, 1, + 3, 4, 5, 6, 9, 11, 13, 13, 4, 5, 6, 8, 9, 10, 10, 4, 5, 6, 6, + 6, 7, 7, 4, 3, 5, 2, 2, 3, 3, 2, 3, 6, 5, 3, 1, 3, 2, 5, + 7, 6, 3, 2, 3, 4, 6, 7, 7, 4, 2, 2, 26, 31, 35, 39, 39, 35, 33, + 26, 30, 33, 39, 38, 36, 31, 24, 29, 32, 36, 37, 33, 29, 23, 26, 30, 33, 34, + 31, 26, 20, 24, 26, 29, 32, 29, 26, 18, 20, 23, 26, 30, 30, 26, 17, 18, 22, + 26, 29, 29, 26, 24, 28, 32, 36, 35, 33, 29, 24, 26, 31, 35, 34, 30, 27, 22, + 25, 29, 33, 31, 29, 24, 21, 24, 27, 29, 29, 27, 21, 18, 20, 23, 25, 25, 24, + 21, 16, 19, 21, 23, 23, 24, 21, 13, 17, 20, 23, 22, 22, 22, 22, 25, 28, 28, + 30, 28, 24, 21, 24, 27, 27, 28, 27, 22, 20, 23, 25, 25, 25, 25, 20, 17, 21, + 22, 21, 22, 22, 16, 11, 18, 18, 18, 18, 18, 16, 7, 17, 17, 16, 16, 17, 16, + 8, 15, 15, 15, 16, 16, 14, 20, 20, 20, 21, 23, 23, 16, 16, 19, 20, 20, 21, + 19, 14, 13, 18, 18, 18, 17, 17, 13, 9, 15, 15, 14, 14, 14, 11, 7, 12, 11, + 10, 10, 10, 8, 7, 8, 10, 9, 9, 9, 5, 7, 5, 8, 8, 7, 8, 3, 8, + 12, 13, 14, 14, 13, 15, 4, 11, 11, 12, 13, 10, 13, 4, 10, 9, 9, 9, 8, + 9, 4, 5, 6, 6, 5, 4, 5, 3, 2, 2, 2, 2, 2, 3, 3, 2, 3, 2, + 1, 2, 3, 4, 3, 5, 3, 2, 0, 3, 3, 6, 7, 8, 9, 11, 13, 3, 5, + 7, 8, 8, 9, 10, 3, 3, 5, 5, 6, 6, 6, 3, 3, 3, 2, 2, 3, 3, + 1, 4, 6, 4, 3, 0, 3, 2, 5, 8, 5, 3, 2, 2, 4, 7, 8, 7, 4, + 2, 2, 4, 6, 6, 7, 8, 10, 11, 4, 6, 6, 6, 7, 8, 8, 4, 6, 7, + 4, 4, 4, 6, 4, 6, 8, 4, 2, 1, 2, 3, 8, 9, 7, 4, 2, 2, 6, + 8, 10, 9, 5, 3, 0, 7, 9, 10, 9, 6, 4, 2, 21, 26, 31, 32, 34, 32, + 27, 20, 24, 28, 32, 34, 30, 25, 19, 22, 27, 30, 32, 28, 23, 18, 21, 24, 28, + 30, 26, 21, 15, 18, 21, 24, 27, 24, 21, 13, 15, 18, 21, 24, 24, 20, 12, 14, + 17, 21, 24, 25, 21, 20, 23, 26, 31, 29, 27, 24, 19, 22, 26, 29, 29, 26, 22, + 17, 21, 24, 27, 27, 24, 19, 16, 18, 21, 24, 23, 22, 17, 13, 15, 17, 20, 20, + 20, 17, 12, 13, 16, 19, 19, 19, 17, 9, 12, 15, 18, 17, 18, 17, 18, 20, 22, + 23, 25, 23, 18, 16, 19, 21, 22, 23, 21, 16, 15, 18, 19, 19, 19, 19, 15, 14, + 16, 16, 16, 16, 16, 12, 9, 12, 13, 13, 12, 13, 12, 6, 12, 12, 12, 11, 12, + 12, 6, 10, 11, 10, 11, 11, 10, 15, 15, 15, 16, 17, 18, 11, 13, 13, 14, 15, + 15, 15, 9, 10, 12, 12, 12, 12, 11, 8, 6, 11, 9, 8, 8, 8, 7, 4, 7, + 6, 6, 5, 5, 4, 5, 5, 5, 4, 4, 4, 2, 6, 4, 3, 3, 3, 3, 2, + 6, 7, 7, 8, 9, 10, 11, 2, 5, 6, 7, 7, 8, 9, 2, 4, 5, 4, 5, + 5, 5, 2, 2, 2, 2, 1, 2, 2, 1, 4, 4, 3, 2, 2, 2, 3, 5, 5, + 4, 2, 2, 1, 4, 6, 7, 4, 3, 3, 0, 3, 4, 5, 6, 7, 8, 10, 4, + 5, 5, 6, 6, 6, 7, 4, 7, 5, 4, 4, 4, 4, 4, 6, 5, 4, 3, 2, + 1, 4, 7, 8, 5, 4, 3, 0, 6, 7, 9, 7, 4, 3, 2, 6, 8, 10, 8, + 5, 3, 2, 7, 9, 7, 5, 6, 8, 8, 7, 9, 8, 5, 5, 5, 5, 7, 9, + 10, 5, 3, 2, 3, 7, 8, 11, 6, 4, 3, 1, 7, 9, 11, 8, 5, 3, 2, + 8, 9, 12, 11, 6, 4, 2, 8, 10, 12, 12, 8, 5, 3, 31, 34, 37, 39, 39, + 37, 34, 28, 33, 36, 38, 38, 35, 32, 27, 31, 34, 37, 37, 35, 31, 26, 28, 32, + 34, 35, 32, 27, 22, 25, 29, 30, 32, 29, 27, 18, 22, 24, 26, 30, 29, 27, 15, + 19, 23, 26, 29, 28, 27, 26, 31, 35, 36, 36, 34, 32, 26, 30, 34, 36, 37, 33, + 31, 24, 28, 31, 34, 34, 31, 28, 22, 26, 30, 32, 30, 30, 24, 20, 22, 25, 28, + 27, 26, 24, 16, 19, 22, 24, 25, 25, 24, 12, 16, 20, 24, 24, 25, 24, 24, 29, + 31, 31, 33, 30, 27, 23, 26, 29, 30, 31, 31, 26, 21, 26, 28, 28, 29, 29, 25, + 19, 23, 25, 24, 25, 25, 20, 12, 19, 20, 21, 21, 21, 20, 8, 16, 18, 18, 19, + 20, 20, 8, 13, 16, 16, 18, 18, 19, 21, 22, 24, 25, 25, 27, 18, 18, 20, 21, + 24, 23, 24, 17, 14, 19, 21, 21, 21, 21, 16, 11, 17, 17, 17, 17, 17, 15, 8, + 12, 12, 13, 13, 13, 11, 7, 9, 9, 10, 11, 12, 8, 9, 7, 7, 8, 9, 10, + 8, 10, 14, 15, 16, 17, 17, 18, 6, 12, 13, 15, 15, 14, 17, 6, 11, 11, 11, + 12, 11, 14, 6, 7, 8, 8, 8, 8, 7, 4, 2, 3, 3, 3, 5, 7, 3, 2, + 2, 2, 0, 3, 7, 5, 5, 4, 2, 2, 2, 5, 5, 6, 8, 9, 12, 15, 17, + 5, 5, 7, 8, 11, 13, 14, 5, 6, 6, 6, 8, 10, 11, 5, 5, 5, 5, 4, + 6, 6, 3, 3, 4, 3, 2, 2, 6, 0, 4, 5, 4, 2, 1, 5, 4, 4, 6, + 5, 2, 2, 3, 7, 9, 9, 8, 10, 13, 15, 7, 9, 10, 8, 8, 11, 13, 7, + 9, 11, 7, 6, 7, 9, 7, 8, 10, 6, 4, 3, 5, 5, 7, 9, 6, 3, 1, + 3, 4, 5, 9, 8, 3, 2, 1, 5, 6, 9, 9, 4, 2, 1, 37, 41, 44, 47, + 48, 44, 42, 35, 39, 43, 47, 48, 44, 40, 33, 38, 41, 45, 45, 42, 38, 32, 36, + 38, 42, 45, 40, 34, 29, 31, 35, 39, 39, 36, 34, 24, 28, 31, 33, 37, 37, 34, + 22, 25, 29, 32, 36, 36, 34, 33, 36, 41, 46, 42, 42, 39, 31, 36, 41, 44, 45, + 42, 36, 30, 34, 38, 41, 41, 39, 35, 29, 32, 36, 38, 39, 35, 30, 25, 29, 31, + 34, 33, 33, 30, 20, 25, 28, 32, 31, 31, 28, 16, 22, 26, 31, 30, 30, 30, 30, + 35, 36, 37, 39, 37, 33, 28, 33, 35, 36, 37, 36, 31, 26, 31, 33, 34, 34, 34, + 29, 22, 29, 30, 31, 31, 30, 24, 16, 24, 26, 26, 25, 26, 25, 11, 21, 23, 24, + 24, 24, 25, 10, 19, 21, 23, 23, 23, 22, 26, 29, 30, 31, 32, 33, 24, 21, 26, + 29, 30, 31, 29, 23, 18, 25, 27, 27, 27, 26, 21, 14, 22, 23, 23, 23, 22, 19, + 12, 16, 19, 19, 18, 17, 16, 11, 12, 15, 16, 16, 16, 12, 10, 8, 13, 14, 14, + 15, 9, 13, 20, 21, 22, 24, 21, 24, 10, 18, 20, 20, 22, 18, 22, 10, 15, 17, + 17, 18, 15, 17, 10, 9, 14, 14, 13, 10, 12, 8, 4, 9, 9, 9, 8, 9, 5, + 3, 5, 5, 6, 6, 9, 7, 5, 3, 3, 4, 5, 7, 6, 12, 13, 14, 17, 19, + 21, 6, 10, 11, 13, 15, 17, 18, 6, 6, 9, 10, 12, 13, 14, 6, 5, 6, 6, + 8, 9, 8, 4, 3, 3, 3, 3, 6, 7, 4, 0, 4, 3, 1, 4, 7, 3, 3, + 5, 3, 2, 3, 6, 6, 8, 8, 10, 15, 17, 19, 6, 8, 9, 9, 13, 15, 16, + 6, 8, 9, 7, 9, 11, 12, 6, 7, 8, 5, 5, 7, 6, 4, 5, 6, 5, 2, + 3, 7, 2, 4, 5, 4, 2, 1, 5, 3, 5, 5, 5, 3, 2, 4, 42, 47, 50, + 55, 55, 54, 48, 41, 45, 49, 54, 55, 52, 45, 39, 43, 47, 51, 52, 50, 45, 38, + 40, 45, 48, 51, 45, 39, 34, 38, 41, 44, 46, 42, 40, 31, 34, 38, 41, 44, 42, + 39, 27, 30, 35, 40, 42, 43, 40, 40, 43, 48, 51, 52, 48, 44, 38, 43, 47, 51, + 50, 46, 42, 35, 40, 45, 48, 48, 46, 42, 34, 38, 42, 44, 44, 42, 35, 29, 35, + 38, 41, 40, 38, 34, 22, 31, 34, 37, 37, 38, 34, 19, 29, 33, 35, 36, 37, 36, + 37, 40, 44, 44, 45, 44, 39, 33, 40, 42, 42, 43, 42, 37, 29, 38, 40, 41, 40, + 39, 34, 25, 35, 37, 36, 37, 35, 30, 20, 30, 33, 33, 32, 29, 29, 14, 26, 30, + 30, 29, 30, 29, 13, 23, 27, 29, 28, 28, 27, 29, 34, 36, 37, 39, 38, 30, 25, + 32, 34, 36, 36, 34, 27, 21, 30, 33, 32, 33, 30, 26, 18, 26, 29, 28, 29, 26, + 25, 16, 20, 25, 25, 24, 20, 21, 14, 14, 22, 21, 21, 20, 17, 14, 10, 19, 20, + 20, 19, 13, 17, 27, 28, 29, 29, 25, 30, 13, 22, 27, 27, 27, 22, 28, 13, 18, + 24, 23, 24, 18, 22, 13, 12, 20, 20, 19, 13, 17, 11, 7, 16, 15, 14, 9, 12, + 9, 5, 11, 11, 11, 8, 10, 9, 6, 8, 10, 10, 8, 9, 9, 15, 18, 20, 20, + 23, 26, 9, 12, 17, 18, 19, 20, 22, 9, 8, 15, 15, 16, 17, 17, 9, 7, 11, + 11, 12, 11, 11, 7, 5, 6, 6, 5, 8, 9, 5, 4, 0, 1, 4, 6, 9, 5, + 3, 2, 2, 3, 6, 8, 7, 8, 11, 16, 19, 21, 22, 7, 7, 9, 14, 18, 18, + 18, 8, 7, 8, 11, 14, 15, 15, 7, 6, 6, 7, 10, 10, 9, 6, 4, 5, 3, + 3, 5, 8, 4, 2, 4, 4, 2, 5, 7, 3, 2, 4, 4, 2, 4, 6, 42, 45, + 48, 52, 53, 51, 46, 40, 42, 47, 52, 52, 48, 43, 38, 42, 46, 49, 52, 47, 42, + 35, 40, 44, 46, 48, 45, 38, 32, 37, 39, 44, 44, 42, 38, 29, 33, 36, 39, 42, + 41, 37, 26, 30, 34, 38, 41, 41, 38, 38, 42, 46, 49, 48, 46, 43, 37, 40, 45, + 49, 48, 44, 40, 35, 38, 43, 47, 46, 42, 35, 33, 38, 40, 43, 41, 39, 33, 26, + 34, 36, 39, 38, 36, 32, 22, 29, 32, 36, 35, 35, 32, 17, 28, 32, 35, 34, 34, + 33, 35, 40, 42, 42, 44, 41, 35, 31, 39, 39, 42, 42, 39, 33, 28, 37, 39, 38, + 38, 37, 30, 24, 33, 34, 35, 35, 32, 28, 18, 28, 31, 31, 30, 29, 28, 13, 24, + 29, 28, 29, 28, 28, 13, 21, 27, 27, 27, 27, 25, 27, 34, 34, 35, 37, 33, 27, + 23, 30, 33, 34, 33, 31, 26, 20, 27, 32, 31, 30, 27, 24, 16, 24, 28, 28, 27, + 23, 23, 14, 17, 24, 23, 23, 18, 19, 13, 13, 21, 21, 20, 17, 16, 12, 9, 19, + 20, 19, 17, 11, 16, 24, 26, 27, 26, 23, 27, 12, 20, 25, 26, 24, 19, 26, 12, + 16, 23, 23, 21, 15, 20, 12, 10, 19, 19, 17, 10, 15, 10, 6, 15, 15, 12, 7, + 11, 9, 5, 11, 11, 11, 6, 8, 8, 5, 7, 9, 9, 6, 7, 8, 14, 18, 18, + 18, 19, 24, 8, 9, 16, 16, 17, 17, 19, 8, 6, 14, 13, 14, 14, 14, 8, 5, + 10, 9, 10, 9, 9, 6, 3, 5, 5, 4, 6, 7, 4, 3, 1, 0, 3, 5, 7, + 4, 3, 1, 2, 2, 4, 6, 6, 7, 11, 14, 17, 19, 20, 6, 7, 10, 13, 15, + 16, 16, 6, 6, 9, 10, 12, 13, 13, 6, 5, 5, 6, 8, 8, 7, 4, 4, 4, + 3, 3, 4, 6, 3, 2, 6, 6, 1, 4, 5, 2, 3, 6, 6, 2, 3, 4, 34, + 39, 42, 47, 46, 43, 40, 34, 37, 42, 46, 46, 43, 37, 32, 35, 40, 44, 45, 41, + 36, 31, 33, 37, 40, 42, 38, 32, 28, 30, 33, 37, 38, 36, 33, 25, 27, 29, 33, + 37, 36, 32, 23, 25, 28, 32, 35, 36, 32, 32, 35, 40, 44, 44, 40, 36, 32, 35, + 38, 43, 42, 38, 33, 30, 33, 38, 40, 40, 36, 31, 28, 31, 34, 37, 36, 34, 28, + 22, 29, 30, 34, 33, 30, 27, 19, 25, 27, 30, 30, 30, 28, 15, 25, 27, 29, 29, + 30, 27, 30, 34, 37, 36, 36, 34, 29, 27, 32, 34, 35, 36, 33, 28, 24, 30, 33, + 32, 32, 30, 25, 21, 29, 29, 30, 30, 27, 23, 15, 24, 26, 26, 25, 23, 22, 11, + 22, 24, 23, 23, 22, 22, 10, 19, 22, 22, 22, 22, 20, 25, 28, 28, 29, 30, 29, + 23, 20, 26, 27, 28, 28, 25, 20, 16, 24, 26, 25, 25, 22, 19, 13, 20, 22, 21, + 22, 18, 18, 11, 15, 19, 18, 17, 14, 14, 10, 11, 17, 15, 15, 14, 11, 10, 7, + 15, 14, 14, 13, 7, 12, 20, 20, 21, 21, 17, 22, 9, 17, 19, 20, 19, 14, 20, + 9, 13, 17, 17, 16, 11, 15, 9, 8, 14, 13, 12, 7, 10, 7, 3, 10, 9, 8, + 4, 7, 6, 3, 7, 6, 6, 3, 5, 5, 4, 5, 5, 4, 4, 4, 5, 10, 12, + 12, 13, 15, 19, 5, 8, 11, 11, 12, 13, 14, 4, 4, 10, 9, 9, 10, 10, 5, + 3, 6, 6, 6, 6, 5, 3, 2, 1, 1, 2, 3, 4, 2, 1, 4, 3, 0, 3, + 4, 3, 2, 4, 3, 2, 2, 3, 5, 5, 8, 10, 12, 14, 15, 5, 5, 7, 10, + 11, 12, 12, 5, 5, 6, 7, 8, 9, 9, 5, 4, 4, 4, 4, 5, 4, 3, 2, + 5, 4, 2, 2, 4, 1, 4, 5, 5, 2, 2, 3, 3, 4, 5, 5, 3, 0, 2, + 28, 33, 37, 40, 41, 38, 35, 28, 31, 36, 40, 39, 37, 33, 26, 29, 35, 38, 38, + 34, 31, 26, 28, 31, 35, 37, 33, 28, 23, 25, 28, 30, 34, 31, 27, 19, 22, 24, + 28, 32, 31, 27, 18, 21, 23, 27, 30, 31, 28, 27, 30, 34, 38, 36, 35, 30, 26, + 30, 32, 37, 37, 33, 28, 25, 28, 31, 34, 33, 32, 26, 23, 26, 28, 30, 30, 28, + 22, 20, 22, 25, 27, 27, 26, 22, 17, 20, 22, 25, 25, 25, 22, 13, 19, 21, 24, + 24, 25, 22, 25, 28, 29, 30, 31, 30, 25, 23, 26, 29, 30, 29, 28, 23, 21, 26, + 27, 27, 27, 27, 21, 18, 23, 23, 23, 24, 23, 17, 12, 20, 20, 20, 20, 19, 17, + 8, 19, 19, 18, 18, 18, 17, 8, 16, 17, 17, 17, 17, 15, 21, 22, 22, 23, 24, + 23, 17, 17, 21, 22, 22, 23, 21, 15, 13, 19, 20, 20, 19, 18, 14, 10, 16, 16, + 16, 16, 15, 13, 8, 12, 13, 12, 12, 11, 10, 8, 9, 11, 11, 10, 10, 6, 8, + 6, 10, 9, 9, 9, 4, 9, 14, 15, 16, 16, 13, 17, 5, 13, 13, 14, 14, 10, + 15, 6, 11, 11, 11, 11, 8, 10, 6, 6, 8, 7, 7, 5, 6, 4, 2, 4, 3, + 3, 3, 3, 3, 2, 2, 1, 2, 2, 3, 4, 2, 4, 2, 1, 2, 3, 3, 7, + 8, 9, 10, 12, 14, 3, 6, 7, 8, 9, 10, 10, 3, 4, 6, 6, 6, 7, 7, + 3, 3, 3, 3, 3, 4, 3, 1, 3, 5, 3, 2, 1, 3, 1, 5, 6, 4, 3, + 0, 3, 2, 5, 6, 6, 3, 2, 2, 4, 6, 6, 7, 9, 11, 12, 4, 7, 6, + 7, 8, 9, 9, 4, 6, 6, 5, 5, 5, 6, 4, 5, 6, 3, 2, 2, 2, 2, + 5, 7, 6, 3, 2, 2, 5, 6, 8, 7, 4, 2, 1, 5, 7, 8, 8, 5, 3, + 0, 24, 28, 32, 36, 35, 32, 29, 23, 26, 30, 34, 36, 32, 28, 21, 25, 29, 32, + 34, 31, 25, 19, 22, 26, 30, 32, 28, 23, 17, 20, 22, 26, 28, 27, 23, 15, 17, + 20, 23, 27, 26, 23, 14, 16, 19, 22, 25, 26, 23, 21, 24, 28, 34, 32, 28, 26, + 20, 24, 28, 31, 31, 28, 24, 18, 22, 26, 29, 28, 26, 22, 18, 20, 23, 25, 26, + 23, 19, 15, 17, 20, 22, 21, 21, 18, 13, 15, 18, 20, 20, 21, 19, 11, 13, 17, + 20, 19, 19, 18, 18, 22, 24, 25, 27, 25, 20, 17, 20, 23, 24, 24, 23, 19, 17, + 19, 22, 22, 21, 22, 17, 14, 18, 18, 18, 18, 18, 14, 10, 14, 15, 15, 15, 15, + 14, 6, 13, 14, 13, 13, 14, 13, 6, 12, 12, 12, 12, 13, 12, 17, 17, 17, 18, + 20, 20, 13, 14, 15, 16, 17, 17, 17, 11, 11, 14, 14, 14, 14, 13, 10, 7, 12, + 11, 11, 11, 10, 9, 5, 9, 8, 7, 7, 7, 5, 6, 7, 7, 6, 6, 6, 3, + 7, 4, 5, 5, 5, 5, 3, 7, 9, 9, 10, 11, 11, 13, 2, 7, 8, 9, 9, + 8, 11, 2, 6, 6, 6, 6, 6, 7, 2, 3, 3, 2, 2, 3, 3, 1, 2, 2, + 2, 2, 0, 2, 2, 4, 5, 4, 2, 1, 2, 3, 6, 7, 4, 3, 2, 2, 3, + 4, 5, 7, 8, 10, 11, 3, 4, 5, 6, 7, 7, 8, 3, 5, 4, 4, 4, 5, + 5, 3, 4, 5, 3, 2, 1, 2, 3, 6, 8, 5, 4, 2, 2, 4, 8, 10, 7, + 4, 3, 0, 6, 9, 10, 8, 5, 3, 1, 6, 8, 6, 5, 7, 8, 9, 6, 8, + 8, 6, 6, 6, 7, 6, 8, 9, 5, 3, 3, 4, 6, 7, 10, 7, 5, 2, 0, + 7, 9, 10, 8, 5, 3, 2, 8, 10, 11, 10, 6, 4, 2, 9, 10, 11, 11, 7, + 5, 3, 33, 37, 40, 43, 42, 41, 37, 32, 36, 40, 42, 42, 40, 36, 30, 34, 38, + 40, 41, 37, 34, 29, 32, 36, 37, 38, 33, 27, 25, 28, 32, 33, 32, 29, 28, 22, + 24, 27, 28, 32, 29, 28, 16, 20, 24, 27, 29, 30, 28, 30, 34, 38, 40, 40, 38, + 35, 29, 33, 37, 42, 40, 37, 34, 27, 31, 35, 38, 36, 34, 30, 26, 29, 32, 34, + 34, 32, 25, 23, 26, 28, 31, 28, 27, 25, 18, 22, 24, 25, 27, 26, 25, 13, 17, + 21, 24, 24, 25, 24, 27, 32, 33, 35, 36, 35, 31, 26, 29, 33, 34, 35, 34, 29, + 24, 29, 31, 31, 31, 31, 26, 20, 26, 27, 28, 28, 26, 21, 14, 22, 24, 24, 22, + 21, 21, 8, 17, 19, 19, 19, 20, 21, 7, 14, 17, 17, 18, 19, 19, 24, 25, 26, + 28, 30, 30, 24, 20, 24, 25, 27, 27, 27, 22, 17, 23, 24, 24, 24, 23, 20, 13, + 19, 20, 20, 20, 19, 17, 11, 14, 16, 16, 14, 13, 14, 8, 9, 11, 10, 11, 12, + 10, 7, 5, 8, 9, 10, 10, 9, 12, 18, 19, 20, 22, 22, 23, 9, 17, 18, 19, + 20, 19, 22, 9, 15, 16, 16, 16, 16, 16, 9, 11, 13, 13, 12, 10, 10, 6, 5, + 8, 8, 4, 6, 8, 4, 3, 1, 2, 3, 5, 8, 3, 2, 2, 1, 2, 4, 7, + 8, 12, 14, 15, 18, 21, 22, 8, 10, 12, 14, 16, 18, 18, 8, 8, 10, 10, 13, + 14, 14, 8, 7, 7, 7, 8, 9, 7, 6, 5, 6, 5, 3, 4, 7, 3, 3, 5, + 4, 3, 2, 6, 0, 3, 5, 5, 3, 2, 5, 8, 11, 11, 11, 16, 19, 20, 9, + 11, 12, 10, 14, 16, 17, 9, 11, 12, 9, 10, 12, 13, 9, 10, 11, 8, 6, 6, + 6, 7, 8, 10, 7, 4, 2, 5, 5, 7, 8, 7, 4, 3, 3, 4, 5, 7, 8, + 4, 3, 2, 39, 43, 46, 51, 52, 48, 44, 38, 42, 45, 50, 49, 46, 43, 36, 39, + 44, 48, 48, 45, 39, 35, 38, 42, 44, 45, 40, 34, 31, 35, 36, 40, 41, 37, 34, + 27, 30, 33, 34, 38, 38, 34, 22, 26, 29, 34, 37, 37, 33, 36, 40, 46, 48, 48, + 43, 41, 34, 38, 42, 47, 47, 42, 38, 32, 36, 41, 43, 44, 41, 35, 31, 34, 38, + 41, 40, 37, 30, 27, 32, 34, 36, 34, 33, 30, 21, 27, 30, 31, 32, 33, 30, 15, + 23, 25, 30, 30, 30, 29, 33, 36, 40, 41, 42, 40, 35, 31, 35, 38, 40, 41, 39, + 33, 28, 34, 37, 38, 36, 36, 31, 24, 31, 33, 33, 33, 31, 26, 17, 27, 28, 29, + 27, 26, 26, 12, 22, 25, 24, 24, 25, 26, 10, 18, 22, 23, 23, 24, 24, 27, 31, + 32, 34, 35, 35, 28, 23, 30, 31, 32, 32, 33, 25, 20, 28, 30, 29, 29, 28, 24, + 16, 24, 25, 26, 25, 22, 22, 13, 18, 21, 21, 18, 18, 18, 12, 11, 17, 16, 16, + 17, 14, 10, 7, 15, 14, 15, 15, 11, 15, 23, 24, 25, 26, 25, 28, 12, 20, 22, + 24, 24, 22, 26, 12, 17, 21, 21, 20, 18, 20, 12, 11, 17, 16, 16, 12, 14, 10, + 5, 13, 12, 9, 8, 10, 7, 5, 7, 6, 7, 7, 9, 5, 4, 4, 4, 5, 7, + 8, 9, 16, 18, 19, 22, 23, 25, 9, 13, 16, 18, 20, 20, 22, 9, 9, 14, 14, + 16, 17, 16, 9, 8, 10, 10, 12, 11, 9, 7, 6, 5, 5, 4, 7, 9, 4, 3, + 3, 3, 2, 5, 9, 4, 0, 3, 4, 2, 4, 7, 9, 9, 10, 15, 19, 22, 22, + 9, 9, 10, 13, 18, 19, 19, 9, 9, 11, 11, 13, 15, 14, 9, 8, 10, 7, 9, + 9, 7, 7, 7, 8, 6, 3, 4, 7, 5, 5, 6, 5, 3, 3, 6, 2, 4, 5, + 5, 3, 2, 5, 44, 47, 53, 55, 56, 52, 48, 42, 47, 51, 53, 55, 51, 47, 41, + 45, 50, 51, 54, 50, 44, 39, 42, 44, 49, 50, 47, 40, 36, 39, 42, 46, 46, 42, + 39, 31, 34, 38, 40, 44, 43, 39, 27, 31, 35, 39, 42, 43, 39, 40, 45, 49, 52, + 52, 48, 45, 39, 44, 47, 52, 50, 47, 42, 36, 42, 45, 48, 49, 45, 39, 35, 39, + 42, 44, 44, 41, 34, 28, 36, 39, 41, 39, 38, 35, 23, 32, 35, 36, 37, 36, 35, + 18, 29, 32, 36, 35, 36, 34, 36, 42, 44, 45, 47, 44, 38, 33, 41, 41, 45, 45, + 43, 37, 30, 39, 40, 41, 41, 39, 34, 25, 35, 37, 37, 37, 36, 30, 20, 31, 34, + 34, 31, 30, 30, 15, 26, 30, 29, 30, 29, 30, 13, 22, 28, 28, 28, 29, 28, 29, + 35, 36, 38, 39, 38, 31, 26, 34, 36, 37, 37, 35, 29, 22, 31, 34, 33, 34, 31, + 27, 18, 27, 30, 29, 30, 26, 25, 16, 20, 26, 25, 24, 21, 22, 15, 14, 22, 21, + 21, 20, 17, 14, 10, 19, 20, 20, 19, 14, 17, 25, 28, 30, 29, 26, 31, 14, 23, + 27, 28, 28, 23, 29, 14, 19, 25, 25, 24, 20, 24, 14, 13, 21, 20, 21, 13, 16, + 12, 8, 16, 16, 13, 10, 13, 9, 5, 11, 11, 12, 9, 11, 9, 6, 8, 10, 10, + 8, 10, 10, 16, 19, 21, 22, 24, 27, 10, 12, 18, 20, 21, 22, 23, 9, 8, 17, + 16, 17, 18, 18, 10, 8, 13, 12, 13, 12, 11, 8, 5, 7, 7, 5, 8, 10, 6, + 5, 2, 1, 4, 7, 9, 5, 3, 0, 2, 4, 6, 8, 9, 8, 12, 17, 21, 23, + 24, 9, 8, 11, 16, 20, 20, 20, 9, 8, 9, 13, 15, 16, 16, 8, 7, 7, 8, + 11, 11, 9, 6, 5, 5, 3, 4, 5, 8, 4, 3, 4, 4, 2, 5, 7, 3, 2, + 4, 4, 2, 4, 6, 44, 48, 53, 55, 55, 53, 49, 41, 48, 50, 54, 54, 52, 48, + 40, 44, 49, 52, 53, 49, 44, 39, 42, 47, 48, 51, 47, 42, 35, 39, 42, 45, 46, + 44, 40, 31, 34, 38, 42, 44, 43, 40, 27, 33, 36, 39, 43, 43, 40, 41, 44, 48, + 53, 53, 48, 43, 39, 45, 48, 51, 50, 47, 42, 36, 42, 46, 48, 48, 46, 39, 33, + 40, 43, 46, 45, 42, 35, 28, 36, 40, 41, 40, 38, 35, 22, 32, 35, 39, 38, 37, + 35, 18, 29, 34, 37, 35, 36, 36, 36, 41, 44, 45, 46, 44, 37, 34, 39, 43, 44, + 43, 41, 35, 29, 39, 41, 41, 40, 39, 33, 26, 37, 37, 37, 37, 36, 30, 19, 31, + 34, 34, 32, 30, 29, 15, 26, 31, 30, 30, 29, 29, 14, 21, 30, 29, 29, 28, 27, + 30, 36, 38, 38, 38, 36, 30, 25, 33, 35, 37, 35, 33, 28, 21, 30, 34, 34, 32, + 30, 26, 17, 24, 31, 30, 30, 24, 25, 15, 19, 26, 27, 24, 20, 21, 15, 14, 24, + 23, 22, 19, 17, 14, 10, 20, 22, 21, 18, 14, 16, 25, 29, 30, 27, 24, 30, 13, + 22, 27, 28, 26, 20, 28, 13, 17, 25, 24, 23, 17, 23, 13, 12, 21, 21, 19, 12, + 17, 11, 7, 17, 17, 13, 8, 13, 10, 6, 12, 13, 12, 7, 10, 9, 6, 8, 12, + 11, 7, 9, 9, 14, 19, 20, 19, 22, 26, 9, 10, 18, 18, 18, 19, 22, 9, 6, + 16, 15, 15, 16, 16, 9, 5, 12, 12, 11, 11, 10, 7, 4, 6, 7, 5, 7, 8, + 5, 3, 2, 2, 3, 5, 8, 5, 3, 2, 0, 3, 5, 7, 7, 7, 12, 16, 18, + 20, 22, 7, 7, 11, 14, 17, 17, 18, 7, 7, 9, 12, 13, 14, 14, 7, 6, 5, + 8, 9, 9, 8, 5, 4, 3, 2, 4, 5, 7, 3, 2, 5, 4, 2, 4, 6, 3, + 1, 5, 5, 1, 4, 5, 38, 42, 47, 47, 48, 47, 43, 36, 41, 44, 48, 49, 45, + 41, 34, 39, 43, 45, 47, 44, 38, 33, 36, 40, 43, 45, 41, 34, 31, 33, 37, 39, + 41, 39, 35, 26, 29, 32, 35, 39, 37, 35, 23, 28, 31, 34, 38, 38, 34, 34, 39, + 43, 47, 46, 41, 38, 34, 38, 41, 45, 44, 40, 36, 31, 35, 40, 43, 42, 39, 33, + 29, 34, 36, 40, 39, 36, 30, 24, 30, 33, 36, 35, 33, 30, 21, 27, 30, 32, 32, + 32, 29, 16, 26, 29, 31, 31, 31, 30, 31, 35, 38, 39, 39, 37, 31, 29, 35, 37, + 38, 38, 35, 30, 26, 32, 35, 35, 36, 33, 27, 22, 31, 32, 31, 32, 30, 24, 16, + 26, 27, 28, 27, 25, 24, 11, 24, 25, 26, 25, 24, 24, 11, 20, 24, 24, 24, 24, + 22, 25, 30, 30, 31, 32, 30, 24, 21, 29, 28, 30, 31, 28, 22, 18, 26, 28, 28, + 27, 24, 21, 15, 21, 24, 25, 24, 20, 20, 12, 15, 21, 20, 20, 16, 16, 11, 12, + 18, 18, 17, 15, 12, 11, 8, 17, 17, 16, 15, 9, 13, 21, 23, 24, 23, 19, 24, + 10, 19, 22, 22, 21, 16, 23, 10, 14, 19, 19, 18, 13, 17, 10, 9, 16, 16, 15, + 8, 12, 8, 4, 12, 12, 10, 5, 9, 7, 4, 9, 8, 8, 4, 6, 7, 4, 6, + 7, 7, 4, 5, 6, 12, 14, 15, 15, 17, 20, 6, 8, 12, 13, 14, 14, 16, 6, + 5, 11, 10, 11, 11, 12, 6, 4, 8, 7, 7, 7, 6, 4, 2, 2, 2, 3, 4, + 5, 2, 2, 3, 3, 2, 3, 5, 3, 2, 4, 3, 0, 3, 4, 5, 5, 10, 12, + 14, 16, 17, 5, 6, 9, 11, 12, 13, 13, 5, 6, 8, 9, 9, 10, 10, 5, 5, + 4, 5, 6, 6, 5, 3, 2, 3, 3, 1, 3, 4, 2, 3, 5, 4, 2, 2, 4, + 2, 4, 5, 4, 3, 2, 3, 31, 36, 40, 43, 43, 40, 36, 30, 33, 38, 43, 43, + 39, 35, 28, 32, 37, 39, 42, 37, 33, 28, 30, 33, 36, 40, 35, 29, 25, 27, 29, + 33, 35, 32, 29, 21, 24, 26, 30, 34, 32, 29, 20, 21, 26, 29, 32, 32, 29, 29, + 32, 36, 40, 38, 35, 33, 29, 31, 35, 38, 37, 35, 30, 26, 30, 33, 36, 36, 32, + 29, 25, 28, 30, 33, 33, 31, 24, 20, 25, 27, 29, 29, 27, 24, 18, 22, 25, 27, + 27, 27, 24, 14, 21, 24, 26, 26, 26, 24, 26, 30, 32, 33, 34, 32, 27, 25, 29, + 30, 31, 31, 30, 25, 23, 27, 29, 29, 29, 28, 22, 18, 26, 25, 26, 26, 24, 19, + 13, 22, 22, 22, 22, 21, 19, 9, 20, 20, 20, 20, 20, 19, 9, 17, 20, 18, 19, + 19, 17, 23, 24, 24, 26, 27, 25, 19, 18, 23, 23, 25, 24, 22, 17, 14, 22, 22, + 21, 22, 19, 16, 11, 18, 19, 18, 18, 16, 14, 9, 13, 15, 14, 14, 12, 11, 9, + 10, 13, 12, 12, 12, 8, 9, 7, 12, 11, 11, 11, 5, 10, 17, 17, 18, 18, 15, + 19, 7, 15, 16, 16, 16, 12, 17, 6, 12, 13, 13, 13, 9, 12, 7, 6, 10, 9, + 9, 6, 7, 5, 2, 6, 5, 5, 3, 5, 4, 2, 4, 3, 3, 3, 4, 4, 3, + 2, 2, 2, 2, 3, 4, 9, 9, 10, 11, 13, 16, 4, 7, 9, 9, 10, 11, 12, + 4, 4, 8, 7, 8, 8, 8, 4, 3, 4, 4, 4, 5, 4, 2, 1, 4, 3, 1, + 2, 3, 2, 3, 6, 4, 2, 2, 3, 2, 5, 6, 5, 3, 0, 3, 4, 5, 6, + 8, 10, 12, 13, 4, 5, 6, 8, 9, 10, 10, 4, 5, 6, 5, 6, 6, 7, 4, + 4, 6, 3, 2, 3, 3, 2, 4, 8, 5, 3, 0, 3, 3, 6, 7, 7, 4, 2, + 2, 5, 7, 7, 8, 5, 2, 2, 25, 28, 34, 37, 37, 34, 31, 24, 28, 32, 36, + 37, 32, 29, 23, 26, 30, 34, 36, 32, 27, 22, 24, 28, 31, 34, 30, 24, 19, 21, + 24, 27, 31, 28, 24, 17, 18, 21, 24, 29, 28, 24, 15, 17, 21, 24, 27, 27, 24, + 23, 27, 31, 34, 33, 30, 27, 22, 25, 29, 33, 33, 28, 25, 20, 24, 28, 31, 30, + 27, 24, 20, 22, 24, 28, 27, 26, 20, 17, 18, 21, 23, 24, 23, 20, 15, 17, 19, + 21, 22, 22, 20, 12, 16, 19, 21, 21, 21, 20, 21, 24, 26, 27, 28, 26, 22, 20, + 23, 24, 25, 26, 25, 20, 19, 21, 23, 23, 23, 22, 18, 16, 20, 20, 20, 19, 19, + 14, 10, 16, 16, 16, 16, 16, 14, 7, 16, 15, 15, 15, 15, 15, 7, 14, 14, 14, + 14, 14, 13, 18, 19, 19, 20, 21, 21, 14, 15, 17, 18, 19, 19, 18, 12, 12, 16, + 16, 16, 15, 15, 11, 8, 14, 13, 12, 12, 12, 10, 6, 10, 9, 9, 8, 8, 7, + 6, 8, 8, 7, 7, 7, 4, 7, 4, 6, 6, 6, 6, 3, 8, 11, 11, 12, 13, + 12, 14, 3, 9, 10, 10, 11, 9, 12, 4, 8, 8, 7, 7, 7, 8, 3, 4, 4, + 4, 3, 3, 3, 1, 1, 1, 1, 1, 1, 3, 2, 3, 4, 3, 2, 0, 2, 3, + 5, 5, 3, 2, 2, 2, 3, 5, 6, 7, 8, 10, 12, 3, 4, 6, 7, 7, 8, + 9, 3, 4, 4, 4, 5, 5, 6, 3, 3, 4, 3, 2, 2, 2, 1, 5, 6, 4, + 3, 2, 2, 3, 6, 8, 6, 3, 2, 1, 5, 7, 8, 7, 4, 3, 0, 5, 7, + 6, 6, 8, 9, 10, 5, 7, 6, 6, 6, 7, 7, 5, 7, 8, 4, 3, 4, 4, + 5, 7, 8, 5, 3, 2, 1, 5, 8, 9, 7, 4, 3, 0, 6, 8, 10, 9, 5, + 3, 2, 7, 9, 10, 10, 6, 4, 2, 31, 36, 39, 41, 40, 39, 36, 31, 35, 38, + 41, 41, 38, 36, 30, 33, 36, 40, 42, 39, 36, 29, 32, 36, 39, 41, 39, 38, 28, + 31, 35, 38, 42, 40, 37, 28, 30, 34, 38, 41, 42, 36, 25, 29, 33, 37, 40, 40, + 37, 29, 32, 36, 40, 38, 35, 32, 28, 32, 35, 38, 38, 34, 32, 27, 30, 34, 38, + 38, 34, 32, 25, 29, 34, 36, 37, 36, 32, 25, 29, 32, 36, 36, 36, 33, 24, 28, + 32, 35, 36, 35, 32, 21, 26, 30, 34, 34, 35, 32, 27, 31, 31, 32, 33, 30, 25, + 27, 29, 30, 30, 32, 29, 25, 24, 28, 29, 30, 30, 30, 25, 21, 27, 28, 29, 30, + 30, 25, 19, 27, 28, 28, 29, 30, 26, 15, 24, 26, 28, 28, 28, 26, 16, 22, 25, + 26, 26, 26, 25, 24, 25, 25, 25, 25, 22, 13, 22, 23, 23, 25, 24, 21, 14, 17, + 22, 22, 23, 22, 20, 15, 14, 22, 21, 22, 23, 20, 17, 15, 19, 20, 21, 21, 19, + 14, 15, 17, 19, 19, 19, 18, 10, 16, 14, 17, 17, 18, 17, 8, 12, 16, 16, 17, + 15, 10, 12, 9, 15, 15, 15, 14, 10, 13, 9, 13, 13, 13, 13, 8, 12, 9, 9, + 13, 13, 12, 9, 10, 10, 7, 11, 11, 11, 6, 8, 10, 9, 8, 9, 9, 5, 8, + 12, 11, 9, 7, 7, 4, 7, 4, 6, 6, 6, 7, 9, 10, 4, 4, 4, 5, 5, + 9, 10, 4, 2, 2, 3, 5, 7, 9, 4, 2, 1, 1, 3, 6, 8, 5, 4, 4, + 4, 4, 4, 7, 7, 6, 8, 6, 4, 4, 6, 9, 9, 9, 7, 5, 4, 5, 0, + 4, 3, 1, 4, 7, 9, 0, 4, 4, 2, 4, 6, 8, 0, 4, 5, 2, 2, 5, + 8, 0, 3, 4, 2, 2, 4, 6, 2, 4, 5, 5, 5, 4, 5, 5, 6, 8, 8, + 5, 5, 4, 8, 8, 9, 9, 6, 5, 4, 37, 41, 45, 47, 47, 45, 41, 37, 40, + 44, 46, 48, 46, 42, 36, 39, 42, 47, 47, 46, 43, 34, 37, 41, 45, 48, 46, 42, + 34, 37, 41, 45, 49, 46, 42, 33, 36, 41, 44, 47, 45, 42, 30, 35, 38, 43, 47, + 46, 42, 36, 39, 42, 45, 43, 41, 36, 34, 37, 41, 44, 44, 39, 36, 33, 36, 40, + 42, 43, 40, 36, 32, 36, 38, 43, 42, 42, 37, 30, 35, 38, 42, 41, 40, 37, 28, + 34, 38, 41, 41, 40, 37, 25, 31, 36, 40, 40, 40, 37, 33, 36, 38, 38, 37, 34, + 28, 31, 34, 36, 38, 36, 34, 28, 28, 34, 36, 36, 35, 34, 29, 25, 34, 34, 36, + 36, 34, 30, 22, 32, 34, 35, 35, 34, 30, 19, 30, 33, 33, 33, 32, 30, 18, 28, + 31, 31, 32, 32, 28, 28, 31, 31, 30, 29, 25, 16, 25, 29, 29, 30, 28, 24, 18, + 21, 28, 28, 28, 27, 23, 20, 17, 26, 29, 27, 27, 23, 23, 18, 23, 27, 27, 26, + 22, 19, 19, 20, 25, 25, 25, 21, 15, 18, 17, 23, 24, 24, 21, 11, 16, 22, 22, + 22, 16, 12, 16, 12, 19, 21, 21, 16, 11, 18, 13, 16, 19, 19, 16, 9, 15, 13, + 12, 19, 19, 15, 11, 14, 14, 10, 17, 17, 13, 8, 11, 13, 11, 14, 14, 12, 7, + 10, 14, 13, 12, 13, 11, 6, 8, 7, 11, 12, 9, 9, 11, 13, 7, 8, 10, 8, + 7, 9, 12, 7, 5, 8, 7, 6, 8, 10, 7, 4, 7, 6, 6, 8, 10, 8, 6, + 5, 5, 4, 6, 9, 9, 8, 8, 7, 5, 6, 8, 11, 9, 8, 7, 6, 5, 7, + 4, 0, 2, 4, 6, 9, 11, 4, 0, 2, 3, 5, 7, 10, 4, 0, 3, 2, 6, + 9, 10, 4, 1, 3, 2, 4, 5, 8, 4, 3, 5, 5, 5, 5, 7, 6, 6, 8, + 8, 6, 5, 6, 7, 9, 8, 8, 7, 5, 6, 36, 40, 42, 44, 44, 42, 39, 35, + 38, 42, 44, 45, 42, 38, 34, 37, 41, 44, 45, 42, 40, 33, 37, 41, 45, 46, 43, + 40, 33, 36, 40, 43, 47, 44, 39, 32, 35, 39, 43, 46, 44, 40, 30, 34, 38, 41, + 45, 44, 39, 34, 37, 40, 43, 41, 36, 34, 32, 35, 39, 42, 42, 37, 33, 31, 35, + 38, 40, 41, 37, 34, 31, 35, 37, 41, 41, 39, 34, 29, 35, 36, 40, 39, 39, 35, + 27, 33, 36, 39, 39, 38, 35, 24, 31, 35, 38, 37, 37, 35, 31, 34, 36, 35, 35, + 31, 24, 29, 33, 34, 35, 34, 31, 24, 27, 33, 34, 34, 32, 31, 26, 23, 33, 33, + 34, 33, 31, 27, 21, 31, 33, 33, 33, 29, 27, 18, 29, 32, 31, 31, 30, 28, 18, + 27, 30, 30, 31, 29, 25, 27, 29, 28, 28, 27, 22, 14, 22, 28, 27, 27, 25, 20, + 16, 19, 26, 27, 27, 25, 20, 18, 15, 24, 27, 26, 25, 20, 21, 17, 22, 25, 25, + 24, 19, 17, 17, 19, 24, 25, 23, 18, 14, 18, 16, 22, 22, 22, 18, 10, 14, 20, + 20, 20, 14, 8, 14, 11, 18, 19, 19, 14, 8, 15, 11, 14, 19, 18, 13, 7, 14, + 11, 11, 18, 18, 13, 7, 13, 13, 9, 16, 16, 12, 6, 9, 12, 11, 14, 14, 11, + 6, 7, 14, 13, 12, 12, 10, 6, 7, 6, 10, 11, 7, 5, 7, 10, 6, 7, 9, + 7, 5, 7, 9, 6, 3, 8, 6, 5, 7, 8, 6, 4, 7, 6, 4, 6, 7, 7, + 6, 5, 5, 6, 6, 7, 9, 8, 11, 11, 8, 6, 7, 11, 10, 12, 12, 10, 6, + 6, 3, 2, 0, 3, 4, 6, 8, 3, 2, 2, 2, 4, 5, 7, 3, 2, 3, 2, + 4, 6, 7, 3, 2, 6, 4, 4, 5, 6, 4, 5, 10, 11, 9, 6, 6, 6, 10, + 15, 16, 11, 7, 6, 9, 14, 17, 17, 13, 8, 6, 28, 32, 36, 38, 38, 36, 32, + 29, 31, 35, 38, 39, 36, 32, 27, 31, 34, 37, 39, 36, 33, 26, 30, 34, 37, 40, + 37, 34, 27, 30, 33, 36, 40, 38, 34, 26, 29, 32, 36, 39, 38, 34, 24, 27, 30, + 35, 37, 38, 34, 28, 30, 34, 36, 34, 30, 27, 26, 28, 32, 35, 34, 31, 27, 25, + 28, 32, 34, 34, 32, 28, 24, 28, 31, 35, 34, 32, 28, 24, 28, 31, 34, 34, 34, + 29, 23, 27, 29, 33, 33, 33, 29, 21, 25, 28, 31, 32, 31, 29, 26, 29, 29, 28, + 29, 25, 19, 25, 26, 28, 28, 28, 25, 19, 23, 26, 27, 28, 28, 25, 20, 19, 26, + 27, 28, 27, 26, 22, 17, 25, 27, 26, 26, 25, 22, 15, 25, 25, 25, 26, 24, 22, + 16, 22, 24, 24, 24, 24, 20, 22, 23, 22, 21, 21, 17, 8, 18, 22, 21, 21, 20, + 16, 10, 15, 21, 21, 21, 20, 16, 13, 12, 20, 21, 20, 19, 16, 16, 14, 18, 21, + 20, 19, 15, 12, 15, 16, 18, 18, 17, 15, 9, 16, 15, 16, 17, 16, 14, 6, 11, + 15, 15, 14, 10, 5, 8, 7, 14, 13, 13, 10, 5, 10, 8, 11, 12, 12, 10, 5, + 9, 7, 9, 12, 12, 10, 5, 8, 9, 7, 11, 11, 9, 6, 6, 10, 9, 10, 9, + 8, 6, 5, 13, 13, 13, 10, 8, 7, 5, 3, 6, 5, 4, 3, 4, 6, 3, 4, + 4, 3, 3, 4, 5, 3, 2, 2, 2, 3, 4, 6, 3, 2, 4, 4, 4, 5, 5, + 5, 6, 9, 9, 8, 7, 5, 7, 10, 16, 14, 10, 7, 6, 11, 15, 17, 15, 12, + 8, 6, 2, 4, 3, 0, 2, 3, 4, 2, 4, 4, 2, 2, 3, 5, 2, 4, 5, + 3, 2, 3, 4, 2, 6, 9, 7, 6, 5, 5, 5, 9, 13, 12, 11, 8, 6, 9, + 14, 18, 18, 13, 10, 7, 14, 18, 19, 19, 15, 11, 7, 24, 27, 30, 33, 32, 30, + 27, 24, 26, 29, 32, 33, 31, 27, 22, 25, 28, 31, 33, 31, 29, 21, 25, 28, 32, + 34, 32, 29, 22, 25, 27, 31, 35, 33, 29, 21, 24, 27, 30, 34, 33, 29, 19, 22, + 25, 29, 33, 33, 28, 21, 24, 28, 30, 29, 25, 23, 21, 24, 27, 30, 29, 25, 22, + 20, 22, 26, 29, 28, 27, 23, 20, 22, 26, 29, 28, 27, 24, 21, 23, 26, 29, 29, + 27, 23, 19, 21, 24, 28, 27, 27, 24, 16, 20, 23, 26, 26, 26, 24, 20, 22, 23, + 23, 23, 20, 15, 19, 22, 22, 23, 22, 20, 16, 19, 20, 22, 23, 22, 21, 17, 16, + 22, 23, 23, 23, 21, 18, 15, 21, 21, 21, 22, 21, 18, 13, 19, 20, 20, 21, 20, + 17, 17, 18, 19, 19, 19, 20, 17, 19, 17, 16, 17, 16, 13, 5, 16, 16, 16, 16, + 15, 12, 6, 13, 16, 15, 16, 15, 13, 9, 10, 16, 16, 15, 15, 13, 12, 11, 14, + 14, 14, 14, 12, 8, 12, 13, 13, 13, 13, 12, 6, 17, 18, 13, 12, 12, 11, 5, + 8, 10, 9, 9, 8, 3, 5, 5, 9, 8, 8, 7, 3, 6, 5, 8, 7, 7, 7, + 3, 5, 5, 6, 7, 7, 7, 5, 5, 6, 7, 7, 7, 8, 7, 5, 9, 12, 14, + 12, 9, 8, 6, 15, 18, 17, 13, 10, 8, 6, 2, 1, 1, 1, 2, 3, 3, 2, + 3, 2, 1, 1, 3, 4, 2, 3, 3, 3, 2, 3, 4, 2, 5, 7, 7, 6, 5, + 6, 5, 10, 13, 12, 11, 8, 6, 10, 15, 19, 17, 12, 9, 7, 16, 19, 21, 18, + 14, 10, 8, 4, 6, 4, 2, 0, 2, 3, 4, 6, 5, 3, 1, 2, 3, 4, 6, + 7, 5, 5, 3, 4, 4, 8, 12, 9, 8, 7, 7, 8, 12, 16, 15, 13, 10, 8, + 13, 16, 20, 21, 15, 11, 9, 18, 22, 21, 21, 17, 13, 9, 19, 23, 25, 29, 28, + 25, 22, 19, 21, 24, 27, 28, 26, 23, 17, 20, 24, 27, 30, 27, 24, 17, 20, 24, + 28, 30, 29, 25, 18, 20, 23, 27, 31, 28, 25, 16, 19, 22, 26, 29, 29, 25, 16, + 18, 22, 25, 28, 29, 26, 18, 20, 23, 25, 23, 21, 18, 16, 19, 23, 25, 25, 21, + 19, 15, 18, 21, 25, 24, 22, 20, 15, 19, 22, 25, 24, 23, 20, 16, 18, 21, 24, + 24, 23, 21, 14, 17, 20, 23, 23, 23, 20, 18, 18, 19, 22, 22, 22, 21, 15, 18, + 19, 19, 19, 16, 13, 15, 17, 18, 18, 18, 17, 13, 15, 16, 18, 18, 18, 18, 14, + 14, 17, 18, 18, 18, 18, 15, 12, 15, 17, 17, 17, 17, 15, 13, 15, 16, 17, 16, + 16, 15, 20, 19, 16, 15, 15, 15, 13, 15, 13, 12, 12, 12, 11, 2, 14, 12, 12, + 11, 11, 10, 3, 11, 11, 11, 12, 11, 11, 6, 7, 11, 11, 11, 11, 10, 9, 9, + 10, 10, 10, 10, 10, 6, 13, 14, 13, 11, 9, 9, 6, 19, 21, 16, 13, 10, 8, + 7, 6, 5, 5, 5, 4, 2, 3, 2, 4, 4, 3, 3, 2, 3, 2, 2, 2, 3, + 3, 3, 4, 2, 3, 5, 5, 6, 6, 6, 5, 10, 10, 10, 10, 8, 7, 11, 16, + 17, 15, 11, 9, 7, 18, 21, 20, 15, 13, 10, 8, 3, 4, 2, 2, 1, 2, 2, + 3, 4, 3, 2, 2, 2, 3, 3, 6, 4, 5, 5, 4, 4, 3, 8, 9, 9, 8, + 7, 7, 8, 12, 15, 14, 13, 10, 8, 13, 17, 20, 19, 14, 11, 8, 19, 22, 23, + 21, 16, 12, 9, 7, 9, 6, 3, 2, 0, 2, 7, 9, 7, 4, 3, 2, 2, 7, + 9, 9, 7, 6, 5, 5, 7, 11, 14, 12, 10, 9, 8, 10, 15, 18, 17, 15, 13, + 9, 15, 19, 22, 23, 17, 13, 10, 20, 23, 23, 24, 19, 15, 11, 15, 18, 21, 24, + 25, 22, 18, 14, 17, 20, 24, 25, 22, 20, 13, 16, 20, 23, 26, 24, 21, 12, 16, + 20, 23, 26, 24, 21, 13, 16, 19, 23, 27, 24, 21, 12, 16, 18, 22, 25, 24, 21, + 17, 16, 17, 21, 24, 24, 21, 13, 16, 19, 21, 21, 18, 15, 12, 15, 18, 20, 20, + 18, 15, 11, 14, 17, 20, 21, 19, 16, 10, 14, 18, 21, 21, 19, 17, 11, 14, 17, + 20, 20, 20, 17, 12, 13, 16, 19, 19, 19, 16, 19, 17, 16, 18, 18, 18, 17, 11, + 14, 15, 15, 16, 14, 10, 10, 13, 14, 14, 14, 13, 10, 9, 11, 13, 14, 14, 14, + 11, 9, 12, 14, 14, 14, 14, 12, 8, 11, 13, 13, 13, 13, 12, 14, 14, 14, 13, + 12, 12, 12, 22, 20, 16, 13, 11, 11, 11, 9, 9, 8, 8, 9, 9, 2, 8, 7, + 7, 7, 7, 7, 2, 6, 6, 7, 7, 7, 7, 3, 6, 6, 7, 7, 7, 7, 6, + 7, 8, 9, 9, 9, 7, 6, 14, 16, 14, 12, 10, 8, 6, 21, 22, 17, 13, 10, + 8, 7, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, + 4, 4, 3, 3, 2, 6, 6, 7, 7, 7, 6, 6, 11, 12, 11, 11, 9, 7, 13, + 17, 18, 15, 12, 10, 7, 20, 22, 21, 16, 13, 11, 8, 6, 5, 4, 3, 2, 1, + 2, 5, 7, 4, 3, 3, 2, 2, 6, 9, 6, 6, 5, 4, 4, 6, 10, 10, 10, + 9, 8, 7, 9, 14, 16, 15, 13, 11, 8, 15, 19, 22, 19, 15, 12, 9, 20, 23, + 24, 22, 16, 13, 10, 9, 11, 7, 4, 3, 2, 0, 10, 11, 9, 5, 3, 3, 3, + 9, 11, 12, 8, 7, 6, 5, 9, 13, 16, 13, 11, 10, 9, 12, 16, 20, 19, 16, + 13, 10, 17, 20, 24, 24, 18, 14, 11, 21, 25, 25, 25, 20, 16, 12, 32, 36, 39, + 42, 41, 39, 35, 31, 35, 37, 41, 41, 40, 35, 29, 33, 36, 39, 41, 39, 36, 29, + 32, 35, 39, 42, 40, 37, 29, 31, 35, 39, 42, 41, 37, 27, 31, 34, 38, 42, 40, + 36, 24, 28, 33, 37, 40, 41, 37, 30, 33, 36, 38, 38, 35, 31, 28, 31, 36, 38, + 37, 34, 32, 27, 31, 34, 37, 37, 35, 31, 25, 30, 34, 37, 36, 35, 33, 26, 29, + 33, 36, 36, 36, 33, 24, 29, 31, 35, 36, 35, 32, 21, 26, 30, 34, 34, 34, 32, + 27, 30, 31, 32, 33, 30, 24, 25, 29, 31, 32, 31, 30, 25, 25, 27, 28, 30, 31, + 30, 25, 21, 27, 28, 30, 29, 30, 26, 19, 26, 29, 30, 29, 28, 25, 15, 25, 26, + 28, 27, 27, 25, 16, 23, 24, 25, 27, 27, 25, 24, 24, 25, 25, 25, 22, 13, 21, + 23, 24, 24, 24, 21, 14, 17, 22, 22, 23, 22, 20, 15, 14, 22, 21, 22, 22, 20, + 18, 14, 19, 20, 21, 21, 19, 14, 15, 17, 19, 19, 19, 18, 11, 16, 14, 16, 18, + 18, 17, 8, 12, 16, 17, 17, 15, 10, 12, 9, 15, 15, 15, 14, 10, 13, 9, 13, + 13, 13, 12, 8, 11, 9, 10, 13, 13, 12, 9, 10, 10, 7, 11, 11, 10, 6, 8, + 10, 9, 8, 9, 9, 5, 8, 12, 11, 9, 7, 7, 4, 7, 4, 6, 6, 6, 7, + 9, 11, 4, 4, 4, 5, 6, 9, 10, 4, 2, 2, 3, 4, 7, 9, 4, 2, 1, + 1, 4, 6, 8, 5, 4, 4, 4, 4, 4, 7, 7, 6, 8, 6, 5, 4, 6, 8, + 9, 9, 7, 5, 4, 5, 0, 4, 3, 2, 4, 7, 9, 0, 4, 4, 2, 3, 7, + 9, 0, 4, 5, 2, 2, 6, 8, 0, 4, 5, 2, 2, 4, 6, 2, 4, 5, 5, + 5, 4, 5, 4, 6, 8, 8, 5, 5, 4, 8, 8, 9, 9, 6, 5, 4, 37, 41, + 45, 47, 47, 44, 41, 36, 40, 43, 47, 47, 44, 41, 35, 38, 43, 46, 47, 44, 41, + 33, 37, 41, 45, 48, 45, 42, 35, 37, 41, 45, 48, 46, 43, 33, 37, 40, 43, 47, + 46, 43, 31, 35, 39, 43, 46, 46, 43, 34, 39, 43, 44, 44, 39, 36, 34, 37, 42, + 44, 43, 41, 36, 33, 36, 40, 43, 43, 39, 36, 31, 36, 40, 43, 43, 41, 37, 30, + 36, 39, 42, 42, 42, 38, 28, 34, 37, 40, 40, 41, 37, 25, 32, 37, 40, 39, 39, + 37, 32, 36, 38, 37, 37, 34, 28, 31, 35, 37, 37, 38, 34, 28, 28, 33, 34, 36, + 36, 34, 28, 25, 34, 35, 34, 35, 34, 30, 23, 33, 35, 34, 35, 34, 29, 18, 30, + 32, 34, 34, 32, 30, 18, 28, 32, 31, 33, 32, 28, 29, 30, 31, 31, 30, 25, 16, + 25, 30, 30, 30, 28, 23, 18, 21, 28, 28, 29, 27, 22, 20, 17, 26, 28, 28, 27, + 23, 22, 18, 23, 27, 27, 27, 22, 18, 19, 20, 25, 25, 25, 21, 15, 18, 17, 22, + 23, 24, 21, 11, 16, 22, 23, 22, 17, 12, 16, 12, 20, 21, 21, 16, 11, 18, 13, + 16, 20, 19, 15, 9, 15, 12, 12, 19, 19, 15, 11, 14, 14, 10, 17, 17, 13, 8, + 11, 13, 11, 15, 15, 13, 7, 10, 14, 13, 12, 13, 11, 6, 9, 7, 11, 12, 9, + 9, 11, 13, 7, 8, 10, 8, 7, 10, 12, 7, 5, 8, 7, 6, 8, 10, 7, 4, + 7, 6, 6, 8, 10, 8, 6, 5, 5, 5, 6, 9, 9, 8, 7, 7, 5, 6, 8, + 11, 9, 8, 7, 6, 5, 7, 4, 0, 2, 4, 6, 9, 11, 4, 0, 2, 3, 5, + 7, 10, 4, 0, 3, 2, 5, 9, 10, 4, 1, 3, 2, 4, 5, 8, 4, 3, 5, + 5, 5, 5, 7, 6, 6, 8, 8, 6, 5, 6, 7, 8, 8, 8, 6, 5, 6, 39, + 41, 46, 47, 47, 45, 41, 37, 41, 43, 47, 46, 43, 40, 37, 39, 42, 46, 48, 45, + 42, 35, 38, 43, 46, 48, 46, 43, 36, 39, 43, 45, 49, 46, 44, 35, 38, 42, 45, + 48, 47, 43, 32, 35, 40, 43, 47, 47, 43, 36, 39, 43, 45, 43, 39, 36, 35, 38, + 42, 43, 44, 40, 35, 34, 37, 42, 44, 42, 40, 36, 32, 37, 41, 43, 42, 40, 37, + 31, 37, 40, 43, 43, 41, 37, 29, 35, 39, 42, 42, 40, 37, 25, 33, 38, 41, 40, + 39, 37, 35, 37, 37, 38, 38, 33, 26, 31, 36, 37, 37, 36, 33, 27, 29, 35, 37, + 37, 36, 33, 28, 25, 34, 36, 37, 36, 33, 30, 23, 34, 36, 36, 35, 32, 30, 19, + 31, 34, 35, 35, 32, 30, 19, 29, 33, 33, 33, 31, 27, 29, 31, 31, 31, 30, 24, + 16, 25, 30, 31, 30, 27, 22, 18, 21, 28, 29, 30, 27, 22, 20, 18, 26, 29, 28, + 28, 22, 23, 19, 23, 28, 28, 26, 21, 19, 19, 20, 26, 26, 26, 20, 16, 19, 17, + 24, 24, 24, 20, 12, 16, 23, 23, 22, 16, 10, 16, 13, 20, 22, 21, 15, 10, 17, + 13, 16, 21, 20, 15, 9, 16, 12, 13, 21, 19, 15, 9, 15, 14, 11, 19, 19, 13, + 7, 11, 15, 12, 16, 16, 12, 7, 9, 15, 14, 14, 15, 11, 7, 8, 7, 12, 13, + 8, 7, 9, 12, 8, 7, 12, 8, 6, 8, 10, 7, 4, 10, 7, 6, 8, 10, 7, + 5, 9, 7, 5, 7, 9, 9, 7, 7, 5, 6, 7, 8, 10, 9, 9, 10, 7, 6, + 7, 12, 10, 11, 11, 9, 6, 7, 4, 2, 2, 3, 5, 7, 9, 4, 2, 0, 3, + 5, 6, 9, 4, 2, 2, 2, 5, 8, 9, 4, 2, 5, 3, 4, 6, 8, 5, 4, + 9, 10, 8, 6, 7, 7, 8, 14, 14, 11, 7, 6, 8, 12, 15, 15, 12, 8, 6, + 31, 35, 38, 40, 41, 38, 34, 30, 34, 37, 40, 41, 37, 34, 29, 31, 36, 39, 41, + 39, 35, 28, 32, 36, 38, 42, 39, 36, 29, 32, 35, 39, 42, 40, 36, 28, 32, 34, + 38, 40, 40, 36, 25, 29, 33, 36, 40, 40, 35, 30, 33, 36, 38, 36, 32, 28, 28, + 31, 34, 37, 36, 32, 29, 27, 30, 34, 36, 36, 34, 30, 26, 30, 34, 36, 36, 34, + 30, 26, 30, 33, 36, 36, 35, 31, 24, 29, 32, 34, 35, 34, 30, 22, 26, 31, 34, + 34, 33, 30, 28, 30, 31, 31, 31, 27, 20, 26, 29, 29, 30, 29, 27, 21, 24, 29, + 29, 30, 30, 27, 22, 20, 28, 30, 30, 29, 27, 24, 18, 28, 29, 29, 29, 27, 23, + 16, 26, 28, 28, 28, 26, 23, 17, 24, 25, 26, 27, 26, 21, 24, 25, 24, 24, 22, + 18, 10, 20, 23, 23, 24, 22, 17, 12, 16, 22, 22, 22, 21, 16, 15, 13, 21, 22, + 22, 21, 17, 18, 14, 19, 22, 21, 20, 16, 14, 15, 17, 19, 20, 19, 16, 10, 17, + 15, 18, 18, 18, 16, 7, 12, 17, 16, 16, 11, 5, 11, 8, 15, 15, 15, 11, 6, + 12, 9, 12, 14, 14, 11, 5, 10, 9, 9, 14, 13, 11, 5, 10, 10, 8, 13, 12, + 10, 6, 7, 11, 10, 10, 10, 9, 5, 6, 13, 12, 11, 9, 8, 6, 5, 4, 7, + 7, 5, 4, 5, 7, 4, 5, 5, 5, 3, 5, 6, 4, 3, 4, 4, 4, 5, 6, + 4, 3, 3, 3, 4, 5, 5, 6, 5, 8, 8, 8, 6, 5, 8, 9, 14, 13, 10, + 7, 5, 10, 13, 16, 14, 11, 8, 5, 2, 3, 2, 2, 3, 4, 5, 2, 3, 3, + 0, 2, 4, 5, 2, 3, 4, 2, 2, 4, 5, 2, 5, 8, 6, 5, 5, 5, 4, + 8, 12, 12, 10, 8, 6, 7, 12, 17, 18, 13, 9, 6, 12, 17, 19, 18, 14, 10, + 7, 25, 29, 32, 35, 35, 31, 29, 24, 28, 30, 35, 35, 32, 28, 23, 26, 30, 33, + 35, 32, 30, 23, 26, 30, 33, 36, 33, 30, 24, 25, 29, 32, 36, 34, 30, 22, 25, + 28, 32, 35, 33, 30, 20, 23, 27, 31, 33, 34, 30, 24, 26, 30, 33, 30, 28, 23, + 23, 25, 28, 32, 31, 28, 24, 22, 23, 28, 31, 30, 27, 24, 21, 24, 27, 30, 30, + 28, 25, 21, 25, 27, 30, 29, 29, 25, 20, 23, 25, 29, 29, 29, 25, 17, 20, 24, + 27, 28, 27, 25, 22, 24, 25, 26, 26, 22, 17, 21, 22, 24, 25, 24, 23, 17, 20, + 22, 24, 24, 24, 22, 17, 17, 23, 24, 23, 24, 23, 18, 15, 22, 23, 22, 23, 22, + 18, 13, 20, 21, 21, 22, 21, 18, 15, 18, 19, 20, 20, 21, 17, 20, 19, 18, 18, + 19, 15, 7, 16, 18, 18, 17, 17, 14, 8, 14, 18, 17, 16, 17, 14, 10, 10, 17, + 17, 16, 16, 14, 13, 12, 16, 16, 15, 16, 13, 9, 12, 14, 14, 14, 14, 12, 6, + 15, 16, 12, 12, 13, 12, 5, 9, 11, 11, 11, 9, 4, 6, 5, 10, 9, 9, 8, + 3, 8, 5, 9, 8, 8, 8, 3, 6, 5, 7, 9, 8, 7, 4, 6, 7, 6, 7, + 7, 7, 6, 4, 9, 10, 12, 10, 8, 6, 5, 13, 16, 16, 11, 9, 7, 5, 2, + 2, 1, 2, 2, 3, 4, 2, 2, 1, 0, 2, 3, 4, 2, 2, 2, 2, 2, 3, + 4, 2, 4, 6, 6, 5, 5, 5, 4, 8, 11, 10, 9, 7, 5, 8, 13, 18, 15, + 11, 8, 6, 14, 18, 19, 17, 12, 9, 7, 4, 5, 3, 2, 1, 2, 3, 4, 5, + 4, 2, 0, 2, 4, 4, 5, 6, 4, 3, 2, 3, 4, 7, 10, 8, 7, 6, 6, + 7, 11, 14, 14, 11, 9, 7, 11, 15, 19, 19, 14, 10, 7, 16, 19, 20, 20, 16, + 12, 8, 21, 24, 27, 31, 32, 29, 25, 19, 23, 27, 30, 31, 28, 24, 18, 22, 26, + 29, 30, 28, 25, 18, 21, 24, 28, 31, 28, 25, 19, 21, 24, 27, 31, 29, 25, 17, + 20, 23, 26, 30, 29, 25, 15, 19, 22, 26, 29, 29, 26, 19, 21, 25, 29, 28, 25, + 21, 18, 20, 24, 28, 27, 24, 20, 17, 20, 22, 26, 25, 23, 21, 16, 20, 22, 25, + 25, 24, 21, 17, 19, 22, 24, 24, 24, 21, 15, 18, 21, 23, 24, 23, 21, 16, 16, + 19, 22, 22, 22, 21, 17, 19, 21, 22, 22, 20, 16, 16, 18, 19, 21, 21, 19, 14, + 16, 17, 19, 19, 19, 18, 15, 14, 18, 18, 18, 18, 18, 16, 13, 17, 18, 18, 17, + 18, 15, 11, 15, 17, 17, 17, 16, 15, 17, 16, 15, 15, 16, 16, 14, 16, 14, 14, + 14, 15, 14, 6, 14, 13, 13, 13, 13, 12, 5, 11, 12, 12, 12, 11, 11, 6, 8, + 12, 12, 12, 11, 11, 9, 9, 11, 11, 11, 10, 10, 6, 11, 11, 11, 9, 9, 9, + 4, 17, 18, 13, 10, 8, 8, 4, 7, 7, 6, 6, 7, 4, 5, 2, 5, 5, 5, + 5, 3, 5, 2, 4, 3, 3, 3, 2, 3, 2, 3, 3, 3, 4, 4, 4, 5, 8, + 8, 7, 8, 6, 4, 9, 13, 14, 12, 9, 7, 5, 16, 18, 17, 13, 10, 8, 5, + 2, 3, 2, 2, 2, 3, 4, 2, 4, 3, 2, 2, 2, 2, 2, 5, 4, 3, 2, + 2, 2, 2, 6, 7, 6, 6, 5, 5, 6, 10, 13, 11, 10, 8, 5, 11, 15, 18, + 16, 12, 9, 6, 16, 19, 19, 18, 13, 10, 7, 6, 8, 5, 3, 2, 2, 3, 6, + 7, 7, 4, 2, 0, 2, 6, 7, 8, 5, 4, 3, 3, 6, 9, 12, 9, 8, 7, + 6, 8, 12, 16, 15, 12, 10, 7, 13, 16, 20, 21, 15, 11, 8, 18, 21, 20, 21, + 16, 12, 9, 17, 20, 24, 28, 28, 25, 22, 16, 19, 23, 27, 28, 24, 20, 14, 17, + 21, 24, 26, 24, 20, 13, 17, 20, 23, 27, 24, 21, 14, 17, 20, 23, 27, 25, 21, + 12, 15, 19, 22, 26, 24, 21, 14, 14, 18, 21, 25, 24, 21, 14, 18, 22, 25, 24, + 21, 18, 13, 17, 20, 23, 23, 20, 16, 13, 15, 18, 21, 21, 19, 16, 12, 15, 18, + 20, 21, 19, 16, 12, 15, 18, 20, 20, 20, 17, 10, 13, 16, 19, 20, 19, 17, 16, + 15, 15, 18, 18, 18, 17, 13, 16, 17, 18, 19, 17, 13, 12, 14, 16, 16, 17, 15, + 11, 10, 13, 14, 14, 14, 14, 11, 10, 13, 14, 14, 14, 14, 12, 9, 12, 14, 13, + 13, 14, 12, 12, 12, 12, 12, 13, 12, 12, 18, 17, 13, 11, 11, 11, 11, 11, 10, + 10, 11, 12, 12, 5, 10, 9, 9, 9, 10, 10, 3, 8, 8, 8, 8, 7, 7, 3, + 5, 8, 7, 7, 7, 7, 5, 7, 7, 7, 6, 6, 6, 3, 12, 13, 11, 9, 7, + 6, 4, 18, 18, 14, 10, 8, 6, 4, 2, 2, 2, 3, 3, 4, 4, 1, 1, 0, + 1, 2, 2, 3, 1, 2, 2, 2, 1, 1, 2, 1, 5, 5, 4, 4, 4, 3, 5, + 10, 9, 8, 8, 6, 4, 11, 14, 14, 12, 10, 7, 5, 17, 19, 17, 13, 10, 8, + 5, 5, 5, 4, 3, 3, 3, 4, 5, 7, 4, 4, 3, 1, 2, 5, 8, 6, 4, + 3, 2, 2, 5, 9, 9, 7, 6, 6, 5, 9, 12, 14, 12, 10, 8, 5, 12, 16, + 19, 16, 12, 9, 6, 17, 19, 20, 18, 14, 10, 7, 9, 10, 7, 5, 3, 2, 3, + 10, 10, 9, 5, 4, 2, 0, 9, 10, 11, 7, 5, 4, 3, 10, 11, 14, 10, 8, + 7, 6, 10, 14, 17, 16, 13, 10, 8, 14, 17, 21, 20, 15, 11, 8, 18, 20, 22, + 22, 17, 12, 9, 32, 35, 38, 41, 41, 38, 36, 30, 34, 37, 41, 41, 39, 37, 29, + 32, 37, 40, 42, 39, 37, 28, 32, 36, 39, 42, 39, 37, 28, 31, 35, 39, 42, 41, + 36, 28, 30, 34, 38, 41, 40, 36, 25, 29, 33, 37, 40, 39, 37, 29, 33, 36, 39, + 38, 35, 32, 28, 32, 35, 39, 37, 35, 31, 27, 31, 34, 37, 37, 35, 31, 25, 30, + 33, 36, 36, 36, 33, 25, 30, 33, 36, 35, 36, 32, 24, 27, 31, 35, 36, 35, 33, + 21, 26, 30, 34, 34, 34, 32, 27, 31, 31, 32, 32, 30, 25, 26, 29, 31, 32, 32, + 30, 25, 24, 28, 30, 30, 30, 30, 24, 21, 28, 28, 30, 30, 29, 26, 18, 26, 28, + 29, 29, 29, 25, 15, 25, 27, 27, 28, 28, 25, 16, 22, 25, 26, 26, 27, 25, 24, + 25, 24, 25, 25, 23, 13, 20, 23, 24, 24, 24, 21, 14, 18, 22, 23, 22, 22, 20, + 15, 14, 21, 21, 22, 22, 20, 18, 14, 19, 20, 21, 21, 19, 14, 15, 17, 18, 19, + 19, 18, 11, 16, 14, 16, 17, 18, 17, 8, 12, 16, 17, 17, 15, 10, 13, 9, 15, + 15, 15, 13, 10, 14, 9, 13, 13, 13, 12, 8, 12, 9, 9, 12, 12, 12, 9, 10, + 10, 7, 11, 11, 10, 6, 8, 10, 9, 8, 8, 9, 5, 8, 12, 10, 9, 7, 7, + 4, 7, 4, 6, 6, 6, 7, 9, 11, 4, 4, 4, 5, 6, 9, 10, 4, 2, 2, + 3, 4, 7, 9, 4, 2, 1, 1, 3, 6, 8, 5, 4, 4, 4, 4, 4, 7, 7, + 6, 8, 6, 5, 4, 6, 9, 9, 9, 7, 5, 4, 6, 0, 4, 3, 2, 4, 7, + 9, 0, 4, 4, 2, 4, 6, 8, 0, 4, 5, 2, 2, 6, 8, 0, 4, 4, 2, + 2, 4, 6, 2, 4, 5, 5, 5, 4, 5, 4, 6, 8, 8, 6, 5, 4, 8, 8, + 9, 9, 6, 5, 4, 38, 41, 44, 47, 47, 44, 41, 37, 40, 43, 47, 47, 45, 42, + 35, 39, 42, 46, 47, 45, 42, 34, 37, 42, 45, 48, 46, 42, 34, 38, 41, 45, 49, + 46, 43, 34, 36, 41, 44, 48, 46, 42, 32, 35, 38, 42, 46, 46, 42, 35, 39, 43, + 44, 42, 39, 36, 34, 38, 41, 45, 43, 39, 36, 33, 36, 39, 43, 42, 40, 36, 31, + 36, 39, 43, 41, 40, 37, 31, 35, 39, 43, 41, 41, 37, 28, 34, 38, 41, 40, 40, + 37, 24, 31, 36, 39, 40, 39, 37, 33, 36, 38, 38, 37, 34, 27, 32, 34, 37, 38, + 37, 33, 28, 28, 33, 36, 35, 36, 34, 28, 25, 34, 35, 36, 35, 34, 30, 22, 33, + 35, 35, 35, 33, 30, 19, 31, 32, 33, 33, 32, 29, 19, 28, 31, 32, 33, 31, 28, + 29, 31, 30, 30, 29, 25, 16, 24, 29, 29, 29, 28, 24, 18, 21, 28, 29, 29, 27, + 23, 19, 17, 26, 27, 28, 28, 23, 22, 18, 23, 27, 26, 26, 22, 19, 19, 19, 25, + 25, 24, 22, 14, 19, 17, 23, 24, 24, 20, 11, 16, 22, 21, 22, 17, 12, 16, 13, + 20, 21, 20, 16, 12, 17, 12, 16, 20, 19, 16, 9, 15, 12, 12, 19, 19, 15, 10, + 14, 14, 10, 18, 17, 14, 8, 11, 14, 11, 15, 15, 12, 7, 10, 15, 13, 12, 13, + 11, 6, 9, 7, 11, 12, 9, 9, 10, 13, 7, 8, 10, 8, 7, 10, 12, 7, 5, + 8, 7, 6, 8, 10, 7, 5, 7, 6, 6, 8, 9, 8, 6, 6, 5, 5, 6, 9, + 9, 8, 7, 7, 5, 6, 8, 11, 9, 8, 7, 6, 5, 7, 4, 0, 2, 4, 6, + 9, 11, 4, 0, 2, 3, 5, 7, 10, 4, 0, 3, 2, 5, 9, 9, 4, 1, 3, + 2, 4, 5, 8, 4, 3, 5, 5, 5, 5, 7, 6, 6, 8, 8, 6, 5, 6, 7, + 9, 8, 8, 6, 5, 6, 41, 44, 47, 50, 50, 47, 43, 40, 43, 48, 50, 51, 47, + 44, 39, 42, 46, 48, 51, 46, 44, 37, 41, 45, 48, 51, 48, 45, 38, 41, 45, 49, + 51, 49, 45, 37, 40, 44, 47, 51, 49, 46, 34, 38, 42, 46, 49, 48, 44, 39, 42, + 46, 48, 46, 42, 38, 38, 41, 45, 48, 46, 42, 37, 37, 40, 43, 46, 45, 43, 39, + 33, 40, 43, 46, 46, 43, 39, 33, 40, 43, 45, 45, 44, 39, 30, 38, 40, 44, 44, + 43, 38, 27, 36, 40, 43, 42, 41, 39, 37, 40, 41, 40, 40, 37, 29, 34, 39, 39, + 41, 38, 36, 29, 31, 38, 40, 38, 38, 36, 30, 27, 37, 38, 40, 37, 36, 32, 25, + 35, 38, 38, 37, 35, 32, 21, 33, 36, 36, 36, 34, 32, 21, 30, 35, 35, 36, 33, + 29, 31, 34, 33, 34, 31, 27, 19, 26, 32, 34, 33, 31, 25, 20, 23, 30, 32, 31, + 30, 24, 22, 19, 27, 31, 32, 29, 23, 25, 20, 25, 31, 30, 28, 22, 21, 21, 22, + 29, 28, 27, 22, 17, 21, 18, 26, 27, 26, 21, 14, 18, 26, 26, 25, 18, 13, 19, + 14, 22, 25, 24, 17, 12, 20, 14, 18, 23, 23, 16, 10, 18, 14, 15, 22, 22, 15, + 10, 17, 15, 12, 21, 20, 14, 9, 13, 16, 13, 18, 18, 14, 8, 10, 16, 14, 15, + 17, 12, 8, 9, 9, 13, 15, 10, 9, 11, 15, 9, 9, 14, 10, 8, 10, 13, 9, + 5, 12, 8, 7, 9, 11, 9, 6, 11, 8, 7, 9, 10, 11, 8, 9, 6, 6, 7, + 9, 11, 9, 8, 8, 6, 7, 9, 12, 11, 9, 9, 8, 6, 7, 5, 3, 3, 5, + 7, 9, 12, 5, 3, 2, 4, 6, 8, 11, 5, 3, 0, 4, 7, 9, 11, 5, 3, + 3, 3, 4, 7, 9, 6, 4, 7, 8, 7, 6, 8, 7, 6, 10, 11, 8, 6, 7, + 9, 10, 11, 11, 9, 7, 6, 34, 38, 42, 44, 45, 41, 37, 32, 37, 41, 44, 44, + 41, 37, 31, 35, 39, 43, 43, 41, 36, 30, 33, 37, 40, 43, 40, 37, 30, 33, 37, + 40, 43, 40, 38, 29, 32, 35, 40, 42, 41, 36, 26, 31, 35, 38, 42, 41, 38, 32, + 35, 39, 43, 40, 36, 33, 31, 34, 38, 41, 40, 37, 32, 30, 32, 36, 39, 38, 35, + 30, 27, 31, 34, 37, 38, 35, 31, 27, 31, 34, 38, 37, 36, 31, 25, 30, 33, 36, + 37, 35, 31, 21, 27, 32, 35, 35, 34, 31, 29, 33, 34, 35, 33, 31, 25, 27, 31, + 33, 35, 33, 30, 24, 24, 30, 31, 32, 31, 29, 23, 21, 30, 30, 30, 30, 28, 24, + 19, 28, 30, 30, 29, 28, 24, 16, 26, 28, 28, 29, 26, 25, 16, 24, 27, 26, 28, + 26, 22, 23, 27, 26, 28, 27, 22, 15, 20, 25, 26, 26, 26, 21, 15, 17, 23, 24, + 24, 23, 18, 16, 14, 23, 23, 23, 21, 18, 19, 15, 19, 23, 22, 21, 17, 15, 15, + 17, 21, 21, 20, 16, 11, 16, 15, 19, 19, 20, 16, 7, 13, 19, 18, 19, 15, 9, + 15, 9, 17, 18, 17, 14, 8, 15, 9, 13, 16, 15, 12, 6, 12, 9, 10, 15, 14, + 11, 6, 10, 10, 8, 14, 13, 10, 5, 7, 11, 9, 11, 11, 9, 4, 5, 12, 11, + 9, 10, 8, 4, 5, 4, 9, 9, 8, 6, 8, 11, 4, 6, 8, 7, 5, 7, 9, + 4, 3, 5, 5, 3, 5, 6, 4, 3, 4, 4, 3, 4, 5, 6, 4, 5, 5, 6, + 4, 5, 7, 6, 11, 10, 7, 5, 5, 9, 11, 12, 12, 9, 6, 4, 2, 2, 2, + 3, 5, 7, 8, 2, 2, 2, 2, 4, 5, 7, 2, 2, 3, 0, 3, 5, 6, 2, + 3, 6, 4, 3, 3, 4, 3, 5, 9, 10, 8, 5, 4, 5, 9, 15, 15, 11, 7, + 4, 9, 14, 17, 17, 12, 8, 5, 27, 33, 36, 39, 39, 37, 33, 27, 30, 35, 38, + 40, 37, 32, 25, 29, 34, 37, 38, 34, 30, 25, 27, 32, 35, 37, 34, 32, 25, 27, + 30, 34, 37, 35, 31, 24, 26, 29, 33, 36, 34, 31, 21, 24, 28, 32, 35, 34, 32, + 26, 29, 34, 37, 35, 32, 28, 24, 29, 32, 35, 36, 32, 27, 24, 26, 30, 33, 33, + 30, 25, 23, 25, 28, 31, 31, 29, 26, 23, 25, 28, 31, 31, 28, 26, 21, 24, 27, + 30, 30, 29, 26, 18, 22, 25, 28, 29, 28, 26, 24, 26, 29, 30, 30, 27, 22, 22, + 25, 28, 28, 29, 26, 20, 21, 24, 26, 26, 26, 25, 18, 17, 24, 24, 24, 25, 24, + 19, 16, 23, 23, 23, 23, 22, 19, 13, 21, 22, 22, 22, 20, 19, 14, 19, 21, 21, + 21, 21, 17, 21, 22, 21, 22, 23, 20, 13, 17, 20, 21, 21, 21, 18, 12, 14, 19, + 19, 18, 19, 15, 12, 11, 19, 17, 17, 17, 14, 13, 12, 16, 16, 17, 16, 13, 10, + 13, 14, 15, 15, 15, 13, 7, 14, 13, 13, 13, 13, 13, 4, 9, 14, 14, 15, 13, + 9, 13, 6, 13, 12, 13, 12, 6, 12, 6, 10, 10, 10, 9, 4, 8, 6, 7, 9, + 9, 8, 4, 6, 7, 5, 8, 7, 7, 3, 4, 8, 7, 8, 7, 6, 3, 4, 10, + 11, 11, 8, 5, 4, 3, 2, 4, 5, 5, 5, 7, 9, 2, 2, 3, 4, 4, 5, + 7, 2, 0, 1, 1, 2, 3, 4, 2, 2, 3, 2, 2, 2, 3, 4, 5, 8, 7, + 6, 4, 3, 5, 9, 14, 12, 8, 5, 3, 10, 13, 16, 13, 9, 6, 3, 3, 6, + 4, 2, 5, 6, 7, 2, 5, 5, 2, 3, 4, 5, 3, 6, 7, 3, 0, 3, 4, + 2, 5, 7, 5, 4, 3, 3, 4, 7, 11, 11, 8, 6, 4, 7, 11, 15, 15, 11, + 7, 4, 12, 16, 16, 16, 12, 8, 5, 24, 29, 32, 36, 35, 32, 29, 23, 27, 31, + 35, 34, 31, 28, 21, 25, 29, 33, 34, 30, 26, 20, 22, 26, 30, 32, 29, 27, 19, + 22, 24, 28, 32, 30, 27, 18, 21, 23, 27, 31, 30, 27, 16, 19, 23, 26, 29, 30, + 26, 22, 25, 28, 33, 31, 28, 25, 20, 24, 28, 31, 31, 27, 24, 19, 22, 26, 30, + 29, 26, 22, 18, 20, 23, 26, 26, 25, 21, 18, 20, 22, 26, 26, 25, 22, 16, 19, + 22, 25, 24, 24, 22, 13, 17, 20, 23, 23, 24, 22, 19, 22, 24, 26, 26, 24, 20, + 18, 21, 23, 24, 25, 23, 18, 17, 20, 22, 21, 22, 21, 16, 15, 19, 19, 19, 20, + 19, 15, 13, 17, 19, 18, 18, 18, 15, 11, 16, 17, 17, 18, 17, 16, 13, 14, 15, + 16, 16, 17, 14, 17, 17, 17, 18, 19, 18, 10, 15, 16, 17, 17, 17, 15, 9, 11, + 15, 15, 15, 14, 13, 8, 8, 14, 13, 12, 12, 11, 10, 9, 12, 12, 11, 11, 10, + 6, 10, 10, 10, 10, 10, 9, 3, 13, 14, 10, 8, 9, 8, 3, 7, 9, 10, 10, + 11, 8, 10, 3, 7, 8, 9, 9, 5, 9, 3, 6, 6, 6, 6, 3, 5, 3, 4, + 4, 4, 3, 2, 3, 5, 5, 4, 4, 4, 3, 3, 7, 9, 10, 8, 6, 4, 2, + 11, 14, 13, 10, 7, 4, 2, 0, 2, 2, 3, 4, 6, 8, 0, 4, 3, 3, 3, + 4, 5, 0, 4, 3, 2, 1, 2, 3, 0, 5, 5, 3, 3, 2, 2, 3, 7, 9, + 8, 7, 4, 2, 7, 12, 15, 12, 9, 5, 3, 12, 15, 16, 14, 10, 7, 4, 6, + 9, 6, 3, 3, 5, 6, 6, 9, 8, 4, 2, 3, 4, 6, 9, 11, 5, 3, 0, + 3, 6, 7, 9, 6, 4, 4, 3, 6, 9, 12, 12, 9, 6, 4, 9, 13, 16, 16, + 11, 8, 4, 14, 17, 17, 17, 13, 9, 5, 20, 23, 27, 31, 30, 28, 24, 19, 22, + 26, 31, 31, 27, 24, 17, 21, 25, 28, 29, 26, 22, 16, 19, 22, 25, 27, 24, 21, + 14, 17, 20, 23, 27, 25, 22, 14, 16, 19, 23, 26, 25, 21, 11, 14, 18, 22, 25, + 25, 22, 17, 20, 25, 29, 28, 25, 21, 16, 20, 24, 28, 27, 23, 20, 15, 18, 22, + 24, 24, 22, 18, 14, 16, 19, 21, 21, 19, 17, 13, 16, 18, 20, 20, 21, 17, 11, + 14, 17, 20, 20, 20, 17, 12, 12, 16, 19, 19, 18, 17, 15, 18, 21, 22, 23, 21, + 16, 14, 17, 19, 20, 21, 20, 15, 13, 16, 18, 18, 18, 17, 13, 12, 14, 14, 14, + 15, 15, 12, 10, 13, 14, 14, 14, 14, 12, 9, 11, 12, 12, 13, 12, 12, 13, 12, + 11, 11, 11, 11, 11, 13, 13, 13, 14, 15, 15, 8, 11, 11, 12, 13, 13, 13, 7, + 9, 10, 11, 10, 10, 10, 6, 5, 9, 8, 7, 7, 7, 6, 7, 7, 7, 7, 6, + 6, 3, 9, 9, 8, 6, 5, 5, 2, 13, 13, 9, 7, 5, 4, 2, 4, 5, 5, + 6, 7, 7, 8, 1, 3, 4, 5, 5, 5, 6, 1, 1, 2, 2, 2, 2, 3, 1, + 3, 2, 1, 2, 1, 2, 3, 6, 6, 5, 5, 3, 2, 8, 11, 11, 9, 6, 4, + 2, 12, 14, 13, 10, 8, 6, 3, 5, 5, 4, 4, 4, 6, 7, 5, 7, 4, 4, + 4, 3, 4, 5, 7, 5, 4, 2, 1, 2, 5, 7, 6, 5, 3, 3, 2, 6, 9, + 11, 9, 7, 6, 3, 9, 12, 15, 13, 9, 6, 4, 13, 15, 16, 14, 10, 7, 4, + 8, 10, 7, 4, 4, 5, 5, 8, 10, 9, 5, 3, 3, 3, 8, 10, 11, 6, 4, + 3, 0, 8, 9, 11, 7, 5, 4, 3, 8, 10, 14, 13, 9, 7, 5, 11, 14, 17, + 16, 12, 8, 6, 14, 16, 17, 17, 13, 9, 6, 32, 35, 38, 42, 42, 39, 35, 31, + 35, 38, 41, 41, 39, 37, 29, 33, 37, 40, 41, 39, 37, 29, 31, 35, 38, 42, 39, + 37, 28, 31, 35, 39, 42, 40, 37, 27, 31, 35, 37, 41, 40, 36, 24, 28, 33, 36, + 41, 39, 36, 29, 33, 37, 39, 38, 34, 32, 29, 32, 35, 38, 37, 35, 31, 27, 30, + 33, 38, 37, 34, 32, 26, 29, 33, 36, 36, 35, 33, 26, 29, 33, 35, 36, 36, 33, + 23, 28, 31, 35, 35, 35, 33, 21, 25, 29, 33, 34, 34, 32, 27, 31, 32, 32, 33, + 30, 24, 26, 28, 32, 31, 32, 29, 25, 24, 28, 29, 30, 30, 29, 24, 21, 28, 28, + 29, 30, 30, 26, 19, 26, 29, 28, 29, 28, 26, 15, 24, 27, 27, 28, 27, 26, 16, + 22, 25, 25, 27, 26, 25, 24, 25, 25, 25, 25, 22, 13, 21, 23, 24, 24, 24, 21, + 14, 18, 22, 23, 23, 22, 20, 15, 13, 22, 22, 22, 23, 20, 17, 15, 20, 21, 21, + 21, 19, 14, 15, 17, 19, 19, 19, 18, 11, 16, 14, 16, 17, 18, 17, 8, 12, 17, + 16, 17, 14, 10, 13, 9, 15, 15, 15, 14, 10, 14, 9, 12, 13, 13, 13, 8, 12, + 9, 10, 13, 12, 12, 9, 10, 10, 7, 11, 11, 10, 6, 8, 10, 9, 8, 9, 9, + 5, 8, 12, 10, 9, 7, 7, 4, 7, 4, 6, 6, 6, 7, 9, 10, 4, 4, 4, + 5, 5, 9, 10, 4, 2, 2, 3, 4, 7, 9, 4, 2, 1, 1, 4, 6, 8, 5, + 4, 4, 4, 4, 4, 7, 7, 6, 8, 6, 4, 4, 6, 9, 9, 8, 7, 5, 4, + 5, 0, 4, 3, 2, 4, 7, 9, 0, 4, 4, 2, 4, 6, 8, 0, 4, 5, 2, + 2, 6, 8, 0, 4, 4, 2, 2, 4, 6, 2, 4, 6, 5, 5, 4, 5, 4, 6, + 8, 8, 6, 5, 4, 8, 8, 9, 9, 6, 5, 4, 38, 42, 46, 49, 49, 46, 42, + 37, 41, 46, 48, 50, 45, 42, 36, 39, 44, 47, 48, 45, 40, 34, 38, 41, 45, 48, + 44, 41, 34, 37, 41, 45, 48, 45, 41, 32, 37, 40, 43, 47, 46, 42, 30, 34, 39, + 43, 46, 46, 42, 36, 40, 44, 46, 44, 41, 37, 34, 38, 42, 45, 45, 40, 37, 33, + 37, 42, 43, 44, 41, 38, 30, 36, 39, 42, 40, 39, 37, 30, 35, 38, 42, 42, 40, + 36, 27, 33, 36, 40, 41, 39, 38, 24, 31, 35, 39, 39, 37, 37, 32, 36, 39, 39, + 39, 36, 29, 32, 35, 37, 39, 37, 35, 29, 28, 34, 36, 37, 36, 35, 28, 25, 34, + 33, 34, 35, 33, 29, 22, 32, 34, 34, 34, 33, 30, 18, 29, 31, 33, 33, 32, 29, + 17, 27, 30, 31, 32, 31, 27, 28, 31, 32, 31, 31, 27, 19, 24, 30, 31, 31, 30, + 25, 19, 20, 27, 29, 28, 28, 24, 21, 16, 26, 27, 27, 26, 22, 22, 17, 22, 26, + 26, 25, 22, 18, 18, 19, 24, 24, 24, 21, 14, 17, 15, 22, 23, 23, 20, 11, 15, + 22, 23, 24, 18, 14, 19, 12, 20, 22, 21, 18, 13, 19, 12, 16, 19, 19, 17, 10, + 16, 12, 12, 18, 18, 15, 10, 13, 13, 9, 17, 16, 13, 8, 10, 12, 10, 14, 14, + 12, 7, 10, 13, 12, 11, 12, 10, 6, 8, 7, 11, 13, 11, 9, 12, 15, 7, 7, + 11, 10, 8, 11, 13, 7, 5, 9, 8, 7, 8, 11, 7, 4, 7, 6, 7, 9, 9, + 7, 5, 5, 4, 4, 6, 8, 8, 7, 6, 6, 4, 5, 8, 10, 8, 8, 6, 5, + 4, 6, 4, 1, 2, 6, 8, 10, 13, 4, 1, 2, 5, 7, 9, 10, 4, 1, 3, + 3, 5, 7, 9, 4, 0, 3, 1, 3, 5, 7, 4, 2, 4, 4, 4, 4, 6, 5, + 5, 7, 7, 5, 4, 6, 7, 7, 7, 7, 5, 4, 5, 45, 49, 52, 55, 56, 52, + 48, 43, 47, 51, 55, 54, 51, 47, 41, 45, 50, 52, 53, 50, 46, 40, 44, 47, 51, + 52, 49, 46, 38, 41, 45, 49, 52, 50, 46, 37, 41, 44, 48, 51, 50, 46, 34, 39, + 43, 47, 50, 49, 47, 42, 45, 49, 53, 51, 48, 43, 40, 45, 49, 53, 51, 47, 42, + 37, 43, 47, 51, 49, 46, 40, 35, 40, 44, 48, 46, 45, 40, 33, 41, 44, 46, 45, + 45, 40, 30, 39, 42, 45, 45, 44, 40, 26, 36, 40, 44, 43, 42, 40, 38, 43, 45, + 46, 45, 42, 34, 34, 41, 44, 44, 44, 40, 34, 31, 40, 42, 41, 41, 39, 33, 28, + 37, 39, 39, 38, 36, 33, 24, 36, 38, 40, 38, 35, 33, 21, 32, 37, 37, 37, 34, + 33, 19, 30, 34, 35, 35, 34, 30, 31, 37, 38, 37, 36, 32, 25, 27, 34, 36, 35, + 35, 30, 25, 24, 31, 35, 34, 33, 27, 25, 20, 28, 31, 32, 30, 25, 26, 20, 25, + 31, 31, 29, 23, 22, 21, 21, 29, 29, 28, 23, 19, 20, 17, 26, 28, 27, 22, 14, + 18, 27, 29, 29, 23, 19, 25, 15, 23, 27, 27, 22, 16, 25, 15, 19, 25, 25, 20, + 13, 20, 15, 15, 23, 23, 17, 11, 17, 15, 12, 21, 21, 15, 10, 14, 16, 12, 18, + 19, 15, 8, 12, 15, 13, 14, 17, 13, 8, 12, 10, 14, 19, 15, 13, 16, 21, 10, + 10, 17, 13, 12, 14, 18, 10, 6, 15, 11, 9, 11, 14, 10, 5, 11, 8, 7, 10, + 11, 10, 6, 9, 6, 5, 8, 10, 10, 8, 6, 5, 4, 6, 10, 11, 9, 7, 5, + 4, 6, 8, 5, 3, 6, 9, 12, 14, 16, 5, 3, 5, 8, 10, 12, 14, 5, 3, + 3, 6, 7, 9, 11, 5, 3, 0, 3, 6, 10, 10, 5, 3, 3, 3, 3, 5, 8, + 6, 5, 5, 6, 4, 5, 7, 8, 6, 6, 6, 5, 4, 6, 38, 43, 47, 49, 51, + 47, 43, 36, 41, 43, 50, 49, 46, 41, 35, 39, 44, 46, 47, 45, 39, 34, 37, 40, + 44, 46, 42, 38, 31, 34, 38, 42, 44, 42, 38, 30, 34, 36, 40, 44, 43, 37, 28, + 31, 35, 39, 42, 42, 38, 34, 40, 44, 47, 45, 42, 38, 34, 38, 42, 46, 45, 41, + 37, 32, 36, 40, 43, 43, 39, 34, 31, 34, 37, 40, 39, 38, 33, 27, 32, 35, 38, + 38, 37, 33, 24, 32, 34, 37, 37, 36, 33, 20, 29, 33, 36, 36, 35, 34, 33, 36, + 38, 38, 39, 36, 30, 29, 34, 38, 39, 39, 35, 29, 26, 33, 36, 36, 36, 34, 27, + 23, 31, 32, 33, 33, 31, 26, 19, 29, 32, 32, 31, 29, 25, 15, 28, 30, 31, 31, + 28, 25, 15, 25, 28, 29, 29, 27, 24, 26, 30, 31, 31, 32, 28, 21, 22, 29, 30, + 31, 30, 25, 20, 18, 26, 28, 29, 27, 23, 20, 16, 22, 25, 25, 25, 19, 20, 14, + 19, 25, 24, 23, 17, 16, 15, 16, 22, 22, 21, 18, 12, 15, 13, 20, 20, 20, 17, + 9, 14, 22, 23, 24, 20, 15, 20, 10, 19, 21, 22, 18, 13, 21, 11, 14, 19, 19, + 16, 10, 16, 10, 9, 17, 16, 12, 7, 12, 10, 7, 15, 15, 11, 7, 9, 11, 8, + 12, 12, 10, 5, 7, 11, 9, 10, 11, 9, 4, 6, 5, 11, 14, 12, 11, 13, 17, + 5, 7, 12, 11, 10, 11, 14, 6, 3, 9, 8, 7, 8, 10, 5, 3, 6, 5, 4, + 5, 7, 5, 3, 4, 3, 2, 4, 6, 6, 5, 7, 6, 4, 3, 7, 8, 7, 8, + 8, 5, 3, 4, 2, 2, 4, 7, 9, 12, 13, 2, 2, 3, 6, 8, 9, 10, 2, + 2, 3, 4, 5, 6, 8, 2, 1, 3, 0, 3, 5, 6, 2, 1, 5, 6, 4, 3, + 5, 3, 5, 11, 11, 7, 3, 4, 5, 9, 12, 13, 8, 4, 3, 32, 37, 41, 44, + 43, 41, 38, 30, 35, 39, 44, 44, 41, 36, 30, 34, 39, 41, 42, 38, 34, 28, 32, + 35, 38, 41, 37, 32, 26, 29, 31, 35, 38, 36, 32, 24, 27, 30, 34, 38, 36, 33, + 22, 25, 29, 34, 36, 36, 32, 30, 35, 38, 41, 41, 37, 33, 30, 32, 36, 40, 38, + 36, 31, 27, 31, 35, 38, 37, 34, 30, 25, 29, 32, 35, 35, 32, 27, 23, 26, 30, + 32, 32, 31, 28, 21, 25, 28, 30, 31, 30, 27, 18, 23, 27, 30, 29, 29, 28, 27, + 31, 33, 34, 35, 33, 26, 25, 29, 31, 33, 33, 30, 24, 23, 28, 31, 30, 31, 29, + 23, 19, 26, 27, 26, 28, 26, 21, 15, 24, 25, 25, 25, 24, 21, 13, 23, 24, 23, + 23, 23, 21, 12, 21, 22, 22, 23, 23, 19, 22, 25, 26, 27, 27, 25, 18, 19, 24, + 24, 25, 25, 22, 17, 15, 22, 23, 23, 22, 19, 16, 12, 19, 19, 19, 20, 16, 16, + 11, 16, 18, 17, 17, 14, 12, 12, 13, 16, 16, 16, 13, 9, 12, 11, 15, 14, 15, + 13, 6, 10, 17, 18, 18, 17, 13, 18, 7, 16, 16, 17, 16, 10, 17, 7, 12, 15, + 14, 13, 8, 12, 7, 7, 11, 10, 10, 5, 8, 7, 4, 9, 9, 8, 4, 5, 7, + 6, 6, 7, 6, 3, 5, 9, 8, 7, 5, 5, 2, 4, 3, 8, 9, 9, 9, 11, + 15, 3, 6, 7, 8, 8, 9, 11, 3, 2, 5, 4, 6, 6, 7, 3, 1, 1, 1, + 3, 3, 4, 2, 2, 3, 3, 2, 2, 4, 4, 5, 9, 8, 4, 2, 5, 6, 9, + 11, 9, 6, 2, 3, 2, 4, 4, 6, 8, 10, 11, 2, 4, 4, 5, 7, 8, 8, + 2, 4, 5, 3, 4, 4, 5, 2, 3, 7, 3, 0, 3, 4, 1, 4, 7, 7, 5, + 2, 3, 3, 8, 11, 12, 7, 3, 2, 8, 12, 13, 12, 8, 4, 2, 27, 32, 36, + 39, 40, 36, 33, 27, 30, 35, 39, 38, 35, 32, 25, 29, 33, 37, 38, 34, 30, 25, + 26, 30, 34, 36, 32, 27, 21, 24, 27, 30, 34, 31, 27, 19, 22, 25, 28, 32, 31, + 28, 18, 20, 24, 27, 30, 31, 27, 26, 29, 34, 37, 35, 33, 28, 24, 27, 31, 35, + 36, 31, 28, 23, 26, 30, 33, 32, 29, 24, 21, 24, 28, 30, 29, 28, 23, 19, 21, + 24, 26, 26, 26, 22, 17, 20, 22, 25, 26, 25, 22, 14, 18, 22, 25, 24, 24, 22, + 23, 26, 28, 29, 31, 28, 24, 22, 25, 27, 28, 28, 27, 21, 20, 25, 25, 26, 26, + 25, 19, 17, 22, 22, 22, 22, 22, 17, 13, 19, 20, 19, 20, 19, 16, 10, 18, 19, + 19, 18, 18, 17, 10, 15, 17, 17, 18, 17, 15, 20, 21, 21, 22, 23, 22, 15, 17, + 20, 19, 21, 21, 20, 14, 13, 19, 19, 18, 18, 17, 13, 9, 16, 15, 15, 14, 13, + 12, 8, 13, 13, 12, 12, 11, 8, 9, 11, 11, 11, 11, 10, 6, 10, 8, 9, 9, + 10, 9, 4, 8, 13, 13, 14, 15, 12, 15, 5, 12, 12, 13, 13, 9, 13, 5, 10, + 10, 9, 10, 7, 9, 5, 5, 6, 6, 6, 3, 5, 4, 2, 4, 3, 3, 3, 3, + 5, 5, 5, 4, 2, 2, 4, 6, 7, 7, 5, 3, 1, 3, 2, 4, 6, 7, 8, + 10, 12, 2, 3, 5, 6, 7, 8, 9, 2, 3, 4, 4, 4, 5, 6, 2, 2, 2, + 2, 1, 2, 3, 2, 3, 6, 4, 3, 1, 3, 3, 7, 10, 8, 5, 2, 3, 6, + 9, 10, 9, 6, 3, 2, 4, 6, 5, 5, 7, 9, 10, 4, 6, 6, 5, 6, 7, + 7, 3, 5, 7, 3, 3, 4, 5, 4, 5, 10, 5, 3, 0, 3, 4, 6, 8, 8, + 5, 3, 1, 6, 9, 12, 11, 7, 4, 1, 9, 11, 12, 12, 8, 5, 2, 24, 27, + 32, 36, 36, 33, 29, 23, 26, 30, 34, 35, 32, 28, 21, 25, 29, 32, 33, 30, 26, + 20, 22, 26, 29, 32, 28, 23, 17, 19, 22, 26, 28, 26, 23, 15, 17, 20, 23, 27, + 26, 22, 14, 16, 19, 22, 26, 26, 22, 21, 25, 28, 33, 31, 29, 25, 20, 24, 28, + 31, 31, 27, 23, 19, 22, 26, 28, 28, 25, 22, 18, 20, 23, 25, 25, 24, 19, 15, + 17, 19, 21, 22, 22, 18, 13, 15, 18, 20, 20, 21, 18, 11, 14, 17, 20, 19, 19, + 18, 19, 22, 24, 25, 27, 25, 20, 18, 21, 23, 24, 24, 23, 18, 17, 20, 21, 22, + 22, 21, 17, 15, 17, 18, 18, 18, 18, 13, 10, 14, 15, 15, 15, 15, 13, 6, 13, + 14, 14, 14, 14, 13, 7, 12, 13, 12, 12, 12, 12, 17, 17, 17, 18, 19, 19, 13, + 15, 15, 16, 16, 17, 17, 11, 11, 14, 15, 14, 14, 13, 10, 7, 12, 11, 10, 10, + 10, 9, 5, 9, 8, 8, 7, 7, 6, 6, 7, 6, 6, 6, 6, 3, 7, 4, 5, + 5, 5, 5, 3, 7, 9, 9, 10, 11, 11, 13, 2, 7, 8, 9, 9, 8, 11, 2, + 6, 6, 5, 6, 6, 6, 2, 3, 3, 2, 2, 2, 3, 1, 2, 2, 2, 2, 0, + 2, 2, 5, 4, 3, 2, 1, 2, 3, 6, 6, 4, 3, 2, 1, 3, 4, 5, 7, + 8, 9, 11, 3, 4, 5, 6, 6, 7, 8, 3, 6, 4, 4, 4, 4, 5, 3, 5, + 4, 3, 2, 1, 2, 3, 6, 6, 5, 3, 2, 1, 5, 7, 9, 7, 4, 2, 0, + 6, 7, 9, 8, 5, 3, 1, 6, 7, 6, 5, 7, 8, 9, 6, 8, 7, 5, 6, + 6, 6, 6, 8, 9, 4, 3, 3, 3, 6, 8, 9, 6, 4, 2, 0, 6, 8, 10, + 8, 4, 3, 2, 7, 9, 11, 10, 6, 3, 2, 7, 9, 11, 10, 7, 4, 2, 33, + 38, 42, 45, 45, 42, 39, 33, 37, 41, 45, 45, 43, 37, 30, 35, 39, 42, 43, 41, + 38, 30, 33, 36, 40, 43, 39, 36, 27, 30, 34, 38, 41, 40, 36, 26, 30, 33, 36, + 40, 39, 35, 23, 27, 32, 36, 39, 38, 36, 31, 36, 39, 42, 41, 38, 35, 29, 33, + 38, 41, 41, 37, 33, 28, 32, 36, 40, 39, 37, 32, 27, 30, 34, 36, 36, 36, 31, + 25, 28, 32, 34, 35, 34, 30, 22, 27, 29, 33, 34, 33, 31, 20, 24, 28, 33, 32, + 33, 31, 28, 32, 35, 34, 36, 34, 28, 27, 30, 32, 35, 35, 32, 28, 24, 29, 32, + 33, 31, 32, 27, 21, 28, 28, 30, 29, 29, 25, 17, 25, 27, 28, 28, 28, 25, 14, + 24, 26, 26, 26, 27, 26, 14, 21, 24, 25, 24, 25, 24, 24, 26, 27, 28, 29, 26, + 17, 20, 25, 26, 28, 28, 25, 17, 17, 23, 25, 24, 24, 23, 18, 13, 20, 21, 21, + 21, 19, 18, 13, 18, 20, 19, 19, 18, 14, 14, 15, 17, 18, 18, 18, 10, 14, 12, + 15, 16, 17, 16, 9, 12, 18, 19, 20, 19, 14, 17, 9, 16, 17, 18, 17, 12, 17, + 8, 13, 15, 15, 15, 10, 14, 9, 8, 12, 12, 12, 8, 10, 8, 5, 10, 10, 9, + 7, 8, 9, 7, 7, 8, 8, 5, 10, 10, 8, 7, 6, 6, 3, 8, 4, 8, 9, + 9, 9, 12, 14, 4, 6, 7, 8, 9, 10, 13, 4, 2, 5, 5, 6, 8, 10, 4, + 2, 1, 1, 4, 6, 8, 4, 2, 2, 2, 2, 3, 8, 5, 4, 6, 4, 3, 2, + 6, 7, 7, 6, 5, 3, 2, 5, 2, 4, 4, 5, 8, 10, 12, 2, 4, 5, 4, + 7, 8, 10, 2, 4, 5, 3, 4, 6, 7, 2, 4, 5, 2, 1, 4, 7, 0, 4, + 5, 3, 3, 2, 5, 3, 4, 6, 6, 4, 3, 4, 5, 6, 6, 6, 4, 3, 2, + 41, 45, 50, 51, 52, 50, 46, 40, 43, 48, 51, 53, 48, 44, 37, 41, 46, 50, 51, + 48, 43, 36, 39, 43, 46, 50, 46, 41, 33, 36, 41, 44, 47, 45, 41, 32, 35, 39, + 42, 46, 45, 42, 28, 34, 37, 41, 45, 45, 41, 37, 41, 47, 49, 48, 44, 41, 35, + 41, 44, 49, 48, 44, 40, 33, 39, 43, 47, 44, 42, 38, 33, 37, 40, 44, 42, 41, + 36, 29, 34, 37, 40, 41, 39, 36, 25, 33, 36, 39, 40, 38, 36, 22, 30, 35, 38, + 39, 38, 36, 34, 39, 42, 42, 42, 39, 34, 32, 37, 40, 41, 42, 38, 32, 29, 36, + 37, 38, 39, 37, 31, 25, 33, 35, 35, 35, 34, 29, 20, 31, 33, 33, 34, 32, 30, + 16, 29, 31, 31, 32, 31, 29, 16, 26, 30, 30, 31, 30, 27, 28, 33, 34, 34, 34, + 32, 23, 24, 31, 32, 34, 33, 29, 23, 20, 29, 31, 30, 30, 27, 23, 17, 24, 27, + 27, 27, 24, 23, 15, 20, 25, 26, 25, 21, 19, 16, 18, 23, 23, 24, 20, 15, 16, + 14, 21, 22, 22, 20, 11, 16, 24, 25, 26, 23, 18, 24, 12, 21, 23, 24, 22, 16, + 23, 12, 17, 21, 21, 19, 13, 19, 12, 11, 18, 17, 15, 10, 14, 11, 8, 16, 15, + 13, 9, 11, 12, 9, 13, 13, 12, 8, 10, 12, 10, 11, 12, 11, 8, 9, 7, 13, + 15, 14, 14, 16, 20, 7, 9, 14, 13, 12, 14, 16, 7, 4, 11, 11, 9, 11, 13, + 7, 4, 7, 7, 6, 8, 10, 6, 4, 4, 4, 3, 8, 9, 7, 5, 4, 3, 2, + 5, 9, 8, 7, 5, 4, 2, 4, 8, 4, 3, 5, 9, 12, 14, 16, 4, 3, 4, + 8, 11, 12, 14, 4, 3, 4, 5, 7, 9, 11, 4, 2, 3, 1, 4, 7, 8, 4, + 0, 4, 3, 2, 4, 8, 3, 3, 4, 5, 3, 3, 7, 5, 5, 5, 5, 3, 2, + 5, 47, 50, 55, 58, 58, 55, 52, 45, 50, 53, 58, 57, 54, 50, 43, 48, 52, 54, + 56, 52, 48, 42, 45, 49, 51, 55, 51, 45, 39, 42, 45, 49, 52, 50, 45, 36, 40, + 43, 47, 50, 49, 45, 32, 38, 43, 46, 49, 51, 45, 42, 47, 51, 55, 54, 50, 47, + 42, 45, 51, 55, 54, 49, 44, 40, 44, 48, 53, 51, 47, 43, 36, 43, 47, 49, 48, + 46, 40, 32, 39, 42, 46, 46, 44, 39, 28, 36, 41, 45, 43, 44, 40, 24, 35, 40, + 44, 43, 41, 40, 38, 43, 47, 47, 48, 45, 38, 36, 43, 46, 48, 47, 43, 37, 32, + 40, 44, 44, 44, 43, 35, 28, 38, 40, 40, 40, 38, 34, 22, 34, 37, 38, 37, 36, + 33, 19, 32, 37, 36, 36, 35, 33, 18, 28, 34, 35, 35, 33, 31, 32, 39, 39, 42, + 40, 36, 30, 28, 36, 38, 39, 38, 34, 28, 24, 33, 37, 36, 35, 29, 28, 21, 28, + 33, 33, 33, 27, 27, 18, 23, 31, 30, 29, 23, 23, 19, 19, 28, 28, 28, 23, 20, + 18, 15, 25, 27, 27, 22, 15, 18, 28, 31, 31, 27, 23, 29, 16, 24, 30, 30, 26, + 20, 28, 16, 20, 27, 26, 23, 17, 23, 16, 14, 23, 23, 19, 13, 19, 14, 10, 20, + 20, 16, 11, 15, 14, 10, 16, 18, 15, 9, 12, 13, 11, 13, 17, 14, 9, 11, 11, + 15, 21, 18, 17, 20, 25, 10, 10, 19, 18, 16, 17, 21, 11, 6, 16, 15, 13, 14, + 17, 10, 6, 12, 12, 9, 11, 12, 9, 5, 7, 7, 7, 9, 11, 9, 7, 5, 4, + 4, 7, 11, 10, 8, 5, 3, 3, 8, 9, 6, 5, 10, 13, 15, 18, 20, 6, 5, + 9, 12, 14, 16, 17, 5, 5, 7, 9, 10, 12, 14, 5, 4, 3, 5, 7, 8, 10, + 5, 4, 0, 2, 4, 7, 9, 5, 3, 3, 4, 3, 6, 8, 6, 4, 4, 4, 3, + 4, 7, 44, 47, 51, 55, 56, 53, 48, 43, 46, 50, 54, 55, 52, 45, 40, 44, 49, + 51, 54, 48, 45, 40, 42, 46, 50, 52, 48, 42, 35, 39, 42, 45, 48, 45, 41, 32, + 37, 39, 42, 46, 45, 41, 29, 34, 39, 42, 45, 46, 41, 42, 45, 49, 53, 51, 47, + 44, 40, 44, 48, 51, 50, 46, 42, 36, 41, 45, 47, 47, 45, 40, 33, 39, 43, 46, + 46, 43, 37, 28, 35, 39, 42, 41, 40, 36, 25, 34, 37, 40, 40, 40, 37, 21, 32, + 36, 39, 39, 38, 36, 36, 42, 43, 44, 46, 42, 37, 33, 39, 42, 44, 43, 41, 33, + 29, 38, 40, 40, 41, 40, 33, 26, 35, 37, 37, 38, 36, 29, 20, 31, 34, 34, 34, + 32, 31, 16, 28, 31, 33, 33, 30, 30, 15, 24, 31, 31, 31, 30, 27, 30, 35, 36, + 37, 37, 35, 29, 25, 33, 34, 36, 36, 31, 26, 22, 30, 34, 34, 32, 28, 26, 17, + 25, 30, 29, 29, 24, 25, 16, 19, 26, 26, 24, 21, 21, 15, 16, 25, 25, 25, 20, + 17, 15, 12, 22, 23, 23, 20, 13, 16, 26, 28, 29, 25, 22, 28, 13, 22, 26, 28, + 25, 19, 27, 13, 17, 25, 24, 22, 15, 21, 13, 12, 21, 21, 18, 11, 17, 12, 7, + 17, 17, 14, 8, 13, 11, 8, 14, 15, 13, 7, 10, 11, 9, 10, 13, 12, 7, 9, + 9, 14, 18, 18, 17, 19, 24, 9, 9, 17, 17, 16, 16, 19, 9, 6, 15, 14, 12, + 13, 15, 8, 5, 10, 10, 9, 10, 10, 7, 4, 5, 6, 5, 7, 8, 6, 5, 3, + 3, 4, 6, 8, 7, 6, 3, 2, 3, 6, 7, 5, 5, 10, 13, 15, 18, 20, 5, + 5, 9, 12, 14, 15, 16, 5, 5, 8, 10, 11, 11, 13, 5, 4, 3, 6, 7, 8, + 8, 3, 3, 2, 0, 3, 5, 7, 3, 2, 4, 5, 2, 5, 6, 4, 4, 6, 6, + 2, 4, 6, 37, 42, 45, 48, 48, 46, 42, 36, 40, 43, 47, 48, 44, 40, 34, 37, + 42, 46, 46, 42, 38, 32, 36, 41, 43, 44, 41, 34, 29, 33, 36, 39, 40, 37, 35, + 27, 29, 33, 35, 39, 37, 33, 24, 27, 30, 35, 37, 39, 34, 34, 38, 41, 46, 45, + 42, 37, 34, 37, 40, 45, 44, 40, 35, 31, 35, 39, 42, 41, 38, 34, 29, 33, 36, + 39, 38, 36, 29, 25, 30, 32, 35, 35, 33, 29, 20, 27, 29, 32, 32, 32, 29, 15, + 26, 29, 32, 31, 31, 29, 31, 34, 37, 39, 40, 37, 30, 28, 34, 36, 37, 37, 35, + 29, 25, 32, 35, 35, 34, 34, 27, 21, 30, 31, 31, 31, 29, 25, 16, 25, 28, 28, + 27, 25, 24, 12, 23, 25, 25, 25, 24, 24, 11, 19, 25, 23, 24, 24, 21, 25, 29, + 30, 31, 31, 30, 24, 21, 28, 29, 30, 30, 27, 21, 18, 25, 27, 27, 27, 23, 20, + 15, 22, 24, 23, 23, 20, 19, 12, 15, 21, 21, 19, 15, 16, 11, 12, 19, 18, 18, + 15, 12, 11, 8, 17, 16, 16, 15, 9, 13, 21, 23, 23, 22, 19, 24, 9, 18, 21, + 22, 21, 15, 22, 10, 14, 19, 18, 17, 12, 17, 10, 8, 16, 15, 14, 8, 11, 8, + 4, 12, 11, 10, 5, 8, 7, 4, 9, 8, 8, 4, 6, 6, 5, 6, 7, 7, 4, + 5, 5, 11, 13, 14, 14, 16, 20, 5, 8, 12, 13, 13, 14, 16, 5, 4, 11, 10, + 10, 11, 11, 5, 3, 7, 6, 7, 7, 6, 3, 2, 2, 1, 3, 4, 5, 3, 2, + 3, 3, 2, 3, 5, 4, 3, 4, 4, 1, 3, 4, 5, 5, 9, 11, 13, 15, 16, + 5, 5, 8, 10, 12, 12, 13, 5, 5, 7, 8, 8, 9, 10, 5, 4, 3, 4, 5, + 6, 4, 3, 2, 4, 3, 0, 3, 4, 2, 3, 5, 5, 2, 2, 3, 2, 5, 6, + 6, 3, 1, 3, 32, 35, 39, 42, 42, 40, 37, 30, 34, 38, 42, 43, 39, 35, 29, + 31, 37, 40, 41, 37, 33, 28, 29, 33, 38, 39, 35, 28, 25, 27, 30, 33, 36, 33, + 29, 22, 23, 26, 30, 34, 32, 29, 20, 22, 25, 29, 32, 32, 28, 29, 33, 36, 40, + 39, 36, 32, 28, 31, 35, 38, 39, 34, 30, 26, 30, 34, 36, 35, 32, 28, 26, 26, + 30, 33, 33, 30, 24, 21, 23, 27, 30, 29, 28, 23, 17, 22, 24, 27, 27, 26, 24, + 14, 20, 23, 26, 26, 26, 24, 27, 30, 31, 32, 35, 31, 27, 25, 29, 31, 32, 31, + 29, 24, 22, 27, 29, 28, 29, 28, 22, 19, 26, 26, 25, 25, 25, 19, 13, 22, 22, + 22, 22, 20, 18, 9, 20, 20, 20, 19, 20, 19, 8, 17, 19, 18, 18, 19, 17, 22, + 25, 25, 25, 27, 26, 19, 18, 23, 24, 24, 25, 23, 17, 14, 22, 22, 22, 21, 19, + 16, 11, 18, 18, 18, 18, 16, 14, 9, 13, 15, 14, 14, 12, 11, 9, 10, 13, 13, + 12, 12, 8, 8, 6, 12, 11, 11, 11, 5, 10, 17, 17, 18, 18, 15, 19, 7, 15, + 15, 16, 16, 12, 17, 7, 12, 13, 13, 13, 9, 12, 7, 6, 10, 9, 9, 5, 8, + 5, 2, 6, 5, 5, 3, 5, 4, 2, 4, 3, 3, 3, 4, 4, 3, 2, 2, 2, + 2, 3, 3, 9, 9, 10, 11, 13, 16, 3, 7, 8, 9, 10, 11, 12, 3, 4, 7, + 7, 7, 8, 8, 3, 3, 4, 4, 4, 4, 3, 2, 1, 4, 3, 1, 2, 3, 1, + 3, 5, 4, 2, 2, 3, 2, 4, 5, 5, 3, 0, 2, 4, 5, 6, 8, 10, 12, + 13, 4, 5, 6, 8, 9, 10, 10, 4, 5, 6, 5, 6, 6, 7, 4, 4, 5, 3, + 2, 3, 3, 2, 4, 7, 5, 3, 0, 3, 3, 5, 7, 6, 3, 2, 2, 4, 6, + 7, 7, 4, 2, 2, 26, 30, 34, 38, 38, 34, 31, 24, 29, 32, 36, 37, 33, 29, + 23, 26, 31, 35, 35, 32, 28, 22, 25, 28, 31, 33, 29, 24, 19, 21, 24, 28, 30, + 28, 24, 17, 19, 22, 25, 29, 28, 25, 16, 17, 20, 24, 27, 28, 24, 23, 27, 31, + 35, 33, 31, 27, 22, 25, 30, 33, 33, 30, 26, 21, 24, 28, 30, 31, 28, 24, 20, + 21, 25, 27, 28, 26, 20, 17, 19, 21, 24, 24, 23, 20, 15, 17, 20, 22, 22, 22, + 20, 12, 16, 19, 21, 21, 21, 20, 22, 24, 27, 27, 29, 26, 22, 20, 23, 25, 26, + 26, 25, 20, 18, 22, 23, 23, 24, 23, 18, 16, 20, 20, 20, 20, 20, 15, 11, 16, + 17, 17, 17, 16, 15, 7, 16, 15, 15, 15, 15, 14, 7, 14, 14, 14, 14, 14, 14, + 18, 18, 19, 20, 22, 21, 14, 15, 18, 18, 19, 19, 19, 13, 12, 17, 17, 16, 16, + 15, 11, 8, 15, 13, 12, 13, 12, 10, 6, 10, 10, 9, 9, 9, 7, 6, 8, 8, + 8, 7, 8, 4, 7, 4, 7, 6, 6, 6, 3, 7, 11, 11, 12, 13, 12, 14, 4, + 9, 10, 10, 11, 10, 12, 4, 8, 8, 7, 7, 7, 8, 4, 5, 4, 4, 4, 4, + 4, 2, 1, 1, 1, 1, 2, 3, 2, 3, 4, 3, 2, 0, 3, 3, 4, 5, 3, + 3, 2, 2, 3, 5, 6, 8, 9, 11, 12, 3, 4, 6, 7, 7, 8, 9, 3, 4, + 4, 5, 5, 5, 6, 3, 3, 4, 3, 2, 2, 2, 1, 5, 6, 4, 3, 2, 2, + 3, 7, 8, 6, 4, 2, 2, 5, 7, 9, 8, 4, 3, 0, 5, 7, 6, 6, 8, + 9, 10, 5, 7, 7, 6, 7, 7, 7, 5, 7, 8, 4, 3, 4, 5, 5, 6, 8, + 5, 3, 1, 2, 5, 8, 10, 8, 4, 3, 0, 7, 9, 10, 9, 5, 3, 1, 8, + 9, 10, 10, 6, 4, 2, 36, 41, 47, 48, 47, 47, 42, 36, 39, 44, 48, 49, 45, + 41, 34, 38, 42, 45, 47, 44, 39, 32, 35, 39, 42, 45, 41, 36, 29, 33, 35, 39, + 41, 39, 37, 26, 29, 32, 37, 41, 39, 36, 23, 27, 32, 34, 38, 39, 35, 33, 38, + 42, 45, 44, 42, 39, 31, 37, 41, 45, 44, 40, 38, 31, 35, 40, 42, 42, 40, 35, + 29, 33, 36, 39, 38, 38, 31, 25, 28, 32, 36, 35, 35, 32, 22, 27, 30, 32, 34, + 34, 31, 18, 24, 28, 32, 33, 32, 31, 31, 36, 37, 38, 39, 37, 32, 29, 33, 35, + 37, 38, 36, 31, 26, 32, 36, 35, 35, 35, 30, 22, 29, 31, 31, 31, 31, 26, 17, + 26, 27, 28, 27, 27, 26, 13, 24, 26, 26, 26, 27, 26, 12, 21, 23, 25, 24, 25, + 24, 27, 29, 30, 31, 32, 31, 23, 21, 27, 29, 30, 29, 28, 22, 19, 25, 27, 26, + 27, 25, 22, 14, 21, 24, 23, 23, 22, 20, 13, 17, 20, 19, 20, 18, 16, 12, 13, + 17, 18, 18, 17, 12, 12, 10, 15, 16, 17, 17, 10, 13, 20, 22, 22, 22, 19, 23, + 10, 18, 20, 20, 21, 16, 21, 10, 15, 18, 18, 18, 13, 17, 10, 9, 14, 14, 14, + 10, 12, 8, 4, 10, 10, 10, 8, 9, 7, 5, 7, 7, 8, 6, 9, 8, 7, 5, + 5, 6, 6, 8, 5, 11, 12, 13, 15, 17, 20, 5, 8, 10, 11, 13, 14, 16, 5, + 5, 8, 8, 10, 12, 13, 5, 4, 4, 4, 6, 8, 8, 4, 3, 2, 1, 2, 6, + 8, 4, 2, 4, 3, 1, 5, 8, 5, 5, 4, 3, 2, 4, 6, 4, 6, 6, 9, + 13, 16, 17, 4, 6, 7, 7, 11, 13, 14, 5, 6, 7, 4, 8, 9, 11, 4, 5, + 6, 3, 3, 5, 7, 3, 3, 5, 3, 2, 3, 7, 0, 4, 5, 5, 2, 1, 5, + 3, 5, 5, 5, 3, 1, 4, 42, 48, 52, 54, 55, 52, 49, 41, 46, 50, 54, 53, + 50, 46, 40, 44, 48, 52, 53, 50, 45, 38, 41, 46, 50, 52, 47, 41, 35, 39, 41, + 46, 47, 46, 42, 31, 35, 37, 42, 46, 44, 41, 28, 33, 38, 41, 44, 44, 41, 39, + 45, 48, 53, 51, 47, 44, 39, 43, 47, 50, 50, 47, 42, 36, 43, 46, 49, 48, 44, + 40, 34, 39, 44, 45, 46, 42, 36, 29, 35, 38, 41, 41, 40, 37, 24, 33, 36, 39, + 39, 39, 36, 20, 31, 34, 38, 38, 37, 37, 36, 40, 43, 43, 46, 43, 37, 34, 39, + 42, 43, 43, 41, 36, 30, 39, 40, 41, 41, 39, 33, 25, 35, 37, 37, 37, 35, 30, + 20, 31, 33, 33, 33, 32, 31, 15, 28, 31, 31, 31, 31, 30, 15, 25, 29, 30, 30, + 30, 27, 30, 35, 37, 37, 38, 36, 28, 25, 33, 34, 36, 35, 32, 27, 21, 30, 34, + 32, 32, 29, 26, 18, 26, 30, 29, 30, 26, 25, 16, 19, 26, 25, 25, 21, 21, 15, + 16, 23, 24, 24, 21, 17, 15, 12, 21, 22, 22, 20, 13, 17, 25, 27, 29, 27, 23, + 29, 14, 22, 26, 27, 25, 20, 27, 13, 18, 23, 23, 22, 17, 21, 13, 12, 20, 20, + 18, 12, 16, 12, 7, 16, 16, 14, 9, 13, 11, 7, 13, 13, 13, 8, 10, 10, 8, + 10, 12, 11, 8, 9, 9, 15, 18, 19, 18, 21, 24, 9, 10, 17, 17, 17, 18, 20, + 9, 6, 14, 14, 14, 15, 16, 9, 5, 10, 10, 10, 11, 11, 7, 4, 5, 5, 5, + 8, 10, 6, 4, 2, 2, 4, 6, 10, 7, 5, 3, 2, 3, 7, 8, 6, 6, 9, + 14, 16, 19, 21, 6, 6, 8, 13, 15, 16, 18, 6, 6, 6, 10, 12, 13, 14, 6, + 5, 5, 5, 8, 9, 9, 4, 3, 3, 2, 3, 5, 9, 4, 0, 3, 4, 1, 6, + 7, 3, 3, 4, 4, 2, 4, 6, 49, 54, 58, 61, 61, 58, 53, 48, 51, 57, 60, + 60, 57, 53, 46, 50, 54, 57, 59, 54, 51, 44, 47, 51, 55, 56, 51, 46, 40, 44, + 47, 51, 53, 49, 46, 36, 41, 44, 46, 50, 50, 46, 32, 38, 42, 46, 49, 48, 47, + 45, 49, 54, 58, 56, 54, 48, 44, 48, 52, 58, 56, 52, 47, 41, 47, 51, 55, 54, + 50, 44, 38, 44, 48, 52, 50, 48, 41, 33, 42, 44, 48, 46, 46, 41, 27, 37, 41, + 44, 45, 43, 40, 23, 34, 39, 43, 42, 42, 41, 41, 46, 50, 50, 51, 49, 41, 38, + 45, 48, 50, 49, 46, 40, 33, 44, 46, 47, 46, 44, 37, 30, 40, 43, 43, 43, 41, + 34, 24, 34, 39, 39, 39, 35, 34, 19, 30, 36, 36, 36, 35, 35, 17, 26, 34, 35, + 34, 34, 32, 34, 42, 41, 43, 42, 41, 34, 29, 38, 41, 41, 40, 36, 33, 25, 34, + 39, 39, 36, 33, 31, 21, 29, 36, 35, 33, 28, 29, 19, 23, 31, 32, 29, 24, 26, + 18, 18, 28, 29, 27, 23, 22, 17, 14, 25, 26, 26, 23, 17, 20, 29, 33, 34, 30, + 28, 33, 17, 25, 32, 32, 29, 24, 31, 17, 21, 29, 30, 26, 20, 26, 17, 15, 25, + 26, 22, 15, 21, 15, 10, 20, 22, 17, 11, 17, 13, 9, 16, 19, 15, 10, 14, 13, + 9, 11, 17, 15, 9, 11, 12, 17, 24, 23, 22, 24, 30, 12, 12, 22, 22, 20, 21, + 25, 12, 9, 19, 19, 17, 18, 20, 12, 8, 14, 16, 13, 13, 14, 10, 6, 7, 11, + 7, 10, 12, 9, 5, 4, 6, 5, 8, 10, 8, 6, 4, 5, 5, 7, 10, 8, 7, + 16, 18, 20, 23, 24, 8, 8, 13, 17, 19, 20, 20, 8, 7, 11, 14, 16, 16, 17, + 8, 6, 5, 11, 11, 12, 10, 6, 4, 3, 4, 5, 7, 10, 5, 3, 0, 1, 3, + 6, 9, 5, 3, 2, 2, 3, 5, 8, 48, 52, 55, 59, 59, 57, 52, 47, 50, 55, + 59, 59, 56, 50, 44, 48, 52, 56, 58, 53, 49, 43, 46, 50, 53, 54, 51, 44, 38, + 44, 46, 49, 52, 49, 44, 34, 40, 43, 45, 50, 48, 43, 30, 37, 41, 44, 48, 47, + 43, 45, 51, 53, 56, 56, 51, 47, 44, 47, 53, 55, 56, 50, 45, 40, 47, 51, 54, + 52, 48, 44, 36, 43, 48, 50, 49, 44, 40, 32, 39, 45, 47, 44, 43, 39, 26, 36, + 40, 43, 42, 42, 39, 21, 33, 38, 42, 42, 41, 40, 40, 45, 47, 48, 50, 48, 40, + 37, 44, 48, 46, 49, 46, 38, 32, 42, 46, 45, 46, 43, 37, 28, 40, 42, 43, 41, + 40, 33, 23, 35, 37, 38, 36, 34, 33, 17, 29, 35, 35, 35, 34, 34, 16, 24, 33, + 33, 33, 32, 31, 32, 39, 40, 43, 42, 40, 34, 28, 38, 40, 41, 40, 36, 32, 24, + 33, 38, 38, 37, 33, 30, 20, 28, 34, 34, 33, 28, 28, 19, 21, 31, 30, 28, 24, + 25, 17, 17, 27, 27, 26, 22, 21, 16, 13, 23, 26, 26, 21, 17, 19, 29, 33, 34, + 30, 27, 33, 16, 24, 32, 32, 29, 24, 31, 16, 21, 29, 29, 26, 20, 26, 16, 15, + 24, 25, 22, 14, 20, 14, 10, 19, 21, 17, 10, 17, 12, 8, 14, 17, 15, 9, 13, + 12, 8, 10, 16, 14, 9, 11, 11, 17, 23, 23, 22, 24, 29, 12, 12, 21, 22, 21, + 21, 24, 12, 9, 19, 19, 17, 18, 20, 11, 7, 14, 15, 13, 12, 13, 10, 5, 7, + 10, 7, 9, 11, 8, 5, 4, 6, 5, 7, 10, 7, 5, 4, 4, 4, 7, 9, 8, + 8, 16, 18, 21, 23, 24, 8, 8, 14, 18, 20, 20, 20, 8, 8, 11, 16, 15, 15, + 16, 8, 7, 6, 11, 11, 11, 10, 6, 5, 4, 5, 5, 6, 9, 4, 4, 1, 0, + 3, 6, 8, 4, 3, 2, 2, 2, 5, 7, 41, 45, 48, 52, 51, 50, 45, 39, 42, + 46, 52, 51, 47, 43, 37, 41, 45, 49, 49, 46, 41, 36, 39, 41, 46, 47, 44, 36, + 33, 36, 38, 42, 43, 40, 37, 29, 32, 35, 39, 42, 41, 37, 25, 30, 34, 37, 40, + 41, 37, 37, 42, 45, 49, 48, 44, 40, 36, 41, 44, 47, 47, 42, 37, 33, 38, 43, + 45, 44, 42, 36, 31, 37, 39, 41, 41, 38, 32, 26, 33, 35, 38, 38, 35, 32, 21, + 30, 33, 35, 34, 34, 31, 16, 28, 31, 34, 34, 33, 32, 34, 39, 40, 43, 42, 40, + 33, 31, 37, 40, 41, 40, 37, 33, 26, 35, 38, 39, 37, 36, 30, 24, 32, 33, 34, + 34, 32, 26, 17, 27, 31, 30, 30, 27, 26, 13, 24, 29, 28, 27, 26, 27, 12, 20, + 27, 27, 27, 26, 24, 27, 33, 32, 34, 34, 33, 27, 22, 30, 33, 32, 32, 29, 24, + 20, 27, 31, 31, 30, 26, 23, 17, 23, 27, 27, 26, 21, 22, 13, 17, 24, 23, 21, + 18, 18, 12, 12, 21, 20, 19, 17, 15, 12, 9, 19, 19, 19, 17, 11, 15, 23, 26, + 26, 24, 21, 26, 11, 20, 24, 25, 23, 18, 24, 11, 15, 22, 22, 20, 15, 19, 11, + 10, 19, 18, 16, 10, 13, 9, 5, 14, 14, 12, 6, 10, 8, 4, 10, 11, 10, 5, + 8, 8, 5, 7, 9, 8, 5, 6, 7, 13, 16, 17, 16, 19, 23, 7, 9, 15, 15, + 15, 16, 18, 7, 5, 13, 12, 13, 13, 13, 7, 4, 10, 9, 9, 9, 8, 5, 2, + 4, 4, 4, 5, 6, 3, 2, 2, 1, 2, 4, 6, 4, 3, 2, 2, 2, 4, 5, + 6, 6, 11, 13, 15, 17, 18, 6, 6, 11, 13, 14, 15, 15, 6, 6, 8, 10, 11, + 11, 11, 5, 5, 4, 6, 7, 7, 6, 3, 3, 3, 2, 2, 3, 5, 2, 1, 3, + 3, 0, 3, 4, 2, 3, 4, 4, 2, 3, 4, 33, 38, 42, 46, 45, 43, 37, 32, + 36, 40, 45, 44, 41, 37, 31, 34, 39, 42, 43, 39, 34, 30, 32, 36, 39, 40, 37, + 31, 27, 29, 31, 36, 37, 35, 31, 23, 26, 29, 33, 36, 34, 31, 22, 25, 28, 30, + 34, 34, 31, 31, 34, 38, 42, 42, 37, 34, 30, 33, 38, 41, 40, 36, 32, 29, 32, + 36, 38, 38, 36, 28, 27, 29, 32, 36, 35, 32, 27, 22, 26, 30, 32, 31, 30, 26, + 18, 23, 26, 29, 29, 29, 26, 15, 23, 25, 28, 28, 28, 26, 28, 31, 35, 34, 37, + 34, 28, 26, 31, 31, 34, 34, 32, 26, 23, 30, 31, 31, 31, 30, 23, 19, 28, 28, + 28, 28, 26, 21, 14, 24, 24, 24, 23, 23, 21, 10, 21, 23, 21, 22, 22, 21, 10, + 19, 21, 20, 21, 21, 18, 24, 26, 27, 27, 29, 27, 21, 19, 25, 26, 27, 27, 24, + 18, 16, 23, 24, 24, 24, 21, 18, 12, 19, 21, 20, 21, 18, 17, 10, 14, 17, 17, + 16, 13, 13, 10, 10, 15, 15, 14, 13, 10, 9, 7, 14, 13, 13, 12, 6, 11, 18, + 19, 20, 20, 16, 21, 8, 16, 18, 18, 18, 13, 19, 8, 12, 15, 15, 15, 11, 14, + 8, 7, 12, 12, 11, 6, 9, 6, 2, 8, 8, 7, 4, 6, 5, 3, 6, 5, 5, + 3, 5, 5, 3, 4, 4, 3, 3, 4, 4, 10, 10, 11, 13, 14, 18, 4, 8, 10, + 10, 12, 12, 13, 4, 4, 9, 8, 9, 9, 9, 4, 3, 5, 5, 5, 5, 4, 2, + 2, 2, 2, 2, 3, 4, 2, 1, 5, 4, 2, 2, 4, 3, 3, 5, 4, 2, 2, + 3, 5, 5, 8, 10, 11, 13, 14, 5, 5, 7, 9, 10, 11, 11, 5, 5, 6, 7, + 7, 8, 8, 5, 4, 5, 3, 3, 4, 3, 3, 3, 7, 5, 2, 2, 3, 1, 5, + 6, 6, 3, 0, 3, 4, 6, 6, 6, 4, 2, 2, 27, 31, 35, 38, 39, 36, 33, + 25, 30, 34, 39, 38, 35, 30, 25, 29, 32, 36, 37, 34, 29, 24, 26, 29, 32, 36, + 31, 26, 21, 24, 26, 29, 33, 30, 26, 18, 20, 23, 27, 30, 30, 25, 17, 19, 22, + 25, 29, 29, 26, 25, 28, 33, 35, 35, 33, 29, 24, 28, 32, 35, 35, 32, 27, 23, + 26, 30, 32, 32, 30, 25, 22, 24, 27, 29, 29, 26, 21, 19, 20, 23, 26, 26, 25, + 21, 16, 18, 21, 24, 23, 24, 21, 13, 17, 20, 22, 23, 22, 21, 22, 26, 28, 29, + 31, 28, 23, 22, 24, 26, 28, 28, 27, 22, 20, 23, 25, 25, 25, 25, 19, 17, 22, + 22, 22, 22, 21, 16, 11, 18, 19, 18, 18, 17, 16, 8, 17, 17, 17, 17, 16, 16, + 8, 16, 16, 15, 15, 16, 14, 20, 21, 20, 22, 24, 22, 16, 16, 20, 20, 21, 21, + 20, 14, 13, 18, 18, 18, 17, 17, 13, 9, 16, 15, 14, 14, 14, 12, 7, 12, 11, + 11, 10, 10, 8, 7, 9, 10, 9, 9, 9, 5, 8, 5, 8, 8, 8, 8, 3, 8, + 13, 13, 14, 15, 13, 15, 5, 11, 12, 12, 13, 10, 14, 5, 10, 10, 9, 9, 8, + 9, 5, 5, 6, 6, 5, 4, 5, 3, 1, 2, 2, 2, 2, 3, 3, 2, 3, 2, + 1, 2, 3, 4, 3, 4, 3, 2, 0, 2, 3, 6, 7, 8, 9, 11, 13, 3, 5, + 7, 8, 8, 9, 10, 3, 4, 5, 5, 6, 6, 6, 3, 3, 3, 2, 2, 3, 3, + 1, 4, 5, 4, 3, 0, 2, 1, 5, 7, 5, 3, 1, 2, 3, 6, 7, 6, 4, + 2, 2, 4, 6, 6, 7, 9, 10, 11, 4, 6, 6, 6, 8, 8, 8, 4, 6, 7, + 4, 4, 4, 6, 4, 6, 7, 4, 2, 1, 2, 3, 7, 8, 6, 3, 2, 1, 5, + 7, 9, 8, 4, 3, 0, 6, 7, 9, 9, 5, 3, 2, 38, 44, 48, 51, 51, 48, + 46, 38, 42, 46, 50, 51, 48, 44, 37, 41, 45, 47, 49, 44, 41, 34, 38, 41, 45, + 47, 43, 36, 32, 34, 38, 42, 42, 38, 37, 28, 30, 33, 36, 41, 38, 37, 23, 26, + 32, 35, 39, 40, 36, 37, 39, 45, 49, 49, 44, 41, 36, 39, 43, 47, 48, 44, 39, + 34, 37, 42, 45, 44, 42, 36, 31, 36, 38, 41, 42, 38, 32, 27, 31, 35, 38, 36, + 36, 31, 22, 28, 31, 33, 34, 35, 32, 18, 25, 29, 32, 33, 33, 32, 34, 36, 40, + 41, 43, 41, 37, 31, 34, 39, 40, 40, 39, 34, 28, 35, 37, 37, 37, 37, 32, 23, + 33, 34, 34, 34, 32, 27, 18, 28, 29, 30, 29, 28, 27, 13, 24, 26, 26, 27, 27, + 27, 11, 21, 24, 24, 25, 25, 25, 28, 32, 33, 34, 36, 35, 27, 23, 30, 31, 34, + 33, 31, 25, 20, 28, 29, 30, 30, 28, 24, 16, 23, 26, 26, 26, 24, 23, 14, 17, + 22, 22, 21, 19, 18, 12, 13, 17, 19, 18, 18, 15, 11, 9, 16, 16, 17, 17, 11, + 15, 23, 25, 26, 27, 23, 27, 12, 20, 23, 25, 25, 21, 25, 12, 16, 21, 21, 21, + 17, 20, 12, 11, 17, 17, 17, 12, 14, 10, 5, 13, 12, 11, 8, 11, 7, 4, 8, + 8, 9, 7, 10, 7, 5, 5, 6, 7, 7, 9, 7, 14, 16, 17, 19, 22, 24, 8, + 11, 15, 16, 18, 19, 20, 8, 7, 13, 13, 15, 15, 16, 7, 6, 9, 9, 11, 10, + 9, 5, 4, 4, 4, 4, 7, 9, 5, 3, 3, 2, 3, 5, 8, 4, 2, 3, 3, + 1, 5, 7, 8, 7, 9, 14, 18, 20, 21, 7, 7, 9, 12, 16, 17, 18, 7, 7, + 9, 9, 12, 14, 14, 8, 6, 8, 5, 7, 9, 7, 5, 5, 6, 4, 2, 4, 8, + 3, 3, 5, 4, 2, 4, 6, 0, 4, 5, 5, 3, 3, 5, 45, 50, 54, 59, 58, + 56, 50, 44, 48, 52, 57, 58, 51, 48, 42, 46, 51, 55, 54, 52, 46, 41, 44, 46, + 51, 53, 48, 41, 36, 41, 44, 47, 48, 45, 41, 32, 37, 40, 42, 45, 46, 42, 28, + 33, 37, 42, 45, 46, 42, 42, 47, 50, 54, 54, 50, 46, 39, 44, 50, 53, 53, 49, + 45, 39, 43, 48, 51, 50, 46, 41, 35, 41, 45, 47, 46, 43, 36, 30, 37, 41, 43, + 41, 40, 37, 24, 33, 38, 38, 40, 40, 37, 19, 31, 35, 38, 39, 38, 36, 38, 43, + 46, 46, 48, 45, 41, 34, 41, 46, 46, 47, 44, 38, 31, 41, 42, 44, 43, 40, 36, + 27, 38, 39, 40, 38, 37, 32, 21, 33, 35, 35, 34, 32, 31, 16, 26, 32, 31, 32, + 30, 32, 15, 24, 29, 31, 31, 30, 29, 31, 38, 40, 39, 40, 39, 32, 27, 35, 37, + 39, 38, 35, 30, 24, 31, 37, 36, 35, 32, 29, 19, 27, 31, 32, 32, 27, 27, 17, + 21, 28, 27, 26, 22, 22, 16, 15, 24, 23, 23, 21, 19, 15, 12, 21, 22, 22, 21, + 15, 18, 28, 30, 31, 30, 27, 31, 15, 24, 29, 30, 29, 24, 30, 15, 19, 26, 27, + 25, 19, 24, 15, 14, 22, 23, 21, 14, 19, 13, 8, 18, 18, 15, 10, 15, 11, 6, + 12, 14, 13, 8, 12, 10, 7, 9, 12, 11, 8, 10, 11, 16, 21, 22, 22, 24, 29, + 11, 12, 20, 20, 21, 22, 24, 11, 8, 17, 17, 18, 18, 18, 10, 7, 13, 13, 13, + 12, 12, 8, 5, 7, 8, 6, 9, 10, 6, 5, 2, 3, 4, 7, 10, 5, 4, 2, + 1, 4, 7, 9, 8, 8, 14, 18, 21, 23, 24, 8, 8, 12, 17, 20, 21, 21, 8, + 8, 10, 14, 16, 16, 16, 9, 7, 6, 9, 12, 11, 9, 6, 5, 4, 4, 5, 6, + 9, 4, 3, 3, 3, 3, 5, 8, 4, 0, 3, 3, 2, 5, 7, 49, 54, 57, 61, + 61, 57, 54, 47, 52, 57, 60, 62, 56, 53, 46, 50, 55, 58, 58, 55, 50, 45, 49, + 52, 55, 57, 52, 46, 40, 45, 49, 52, 53, 50, 46, 35, 41, 44, 47, 50, 50, 46, + 31, 38, 43, 45, 50, 51, 45, 47, 49, 55, 59, 57, 54, 50, 44, 50, 55, 58, 57, + 52, 46, 41, 47, 53, 55, 54, 51, 44, 39, 46, 50, 51, 50, 48, 40, 32, 41, 45, + 47, 46, 45, 40, 27, 37, 41, 43, 44, 44, 41, 22, 34, 40, 44, 42, 41, 41, 41, + 49, 50, 52, 52, 49, 43, 37, 46, 50, 50, 50, 47, 41, 33, 42, 47, 47, 47, 44, + 38, 29, 41, 43, 44, 42, 41, 35, 23, 35, 39, 40, 37, 36, 35, 19, 29, 37, 36, + 37, 34, 36, 18, 26, 35, 35, 34, 33, 32, 33, 40, 43, 45, 43, 41, 35, 30, 38, + 41, 42, 42, 38, 34, 25, 35, 40, 40, 39, 33, 32, 22, 30, 36, 35, 35, 30, 30, + 20, 23, 31, 32, 30, 24, 26, 18, 18, 28, 29, 28, 23, 23, 18, 14, 24, 27, 26, + 23, 18, 21, 29, 34, 36, 33, 29, 34, 17, 26, 33, 34, 31, 25, 33, 17, 21, 30, + 30, 28, 21, 27, 17, 16, 25, 27, 23, 15, 21, 15, 10, 20, 23, 18, 11, 17, 13, + 9, 15, 19, 16, 10, 14, 13, 9, 11, 18, 15, 10, 12, 12, 17, 25, 24, 23, 26, + 31, 12, 13, 23, 23, 22, 22, 26, 12, 9, 20, 20, 19, 19, 21, 12, 8, 14, 16, + 14, 14, 14, 11, 6, 8, 11, 7, 9, 12, 9, 5, 4, 6, 5, 8, 11, 7, 5, + 4, 5, 4, 7, 10, 9, 8, 17, 19, 22, 24, 26, 9, 8, 15, 19, 20, 21, 21, + 9, 8, 11, 16, 16, 17, 17, 9, 7, 7, 13, 12, 12, 11, 6, 5, 4, 6, 6, + 7, 10, 5, 4, 2, 2, 3, 7, 9, 4, 3, 0, 0, 3, 5, 8, 49, 53, 57, + 61, 62, 59, 55, 48, 53, 57, 60, 61, 57, 52, 45, 51, 53, 58, 59, 56, 51, 44, + 47, 52, 55, 57, 52, 46, 42, 45, 48, 51, 54, 49, 45, 35, 41, 45, 47, 50, 49, + 45, 31, 38, 41, 46, 49, 50, 46, 46, 52, 55, 59, 57, 54, 50, 46, 50, 54, 57, + 55, 53, 48, 41, 48, 52, 56, 53, 50, 44, 38, 46, 50, 52, 50, 47, 42, 31, 41, + 46, 48, 45, 45, 40, 27, 37, 41, 43, 43, 43, 40, 22, 35, 40, 42, 43, 41, 41, + 41, 48, 50, 51, 51, 49, 42, 36, 46, 48, 50, 49, 46, 41, 33, 43, 47, 48, 46, + 45, 38, 30, 41, 44, 44, 44, 40, 35, 24, 34, 39, 40, 38, 36, 35, 19, 30, 36, + 36, 36, 35, 35, 17, 24, 34, 35, 35, 33, 32, 33, 41, 43, 44, 44, 41, 35, 29, + 38, 42, 43, 40, 38, 33, 26, 34, 40, 40, 39, 33, 31, 22, 30, 36, 36, 34, 29, + 30, 20, 23, 31, 32, 30, 24, 26, 19, 18, 28, 29, 27, 23, 22, 17, 14, 24, 27, + 27, 22, 18, 21, 31, 34, 35, 32, 29, 35, 17, 26, 33, 33, 30, 25, 33, 17, 21, + 30, 30, 28, 21, 27, 17, 16, 25, 27, 24, 15, 22, 15, 11, 20, 22, 17, 11, 17, + 14, 9, 15, 18, 16, 10, 14, 13, 9, 10, 17, 15, 9, 12, 13, 17, 25, 24, 23, + 25, 31, 13, 13, 22, 23, 22, 23, 26, 13, 9, 20, 20, 18, 19, 21, 12, 8, 14, + 16, 14, 13, 14, 10, 6, 8, 12, 7, 10, 12, 9, 5, 4, 7, 5, 8, 10, 7, + 6, 4, 5, 5, 8, 10, 9, 8, 17, 19, 21, 24, 25, 9, 8, 15, 18, 20, 21, + 22, 9, 8, 11, 17, 17, 17, 17, 9, 7, 6, 12, 12, 12, 11, 6, 5, 4, 6, + 6, 7, 10, 5, 4, 2, 2, 4, 6, 9, 5, 3, 0, 0, 3, 5, 8, 43, 47, + 51, 55, 55, 53, 49, 40, 45, 50, 53, 53, 50, 45, 39, 44, 47, 51, 52, 48, 43, + 39, 42, 46, 47, 49, 46, 39, 35, 38, 41, 45, 46, 43, 39, 30, 34, 37, 40, 44, + 43, 38, 27, 32, 36, 39, 42, 43, 40, 40, 43, 48, 51, 51, 47, 43, 39, 42, 47, + 50, 50, 47, 41, 36, 41, 45, 47, 48, 44, 39, 33, 38, 42, 44, 44, 40, 34, 27, + 36, 38, 42, 39, 38, 35, 22, 32, 35, 37, 36, 37, 34, 18, 29, 34, 37, 37, 35, + 34, 36, 40, 43, 44, 45, 42, 37, 32, 38, 42, 44, 42, 41, 33, 28, 38, 40, 40, + 40, 38, 33, 25, 35, 36, 36, 36, 34, 29, 19, 30, 33, 33, 32, 30, 29, 14, 26, + 30, 29, 30, 28, 29, 13, 21, 29, 28, 29, 28, 26, 28, 36, 36, 37, 37, 35, 29, + 24, 32, 35, 36, 35, 31, 27, 20, 30, 33, 33, 32, 28, 25, 17, 24, 29, 28, 28, + 24, 24, 15, 18, 25, 26, 24, 19, 20, 14, 14, 23, 22, 22, 19, 17, 13, 10, 20, + 21, 21, 18, 12, 16, 25, 28, 29, 26, 23, 28, 13, 21, 26, 27, 25, 19, 27, 13, + 17, 24, 24, 22, 16, 21, 13, 12, 20, 19, 18, 11, 16, 11, 7, 16, 16, 13, 7, + 12, 10, 5, 12, 13, 12, 6, 9, 9, 6, 8, 11, 10, 6, 8, 8, 14, 19, 19, + 18, 20, 24, 8, 10, 17, 18, 17, 17, 20, 8, 6, 14, 14, 14, 14, 15, 8, 5, + 11, 11, 10, 10, 10, 6, 3, 5, 6, 4, 6, 8, 4, 3, 2, 2, 3, 5, 7, + 4, 3, 2, 1, 3, 4, 6, 6, 6, 13, 15, 17, 19, 20, 6, 6, 12, 14, 16, + 16, 17, 6, 6, 9, 12, 12, 12, 13, 6, 5, 5, 8, 8, 8, 7, 4, 3, 3, + 2, 3, 4, 6, 3, 2, 3, 2, 2, 4, 5, 3, 2, 3, 3, 0, 4, 5, 36, + 40, 45, 47, 47, 44, 40, 34, 38, 42, 46, 46, 43, 38, 32, 36, 41, 44, 45, 42, + 36, 31, 34, 38, 40, 43, 39, 33, 29, 32, 33, 37, 39, 36, 32, 25, 27, 31, 33, + 37, 36, 33, 23, 26, 29, 33, 36, 37, 33, 33, 36, 41, 45, 43, 40, 35, 31, 35, + 39, 44, 43, 39, 35, 30, 33, 38, 41, 39, 36, 32, 29, 31, 34, 37, 37, 35, 29, + 24, 29, 31, 34, 32, 32, 29, 19, 26, 28, 31, 30, 32, 28, 15, 24, 27, 30, 30, + 29, 28, 31, 34, 36, 37, 37, 36, 30, 28, 32, 34, 36, 36, 35, 28, 25, 31, 34, + 34, 34, 31, 25, 20, 29, 29, 29, 30, 28, 23, 15, 24, 26, 26, 25, 24, 23, 11, + 21, 23, 23, 24, 23, 23, 10, 19, 24, 23, 22, 23, 20, 25, 29, 28, 30, 30, 29, + 23, 20, 27, 28, 29, 29, 26, 21, 17, 24, 27, 26, 26, 22, 19, 14, 20, 23, 22, + 22, 19, 18, 11, 15, 19, 19, 18, 14, 15, 11, 11, 17, 16, 16, 14, 11, 10, 7, + 16, 15, 15, 14, 8, 12, 20, 21, 22, 21, 18, 22, 9, 17, 20, 20, 20, 15, 21, + 9, 14, 18, 17, 17, 12, 15, 9, 8, 15, 14, 13, 7, 10, 7, 3, 10, 10, 9, + 5, 7, 6, 3, 8, 7, 7, 4, 5, 6, 4, 5, 6, 5, 4, 5, 5, 11, 12, + 13, 14, 16, 19, 5, 8, 11, 12, 13, 13, 15, 5, 5, 10, 9, 10, 10, 10, 5, + 3, 7, 6, 6, 6, 5, 3, 2, 1, 1, 2, 4, 4, 2, 2, 4, 3, 0, 3, + 5, 3, 2, 4, 4, 2, 2, 4, 5, 5, 9, 11, 13, 15, 15, 5, 5, 8, 10, + 12, 12, 12, 5, 5, 7, 8, 8, 9, 9, 5, 4, 4, 4, 4, 5, 4, 3, 2, + 4, 4, 1, 2, 4, 1, 4, 5, 5, 3, 2, 3, 2, 5, 5, 5, 3, 0, 3, + 29, 34, 38, 41, 41, 39, 34, 28, 31, 36, 40, 40, 37, 33, 27, 31, 34, 38, 39, + 36, 30, 26, 28, 31, 34, 37, 32, 27, 23, 25, 27, 31, 33, 31, 27, 20, 22, 25, + 28, 33, 31, 27, 19, 21, 23, 27, 30, 30, 28, 27, 30, 34, 38, 38, 34, 31, 26, + 29, 32, 37, 36, 34, 29, 25, 27, 32, 35, 33, 31, 26, 23, 25, 28, 31, 30, 28, + 23, 20, 23, 25, 28, 27, 26, 22, 17, 20, 23, 25, 25, 25, 23, 14, 19, 22, 24, + 24, 24, 24, 25, 28, 29, 31, 32, 30, 26, 23, 27, 28, 29, 30, 27, 23, 22, 25, + 28, 27, 27, 26, 21, 18, 23, 24, 23, 23, 23, 17, 12, 20, 20, 19, 20, 18, 17, + 8, 19, 19, 18, 18, 18, 17, 8, 16, 18, 17, 17, 18, 15, 21, 23, 23, 23, 25, + 24, 17, 18, 21, 22, 22, 22, 22, 15, 14, 20, 20, 19, 20, 18, 14, 10, 17, 17, + 16, 16, 15, 13, 8, 13, 13, 12, 12, 11, 10, 8, 9, 12, 11, 10, 10, 7, 8, + 6, 10, 9, 9, 9, 4, 9, 15, 15, 16, 17, 14, 17, 6, 13, 13, 14, 14, 11, + 15, 6, 11, 11, 11, 11, 8, 10, 6, 6, 8, 8, 7, 5, 6, 4, 2, 4, 4, + 3, 3, 4, 3, 2, 2, 2, 2, 3, 4, 4, 2, 3, 2, 1, 2, 3, 3, 7, + 8, 9, 10, 12, 14, 3, 6, 8, 9, 9, 10, 10, 3, 4, 6, 6, 6, 7, 7, + 3, 3, 3, 3, 3, 4, 3, 1, 3, 5, 3, 2, 2, 3, 1, 4, 6, 4, 3, + 0, 3, 2, 5, 6, 5, 3, 2, 2, 4, 6, 6, 8, 9, 11, 12, 4, 6, 6, + 7, 8, 9, 9, 4, 6, 6, 5, 5, 5, 6, 4, 4, 6, 3, 2, 2, 3, 2, + 5, 7, 6, 3, 2, 2, 4, 6, 8, 7, 4, 3, 2, 5, 7, 8, 8, 5, 3, + 0, +}; diff --git a/libwebp_src/extras/sharpyuv_risk_table.h b/libwebp_src/extras/sharpyuv_risk_table.h new file mode 100644 index 0000000..32f276e --- /dev/null +++ b/libwebp_src/extras/sharpyuv_risk_table.h @@ -0,0 +1,27 @@ +// Copyright 2023 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Precomputed data for 420 risk estimation. + +#ifndef WEBP_EXTRAS_SHARPYUV_RISK_TABLE_H_ +#define WEBP_EXTRAS_SHARPYUV_RISK_TABLE_H_ + +#include "src/webp/types.h" + +extern const int kSharpYuvPrecomputedRiskYuvSampling; +// Table of precomputed risk scores when chroma subsampling images with two +// given colors. +// Since precomputing values for all possible YUV colors would create a huge +// table, the YUV space (i.e. [0, 255]^3) is reduced to +// [0, kSharpYuvPrecomputedRiskYuvSampling-1]^3 +// where 255 maps to kSharpYuvPrecomputedRiskYuvSampling-1. +// Table size: kSharpYuvPrecomputedRiskYuvSampling^6 bytes or 114 KiB +extern const uint8_t kSharpYuvPrecomputedRisk[]; + +#endif // WEBP_EXTRAS_SHARPYUV_RISK_TABLE_H_ diff --git a/libwebp_src/extras/vwebp_sdl.c b/libwebp_src/extras/vwebp_sdl.c index e9554eb..acf4890 100644 --- a/libwebp_src/extras/vwebp_sdl.c +++ b/libwebp_src/extras/vwebp_sdl.c @@ -30,7 +30,7 @@ #if defined(WEBP_HAVE_JUST_SDL_H) #include #else -#include +#include #endif static void ProcessEvents(void) { diff --git a/libwebp_src/extras/webp_to_sdl.c b/libwebp_src/extras/webp_to_sdl.c index 1e52681..971ffc8 100644 --- a/libwebp_src/extras/webp_to_sdl.c +++ b/libwebp_src/extras/webp_to_sdl.c @@ -20,88 +20,75 @@ #include "webp_to_sdl.h" #include + #include "src/webp/decode.h" #if defined(WEBP_HAVE_JUST_SDL_H) #include #else -#include +#include #endif static int init_ok = 0; int WebPToSDL(const char* data, unsigned int data_size) { int ok = 0; VP8StatusCode status; - WebPDecoderConfig config; - WebPBitstreamFeatures* const input = &config.input; - WebPDecBuffer* const output = &config.output; - SDL_Surface* screen = NULL; - SDL_Surface* surface = NULL; - - if (!WebPInitDecoderConfig(&config)) { - fprintf(stderr, "Library version mismatch!\n"); - return 0; - } + WebPBitstreamFeatures input; + uint8_t* output = NULL; + SDL_Window* window = NULL; + SDL_Renderer* renderer = NULL; + SDL_Texture* texture = NULL; + int width, height; if (!init_ok) { SDL_Init(SDL_INIT_VIDEO); init_ok = 1; } - status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &config.input); + status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &input); if (status != VP8_STATUS_OK) goto Error; + width = input.width; + height = input.height; - screen = SDL_SetVideoMode(input->width, input->height, 32, SDL_SWSURFACE); - if (screen == NULL) { - fprintf(stderr, "Unable to set video mode (32bpp %dx%d)!\n", - input->width, input->height); + SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer); + if (window == NULL || renderer == NULL) { + fprintf(stderr, "Unable to create window or renderer!\n"); goto Error; } - - surface = SDL_CreateRGBSurface(SDL_SWSURFACE, - input->width, input->height, 32, - 0x000000ffu, // R mask - 0x0000ff00u, // G mask - 0x00ff0000u, // B mask - 0xff000000u); // A mask - - if (surface == NULL) { - fprintf(stderr, "Unable to create %dx%d RGBA surface!\n", - input->width, input->height); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, + "linear"); // make the scaled rendering look smoother. + SDL_RenderSetLogicalSize(renderer, width, height); + + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, + SDL_TEXTUREACCESS_STREAMING, width, height); + if (texture == NULL) { + fprintf(stderr, "Unable to create %dx%d RGBA texture!\n", width, height); goto Error; } - if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface); #if SDL_BYTEORDER == SDL_BIG_ENDIAN - output->colorspace = MODE_BGRA; + output = WebPDecodeBGRA((const uint8_t*)data, (size_t)data_size, &width, + &height); #else - output->colorspace = MODE_RGBA; + output = WebPDecodeRGBA((const uint8_t*)data, (size_t)data_size, &width, + &height); #endif - output->width = surface->w; - output->height = surface->h; - output->u.RGBA.rgba = surface->pixels; - output->u.RGBA.stride = surface->pitch; - output->u.RGBA.size = surface->pitch * surface->h; - output->is_external_memory = 1; - - status = WebPDecode((const uint8_t*)data, (size_t)data_size, &config); - if (status != VP8_STATUS_OK) { + if (output == NULL) { fprintf(stderr, "Error decoding image (%d)\n", status); goto Error; } - if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); - if (SDL_BlitSurface(surface, NULL, screen, NULL) || - SDL_Flip(screen)) { - goto Error; - } - + SDL_UpdateTexture(texture, NULL, output, width * sizeof(uint32_t)); + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer, texture, NULL, NULL); + SDL_RenderPresent(renderer); ok = 1; Error: - SDL_FreeSurface(surface); - SDL_FreeSurface(screen); - WebPFreeDecBuffer(output); + // We should call SDL_DestroyWindow(window) but that makes .js fail. + SDL_DestroyRenderer(renderer); + SDL_DestroyTexture(texture); + WebPFree(output); return ok; } diff --git a/libwebp_src/imageio/image_enc.c b/libwebp_src/imageio/image_enc.c index e06bcaf..d58477f 100644 --- a/libwebp_src/imageio/image_enc.c +++ b/libwebp_src/imageio/image_enc.c @@ -260,14 +260,20 @@ int WebPWritePAM(FILE* fout, const WebPDecBuffer* const buffer) { // Save 16b mode (RGBA4444, RGB565, ...) for debugging purpose. int WebPWrite16bAsPGM(FILE* fout, const WebPDecBuffer* const buffer) { - const uint32_t width = buffer->width; - const uint32_t height = buffer->height; - const uint8_t* rgba = buffer->u.RGBA.rgba; - const int stride = buffer->u.RGBA.stride; + uint32_t width, height; + uint8_t* rgba; + int stride; const uint32_t bytes_per_px = 2; uint32_t y; - if (fout == NULL || buffer == NULL || rgba == NULL) return 0; + if (fout == NULL || buffer == NULL) return 0; + + width = buffer->width; + height = buffer->height; + rgba = buffer->u.RGBA.rgba; + stride = buffer->u.RGBA.stride; + + if (rgba == NULL) return 0; fprintf(fout, "P5\n%u %u\n255\n", width * bytes_per_px, height); for (y = 0; y < height; ++y) { @@ -295,22 +301,29 @@ static void PutLE32(uint8_t* const dst, uint32_t value) { #define BMP_HEADER_SIZE 54 #define BMP_HEADER_ALPHA_EXTRA_SIZE 16 // for alpha info int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) { - const int has_alpha = WebPIsAlphaMode(buffer->colorspace); - const int header_size = - BMP_HEADER_SIZE + (has_alpha ? BMP_HEADER_ALPHA_EXTRA_SIZE : 0); - const uint32_t width = buffer->width; - const uint32_t height = buffer->height; - const uint8_t* rgba = buffer->u.RGBA.rgba; - const int stride = buffer->u.RGBA.stride; - const uint32_t bytes_per_px = has_alpha ? 4 : 3; + int has_alpha, header_size; + uint32_t width, height; + uint8_t* rgba; + int stride; uint32_t y; - const uint32_t line_size = bytes_per_px * width; - const uint32_t bmp_stride = (line_size + 3) & ~3; // pad to 4 - const uint32_t image_size = bmp_stride * height; - const uint32_t total_size = image_size + header_size; + uint32_t bytes_per_px, line_size, image_size, bmp_stride, total_size; uint8_t bmp_header[BMP_HEADER_SIZE + BMP_HEADER_ALPHA_EXTRA_SIZE] = { 0 }; - if (fout == NULL || buffer == NULL || rgba == NULL) return 0; + if (fout == NULL || buffer == NULL) return 0; + + has_alpha = WebPIsAlphaMode(buffer->colorspace); + header_size = BMP_HEADER_SIZE + (has_alpha ? BMP_HEADER_ALPHA_EXTRA_SIZE : 0); + width = buffer->width; + height = buffer->height; + rgba = buffer->u.RGBA.rgba; + stride = buffer->u.RGBA.stride; + bytes_per_px = has_alpha ? 4 : 3; + line_size = bytes_per_px * width; + bmp_stride = (line_size + 3) & ~3; // pad to 4 + image_size = bmp_stride * height; + total_size = image_size + header_size; + + if (rgba == NULL) return 0; // bitmap file header PutLE16(bmp_header + 0, 0x4d42); // signature 'BM' @@ -372,17 +385,14 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) { #define TIFF_HEADER_SIZE (EXTRA_DATA_OFFSET + EXTRA_DATA_SIZE) int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) { - const int has_alpha = WebPIsAlphaMode(buffer->colorspace); - const uint32_t width = buffer->width; - const uint32_t height = buffer->height; - const uint8_t* rgba = buffer->u.RGBA.rgba; - const int stride = buffer->u.RGBA.stride; - const uint8_t bytes_per_px = has_alpha ? 4 : 3; - const uint8_t assoc_alpha = - WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2; + int has_alpha; + uint32_t width, height; + uint8_t* rgba; + int stride; + uint8_t bytes_per_px = 0; + const uint8_t assoc_alpha = 0; // For non-alpha case, we omit tag 0x152 (ExtraSamples). - const uint8_t num_ifd_entries = has_alpha ? NUM_IFD_ENTRIES - : NUM_IFD_ENTRIES - 1; + const uint8_t num_ifd_entries = 0; uint8_t tiff_header[TIFF_HEADER_SIZE] = { 0x49, 0x49, 0x2a, 0x00, // little endian signature 8, 0, 0, 0, // offset to the unique IFD that follows @@ -416,7 +426,20 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) { }; uint32_t y; - if (fout == NULL || buffer == NULL || rgba == NULL) return 0; + if (fout == NULL || buffer == NULL) return 0; + + has_alpha = WebPIsAlphaMode(buffer->colorspace); + width = buffer->width; + height = buffer->height; + rgba = buffer->u.RGBA.rgba; + stride = buffer->u.RGBA.stride; + + if (rgba == NULL) return 0; + + // Update bytes_per_px, num_ifd_entries and assoc_alpha. + tiff_header[38] = tiff_header[102] = bytes_per_px = has_alpha ? 4 : 3; + tiff_header[8] = has_alpha ? NUM_IFD_ENTRIES : NUM_IFD_ENTRIES - 1; + tiff_header[186] = WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2; // Fill placeholders in IFD: PutLE32(tiff_header + 10 + 8, width); diff --git a/libwebp_src/iosbuild.sh b/libwebp_src/iosbuild.sh index cd3a24c..d0fb557 100755 --- a/libwebp_src/iosbuild.sh +++ b/libwebp_src/iosbuild.sh @@ -41,6 +41,7 @@ readonly TARGETDIR="${TOPDIR}/WebP.framework" readonly DECTARGETDIR="${TOPDIR}/WebPDecoder.framework" readonly MUXTARGETDIR="${TOPDIR}/WebPMux.framework" readonly DEMUXTARGETDIR="${TOPDIR}/WebPDemux.framework" +readonly SHARPYUVTARGETDIR="${TOPDIR}/SharpYuv.framework" readonly DEVELOPER=$(xcode-select --print-path) readonly PLATFORMSROOT="${DEVELOPER}/Platforms" readonly LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo) @@ -63,7 +64,8 @@ echo "Xcode Version: ${XCODE}" echo "iOS SDK Version: ${SDK}" if [[ -e "${BUILDDIR}" || -e "${TARGETDIR}" || -e "${DECTARGETDIR}" \ - || -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" ]]; then + || -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" \ + || -e "${SHARPYUVTARGETDIR}" ]]; then cat << EOF WARNING: The following directories will be deleted: WARNING: ${BUILDDIR} @@ -71,14 +73,16 @@ WARNING: ${TARGETDIR} WARNING: ${DECTARGETDIR} WARNING: ${MUXTARGETDIR} WARNING: ${DEMUXTARGETDIR} +WARNING: ${SHARPYUVTARGETDIR} WARNING: The build will continue in 5 seconds... EOF sleep 5 fi rm -rf ${BUILDDIR} ${TARGETDIR} ${DECTARGETDIR} \ - ${MUXTARGETDIR} ${DEMUXTARGETDIR} + ${MUXTARGETDIR} ${DEMUXTARGETDIR} ${SHARPYUVTARGETDIR} mkdir -p ${BUILDDIR} ${TARGETDIR}/Headers/ ${DECTARGETDIR}/Headers/ \ - ${MUXTARGETDIR}/Headers/ ${DEMUXTARGETDIR}/Headers/ + ${MUXTARGETDIR}/Headers/ ${DEMUXTARGETDIR}/Headers/ \ + ${SHARPYUVTARGETDIR}/Headers/ if [[ ! -e ${SRCDIR}/configure ]]; then if ! (cd ${SRCDIR} && sh autogen.sh); then @@ -134,13 +138,14 @@ for PLATFORM in ${PLATFORMS}; do set +x # Build only the libraries, skip the examples. - make V=0 -C sharpyuv + make V=0 -C sharpyuv install make V=0 -C src install LIBLIST+=" ${ROOTDIR}/lib/libwebp.a" DECLIBLIST+=" ${ROOTDIR}/lib/libwebpdecoder.a" MUXLIBLIST+=" ${ROOTDIR}/lib/libwebpmux.a" DEMUXLIBLIST+=" ${ROOTDIR}/lib/libwebpdemux.a" + SHARPYUVLIBLIST+=" ${ROOTDIR}/lib/libsharpyuv.a" make clean @@ -165,4 +170,9 @@ cp -a ${SRCDIR}/src/webp/{decode,types,mux_types,demux}.h \ ${DEMUXTARGETDIR}/Headers/ ${LIPO} -create ${DEMUXLIBLIST} -output ${DEMUXTARGETDIR}/WebPDemux +echo "SHARPYUVLIBLIST = ${SHARPYUVLIBLIST}" +cp -a ${SRCDIR}/sharpyuv/{sharpyuv,sharpyuv_csp}.h \ + ${SHARPYUVTARGETDIR}/Headers/ +${LIPO} -create ${SHARPYUVLIBLIST} -output ${SHARPYUVTARGETDIR}/SharpYuv + echo "SUCCESS" diff --git a/libwebp_src/makefile.unix b/libwebp_src/makefile.unix index 8348d10..70f97ff 100644 --- a/libwebp_src/makefile.unix +++ b/libwebp_src/makefile.unix @@ -37,13 +37,13 @@ else endif # SDL flags: use sdl-config if it exists -SDL_CONFIG = $(shell sdl-config --version 2> /dev/null) +SDL_CONFIG = $(shell sdl2-config --version 2> /dev/null) ifneq ($(SDL_CONFIG),) - SDL_LIBS = $(shell sdl-config --libs) - SDL_FLAGS = $(shell sdl-config --cflags) + SDL_LIBS = $(shell sdl2-config --libs) + SDL_FLAGS = $(shell sdl2-config --cflags) else # use best-guess - SDL_LIBS = -lSDL + SDL_LIBS = -lSDL2 SDL_FLAGS = endif @@ -276,6 +276,7 @@ UTILS_DEC_OBJS = \ src/utils/color_cache_utils.o \ src/utils/filters_utils.o \ src/utils/huffman_utils.o \ + src/utils/palette.o \ src/utils/quant_levels_dec_utils.o \ src/utils/random_utils.o \ src/utils/rescaler_utils.o \ @@ -290,6 +291,7 @@ UTILS_ENC_OBJS = \ EXTRA_OBJS = \ extras/extras.o \ extras/quality_estimate.o \ + extras/sharpyuv_risk_table.o \ LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS) LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) \ @@ -343,6 +345,7 @@ HDRS = \ src/utils/filters_utils.h \ src/utils/huffman_utils.h \ src/utils/huffman_encode_utils.h \ + src/utils/palette.h \ src/utils/quant_levels_utils.h \ src/utils/quant_levels_dec_utils.h \ src/utils/random_utils.h \ diff --git a/libwebp_src/man/cwebp.1 b/libwebp_src/man/cwebp.1 index 28de4c9..f8d8814 100644 --- a/libwebp_src/man/cwebp.1 +++ b/libwebp_src/man/cwebp.1 @@ -1,5 +1,5 @@ .\" Hey, EMACS: -*- nroff -*- -.TH CWEBP 1 "March 17, 2022" +.TH CWEBP 1 "March 26, 2024" .SH NAME cwebp \- compress an image file to a WebP file .SH SYNOPSIS @@ -135,7 +135,9 @@ are used, \fB\-size\fP value will prevail. Set a maximum number of passes to use during the dichotomy used by options \fB\-size\fP or \fB\-psnr\fP. Maximum value is 10, default is 1. If options \fB\-size\fP or \fB\-psnr\fP were used, but \fB\-pass\fP wasn't -specified, a default value of '6' passes will be used. +specified, a default value of '6' passes will be used. If \fB\-pass\fP is +specified, but neither \fB-size\fP nor \fB-psnr\fP are, a target PSNR of 40dB +will be used. .TP .BI \-qrange " int int Specifies the permissible interval for the quality factor. This is particularly @@ -202,7 +204,8 @@ In the VP8 format, the so\-called control partition has a limit of 512k and is used to store the following information: whether the macroblock is skipped, which segment it belongs to, whether it is coded as intra 4x4 or intra 16x16 mode, and finally the prediction modes to use for each of the sub\-blocks. -For a very large image, 512k only leaves room to few bits per 16x16 macroblock. +For a very large image, 512k only leaves room for a few bits per 16x16 +macroblock. The absolute minimum is 4 bits per macroblock. Skip, segment, and mode information can use up almost all these 4 bits (although the case is unlikely), which is problematic for very large images. The partition_limit factor controls @@ -211,7 +214,8 @@ useful in case the 512k limit is reached and the following message is displayed: \fIError code: 6 (PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k)\fP. If using \fB\-partition_limit\fP is not enough to meet the 512k constraint, one should use less segments in order to save more header bits per macroblock. -See the \fB\-segments\fP option. +See the \fB\-segments\fP option. Note the \fB-m\fP and \fB-q\fP options also +influence the encoder's decisions and ability to hit this limit. .SS LOGGING OPTIONS These options control the level of output: diff --git a/libwebp_src/sharpyuv/Makefile.am b/libwebp_src/sharpyuv/Makefile.am index 8d9ba7c..1a94d46 100644 --- a/libwebp_src/sharpyuv/Makefile.am +++ b/libwebp_src/sharpyuv/Makefile.am @@ -33,7 +33,7 @@ libsharpyuv_la_SOURCES += sharpyuv_gamma.c sharpyuv_gamma.h libsharpyuv_la_SOURCES += sharpyuv.c sharpyuv.h libsharpyuv_la_CPPFLAGS = $(AM_CPPFLAGS) -libsharpyuv_la_LDFLAGS = -no-undefined -version-info 0:1:0 -lm +libsharpyuv_la_LDFLAGS = -no-undefined -version-info 1:0:1 -lm libsharpyuv_la_LIBADD = libsharpyuv_la_LIBADD += libsharpyuv_sse2.la libsharpyuv_la_LIBADD += libsharpyuv_neon.la diff --git a/libwebp_src/sharpyuv/libsharpyuv.rc b/libwebp_src/sharpyuv/libsharpyuv.rc index 49c338a..e0027aa 100644 --- a/libwebp_src/sharpyuv/libsharpyuv.rc +++ b/libwebp_src/sharpyuv/libsharpyuv.rc @@ -6,8 +6,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,0,2,1 - PRODUCTVERSION 0,0,2,1 + FILEVERSION 0,0,4,0 + PRODUCTVERSION 0,0,4,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -24,12 +24,12 @@ BEGIN BEGIN VALUE "CompanyName", "Google, Inc." VALUE "FileDescription", "libsharpyuv DLL" - VALUE "FileVersion", "0.2.1" + VALUE "FileVersion", "0.4.0" VALUE "InternalName", "libsharpyuv.dll" - VALUE "LegalCopyright", "Copyright (C) 2023" + VALUE "LegalCopyright", "Copyright (C) 2024" VALUE "OriginalFilename", "libsharpyuv.dll" VALUE "ProductName", "SharpYuv Library" - VALUE "ProductVersion", "0.2.1" + VALUE "ProductVersion", "0.4.0" END END BLOCK "VarFileInfo" diff --git a/libwebp_src/sharpyuv/sharpyuv.c b/libwebp_src/sharpyuv/sharpyuv.c index a074564..7cbf668 100644 --- a/libwebp_src/sharpyuv/sharpyuv.c +++ b/libwebp_src/sharpyuv/sharpyuv.c @@ -75,41 +75,48 @@ static int RGBToGray(int64_t r, int64_t g, int64_t b) { } static uint32_t ScaleDown(uint16_t a, uint16_t b, uint16_t c, uint16_t d, - int rgb_bit_depth) { + int rgb_bit_depth, + SharpYuvTransferFunctionType transfer_type) { const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth); - const uint32_t A = SharpYuvGammaToLinear(a, bit_depth); - const uint32_t B = SharpYuvGammaToLinear(b, bit_depth); - const uint32_t C = SharpYuvGammaToLinear(c, bit_depth); - const uint32_t D = SharpYuvGammaToLinear(d, bit_depth); - return SharpYuvLinearToGamma((A + B + C + D + 2) >> 2, bit_depth); + const uint32_t A = SharpYuvGammaToLinear(a, bit_depth, transfer_type); + const uint32_t B = SharpYuvGammaToLinear(b, bit_depth, transfer_type); + const uint32_t C = SharpYuvGammaToLinear(c, bit_depth, transfer_type); + const uint32_t D = SharpYuvGammaToLinear(d, bit_depth, transfer_type); + return SharpYuvLinearToGamma((A + B + C + D + 2) >> 2, bit_depth, + transfer_type); } static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int w, - int rgb_bit_depth) { + int rgb_bit_depth, + SharpYuvTransferFunctionType transfer_type) { const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth); - int i; - for (i = 0; i < w; ++i) { - const uint32_t R = SharpYuvGammaToLinear(src[0 * w + i], bit_depth); - const uint32_t G = SharpYuvGammaToLinear(src[1 * w + i], bit_depth); - const uint32_t B = SharpYuvGammaToLinear(src[2 * w + i], bit_depth); + int i = 0; + do { + const uint32_t R = + SharpYuvGammaToLinear(src[0 * w + i], bit_depth, transfer_type); + const uint32_t G = + SharpYuvGammaToLinear(src[1 * w + i], bit_depth, transfer_type); + const uint32_t B = + SharpYuvGammaToLinear(src[2 * w + i], bit_depth, transfer_type); const uint32_t Y = RGBToGray(R, G, B); - dst[i] = (fixed_y_t)SharpYuvLinearToGamma(Y, bit_depth); - } + dst[i] = (fixed_y_t)SharpYuvLinearToGamma(Y, bit_depth, transfer_type); + } while (++i < w); } static void UpdateChroma(const fixed_y_t* src1, const fixed_y_t* src2, - fixed_t* dst, int uv_w, int rgb_bit_depth) { - int i; - for (i = 0; i < uv_w; ++i) { + fixed_t* dst, int uv_w, int rgb_bit_depth, + SharpYuvTransferFunctionType transfer_type) { + int i = 0; + do { const int r = ScaleDown(src1[0 * uv_w + 0], src1[0 * uv_w + 1], src2[0 * uv_w + 0], - src2[0 * uv_w + 1], rgb_bit_depth); + src2[0 * uv_w + 1], rgb_bit_depth, transfer_type); const int g = ScaleDown(src1[2 * uv_w + 0], src1[2 * uv_w + 1], src2[2 * uv_w + 0], - src2[2 * uv_w + 1], rgb_bit_depth); + src2[2 * uv_w + 1], rgb_bit_depth, transfer_type); const int b = ScaleDown(src1[4 * uv_w + 0], src1[4 * uv_w + 1], src2[4 * uv_w + 0], - src2[4 * uv_w + 1], rgb_bit_depth); + src2[4 * uv_w + 1], rgb_bit_depth, transfer_type); const int W = RGBToGray(r, g, b); dst[0 * uv_w] = (fixed_t)(r - W); dst[1 * uv_w] = (fixed_t)(g - W); @@ -117,15 +124,15 @@ static void UpdateChroma(const fixed_y_t* src1, const fixed_y_t* src2, dst += 1; src1 += 2; src2 += 2; - } + } while (++i < uv_w); } static void StoreGray(const fixed_y_t* rgb, fixed_y_t* y, int w) { - int i; + int i = 0; assert(w > 0); - for (i = 0; i < w; ++i) { + do { y[i] = RGBToGray(rgb[0 * w + i], rgb[1 * w + i], rgb[2 * w + i]); - } + } while (++i < w); } //------------------------------------------------------------------------------ @@ -151,9 +158,9 @@ static void ImportOneRow(const uint8_t* const r_ptr, // Convert the rgb_step from a number of bytes to a number of uint8_t or // uint16_t values depending the bit depth. const int step = (rgb_bit_depth > 8) ? rgb_step / 2 : rgb_step; - int i; + int i = 0; const int w = (pic_width + 1) & ~1; - for (i = 0; i < pic_width; ++i) { + do { const int off = i * step; const int shift = GetPrecisionShift(rgb_bit_depth); if (rgb_bit_depth == 8) { @@ -165,7 +172,7 @@ static void ImportOneRow(const uint8_t* const r_ptr, dst[i + 1 * w] = Shift(((uint16_t*)g_ptr)[off], shift); dst[i + 2 * w] = Shift(((uint16_t*)b_ptr)[off], shift); } - } + } while (++i < pic_width); if (pic_width & 1) { // replicate rightmost pixel dst[pic_width + 0 * w] = dst[pic_width + 0 * w - 1]; dst[pic_width + 1 * w] = dst[pic_width + 1 * w - 1]; @@ -233,8 +240,11 @@ static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv, const int sfix = GetPrecisionShift(rgb_bit_depth); const int yuv_max = (1 << yuv_bit_depth) - 1; - for (best_uv = best_uv_base, j = 0; j < height; ++j) { - for (i = 0; i < width; ++i) { + best_uv = best_uv_base; + j = 0; + do { + i = 0; + do { const int off = (i >> 1); const int W = best_y[i]; const int r = best_uv[off + 0 * uv_w] + W; @@ -246,19 +256,22 @@ static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv, } else { ((uint16_t*)y_ptr)[i] = clip(y, yuv_max); } - } + } while (++i < width); best_y += w; best_uv += (j & 1) * 3 * uv_w; y_ptr += y_stride; - } - for (best_uv = best_uv_base, j = 0; j < uv_h; ++j) { - for (i = 0; i < uv_w; ++i) { - const int off = i; + } while (++j < height); + + best_uv = best_uv_base; + j = 0; + do { + i = 0; + do { // Note r, g and b values here are off by W, but a constant offset on all // 3 components doesn't change the value of u and v with a YCbCr matrix. - const int r = best_uv[off + 0 * uv_w]; - const int g = best_uv[off + 1 * uv_w]; - const int b = best_uv[off + 2 * uv_w]; + const int r = best_uv[i + 0 * uv_w]; + const int g = best_uv[i + 1 * uv_w]; + const int b = best_uv[i + 2 * uv_w]; const int u = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_u, sfix); const int v = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_v, sfix); if (yuv_bit_depth <= 8) { @@ -268,11 +281,11 @@ static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv, ((uint16_t*)u_ptr)[i] = clip(u, yuv_max); ((uint16_t*)v_ptr)[i] = clip(v, yuv_max); } - } + } while (++i < uv_w); best_uv += 3 * uv_w; u_ptr += u_stride; v_ptr += v_stride; - } + } while (++j < uv_h); return 1; } @@ -285,7 +298,7 @@ static void* SafeMalloc(uint64_t nmemb, size_t size) { return malloc((size_t)total_size); } -#define SAFE_ALLOC(W, H, T) ((T*)SafeMalloc((W) * (H), sizeof(T))) +#define SAFE_ALLOC(W, H, T) ((T*)SafeMalloc((uint64_t)(W) * (H), sizeof(T))) static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, const uint8_t* b_ptr, int rgb_step, int rgb_stride, @@ -293,12 +306,14 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, uint8_t* u_ptr, int u_stride, uint8_t* v_ptr, int v_stride, int yuv_bit_depth, int width, int height, - const SharpYuvConversionMatrix* yuv_matrix) { + const SharpYuvConversionMatrix* yuv_matrix, + SharpYuvTransferFunctionType transfer_type) { // we expand the right/bottom border if needed const int w = (width + 1) & ~1; const int h = (height + 1) & ~1; const int uv_w = w >> 1; const int uv_h = h >> 1; + const int y_bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth); uint64_t prev_diff_y_sum = ~0; int j, iter; @@ -346,9 +361,9 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, StoreGray(src1, best_y + 0, w); StoreGray(src2, best_y + w, w); - UpdateW(src1, target_y, w, rgb_bit_depth); - UpdateW(src2, target_y + w, w, rgb_bit_depth); - UpdateChroma(src1, src2, target_uv, uv_w, rgb_bit_depth); + UpdateW(src1, target_y, w, rgb_bit_depth, transfer_type); + UpdateW(src2, target_y + w, w, rgb_bit_depth, transfer_type); + UpdateChroma(src1, src2, target_uv, uv_w, rgb_bit_depth, transfer_type); memcpy(best_uv, target_uv, 3 * uv_w * sizeof(*best_uv)); best_y += 2 * w; best_uv += 3 * uv_w; @@ -369,7 +384,8 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, best_uv = best_uv_base; target_y = target_y_base; target_uv = target_uv_base; - for (j = 0; j < h; j += 2) { + j = 0; + do { fixed_y_t* const src1 = tmp_buffer + 0 * w; fixed_y_t* const src2 = tmp_buffer + 3 * w; { @@ -380,21 +396,21 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, cur_uv = next_uv; } - UpdateW(src1, best_rgb_y + 0 * w, w, rgb_bit_depth); - UpdateW(src2, best_rgb_y + 1 * w, w, rgb_bit_depth); - UpdateChroma(src1, src2, best_rgb_uv, uv_w, rgb_bit_depth); + UpdateW(src1, best_rgb_y + 0 * w, w, rgb_bit_depth, transfer_type); + UpdateW(src2, best_rgb_y + 1 * w, w, rgb_bit_depth, transfer_type); + UpdateChroma(src1, src2, best_rgb_uv, uv_w, rgb_bit_depth, transfer_type); // update two rows of Y and one row of RGB diff_y_sum += - SharpYuvUpdateY(target_y, best_rgb_y, best_y, 2 * w, - rgb_bit_depth + GetPrecisionShift(rgb_bit_depth)); + SharpYuvUpdateY(target_y, best_rgb_y, best_y, 2 * w, y_bit_depth); SharpYuvUpdateRGB(target_uv, best_rgb_uv, best_uv, 3 * uv_w); best_y += 2 * w; best_uv += 3 * uv_w; target_y += 2 * w; target_uv += 3 * uv_w; - } + j += 2; + } while (j < h); // test exit condition if (iter > 0) { if (diff_y_sum < diff_y_threshold) break; @@ -418,6 +434,7 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, free(tmp_buffer); return ok; } + #undef SAFE_ALLOC #if defined(WEBP_USE_THREAD) && !defined(_WIN32) @@ -462,12 +479,42 @@ void SharpYuvInit(VP8CPUInfo cpu_info_func) { UNLOCK_ACCESS_AND_RETURN; } -int SharpYuvConvert(const void* r_ptr, const void* g_ptr, - const void* b_ptr, int rgb_step, int rgb_stride, - int rgb_bit_depth, void* y_ptr, int y_stride, - void* u_ptr, int u_stride, void* v_ptr, - int v_stride, int yuv_bit_depth, int width, +int SharpYuvConvert(const void* r_ptr, const void* g_ptr, const void* b_ptr, + int rgb_step, int rgb_stride, int rgb_bit_depth, + void* y_ptr, int y_stride, void* u_ptr, int u_stride, + void* v_ptr, int v_stride, int yuv_bit_depth, int width, int height, const SharpYuvConversionMatrix* yuv_matrix) { + SharpYuvOptions options; + options.yuv_matrix = yuv_matrix; + options.transfer_type = kSharpYuvTransferFunctionSrgb; + return SharpYuvConvertWithOptions( + r_ptr, g_ptr, b_ptr, rgb_step, rgb_stride, rgb_bit_depth, y_ptr, y_stride, + u_ptr, u_stride, v_ptr, v_stride, yuv_bit_depth, width, height, &options); +} + +int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix* yuv_matrix, + SharpYuvOptions* options, int version) { + const int major = (version >> 24); + const int minor = (version >> 16) & 0xff; + if (options == NULL || yuv_matrix == NULL || + (major == SHARPYUV_VERSION_MAJOR && major == 0 && + minor != SHARPYUV_VERSION_MINOR) || + (major != SHARPYUV_VERSION_MAJOR)) { + return 0; + } + options->yuv_matrix = yuv_matrix; + options->transfer_type = kSharpYuvTransferFunctionSrgb; + return 1; +} + +int SharpYuvConvertWithOptions(const void* r_ptr, const void* g_ptr, + const void* b_ptr, int rgb_step, int rgb_stride, + int rgb_bit_depth, void* y_ptr, int y_stride, + void* u_ptr, int u_stride, void* v_ptr, + int v_stride, int yuv_bit_depth, int width, + int height, const SharpYuvOptions* options) { + const SharpYuvConversionMatrix* yuv_matrix = options->yuv_matrix; + SharpYuvTransferFunctionType transfer_type = options->transfer_type; SharpYuvConversionMatrix scaled_matrix; const int rgb_max = (1 << rgb_bit_depth) - 1; const int rgb_round = 1 << (rgb_bit_depth - 1); @@ -486,7 +533,7 @@ int SharpYuvConvert(const void* r_ptr, const void* g_ptr, if (yuv_bit_depth != 8 && yuv_bit_depth != 10 && yuv_bit_depth != 12) { return 0; } - if (rgb_bit_depth > 8 && (rgb_step % 2 != 0 || rgb_stride %2 != 0)) { + if (rgb_bit_depth > 8 && (rgb_step % 2 != 0 || rgb_stride % 2 != 0)) { // Step/stride should be even for uint16_t buffers. return 0; } @@ -521,7 +568,7 @@ int SharpYuvConvert(const void* r_ptr, const void* g_ptr, return DoSharpArgbToYuv(r_ptr, g_ptr, b_ptr, rgb_step, rgb_stride, rgb_bit_depth, y_ptr, y_stride, u_ptr, u_stride, v_ptr, v_stride, yuv_bit_depth, width, height, - &scaled_matrix); + &scaled_matrix, transfer_type); } //------------------------------------------------------------------------------ diff --git a/libwebp_src/sharpyuv/sharpyuv.h b/libwebp_src/sharpyuv/sharpyuv.h index 7b9904d..fe95891 100644 --- a/libwebp_src/sharpyuv/sharpyuv.h +++ b/libwebp_src/sharpyuv/sharpyuv.h @@ -22,22 +22,37 @@ extern "C" { #else // This explicitly marks library functions and allows for changing the // signature for e.g., Windows DLL builds. -#if defined(__GNUC__) && __GNUC__ >= 4 -#define SHARPYUV_EXTERN extern __attribute__((visibility("default"))) -#else -#if defined(_MSC_VER) && defined(WEBP_DLL) +#if defined(_WIN32) && defined(WEBP_DLL) #define SHARPYUV_EXTERN __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +#define SHARPYUV_EXTERN extern __attribute__((visibility("default"))) #else #define SHARPYUV_EXTERN extern -#endif /* _MSC_VER && WEBP_DLL */ -#endif /* __GNUC__ >= 4 */ +#endif /* defined(_WIN32) && defined(WEBP_DLL) */ #endif /* WEBP_EXTERN */ #endif /* SHARPYUV_EXTERN */ +#ifndef SHARPYUV_INLINE +#ifdef WEBP_INLINE +#define SHARPYUV_INLINE WEBP_INLINE +#else +#ifndef _MSC_VER +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +#define SHARPYUV_INLINE inline +#else +#define SHARPYUV_INLINE +#endif +#else +#define SHARPYUV_INLINE __forceinline +#endif /* _MSC_VER */ +#endif /* WEBP_INLINE */ +#endif /* SHARPYUV_INLINE */ + // SharpYUV API version following the convention from semver.org #define SHARPYUV_VERSION_MAJOR 0 -#define SHARPYUV_VERSION_MINOR 2 -#define SHARPYUV_VERSION_PATCH 1 +#define SHARPYUV_VERSION_MINOR 4 +#define SHARPYUV_VERSION_PATCH 0 // Version as a uint32_t. The major number is the high 8 bits. // The minor number is the middle 8 bits. The patch number is the low 16 bits. #define SHARPYUV_MAKE_VERSION(MAJOR, MINOR, PATCH) \ @@ -61,6 +76,33 @@ typedef struct { int rgb_to_v[4]; } SharpYuvConversionMatrix; +typedef struct SharpYuvOptions SharpYuvOptions; + +// Enums for transfer functions, as defined in H.273, +// https://www.itu.int/rec/T-REC-H.273-202107-I/en +typedef enum SharpYuvTransferFunctionType { + // 0 is reserved + kSharpYuvTransferFunctionBt709 = 1, + // 2 is unspecified + // 3 is reserved + kSharpYuvTransferFunctionBt470M = 4, + kSharpYuvTransferFunctionBt470Bg = 5, + kSharpYuvTransferFunctionBt601 = 6, + kSharpYuvTransferFunctionSmpte240 = 7, + kSharpYuvTransferFunctionLinear = 8, + kSharpYuvTransferFunctionLog100 = 9, + kSharpYuvTransferFunctionLog100_Sqrt10 = 10, + kSharpYuvTransferFunctionIec61966 = 11, + kSharpYuvTransferFunctionBt1361 = 12, + kSharpYuvTransferFunctionSrgb = 13, + kSharpYuvTransferFunctionBt2020_10Bit = 14, + kSharpYuvTransferFunctionBt2020_12Bit = 15, + kSharpYuvTransferFunctionSmpte2084 = 16, // PQ + kSharpYuvTransferFunctionSmpte428 = 17, + kSharpYuvTransferFunctionHlg = 18, + kSharpYuvTransferFunctionNum +} SharpYuvTransferFunctionType; + // Converts RGB to YUV420 using a downsampling algorithm that minimizes // artefacts caused by chroma subsampling. // This is slower than standard downsampling (averaging of 4 UV values). @@ -85,6 +127,8 @@ typedef struct { // adjacent pixels on the y, u and v channels. If yuv_bit_depth > 8, they // should be multiples of 2. // width, height: width and height of the image in pixels +// This function calls SharpYuvConvertWithOptions with a default transfer +// function of kSharpYuvTransferFunctionSrgb. SHARPYUV_EXTERN int SharpYuvConvert(const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step, int rgb_stride, int rgb_bit_depth, @@ -93,6 +137,31 @@ SHARPYUV_EXTERN int SharpYuvConvert(const void* r_ptr, const void* g_ptr, int yuv_bit_depth, int width, int height, const SharpYuvConversionMatrix* yuv_matrix); +struct SharpYuvOptions { + // This matrix cannot be NULL and can be initialized by + // SharpYuvComputeConversionMatrix. + const SharpYuvConversionMatrix* yuv_matrix; + SharpYuvTransferFunctionType transfer_type; +}; + +// Internal, version-checked, entry point +SHARPYUV_EXTERN int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix*, + SharpYuvOptions*, int); + +// Should always be called, to initialize a fresh SharpYuvOptions +// structure before modification. SharpYuvOptionsInit() must have succeeded +// before using the 'options' object. +static SHARPYUV_INLINE int SharpYuvOptionsInit( + const SharpYuvConversionMatrix* yuv_matrix, SharpYuvOptions* options) { + return SharpYuvOptionsInitInternal(yuv_matrix, options, SHARPYUV_VERSION); +} + +SHARPYUV_EXTERN int SharpYuvConvertWithOptions( + const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step, + int rgb_stride, int rgb_bit_depth, void* y_ptr, int y_stride, void* u_ptr, + int u_stride, void* v_ptr, int v_stride, int yuv_bit_depth, int width, + int height, const SharpYuvOptions* options); + // TODO(b/194336375): Add YUV444 to YUV420 conversion. Maybe also add 422 // support (it's rarely used in practice, especially for images). diff --git a/libwebp_src/sharpyuv/sharpyuv_dsp.c b/libwebp_src/sharpyuv/sharpyuv_dsp.c index 0da3efc..94a40ec 100644 --- a/libwebp_src/sharpyuv/sharpyuv_dsp.c +++ b/libwebp_src/sharpyuv/sharpyuv_dsp.c @@ -17,6 +17,7 @@ #include #include "sharpyuv/sharpyuv_cpu.h" +#include "src/webp/types.h" //----------------------------------------------------------------------------- @@ -69,8 +70,7 @@ uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref, void (*SharpYuvUpdateRGB)(const int16_t* src, const int16_t* ref, int16_t* dst, int len); void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len, - const uint16_t* best_y, uint16_t* out, - int bit_depth); + const uint16_t* best_y, uint16_t* out, int bit_depth); extern VP8CPUInfo SharpYuvGetCPUInfo; extern void InitSharpYuvSSE2(void); diff --git a/libwebp_src/sharpyuv/sharpyuv_gamma.c b/libwebp_src/sharpyuv/sharpyuv_gamma.c index 20ab2da..0902842 100644 --- a/libwebp_src/sharpyuv/sharpyuv_gamma.c +++ b/libwebp_src/sharpyuv/sharpyuv_gamma.c @@ -12,6 +12,7 @@ #include "sharpyuv/sharpyuv_gamma.h" #include +#include #include #include "src/webp/types.h" @@ -97,7 +98,7 @@ static WEBP_INLINE uint32_t FixedPointInterpolation(int v, uint32_t* tab, return result; } -uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth) { +static uint32_t ToLinearSrgb(uint16_t v, int bit_depth) { const int shift = GAMMA_TO_LINEAR_TAB_BITS - bit_depth; if (shift > 0) { return kGammaToLinearTabS[v << shift]; @@ -105,9 +106,314 @@ uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth) { return FixedPointInterpolation(v, kGammaToLinearTabS, -shift, 0); } -uint16_t SharpYuvLinearToGamma(uint32_t value, int bit_depth) { +static uint16_t FromLinearSrgb(uint32_t value, int bit_depth) { return FixedPointInterpolation( value, kLinearToGammaTabS, (GAMMA_TO_LINEAR_BITS - LINEAR_TO_GAMMA_TAB_BITS), bit_depth - GAMMA_TO_LINEAR_BITS); } + +//////////////////////////////////////////////////////////////////////////////// + +#define CLAMP(x, low, high) \ + (((x) < (low)) ? (low) : (((high) < (x)) ? (high) : (x))) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +static WEBP_INLINE float Roundf(float x) { + if (x < 0) + return (float)ceil((double)(x - 0.5f)); + else + return (float)floor((double)(x + 0.5f)); +} + +static WEBP_INLINE float Powf(float base, float exp) { + return (float)pow((double)base, (double)exp); +} + +static WEBP_INLINE float Log10f(float x) { return (float)log10((double)x); } + +static float ToLinear709(float gamma) { + if (gamma < 0.f) { + return 0.f; + } else if (gamma < 4.5f * 0.018053968510807f) { + return gamma / 4.5f; + } else if (gamma < 1.f) { + return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f); + } + return 1.f; +} + +static float FromLinear709(float linear) { + if (linear < 0.f) { + return 0.f; + } else if (linear < 0.018053968510807f) { + return linear * 4.5f; + } else if (linear < 1.f) { + return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f; + } + return 1.f; +} + +static float ToLinear470M(float gamma) { + return Powf(CLAMP(gamma, 0.f, 1.f), 2.2f); +} + +static float FromLinear470M(float linear) { + return Powf(CLAMP(linear, 0.f, 1.f), 1.f / 2.2f); +} + +static float ToLinear470Bg(float gamma) { + return Powf(CLAMP(gamma, 0.f, 1.f), 2.8f); +} + +static float FromLinear470Bg(float linear) { + return Powf(CLAMP(linear, 0.f, 1.f), 1.f / 2.8f); +} + +static float ToLinearSmpte240(float gamma) { + if (gamma < 0.f) { + return 0.f; + } else if (gamma < 4.f * 0.022821585529445f) { + return gamma / 4.f; + } else if (gamma < 1.f) { + return Powf((gamma + 0.111572195921731f) / 1.111572195921731f, 1.f / 0.45f); + } + return 1.f; +} + +static float FromLinearSmpte240(float linear) { + if (linear < 0.f) { + return 0.f; + } else if (linear < 0.022821585529445f) { + return linear * 4.f; + } else if (linear < 1.f) { + return 1.111572195921731f * Powf(linear, 0.45f) - 0.111572195921731f; + } + return 1.f; +} + +static float ToLinearLog100(float gamma) { + // The function is non-bijective so choose the middle of [0, 0.01]. + const float mid_interval = 0.01f / 2.f; + return (gamma <= 0.0f) ? mid_interval + : Powf(10.0f, 2.f * (MIN(gamma, 1.f) - 1.0f)); +} + +static float FromLinearLog100(float linear) { + return (linear < 0.01f) ? 0.0f : 1.0f + Log10f(MIN(linear, 1.f)) / 2.0f; +} + +static float ToLinearLog100Sqrt10(float gamma) { + // The function is non-bijective so choose the middle of [0, 0.00316227766f[. + const float mid_interval = 0.00316227766f / 2.f; + return (gamma <= 0.0f) ? mid_interval + : Powf(10.0f, 2.5f * (MIN(gamma, 1.f) - 1.0f)); +} + +static float FromLinearLog100Sqrt10(float linear) { + return (linear < 0.00316227766f) ? 0.0f + : 1.0f + Log10f(MIN(linear, 1.f)) / 2.5f; +} + +static float ToLinearIec61966(float gamma) { + if (gamma <= -4.5f * 0.018053968510807f) { + return Powf((-gamma + 0.09929682680944f) / -1.09929682680944f, 1.f / 0.45f); + } else if (gamma < 4.5f * 0.018053968510807f) { + return gamma / 4.5f; + } + return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f); +} + +static float FromLinearIec61966(float linear) { + if (linear <= -0.018053968510807f) { + return -1.09929682680944f * Powf(-linear, 0.45f) + 0.09929682680944f; + } else if (linear < 0.018053968510807f) { + return linear * 4.5f; + } + return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f; +} + +static float ToLinearBt1361(float gamma) { + if (gamma < -0.25f) { + return -0.25f; + } else if (gamma < 0.f) { + return Powf((gamma - 0.02482420670236f) / -0.27482420670236f, 1.f / 0.45f) / + -4.f; + } else if (gamma < 4.5f * 0.018053968510807f) { + return gamma / 4.5f; + } else if (gamma < 1.f) { + return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f); + } + return 1.f; +} + +static float FromLinearBt1361(float linear) { + if (linear < -0.25f) { + return -0.25f; + } else if (linear < 0.f) { + return -0.27482420670236f * Powf(-4.f * linear, 0.45f) + 0.02482420670236f; + } else if (linear < 0.018053968510807f) { + return linear * 4.5f; + } else if (linear < 1.f) { + return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f; + } + return 1.f; +} + +static float ToLinearPq(float gamma) { + if (gamma > 0.f) { + const float pow_gamma = Powf(gamma, 32.f / 2523.f); + const float num = MAX(pow_gamma - 107.f / 128.f, 0.0f); + const float den = MAX(2413.f / 128.f - 2392.f / 128.f * pow_gamma, FLT_MIN); + return Powf(num / den, 4096.f / 653.f); + } + return 0.f; +} + +static float FromLinearPq(float linear) { + if (linear > 0.f) { + const float pow_linear = Powf(linear, 653.f / 4096.f); + const float num = 107.f / 128.f + 2413.f / 128.f * pow_linear; + const float den = 1.0f + 2392.f / 128.f * pow_linear; + return Powf(num / den, 2523.f / 32.f); + } + return 0.f; +} + +static float ToLinearSmpte428(float gamma) { + return Powf(MAX(gamma, 0.f), 2.6f) / 0.91655527974030934f; +} + +static float FromLinearSmpte428(float linear) { + return Powf(0.91655527974030934f * MAX(linear, 0.f), 1.f / 2.6f); +} + +// Conversion in BT.2100 requires RGB info. Simplify to gamma correction here. +static float ToLinearHlg(float gamma) { + if (gamma < 0.f) { + return 0.f; + } else if (gamma <= 0.5f) { + return Powf((gamma * gamma) * (1.f / 3.f), 1.2f); + } + return Powf((expf((gamma - 0.55991073f) / 0.17883277f) + 0.28466892f) / 12.0f, + 1.2f); +} + +static float FromLinearHlg(float linear) { + linear = Powf(linear, 1.f / 1.2f); + if (linear < 0.f) { + return 0.f; + } else if (linear <= (1.f / 12.f)) { + return sqrtf(3.f * linear); + } + return 0.17883277f * logf(12.f * linear - 0.28466892f) + 0.55991073f; +} + +uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth, + SharpYuvTransferFunctionType transfer_type) { + float v_float, linear; + if (transfer_type == kSharpYuvTransferFunctionSrgb) { + return ToLinearSrgb(v, bit_depth); + } + v_float = (float)v / ((1 << bit_depth) - 1); + switch (transfer_type) { + case kSharpYuvTransferFunctionBt709: + case kSharpYuvTransferFunctionBt601: + case kSharpYuvTransferFunctionBt2020_10Bit: + case kSharpYuvTransferFunctionBt2020_12Bit: + linear = ToLinear709(v_float); + break; + case kSharpYuvTransferFunctionBt470M: + linear = ToLinear470M(v_float); + break; + case kSharpYuvTransferFunctionBt470Bg: + linear = ToLinear470Bg(v_float); + break; + case kSharpYuvTransferFunctionSmpte240: + linear = ToLinearSmpte240(v_float); + break; + case kSharpYuvTransferFunctionLinear: + return v; + case kSharpYuvTransferFunctionLog100: + linear = ToLinearLog100(v_float); + break; + case kSharpYuvTransferFunctionLog100_Sqrt10: + linear = ToLinearLog100Sqrt10(v_float); + break; + case kSharpYuvTransferFunctionIec61966: + linear = ToLinearIec61966(v_float); + break; + case kSharpYuvTransferFunctionBt1361: + linear = ToLinearBt1361(v_float); + break; + case kSharpYuvTransferFunctionSmpte2084: + linear = ToLinearPq(v_float); + break; + case kSharpYuvTransferFunctionSmpte428: + linear = ToLinearSmpte428(v_float); + break; + case kSharpYuvTransferFunctionHlg: + linear = ToLinearHlg(v_float); + break; + default: + assert(0); + linear = 0; + break; + } + return (uint32_t)Roundf(linear * ((1 << 16) - 1)); +} + +uint16_t SharpYuvLinearToGamma(uint32_t v, int bit_depth, + SharpYuvTransferFunctionType transfer_type) { + float v_float, linear; + if (transfer_type == kSharpYuvTransferFunctionSrgb) { + return FromLinearSrgb(v, bit_depth); + } + v_float = (float)v / ((1 << 16) - 1); + switch (transfer_type) { + case kSharpYuvTransferFunctionBt709: + case kSharpYuvTransferFunctionBt601: + case kSharpYuvTransferFunctionBt2020_10Bit: + case kSharpYuvTransferFunctionBt2020_12Bit: + linear = FromLinear709(v_float); + break; + case kSharpYuvTransferFunctionBt470M: + linear = FromLinear470M(v_float); + break; + case kSharpYuvTransferFunctionBt470Bg: + linear = FromLinear470Bg(v_float); + break; + case kSharpYuvTransferFunctionSmpte240: + linear = FromLinearSmpte240(v_float); + break; + case kSharpYuvTransferFunctionLinear: + return v; + case kSharpYuvTransferFunctionLog100: + linear = FromLinearLog100(v_float); + break; + case kSharpYuvTransferFunctionLog100_Sqrt10: + linear = FromLinearLog100Sqrt10(v_float); + break; + case kSharpYuvTransferFunctionIec61966: + linear = FromLinearIec61966(v_float); + break; + case kSharpYuvTransferFunctionBt1361: + linear = FromLinearBt1361(v_float); + break; + case kSharpYuvTransferFunctionSmpte2084: + linear = FromLinearPq(v_float); + break; + case kSharpYuvTransferFunctionSmpte428: + linear = FromLinearSmpte428(v_float); + break; + case kSharpYuvTransferFunctionHlg: + linear = FromLinearHlg(v_float); + break; + default: + assert(0); + linear = 0; + break; + } + return (uint16_t)Roundf(linear * ((1 << bit_depth) - 1)); +} diff --git a/libwebp_src/sharpyuv/sharpyuv_gamma.h b/libwebp_src/sharpyuv/sharpyuv_gamma.h index d13aff5..b8ba7e9 100644 --- a/libwebp_src/sharpyuv/sharpyuv_gamma.h +++ b/libwebp_src/sharpyuv/sharpyuv_gamma.h @@ -12,6 +12,7 @@ #ifndef WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ #define WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ +#include "sharpyuv/sharpyuv.h" #include "src/webp/types.h" #ifdef __cplusplus @@ -22,11 +23,13 @@ extern "C" { // SharpYuvGammaToLinear or SharpYuvLinearToGamma. void SharpYuvInitGammaTables(void); -// Converts a gamma color value on 'bit_depth' bits to a 16 bit linear value. -uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth); +// Converts a 'bit_depth'-bit gamma color value to a 16-bit linear value. +uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth, + SharpYuvTransferFunctionType transfer_type); -// Converts a 16 bit linear color value to a gamma value on 'bit_depth' bits. -uint16_t SharpYuvLinearToGamma(uint32_t value, int bit_depth); +// Converts a 16-bit linear color value to a 'bit_depth'-bit gamma value. +uint16_t SharpYuvLinearToGamma(uint32_t value, int bit_depth, + SharpYuvTransferFunctionType transfer_type); #ifdef __cplusplus } // extern "C" diff --git a/libwebp_src/src/Makefile.am b/libwebp_src/src/Makefile.am index bc4a320..1dafadd 100644 --- a/libwebp_src/src/Makefile.am +++ b/libwebp_src/src/Makefile.am @@ -36,7 +36,7 @@ libwebp_la_LIBADD += utils/libwebputils.la # other than the ones listed on the command line, i.e., after linking, it will # not have unresolved symbols. Some platforms (Windows among them) require all # symbols in shared libraries to be resolved at library creation. -libwebp_la_LDFLAGS = -no-undefined -version-info 8:8:1 +libwebp_la_LDFLAGS = -no-undefined -version-info 8:9:1 libwebpincludedir = $(includedir)/webp pkgconfig_DATA = libwebp.pc @@ -48,7 +48,7 @@ if BUILD_LIBWEBPDECODER libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la - libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 4:8:1 + libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 4:9:1 pkgconfig_DATA += libwebpdecoder.pc endif diff --git a/libwebp_src/src/dec/alpha_dec.c b/libwebp_src/src/dec/alpha_dec.c index 0b93a30..b6c874f 100644 --- a/libwebp_src/src/dec/alpha_dec.c +++ b/libwebp_src/src/dec/alpha_dec.c @@ -13,18 +13,20 @@ #include #include "src/dec/alphai_dec.h" +#include "src/dec/vp8_dec.h" #include "src/dec/vp8i_dec.h" #include "src/dec/vp8li_dec.h" #include "src/dsp/dsp.h" #include "src/utils/quant_levels_dec_utils.h" #include "src/utils/utils.h" #include "src/webp/format_constants.h" +#include "src/webp/types.h" //------------------------------------------------------------------------------ // ALPHDecoder object. // Allocates a new alpha decoder instance. -static ALPHDecoder* ALPHNew(void) { +WEBP_NODISCARD static ALPHDecoder* ALPHNew(void) { ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); return dec; } @@ -45,9 +47,9 @@ static void ALPHDelete(ALPHDecoder* const dec) { // header for alpha data stored using lossless compression. // Returns false in case of error in alpha header (data too short, invalid // compression method or filter, error in lossless header data etc). -static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, - size_t data_size, const VP8Io* const src_io, - uint8_t* output) { +WEBP_NODISCARD static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, + size_t data_size, const VP8Io* const src_io, + uint8_t* output) { int ok = 0; const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; @@ -79,7 +81,9 @@ static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, } // Copy the necessary parameters from src_io to io - VP8InitIo(io); + if (!VP8InitIo(io)) { + return 0; + } WebPInitCustomIo(NULL, io); io->opaque = dec; io->width = src_io->width; @@ -107,7 +111,8 @@ static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, // starting from row number 'row'. It assumes that rows up to (row - 1) have // already been decoded. // Returns false in case of bitstream error. -static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { +WEBP_NODISCARD static int ALPHDecode(VP8Decoder* const dec, int row, + int num_rows) { ALPHDecoder* const alph_dec = dec->alph_dec_; const int width = alph_dec->width_; const int height = alph_dec->io_.crop_bottom; @@ -117,21 +122,12 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { const uint8_t* deltas = dec->alpha_data_ + ALPHA_HEADER_LEN + row * width; uint8_t* dst = dec->alpha_plane_ + row * width; assert(deltas <= &dec->alpha_data_[dec->alpha_data_size_]); - if (alph_dec->filter_ != WEBP_FILTER_NONE) { - assert(WebPUnfilters[alph_dec->filter_] != NULL); - for (y = 0; y < num_rows; ++y) { - WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width); - prev_line = dst; - dst += width; - deltas += width; - } - } else { - for (y = 0; y < num_rows; ++y) { - memcpy(dst, deltas, width * sizeof(*dst)); - prev_line = dst; - dst += width; - deltas += width; - } + assert(WebPUnfilters[alph_dec->filter_] != NULL); + for (y = 0; y < num_rows; ++y) { + WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width); + prev_line = dst; + dst += width; + deltas += width; } dec->alpha_prev_line_ = prev_line; } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION @@ -147,7 +143,8 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { return 1; } -static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) { +WEBP_NODISCARD static int AllocateAlphaPlane(VP8Decoder* const dec, + const VP8Io* const io) { const int stride = io->width; const int height = io->crop_bottom; const uint64_t alpha_size = (uint64_t)stride * height; @@ -155,7 +152,8 @@ static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) { dec->alpha_plane_mem_ = (uint8_t*)WebPSafeMalloc(alpha_size, sizeof(*dec->alpha_plane_)); if (dec->alpha_plane_mem_ == NULL) { - return 0; + return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, + "Alpha decoder initialization failed."); } dec->alpha_plane_ = dec->alpha_plane_mem_; dec->alpha_prev_line_ = NULL; @@ -174,9 +172,9 @@ void WebPDeallocateAlphaMemory(VP8Decoder* const dec) { //------------------------------------------------------------------------------ // Main entry point. -const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, - const VP8Io* const io, - int row, int num_rows) { +WEBP_NODISCARD const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, + const VP8Io* const io, + int row, int num_rows) { const int width = io->width; const int height = io->crop_bottom; @@ -189,10 +187,19 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, if (!dec->is_alpha_decoded_) { if (dec->alph_dec_ == NULL) { // Initialize decoder. dec->alph_dec_ = ALPHNew(); - if (dec->alph_dec_ == NULL) return NULL; + if (dec->alph_dec_ == NULL) { + VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, + "Alpha decoder initialization failed."); + return NULL; + } if (!AllocateAlphaPlane(dec, io)) goto Error; if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_, io, dec->alpha_plane_)) { + VP8LDecoder* const vp8l_dec = dec->alph_dec_->vp8l_dec_; + VP8SetError(dec, + (vp8l_dec == NULL) ? VP8_STATUS_OUT_OF_MEMORY + : vp8l_dec->status_, + "Alpha decoder initialization failed."); goto Error; } // if we allowed use of alpha dithering, check whether it's needed at all diff --git a/libwebp_src/src/dec/buffer_dec.c b/libwebp_src/src/dec/buffer_dec.c index 4786cf0..11ce76f 100644 --- a/libwebp_src/src/dec/buffer_dec.c +++ b/libwebp_src/src/dec/buffer_dec.c @@ -75,7 +75,7 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { const WebPRGBABuffer* const buf = &buffer->u.RGBA; const int stride = abs(buf->stride); const uint64_t size = - MIN_BUFFER_SIZE(width * kModeBpp[mode], height, stride); + MIN_BUFFER_SIZE((uint64_t)width * kModeBpp[mode], height, stride); ok &= (size <= buf->size); ok &= (stride >= width * kModeBpp[mode]); ok &= (buf->rgba != NULL); diff --git a/libwebp_src/src/dec/idec_dec.c b/libwebp_src/src/dec/idec_dec.c index 9035df5..ad042a1 100644 --- a/libwebp_src/src/dec/idec_dec.c +++ b/libwebp_src/src/dec/idec_dec.c @@ -17,8 +17,10 @@ #include "src/dec/alphai_dec.h" #include "src/dec/webpi_dec.h" +#include "src/dec/vp8_dec.h" #include "src/dec/vp8i_dec.h" #include "src/utils/utils.h" +#include "src/webp/decode.h" // In append mode, buffer allocations increase as multiples of this value. // Needs to be a power of 2. @@ -161,8 +163,9 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { // Appends data to the end of MemBuffer->buf_. It expands the allocated memory // size if required and also updates VP8BitReader's if new memory is allocated. -static int AppendToMemBuffer(WebPIDecoder* const idec, - const uint8_t* const data, size_t data_size) { +WEBP_NODISCARD static int AppendToMemBuffer(WebPIDecoder* const idec, + const uint8_t* const data, + size_t data_size) { VP8Decoder* const dec = (VP8Decoder*)idec->dec_; MemBuffer* const mem = &idec->mem_; const int need_compressed_alpha = NeedCompressedAlpha(idec); @@ -203,8 +206,9 @@ static int AppendToMemBuffer(WebPIDecoder* const idec, return 1; } -static int RemapMemBuffer(WebPIDecoder* const idec, - const uint8_t* const data, size_t data_size) { +WEBP_NODISCARD static int RemapMemBuffer(WebPIDecoder* const idec, + const uint8_t* const data, + size_t data_size) { MemBuffer* const mem = &idec->mem_; const uint8_t* const old_buf = mem->buf_; const uint8_t* const old_start = @@ -237,7 +241,8 @@ static void ClearMemBuffer(MemBuffer* const mem) { } } -static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) { +WEBP_NODISCARD static int CheckMemBufferMode(MemBuffer* const mem, + MemBufferMode expected) { if (mem->mode_ == MEM_MODE_NONE) { mem->mode_ = expected; // switch to the expected mode } else if (mem->mode_ != expected) { @@ -248,7 +253,7 @@ static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) { } // To be called last. -static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { +WEBP_NODISCARD static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { const WebPDecoderOptions* const options = idec->params_.options; WebPDecBuffer* const output = idec->params_.output; @@ -258,8 +263,10 @@ static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { if (status != VP8_STATUS_OK) return status; } if (idec->final_output_ != NULL) { - WebPCopyDecBufferPixels(output, idec->final_output_); // do the slow-copy + const VP8StatusCode status = WebPCopyDecBufferPixels( + output, idec->final_output_); // do the slow-copy WebPFreeDecBuffer(&idec->output_); + if (status != VP8_STATUS_OK) return status; *output = *idec->final_output_; idec->final_output_ = NULL; } @@ -288,7 +295,7 @@ static void RestoreContext(const MBContext* context, VP8Decoder* const dec, static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { if (idec->state_ == STATE_VP8_DATA) { // Synchronize the thread, clean-up and check for errors. - VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); + (void)VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); } idec->state_ = STATE_ERROR; return error; @@ -329,6 +336,7 @@ static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) { if (dec == NULL) { return VP8_STATUS_OUT_OF_MEMORY; } + dec->incremental_ = 1; idec->dec_ = dec; dec->alpha_data_ = headers.alpha_data; dec->alpha_data_size_ = headers.alpha_data_size; @@ -601,8 +609,9 @@ static VP8StatusCode IDecode(WebPIDecoder* idec) { //------------------------------------------------------------------------------ // Internal constructor -static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer, - const WebPBitstreamFeatures* const features) { +WEBP_NODISCARD static WebPIDecoder* NewDecoder( + WebPDecBuffer* const output_buffer, + const WebPBitstreamFeatures* const features) { WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec)); if (idec == NULL) { return NULL; @@ -614,8 +623,10 @@ static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer, idec->last_mb_y_ = -1; InitMemBuffer(&idec->mem_); - WebPInitDecBuffer(&idec->output_); - VP8InitIo(&idec->io_); + if (!WebPInitDecBuffer(&idec->output_) || !VP8InitIo(&idec->io_)) { + WebPSafeFree(idec); + return NULL; + } WebPResetDecParams(&idec->params_); if (output_buffer == NULL || WebPAvoidSlowMemory(output_buffer, features)) { @@ -674,7 +685,8 @@ void WebPIDelete(WebPIDecoder* idec) { if (!idec->is_lossless_) { if (idec->state_ == STATE_VP8_DATA) { // Synchronize the thread, clean-up and check for errors. - VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); + // TODO(vrabaud) do we care about the return result? + (void)VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); } VP8Delete((VP8Decoder*)idec->dec_); } else { @@ -851,8 +863,8 @@ const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, return src; } -uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, - int* width, int* height, int* stride) { +WEBP_NODISCARD uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, + int* width, int* height, int* stride) { const WebPDecBuffer* const src = GetOutputBuffer(idec); if (src == NULL) return NULL; if (src->colorspace >= MODE_YUV) { @@ -867,10 +879,10 @@ uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, return src->u.RGBA.rgba; } -uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y, - uint8_t** u, uint8_t** v, uint8_t** a, - int* width, int* height, - int* stride, int* uv_stride, int* a_stride) { +WEBP_NODISCARD uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y, + uint8_t** u, uint8_t** v, uint8_t** a, + int* width, int* height, int* stride, + int* uv_stride, int* a_stride) { const WebPDecBuffer* const src = GetOutputBuffer(idec); if (src == NULL) return NULL; if (src->colorspace < MODE_YUV) { diff --git a/libwebp_src/src/dec/vp8_dec.c b/libwebp_src/src/dec/vp8_dec.c index 20b92e8..2ee8900 100644 --- a/libwebp_src/src/dec/vp8_dec.c +++ b/libwebp_src/src/dec/vp8_dec.c @@ -86,6 +86,8 @@ void VP8Delete(VP8Decoder* const dec) { int VP8SetError(VP8Decoder* const dec, VP8StatusCode error, const char* const msg) { + // VP8_STATUS_SUSPENDED is only meaningful in incremental decoding. + assert(dec->incremental_ || error != VP8_STATUS_SUSPENDED); // The oldest error reported takes precedence over the new one. if (dec->status_ == VP8_STATUS_OK) { dec->status_ = error; @@ -190,12 +192,12 @@ static int ParseSegmentHeader(VP8BitReader* br, } // Paragraph 9.5 -// This function returns VP8_STATUS_SUSPENDED if we don't have all the -// necessary data in 'buf'. -// This case is not necessarily an error (for incremental decoding). -// Still, no bitreader is ever initialized to make it possible to read -// unavailable memory. -// If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA +// If we don't have all the necessary data in 'buf', this function returns +// VP8_STATUS_SUSPENDED in incremental decoding, VP8_STATUS_NOT_ENOUGH_DATA +// otherwise. +// In incremental decoding, this case is not necessarily an error. Still, no +// bitreader is ever initialized to make it possible to read unavailable memory. +// If we don't even have the partitions' sizes, then VP8_STATUS_NOT_ENOUGH_DATA // is returned, and this is an unrecoverable error. // If the partitions were positioned ok, VP8_STATUS_OK is returned. static VP8StatusCode ParsePartitions(VP8Decoder* const dec, @@ -225,8 +227,10 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec, sz += 3; } VP8InitBitReader(dec->parts_ + last_part, part_start, size_left); - return (part_start < buf_end) ? VP8_STATUS_OK : - VP8_STATUS_SUSPENDED; // Init is ok, but there's not enough data + if (part_start < buf_end) return VP8_STATUS_OK; + return dec->incremental_ + ? VP8_STATUS_SUSPENDED // Init is ok, but there's not enough data + : VP8_STATUS_NOT_ENOUGH_DATA; } // Paragraph 9.4 diff --git a/libwebp_src/src/dec/vp8_dec.h b/libwebp_src/src/dec/vp8_dec.h index a05405d..91fe104 100644 --- a/libwebp_src/src/dec/vp8_dec.h +++ b/libwebp_src/src/dec/vp8_dec.h @@ -15,6 +15,7 @@ #define WEBP_DEC_VP8_DEC_H_ #include "src/webp/decode.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -108,16 +109,14 @@ struct VP8Io { }; // Internal, version-checked, entry point -int VP8InitIoInternal(VP8Io* const, int); +WEBP_NODISCARD int VP8InitIoInternal(VP8Io* const, int); // Set the custom IO function pointers and user-data. The setter for IO hooks // should be called before initiating incremental decoding. Returns true if // WebPIDecoder object is successfully modified, false otherwise. -int WebPISetIOHooks(WebPIDecoder* const idec, - VP8IoPutHook put, - VP8IoSetupHook setup, - VP8IoTeardownHook teardown, - void* user_data); +WEBP_NODISCARD int WebPISetIOHooks(WebPIDecoder* const idec, VP8IoPutHook put, + VP8IoSetupHook setup, + VP8IoTeardownHook teardown, void* user_data); // Main decoding object. This is an opaque structure. typedef struct VP8Decoder VP8Decoder; @@ -128,17 +127,17 @@ VP8Decoder* VP8New(void); // Must be called to make sure 'io' is initialized properly. // Returns false in case of version mismatch. Upon such failure, no other // decoding function should be called (VP8Decode, VP8GetHeaders, ...) -static WEBP_INLINE int VP8InitIo(VP8Io* const io) { +WEBP_NODISCARD static WEBP_INLINE int VP8InitIo(VP8Io* const io) { return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION); } // Decode the VP8 frame header. Returns true if ok. // Note: 'io->data' must be pointing to the start of the VP8 frame header. -int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io); +WEBP_NODISCARD int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io); // Decode a picture. Will call VP8GetHeaders() if it wasn't done already. // Returns false in case of error. -int VP8Decode(VP8Decoder* const dec, VP8Io* const io); +WEBP_NODISCARD int VP8Decode(VP8Decoder* const dec, VP8Io* const io); // Return current status of the decoder: VP8StatusCode VP8Status(VP8Decoder* const dec); diff --git a/libwebp_src/src/dec/vp8i_dec.h b/libwebp_src/src/dec/vp8i_dec.h index 7929fd7..cb21d47 100644 --- a/libwebp_src/src/dec/vp8i_dec.h +++ b/libwebp_src/src/dec/vp8i_dec.h @@ -21,6 +21,7 @@ #include "src/utils/random_utils.h" #include "src/utils/thread_utils.h" #include "src/dsp/dsp.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -31,8 +32,8 @@ extern "C" { // version numbers #define DEC_MAJ_VERSION 1 -#define DEC_MIN_VERSION 3 -#define DEC_REV_VERSION 2 +#define DEC_MIN_VERSION 4 +#define DEC_REV_VERSION 0 // YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). // Constraints are: We need to store one 16x16 block of luma samples (y), @@ -186,6 +187,7 @@ struct VP8Decoder { // Main data source VP8BitReader br_; + int incremental_; // if true, incremental decoding is expected // headers VP8FrameHeader frm_hdr_; @@ -281,7 +283,7 @@ int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec); void VP8ParseQuant(VP8Decoder* const dec); // in frame.c -int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io); +WEBP_NODISCARD int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io); // Call io->setup() and finish setting up scan parameters. // After this call returns, one must always call VP8ExitCritical() with the // same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK @@ -289,7 +291,7 @@ int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io); VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io); // Must always be called in pair with VP8EnterCritical(). // Returns false in case of error. -int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io); +WEBP_NODISCARD int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io); // Return the multi-threading method to use (0=off), depending // on options and bitstream size. Only for lossy decoding. int VP8GetThreadMethod(const WebPDecoderOptions* const options, @@ -299,11 +301,12 @@ int VP8GetThreadMethod(const WebPDecoderOptions* const options, void VP8InitDithering(const WebPDecoderOptions* const options, VP8Decoder* const dec); // Process the last decoded row (filtering + output). -int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io); +WEBP_NODISCARD int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io); // To be called at the start of a new scanline, to initialize predictors. void VP8InitScanline(VP8Decoder* const dec); // Decode one macroblock. Returns false if there is not enough data. -int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br); +WEBP_NODISCARD int VP8DecodeMB(VP8Decoder* const dec, + VP8BitReader* const token_br); // in alpha.c const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, diff --git a/libwebp_src/src/dec/vp8l_dec.c b/libwebp_src/src/dec/vp8l_dec.c index 7995313..11c00ea 100644 --- a/libwebp_src/src/dec/vp8l_dec.c +++ b/libwebp_src/src/dec/vp8l_dec.c @@ -12,6 +12,7 @@ // Authors: Vikas Arora (vikaas.arora@gmail.com) // Jyrki Alakuijala (jyrki@google.com) +#include #include #include "src/dec/alphai_dec.h" @@ -101,6 +102,14 @@ static const uint16_t kTableSize[12] = { FIXED_TABLE_SIZE + 2704 }; +static int VP8LSetError(VP8LDecoder* const dec, VP8StatusCode error) { + // The oldest error reported takes precedence over the new one. + if (dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED) { + dec->status_ = error; + } + return 0; +} + static int DecodeImageStream(int xsize, int ysize, int is_level0, VP8LDecoder* const dec, @@ -301,7 +310,7 @@ static int ReadHuffmanCodeLengths( End: VP8LHuffmanTablesDeallocate(&tables); - if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR; + if (!ok) return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); return ok; } @@ -333,10 +342,7 @@ static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec, int i; int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 }; const int num_codes = VP8LReadBits(br, 4) + 4; - if (num_codes > NUM_CODE_LENGTH_CODES) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - return 0; - } + assert(num_codes <= NUM_CODE_LENGTH_CODES); for (i = 0; i < num_codes; ++i) { code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3); @@ -351,15 +357,14 @@ static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec, code_lengths, alphabet_size); } if (!ok || size == 0) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - return 0; + return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); } return size; } static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, int color_cache_bits, int allow_recursion) { - int i, j; + int i; VP8LBitReader* const br = &dec->br_; VP8LMetadata* const hdr = &dec->hdr_; uint32_t* huffman_image = NULL; @@ -367,9 +372,6 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, HuffmanTables* huffman_tables = &hdr->huffman_tables_; int num_htree_groups = 1; int num_htree_groups_max = 1; - int max_alphabet_size = 0; - int* code_lengths = NULL; - const int table_size = kTableSize[color_cache_bits]; int* mapping = NULL; int ok = 0; @@ -383,7 +385,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision); const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision); const int huffman_pixs = huffman_xsize * huffman_ysize; - if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec, + if (!DecodeImageStream(huffman_xsize, huffman_ysize, /*is_level0=*/0, dec, &huffman_image)) { goto Error; } @@ -407,7 +409,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, // values [0, num_htree_groups) mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping)); if (mapping == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; + VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); goto Error; } // -1 means a value is unmapped, and therefore unused in the Huffman @@ -426,25 +428,52 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, if (br->eos_) goto Error; - // Find maximum alphabet size for the htree group. - for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { - int alphabet_size = kAlphabetSize[j]; - if (j == 0 && color_cache_bits > 0) { - alphabet_size += 1 << color_cache_bits; - } - if (max_alphabet_size < alphabet_size) { - max_alphabet_size = alphabet_size; - } + if (!ReadHuffmanCodesHelper(color_cache_bits, num_htree_groups, + num_htree_groups_max, mapping, dec, + huffman_tables, &htree_groups)) { + goto Error; } + ok = 1; - code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, - sizeof(*code_lengths)); - htree_groups = VP8LHtreeGroupsNew(num_htree_groups); + // All OK. Finalize pointers. + hdr->huffman_image_ = huffman_image; + hdr->num_htree_groups_ = num_htree_groups; + hdr->htree_groups_ = htree_groups; - if (htree_groups == NULL || code_lengths == NULL || + Error: + WebPSafeFree(mapping); + if (!ok) { + WebPSafeFree(huffman_image); + VP8LHuffmanTablesDeallocate(huffman_tables); + VP8LHtreeGroupsFree(htree_groups); + } + return ok; +} + +int ReadHuffmanCodesHelper(int color_cache_bits, int num_htree_groups, + int num_htree_groups_max, const int* const mapping, + VP8LDecoder* const dec, + HuffmanTables* const huffman_tables, + HTreeGroup** const htree_groups) { + int i, j, ok = 0; + const int max_alphabet_size = + kAlphabetSize[0] + ((color_cache_bits > 0) ? 1 << color_cache_bits : 0); + const int table_size = kTableSize[color_cache_bits]; + int* code_lengths = NULL; + + if ((mapping == NULL && num_htree_groups != num_htree_groups_max) || + num_htree_groups > num_htree_groups_max) { + goto Error; + } + + code_lengths = + (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths)); + *htree_groups = VP8LHtreeGroupsNew(num_htree_groups); + + if (*htree_groups == NULL || code_lengths == NULL || !VP8LHuffmanTablesAllocate(num_htree_groups * table_size, huffman_tables)) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; + VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); goto Error; } @@ -464,7 +493,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, } } else { HTreeGroup* const htree_group = - &htree_groups[(mapping == NULL) ? i : mapping[i]]; + &(*htree_groups)[(mapping == NULL) ? i : mapping[i]]; HuffmanCode** const htrees = htree_group->htrees; int size; int total_size = 0; @@ -516,18 +545,12 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, } ok = 1; - // All OK. Finalize pointers. - hdr->huffman_image_ = huffman_image; - hdr->num_htree_groups_ = num_htree_groups; - hdr->htree_groups_ = htree_groups; - Error: WebPSafeFree(code_lengths); - WebPSafeFree(mapping); if (!ok) { - WebPSafeFree(huffman_image); VP8LHuffmanTablesDeallocate(huffman_tables); - VP8LHtreeGroupsFree(htree_groups); + VP8LHtreeGroupsFree(*htree_groups); + *htree_groups = NULL; } return ok; } @@ -551,8 +574,7 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { scaled_data_size * sizeof(*scaled_data); uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory)); if (memory == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - return 0; + return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); } assert(dec->rescaler_memory == NULL); dec->rescaler_memory = memory; @@ -1086,12 +1108,10 @@ static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data, End: br->eos_ = VP8LIsEndOfStream(br); if (!ok || (br->eos_ && pos < end)) { - ok = 0; - dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED - : VP8_STATUS_BITSTREAM_ERROR; - } else { - dec->last_pixel_ = pos; + return VP8LSetError( + dec, br->eos_ ? VP8_STATUS_SUSPENDED : VP8_STATUS_BITSTREAM_ERROR); } + dec->last_pixel_ = pos; return ok; } @@ -1241,9 +1261,20 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, } br->eos_ = VP8LIsEndOfStream(br); - if (dec->incremental_ && br->eos_ && src < src_end) { + // In incremental decoding: + // br->eos_ && src < src_last: if 'br' reached the end of the buffer and + // 'src_last' has not been reached yet, there is not enough data. 'dec' has to + // be reset until there is more data. + // !br->eos_ && src < src_last: this cannot happen as either the buffer is + // fully read, either enough has been read to reach 'src_last'. + // src >= src_last: 'src_last' is reached, all is fine. 'src' can actually go + // beyond 'src_last' in case the image is cropped and an LZ77 goes further. + // The buffer might have been enough or there is some left. 'br->eos_' does + // not matter. + assert(!dec->incremental_ || (br->eos_ && src < src_last) || src >= src_last); + if (dec->incremental_ && br->eos_ && src < src_last) { RestoreState(dec); - } else if (!br->eos_) { + } else if ((dec->incremental_ && src >= src_last) || !br->eos_) { // Process the remaining rows corresponding to last row-block. if (process_func != NULL) { process_func(dec, row > last_row ? last_row : row); @@ -1258,8 +1289,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, return 1; Error: - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; - return 0; + return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); } // ----------------------------------------------------------------------------- @@ -1326,7 +1356,7 @@ static int ReadTransform(int* const xsize, int const* ysize, transform->bits_), VP8LSubSampleSize(transform->ysize_, transform->bits_), - 0, dec, &transform->data_); + /*is_level0=*/0, dec, &transform->data_); break; case COLOR_INDEXING_TRANSFORM: { const int num_colors = VP8LReadBits(br, 8) + 1; @@ -1336,8 +1366,11 @@ static int ReadTransform(int* const xsize, int const* ysize, : 3; *xsize = VP8LSubSampleSize(transform->xsize_, bits); transform->bits_ = bits; - ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_); - ok = ok && ExpandColorMap(num_colors, transform); + ok = DecodeImageStream(num_colors, /*ysize=*/1, /*is_level0=*/0, dec, + &transform->data_); + if (ok && !ExpandColorMap(num_colors, transform)) { + return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); + } break; } case SUBTRACT_GREEN_TRANSFORM: @@ -1443,7 +1476,7 @@ static int DecodeImageStream(int xsize, int ysize, color_cache_bits = VP8LReadBits(br, 4); ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS); if (!ok) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; + VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); goto End; } } @@ -1452,7 +1485,7 @@ static int DecodeImageStream(int xsize, int ysize, ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize, color_cache_bits, is_level0); if (!ok) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; + VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); goto End; } @@ -1460,8 +1493,7 @@ static int DecodeImageStream(int xsize, int ysize, if (color_cache_bits > 0) { hdr->color_cache_size_ = 1 << color_cache_bits; if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - ok = 0; + ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); goto End; } } else { @@ -1478,8 +1510,7 @@ static int DecodeImageStream(int xsize, int ysize, const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize; data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data)); if (data == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - ok = 0; + ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); goto End; } } @@ -1524,8 +1555,7 @@ static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) { dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t)); if (dec->pixels_ == NULL) { dec->argb_cache_ = NULL; // for soundness - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - return 0; + return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); } dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels; return 1; @@ -1536,8 +1566,7 @@ static int AllocateInternalBuffers8b(VP8LDecoder* const dec) { dec->argb_cache_ = NULL; // for soundness dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t)); if (dec->pixels_ == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - return 0; + return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); } return 1; } @@ -1592,7 +1621,8 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, dec->status_ = VP8_STATUS_OK; VP8LInitBitReader(&dec->br_, data, data_size); - if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) { + if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, /*is_level0=*/1, + dec, /*decoded_data=*/NULL)) { goto Err; } @@ -1647,22 +1677,24 @@ int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) { if (dec == NULL) return 0; if (io == NULL) { - dec->status_ = VP8_STATUS_INVALID_PARAM; - return 0; + return VP8LSetError(dec, VP8_STATUS_INVALID_PARAM); } dec->io_ = io; dec->status_ = VP8_STATUS_OK; VP8LInitBitReader(&dec->br_, io->data, io->data_size); if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) { - dec->status_ = VP8_STATUS_BITSTREAM_ERROR; + VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR); goto Error; } dec->state_ = READ_DIM; io->width = width; io->height = height; - if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error; + if (!DecodeImageStream(width, height, /*is_level0=*/1, dec, + /*decoded_data=*/NULL)) { + goto Error; + } return 1; Error: @@ -1692,7 +1724,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) { assert(dec->output_ != NULL); if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) { - dec->status_ = VP8_STATUS_INVALID_PARAM; + VP8LSetError(dec, VP8_STATUS_INVALID_PARAM); goto Err; } @@ -1702,7 +1734,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) { if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; #else if (io->use_scaling) { - dec->status_ = VP8_STATUS_INVALID_PARAM; + VP8LSetError(dec, VP8_STATUS_INVALID_PARAM); goto Err; } #endif @@ -1720,7 +1752,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) { dec->hdr_.saved_color_cache_.colors_ == NULL) { if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_, dec->hdr_.color_cache_.hash_bits_)) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; + VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY); goto Err; } } diff --git a/libwebp_src/src/dec/vp8li_dec.h b/libwebp_src/src/dec/vp8li_dec.h index 32540a4..9a13bcc 100644 --- a/libwebp_src/src/dec/vp8li_dec.h +++ b/libwebp_src/src/dec/vp8li_dec.h @@ -20,6 +20,7 @@ #include "src/utils/bit_reader_utils.h" #include "src/utils/color_cache_utils.h" #include "src/utils/huffman_utils.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -99,25 +100,26 @@ struct ALPHDecoder; // Defined in dec/alphai.h. // Decodes image header for alpha data stored using lossless compression. // Returns false in case of error. -int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec, - const uint8_t* const data, size_t data_size); +WEBP_NODISCARD int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec, + const uint8_t* const data, + size_t data_size); // Decodes *at least* 'last_row' rows of alpha. If some of the initial rows are // already decoded in previous call(s), it will resume decoding from where it // was paused. // Returns false in case of bitstream error. -int VP8LDecodeAlphaImageStream(struct ALPHDecoder* const alph_dec, - int last_row); +WEBP_NODISCARD int VP8LDecodeAlphaImageStream( + struct ALPHDecoder* const alph_dec, int last_row); // Allocates and initialize a new lossless decoder instance. -VP8LDecoder* VP8LNew(void); +WEBP_NODISCARD VP8LDecoder* VP8LNew(void); // Decodes the image header. Returns false in case of error. -int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io); +WEBP_NODISCARD int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io); // Decodes an image. It's required to decode the lossless header before calling // this function. Returns false in case of error, with updated dec->status_. -int VP8LDecodeImage(VP8LDecoder* const dec); +WEBP_NODISCARD int VP8LDecodeImage(VP8LDecoder* const dec); // Resets the decoder in its initial state, reclaiming memory. // Preserves the dec->status_ value. @@ -126,6 +128,18 @@ void VP8LClear(VP8LDecoder* const dec); // Clears and deallocate a lossless decoder instance. void VP8LDelete(VP8LDecoder* const dec); +// Helper function for reading the different Huffman codes and storing them in +// 'huffman_tables' and 'htree_groups'. +// If mapping is NULL 'num_htree_groups_max' must equal 'num_htree_groups'. +// If it is not NULL, it maps 'num_htree_groups_max' indices to the +// 'num_htree_groups' groups. If 'num_htree_groups_max' > 'num_htree_groups', +// some of those indices map to -1. This is used for non-balanced codes to +// limit memory usage. +WEBP_NODISCARD int ReadHuffmanCodesHelper( + int color_cache_bits, int num_htree_groups, int num_htree_groups_max, + const int* const mapping, VP8LDecoder* const dec, + HuffmanTables* const huffman_tables, HTreeGroup** const htree_groups); + //------------------------------------------------------------------------------ #ifdef __cplusplus diff --git a/libwebp_src/src/dec/webp_dec.c b/libwebp_src/src/dec/webp_dec.c index f557868..49ef205 100644 --- a/libwebp_src/src/dec/webp_dec.c +++ b/libwebp_src/src/dec/webp_dec.c @@ -13,11 +13,14 @@ #include +#include "src/dec/vp8_dec.h" #include "src/dec/vp8i_dec.h" #include "src/dec/vp8li_dec.h" #include "src/dec/webpi_dec.h" #include "src/utils/utils.h" #include "src/webp/mux_types.h" // ALPHA_FLAG +#include "src/webp/decode.h" +#include "src/webp/types.h" //------------------------------------------------------------------------------ // RIFF layout is: @@ -444,8 +447,9 @@ void WebPResetDecParams(WebPDecParams* const params) { // "Into" decoding variants // Main flow -static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size, - WebPDecParams* const params) { +WEBP_NODISCARD static VP8StatusCode DecodeInto(const uint8_t* const data, + size_t data_size, + WebPDecParams* const params) { VP8StatusCode status; VP8Io io; WebPHeaderStructure headers; @@ -459,7 +463,9 @@ static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size, } assert(params != NULL); - VP8InitIo(&io); + if (!VP8InitIo(&io)) { + return VP8_STATUS_INVALID_PARAM; + } io.data = headers.data + headers.offset; io.data_size = headers.data_size - headers.offset; WebPInitCustomIo(params, &io); // Plug the I/O functions. @@ -523,17 +529,16 @@ static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size, } // Helpers -static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, - const uint8_t* const data, - size_t data_size, - uint8_t* const rgba, - int stride, size_t size) { +WEBP_NODISCARD static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, + const uint8_t* const data, + size_t data_size, + uint8_t* const rgba, + int stride, size_t size) { WebPDecParams params; WebPDecBuffer buf; - if (rgba == NULL) { + if (rgba == NULL || !WebPInitDecBuffer(&buf)) { return NULL; } - WebPInitDecBuffer(&buf); WebPResetDecParams(¶ms); params.output = &buf; buf.colorspace = colorspace; @@ -578,8 +583,7 @@ uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size, uint8_t* v, size_t v_size, int v_stride) { WebPDecParams params; WebPDecBuffer output; - if (luma == NULL) return NULL; - WebPInitDecBuffer(&output); + if (luma == NULL || !WebPInitDecBuffer(&output)) return NULL; WebPResetDecParams(¶ms); params.output = &output; output.colorspace = MODE_YUV; @@ -601,13 +605,17 @@ uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size, //------------------------------------------------------------------------------ -static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data, - size_t data_size, int* const width, int* const height, - WebPDecBuffer* const keep_info) { +WEBP_NODISCARD static uint8_t* Decode(WEBP_CSP_MODE mode, + const uint8_t* const data, + size_t data_size, int* const width, + int* const height, + WebPDecBuffer* const keep_info) { WebPDecParams params; WebPDecBuffer output; - WebPInitDecBuffer(&output); + if (!WebPInitDecBuffer(&output)) { + return NULL; + } WebPResetDecParams(¶ms); params.output = &output; output.colorspace = mode; @@ -733,7 +741,9 @@ int WebPInitDecoderConfigInternal(WebPDecoderConfig* config, } memset(config, 0, sizeof(*config)); DefaultFeatures(&config->input); - WebPInitDecBuffer(&config->output); + if (!WebPInitDecBuffer(&config->output)) { + return 0; + } return 1; } @@ -772,7 +782,9 @@ VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, if (WebPAvoidSlowMemory(params.output, &config->input)) { // decoding to slow memory: use a temporary in-mem buffer to decode into. WebPDecBuffer in_mem_buffer; - WebPInitDecBuffer(&in_mem_buffer); + if (!WebPInitDecBuffer(&in_mem_buffer)) { + return VP8_STATUS_INVALID_PARAM; + } in_mem_buffer.colorspace = config->output.colorspace; in_mem_buffer.width = config->input.width; in_mem_buffer.height = config->input.height; diff --git a/libwebp_src/src/dec/webpi_dec.h b/libwebp_src/src/dec/webpi_dec.h index 3b97388..77bf526 100644 --- a/libwebp_src/src/dec/webpi_dec.h +++ b/libwebp_src/src/dec/webpi_dec.h @@ -20,6 +20,7 @@ extern "C" { #include "src/utils/rescaler_utils.h" #include "src/dec/vp8_dec.h" +#include "src/webp/decode.h" //------------------------------------------------------------------------------ // WebPDecParams: Decoding output parameters. Transient internal object. @@ -87,8 +88,9 @@ void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io); // Setup crop_xxx fields, mb_w and mb_h in io. 'src_colorspace' refers // to the *compressed* format, not the output one. -int WebPIoInitFromOptions(const WebPDecoderOptions* const options, - VP8Io* const io, WEBP_CSP_MODE src_colorspace); +WEBP_NODISCARD int WebPIoInitFromOptions( + const WebPDecoderOptions* const options, VP8Io* const io, + WEBP_CSP_MODE src_colorspace); //------------------------------------------------------------------------------ // Internal functions regarding WebPDecBuffer memory (in buffer.c). diff --git a/libwebp_src/src/demux/Makefile.am b/libwebp_src/src/demux/Makefile.am index 2df2db5..9ecff14 100644 --- a/libwebp_src/src/demux/Makefile.am +++ b/libwebp_src/src/demux/Makefile.am @@ -13,6 +13,6 @@ noinst_HEADERS = noinst_HEADERS += ../webp/format_constants.h libwebpdemux_la_LIBADD = ../libwebp.la -libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:14:0 +libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:15:0 libwebpdemuxincludedir = $(includedir)/webp pkgconfig_DATA = libwebpdemux.pc diff --git a/libwebp_src/src/demux/anim_decode.c b/libwebp_src/src/demux/anim_decode.c index e077ffb..27f0e2b 100644 --- a/libwebp_src/src/demux/anim_decode.c +++ b/libwebp_src/src/demux/anim_decode.c @@ -20,6 +20,7 @@ #include "src/utils/utils.h" #include "src/webp/decode.h" #include "src/webp/demux.h" +#include "src/webp/types.h" #define NUM_CHANNELS 4 @@ -68,8 +69,9 @@ int WebPAnimDecoderOptionsInitInternal(WebPAnimDecoderOptions* dec_options, return 1; } -static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options, - WebPAnimDecoder* const dec) { +WEBP_NODISCARD static int ApplyDecoderOptions( + const WebPAnimDecoderOptions* const dec_options, + WebPAnimDecoder* const dec) { WEBP_CSP_MODE mode; WebPDecoderConfig* config = &dec->config_; assert(dec_options != NULL); @@ -82,7 +84,9 @@ static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options, dec->blend_func_ = (mode == MODE_RGBA || mode == MODE_BGRA) ? &BlendPixelRowNonPremult : &BlendPixelRowPremult; - WebPInitDecoderConfig(config); + if (!WebPInitDecoderConfig(config)) { + return 0; + } config->output.colorspace = mode; config->output.is_external_memory = 1; config->options.use_threads = dec_options->use_threads; @@ -157,8 +161,8 @@ static int IsFullFrame(int width, int height, int canvas_width, } // Clear the canvas to transparent. -static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, - uint32_t canvas_height) { +WEBP_NODISCARD static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, + uint32_t canvas_height) { const uint64_t size = (uint64_t)canvas_width * canvas_height * NUM_CHANNELS * sizeof(*buf); if (!CheckSizeOverflow(size)) return 0; @@ -179,8 +183,8 @@ static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset, } // Copy width * height pixels from 'src' to 'dst'. -static int CopyCanvas(const uint8_t* src, uint8_t* dst, - uint32_t width, uint32_t height) { +WEBP_NODISCARD static int CopyCanvas(const uint8_t* src, uint8_t* dst, + uint32_t width, uint32_t height) { const uint64_t size = (uint64_t)width * height * NUM_CHANNELS; if (!CheckSizeOverflow(size)) return 0; assert(src != NULL && dst != NULL); @@ -424,7 +428,9 @@ int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, WebPDemuxReleaseIterator(&dec->prev_iter_); dec->prev_iter_ = iter; dec->prev_frame_was_keyframe_ = is_key_frame; - CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height); + if (!CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height)) { + goto Error; + } if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS, dec->prev_iter_.x_offset, dec->prev_iter_.y_offset, diff --git a/libwebp_src/src/demux/demux.c b/libwebp_src/src/demux/demux.c index 4b0d3f5..d01c6a7 100644 --- a/libwebp_src/src/demux/demux.c +++ b/libwebp_src/src/demux/demux.c @@ -24,8 +24,8 @@ #include "src/webp/format_constants.h" #define DMUX_MAJ_VERSION 1 -#define DMUX_MIN_VERSION 3 -#define DMUX_REV_VERSION 2 +#define DMUX_MIN_VERSION 4 +#define DMUX_REV_VERSION 0 typedef struct { size_t start_; // start location of the data diff --git a/libwebp_src/src/demux/libwebpdemux.rc b/libwebp_src/src/demux/libwebpdemux.rc index b0c9413..bc57c40 100644 --- a/libwebp_src/src/demux/libwebpdemux.rc +++ b/libwebp_src/src/demux/libwebpdemux.rc @@ -6,8 +6,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,3,2 - PRODUCTVERSION 1,0,3,2 + FILEVERSION 1,0,4,0 + PRODUCTVERSION 1,0,4,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -24,12 +24,12 @@ BEGIN BEGIN VALUE "CompanyName", "Google, Inc." VALUE "FileDescription", "libwebpdemux DLL" - VALUE "FileVersion", "1.3.2" + VALUE "FileVersion", "1.4.0" VALUE "InternalName", "libwebpdemux.dll" - VALUE "LegalCopyright", "Copyright (C) 2023" + VALUE "LegalCopyright", "Copyright (C) 2024" VALUE "OriginalFilename", "libwebpdemux.dll" VALUE "ProductName", "WebP Image Demuxer" - VALUE "ProductVersion", "1.3.2" + VALUE "ProductVersion", "1.4.0" END END BLOCK "VarFileInfo" diff --git a/libwebp_src/src/dsp/alpha_processing_sse2.c b/libwebp_src/src/dsp/alpha_processing_sse2.c index f0843d0..aa0cc28 100644 --- a/libwebp_src/src/dsp/alpha_processing_sse2.c +++ b/libwebp_src/src/dsp/alpha_processing_sse2.c @@ -144,6 +144,46 @@ static int ExtractAlpha_SSE2(const uint8_t* WEBP_RESTRICT argb, int argb_stride, return (alpha_and == 0xff); } +static void ExtractGreen_SSE2(const uint32_t* WEBP_RESTRICT argb, + uint8_t* WEBP_RESTRICT alpha, int size) { + int i; + const __m128i mask = _mm_set1_epi32(0xff); + const __m128i* src = (const __m128i*)argb; + + for (i = 0; i + 16 <= size; i += 16, src += 4) { + const __m128i a0 = _mm_loadu_si128(src + 0); + const __m128i a1 = _mm_loadu_si128(src + 1); + const __m128i a2 = _mm_loadu_si128(src + 2); + const __m128i a3 = _mm_loadu_si128(src + 3); + const __m128i b0 = _mm_srli_epi32(a0, 8); + const __m128i b1 = _mm_srli_epi32(a1, 8); + const __m128i b2 = _mm_srli_epi32(a2, 8); + const __m128i b3 = _mm_srli_epi32(a3, 8); + const __m128i c0 = _mm_and_si128(b0, mask); + const __m128i c1 = _mm_and_si128(b1, mask); + const __m128i c2 = _mm_and_si128(b2, mask); + const __m128i c3 = _mm_and_si128(b3, mask); + const __m128i d0 = _mm_packs_epi32(c0, c1); + const __m128i d1 = _mm_packs_epi32(c2, c3); + const __m128i e = _mm_packus_epi16(d0, d1); + // store + _mm_storeu_si128((__m128i*)&alpha[i], e); + } + if (i + 8 <= size) { + const __m128i a0 = _mm_loadu_si128(src + 0); + const __m128i a1 = _mm_loadu_si128(src + 1); + const __m128i b0 = _mm_srli_epi32(a0, 8); + const __m128i b1 = _mm_srli_epi32(a1, 8); + const __m128i c0 = _mm_and_si128(b0, mask); + const __m128i c1 = _mm_and_si128(b1, mask); + const __m128i d = _mm_packs_epi32(c0, c1); + const __m128i e = _mm_packus_epi16(d, d); + _mm_storel_epi64((__m128i*)&alpha[i], e); + i += 8; + } + for (; i < size; ++i) alpha[i] = argb[i] >> 8; +} + //------------------------------------------------------------------------------ // Non-dither premultiplied modes @@ -354,6 +394,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE2(void) { WebPDispatchAlpha = DispatchAlpha_SSE2; WebPDispatchAlphaToGreen = DispatchAlphaToGreen_SSE2; WebPExtractAlpha = ExtractAlpha_SSE2; + WebPExtractGreen = ExtractGreen_SSE2; WebPHasAlpha8b = HasAlpha8b_SSE2; WebPHasAlpha32b = HasAlpha32b_SSE2; diff --git a/libwebp_src/src/dsp/cpu.c b/libwebp_src/src/dsp/cpu.c index 2234c77..8ba8f68 100644 --- a/libwebp_src/src/dsp/cpu.c +++ b/libwebp_src/src/dsp/cpu.c @@ -36,18 +36,6 @@ static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) : "a"(info_type), "c"(0)); } -#elif defined(__x86_64__) && \ - (defined(__code_model_medium__) || defined(__code_model_large__)) && \ - defined(__PIC__) -static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { - __asm__ volatile ( - "xchg{q}\t{%%rbx}, %q1\n" - "cpuid\n" - "xchg{q}\t{%%rbx}, %q1\n" - : "=a"(cpu_info[0]), "=&r"(cpu_info[1]), "=c"(cpu_info[2]), - "=d"(cpu_info[3]) - : "a"(info_type), "c"(0)); -} #elif defined(__i386__) || defined(__x86_64__) static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { __asm__ volatile ( diff --git a/libwebp_src/src/dsp/dec.c b/libwebp_src/src/dsp/dec.c index 33d8df8..451d649 100644 --- a/libwebp_src/src/dsp/dec.c +++ b/libwebp_src/src/dsp/dec.c @@ -37,9 +37,6 @@ static WEBP_INLINE uint8_t clip_8b(int v) { STORE(3, y, DC - (d)); \ } while (0) -#define MUL1(a) ((((a) * 20091) >> 16) + (a)) -#define MUL2(a) (((a) * 35468) >> 16) - #if !WEBP_NEON_OMIT_C_CODE static void TransformOne_C(const int16_t* in, uint8_t* dst) { int C[4 * 4], *tmp; @@ -48,8 +45,10 @@ static void TransformOne_C(const int16_t* in, uint8_t* dst) { for (i = 0; i < 4; ++i) { // vertical pass const int a = in[0] + in[8]; // [-4096, 4094] const int b = in[0] - in[8]; // [-4095, 4095] - const int c = MUL2(in[4]) - MUL1(in[12]); // [-3783, 3783] - const int d = MUL1(in[4]) + MUL2(in[12]); // [-3785, 3781] + const int c = WEBP_TRANSFORM_AC3_MUL2(in[4]) - + WEBP_TRANSFORM_AC3_MUL1(in[12]); // [-3783, 3783] + const int d = WEBP_TRANSFORM_AC3_MUL1(in[4]) + + WEBP_TRANSFORM_AC3_MUL2(in[12]); // [-3785, 3781] tmp[0] = a + d; // [-7881, 7875] tmp[1] = b + c; // [-7878, 7878] tmp[2] = b - c; // [-7878, 7878] @@ -69,8 +68,10 @@ static void TransformOne_C(const int16_t* in, uint8_t* dst) { const int dc = tmp[0] + 4; const int a = dc + tmp[8]; const int b = dc - tmp[8]; - const int c = MUL2(tmp[4]) - MUL1(tmp[12]); - const int d = MUL1(tmp[4]) + MUL2(tmp[12]); + const int c = + WEBP_TRANSFORM_AC3_MUL2(tmp[4]) - WEBP_TRANSFORM_AC3_MUL1(tmp[12]); + const int d = + WEBP_TRANSFORM_AC3_MUL1(tmp[4]) + WEBP_TRANSFORM_AC3_MUL2(tmp[12]); STORE(0, 0, a + d); STORE(1, 0, b + c); STORE(2, 0, b - c); @@ -83,17 +84,15 @@ static void TransformOne_C(const int16_t* in, uint8_t* dst) { // Simplified transform when only in[0], in[1] and in[4] are non-zero static void TransformAC3_C(const int16_t* in, uint8_t* dst) { const int a = in[0] + 4; - const int c4 = MUL2(in[4]); - const int d4 = MUL1(in[4]); - const int c1 = MUL2(in[1]); - const int d1 = MUL1(in[1]); + const int c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]); + const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]); + const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]); STORE2(0, a + d4, d1, c1); STORE2(1, a + c4, d1, c1); STORE2(2, a - c4, d1, c1); STORE2(3, a - d4, d1, c1); } -#undef MUL1 -#undef MUL2 #undef STORE2 static void TransformTwo_C(const int16_t* in, uint8_t* dst, int do_two) { diff --git a/libwebp_src/src/dsp/dec_mips32.c b/libwebp_src/src/dsp/dec_mips32.c index e4e7096..f0e7de4 100644 --- a/libwebp_src/src/dsp/dec_mips32.c +++ b/libwebp_src/src/dsp/dec_mips32.c @@ -18,8 +18,8 @@ #include "src/dsp/mips_macro.h" -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; +static const int kC1 = WEBP_TRANSFORM_AC3_C1; +static const int kC2 = WEBP_TRANSFORM_AC3_C2; static WEBP_INLINE int abs_mips32(int x) { const int sign = x >> 31; @@ -219,7 +219,7 @@ static void TransformOne(const int16_t* in, uint8_t* dst) { int temp0, temp1, temp2, temp3, temp4; int temp5, temp6, temp7, temp8, temp9; int temp10, temp11, temp12, temp13, temp14; - int temp15, temp16, temp17, temp18; + int temp15, temp16, temp17, temp18, temp19; int16_t* p_in = (int16_t*)in; // loops unrolled and merged to avoid usage of tmp buffer @@ -233,16 +233,14 @@ static void TransformOne(const int16_t* in, uint8_t* dst) { "addu %[temp16], %[temp0], %[temp8] \n\t" "subu %[temp0], %[temp0], %[temp8] \n\t" "mul %[temp8], %[temp4], %[kC2] \n\t" - "mul %[temp17], %[temp12], %[kC1] \n\t" - "mul %[temp4], %[temp4], %[kC1] \n\t" + MUL_SHIFT_C1(temp17, temp12) + MUL_SHIFT_C1_IO(temp4, temp19) "mul %[temp12], %[temp12], %[kC2] \n\t" "lh %[temp1], 2(%[in]) \n\t" "lh %[temp5], 10(%[in]) \n\t" "lh %[temp9], 18(%[in]) \n\t" "lh %[temp13], 26(%[in]) \n\t" "sra %[temp8], %[temp8], 16 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "sra %[temp4], %[temp4], 16 \n\t" "sra %[temp12], %[temp12], 16 \n\t" "lh %[temp2], 4(%[in]) \n\t" "lh %[temp6], 12(%[in]) \n\t" @@ -261,49 +259,43 @@ static void TransformOne(const int16_t* in, uint8_t* dst) { "addu %[temp12], %[temp0], %[temp17] \n\t" "subu %[temp0], %[temp0], %[temp17] \n\t" "mul %[temp9], %[temp5], %[kC2] \n\t" - "mul %[temp17], %[temp13], %[kC1] \n\t" - "mul %[temp5], %[temp5], %[kC1] \n\t" + MUL_SHIFT_C1(temp17, temp13) + MUL_SHIFT_C1_IO(temp5, temp19) "mul %[temp13], %[temp13], %[kC2] \n\t" "sra %[temp9], %[temp9], 16 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" "subu %[temp17], %[temp9], %[temp17] \n\t" - "sra %[temp5], %[temp5], 16 \n\t" "sra %[temp13], %[temp13], 16 \n\t" "addu %[temp5], %[temp5], %[temp13] \n\t" "addu %[temp13], %[temp1], %[temp17] \n\t" "subu %[temp1], %[temp1], %[temp17] \n\t" - "mul %[temp17], %[temp14], %[kC1] \n\t" + MUL_SHIFT_C1(temp17, temp14) "mul %[temp14], %[temp14], %[kC2] \n\t" "addu %[temp9], %[temp16], %[temp5] \n\t" "subu %[temp5], %[temp16], %[temp5] \n\t" "addu %[temp16], %[temp2], %[temp10] \n\t" "subu %[temp2], %[temp2], %[temp10] \n\t" "mul %[temp10], %[temp6], %[kC2] \n\t" - "mul %[temp6], %[temp6], %[kC1] \n\t" - "sra %[temp17], %[temp17], 16 \n\t" + MUL_SHIFT_C1_IO(temp6, temp19) "sra %[temp14], %[temp14], 16 \n\t" "sra %[temp10], %[temp10], 16 \n\t" - "sra %[temp6], %[temp6], 16 \n\t" "subu %[temp17], %[temp10], %[temp17] \n\t" "addu %[temp6], %[temp6], %[temp14] \n\t" "addu %[temp10], %[temp16], %[temp6] \n\t" "subu %[temp6], %[temp16], %[temp6] \n\t" "addu %[temp14], %[temp2], %[temp17] \n\t" "subu %[temp2], %[temp2], %[temp17] \n\t" - "mul %[temp17], %[temp15], %[kC1] \n\t" + MUL_SHIFT_C1(temp17, temp15) "mul %[temp15], %[temp15], %[kC2] \n\t" "addu %[temp16], %[temp3], %[temp11] \n\t" "subu %[temp3], %[temp3], %[temp11] \n\t" "mul %[temp11], %[temp7], %[kC2] \n\t" - "mul %[temp7], %[temp7], %[kC1] \n\t" + MUL_SHIFT_C1_IO(temp7, temp19) "addiu %[temp8], %[temp8], 4 \n\t" "addiu %[temp12], %[temp12], 4 \n\t" "addiu %[temp0], %[temp0], 4 \n\t" "addiu %[temp4], %[temp4], 4 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" "sra %[temp15], %[temp15], 16 \n\t" "sra %[temp11], %[temp11], 16 \n\t" - "sra %[temp7], %[temp7], 16 \n\t" "subu %[temp17], %[temp11], %[temp17] \n\t" "addu %[temp7], %[temp7], %[temp15] \n\t" "addu %[temp15], %[temp3], %[temp17] \n\t" @@ -313,48 +305,40 @@ static void TransformOne(const int16_t* in, uint8_t* dst) { "addu %[temp16], %[temp8], %[temp10] \n\t" "subu %[temp8], %[temp8], %[temp10] \n\t" "mul %[temp10], %[temp9], %[kC2] \n\t" - "mul %[temp17], %[temp11], %[kC1] \n\t" - "mul %[temp9], %[temp9], %[kC1] \n\t" + MUL_SHIFT_C1(temp17, temp11) + MUL_SHIFT_C1_IO(temp9, temp19) "mul %[temp11], %[temp11], %[kC2] \n\t" "sra %[temp10], %[temp10], 16 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "sra %[temp9], %[temp9], 16 \n\t" "sra %[temp11], %[temp11], 16 \n\t" "subu %[temp17], %[temp10], %[temp17] \n\t" "addu %[temp11], %[temp9], %[temp11] \n\t" "addu %[temp10], %[temp12], %[temp14] \n\t" "subu %[temp12], %[temp12], %[temp14] \n\t" "mul %[temp14], %[temp13], %[kC2] \n\t" - "mul %[temp9], %[temp15], %[kC1] \n\t" - "mul %[temp13], %[temp13], %[kC1] \n\t" + MUL_SHIFT_C1(temp9, temp15) + MUL_SHIFT_C1_IO(temp13, temp19) "mul %[temp15], %[temp15], %[kC2] \n\t" "sra %[temp14], %[temp14], 16 \n\t" - "sra %[temp9], %[temp9], 16 \n\t" - "sra %[temp13], %[temp13], 16 \n\t" "sra %[temp15], %[temp15], 16 \n\t" "subu %[temp9], %[temp14], %[temp9] \n\t" "addu %[temp15], %[temp13], %[temp15] \n\t" "addu %[temp14], %[temp0], %[temp2] \n\t" "subu %[temp0], %[temp0], %[temp2] \n\t" "mul %[temp2], %[temp1], %[kC2] \n\t" - "mul %[temp13], %[temp3], %[kC1] \n\t" - "mul %[temp1], %[temp1], %[kC1] \n\t" + MUL_SHIFT_C1(temp13, temp3) + MUL_SHIFT_C1_IO(temp1, temp19) "mul %[temp3], %[temp3], %[kC2] \n\t" "sra %[temp2], %[temp2], 16 \n\t" - "sra %[temp13], %[temp13], 16 \n\t" - "sra %[temp1], %[temp1], 16 \n\t" "sra %[temp3], %[temp3], 16 \n\t" "subu %[temp13], %[temp2], %[temp13] \n\t" "addu %[temp3], %[temp1], %[temp3] \n\t" "addu %[temp2], %[temp4], %[temp6] \n\t" "subu %[temp4], %[temp4], %[temp6] \n\t" "mul %[temp6], %[temp5], %[kC2] \n\t" - "mul %[temp1], %[temp7], %[kC1] \n\t" - "mul %[temp5], %[temp5], %[kC1] \n\t" + MUL_SHIFT_C1(temp1, temp7) + MUL_SHIFT_C1_IO(temp5, temp19) "mul %[temp7], %[temp7], %[kC2] \n\t" "sra %[temp6], %[temp6], 16 \n\t" - "sra %[temp1], %[temp1], 16 \n\t" - "sra %[temp5], %[temp5], 16 \n\t" "sra %[temp7], %[temp7], 16 \n\t" "subu %[temp1], %[temp6], %[temp1] \n\t" "addu %[temp7], %[temp5], %[temp7] \n\t" @@ -542,7 +526,7 @@ static void TransformOne(const int16_t* in, uint8_t* dst) { [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), - [temp18]"=&r"(temp18) + [temp18]"=&r"(temp18), [temp19]"=&r"(temp19) : [in]"r"(p_in), [kC1]"r"(kC1), [kC2]"r"(kC2), [dst]"r"(dst) : "memory", "hi", "lo" ); diff --git a/libwebp_src/src/dsp/dec_mips_dsp_r2.c b/libwebp_src/src/dsp/dec_mips_dsp_r2.c index b0936bc..0ba706a 100644 --- a/libwebp_src/src/dsp/dec_mips_dsp_r2.c +++ b/libwebp_src/src/dsp/dec_mips_dsp_r2.c @@ -18,10 +18,8 @@ #include "src/dsp/mips_macro.h" -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; - -#define MUL(a, b) (((a) * (b)) >> 16) +static const int kC1 = WEBP_TRANSFORM_AC3_C1; +static const int kC2 = WEBP_TRANSFORM_AC3_C2; static void TransformDC(const int16_t* in, uint8_t* dst) { int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10; @@ -49,10 +47,10 @@ static void TransformDC(const int16_t* in, uint8_t* dst) { static void TransformAC3(const int16_t* in, uint8_t* dst) { const int a = in[0] + 4; - int c4 = MUL(in[4], kC2); - const int d4 = MUL(in[4], kC1); - const int c1 = MUL(in[1], kC2); - const int d1 = MUL(in[1], kC1); + int c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]); + const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]); + const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]); int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; @@ -479,8 +477,6 @@ static void HFilter8i(uint8_t* u, uint8_t* v, int stride, FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); } -#undef MUL - //------------------------------------------------------------------------------ // Simple In-loop filtering (Paragraph 15.2) diff --git a/libwebp_src/src/dsp/dec_msa.c b/libwebp_src/src/dsp/dec_msa.c index 8090622..58d1730 100644 --- a/libwebp_src/src/dsp/dec_msa.c +++ b/libwebp_src/src/dsp/dec_msa.c @@ -37,8 +37,6 @@ d1_m = d_tmp1_m + d_tmp2_m; \ BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \ } -#define MULT1(a) ((((a) * 20091) >> 16) + (a)) -#define MULT2(a) (((a) * 35468) >> 16) static void TransformOne(const int16_t* in, uint8_t* dst) { v8i16 input0, input1; @@ -124,10 +122,10 @@ static void TransformDC(const int16_t* in, uint8_t* dst) { static void TransformAC3(const int16_t* in, uint8_t* dst) { const int a = in[0] + 4; - const int c4 = MULT2(in[4]); - const int d4 = MULT1(in[4]); - const int in2 = MULT2(in[1]); - const int in3 = MULT1(in[1]); + const int c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]); + const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]); + const int in2 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int in3 = WEBP_TRANSFORM_AC3_MUL1(in[1]); v4i32 tmp0 = { 0 }; v4i32 out0 = __msa_fill_w(a + d4); v4i32 out1 = __msa_fill_w(a + c4); diff --git a/libwebp_src/src/dsp/dec_neon.c b/libwebp_src/src/dsp/dec_neon.c index 22784cf..83b3a1f 100644 --- a/libwebp_src/src/dsp/dec_neon.c +++ b/libwebp_src/src/dsp/dec_neon.c @@ -1000,8 +1000,9 @@ static void HFilter8i_NEON(uint8_t* u, uint8_t* v, int stride, // libwebp adds 1 << 16 to cospi8sqrt2minus1 (kC1). However, this causes the // same issue with kC1 and vqdmulh that we work around by down shifting kC2 -static const int16_t kC1 = 20091; -static const int16_t kC2 = 17734; // half of kC2, actually. See comment above. +static const int16_t kC1 = WEBP_TRANSFORM_AC3_C1; +static const int16_t kC2 = + WEBP_TRANSFORM_AC3_C2 / 2; // half of kC2, actually. See comment above. #if defined(WEBP_USE_INTRINSICS) static WEBP_INLINE void Transpose8x2_NEON(const int16x8_t in0, @@ -1255,15 +1256,12 @@ static void TransformWHT_NEON(const int16_t* in, int16_t* out) { //------------------------------------------------------------------------------ -#define MUL(a, b) (((a) * (b)) >> 16) static void TransformAC3_NEON(const int16_t* in, uint8_t* dst) { - static const int kC1_full = 20091 + (1 << 16); - static const int kC2_full = 35468; const int16x4_t A = vld1_dup_s16(in); - const int16x4_t c4 = vdup_n_s16(MUL(in[4], kC2_full)); - const int16x4_t d4 = vdup_n_s16(MUL(in[4], kC1_full)); - const int c1 = MUL(in[1], kC2_full); - const int d1 = MUL(in[1], kC1_full); + const int16x4_t c4 = vdup_n_s16(WEBP_TRANSFORM_AC3_MUL2(in[4])); + const int16x4_t d4 = vdup_n_s16(WEBP_TRANSFORM_AC3_MUL1(in[4])); + const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]); const uint64_t cd = (uint64_t)( d1 & 0xffff) << 0 | (uint64_t)( c1 & 0xffff) << 16 | (uint64_t)(-c1 & 0xffff) << 32 | @@ -1274,7 +1272,6 @@ static void TransformAC3_NEON(const int16_t* in, uint8_t* dst) { const int16x8_t m2_m3 = vcombine_s16(vqsub_s16(B, c4), vqsub_s16(B, d4)); Add4x4_NEON(m0_m1, m2_m3, dst); } -#undef MUL //------------------------------------------------------------------------------ // 4x4 diff --git a/libwebp_src/src/dsp/dec_sse2.c b/libwebp_src/src/dsp/dec_sse2.c index 01e6bcb..ff3a285 100644 --- a/libwebp_src/src/dsp/dec_sse2.c +++ b/libwebp_src/src/dsp/dec_sse2.c @@ -196,15 +196,13 @@ static void Transform_SSE2(const int16_t* in, uint8_t* dst, int do_two) { } #if (USE_TRANSFORM_AC3 == 1) -#define MUL(a, b) (((a) * (b)) >> 16) + static void TransformAC3(const int16_t* in, uint8_t* dst) { - static const int kC1 = 20091 + (1 << 16); - static const int kC2 = 35468; const __m128i A = _mm_set1_epi16(in[0] + 4); - const __m128i c4 = _mm_set1_epi16(MUL(in[4], kC2)); - const __m128i d4 = _mm_set1_epi16(MUL(in[4], kC1)); - const int c1 = MUL(in[1], kC2); - const int d1 = MUL(in[1], kC1); + const __m128i c4 = _mm_set1_epi16(WEBP_TRANSFORM_AC3_MUL2(in[4])); + const __m128i d4 = _mm_set1_epi16(WEBP_TRANSFORM_AC3_MUL1(in[4])); + const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]); const __m128i CD = _mm_set_epi16(0, 0, 0, 0, -d1, -c1, c1, d1); const __m128i B = _mm_adds_epi16(A, CD); const __m128i m0 = _mm_adds_epi16(B, d4); @@ -238,7 +236,7 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) { WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); } -#undef MUL + #endif // USE_TRANSFORM_AC3 //------------------------------------------------------------------------------ @@ -259,15 +257,15 @@ static WEBP_INLINE void SignedShift8b_SSE2(__m128i* const x) { *x = _mm_packs_epi16(lo_1, hi_1); } -#define FLIP_SIGN_BIT2(a, b) { \ +#define FLIP_SIGN_BIT2(a, b) do { \ (a) = _mm_xor_si128(a, sign_bit); \ (b) = _mm_xor_si128(b, sign_bit); \ -} +} while (0) -#define FLIP_SIGN_BIT4(a, b, c, d) { \ +#define FLIP_SIGN_BIT4(a, b, c, d) do { \ FLIP_SIGN_BIT2(a, b); \ FLIP_SIGN_BIT2(c, d); \ -} +} while (0) // input/output is uint8_t static WEBP_INLINE void GetNotHEV_SSE2(const __m128i* const p1, @@ -645,12 +643,12 @@ static void SimpleHFilter16i_SSE2(uint8_t* p, int stride, int thresh) { (m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \ } while (0) -#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) { \ +#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) do { \ (e1) = _mm_loadu_si128((__m128i*)&(p)[0 * (stride)]); \ (e2) = _mm_loadu_si128((__m128i*)&(p)[1 * (stride)]); \ (e3) = _mm_loadu_si128((__m128i*)&(p)[2 * (stride)]); \ (e4) = _mm_loadu_si128((__m128i*)&(p)[3 * (stride)]); \ -} +} while (0) #define LOADUV_H_EDGE(p, u, v, stride) do { \ const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \ @@ -658,18 +656,18 @@ static void SimpleHFilter16i_SSE2(uint8_t* p, int stride, int thresh) { (p) = _mm_unpacklo_epi64(U, V); \ } while (0) -#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) { \ +#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) do { \ LOADUV_H_EDGE(e1, u, v, 0 * (stride)); \ LOADUV_H_EDGE(e2, u, v, 1 * (stride)); \ LOADUV_H_EDGE(e3, u, v, 2 * (stride)); \ LOADUV_H_EDGE(e4, u, v, 3 * (stride)); \ -} +} while (0) -#define STOREUV(p, u, v, stride) { \ +#define STOREUV(p, u, v, stride) do { \ _mm_storel_epi64((__m128i*)&(u)[(stride)], p); \ (p) = _mm_srli_si128(p, 8); \ _mm_storel_epi64((__m128i*)&(v)[(stride)], p); \ -} +} while (0) static WEBP_INLINE void ComplexMask_SSE2(const __m128i* const p1, const __m128i* const p0, diff --git a/libwebp_src/src/dsp/dsp.h b/libwebp_src/src/dsp/dsp.h index d2000b8..23bc296 100644 --- a/libwebp_src/src/dsp/dsp.h +++ b/libwebp_src/src/dsp/dsp.h @@ -203,6 +203,11 @@ extern VP8DecIdct VP8TransformDC; extern VP8DecIdct VP8TransformDCUV; extern VP8WHT VP8TransformWHT; +#define WEBP_TRANSFORM_AC3_C1 20091 +#define WEBP_TRANSFORM_AC3_C2 35468 +#define WEBP_TRANSFORM_AC3_MUL1(a) ((((a) * WEBP_TRANSFORM_AC3_C1) >> 16) + (a)) +#define WEBP_TRANSFORM_AC3_MUL2(a) (((a) * WEBP_TRANSFORM_AC3_C2) >> 16) + // *dst is the destination block, with stride BPS. Boundary samples are // assumed accessible when needed. typedef void (*VP8PredFunc)(uint8_t* dst); diff --git a/libwebp_src/src/dsp/enc.c b/libwebp_src/src/dsp/enc.c index 2ba97ba..395ad05 100644 --- a/libwebp_src/src/dsp/enc.c +++ b/libwebp_src/src/dsp/enc.c @@ -109,10 +109,6 @@ static WEBP_TSAN_IGNORE_FUNCTION void InitTables(void) { #define STORE(x, y, v) \ dst[(x) + (y) * BPS] = clip_8b(ref[(x) + (y) * BPS] + ((v) >> 3)) -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; -#define MUL(a, b) (((a) * (b)) >> 16) - static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, uint8_t* dst) { int C[4 * 4], *tmp; @@ -121,8 +117,10 @@ static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, for (i = 0; i < 4; ++i) { // vertical pass const int a = in[0] + in[8]; const int b = in[0] - in[8]; - const int c = MUL(in[4], kC2) - MUL(in[12], kC1); - const int d = MUL(in[4], kC1) + MUL(in[12], kC2); + const int c = + WEBP_TRANSFORM_AC3_MUL2(in[4]) - WEBP_TRANSFORM_AC3_MUL1(in[12]); + const int d = + WEBP_TRANSFORM_AC3_MUL1(in[4]) + WEBP_TRANSFORM_AC3_MUL2(in[12]); tmp[0] = a + d; tmp[1] = b + c; tmp[2] = b - c; @@ -134,10 +132,12 @@ static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, tmp = C; for (i = 0; i < 4; ++i) { // horizontal pass const int dc = tmp[0] + 4; - const int a = dc + tmp[8]; - const int b = dc - tmp[8]; - const int c = MUL(tmp[4], kC2) - MUL(tmp[12], kC1); - const int d = MUL(tmp[4], kC1) + MUL(tmp[12], kC2); + const int a = dc + tmp[8]; + const int b = dc - tmp[8]; + const int c = + WEBP_TRANSFORM_AC3_MUL2(tmp[4]) - WEBP_TRANSFORM_AC3_MUL1(tmp[12]); + const int d = + WEBP_TRANSFORM_AC3_MUL1(tmp[4]) + WEBP_TRANSFORM_AC3_MUL2(tmp[12]); STORE(0, i, a + d); STORE(1, i, b + c); STORE(2, i, b - c); @@ -222,7 +222,6 @@ static void FTransformWHT_C(const int16_t* in, int16_t* out) { } #endif // !WEBP_NEON_OMIT_C_CODE -#undef MUL #undef STORE //------------------------------------------------------------------------------ diff --git a/libwebp_src/src/dsp/enc_mips32.c b/libwebp_src/src/dsp/enc_mips32.c index 618f0fc..50518a5 100644 --- a/libwebp_src/src/dsp/enc_mips32.c +++ b/libwebp_src/src/dsp/enc_mips32.c @@ -21,8 +21,8 @@ #include "src/enc/vp8i_enc.h" #include "src/enc/cost_enc.h" -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; +static const int kC1 = WEBP_TRANSFORM_AC3_C1; +static const int kC2 = WEBP_TRANSFORM_AC3_C2; // macro for one vertical pass in ITransformOne // MUL macro inlined @@ -30,7 +30,7 @@ static const int kC2 = 35468; // A..D - offsets in bytes to load from in buffer // TEMP0..TEMP3 - registers for corresponding tmp elements // TEMP4..TEMP5 - temporary registers -#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \ +#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \ "lh %[temp16], " #A "(%[temp20]) \n\t" \ "lh %[temp18], " #B "(%[temp20]) \n\t" \ "lh %[temp17], " #C "(%[temp20]) \n\t" \ @@ -38,12 +38,10 @@ static const int kC2 = 35468; "addu %[" #TEMP4 "], %[temp16], %[temp18] \n\t" \ "subu %[temp16], %[temp16], %[temp18] \n\t" \ "mul %[" #TEMP0 "], %[temp17], %[kC2] \n\t" \ - "mul %[temp18], %[temp19], %[kC1] \n\t" \ - "mul %[temp17], %[temp17], %[kC1] \n\t" \ + MUL_SHIFT_C1_IO(temp17, temp18) \ + MUL_SHIFT_C1(temp18, temp19) \ "mul %[temp19], %[temp19], %[kC2] \n\t" \ "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\n" \ - "sra %[temp18], %[temp18], 16 \n\n" \ - "sra %[temp17], %[temp17], 16 \n\n" \ "sra %[temp19], %[temp19], 16 \n\n" \ "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp18] \n\t" \ "addu %[" #TEMP3 "], %[temp17], %[temp19] \n\t" \ @@ -58,17 +56,15 @@ static const int kC2 = 35468; // temp0..temp15 holds tmp[0]..tmp[15] // A - offset in bytes to load from ref and store to dst buffer // TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements -#define HORIZONTAL_PASS(A, TEMP0, TEMP4, TEMP8, TEMP12) \ +#define HORIZONTAL_PASS(A, TEMP0, TEMP4, TEMP8, TEMP12) \ "addiu %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ "addu %[temp16], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ "subu %[temp17], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ "mul %[" #TEMP0 "], %[" #TEMP4 "], %[kC2] \n\t" \ - "mul %[" #TEMP8 "], %[" #TEMP12 "], %[kC1] \n\t" \ - "mul %[" #TEMP4 "], %[" #TEMP4 "], %[kC1] \n\t" \ + MUL_SHIFT_C1_IO(TEMP4, TEMP8) \ + MUL_SHIFT_C1(TEMP8, TEMP12) \ "mul %[" #TEMP12 "], %[" #TEMP12 "], %[kC2] \n\t" \ "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \ - "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ - "sra %[" #TEMP4 "], %[" #TEMP4 "], 16 \n\t" \ "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ "subu %[temp18], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ "addu %[temp19], %[" #TEMP4 "], %[" #TEMP12 "] \n\t" \ diff --git a/libwebp_src/src/dsp/enc_mips_dsp_r2.c b/libwebp_src/src/dsp/enc_mips_dsp_r2.c index 9ddd895..e1431f3 100644 --- a/libwebp_src/src/dsp/enc_mips_dsp_r2.c +++ b/libwebp_src/src/dsp/enc_mips_dsp_r2.c @@ -20,8 +20,8 @@ #include "src/enc/cost_enc.h" #include "src/enc/vp8i_enc.h" -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; +static const int kC1 = WEBP_TRANSFORM_AC3_C1; +static const int kC2 = WEBP_TRANSFORM_AC3_C2; // O - output // I - input (macro doesn't change it) diff --git a/libwebp_src/src/dsp/enc_neon.c b/libwebp_src/src/dsp/enc_neon.c index 7148003..6f641c9 100644 --- a/libwebp_src/src/dsp/enc_neon.c +++ b/libwebp_src/src/dsp/enc_neon.c @@ -27,8 +27,9 @@ // This code is pretty much the same as TransformOne in the dec_neon.c, except // for subtraction to *ref. See the comments there for algorithmic explanations. -static const int16_t kC1 = 20091; -static const int16_t kC2 = 17734; // half of kC2, actually. See comment above. +static const int16_t kC1 = WEBP_TRANSFORM_AC3_C1; +static const int16_t kC2 = + WEBP_TRANSFORM_AC3_C2 / 2; // half of kC2, actually. See comment above. // This code works but is *slower* than the inlined-asm version below // (with gcc-4.6). So we disable it for now. Later, it'll be conditional to diff --git a/libwebp_src/src/dsp/filters.c b/libwebp_src/src/dsp/filters.c index 85eee50..c9232ff 100644 --- a/libwebp_src/src/dsp/filters.c +++ b/libwebp_src/src/dsp/filters.c @@ -19,14 +19,16 @@ //------------------------------------------------------------------------------ // Helpful macro. -# define SANITY_CHECK(in, out) \ - assert((in) != NULL); \ - assert((out) != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. +#define DCHECK(in, out) \ + do { \ + assert((in) != NULL); \ + assert((out) != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; /* Silence unused warning. */ \ + } while (0) #if !WEBP_NEON_OMIT_C_CODE static WEBP_INLINE void PredictLine_C(const uint8_t* src, const uint8_t* pred, @@ -49,7 +51,7 @@ static WEBP_INLINE void DoHorizontalFilter_C(const uint8_t* in, const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; preds = inverse ? out : in; @@ -86,7 +88,7 @@ static WEBP_INLINE void DoVerticalFilter_C(const uint8_t* in, const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; preds = inverse ? out : in; @@ -131,7 +133,7 @@ static WEBP_INLINE void DoGradientFilter_C(const uint8_t* in, const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; preds = inverse ? out : in; @@ -165,7 +167,7 @@ static WEBP_INLINE void DoGradientFilter_C(const uint8_t* in, } #endif // !WEBP_NEON_OMIT_C_CODE -#undef SANITY_CHECK +#undef DCHECK //------------------------------------------------------------------------------ @@ -189,6 +191,12 @@ static void GradientFilter_C(const uint8_t* data, int width, int height, //------------------------------------------------------------------------------ +static void NoneUnfilter_C(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { + (void)prev; + if (out != in) memcpy(out, in, width * sizeof(*out)); +} + static void HorizontalUnfilter_C(const uint8_t* prev, const uint8_t* in, uint8_t* out, int width) { uint8_t pred = (prev == NULL) ? 0 : prev[0]; @@ -240,7 +248,7 @@ extern void VP8FiltersInitNEON(void); extern void VP8FiltersInitSSE2(void); WEBP_DSP_INIT_FUNC(VP8FiltersInit) { - WebPUnfilters[WEBP_FILTER_NONE] = NULL; + WebPUnfilters[WEBP_FILTER_NONE] = NoneUnfilter_C; #if !WEBP_NEON_OMIT_C_CODE WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_C; WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_C; @@ -279,6 +287,7 @@ WEBP_DSP_INIT_FUNC(VP8FiltersInit) { } #endif + assert(WebPUnfilters[WEBP_FILTER_NONE] != NULL); assert(WebPUnfilters[WEBP_FILTER_HORIZONTAL] != NULL); assert(WebPUnfilters[WEBP_FILTER_VERTICAL] != NULL); assert(WebPUnfilters[WEBP_FILTER_GRADIENT] != NULL); diff --git a/libwebp_src/src/dsp/filters_mips_dsp_r2.c b/libwebp_src/src/dsp/filters_mips_dsp_r2.c index 9382b12..eca866f 100644 --- a/libwebp_src/src/dsp/filters_mips_dsp_r2.c +++ b/libwebp_src/src/dsp/filters_mips_dsp_r2.c @@ -24,14 +24,16 @@ //------------------------------------------------------------------------------ // Helpful macro. -# define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. +#define DCHECK(in, out) \ + do { \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; /* Silence unused warning. */ \ + } while (0) #define DO_PREDICT_LINE(SRC, DST, LENGTH, INVERSE) do { \ const uint8_t* psrc = (uint8_t*)(SRC); \ @@ -200,7 +202,7 @@ static WEBP_INLINE void DoHorizontalFilter_MIPSdspR2(const uint8_t* in, const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; preds = in; @@ -248,7 +250,7 @@ static WEBP_INLINE void DoVerticalFilter_MIPSdspR2(const uint8_t* in, const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; preds = in; @@ -316,7 +318,7 @@ static void DoGradientFilter_MIPSdspR2(const uint8_t* in, const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; preds = in; @@ -378,7 +380,7 @@ static void GradientUnfilter_MIPSdspR2(const uint8_t* prev, const uint8_t* in, #undef DO_PREDICT_LINE_VERTICAL #undef PREDICT_LINE_ONE_PASS #undef DO_PREDICT_LINE -#undef SANITY_CHECK +#undef DCHECK //------------------------------------------------------------------------------ // Entry point diff --git a/libwebp_src/src/dsp/filters_msa.c b/libwebp_src/src/dsp/filters_msa.c index 14c437d..33a1b20 100644 --- a/libwebp_src/src/dsp/filters_msa.c +++ b/libwebp_src/src/dsp/filters_msa.c @@ -56,12 +56,14 @@ static WEBP_INLINE void PredictLineInverse0(const uint8_t* src, //------------------------------------------------------------------------------ // Helpful macro. -#define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); +#define DCHECK(in, out) \ + do { \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + } while (0) //------------------------------------------------------------------------------ // Horrizontal filter @@ -72,7 +74,7 @@ static void HorizontalFilter_MSA(const uint8_t* data, int width, int height, const uint8_t* in = data; uint8_t* out = filtered_data; int row = 1; - SANITY_CHECK(in, out); + DCHECK(in, out); // Leftmost pixel is the same as input for topmost scanline. out[0] = in[0]; @@ -135,7 +137,7 @@ static void GradientFilter_MSA(const uint8_t* data, int width, int height, const uint8_t* preds = data; uint8_t* out = filtered_data; int row = 1; - SANITY_CHECK(in, out); + DCHECK(in, out); // left prediction for top scan-line out[0] = in[0]; @@ -163,7 +165,7 @@ static void VerticalFilter_MSA(const uint8_t* data, int width, int height, const uint8_t* preds = data; uint8_t* out = filtered_data; int row = 1; - SANITY_CHECK(in, out); + DCHECK(in, out); // Very first top-left pixel is copied. out[0] = in[0]; @@ -182,7 +184,7 @@ static void VerticalFilter_MSA(const uint8_t* data, int width, int height, } } -#undef SANITY_CHECK +#undef DCHECK //------------------------------------------------------------------------------ // Entry point diff --git a/libwebp_src/src/dsp/filters_neon.c b/libwebp_src/src/dsp/filters_neon.c index 3e6a578..b49e515 100644 --- a/libwebp_src/src/dsp/filters_neon.c +++ b/libwebp_src/src/dsp/filters_neon.c @@ -21,14 +21,16 @@ //------------------------------------------------------------------------------ // Helpful macros. -# define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. +#define DCHECK(in, out) \ + do { \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; /* Silence unused warning. */ \ + } while (0) // load eight u8 and widen to s16 #define U8_TO_S16(A) vreinterpretq_s16_u16(vmovl_u8(A)) @@ -71,7 +73,7 @@ static WEBP_INLINE void DoHorizontalFilter_NEON(const uint8_t* in, uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; @@ -110,7 +112,7 @@ static WEBP_INLINE void DoVerticalFilter_NEON(const uint8_t* in, uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; @@ -172,7 +174,7 @@ static WEBP_INLINE void DoGradientFilter_NEON(const uint8_t* in, uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; @@ -201,7 +203,7 @@ static void GradientFilter_NEON(const uint8_t* data, int width, int height, filtered_data); } -#undef SANITY_CHECK +#undef DCHECK //------------------------------------------------------------------------------ // Inverse transforms diff --git a/libwebp_src/src/dsp/filters_sse2.c b/libwebp_src/src/dsp/filters_sse2.c index 5c33ec1..bb4b5d5 100644 --- a/libwebp_src/src/dsp/filters_sse2.c +++ b/libwebp_src/src/dsp/filters_sse2.c @@ -23,14 +23,16 @@ //------------------------------------------------------------------------------ // Helpful macro. -# define SANITY_CHECK(in, out) \ - assert((in) != NULL); \ - assert((out) != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. +#define DCHECK(in, out) \ + do { \ + assert((in) != NULL); \ + assert((out) != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; /* Silence unused warning. */ \ + } while (0) static void PredictLineTop_SSE2(const uint8_t* src, const uint8_t* pred, uint8_t* dst, int length) { @@ -78,7 +80,7 @@ static WEBP_INLINE void DoHorizontalFilter_SSE2(const uint8_t* in, uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; @@ -111,7 +113,7 @@ static WEBP_INLINE void DoVerticalFilter_SSE2(const uint8_t* in, uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; @@ -174,7 +176,7 @@ static WEBP_INLINE void DoGradientFilter_SSE2(const uint8_t* in, uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; @@ -197,7 +199,7 @@ static WEBP_INLINE void DoGradientFilter_SSE2(const uint8_t* in, } } -#undef SANITY_CHECK +#undef DCHECK //------------------------------------------------------------------------------ diff --git a/libwebp_src/src/dsp/lossless.h b/libwebp_src/src/dsp/lossless.h index de60d95..0bf10a1 100644 --- a/libwebp_src/src/dsp/lossless.h +++ b/libwebp_src/src/dsp/lossless.h @@ -182,9 +182,9 @@ extern VP8LPredictorAddSubFunc VP8LPredictorsSub_C[16]; // ----------------------------------------------------------------------------- // Huffman-cost related functions. -typedef float (*VP8LCostFunc)(const uint32_t* population, int length); -typedef float (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y, - int length); +typedef uint32_t (*VP8LCostFunc)(const uint32_t* population, int length); +typedef uint32_t (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y, + int length); typedef float (*VP8LCombinedShannonEntropyFunc)(const int X[256], const int Y[256]); diff --git a/libwebp_src/src/dsp/lossless_common.h b/libwebp_src/src/dsp/lossless_common.h index 6a2f736..d6139b2 100644 --- a/libwebp_src/src/dsp/lossless_common.h +++ b/libwebp_src/src/dsp/lossless_common.h @@ -16,9 +16,9 @@ #ifndef WEBP_DSP_LOSSLESS_COMMON_H_ #define WEBP_DSP_LOSSLESS_COMMON_H_ -#include "src/webp/types.h" - +#include "src/dsp/cpu.h" #include "src/utils/utils.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -166,7 +166,7 @@ uint32_t VP8LSubPixels(uint32_t a, uint32_t b) { } //------------------------------------------------------------------------------ -// Transform-related functions use din both encoding and decoding. +// Transform-related functions used in both encoding and decoding. // Macros used to create a batch predictor that iteratively uses a // one-pixel predictor. diff --git a/libwebp_src/src/dsp/lossless_enc.c b/libwebp_src/src/dsp/lossless_enc.c index cde1280..997d56c 100644 --- a/libwebp_src/src/dsp/lossless_enc.c +++ b/libwebp_src/src/dsp/lossless_enc.c @@ -636,20 +636,25 @@ void VP8LBundleColorMap_C(const uint8_t* const row, int width, int xbits, //------------------------------------------------------------------------------ -static float ExtraCost_C(const uint32_t* population, int length) { +static uint32_t ExtraCost_C(const uint32_t* population, int length) { int i; - float cost = 0.f; - for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2]; + uint32_t cost = population[4] + population[5]; + assert(length % 2 == 0); + for (i = 2; i < length / 2 - 1; ++i) { + cost += i * (population[2 * i + 2] + population[2 * i + 3]); + } return cost; } -static float ExtraCostCombined_C(const uint32_t* X, const uint32_t* Y, - int length) { +static uint32_t ExtraCostCombined_C(const uint32_t* X, const uint32_t* Y, + int length) { int i; - float cost = 0.f; - for (i = 2; i < length - 2; ++i) { - const int xy = X[i + 2] + Y[i + 2]; - cost += (i >> 1) * xy; + uint32_t cost = X[4] + Y[4] + X[5] + Y[5]; + assert(length % 2 == 0); + for (i = 2; i < length / 2 - 1; ++i) { + const int xy0 = X[2 * i + 2] + Y[2 * i + 2]; + const int xy1 = X[2 * i + 3] + Y[2 * i + 3]; + cost += i * (xy0 + xy1); } return cost; } diff --git a/libwebp_src/src/dsp/lossless_enc_mips32.c b/libwebp_src/src/dsp/lossless_enc_mips32.c index 639f786..e10f12d 100644 --- a/libwebp_src/src/dsp/lossless_enc_mips32.c +++ b/libwebp_src/src/dsp/lossless_enc_mips32.c @@ -103,8 +103,8 @@ static float FastLog2Slow_MIPS32(uint32_t v) { // cost += i * *(pop + 1); // pop += 2; // } -// return (float)cost; -static float ExtraCost_MIPS32(const uint32_t* const population, int length) { +// return cost; +static uint32_t ExtraCost_MIPS32(const uint32_t* const population, int length) { int i, temp0, temp1; const uint32_t* pop = &population[4]; const uint32_t* const LoopEnd = &population[length]; @@ -130,7 +130,7 @@ static float ExtraCost_MIPS32(const uint32_t* const population, int length) { : "memory", "hi", "lo" ); - return (float)((int64_t)temp0 << 32 | temp1); + return ((int64_t)temp0 << 32 | temp1); } // C version of this function: @@ -148,9 +148,9 @@ static float ExtraCost_MIPS32(const uint32_t* const population, int length) { // pX += 2; // pY += 2; // } -// return (float)cost; -static float ExtraCostCombined_MIPS32(const uint32_t* const X, - const uint32_t* const Y, int length) { +// return cost; +static uint32_t ExtraCostCombined_MIPS32(const uint32_t* const X, + const uint32_t* const Y, int length) { int i, temp0, temp1, temp2, temp3; const uint32_t* pX = &X[4]; const uint32_t* pY = &Y[4]; @@ -183,7 +183,7 @@ static float ExtraCostCombined_MIPS32(const uint32_t* const X, : "memory", "hi", "lo" ); - return (float)((int64_t)temp0 << 32 | temp1); + return ((int64_t)temp0 << 32 | temp1); } #define HUFFMAN_COST_PASS \ diff --git a/libwebp_src/src/dsp/lossless_enc_sse41.c b/libwebp_src/src/dsp/lossless_enc_sse41.c index ad358a6..7ab83c2 100644 --- a/libwebp_src/src/dsp/lossless_enc_sse41.c +++ b/libwebp_src/src/dsp/lossless_enc_sse41.c @@ -18,8 +18,53 @@ #include #include "src/dsp/lossless.h" -// For sign-extended multiplying constants, pre-shifted by 5: -#define CST_5b(X) (((int16_t)((uint16_t)(X) << 8)) >> 5) +//------------------------------------------------------------------------------ +// Cost operations. + +static WEBP_INLINE uint32_t HorizontalSum_SSE41(__m128i cost) { + cost = _mm_add_epi32(cost, _mm_srli_si128(cost, 8)); + cost = _mm_add_epi32(cost, _mm_srli_si128(cost, 4)); + return _mm_cvtsi128_si32(cost); +} + +static uint32_t ExtraCost_SSE41(const uint32_t* const a, int length) { + int i; + __m128i cost = _mm_set_epi32(2 * a[7], 2 * a[6], a[5], a[4]); + assert(length % 8 == 0); + + for (i = 8; i + 8 <= length; i += 8) { + const int j = (i - 2) >> 1; + const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); + const __m128i w = _mm_set_epi32(j + 3, j + 2, j + 1, j); + const __m128i a2 = _mm_hadd_epi32(a0, a1); + const __m128i mul = _mm_mullo_epi32(a2, w); + cost = _mm_add_epi32(mul, cost); + } + return HorizontalSum_SSE41(cost); +} + +static uint32_t ExtraCostCombined_SSE41(const uint32_t* const a, + const uint32_t* const b, int length) { + int i; + __m128i cost = _mm_add_epi32(_mm_set_epi32(2 * a[7], 2 * a[6], a[5], a[4]), + _mm_set_epi32(2 * b[7], 2 * b[6], b[5], b[4])); + assert(length % 8 == 0); + + for (i = 8; i + 8 <= length; i += 8) { + const int j = (i - 2) >> 1; + const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i]); + const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); + const __m128i b0 = _mm_loadu_si128((const __m128i*)&b[i]); + const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[i + 4]); + const __m128i w = _mm_set_epi32(j + 3, j + 2, j + 1, j); + const __m128i a2 = _mm_hadd_epi32(a0, a1); + const __m128i b2 = _mm_hadd_epi32(b0, b1); + const __m128i mul = _mm_mullo_epi32(_mm_add_epi32(a2, b2), w); + cost = _mm_add_epi32(mul, cost); + } + return HorizontalSum_SSE41(cost); +} //------------------------------------------------------------------------------ // Subtract-Green Transform @@ -44,6 +89,9 @@ static void SubtractGreenFromBlueAndRed_SSE41(uint32_t* argb_data, //------------------------------------------------------------------------------ // Color Transform +// For sign-extended multiplying constants, pre-shifted by 5: +#define CST_5b(X) (((int16_t)((uint16_t)(X) << 8)) >> 5) + #define MK_CST_16(HI, LO) \ _mm_set1_epi32((int)(((uint32_t)(HI) << 16) | ((LO) & 0xffff))) @@ -143,6 +191,8 @@ static void CollectColorRedTransforms_SSE41(const uint32_t* argb, int stride, extern void VP8LEncDspInitSSE41(void); WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE41(void) { + VP8LExtraCost = ExtraCost_SSE41; + VP8LExtraCostCombined = ExtraCostCombined_SSE41; VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_SSE41; VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE41; VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE41; diff --git a/libwebp_src/src/dsp/lossless_neon.c b/libwebp_src/src/dsp/lossless_neon.c index ddc9b61..e9960db 100644 --- a/libwebp_src/src/dsp/lossless_neon.c +++ b/libwebp_src/src/dsp/lossless_neon.c @@ -146,9 +146,9 @@ static void ConvertBGRAToRGB_NEON(const uint32_t* src, #define LOAD_U32P_AS_U8(IN) vreinterpret_u8_u32(vld1_u32((IN))) #define LOADQ_U32_AS_U8(IN) vreinterpretq_u8_u32(vdupq_n_u32((IN))) #define LOADQ_U32P_AS_U8(IN) vreinterpretq_u8_u32(vld1q_u32((IN))) -#define GET_U8_AS_U32(IN) vget_lane_u32(vreinterpret_u32_u8((IN)), 0); -#define GETQ_U8_AS_U32(IN) vgetq_lane_u32(vreinterpretq_u32_u8((IN)), 0); -#define STOREQ_U8_AS_U32P(OUT, IN) vst1q_u32((OUT), vreinterpretq_u32_u8((IN))); +#define GET_U8_AS_U32(IN) vget_lane_u32(vreinterpret_u32_u8((IN)), 0) +#define GETQ_U8_AS_U32(IN) vgetq_lane_u32(vreinterpretq_u32_u8((IN)), 0) +#define STOREQ_U8_AS_U32P(OUT, IN) vst1q_u32((OUT), vreinterpretq_u32_u8((IN))) #define ROTATE32_LEFT(L) vextq_u8((L), (L), 12) // D|C|B|A -> C|B|A|D static WEBP_INLINE uint8x8_t Average2_u8_NEON(uint32_t a0, uint32_t a1) { diff --git a/libwebp_src/src/dsp/mips_macro.h b/libwebp_src/src/dsp/mips_macro.h index 44aba9b..e810d3d 100644 --- a/libwebp_src/src/dsp/mips_macro.h +++ b/libwebp_src/src/dsp/mips_macro.h @@ -45,28 +45,38 @@ "ulw %[" #O2 "], " #I3 "+" XSTR(I9) "*" #I7 "(%[" #I0 "]) \n\t" \ "ulw %[" #O3 "], " #I4 "+" XSTR(I9) "*" #I8 "(%[" #I0 "]) \n\t" + +// O - output +// I - input (macro doesn't change it so it should be different from I) +#define MUL_SHIFT_C1(O, I) \ + "mul %[" #O "], %[" #I "], %[kC1] \n\t" \ + "sra %[" #O "], %[" #O "], 16 \n\t" \ + "addu %[" #O "], %[" #O "], %[" #I "] \n\t" +#define MUL_SHIFT_C2(O, I) \ + "mul %[" #O "], %[" #I "], %[kC2] \n\t" \ + "sra %[" #O "], %[" #O "], 16 \n\t" + +// Same as #define MUL_SHIFT_C1 but I and O are the same. It stores the +// intermediary result in TMP. +#define MUL_SHIFT_C1_IO(IO, TMP) \ + "mul %[" #TMP "], %[" #IO "], %[kC1] \n\t" \ + "sra %[" #TMP "], %[" #TMP "], 16 \n\t" \ + "addu %[" #IO "], %[" #TMP "], %[" #IO "] \n\t" + // O - output // IO - input/output // I - input (macro doesn't change it) #define MUL_SHIFT_SUM(O0, O1, O2, O3, O4, O5, O6, O7, \ IO0, IO1, IO2, IO3, \ I0, I1, I2, I3, I4, I5, I6, I7) \ - "mul %[" #O0 "], %[" #I0 "], %[kC2] \n\t" \ - "mul %[" #O1 "], %[" #I0 "], %[kC1] \n\t" \ - "mul %[" #O2 "], %[" #I1 "], %[kC2] \n\t" \ - "mul %[" #O3 "], %[" #I1 "], %[kC1] \n\t" \ - "mul %[" #O4 "], %[" #I2 "], %[kC2] \n\t" \ - "mul %[" #O5 "], %[" #I2 "], %[kC1] \n\t" \ - "mul %[" #O6 "], %[" #I3 "], %[kC2] \n\t" \ - "mul %[" #O7 "], %[" #I3 "], %[kC1] \n\t" \ - "sra %[" #O0 "], %[" #O0 "], 16 \n\t" \ - "sra %[" #O1 "], %[" #O1 "], 16 \n\t" \ - "sra %[" #O2 "], %[" #O2 "], 16 \n\t" \ - "sra %[" #O3 "], %[" #O3 "], 16 \n\t" \ - "sra %[" #O4 "], %[" #O4 "], 16 \n\t" \ - "sra %[" #O5 "], %[" #O5 "], 16 \n\t" \ - "sra %[" #O6 "], %[" #O6 "], 16 \n\t" \ - "sra %[" #O7 "], %[" #O7 "], 16 \n\t" \ + MUL_SHIFT_C2(O0, I0) \ + MUL_SHIFT_C1(O1, I0) \ + MUL_SHIFT_C2(O2, I1) \ + MUL_SHIFT_C1(O3, I1) \ + MUL_SHIFT_C2(O4, I2) \ + MUL_SHIFT_C1(O5, I2) \ + MUL_SHIFT_C2(O6, I3) \ + MUL_SHIFT_C1(O7, I3) \ "addu %[" #IO0 "], %[" #IO0 "], %[" #I4 "] \n\t" \ "addu %[" #IO1 "], %[" #IO1 "], %[" #I5 "] \n\t" \ "subu %[" #IO2 "], %[" #IO2 "], %[" #I6 "] \n\t" \ diff --git a/libwebp_src/src/dsp/msa_macro.h b/libwebp_src/src/dsp/msa_macro.h index 51f6c64..90adbbc 100644 --- a/libwebp_src/src/dsp/msa_macro.h +++ b/libwebp_src/src/dsp/msa_macro.h @@ -73,27 +73,25 @@ #define ST_UW(...) ST_W(v4u32, __VA_ARGS__) #define ST_SW(...) ST_W(v4i32, __VA_ARGS__) -#define MSA_LOAD_FUNC(TYPE, INSTR, FUNC_NAME) \ - static inline TYPE FUNC_NAME(const void* const psrc) { \ - const uint8_t* const psrc_m = (const uint8_t*)psrc; \ - TYPE val_m; \ - asm volatile ( \ - "" #INSTR " %[val_m], %[psrc_m] \n\t" \ - : [val_m] "=r" (val_m) \ - : [psrc_m] "m" (*psrc_m)); \ - return val_m; \ +#define MSA_LOAD_FUNC(TYPE, INSTR, FUNC_NAME) \ + static inline TYPE FUNC_NAME(const void* const psrc) { \ + const uint8_t* const psrc_m = (const uint8_t*)psrc; \ + TYPE val_m; \ + __asm__ volatile("" #INSTR " %[val_m], %[psrc_m] \n\t" \ + : [val_m] "=r"(val_m) \ + : [psrc_m] "m"(*psrc_m)); \ + return val_m; \ } #define MSA_LOAD(psrc, FUNC_NAME) FUNC_NAME(psrc) -#define MSA_STORE_FUNC(TYPE, INSTR, FUNC_NAME) \ - static inline void FUNC_NAME(TYPE val, void* const pdst) { \ - uint8_t* const pdst_m = (uint8_t*)pdst; \ - TYPE val_m = val; \ - asm volatile ( \ - " " #INSTR " %[val_m], %[pdst_m] \n\t" \ - : [pdst_m] "=m" (*pdst_m) \ - : [val_m] "r" (val_m)); \ +#define MSA_STORE_FUNC(TYPE, INSTR, FUNC_NAME) \ + static inline void FUNC_NAME(TYPE val, void* const pdst) { \ + uint8_t* const pdst_m = (uint8_t*)pdst; \ + TYPE val_m = val; \ + __asm__ volatile(" " #INSTR " %[val_m], %[pdst_m] \n\t" \ + : [pdst_m] "=m"(*pdst_m) \ + : [val_m] "r"(val_m)); \ } #define MSA_STORE(val, pdst, FUNC_NAME) FUNC_NAME(val, pdst) diff --git a/libwebp_src/src/dsp/quant.h b/libwebp_src/src/dsp/quant.h index bf7734c..dcbc11c 100644 --- a/libwebp_src/src/dsp/quant.h +++ b/libwebp_src/src/dsp/quant.h @@ -36,8 +36,9 @@ static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks, int thresh) { const int16x8_t tst_ones = vdupq_n_s16(-1); uint32x4_t sum = vdupq_n_u32(0); + int i; - for (int i = 0; i < num_blocks; ++i) { + for (i = 0; i < num_blocks; ++i) { // Set DC to zero. const int16x8_t a_0 = vsetq_lane_s16(0, vld1q_s16(levels), 0); const int16x8_t a_1 = vld1q_s16(levels + 8); diff --git a/libwebp_src/src/dsp/rescaler_neon.c b/libwebp_src/src/dsp/rescaler_neon.c index b976a85..957a92d 100644 --- a/libwebp_src/src/dsp/rescaler_neon.c +++ b/libwebp_src/src/dsp/rescaler_neon.c @@ -32,7 +32,7 @@ #define STORE_32x8(SRC0, SRC1, DST) do { \ vst1q_u32((DST) + 0, SRC0); \ vst1q_u32((DST) + 4, SRC1); \ -} while (0); +} while (0) #if (WEBP_RESCALER_RFIX == 32) #define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1)) diff --git a/libwebp_src/src/dsp/upsampling_sse2.c b/libwebp_src/src/dsp/upsampling_sse2.c index 08b6d0b..77b4f72 100644 --- a/libwebp_src/src/dsp/upsampling_sse2.c +++ b/libwebp_src/src/dsp/upsampling_sse2.c @@ -58,7 +58,7 @@ } while (0) // Loads 17 pixels each from rows r1 and r2 and generates 32 pixels. -#define UPSAMPLE_32PIXELS(r1, r2, out) { \ +#define UPSAMPLE_32PIXELS(r1, r2, out) do { \ const __m128i one = _mm_set1_epi8(1); \ const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \ const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \ @@ -85,7 +85,7 @@ /* pack the alternate pixels */ \ PACK_AND_STORE(a, b, diag1, diag2, (out) + 0); /* store top */ \ PACK_AND_STORE(c, d, diag2, diag1, (out) + 2 * 32); /* store bottom */ \ -} +} while (0) // Turn the macro into a function for reducing code-size when non-critical static void Upsample32Pixels_SSE2(const uint8_t r1[], const uint8_t r2[], @@ -229,11 +229,11 @@ static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ } \ } -YUV444_FUNC(Yuv444ToRgba_SSE2, VP8YuvToRgba32_SSE2, WebPYuv444ToRgba_C, 4); -YUV444_FUNC(Yuv444ToBgra_SSE2, VP8YuvToBgra32_SSE2, WebPYuv444ToBgra_C, 4); +YUV444_FUNC(Yuv444ToRgba_SSE2, VP8YuvToRgba32_SSE2, WebPYuv444ToRgba_C, 4) +YUV444_FUNC(Yuv444ToBgra_SSE2, VP8YuvToBgra32_SSE2, WebPYuv444ToBgra_C, 4) #if !defined(WEBP_REDUCE_CSP) -YUV444_FUNC(Yuv444ToRgb_SSE2, VP8YuvToRgb32_SSE2, WebPYuv444ToRgb_C, 3); -YUV444_FUNC(Yuv444ToBgr_SSE2, VP8YuvToBgr32_SSE2, WebPYuv444ToBgr_C, 3); +YUV444_FUNC(Yuv444ToRgb_SSE2, VP8YuvToRgb32_SSE2, WebPYuv444ToRgb_C, 3) +YUV444_FUNC(Yuv444ToBgr_SSE2, VP8YuvToBgr32_SSE2, WebPYuv444ToBgr_C, 3) YUV444_FUNC(Yuv444ToArgb_SSE2, VP8YuvToArgb32_SSE2, WebPYuv444ToArgb_C, 4) YUV444_FUNC(Yuv444ToRgba4444_SSE2, VP8YuvToRgba444432_SSE2, \ WebPYuv444ToRgba4444_C, 2) diff --git a/libwebp_src/src/dsp/upsampling_sse41.c b/libwebp_src/src/dsp/upsampling_sse41.c index 648d456..e38c88d 100644 --- a/libwebp_src/src/dsp/upsampling_sse41.c +++ b/libwebp_src/src/dsp/upsampling_sse41.c @@ -60,7 +60,7 @@ } while (0) // Loads 17 pixels each from rows r1 and r2 and generates 32 pixels. -#define UPSAMPLE_32PIXELS(r1, r2, out) { \ +#define UPSAMPLE_32PIXELS(r1, r2, out) do { \ const __m128i one = _mm_set1_epi8(1); \ const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \ const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \ @@ -87,7 +87,7 @@ /* pack the alternate pixels */ \ PACK_AND_STORE(a, b, diag1, diag2, (out) + 0); /* store top */ \ PACK_AND_STORE(c, d, diag2, diag1, (out) + 2 * 32); /* store bottom */ \ -} +} while (0) // Turn the macro into a function for reducing code-size when non-critical static void Upsample32Pixels_SSE41(const uint8_t r1[], const uint8_t r2[], @@ -217,8 +217,8 @@ static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ } #if !defined(WEBP_REDUCE_CSP) -YUV444_FUNC(Yuv444ToRgb_SSE41, VP8YuvToRgb32_SSE41, WebPYuv444ToRgb_C, 3); -YUV444_FUNC(Yuv444ToBgr_SSE41, VP8YuvToBgr32_SSE41, WebPYuv444ToBgr_C, 3); +YUV444_FUNC(Yuv444ToRgb_SSE41, VP8YuvToRgb32_SSE41, WebPYuv444ToRgb_C, 3) +YUV444_FUNC(Yuv444ToBgr_SSE41, VP8YuvToBgr32_SSE41, WebPYuv444ToBgr_C, 3) #endif // WEBP_REDUCE_CSP WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE41(void) { diff --git a/libwebp_src/src/enc/alpha_enc.c b/libwebp_src/src/enc/alpha_enc.c index 26f0034..c11a261 100644 --- a/libwebp_src/src/enc/alpha_enc.c +++ b/libwebp_src/src/enc/alpha_enc.c @@ -20,6 +20,7 @@ #include "src/utils/filters_utils.h" #include "src/utils/quant_levels_utils.h" #include "src/utils/utils.h" +#include "src/webp/encode.h" #include "src/webp/format_constants.h" // ----------------------------------------------------------------------------- @@ -55,7 +56,7 @@ static int EncodeLossless(const uint8_t* const data, int width, int height, WebPConfig config; WebPPicture picture; - WebPPictureInit(&picture); + if (!WebPPictureInit(&picture)) return 0; picture.width = width; picture.height = height; picture.use_argb = 1; @@ -66,7 +67,7 @@ static int EncodeLossless(const uint8_t* const data, int width, int height, WebPDispatchAlphaToGreen(data, width, picture.width, picture.height, picture.argb, picture.argb_stride); - WebPConfigInit(&config); + if (!WebPConfigInit(&config)) return 0; config.lossless = 1; // Enable exact, or it would alter RGB values of transparent alpha, which is // normally OK but not here since we are not encoding the input image but an @@ -83,11 +84,7 @@ static int EncodeLossless(const uint8_t* const data, int width, int height, (use_quality_100 && effort_level == 6) ? 100 : 8.f * effort_level; assert(config.quality >= 0 && config.quality <= 100.f); - // TODO(urvang): Temporary fix to avoid generating images that trigger - // a decoder bug related to alpha with color cache. - // See: https://code.google.com/p/webp/issues/detail?id=239 - // Need to re-enable this later. - ok = VP8LEncodeStream(&config, &picture, bw, /*use_cache=*/0); + ok = VP8LEncodeStream(&config, &picture, bw); WebPPictureFree(&picture); ok = ok && !bw->error_; if (!ok) { diff --git a/libwebp_src/src/enc/frame_enc.c b/libwebp_src/src/enc/frame_enc.c index 9a98dc1..01860ca 100644 --- a/libwebp_src/src/enc/frame_enc.c +++ b/libwebp_src/src/enc/frame_enc.c @@ -578,7 +578,7 @@ static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt, uint64_t size = 0; uint64_t size_p0 = 0; uint64_t distortion = 0; - const uint64_t pixel_count = nb_mbs * 384; + const uint64_t pixel_count = (uint64_t)nb_mbs * 384; VP8IteratorInit(enc, &it); SetLoopParams(enc, s->q); @@ -789,7 +789,7 @@ int VP8EncTokenLoop(VP8Encoder* const enc) { VP8EncIterator it; VP8EncProba* const proba = &enc->proba_; const VP8RDLevel rd_opt = enc->rd_opt_level_; - const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384; + const uint64_t pixel_count = (uint64_t)enc->mb_w_ * enc->mb_h_ * 384; PassStats stats; int ok; diff --git a/libwebp_src/src/enc/histogram_enc.c b/libwebp_src/src/enc/histogram_enc.c index 8418def..3ca67b3 100644 --- a/libwebp_src/src/enc/histogram_enc.c +++ b/libwebp_src/src/enc/histogram_enc.c @@ -358,15 +358,17 @@ static WEBP_INLINE float GetCombinedEntropy(const uint32_t* const X, // Estimates the Entropy + Huffman + other block overhead size cost. float VP8LHistogramEstimateBits(VP8LHistogram* const p) { - return - PopulationCost(p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_), - NULL, &p->is_used_[0]) - + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL, &p->is_used_[1]) - + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL, &p->is_used_[2]) - + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL, &p->is_used_[3]) - + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL, &p->is_used_[4]) - + VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES) - + VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES); + return PopulationCost(p->literal_, + VP8LHistogramNumCodes(p->palette_code_bits_), NULL, + &p->is_used_[0]) + + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL, &p->is_used_[1]) + + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL, &p->is_used_[2]) + + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL, &p->is_used_[3]) + + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL, + &p->is_used_[4]) + + (float)VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, + NUM_LENGTH_CODES) + + (float)VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES); } // ----------------------------------------------------------------------------- @@ -381,9 +383,9 @@ static int GetCombinedHistogramEntropy(const VP8LHistogram* const a, *cost += GetCombinedEntropy(a->literal_, b->literal_, VP8LHistogramNumCodes(palette_code_bits), a->is_used_[0], b->is_used_[0], 0); - *cost += VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES, - b->literal_ + NUM_LITERAL_CODES, - NUM_LENGTH_CODES); + *cost += (float)VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES, + b->literal_ + NUM_LITERAL_CODES, + NUM_LENGTH_CODES); if (*cost > cost_threshold) return 0; if (a->trivial_symbol_ != VP8L_NON_TRIVIAL_SYM && @@ -417,8 +419,8 @@ static int GetCombinedHistogramEntropy(const VP8LHistogram* const a, *cost += GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES, a->is_used_[4], b->is_used_[4], 0); - *cost += - VP8LExtraCostCombined(a->distance_, b->distance_, NUM_DISTANCE_CODES); + *cost += (float)VP8LExtraCostCombined(a->distance_, b->distance_, + NUM_DISTANCE_CODES); if (*cost > cost_threshold) return 0; return 1; @@ -506,11 +508,11 @@ static void UpdateHistogramCost(VP8LHistogram* const h) { PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym, &h->is_used_[3]); const float distance_cost = PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL, &h->is_used_[4]) + - VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES); + (float)VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES); const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_); h->literal_cost_ = PopulationCost(h->literal_, num_codes, NULL, &h->is_used_[0]) + - VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES); + (float)VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES); h->red_cost_ = PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym, &h->is_used_[1]); h->blue_cost_ = @@ -1179,7 +1181,7 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize, const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE; int entropy_combine; uint16_t* const map_tmp = - WebPSafeMalloc(2 * image_histo_raw_size, sizeof(map_tmp)); + WebPSafeMalloc(2 * image_histo_raw_size, sizeof(*map_tmp)); uint16_t* const cluster_mappings = map_tmp + image_histo_raw_size; int num_used = image_histo_raw_size; if (orig_histo == NULL || map_tmp == NULL) { diff --git a/libwebp_src/src/enc/picture_enc.c b/libwebp_src/src/enc/picture_enc.c index 3af6383..5a27035 100644 --- a/libwebp_src/src/enc/picture_enc.c +++ b/libwebp_src/src/enc/picture_enc.c @@ -12,10 +12,10 @@ // Author: Skal (pascal.massimino@gmail.com) #include +#include #include #include "src/enc/vp8i_enc.h" -#include "src/dsp/dsp.h" #include "src/utils/utils.h" //------------------------------------------------------------------------------ diff --git a/libwebp_src/src/enc/vp8i_enc.h b/libwebp_src/src/enc/vp8i_enc.h index 0864fbf..00ff1be 100644 --- a/libwebp_src/src/enc/vp8i_enc.h +++ b/libwebp_src/src/enc/vp8i_enc.h @@ -31,8 +31,8 @@ extern "C" { // version numbers #define ENC_MAJ_VERSION 1 -#define ENC_MIN_VERSION 3 -#define ENC_REV_VERSION 2 +#define ENC_MIN_VERSION 4 +#define ENC_REV_VERSION 0 enum { MAX_LF_LEVELS = 64, // Maximum loop filter level MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost diff --git a/libwebp_src/src/enc/vp8l_enc.c b/libwebp_src/src/enc/vp8l_enc.c index 3a8ec3d..40eafa4 100644 --- a/libwebp_src/src/enc/vp8l_enc.c +++ b/libwebp_src/src/enc/vp8l_enc.c @@ -23,6 +23,7 @@ #include "src/enc/vp8li_enc.h" #include "src/utils/bit_writer_utils.h" #include "src/utils/huffman_encode_utils.h" +#include "src/utils/palette.h" #include "src/utils/utils.h" #include "src/webp/encode.h" #include "src/webp/format_constants.h" @@ -30,298 +31,6 @@ // Maximum number of histogram images (sub-blocks). #define MAX_HUFF_IMAGE_SIZE 2600 -// Palette reordering for smaller sum of deltas (and for smaller storage). - -static int PaletteCompareColorsForQsort(const void* p1, const void* p2) { - const uint32_t a = WebPMemToUint32((uint8_t*)p1); - const uint32_t b = WebPMemToUint32((uint8_t*)p2); - assert(a != b); - return (a < b) ? -1 : 1; -} - -static WEBP_INLINE uint32_t PaletteComponentDistance(uint32_t v) { - return (v <= 128) ? v : (256 - v); -} - -// Computes a value that is related to the entropy created by the -// palette entry diff. -// -// Note that the last & 0xff is a no-operation in the next statement, but -// removed by most compilers and is here only for regularity of the code. -static WEBP_INLINE uint32_t PaletteColorDistance(uint32_t col1, uint32_t col2) { - const uint32_t diff = VP8LSubPixels(col1, col2); - const int kMoreWeightForRGBThanForAlpha = 9; - uint32_t score; - score = PaletteComponentDistance((diff >> 0) & 0xff); - score += PaletteComponentDistance((diff >> 8) & 0xff); - score += PaletteComponentDistance((diff >> 16) & 0xff); - score *= kMoreWeightForRGBThanForAlpha; - score += PaletteComponentDistance((diff >> 24) & 0xff); - return score; -} - -static WEBP_INLINE void SwapColor(uint32_t* const col1, uint32_t* const col2) { - const uint32_t tmp = *col1; - *col1 = *col2; - *col2 = tmp; -} - -static WEBP_INLINE int SearchColorNoIdx(const uint32_t sorted[], uint32_t color, - int num_colors) { - int low = 0, hi = num_colors; - if (sorted[low] == color) return low; // loop invariant: sorted[low] != color - while (1) { - const int mid = (low + hi) >> 1; - if (sorted[mid] == color) { - return mid; - } else if (sorted[mid] < color) { - low = mid; - } else { - hi = mid; - } - } - assert(0); - return 0; -} - -// The palette has been sorted by alpha. This function checks if the other -// components of the palette have a monotonic development with regards to -// position in the palette. If all have monotonic development, there is -// no benefit to re-organize them greedily. A monotonic development -// would be spotted in green-only situations (like lossy alpha) or gray-scale -// images. -static int PaletteHasNonMonotonousDeltas(const uint32_t* const palette, - int num_colors) { - uint32_t predict = 0x000000; - int i; - uint8_t sign_found = 0x00; - for (i = 0; i < num_colors; ++i) { - const uint32_t diff = VP8LSubPixels(palette[i], predict); - const uint8_t rd = (diff >> 16) & 0xff; - const uint8_t gd = (diff >> 8) & 0xff; - const uint8_t bd = (diff >> 0) & 0xff; - if (rd != 0x00) { - sign_found |= (rd < 0x80) ? 1 : 2; - } - if (gd != 0x00) { - sign_found |= (gd < 0x80) ? 8 : 16; - } - if (bd != 0x00) { - sign_found |= (bd < 0x80) ? 64 : 128; - } - predict = palette[i]; - } - return (sign_found & (sign_found << 1)) != 0; // two consequent signs. -} - -static void PaletteSortMinimizeDeltas(const uint32_t* const palette_sorted, - int num_colors, uint32_t* const palette) { - uint32_t predict = 0x00000000; - int i, k; - memcpy(palette, palette_sorted, num_colors * sizeof(*palette)); - if (!PaletteHasNonMonotonousDeltas(palette_sorted, num_colors)) return; - // Find greedily always the closest color of the predicted color to minimize - // deltas in the palette. This reduces storage needs since the - // palette is stored with delta encoding. - for (i = 0; i < num_colors; ++i) { - int best_ix = i; - uint32_t best_score = ~0U; - for (k = i; k < num_colors; ++k) { - const uint32_t cur_score = PaletteColorDistance(palette[k], predict); - if (best_score > cur_score) { - best_score = cur_score; - best_ix = k; - } - } - SwapColor(&palette[best_ix], &palette[i]); - predict = palette[i]; - } -} - -// Sort palette in increasing order and prepare an inverse mapping array. -static void PrepareMapToPalette(const uint32_t palette[], uint32_t num_colors, - uint32_t sorted[], uint32_t idx_map[]) { - uint32_t i; - memcpy(sorted, palette, num_colors * sizeof(*sorted)); - qsort(sorted, num_colors, sizeof(*sorted), PaletteCompareColorsForQsort); - for (i = 0; i < num_colors; ++i) { - idx_map[SearchColorNoIdx(sorted, palette[i], num_colors)] = i; - } -} - -// ----------------------------------------------------------------------------- -// Modified Zeng method from "A Survey on Palette Reordering -// Methods for Improving the Compression of Color-Indexed Images" by Armando J. -// Pinho and Antonio J. R. Neves. - -// Finds the biggest cooccurrence in the matrix. -static void CoOccurrenceFindMax(const uint32_t* const cooccurrence, - uint32_t num_colors, uint8_t* const c1, - uint8_t* const c2) { - // Find the index that is most frequently located adjacent to other - // (different) indexes. - uint32_t best_sum = 0u; - uint32_t i, j, best_cooccurrence; - *c1 = 0u; - for (i = 0; i < num_colors; ++i) { - uint32_t sum = 0; - for (j = 0; j < num_colors; ++j) sum += cooccurrence[i * num_colors + j]; - if (sum > best_sum) { - best_sum = sum; - *c1 = i; - } - } - // Find the index that is most frequently found adjacent to *c1. - *c2 = 0u; - best_cooccurrence = 0u; - for (i = 0; i < num_colors; ++i) { - if (cooccurrence[*c1 * num_colors + i] > best_cooccurrence) { - best_cooccurrence = cooccurrence[*c1 * num_colors + i]; - *c2 = i; - } - } - assert(*c1 != *c2); -} - -// Builds the cooccurrence matrix -static int CoOccurrenceBuild(const WebPPicture* const pic, - const uint32_t* const palette, uint32_t num_colors, - uint32_t* cooccurrence) { - uint32_t *lines, *line_top, *line_current, *line_tmp; - int x, y; - const uint32_t* src = pic->argb; - uint32_t prev_pix = ~src[0]; - uint32_t prev_idx = 0u; - uint32_t idx_map[MAX_PALETTE_SIZE] = {0}; - uint32_t palette_sorted[MAX_PALETTE_SIZE]; - lines = (uint32_t*)WebPSafeMalloc(2 * pic->width, sizeof(*lines)); - if (lines == NULL) { - return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - line_top = &lines[0]; - line_current = &lines[pic->width]; - PrepareMapToPalette(palette, num_colors, palette_sorted, idx_map); - for (y = 0; y < pic->height; ++y) { - for (x = 0; x < pic->width; ++x) { - const uint32_t pix = src[x]; - if (pix != prev_pix) { - prev_idx = idx_map[SearchColorNoIdx(palette_sorted, pix, num_colors)]; - prev_pix = pix; - } - line_current[x] = prev_idx; - // 4-connectivity is what works best as mentioned in "On the relation - // between Memon's and the modified Zeng's palette reordering methods". - if (x > 0 && prev_idx != line_current[x - 1]) { - const uint32_t left_idx = line_current[x - 1]; - ++cooccurrence[prev_idx * num_colors + left_idx]; - ++cooccurrence[left_idx * num_colors + prev_idx]; - } - if (y > 0 && prev_idx != line_top[x]) { - const uint32_t top_idx = line_top[x]; - ++cooccurrence[prev_idx * num_colors + top_idx]; - ++cooccurrence[top_idx * num_colors + prev_idx]; - } - } - line_tmp = line_top; - line_top = line_current; - line_current = line_tmp; - src += pic->argb_stride; - } - WebPSafeFree(lines); - return 1; -} - -struct Sum { - uint8_t index; - uint32_t sum; -}; - -// Implements the modified Zeng method from "A Survey on Palette Reordering -// Methods for Improving the Compression of Color-Indexed Images" by Armando J. -// Pinho and Antonio J. R. Neves. -static int PaletteSortModifiedZeng( - const WebPPicture* const pic, const uint32_t* const palette_sorted, - uint32_t num_colors, uint32_t* const palette) { - uint32_t i, j, ind; - uint8_t remapping[MAX_PALETTE_SIZE]; - uint32_t* cooccurrence; - struct Sum sums[MAX_PALETTE_SIZE]; - uint32_t first, last; - uint32_t num_sums; - // TODO(vrabaud) check whether one color images should use palette or not. - if (num_colors <= 1) return 1; - // Build the co-occurrence matrix. - cooccurrence = - (uint32_t*)WebPSafeCalloc(num_colors * num_colors, sizeof(*cooccurrence)); - if (cooccurrence == NULL) { - return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); - } - if (!CoOccurrenceBuild(pic, palette_sorted, num_colors, cooccurrence)) { - WebPSafeFree(cooccurrence); - return 0; - } - - // Initialize the mapping list with the two best indices. - CoOccurrenceFindMax(cooccurrence, num_colors, &remapping[0], &remapping[1]); - - // We need to append and prepend to the list of remapping. To this end, we - // actually define the next start/end of the list as indices in a vector (with - // a wrap around when the end is reached). - first = 0; - last = 1; - num_sums = num_colors - 2; // -2 because we know the first two values - if (num_sums > 0) { - // Initialize the sums with the first two remappings and find the best one - struct Sum* best_sum = &sums[0]; - best_sum->index = 0u; - best_sum->sum = 0u; - for (i = 0, j = 0; i < num_colors; ++i) { - if (i == remapping[0] || i == remapping[1]) continue; - sums[j].index = i; - sums[j].sum = cooccurrence[i * num_colors + remapping[0]] + - cooccurrence[i * num_colors + remapping[1]]; - if (sums[j].sum > best_sum->sum) best_sum = &sums[j]; - ++j; - } - - while (num_sums > 0) { - const uint8_t best_index = best_sum->index; - // Compute delta to know if we need to prepend or append the best index. - int32_t delta = 0; - const int32_t n = num_colors - num_sums; - for (ind = first, j = 0; (ind + j) % num_colors != last + 1; ++j) { - const uint16_t l_j = remapping[(ind + j) % num_colors]; - delta += (n - 1 - 2 * (int32_t)j) * - (int32_t)cooccurrence[best_index * num_colors + l_j]; - } - if (delta > 0) { - first = (first == 0) ? num_colors - 1 : first - 1; - remapping[first] = best_index; - } else { - ++last; - remapping[last] = best_index; - } - // Remove best_sum from sums. - *best_sum = sums[num_sums - 1]; - --num_sums; - // Update all the sums and find the best one. - best_sum = &sums[0]; - for (i = 0; i < num_sums; ++i) { - sums[i].sum += cooccurrence[best_index * num_colors + sums[i].index]; - if (sums[i].sum > best_sum->sum) best_sum = &sums[i]; - } - } - } - assert((last + 1) % num_colors == first); - WebPSafeFree(cooccurrence); - - // Re-map the palette. - for (i = 0; i < num_colors; ++i) { - palette[i] = palette_sorted[remapping[(first + i) % num_colors]]; - } - return 1; -} - // ----------------------------------------------------------------------------- // Palette @@ -336,13 +45,6 @@ typedef enum { kNumEntropyIx = 6 } EntropyIx; -typedef enum { - kSortedDefault = 0, - kMinimizeDelta = 1, - kModifiedZeng = 2, - kUnusedPalette = 3, -} PaletteSorting; - typedef enum { kHistoAlpha = 0, kHistoAlphaPred, @@ -565,7 +267,7 @@ typedef struct { // +2 because we add a palette sorting configuration for kPalette and // kPaletteAndSpatial. -#define CRUNCH_CONFIGS_MAX (kNumEntropyIx + 2) +#define CRUNCH_CONFIGS_MAX (kNumEntropyIx + 2 * kPaletteSortingNum) static int EncoderAnalyze(VP8LEncoder* const enc, CrunchConfig crunch_configs[CRUNCH_CONFIGS_MAX], @@ -586,13 +288,10 @@ static int EncoderAnalyze(VP8LEncoder* const enc, assert(pic != NULL && pic->argb != NULL); // Check whether a palette is possible. - enc->palette_size_ = WebPGetColorPalette(pic, enc->palette_sorted_); + enc->palette_size_ = GetColorPalette(pic, enc->palette_sorted_); use_palette = (enc->palette_size_ <= MAX_PALETTE_SIZE); if (!use_palette) { enc->palette_size_ = 0; - } else { - qsort(enc->palette_sorted_, enc->palette_size_, - sizeof(*enc->palette_sorted_), PaletteCompareColorsForQsort); } // Empirical bit sizes. @@ -625,20 +324,29 @@ static int EncoderAnalyze(VP8LEncoder* const enc, // a palette. if ((i != kPalette && i != kPaletteAndSpatial) || use_palette) { assert(*crunch_configs_size < CRUNCH_CONFIGS_MAX); - crunch_configs[(*crunch_configs_size)].entropy_idx_ = i; if (use_palette && (i == kPalette || i == kPaletteAndSpatial)) { - crunch_configs[(*crunch_configs_size)].palette_sorting_type_ = - kMinimizeDelta; - ++*crunch_configs_size; - // Also add modified Zeng's method. - crunch_configs[(*crunch_configs_size)].entropy_idx_ = i; - crunch_configs[(*crunch_configs_size)].palette_sorting_type_ = - kModifiedZeng; + int sorting_method; + for (sorting_method = 0; sorting_method < kPaletteSortingNum; + ++sorting_method) { + const PaletteSorting typed_sorting_method = + (PaletteSorting)sorting_method; + // TODO(vrabaud) kSortedDefault should be tested. It is omitted + // for now for backward compatibility. + if (typed_sorting_method == kUnusedPalette || + typed_sorting_method == kSortedDefault) { + continue; + } + crunch_configs[(*crunch_configs_size)].entropy_idx_ = i; + crunch_configs[(*crunch_configs_size)].palette_sorting_type_ = + typed_sorting_method; + ++*crunch_configs_size; + } } else { + crunch_configs[(*crunch_configs_size)].entropy_idx_ = i; crunch_configs[(*crunch_configs_size)].palette_sorting_type_ = kUnusedPalette; + ++*crunch_configs_size; } - ++*crunch_configs_size; } } } else { @@ -1112,10 +820,10 @@ static int EncodeImageNoHuffman(VP8LBitWriter* const bw, static int EncodeImageInternal( VP8LBitWriter* const bw, const uint32_t* const argb, VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[4], int width, - int height, int quality, int low_effort, int use_cache, - const CrunchConfig* const config, int* cache_bits, int histogram_bits, - size_t init_byte_position, int* const hdr_size, int* const data_size, - const WebPPicture* const pic, int percent_range, int* const percent) { + int height, int quality, int low_effort, const CrunchConfig* const config, + int* cache_bits, int histogram_bits, size_t init_byte_position, + int* const hdr_size, int* const data_size, const WebPPicture* const pic, + int percent_range, int* const percent) { const uint32_t histogram_image_xysize = VP8LSubSampleSize(width, histogram_bits) * VP8LSubSampleSize(height, histogram_bits); @@ -1163,13 +871,9 @@ static int EncodeImageInternal( percent_start += percent_range; remaining_percent -= percent_range; - if (use_cache) { - // If the value is different from zero, it has been set during the - // palette analysis. - cache_bits_init = (*cache_bits == 0) ? MAX_COLOR_CACHE_BITS : *cache_bits; - } else { - cache_bits_init = 0; - } + // If the value is different from zero, it has been set during the palette + // analysis. + cache_bits_init = (*cache_bits == 0) ? MAX_COLOR_CACHE_BITS : *cache_bits; // If several iterations will happen, clone into bw_best. if ((config->sub_configs_size_ > 1 || config->sub_configs_[0].do_no_cache_) && !VP8LBitWriterClone(bw, &bw_best)) { @@ -1485,7 +1189,7 @@ static void ClearTransformBuffer(VP8LEncoder* const enc) { // enc->use_predict_, enc->use_cross_color_ static int AllocateTransformBuffer(VP8LEncoder* const enc, int width, int height) { - const uint64_t image_size = width * height; + const uint64_t image_size = (uint64_t)width * height; // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra // pixel in each, plus 2 regular scanlines of bytes. // TODO(skal): Clean up by using arithmetic in bytes instead of words. @@ -1495,7 +1199,7 @@ static int AllocateTransformBuffer(VP8LEncoder* const enc, int width, : 0; const uint64_t transform_data_size = (enc->use_predict_ || enc->use_cross_color_) - ? VP8LSubSampleSize(width, enc->transform_bits_) * + ? (uint64_t)VP8LSubSampleSize(width, enc->transform_bits_) * VP8LSubSampleSize(height, enc->transform_bits_) : 0; const uint64_t max_alignment_in_words = @@ -1758,7 +1462,6 @@ typedef struct { const WebPPicture* picture_; VP8LBitWriter* bw_; VP8LEncoder* enc_; - int use_cache_; CrunchConfig crunch_configs_[CRUNCH_CONFIGS_MAX]; int num_crunch_configs_; int red_and_blue_always_zero_; @@ -1771,7 +1474,6 @@ static int EncodeStreamHook(void* input, void* data2) { const WebPPicture* const picture = params->picture_; VP8LBitWriter* const bw = params->bw_; VP8LEncoder* const enc = params->enc_; - const int use_cache = params->use_cache_; const CrunchConfig* const crunch_configs = params->crunch_configs_; const int num_crunch_configs = params->num_crunch_configs_; const int red_and_blue_always_zero = params->red_and_blue_always_zero_; @@ -1845,19 +1547,11 @@ static int EncodeStreamHook(void* input, void* data2) { // Encode palette if (enc->use_palette_) { - if (crunch_configs[idx].palette_sorting_type_ == kSortedDefault) { - // Nothing to do, we have already sorted the palette. - memcpy(enc->palette_, enc->palette_sorted_, - enc->palette_size_ * sizeof(*enc->palette_)); - } else if (crunch_configs[idx].palette_sorting_type_ == kMinimizeDelta) { - PaletteSortMinimizeDeltas(enc->palette_sorted_, enc->palette_size_, - enc->palette_); - } else { - assert(crunch_configs[idx].palette_sorting_type_ == kModifiedZeng); - if (!PaletteSortModifiedZeng(enc->pic_, enc->palette_sorted_, - enc->palette_size_, enc->palette_)) { - goto Error; - } + if (!PaletteSort(crunch_configs[idx].palette_sorting_type_, enc->pic_, + enc->palette_sorted_, enc->palette_size_, + enc->palette_)) { + WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); + goto Error; } percent_range = remaining_percent / 4; if (!EncodePalette(bw, low_effort, enc, percent_range, &percent)) { @@ -1867,7 +1561,7 @@ static int EncodeStreamHook(void* input, void* data2) { if (!MapImageFromPalette(enc, use_delta_palette)) goto Error; // If using a color cache, do not have it bigger than the number of // colors. - if (use_cache && enc->palette_size_ < (1 << MAX_COLOR_CACHE_BITS)) { + if (enc->palette_size_ < (1 << MAX_COLOR_CACHE_BITS)) { enc->cache_bits_ = BitsLog2Floor(enc->palette_size_) + 1; } } @@ -1911,7 +1605,7 @@ static int EncodeStreamHook(void* input, void* data2) { // Encode and write the transformed image. if (!EncodeImageInternal( bw, enc->argb_, &enc->hash_chain_, enc->refs_, enc->current_width_, - height, quality, low_effort, use_cache, &crunch_configs[idx], + height, quality, low_effort, &crunch_configs[idx], &enc->cache_bits_, enc->histo_bits_, byte_position, &hdr_size, &data_size, picture, remaining_percent, &percent)) { goto Error; @@ -1953,7 +1647,7 @@ static int EncodeStreamHook(void* input, void* data2) { int VP8LEncodeStream(const WebPConfig* const config, const WebPPicture* const picture, - VP8LBitWriter* const bw_main, int use_cache) { + VP8LBitWriter* const bw_main) { VP8LEncoder* const enc_main = VP8LEncoderNew(config, picture); VP8LEncoder* enc_side = NULL; CrunchConfig crunch_configs[CRUNCH_CONFIGS_MAX]; @@ -1975,7 +1669,9 @@ int VP8LEncodeStream(const WebPConfig* const config, } // Avoid "garbage value" error from Clang's static analysis tool. - WebPPictureInit(&picture_side); + if (!WebPPictureInit(&picture_side)) { + goto Error; + } // Analyze image (entropy, num_palettes etc) if (!EncoderAnalyze(enc_main, crunch_configs, &num_crunch_configs_main, @@ -2010,7 +1706,6 @@ int VP8LEncodeStream(const WebPConfig* const config, StreamEncodeContext* const param = (idx == 0) ? ¶ms_main : ¶ms_side; param->config_ = config; - param->use_cache_ = use_cache; param->red_and_blue_always_zero_ = red_and_blue_always_zero; if (idx == 0) { param->picture_ = picture; @@ -2164,7 +1859,7 @@ int VP8LEncodeImage(const WebPConfig* const config, if (!WebPReportProgress(picture, 2, &percent)) goto UserAbort; // Encode main image stream. - if (!VP8LEncodeStream(config, picture, &bw, 1 /*use_cache*/)) goto Error; + if (!VP8LEncodeStream(config, picture, &bw)) goto Error; if (!WebPReportProgress(picture, 99, &percent)) goto UserAbort; diff --git a/libwebp_src/src/enc/vp8li_enc.h b/libwebp_src/src/enc/vp8li_enc.h index 3d35e16..c5b60dc 100644 --- a/libwebp_src/src/enc/vp8li_enc.h +++ b/libwebp_src/src/enc/vp8li_enc.h @@ -88,11 +88,9 @@ int VP8LEncodeImage(const WebPConfig* const config, const WebPPicture* const picture); // Encodes the main image stream using the supplied bit writer. -// If 'use_cache' is false, disables the use of color cache. // Returns false in case of error (stored in picture->error_code). int VP8LEncodeStream(const WebPConfig* const config, - const WebPPicture* const picture, VP8LBitWriter* const bw, - int use_cache); + const WebPPicture* const picture, VP8LBitWriter* const bw); #if (WEBP_NEAR_LOSSLESS == 1) // in near_lossless.c diff --git a/libwebp_src/src/libwebp.rc b/libwebp_src/src/libwebp.rc index 4e8e402..d51536f 100644 --- a/libwebp_src/src/libwebp.rc +++ b/libwebp_src/src/libwebp.rc @@ -6,8 +6,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,3,2 - PRODUCTVERSION 1,0,3,2 + FILEVERSION 1,0,4,0 + PRODUCTVERSION 1,0,4,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -24,12 +24,12 @@ BEGIN BEGIN VALUE "CompanyName", "Google, Inc." VALUE "FileDescription", "libwebp DLL" - VALUE "FileVersion", "1.3.2" + VALUE "FileVersion", "1.4.0" VALUE "InternalName", "libwebp.dll" - VALUE "LegalCopyright", "Copyright (C) 2023" + VALUE "LegalCopyright", "Copyright (C) 2024" VALUE "OriginalFilename", "libwebp.dll" VALUE "ProductName", "WebP Image Codec" - VALUE "ProductVersion", "1.3.2" + VALUE "ProductVersion", "1.4.0" END END BLOCK "VarFileInfo" diff --git a/libwebp_src/src/libwebpdecoder.rc b/libwebp_src/src/libwebpdecoder.rc index c3f3e4a..3891488 100644 --- a/libwebp_src/src/libwebpdecoder.rc +++ b/libwebp_src/src/libwebpdecoder.rc @@ -6,8 +6,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,3,2 - PRODUCTVERSION 1,0,3,2 + FILEVERSION 1,0,4,0 + PRODUCTVERSION 1,0,4,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -24,12 +24,12 @@ BEGIN BEGIN VALUE "CompanyName", "Google, Inc." VALUE "FileDescription", "libwebpdecoder DLL" - VALUE "FileVersion", "1.3.2" + VALUE "FileVersion", "1.4.0" VALUE "InternalName", "libwebpdecoder.dll" - VALUE "LegalCopyright", "Copyright (C) 2023" + VALUE "LegalCopyright", "Copyright (C) 2024" VALUE "OriginalFilename", "libwebpdecoder.dll" VALUE "ProductName", "WebP Image Decoder" - VALUE "ProductVersion", "1.3.2" + VALUE "ProductVersion", "1.4.0" END END BLOCK "VarFileInfo" diff --git a/libwebp_src/src/mux/Makefile.am b/libwebp_src/src/mux/Makefile.am index 9abd859..18bc90e 100644 --- a/libwebp_src/src/mux/Makefile.am +++ b/libwebp_src/src/mux/Makefile.am @@ -17,6 +17,6 @@ noinst_HEADERS = noinst_HEADERS += ../webp/format_constants.h libwebpmux_la_LIBADD = ../libwebp.la -libwebpmux_la_LDFLAGS = -no-undefined -version-info 3:13:0 -lm +libwebpmux_la_LDFLAGS = -no-undefined -version-info 4:0:1 -lm libwebpmuxincludedir = $(includedir)/webp pkgconfig_DATA = libwebpmux.pc diff --git a/libwebp_src/src/mux/anim_encode.c b/libwebp_src/src/mux/anim_encode.c index 7078d9a..31bd045 100644 --- a/libwebp_src/src/mux/anim_encode.c +++ b/libwebp_src/src/mux/anim_encode.c @@ -22,6 +22,7 @@ #include "src/webp/encode.h" #include "src/webp/format_constants.h" #include "src/webp/mux.h" +#include "src/webp/types.h" #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf @@ -593,16 +594,17 @@ int WebPAnimEncoderRefineRect( int is_lossless, float quality, int* const x_offset, int* const y_offset, int* const width, int* const height) { FrameRectangle rect; - const int right = clip(*x_offset + *width, 0, curr_canvas->width); - const int left = clip(*x_offset, 0, curr_canvas->width - 1); - const int bottom = clip(*y_offset + *height, 0, curr_canvas->height); - const int top = clip(*y_offset, 0, curr_canvas->height - 1); + int right, left, bottom, top; if (prev_canvas == NULL || curr_canvas == NULL || prev_canvas->width != curr_canvas->width || prev_canvas->height != curr_canvas->height || !prev_canvas->use_argb || !curr_canvas->use_argb) { return 0; } + right = clip(*x_offset + *width, 0, curr_canvas->width); + left = clip(*x_offset, 0, curr_canvas->width - 1); + bottom = clip(*y_offset + *height, 0, curr_canvas->height); + top = clip(*y_offset, 0, curr_canvas->height - 1); rect.x_offset_ = left; rect.y_offset_ = top; rect.width_ = clip(right - left, 0, curr_canvas->width - rect.x_offset_); @@ -1397,7 +1399,10 @@ int WebPAnimEncoderAdd(WebPAnimEncoder* enc, WebPPicture* frame, int timestamp, } config = *encoder_config; } else { - WebPConfigInit(&config); + if (!WebPConfigInit(&config)) { + MarkError(enc, "Cannot Init config"); + return 0; + } config.lossless = 1; } assert(enc->curr_canvas_ == NULL); @@ -1418,12 +1423,14 @@ int WebPAnimEncoderAdd(WebPAnimEncoder* enc, WebPPicture* frame, int timestamp, // ----------------------------------------------------------------------------- // Bitstream assembly. -static int DecodeFrameOntoCanvas(const WebPMuxFrameInfo* const frame, - WebPPicture* const canvas) { +WEBP_NODISCARD static int DecodeFrameOntoCanvas( + const WebPMuxFrameInfo* const frame, WebPPicture* const canvas) { const WebPData* const image = &frame->bitstream; WebPPicture sub_image; WebPDecoderConfig config; - WebPInitDecoderConfig(&config); + if (!WebPInitDecoderConfig(&config)) { + return 0; + } WebPUtilClearPic(canvas, NULL); if (WebPGetFeatures(image->bytes, image->size, &config.input) != VP8_STATUS_OK) { @@ -1582,4 +1589,23 @@ const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc) { return enc->error_str_; } +WebPMuxError WebPAnimEncoderSetChunk( + WebPAnimEncoder* enc, const char fourcc[4], const WebPData* chunk_data, + int copy_data) { + if (enc == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return WebPMuxSetChunk(enc->mux_, fourcc, chunk_data, copy_data); +} + +WebPMuxError WebPAnimEncoderGetChunk( + const WebPAnimEncoder* enc, const char fourcc[4], WebPData* chunk_data) { + if (enc == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return WebPMuxGetChunk(enc->mux_, fourcc, chunk_data); +} + +WebPMuxError WebPAnimEncoderDeleteChunk( + WebPAnimEncoder* enc, const char fourcc[4]) { + if (enc == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return WebPMuxDeleteChunk(enc->mux_, fourcc); +} + // ----------------------------------------------------------------------------- diff --git a/libwebp_src/src/mux/libwebpmux.rc b/libwebp_src/src/mux/libwebpmux.rc index bca38f6..1b20fac 100644 --- a/libwebp_src/src/mux/libwebpmux.rc +++ b/libwebp_src/src/mux/libwebpmux.rc @@ -6,8 +6,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,3,2 - PRODUCTVERSION 1,0,3,2 + FILEVERSION 1,0,4,0 + PRODUCTVERSION 1,0,4,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -24,12 +24,12 @@ BEGIN BEGIN VALUE "CompanyName", "Google, Inc." VALUE "FileDescription", "libwebpmux DLL" - VALUE "FileVersion", "1.3.2" + VALUE "FileVersion", "1.4.0" VALUE "InternalName", "libwebpmux.dll" - VALUE "LegalCopyright", "Copyright (C) 2023" + VALUE "LegalCopyright", "Copyright (C) 2024" VALUE "OriginalFilename", "libwebpmux.dll" VALUE "ProductName", "WebP Image Muxer" - VALUE "ProductVersion", "1.3.2" + VALUE "ProductVersion", "1.4.0" END END BLOCK "VarFileInfo" diff --git a/libwebp_src/src/mux/muxedit.c b/libwebp_src/src/mux/muxedit.c index 63e71a0..48c6834 100644 --- a/libwebp_src/src/mux/muxedit.c +++ b/libwebp_src/src/mux/muxedit.c @@ -66,14 +66,16 @@ void WebPMuxDelete(WebPMux* mux) { // Handy MACRO, makes MuxSet() very symmetric to MuxGet(). #define SWITCH_ID_LIST(INDEX, LIST) \ - if (idx == (INDEX)) { \ - err = ChunkAssignData(&chunk, data, copy_data, tag); \ - if (err == WEBP_MUX_OK) { \ - err = ChunkSetHead(&chunk, (LIST)); \ - if (err != WEBP_MUX_OK) ChunkRelease(&chunk); \ + do { \ + if (idx == (INDEX)) { \ + err = ChunkAssignData(&chunk, data, copy_data, tag); \ + if (err == WEBP_MUX_OK) { \ + err = ChunkSetHead(&chunk, (LIST)); \ + if (err != WEBP_MUX_OK) ChunkRelease(&chunk); \ + } \ + return err; \ } \ - return err; \ - } + } while (0) static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, const WebPData* const data, int copy_data) { @@ -555,7 +557,8 @@ static WebPMuxError MuxCleanup(WebPMux* const mux) { if (num_frames == 1) { WebPMuxImage* frame = NULL; err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame); - assert(err == WEBP_MUX_OK); // We know that one frame does exist. + if (err != WEBP_MUX_OK) return err; + // We know that one frame does exist. assert(frame != NULL); if (frame->header_ != NULL && ((mux->canvas_width_ == 0 && mux->canvas_height_ == 0) || diff --git a/libwebp_src/src/mux/muxi.h b/libwebp_src/src/mux/muxi.h index afc5954..74ae3fa 100644 --- a/libwebp_src/src/mux/muxi.h +++ b/libwebp_src/src/mux/muxi.h @@ -28,8 +28,8 @@ extern "C" { // Defines and constants. #define MUX_MAJ_VERSION 1 -#define MUX_MIN_VERSION 3 -#define MUX_REV_VERSION 2 +#define MUX_MIN_VERSION 4 +#define MUX_REV_VERSION 0 // Chunk object. typedef struct WebPChunk WebPChunk; diff --git a/libwebp_src/src/mux/muxread.c b/libwebp_src/src/mux/muxread.c index 9862ec6..afd3542 100644 --- a/libwebp_src/src/mux/muxread.c +++ b/libwebp_src/src/mux/muxread.c @@ -21,20 +21,23 @@ // Handy MACRO. #define SWITCH_ID_LIST(INDEX, LIST) \ - if (idx == (INDEX)) { \ - const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \ - kChunks[(INDEX)].tag); \ - if (chunk) { \ - *data = chunk->data_; \ - return WEBP_MUX_OK; \ - } else { \ - return WEBP_MUX_NOT_FOUND; \ + do { \ + if (idx == (INDEX)) { \ + const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \ + kChunks[(INDEX)].tag); \ + if (chunk) { \ + *data = chunk->data_; \ + return WEBP_MUX_OK; \ + } else { \ + return WEBP_MUX_NOT_FOUND; \ + } \ } \ - } + } while (0) static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx, uint32_t nth, WebPData* const data) { assert(mux != NULL); + assert(idx != IDX_LAST_CHUNK); assert(!IsWPI(kChunks[idx].id)); WebPDataInit(data); @@ -429,6 +432,7 @@ WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4], return WEBP_MUX_INVALID_ARGUMENT; } idx = ChunkGetIndexFromFourCC(fourcc); + assert(idx != IDX_LAST_CHUNK); if (IsWPI(kChunks[idx].id)) { // An image chunk. return WEBP_MUX_INVALID_ARGUMENT; } else if (idx != IDX_UNKNOWN) { // A known chunk type. diff --git a/libwebp_src/src/utils/Makefile.am b/libwebp_src/src/utils/Makefile.am index a4bff8b..a0b7fe3 100644 --- a/libwebp_src/src/utils/Makefile.am +++ b/libwebp_src/src/utils/Makefile.am @@ -26,6 +26,8 @@ COMMON_SOURCES += filters_utils.c COMMON_SOURCES += filters_utils.h COMMON_SOURCES += huffman_utils.c COMMON_SOURCES += huffman_utils.h +COMMON_SOURCES += palette.c +COMMON_SOURCES += palette.h COMMON_SOURCES += quant_levels_dec_utils.c COMMON_SOURCES += quant_levels_dec_utils.h COMMON_SOURCES += rescaler_utils.c diff --git a/libwebp_src/src/utils/huffman_utils.c b/libwebp_src/src/utils/huffman_utils.c index cf73abd..16f9faa 100644 --- a/libwebp_src/src/utils/huffman_utils.c +++ b/libwebp_src/src/utils/huffman_utils.c @@ -122,6 +122,9 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits, const int symbol_code_length = code_lengths[symbol]; if (code_lengths[symbol] > 0) { if (sorted != NULL) { + if(offset[symbol_code_length] >= code_lengths_size) { + return 0; + } sorted[offset[symbol_code_length]++] = symbol; } else { offset[symbol_code_length]++; @@ -267,11 +270,11 @@ int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables) { // Have 'segment' point to the first segment for now, 'root'. HuffmanTablesSegment* const root = &huffman_tables->root; huffman_tables->curr_segment = root; + root->next = NULL; // Allocate root. root->start = (HuffmanCode*)WebPSafeMalloc(size, sizeof(*root->start)); if (root->start == NULL) return 0; root->curr_table = root->start; - root->next = NULL; root->size = size; return 1; } diff --git a/libwebp_src/src/utils/huffman_utils.h b/libwebp_src/src/utils/huffman_utils.h index 98415c5..d511dc0 100644 --- a/libwebp_src/src/utils/huffman_utils.h +++ b/libwebp_src/src/utils/huffman_utils.h @@ -63,7 +63,8 @@ typedef struct HuffmanTables { // Allocates a HuffmanTables with 'size' contiguous HuffmanCodes. Returns 0 on // memory allocation error, 1 otherwise. -int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables); +WEBP_NODISCARD int VP8LHuffmanTablesAllocate(int size, + HuffmanTables* huffman_tables); void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables); #define HUFFMAN_PACKED_BITS 6 @@ -91,7 +92,7 @@ struct HTreeGroup { }; // Creates the instance of HTreeGroup with specified number of tree-groups. -HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups); +WEBP_NODISCARD HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups); // Releases the memory allocated for HTreeGroup. void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups); @@ -101,8 +102,10 @@ void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups); // the huffman table. // Returns built table size or 0 in case of error (invalid tree or // memory error). -int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits, - const int code_lengths[], int code_lengths_size); +WEBP_NODISCARD int VP8LBuildHuffmanTable(HuffmanTables* const root_table, + int root_bits, + const int code_lengths[], + int code_lengths_size); #ifdef __cplusplus } // extern "C" diff --git a/libwebp_src/src/utils/palette.c b/libwebp_src/src/utils/palette.c new file mode 100644 index 0000000..515da21 --- /dev/null +++ b/libwebp_src/src/utils/palette.c @@ -0,0 +1,402 @@ +// Copyright 2023 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for palette analysis. +// +// Author: Vincent Rabaud (vrabaud@google.com) + +#include "src/utils/palette.h" + +#include +#include + +#include "src/dsp/lossless_common.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" +#include "src/webp/encode.h" +#include "src/webp/format_constants.h" + +// ----------------------------------------------------------------------------- + +// Palette reordering for smaller sum of deltas (and for smaller storage). + +static int PaletteCompareColorsForQsort(const void* p1, const void* p2) { + const uint32_t a = WebPMemToUint32((uint8_t*)p1); + const uint32_t b = WebPMemToUint32((uint8_t*)p2); + assert(a != b); + return (a < b) ? -1 : 1; +} + +static WEBP_INLINE uint32_t PaletteComponentDistance(uint32_t v) { + return (v <= 128) ? v : (256 - v); +} + +// Computes a value that is related to the entropy created by the +// palette entry diff. +// +// Note that the last & 0xff is a no-operation in the next statement, but +// removed by most compilers and is here only for regularity of the code. +static WEBP_INLINE uint32_t PaletteColorDistance(uint32_t col1, uint32_t col2) { + const uint32_t diff = VP8LSubPixels(col1, col2); + const int kMoreWeightForRGBThanForAlpha = 9; + uint32_t score; + score = PaletteComponentDistance((diff >> 0) & 0xff); + score += PaletteComponentDistance((diff >> 8) & 0xff); + score += PaletteComponentDistance((diff >> 16) & 0xff); + score *= kMoreWeightForRGBThanForAlpha; + score += PaletteComponentDistance((diff >> 24) & 0xff); + return score; +} + +static WEBP_INLINE void SwapColor(uint32_t* const col1, uint32_t* const col2) { + const uint32_t tmp = *col1; + *col1 = *col2; + *col2 = tmp; +} + +int SearchColorNoIdx(const uint32_t sorted[], uint32_t color, int num_colors) { + int low = 0, hi = num_colors; + if (sorted[low] == color) return low; // loop invariant: sorted[low] != color + while (1) { + const int mid = (low + hi) >> 1; + if (sorted[mid] == color) { + return mid; + } else if (sorted[mid] < color) { + low = mid; + } else { + hi = mid; + } + } + assert(0); + return 0; +} + +void PrepareMapToPalette(const uint32_t palette[], uint32_t num_colors, + uint32_t sorted[], uint32_t idx_map[]) { + uint32_t i; + memcpy(sorted, palette, num_colors * sizeof(*sorted)); + qsort(sorted, num_colors, sizeof(*sorted), PaletteCompareColorsForQsort); + for (i = 0; i < num_colors; ++i) { + idx_map[SearchColorNoIdx(sorted, palette[i], num_colors)] = i; + } +} + +//------------------------------------------------------------------------------ + +#define COLOR_HASH_SIZE (MAX_PALETTE_SIZE * 4) +#define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE). + +int GetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { + int i; + int x, y; + int num_colors = 0; + uint8_t in_use[COLOR_HASH_SIZE] = {0}; + uint32_t colors[COLOR_HASH_SIZE] = {0}; + const uint32_t* argb = pic->argb; + const int width = pic->width; + const int height = pic->height; + uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] + assert(pic != NULL); + assert(pic->use_argb); + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + int key; + if (argb[x] == last_pix) { + continue; + } + last_pix = argb[x]; + key = VP8LHashPix(last_pix, COLOR_HASH_RIGHT_SHIFT); + while (1) { + if (!in_use[key]) { + colors[key] = last_pix; + in_use[key] = 1; + ++num_colors; + if (num_colors > MAX_PALETTE_SIZE) { + return MAX_PALETTE_SIZE + 1; // Exact count not needed. + } + break; + } else if (colors[key] == last_pix) { + break; // The color is already there. + } else { + // Some other color sits here, so do linear conflict resolution. + ++key; + key &= (COLOR_HASH_SIZE - 1); // Key mask. + } + } + } + argb += pic->argb_stride; + } + + if (palette != NULL) { // Fill the colors into palette. + num_colors = 0; + for (i = 0; i < COLOR_HASH_SIZE; ++i) { + if (in_use[i]) { + palette[num_colors] = colors[i]; + ++num_colors; + } + } + qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort); + } + return num_colors; +} + +#undef COLOR_HASH_SIZE +#undef COLOR_HASH_RIGHT_SHIFT + +// ----------------------------------------------------------------------------- + +// The palette has been sorted by alpha. This function checks if the other +// components of the palette have a monotonic development with regards to +// position in the palette. If all have monotonic development, there is +// no benefit to re-organize them greedily. A monotonic development +// would be spotted in green-only situations (like lossy alpha) or gray-scale +// images. +static int PaletteHasNonMonotonousDeltas(const uint32_t* const palette, + int num_colors) { + uint32_t predict = 0x000000; + int i; + uint8_t sign_found = 0x00; + for (i = 0; i < num_colors; ++i) { + const uint32_t diff = VP8LSubPixels(palette[i], predict); + const uint8_t rd = (diff >> 16) & 0xff; + const uint8_t gd = (diff >> 8) & 0xff; + const uint8_t bd = (diff >> 0) & 0xff; + if (rd != 0x00) { + sign_found |= (rd < 0x80) ? 1 : 2; + } + if (gd != 0x00) { + sign_found |= (gd < 0x80) ? 8 : 16; + } + if (bd != 0x00) { + sign_found |= (bd < 0x80) ? 64 : 128; + } + predict = palette[i]; + } + return (sign_found & (sign_found << 1)) != 0; // two consequent signs. +} + +static void PaletteSortMinimizeDeltas(const uint32_t* const palette_sorted, + int num_colors, uint32_t* const palette) { + uint32_t predict = 0x00000000; + int i, k; + memcpy(palette, palette_sorted, num_colors * sizeof(*palette)); + if (!PaletteHasNonMonotonousDeltas(palette_sorted, num_colors)) return; + // Find greedily always the closest color of the predicted color to minimize + // deltas in the palette. This reduces storage needs since the + // palette is stored with delta encoding. + for (i = 0; i < num_colors; ++i) { + int best_ix = i; + uint32_t best_score = ~0U; + for (k = i; k < num_colors; ++k) { + const uint32_t cur_score = PaletteColorDistance(palette[k], predict); + if (best_score > cur_score) { + best_score = cur_score; + best_ix = k; + } + } + SwapColor(&palette[best_ix], &palette[i]); + predict = palette[i]; + } +} + +// ----------------------------------------------------------------------------- +// Modified Zeng method from "A Survey on Palette Reordering +// Methods for Improving the Compression of Color-Indexed Images" by Armando J. +// Pinho and Antonio J. R. Neves. + +// Finds the biggest cooccurrence in the matrix. +static void CoOccurrenceFindMax(const uint32_t* const cooccurrence, + uint32_t num_colors, uint8_t* const c1, + uint8_t* const c2) { + // Find the index that is most frequently located adjacent to other + // (different) indexes. + uint32_t best_sum = 0u; + uint32_t i, j, best_cooccurrence; + *c1 = 0u; + for (i = 0; i < num_colors; ++i) { + uint32_t sum = 0; + for (j = 0; j < num_colors; ++j) sum += cooccurrence[i * num_colors + j]; + if (sum > best_sum) { + best_sum = sum; + *c1 = i; + } + } + // Find the index that is most frequently found adjacent to *c1. + *c2 = 0u; + best_cooccurrence = 0u; + for (i = 0; i < num_colors; ++i) { + if (cooccurrence[*c1 * num_colors + i] > best_cooccurrence) { + best_cooccurrence = cooccurrence[*c1 * num_colors + i]; + *c2 = i; + } + } + assert(*c1 != *c2); +} + +// Builds the cooccurrence matrix +static int CoOccurrenceBuild(const WebPPicture* const pic, + const uint32_t* const palette, uint32_t num_colors, + uint32_t* cooccurrence) { + uint32_t *lines, *line_top, *line_current, *line_tmp; + int x, y; + const uint32_t* src = pic->argb; + uint32_t prev_pix = ~src[0]; + uint32_t prev_idx = 0u; + uint32_t idx_map[MAX_PALETTE_SIZE] = {0}; + uint32_t palette_sorted[MAX_PALETTE_SIZE]; + lines = (uint32_t*)WebPSafeMalloc(2 * pic->width, sizeof(*lines)); + if (lines == NULL) { + return 0; + } + line_top = &lines[0]; + line_current = &lines[pic->width]; + PrepareMapToPalette(palette, num_colors, palette_sorted, idx_map); + for (y = 0; y < pic->height; ++y) { + for (x = 0; x < pic->width; ++x) { + const uint32_t pix = src[x]; + if (pix != prev_pix) { + prev_idx = idx_map[SearchColorNoIdx(palette_sorted, pix, num_colors)]; + prev_pix = pix; + } + line_current[x] = prev_idx; + // 4-connectivity is what works best as mentioned in "On the relation + // between Memon's and the modified Zeng's palette reordering methods". + if (x > 0 && prev_idx != line_current[x - 1]) { + const uint32_t left_idx = line_current[x - 1]; + ++cooccurrence[prev_idx * num_colors + left_idx]; + ++cooccurrence[left_idx * num_colors + prev_idx]; + } + if (y > 0 && prev_idx != line_top[x]) { + const uint32_t top_idx = line_top[x]; + ++cooccurrence[prev_idx * num_colors + top_idx]; + ++cooccurrence[top_idx * num_colors + prev_idx]; + } + } + line_tmp = line_top; + line_top = line_current; + line_current = line_tmp; + src += pic->argb_stride; + } + WebPSafeFree(lines); + return 1; +} + +struct Sum { + uint8_t index; + uint32_t sum; +}; + +static int PaletteSortModifiedZeng(const WebPPicture* const pic, + const uint32_t* const palette_in, + uint32_t num_colors, + uint32_t* const palette) { + uint32_t i, j, ind; + uint8_t remapping[MAX_PALETTE_SIZE]; + uint32_t* cooccurrence; + struct Sum sums[MAX_PALETTE_SIZE]; + uint32_t first, last; + uint32_t num_sums; + // TODO(vrabaud) check whether one color images should use palette or not. + if (num_colors <= 1) return 1; + // Build the co-occurrence matrix. + cooccurrence = + (uint32_t*)WebPSafeCalloc(num_colors * num_colors, sizeof(*cooccurrence)); + if (cooccurrence == NULL) { + return 0; + } + if (!CoOccurrenceBuild(pic, palette_in, num_colors, cooccurrence)) { + WebPSafeFree(cooccurrence); + return 0; + } + + // Initialize the mapping list with the two best indices. + CoOccurrenceFindMax(cooccurrence, num_colors, &remapping[0], &remapping[1]); + + // We need to append and prepend to the list of remapping. To this end, we + // actually define the next start/end of the list as indices in a vector (with + // a wrap around when the end is reached). + first = 0; + last = 1; + num_sums = num_colors - 2; // -2 because we know the first two values + if (num_sums > 0) { + // Initialize the sums with the first two remappings and find the best one + struct Sum* best_sum = &sums[0]; + best_sum->index = 0u; + best_sum->sum = 0u; + for (i = 0, j = 0; i < num_colors; ++i) { + if (i == remapping[0] || i == remapping[1]) continue; + sums[j].index = i; + sums[j].sum = cooccurrence[i * num_colors + remapping[0]] + + cooccurrence[i * num_colors + remapping[1]]; + if (sums[j].sum > best_sum->sum) best_sum = &sums[j]; + ++j; + } + + while (num_sums > 0) { + const uint8_t best_index = best_sum->index; + // Compute delta to know if we need to prepend or append the best index. + int32_t delta = 0; + const int32_t n = num_colors - num_sums; + for (ind = first, j = 0; (ind + j) % num_colors != last + 1; ++j) { + const uint16_t l_j = remapping[(ind + j) % num_colors]; + delta += (n - 1 - 2 * (int32_t)j) * + (int32_t)cooccurrence[best_index * num_colors + l_j]; + } + if (delta > 0) { + first = (first == 0) ? num_colors - 1 : first - 1; + remapping[first] = best_index; + } else { + ++last; + remapping[last] = best_index; + } + // Remove best_sum from sums. + *best_sum = sums[num_sums - 1]; + --num_sums; + // Update all the sums and find the best one. + best_sum = &sums[0]; + for (i = 0; i < num_sums; ++i) { + sums[i].sum += cooccurrence[best_index * num_colors + sums[i].index]; + if (sums[i].sum > best_sum->sum) best_sum = &sums[i]; + } + } + } + assert((last + 1) % num_colors == first); + WebPSafeFree(cooccurrence); + + // Re-map the palette. + for (i = 0; i < num_colors; ++i) { + palette[i] = palette_in[remapping[(first + i) % num_colors]]; + } + return 1; +} + +// ----------------------------------------------------------------------------- + +int PaletteSort(PaletteSorting method, const struct WebPPicture* const pic, + const uint32_t* const palette_sorted, uint32_t num_colors, + uint32_t* const palette) { + switch (method) { + case kSortedDefault: + // Nothing to do, we have already sorted the palette. + memcpy(palette, palette_sorted, num_colors * sizeof(*palette)); + return 1; + case kMinimizeDelta: + PaletteSortMinimizeDeltas(palette_sorted, num_colors, palette); + return 1; + case kModifiedZeng: + return PaletteSortModifiedZeng(pic, palette_sorted, num_colors, palette); + case kUnusedPalette: + case kPaletteSortingNum: + break; + } + + assert(0); + return 0; +} diff --git a/libwebp_src/src/utils/palette.h b/libwebp_src/src/utils/palette.h new file mode 100644 index 0000000..34479e4 --- /dev/null +++ b/libwebp_src/src/utils/palette.h @@ -0,0 +1,60 @@ +// Copyright 2023 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for palette analysis. +// +// Author: Vincent Rabaud (vrabaud@google.com) + +#ifndef WEBP_UTILS_PALETTE_H_ +#define WEBP_UTILS_PALETTE_H_ + +#include "src/webp/types.h" + +struct WebPPicture; + +// The different ways a palette can be sorted. +typedef enum PaletteSorting { + kSortedDefault = 0, + // Sorts by minimizing L1 deltas between consecutive colors, giving more + // weight to RGB colors. + kMinimizeDelta = 1, + // Implements the modified Zeng method from "A Survey on Palette Reordering + // Methods for Improving the Compression of Color-Indexed Images" by Armando + // J. Pinho and Antonio J. R. Neves. + kModifiedZeng = 2, + kUnusedPalette = 3, + kPaletteSortingNum = 4 +} PaletteSorting; + +// Returns the index of 'color' in the sorted palette 'sorted' of size +// 'num_colors'. +int SearchColorNoIdx(const uint32_t sorted[], uint32_t color, int num_colors); + +// Sort palette in increasing order and prepare an inverse mapping array. +void PrepareMapToPalette(const uint32_t palette[], uint32_t num_colors, + uint32_t sorted[], uint32_t idx_map[]); + +// Returns count of unique colors in 'pic', assuming pic->use_argb is true. +// If the unique color count is more than MAX_PALETTE_SIZE, returns +// MAX_PALETTE_SIZE+1. +// If 'palette' is not NULL and the number of unique colors is less than or +// equal to MAX_PALETTE_SIZE, also outputs the actual unique colors into +// 'palette' in a sorted order. Note: 'palette' is assumed to be an array +// already allocated with at least MAX_PALETTE_SIZE elements. +int GetColorPalette(const struct WebPPicture* const pic, + uint32_t* const palette); + +// Sorts the palette according to the criterion defined by 'method'. +// 'palette_sorted' is the input palette sorted lexicographically, as done in +// PrepareMapToPalette. Returns 0 on memory allocation error. +int PaletteSort(PaletteSorting method, const struct WebPPicture* const pic, + const uint32_t* const palette_sorted, uint32_t num_colors, + uint32_t* const palette); + +#endif // WEBP_UTILS_PALETTE_H_ diff --git a/libwebp_src/src/utils/utils.c b/libwebp_src/src/utils/utils.c index a7c3a70..408ce88 100644 --- a/libwebp_src/src/utils/utils.c +++ b/libwebp_src/src/utils/utils.c @@ -11,13 +11,13 @@ // // Author: Skal (pascal.massimino@gmail.com) +#include "src/utils/utils.h" + #include #include // for memcpy() -#include "src/webp/decode.h" + +#include "src/utils/palette.h" #include "src/webp/encode.h" -#include "src/webp/format_constants.h" // for MAX_PALETTE_SIZE -#include "src/utils/color_cache_utils.h" -#include "src/utils/utils.h" // If PRINT_MEM_INFO is defined, extra info (like total memory used, number of // alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, @@ -252,66 +252,10 @@ void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) { //------------------------------------------------------------------------------ -#define COLOR_HASH_SIZE (MAX_PALETTE_SIZE * 4) -#define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE). - int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { - int i; - int x, y; - int num_colors = 0; - uint8_t in_use[COLOR_HASH_SIZE] = { 0 }; - uint32_t colors[COLOR_HASH_SIZE]; - const uint32_t* argb = pic->argb; - const int width = pic->width; - const int height = pic->height; - uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] - assert(pic != NULL); - assert(pic->use_argb); - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - int key; - if (argb[x] == last_pix) { - continue; - } - last_pix = argb[x]; - key = VP8LHashPix(last_pix, COLOR_HASH_RIGHT_SHIFT); - while (1) { - if (!in_use[key]) { - colors[key] = last_pix; - in_use[key] = 1; - ++num_colors; - if (num_colors > MAX_PALETTE_SIZE) { - return MAX_PALETTE_SIZE + 1; // Exact count not needed. - } - break; - } else if (colors[key] == last_pix) { - break; // The color is already there. - } else { - // Some other color sits here, so do linear conflict resolution. - ++key; - key &= (COLOR_HASH_SIZE - 1); // Key mask. - } - } - } - argb += pic->argb_stride; - } - - if (palette != NULL) { // Fill the colors into palette. - num_colors = 0; - for (i = 0; i < COLOR_HASH_SIZE; ++i) { - if (in_use[i]) { - palette[num_colors] = colors[i]; - ++num_colors; - } - } - } - return num_colors; + return GetColorPalette(pic, palette); } -#undef COLOR_HASH_SIZE -#undef COLOR_HASH_RIGHT_SHIFT - //------------------------------------------------------------------------------ #if defined(WEBP_NEED_LOG_TABLE_8BIT) diff --git a/libwebp_src/src/utils/utils.h b/libwebp_src/src/utils/utils.h index c5ee873..b2241fb 100644 --- a/libwebp_src/src/utils/utils.h +++ b/libwebp_src/src/utils/utils.h @@ -20,9 +20,7 @@ #endif #include -#include -#include "src/dsp/dsp.h" #include "src/webp/types.h" #ifdef __cplusplus @@ -198,6 +196,7 @@ WEBP_EXTERN void WebPCopyPixels(const struct WebPPicture* const src, // MAX_PALETTE_SIZE, also outputs the actual unique colors into 'palette'. // Note: 'palette' is assumed to be an array already allocated with at least // MAX_PALETTE_SIZE elements. +// TODO(vrabaud) remove whenever we can break the ABI. WEBP_EXTERN int WebPGetColorPalette(const struct WebPPicture* const pic, uint32_t* const palette); diff --git a/libwebp_src/src/webp/decode.h b/libwebp_src/src/webp/decode.h index 0177b12..d6895f5 100644 --- a/libwebp_src/src/webp/decode.h +++ b/libwebp_src/src/webp/decode.h @@ -48,34 +48,33 @@ WEBP_EXTERN int WebPGetDecoderVersion(void); // RIFF + VP8X + (optional chunks) + VP8(L) // ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. // VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. -WEBP_EXTERN int WebPGetInfo(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_NODISCARD WEBP_EXTERN int WebPGetInfo( + const uint8_t* data, size_t data_size, int* width, int* height); // Decodes WebP images pointed to by 'data' and returns RGBA samples, along // with the dimensions in *width and *height. The ordering of samples in // memory is R, G, B, A, R, G, B, A... in scan order (endian-independent). // The returned pointer should be deleted calling WebPFree(). // Returns NULL in case of error. -WEBP_EXTERN uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeRGBA( + const uint8_t* data, size_t data_size, int* width, int* height); // Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data. -WEBP_EXTERN uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeARGB( + const uint8_t* data, size_t data_size, int* width, int* height); // Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data. -WEBP_EXTERN uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeBGRA( + const uint8_t* data, size_t data_size, int* width, int* height); // Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data. // If the bitstream contains transparency, it is ignored. -WEBP_EXTERN uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeRGB( + const uint8_t* data, size_t data_size, int* width, int* height); // Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data. -WEBP_EXTERN uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, - int* width, int* height); - +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeBGR( + const uint8_t* data, size_t data_size, int* width, int* height); // Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer // returned is the Y samples buffer. Upon return, *u and *v will point to @@ -87,10 +86,9 @@ WEBP_EXTERN uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, // 'width' and 'height' may be NULL, the other pointers must not be. // Returns NULL in case of error. // (*) Also named Y'CbCr. See: https://en.wikipedia.org/wiki/YCbCr -WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, - int* width, int* height, - uint8_t** u, uint8_t** v, - int* stride, int* uv_stride); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeYUV( + const uint8_t* data, size_t data_size, int* width, int* height, + uint8_t** u, uint8_t** v, int* stride, int* uv_stride); // These five functions are variants of the above ones, that decode the image // directly into a pre-allocated buffer 'output_buffer'. The maximum storage @@ -100,22 +98,22 @@ WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, // The parameter 'output_stride' specifies the distance (in bytes) // between scanlines. Hence, output_buffer_size is expected to be at least // output_stride x picture-height. -WEBP_EXTERN uint8_t* WebPDecodeRGBAInto( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeRGBAInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN uint8_t* WebPDecodeARGBInto( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeARGBInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN uint8_t* WebPDecodeBGRAInto( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeBGRAInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); // RGB and BGR variants. Here too the transparency information, if present, // will be dropped and ignored. -WEBP_EXTERN uint8_t* WebPDecodeRGBInto( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeRGBInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN uint8_t* WebPDecodeBGRInto( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeBGRInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); @@ -126,7 +124,7 @@ WEBP_EXTERN uint8_t* WebPDecodeBGRInto( // 'u_size' and 'v_size' respectively. // Pointer to the luma plane ('*luma') is returned or NULL if an error occurred // during decoding (or because some buffers were found to be too small). -WEBP_EXTERN uint8_t* WebPDecodeYUVInto( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeYUVInto( const uint8_t* data, size_t data_size, uint8_t* luma, size_t luma_size, int luma_stride, uint8_t* u, size_t u_size, int u_stride, @@ -217,11 +215,11 @@ struct WebPDecBuffer { }; // Internal, version-checked, entry point -WEBP_EXTERN int WebPInitDecBufferInternal(WebPDecBuffer*, int); +WEBP_NODISCARD WEBP_EXTERN int WebPInitDecBufferInternal(WebPDecBuffer*, int); // Initialize the structure as empty. Must be called before any other use. // Returns false in case of version mismatch -static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { +WEBP_NODISCARD static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION); } @@ -232,7 +230,7 @@ WEBP_EXTERN void WebPFreeDecBuffer(WebPDecBuffer* buffer); //------------------------------------------------------------------------------ // Enumeration of the status codes -typedef enum VP8StatusCode { +typedef enum WEBP_NODISCARD VP8StatusCode { VP8_STATUS_OK = 0, VP8_STATUS_OUT_OF_MEMORY, VP8_STATUS_INVALID_PARAM, @@ -251,23 +249,24 @@ typedef enum VP8StatusCode { // WebPIDecoder object. This object can be left in a SUSPENDED state if the // picture is only partially decoded, pending additional input. // Code example: -// -// WebPInitDecBuffer(&output_buffer); -// output_buffer.colorspace = mode; -// ... -// WebPIDecoder* idec = WebPINewDecoder(&output_buffer); -// while (additional_data_is_available) { -// // ... (get additional data in some new_data[] buffer) -// status = WebPIAppend(idec, new_data, new_data_size); -// if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) { -// break; // an error occurred. -// } -// -// // The above call decodes the current available buffer. -// // Part of the image can now be refreshed by calling -// // WebPIDecGetRGB()/WebPIDecGetYUVA() etc. -// } -// WebPIDelete(idec); +/* + WebPInitDecBuffer(&output_buffer); + output_buffer.colorspace = mode; + ... + WebPIDecoder* idec = WebPINewDecoder(&output_buffer); + while (additional_data_is_available) { + // ... (get additional data in some new_data[] buffer) + status = WebPIAppend(idec, new_data, new_data_size); + if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) { + break; // an error occurred. + } + + // The above call decodes the current available buffer. + // Part of the image can now be refreshed by calling + // WebPIDecGetRGB()/WebPIDecGetYUVA() etc. + } + WebPIDelete(idec); +*/ // Creates a new incremental decoder with the supplied buffer parameter. // This output_buffer can be passed NULL, in which case a default output buffer @@ -281,7 +280,8 @@ typedef enum VP8StatusCode { // within valid bounds. // All other fields of WebPDecBuffer MUST remain constant between calls. // Returns NULL if the allocation failed. -WEBP_EXTERN WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer); +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPINewDecoder( + WebPDecBuffer* output_buffer); // This function allocates and initializes an incremental-decoder object, which // will output the RGB/A samples specified by 'csp' into a preallocated @@ -293,7 +293,7 @@ WEBP_EXTERN WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer); // colorspace 'csp' is taken into account for allocating this buffer. All other // parameters are ignored. // Returns NULL if the allocation failed, or if some parameters are invalid. -WEBP_EXTERN WebPIDecoder* WebPINewRGB( +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPINewRGB( WEBP_CSP_MODE csp, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); @@ -308,7 +308,7 @@ WEBP_EXTERN WebPIDecoder* WebPINewRGB( // In this case, the output buffer will be automatically allocated (using // MODE_YUVA) when decoding starts. All parameters are then ignored. // Returns NULL if the allocation failed or if a parameter is invalid. -WEBP_EXTERN WebPIDecoder* WebPINewYUVA( +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPINewYUVA( uint8_t* luma, size_t luma_size, int luma_stride, uint8_t* u, size_t u_size, int u_stride, uint8_t* v, size_t v_size, int v_stride, @@ -316,7 +316,7 @@ WEBP_EXTERN WebPIDecoder* WebPINewYUVA( // Deprecated version of the above, without the alpha plane. // Kept for backward compatibility. -WEBP_EXTERN WebPIDecoder* WebPINewYUV( +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPINewYUV( uint8_t* luma, size_t luma_size, int luma_stride, uint8_t* u, size_t u_size, int u_stride, uint8_t* v, size_t v_size, int v_stride); @@ -346,21 +346,21 @@ WEBP_EXTERN VP8StatusCode WebPIUpdate( // (*last_y, *width etc.) can be NULL if corresponding information is not // needed. The values in these pointers are only valid on successful (non-NULL) // return. -WEBP_EXTERN uint8_t* WebPIDecGetRGB( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPIDecGetRGB( const WebPIDecoder* idec, int* last_y, int* width, int* height, int* stride); // Same as above function to get a YUVA image. Returns pointer to the luma // plane or NULL in case of error. If there is no alpha information // the alpha pointer '*a' will be returned NULL. -WEBP_EXTERN uint8_t* WebPIDecGetYUVA( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPIDecGetYUVA( const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, uint8_t** a, int* width, int* height, int* stride, int* uv_stride, int* a_stride); // Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the // alpha information (if present). Kept for backward compatibility. -static WEBP_INLINE uint8_t* WebPIDecGetYUV( +WEBP_NODISCARD static WEBP_INLINE uint8_t* WebPIDecGetYUV( const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, int* width, int* height, int* stride, int* uv_stride) { return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height, @@ -373,7 +373,7 @@ static WEBP_INLINE uint8_t* WebPIDecGetYUV( // Returns NULL in case the incremental decoder object is in an invalid state. // Otherwise returns the pointer to the internal representation. This structure // is read-only, tied to WebPIDecoder's lifespan and should not be modified. -WEBP_EXTERN const WebPDecBuffer* WebPIDecodedArea( +WEBP_NODISCARD WEBP_EXTERN const WebPDecBuffer* WebPIDecodedArea( const WebPIDecoder* idec, int* left, int* top, int* width, int* height); //------------------------------------------------------------------------------ @@ -389,7 +389,7 @@ WEBP_EXTERN const WebPDecBuffer* WebPIDecodedArea( CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); // C) Adjust 'config', if needed - config.no_fancy_upsampling = 1; + config.options.no_fancy_upsampling = 1; config.output.colorspace = MODE_BGRA; // etc. @@ -468,12 +468,14 @@ struct WebPDecoderConfig { }; // Internal, version-checked, entry point -WEBP_EXTERN int WebPInitDecoderConfigInternal(WebPDecoderConfig*, int); +WEBP_NODISCARD WEBP_EXTERN int WebPInitDecoderConfigInternal(WebPDecoderConfig*, + int); // Initialize the configuration as empty. This function must always be // called first, unless WebPGetFeatures() is to be called. // Returns false in case of mismatched version. -static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { +WEBP_NODISCARD static WEBP_INLINE int WebPInitDecoderConfig( + WebPDecoderConfig* config) { return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION); } @@ -488,8 +490,8 @@ static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { // The return WebPIDecoder object must always be deleted calling WebPIDelete(). // Returns NULL in case of error (and config->status will then reflect // the error condition, if available). -WEBP_EXTERN WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config); +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPIDecode( + const uint8_t* data, size_t data_size, WebPDecoderConfig* config); // Non-incremental version. This version decodes the full data at once, taking // 'config' into account. Returns decoding status (which should be VP8_STATUS_OK diff --git a/libwebp_src/src/webp/demux.h b/libwebp_src/src/webp/demux.h index 846eeb1..8d24655 100644 --- a/libwebp_src/src/webp/demux.h +++ b/libwebp_src/src/webp/demux.h @@ -50,6 +50,7 @@ #include "./decode.h" // for WEBP_CSP_MODE #include "./mux_types.h" +#include "./types.h" #ifdef __cplusplus extern "C" { @@ -85,13 +86,13 @@ typedef enum WebPDemuxState { } WebPDemuxState; // Internal, version-checked, entry point -WEBP_EXTERN WebPDemuxer* WebPDemuxInternal( +WEBP_NODISCARD WEBP_EXTERN WebPDemuxer* WebPDemuxInternal( const WebPData*, int, WebPDemuxState*, int); // Parses the full WebP file given by 'data'. For single images the WebP file // header alone or the file header and the chunk header may be absent. // Returns a WebPDemuxer object on successful parse, NULL otherwise. -static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { +WEBP_NODISCARD static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); } @@ -103,7 +104,7 @@ static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { // If this data is volatile, the demuxer object should be deleted (by calling // WebPDemuxDelete()) and WebPDemuxPartial() called again on the new data. // This is usually an inexpensive operation. -static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( +WEBP_NODISCARD static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( const WebPData* data, WebPDemuxState* state) { return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION); } @@ -164,14 +165,14 @@ struct WebPIterator { // Returns false if 'dmux' is NULL or frame 'frame_number' is not present. // Call WebPDemuxReleaseIterator() when use of the iterator is complete. // NOTE: 'dmux' must persist for the lifetime of 'iter'. -WEBP_EXTERN int WebPDemuxGetFrame( +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxGetFrame( const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); // Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or // previous ('iter->frame_num' - 1) frame. These functions do not loop. // Returns true on success, false otherwise. -WEBP_EXTERN int WebPDemuxNextFrame(WebPIterator* iter); -WEBP_EXTERN int WebPDemuxPrevFrame(WebPIterator* iter); +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxNextFrame(WebPIterator* iter); +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxPrevFrame(WebPIterator* iter); // Releases any memory associated with 'iter'. // Must be called before any subsequent calls to WebPDemuxGetChunk() on the same @@ -202,15 +203,16 @@ struct WebPChunkIterator { // payloads are accessed through WebPDemuxGetFrame() and related functions. // Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. // NOTE: 'dmux' must persist for the lifetime of the iterator. -WEBP_EXTERN int WebPDemuxGetChunk(const WebPDemuxer* dmux, - const char fourcc[4], int chunk_number, - WebPChunkIterator* iter); +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxGetChunk(const WebPDemuxer* dmux, + const char fourcc[4], + int chunk_number, + WebPChunkIterator* iter); // Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous // ('iter->chunk_num' - 1) chunk. These functions do not loop. // Returns true on success, false otherwise. -WEBP_EXTERN int WebPDemuxNextChunk(WebPChunkIterator* iter); -WEBP_EXTERN int WebPDemuxPrevChunk(WebPChunkIterator* iter); +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxNextChunk(WebPChunkIterator* iter); +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxPrevChunk(WebPChunkIterator* iter); // Releases any memory associated with 'iter'. // Must be called before destroying the associated WebPDemuxer with @@ -257,21 +259,21 @@ struct WebPAnimDecoderOptions { }; // Internal, version-checked, entry point. -WEBP_EXTERN int WebPAnimDecoderOptionsInitInternal( +WEBP_NODISCARD WEBP_EXTERN int WebPAnimDecoderOptionsInitInternal( WebPAnimDecoderOptions*, int); // Should always be called, to initialize a fresh WebPAnimDecoderOptions // structure before modification. Returns false in case of version mismatch. // WebPAnimDecoderOptionsInit() must have succeeded before using the // 'dec_options' object. -static WEBP_INLINE int WebPAnimDecoderOptionsInit( +WEBP_NODISCARD static WEBP_INLINE int WebPAnimDecoderOptionsInit( WebPAnimDecoderOptions* dec_options) { return WebPAnimDecoderOptionsInitInternal(dec_options, WEBP_DEMUX_ABI_VERSION); } // Internal, version-checked, entry point. -WEBP_EXTERN WebPAnimDecoder* WebPAnimDecoderNewInternal( +WEBP_NODISCARD WEBP_EXTERN WebPAnimDecoder* WebPAnimDecoderNewInternal( const WebPData*, const WebPAnimDecoderOptions*, int); // Creates and initializes a WebPAnimDecoder object. @@ -284,7 +286,7 @@ WEBP_EXTERN WebPAnimDecoder* WebPAnimDecoderNewInternal( // Returns: // A pointer to the newly created WebPAnimDecoder object, or NULL in case of // parsing error, invalid option or memory error. -static WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew( +WEBP_NODISCARD static WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew( const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options) { return WebPAnimDecoderNewInternal(webp_data, dec_options, WEBP_DEMUX_ABI_VERSION); @@ -306,8 +308,8 @@ struct WebPAnimInfo { // info - (out) global information fetched from the animation. // Returns: // True on success. -WEBP_EXTERN int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, - WebPAnimInfo* info); +WEBP_NODISCARD WEBP_EXTERN int WebPAnimDecoderGetInfo( + const WebPAnimDecoder* dec, WebPAnimInfo* info); // Fetch the next frame from 'dec' based on options supplied to // WebPAnimDecoderNew(). This will be a fully reconstructed canvas of size @@ -321,8 +323,9 @@ WEBP_EXTERN int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, // Returns: // False if any of the arguments are NULL, or if there is a parsing or // decoding error, or if there are no more frames. Otherwise, returns true. -WEBP_EXTERN int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, - uint8_t** buf, int* timestamp); +WEBP_NODISCARD WEBP_EXTERN int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, + uint8_t** buf, + int* timestamp); // Check if there are more frames left to decode. // Parameters: @@ -330,7 +333,8 @@ WEBP_EXTERN int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, // Returns: // True if 'dec' is not NULL and some frames are yet to be decoded. // Otherwise, returns false. -WEBP_EXTERN int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec); +WEBP_NODISCARD WEBP_EXTERN int WebPAnimDecoderHasMoreFrames( + const WebPAnimDecoder* dec); // Resets the WebPAnimDecoder object, so that next call to // WebPAnimDecoderGetNext() will restart decoding from 1st frame. This would be @@ -348,7 +352,7 @@ WEBP_EXTERN void WebPAnimDecoderReset(WebPAnimDecoder* dec); // // Parameters: // dec - (in) decoder instance from which the demuxer object is to be fetched. -WEBP_EXTERN const WebPDemuxer* WebPAnimDecoderGetDemuxer( +WEBP_NODISCARD WEBP_EXTERN const WebPDemuxer* WebPAnimDecoderGetDemuxer( const WebPAnimDecoder* dec); // Deletes the WebPAnimDecoder object. diff --git a/libwebp_src/src/webp/encode.h b/libwebp_src/src/webp/encode.h index 56b68e2..f3d5929 100644 --- a/libwebp_src/src/webp/encode.h +++ b/libwebp_src/src/webp/encode.h @@ -164,13 +164,14 @@ typedef enum WebPPreset { } WebPPreset; // Internal, version-checked, entry point -WEBP_EXTERN int WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int); +WEBP_NODISCARD WEBP_EXTERN int WebPConfigInitInternal(WebPConfig*, WebPPreset, + float, int); // Should always be called, to initialize a fresh WebPConfig structure before // modification. Returns false in case of version mismatch. WebPConfigInit() // must have succeeded before using the 'config' object. // Note that the default values are lossless=0 and quality=75. -static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { +WEBP_NODISCARD static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f, WEBP_ENCODER_ABI_VERSION); } @@ -179,8 +180,9 @@ static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { // set of parameters (referred to by 'preset') and a given quality factor. // This function can be called as a replacement to WebPConfigInit(). Will // return false in case of error. -static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, - WebPPreset preset, float quality) { +WEBP_NODISCARD static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, + WebPPreset preset, + float quality) { return WebPConfigInitInternal(config, preset, quality, WEBP_ENCODER_ABI_VERSION); } @@ -191,11 +193,12 @@ static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, // speed and final compressed size. // This function will overwrite several fields from config: 'method', 'quality' // and 'lossless'. Returns false in case of parameter error. -WEBP_EXTERN int WebPConfigLosslessPreset(WebPConfig* config, int level); +WEBP_NODISCARD WEBP_EXTERN int WebPConfigLosslessPreset(WebPConfig* config, + int level); // Returns true if 'config' is non-NULL and all configuration parameters are // within their valid ranges. -WEBP_EXTERN int WebPValidateConfig(const WebPConfig* config); +WEBP_NODISCARD WEBP_EXTERN int WebPValidateConfig(const WebPConfig* config); //------------------------------------------------------------------------------ // Input / Output @@ -255,8 +258,8 @@ WEBP_EXTERN void WebPMemoryWriterClear(WebPMemoryWriter* writer); // The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon // completion, writer.mem and writer.size will hold the coded data. // writer.mem must be freed by calling WebPMemoryWriterClear. -WEBP_EXTERN int WebPMemoryWrite(const uint8_t* data, size_t data_size, - const WebPPicture* picture); +WEBP_NODISCARD WEBP_EXTERN int WebPMemoryWrite( + const uint8_t* data, size_t data_size, const WebPPicture* picture); // Progress hook, called from time to time to report progress. It can return // false to request an abort of the encoding process, or true otherwise if @@ -364,13 +367,13 @@ struct WebPPicture { }; // Internal, version-checked, entry point -WEBP_EXTERN int WebPPictureInitInternal(WebPPicture*, int); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureInitInternal(WebPPicture*, int); // Should always be called, to initialize the structure. Returns false in case // of version mismatch. WebPPictureInit() must have succeeded before using the // 'picture' object. // Note that, by default, use_argb is false and colorspace is WEBP_YUV420. -static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { +WEBP_NODISCARD static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION); } @@ -381,7 +384,7 @@ static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { // Allocate y/u/v buffers as per colorspace/width/height specification. // Note! This function will free the previous buffer if needed. // Returns false in case of memory error. -WEBP_EXTERN int WebPPictureAlloc(WebPPicture* picture); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureAlloc(WebPPicture* picture); // Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*(). // Note that this function does _not_ free the memory used by the 'picture' @@ -394,7 +397,8 @@ WEBP_EXTERN void WebPPictureFree(WebPPicture* picture); // will fully own the copied pixels (this is not a view). The 'dst' picture need // not be initialized as its content is overwritten. // Returns false in case of memory allocation error. -WEBP_EXTERN int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureCopy(const WebPPicture* src, + WebPPicture* dst); // Compute the single distortion for packed planes of samples. // 'src' will be compared to 'ref', and the raw distortion stored into @@ -403,19 +407,18 @@ WEBP_EXTERN int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); // 'x_step' is the horizontal stride (in bytes) between samples. // 'src/ref_stride' is the byte distance between rows. // Returns false in case of error (bad parameter, memory allocation error, ...). -WEBP_EXTERN int WebPPlaneDistortion(const uint8_t* src, size_t src_stride, - const uint8_t* ref, size_t ref_stride, - int width, int height, - size_t x_step, - int type, // 0 = PSNR, 1 = SSIM, 2 = LSIM - float* distortion, float* result); +WEBP_NODISCARD WEBP_EXTERN int WebPPlaneDistortion( + const uint8_t* src, size_t src_stride, + const uint8_t* ref, size_t ref_stride, int width, int height, size_t x_step, + int type, // 0 = PSNR, 1 = SSIM, 2 = LSIM + float* distortion, float* result); // Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results // are in dB, stored in result[] in the B/G/R/A/All order. The distortion is // always performed using ARGB samples. Hence if the input is YUV(A), the // picture will be internally converted to ARGB (just for the measurement). // Warning: this function is rather CPU-intensive. -WEBP_EXTERN int WebPPictureDistortion( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureDistortion( const WebPPicture* src, const WebPPicture* ref, int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM float result[5]); @@ -428,8 +431,8 @@ WEBP_EXTERN int WebPPictureDistortion( // must be fully be comprised inside the 'src' source picture. If the source // picture uses the YUV420 colorspace, the top and left coordinates will be // snapped to even values. -WEBP_EXTERN int WebPPictureCrop(WebPPicture* picture, - int left, int top, int width, int height); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureCrop( + WebPPicture* picture, int left, int top, int width, int height); // Extracts a view from 'src' picture into 'dst'. The rectangle for the view // is defined by the top-left corner pixel coordinates (left, top) as well @@ -442,9 +445,9 @@ WEBP_EXTERN int WebPPictureCrop(WebPPicture* picture, // with WebPPictureInit() if it is different from 'src', since its content will // be overwritten. // Returns false in case of invalid parameters. -WEBP_EXTERN int WebPPictureView(const WebPPicture* src, - int left, int top, int width, int height, - WebPPicture* dst); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureView( + const WebPPicture* src, int left, int top, int width, int height, + WebPPicture* dst); // Returns true if the 'picture' is actually a view and therefore does // not own the memory for pixels. @@ -455,29 +458,30 @@ WEBP_EXTERN int WebPPictureIsView(const WebPPicture* picture); // dimension will be calculated preserving the aspect ratio. // No gamma correction is applied. // Returns false in case of error (invalid parameter or insufficient memory). -WEBP_EXTERN int WebPPictureRescale(WebPPicture* picture, int width, int height); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureRescale(WebPPicture* picture, + int width, int height); // Colorspace conversion function to import RGB samples. // Previous buffer will be free'd, if any. // *rgb buffer should have a size of at least height * rgb_stride. // Returns false in case of memory error. -WEBP_EXTERN int WebPPictureImportRGB( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportRGB( WebPPicture* picture, const uint8_t* rgb, int rgb_stride); // Same, but for RGBA buffer. -WEBP_EXTERN int WebPPictureImportRGBA( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportRGBA( WebPPicture* picture, const uint8_t* rgba, int rgba_stride); // Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format // input buffer ignoring the alpha channel. Avoids needing to copy the data // to a temporary 24-bit RGB buffer to import the RGB only. -WEBP_EXTERN int WebPPictureImportRGBX( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportRGBX( WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride); // Variants of the above, but taking BGR(A|X) input. -WEBP_EXTERN int WebPPictureImportBGR( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportBGR( WebPPicture* picture, const uint8_t* bgr, int bgr_stride); -WEBP_EXTERN int WebPPictureImportBGRA( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportBGRA( WebPPicture* picture, const uint8_t* bgra, int bgra_stride); -WEBP_EXTERN int WebPPictureImportBGRX( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportBGRX( WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride); // Converts picture->argb data to the YUV420A format. The 'colorspace' @@ -486,24 +490,24 @@ WEBP_EXTERN int WebPPictureImportBGRX( // non-opaque transparent values is detected, and 'colorspace' will be // adjusted accordingly. Note that this method is lossy. // Returns false in case of error. -WEBP_EXTERN int WebPPictureARGBToYUVA(WebPPicture* picture, - WebPEncCSP /*colorspace = WEBP_YUV420*/); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureARGBToYUVA( + WebPPicture* picture, WebPEncCSP /*colorspace = WEBP_YUV420*/); // Same as WebPPictureARGBToYUVA(), but the conversion is done using // pseudo-random dithering with a strength 'dithering' between // 0.0 (no dithering) and 1.0 (maximum dithering). This is useful // for photographic picture. -WEBP_EXTERN int WebPPictureARGBToYUVADithered( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureARGBToYUVADithered( WebPPicture* picture, WebPEncCSP colorspace, float dithering); -// Performs 'sharp' RGBA->YUVA420 downsampling and colorspace conversion. +// Performs 'sharp' RGBA->YUVA420 downsampling and colorspace conversion // Downsampling is handled with extra care in case of color clipping. This // method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better // and sharper YUV representation. // Returns false in case of error. -WEBP_EXTERN int WebPPictureSharpARGBToYUVA(WebPPicture* picture); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureSharpARGBToYUVA(WebPPicture* picture); // kept for backward compatibility: -WEBP_EXTERN int WebPPictureSmartARGBToYUVA(WebPPicture* picture); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureSmartARGBToYUVA(WebPPicture* picture); // Converts picture->yuv to picture->argb and sets picture->use_argb to true. // The input format must be YUV_420 or YUV_420A. The conversion from YUV420 to @@ -511,7 +515,7 @@ WEBP_EXTERN int WebPPictureSmartARGBToYUVA(WebPPicture* picture); // Note that the use of this colorspace is discouraged if one has access to the // raw ARGB samples, since using YUV420 is comparatively lossy. // Returns false in case of error. -WEBP_EXTERN int WebPPictureYUVAToARGB(WebPPicture* picture); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureYUVAToARGB(WebPPicture* picture); // Helper function: given a width x height plane of RGBA or YUV(A) samples // clean-up or smoothen the YUV or RGB samples under fully transparent area, @@ -541,7 +545,8 @@ WEBP_EXTERN void WebPBlendAlpha(WebPPicture* picture, uint32_t background_rgb); // the former for lossy encoding, and the latter for lossless encoding // (when config.lossless is true). Automatic conversion from one format to // another is provided but they both incur some loss. -WEBP_EXTERN int WebPEncode(const WebPConfig* config, WebPPicture* picture); +WEBP_NODISCARD WEBP_EXTERN int WebPEncode(const WebPConfig* config, + WebPPicture* picture); //------------------------------------------------------------------------------ diff --git a/libwebp_src/src/webp/mux.h b/libwebp_src/src/webp/mux.h index 7d27489..8fb067e 100644 --- a/libwebp_src/src/webp/mux.h +++ b/libwebp_src/src/webp/mux.h @@ -16,12 +16,13 @@ #define WEBP_WEBP_MUX_H_ #include "./mux_types.h" +#include "./types.h" #ifdef __cplusplus extern "C" { #endif -#define WEBP_MUX_ABI_VERSION 0x0108 // MAJOR(8b) + MINOR(8b) +#define WEBP_MUX_ABI_VERSION 0x0109 // MAJOR(8b) + MINOR(8b) //------------------------------------------------------------------------------ // Mux API @@ -70,7 +71,7 @@ typedef struct WebPMuxAnimParams WebPMuxAnimParams; typedef struct WebPAnimEncoderOptions WebPAnimEncoderOptions; // Error codes -typedef enum WebPMuxError { +typedef enum WEBP_NODISCARD WebPMuxError { WEBP_MUX_OK = 1, WEBP_MUX_NOT_FOUND = 0, WEBP_MUX_INVALID_ARGUMENT = -1, @@ -104,13 +105,13 @@ WEBP_EXTERN int WebPGetMuxVersion(void); // Life of a Mux object // Internal, version-checked, entry point -WEBP_EXTERN WebPMux* WebPNewInternal(int); +WEBP_NODISCARD WEBP_EXTERN WebPMux* WebPNewInternal(int); // Creates an empty mux object. // Returns: // A pointer to the newly created empty mux object. // Or NULL in case of memory error. -static WEBP_INLINE WebPMux* WebPMuxNew(void) { +WEBP_NODISCARD static WEBP_INLINE WebPMux* WebPMuxNew(void) { return WebPNewInternal(WEBP_MUX_ABI_VERSION); } @@ -123,18 +124,21 @@ WEBP_EXTERN void WebPMuxDelete(WebPMux* mux); // Mux creation. // Internal, version-checked, entry point -WEBP_EXTERN WebPMux* WebPMuxCreateInternal(const WebPData*, int, int); +WEBP_NODISCARD WEBP_EXTERN WebPMux* WebPMuxCreateInternal(const WebPData*, int, + int); // Creates a mux object from raw data given in WebP RIFF format. // Parameters: // bitstream - (in) the bitstream data in WebP RIFF format // copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist for the lifetime of the +// mux object. // Returns: // A pointer to the mux object created from given data - on success. // NULL - In case of invalid data or memory error. -static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream, - int copy_data) { +WEBP_NODISCARD static WEBP_INLINE WebPMux* WebPMuxCreate( + const WebPData* bitstream, int copy_data) { return WebPMuxCreateInternal(bitstream, copy_data, WEBP_MUX_ABI_VERSION); } @@ -154,7 +158,9 @@ static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream, // e.g., "ICCP", "XMP ", "EXIF" etc. // chunk_data - (in) the chunk data to be added // copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist until a call to +// WebPMuxAssemble() is made. // Returns: // WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL // or if fourcc corresponds to an image chunk. @@ -217,7 +223,9 @@ struct WebPMuxFrameInfo { // bitstream - (in) can be a raw VP8/VP8L bitstream or a single-image // WebP file (non-animated) // copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist until a call to +// WebPMuxAssemble() is made. // Returns: // WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL. // WEBP_MUX_MEMORY_ERROR - on memory allocation error. @@ -235,7 +243,9 @@ WEBP_EXTERN WebPMuxError WebPMuxSetImage( // mux - (in/out) object to which the frame is to be added // frame - (in) frame data. // copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist until a call to +// WebPMuxAssemble() is made. // Returns: // WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL // or if content of 'frame' is invalid. @@ -449,7 +459,7 @@ WEBP_EXTERN int WebPAnimEncoderOptionsInitInternal( // structure before modification. Returns false in case of version mismatch. // WebPAnimEncoderOptionsInit() must have succeeded before using the // 'enc_options' object. -static WEBP_INLINE int WebPAnimEncoderOptionsInit( +WEBP_NODISCARD static WEBP_INLINE int WebPAnimEncoderOptionsInit( WebPAnimEncoderOptions* enc_options) { return WebPAnimEncoderOptionsInitInternal(enc_options, WEBP_MUX_ABI_VERSION); } @@ -490,7 +500,7 @@ static WEBP_INLINE WebPAnimEncoder* WebPAnimEncoderNew( // Returns: // On error, returns false and frame->error_code is set appropriately. // Otherwise, returns true. -WEBP_EXTERN int WebPAnimEncoderAdd( +WEBP_NODISCARD WEBP_EXTERN int WebPAnimEncoderAdd( WebPAnimEncoder* enc, struct WebPPicture* frame, int timestamp_ms, const struct WebPConfig* config); @@ -503,8 +513,8 @@ WEBP_EXTERN int WebPAnimEncoderAdd( // webp_data - (out) generated WebP bitstream. // Returns: // True on success. -WEBP_EXTERN int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, - WebPData* webp_data); +WEBP_NODISCARD WEBP_EXTERN int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, + WebPData* webp_data); // Get error string corresponding to the most recent call using 'enc'. The // returned string is owned by 'enc' and is valid only until the next call to @@ -521,6 +531,57 @@ WEBP_EXTERN const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc); // enc - (in/out) object to be deleted WEBP_EXTERN void WebPAnimEncoderDelete(WebPAnimEncoder* enc); +//------------------------------------------------------------------------------ +// Non-image chunks. + +// Note: Only non-image related chunks should be managed through chunk APIs. +// (Image related chunks are: "ANMF", "VP8 ", "VP8L" and "ALPH"). + +// Adds a chunk with id 'fourcc' and data 'chunk_data' in the enc object. +// Any existing chunk(s) with the same id will be removed. +// Parameters: +// enc - (in/out) object to which the chunk is to be added +// fourcc - (in) a character array containing the fourcc of the given chunk; +// e.g., "ICCP", "XMP ", "EXIF", etc. +// chunk_data - (in) the chunk data to be added +// copy_data - (in) value 1 indicates given data WILL be copied to the enc +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist until a call to +// WebPAnimEncoderAssemble() is made. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if enc, fourcc or chunk_data is NULL. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPAnimEncoderSetChunk( + WebPAnimEncoder* enc, const char fourcc[4], const WebPData* chunk_data, + int copy_data); + +// Gets a reference to the data of the chunk with id 'fourcc' in the enc object. +// The caller should NOT free the returned data. +// Parameters: +// enc - (in) object from which the chunk data is to be fetched +// fourcc - (in) a character array containing the fourcc of the chunk; +// e.g., "ICCP", "XMP ", "EXIF", etc. +// chunk_data - (out) returned chunk data +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if enc, fourcc or chunk_data is NULL. +// WEBP_MUX_NOT_FOUND - If enc does not contain a chunk with the given id. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPAnimEncoderGetChunk( + const WebPAnimEncoder* enc, const char fourcc[4], WebPData* chunk_data); + +// Deletes the chunk with the given 'fourcc' from the enc object. +// Parameters: +// enc - (in/out) object from which the chunk is to be deleted +// fourcc - (in) a character array containing the fourcc of the chunk; +// e.g., "ICCP", "XMP ", "EXIF", etc. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if enc or fourcc is NULL. +// WEBP_MUX_NOT_FOUND - If enc does not contain a chunk with the given fourcc. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPAnimEncoderDeleteChunk( + WebPAnimEncoder* enc, const char fourcc[4]); + //------------------------------------------------------------------------------ #ifdef __cplusplus diff --git a/libwebp_src/src/webp/mux_types.h b/libwebp_src/src/webp/mux_types.h index 2fe8195..c585d20 100644 --- a/libwebp_src/src/webp/mux_types.h +++ b/libwebp_src/src/webp/mux_types.h @@ -79,7 +79,8 @@ static WEBP_INLINE void WebPDataClear(WebPData* webp_data) { // Allocates necessary storage for 'dst' and copies the contents of 'src'. // Returns true on success. -static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) { +WEBP_NODISCARD static WEBP_INLINE int WebPDataCopy(const WebPData* src, + WebPData* dst) { if (src == NULL || dst == NULL) return 0; WebPDataInit(dst); if (src->bytes != NULL && src->size != 0) { diff --git a/libwebp_src/src/webp/types.h b/libwebp_src/src/webp/types.h index f255432..9c17ede 100644 --- a/libwebp_src/src/webp/types.h +++ b/libwebp_src/src/webp/types.h @@ -36,18 +36,39 @@ typedef long long int int64_t; #define WEBP_INLINE __forceinline #endif /* _MSC_VER */ +#ifndef WEBP_NODISCARD +#if defined(WEBP_ENABLE_NODISCARD) && WEBP_ENABLE_NODISCARD +#if (defined(__cplusplus) && __cplusplus >= 201700L) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) +#define WEBP_NODISCARD [[nodiscard]] +#else +// gcc's __has_attribute does not work for enums. +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(warn_unused_result) +#define WEBP_NODISCARD __attribute__((warn_unused_result)) +#else +#define WEBP_NODISCARD +#endif /* __has_attribute(warn_unused_result) */ +#else +#define WEBP_NODISCARD +#endif /* defined(__clang__) && defined(__has_attribute) */ +#endif /* (defined(__cplusplus) && __cplusplus >= 201700L) || + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) */ +#else +#define WEBP_NODISCARD +#endif /* defined(WEBP_ENABLE_NODISCARD) && WEBP_ENABLE_NODISCARD */ +#endif /* WEBP_NODISCARD */ + #ifndef WEBP_EXTERN // This explicitly marks library functions and allows for changing the // signature for e.g., Windows DLL builds. -# if defined(__GNUC__) && __GNUC__ >= 4 +# if defined(_WIN32) && defined(WEBP_DLL) +# define WEBP_EXTERN __declspec(dllexport) +# elif defined(__GNUC__) && __GNUC__ >= 4 # define WEBP_EXTERN extern __attribute__ ((visibility ("default"))) # else -# if defined(_MSC_VER) && defined(WEBP_DLL) -# define WEBP_EXTERN __declspec(dllexport) -# else -# define WEBP_EXTERN extern -# endif -# endif /* __GNUC__ >= 4 */ +# define WEBP_EXTERN extern +# endif /* defined(_WIN32) && defined(WEBP_DLL) */ #endif /* WEBP_EXTERN */ // Macro to check ABI compatibility (same major revision number) @@ -60,7 +81,7 @@ extern "C" { // Allocates 'size' bytes of memory. Returns NULL upon error. Memory // must be deallocated by calling WebPFree(). This function is made available // by the core 'libwebp' library. -WEBP_EXTERN void* WebPMalloc(size_t size); +WEBP_NODISCARD WEBP_EXTERN void* WebPMalloc(size_t size); // Releases memory returned by the WebPDecode*() functions (from decode.h). WEBP_EXTERN void WebPFree(void* ptr); diff --git a/libwebp_src/swig/README.md b/libwebp_src/swig/README.md deleted file mode 100644 index 7fa1c38..0000000 --- a/libwebp_src/swig/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# SWIG bindings - -## Building - -### JNI SWIG bindings - -```shell - $ gcc -shared -fPIC -fno-strict-aliasing -O2 \ - -I/path/to/your/jdk/includes \ - libwebp_java_wrap.c \ - -lwebp \ - -o libwebp_jni.so -``` - -Example usage: - -```java -import com.google.webp.libwebp; - -import java.lang.reflect.Method; - -public class libwebp_jni_example { - static { - System.loadLibrary("webp_jni"); - } - - /** - * usage: java -cp libwebp.jar:. libwebp_jni_example - */ - public static void main(String argv[]) { - final int version = libwebp.WebPGetDecoderVersion(); - System.out.println("libwebp version: " + Integer.toHexString(version)); - - System.out.println("libwebp methods:"); - final Method[] libwebpMethods = libwebp.class.getDeclaredMethods(); - for (int i = 0; i < libwebpMethods.length; i++) { - System.out.println(libwebpMethods[i]); - } - } -} -``` - -```shell - $ javac -cp libwebp.jar libwebp_jni_example.java - $ java -Djava.library.path=. -cp libwebp.jar:. libwebp_jni_example -``` - -### Python SWIG bindings: - -```shell - $ python setup.py build_ext - $ python setup.py install --prefix=pylocal -``` - -Example usage: - -```python -import glob -import sys -sys.path.append(glob.glob('pylocal/lib/python*/site-packages')[0]) - -from com.google.webp import libwebp -print "libwebp decoder version: %x" % libwebp.WebPGetDecoderVersion() - -print "libwebp attributes:" -for attr in dir(libwebp): print attr -``` diff --git a/libwebp_src/swig/libwebp.go b/libwebp_src/swig/libwebp.go deleted file mode 100644 index df205aa..0000000 --- a/libwebp_src/swig/libwebp.go +++ /dev/null @@ -1,45 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 2.0.10 - * - * This file is not intended to be easily readable and contains a number of - * coding conventions designed to improve portability and efficiency. Do not make - * changes to this file unless you know what you are doing--modify the SWIG - * interface file instead. - * ----------------------------------------------------------------------------- */ - -package libwebp - -import _ "runtime/cgo" -import "unsafe" - -type _ unsafe.Pointer - -type _swig_fnptr *byte -type _swig_memberptr *byte - -//extern libwebpSwigCgocall -func SwigCgocall() - -//extern libwebpSwigCgocallDone -func SwigCgocallDone() - -//extern libwebpSwigCgocallBack -func SwigCgocallBack() - -//extern libwebpSwigCgocallBackDone -func SwigCgocallBackDone() - -func WebPGetDecoderVersion() int -func Wrapped_WebPGetInfo(string, []int, []int) int - -// WebPGetInfo has 2 output parameters, provide a version in the more natural -// go idiom: -func WebPGetInfo(webp []byte) (ok bool, width int, height int) { - w := []int{0} - h := []int{0} - ok = Wrapped_WebPGetInfo(string(webp), w, h) != 0 - width = w[0] - height = h[0] - return -} diff --git a/libwebp_src/swig/libwebp.jar b/libwebp_src/swig/libwebp.jar deleted file mode 100644 index 2fc502b..0000000 Binary files a/libwebp_src/swig/libwebp.jar and /dev/null differ diff --git a/libwebp_src/swig/libwebp.py b/libwebp_src/swig/libwebp.py deleted file mode 100644 index 2d126b5..0000000 --- a/libwebp_src/swig/libwebp.py +++ /dev/null @@ -1,235 +0,0 @@ -# This file was automatically generated by SWIG (http://www.swig.org). -# Version 3.0.12 -# -# Do not make changes to this file unless you know what you are doing--modify -# the SWIG interface file instead. - -from sys import version_info as _swig_python_version_info -if _swig_python_version_info >= (2, 7, 0): - def swig_import_helper(): - import importlib - pkg = __name__.rpartition('.')[0] - mname = '.'.join((pkg, '_libwebp')).lstrip('.') - try: - return importlib.import_module(mname) - except ImportError: - return importlib.import_module('_libwebp') - _libwebp = swig_import_helper() - del swig_import_helper -elif _swig_python_version_info >= (2, 6, 0): - def swig_import_helper(): - from os.path import dirname - import imp - fp = None - try: - fp, pathname, description = imp.find_module('_libwebp', [dirname(__file__)]) - except ImportError: - import _libwebp - return _libwebp - try: - _mod = imp.load_module('_libwebp', fp, pathname, description) - finally: - if fp is not None: - fp.close() - return _mod - _libwebp = swig_import_helper() - del swig_import_helper -else: - import _libwebp -del _swig_python_version_info - -try: - _swig_property = property -except NameError: - pass # Python < 2.2 doesn't have 'property'. - -try: - import builtins as __builtin__ -except ImportError: - import __builtin__ - -def _swig_setattr_nondynamic(self, class_type, name, value, static=1): - if (name == "thisown"): - return self.this.own(value) - if (name == "this"): - if type(value).__name__ == 'SwigPyObject': - self.__dict__[name] = value - return - method = class_type.__swig_setmethods__.get(name, None) - if method: - return method(self, value) - if (not static): - if _newclass: - object.__setattr__(self, name, value) - else: - self.__dict__[name] = value - else: - raise AttributeError("You cannot add attributes to %s" % self) - - -def _swig_setattr(self, class_type, name, value): - return _swig_setattr_nondynamic(self, class_type, name, value, 0) - - -def _swig_getattr(self, class_type, name): - if (name == "thisown"): - return self.this.own() - method = class_type.__swig_getmethods__.get(name, None) - if method: - return method(self) - raise AttributeError("'%s' object has no attribute '%s'" % (class_type.__name__, name)) - - -def _swig_repr(self): - try: - strthis = "proxy of " + self.this.__repr__() - except __builtin__.Exception: - strthis = "" - return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) - -try: - _object = object - _newclass = 1 -except __builtin__.Exception: - class _object: - pass - _newclass = 0 - - -def WebPGetDecoderVersion(): - """WebPGetDecoderVersion() -> int""" - return _libwebp.WebPGetDecoderVersion() - -def WebPGetInfo(data): - """WebPGetInfo(uint8_t data) -> (width, height)""" - return _libwebp.WebPGetInfo(data) - -def WebPDecodeRGB(data): - """WebPDecodeRGB(uint8_t data) -> (rgb, width, height)""" - return _libwebp.WebPDecodeRGB(data) - -def WebPDecodeRGBA(data): - """WebPDecodeRGBA(uint8_t data) -> (rgb, width, height)""" - return _libwebp.WebPDecodeRGBA(data) - -def WebPDecodeARGB(data): - """WebPDecodeARGB(uint8_t data) -> (rgb, width, height)""" - return _libwebp.WebPDecodeARGB(data) - -def WebPDecodeBGR(data): - """WebPDecodeBGR(uint8_t data) -> (rgb, width, height)""" - return _libwebp.WebPDecodeBGR(data) - -def WebPDecodeBGRA(data): - """WebPDecodeBGRA(uint8_t data) -> (rgb, width, height)""" - return _libwebp.WebPDecodeBGRA(data) - -def WebPGetEncoderVersion(): - """WebPGetEncoderVersion() -> int""" - return _libwebp.WebPGetEncoderVersion() - -def wrap_WebPEncodeRGB(rgb, unused1, unused2, width, height, stride, quality_factor): - """private, do not call directly.""" - return _libwebp.wrap_WebPEncodeRGB(rgb, unused1, unused2, width, height, stride, quality_factor) - -def wrap_WebPEncodeBGR(rgb, unused1, unused2, width, height, stride, quality_factor): - """private, do not call directly.""" - return _libwebp.wrap_WebPEncodeBGR(rgb, unused1, unused2, width, height, stride, quality_factor) - -def wrap_WebPEncodeRGBA(rgb, unused1, unused2, width, height, stride, quality_factor): - """private, do not call directly.""" - return _libwebp.wrap_WebPEncodeRGBA(rgb, unused1, unused2, width, height, stride, quality_factor) - -def wrap_WebPEncodeBGRA(rgb, unused1, unused2, width, height, stride, quality_factor): - """private, do not call directly.""" - return _libwebp.wrap_WebPEncodeBGRA(rgb, unused1, unused2, width, height, stride, quality_factor) - -def wrap_WebPEncodeLosslessRGB(rgb, unused1, unused2, width, height, stride): - """private, do not call directly.""" - return _libwebp.wrap_WebPEncodeLosslessRGB(rgb, unused1, unused2, width, height, stride) - -def wrap_WebPEncodeLosslessBGR(rgb, unused1, unused2, width, height, stride): - """private, do not call directly.""" - return _libwebp.wrap_WebPEncodeLosslessBGR(rgb, unused1, unused2, width, height, stride) - -def wrap_WebPEncodeLosslessRGBA(rgb, unused1, unused2, width, height, stride): - """private, do not call directly.""" - return _libwebp.wrap_WebPEncodeLosslessRGBA(rgb, unused1, unused2, width, height, stride) - -def wrap_WebPEncodeLosslessBGRA(rgb, unused1, unused2, width, height, stride): - """private, do not call directly.""" - return _libwebp.wrap_WebPEncodeLosslessBGRA(rgb, unused1, unused2, width, height, stride) - -_UNUSED = 1 - - -def WebPEncodeRGB(rgb, width, height, stride, quality_factor): - """WebPEncodeRGB(uint8_t rgb, int width, int height, int stride, float quality_factor) -> lossy_webp""" - webp = wrap_WebPEncodeRGB( - rgb, _UNUSED, _UNUSED, width, height, stride, quality_factor) - if len(webp[0]) == 0: - return None - return webp[0] - - -def WebPEncodeRGBA(rgb, width, height, stride, quality_factor): - """WebPEncodeRGBA(uint8_t rgb, int width, int height, int stride, float quality_factor) -> lossy_webp""" - webp = wrap_WebPEncodeRGBA( - rgb, _UNUSED, _UNUSED, width, height, stride, quality_factor) - if len(webp[0]) == 0: - return None - return webp[0] - - -def WebPEncodeBGR(rgb, width, height, stride, quality_factor): - """WebPEncodeBGR(uint8_t rgb, int width, int height, int stride, float quality_factor) -> lossy_webp""" - webp = wrap_WebPEncodeBGR( - rgb, _UNUSED, _UNUSED, width, height, stride, quality_factor) - if len(webp[0]) == 0: - return None - return webp[0] - - -def WebPEncodeBGRA(rgb, width, height, stride, quality_factor): - """WebPEncodeBGRA(uint8_t rgb, int width, int height, int stride, float quality_factor) -> lossy_webp""" - webp = wrap_WebPEncodeBGRA( - rgb, _UNUSED, _UNUSED, width, height, stride, quality_factor) - if len(webp[0]) == 0: - return None - return webp[0] - - -def WebPEncodeLosslessRGB(rgb, width, height, stride): - """WebPEncodeLosslessRGB(uint8_t rgb, int width, int height, int stride) -> lossless_webp""" - webp = wrap_WebPEncodeLosslessRGB(rgb, _UNUSED, _UNUSED, width, height, stride) - if len(webp[0]) == 0: - return None - return webp[0] - - -def WebPEncodeLosslessRGBA(rgb, width, height, stride): - """WebPEncodeLosslessRGBA(uint8_t rgb, int width, int height, int stride) -> lossless_webp""" - webp = wrap_WebPEncodeLosslessRGBA(rgb, _UNUSED, _UNUSED, width, height, stride) - if len(webp[0]) == 0: - return None - return webp[0] - - -def WebPEncodeLosslessBGR(rgb, width, height, stride): - """WebPEncodeLosslessBGR(uint8_t rgb, int width, int height, int stride) -> lossless_webp""" - webp = wrap_WebPEncodeLosslessBGR(rgb, _UNUSED, _UNUSED, width, height, stride) - if len(webp[0]) == 0: - return None - return webp[0] - - -def WebPEncodeLosslessBGRA(rgb, width, height, stride): - """WebPEncodeLosslessBGRA(uint8_t rgb, int width, int height, int stride) -> lossless_webp""" - webp = wrap_WebPEncodeLosslessBGRA(rgb, _UNUSED, _UNUSED, width, height, stride) - if len(webp[0]) == 0: - return None - return webp[0] - -# This file is compatible with both classic and new-style classes. - - diff --git a/libwebp_src/swig/libwebp.swig b/libwebp_src/swig/libwebp.swig deleted file mode 100644 index ca38298..0000000 --- a/libwebp_src/swig/libwebp.swig +++ /dev/null @@ -1,438 +0,0 @@ -// Copyright 2011 Google Inc. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// libwebp swig interface definition -// -// Author: James Zern (jzern@google.com) - -/* - Go bindings: - $ swig -go \ - -outdir . \ - -o libwebp_go_wrap.c libwebp.swig - - Java bindings: - $ mkdir -p java/com/google/webp - $ swig -java \ - -package com.google.webp \ - -outdir java/com/google/webp \ - -o libwebp_java_wrap.c libwebp.swig - - Python bindings: - $ swig -python \ - -outdir . \ - -o libwebp_python_wrap.c libwebp.swig -*/ - -#ifdef SWIGPYTHON -%module(package="com.google.webp") libwebp -%begin %{ -#define SWIG_PYTHON_STRICT_BYTE_CHAR -%} -#else -%module libwebp -#endif /* SWIGPYTHON */ - -%include "constraints.i" -%include "typemaps.i" - -#ifdef SWIGGO -%apply (char* STRING, size_t LENGTH) { (const uint8_t* data, size_t data_size) } - -%rename(wrapped_WebPGetInfo) WebPGetInfo(const uint8_t* data, size_t data_size, - int* width, int* height); -#endif /* SWIGGO */ - -#ifdef SWIGJAVA -%include "arrays_java.i"; -%include "enums.swg" /*NB: requires JDK-1.5+ - See: http://www.swig.org/Doc1.3/Java.html#enumerations */ - -// map uint8_t* such that a byte[] is used -%{ -#include "webp/types.h" -%} -// from arrays_java.i (signed char) -JAVA_ARRAYS_DECL(uint8_t, jbyte, Byte, Uint8) -JAVA_ARRAYS_IMPL(uint8_t, jbyte, Byte, Uint8) -JAVA_ARRAYS_TYPEMAPS(uint8_t, byte, jbyte, Uint8, "[B") -%apply uint8_t[] { uint8_t* } -#endif /* SWIGJAVA */ - -#ifdef SWIGPYTHON -%apply (char* STRING, size_t LENGTH) { (const uint8_t* data, size_t data_size) } -%typemap(out) uint8_t* { - $result = PyString_FromStringAndSize( - (const char*)$1, - ($1 == NULL) ? 0 : ReturnedBufferSize("$symname", arg3, arg4)); -} - -%typemap (in) const uint8_t* rgb (Py_buffer rgb_buffer) { - // NB: with Python < 2.6 the old style buffer protocol may be used: - // Py_ssize_t unused; - // PyObject_AsReadBuffer($input, (const void**)(&$1), &unused); - if (!PyObject_CheckBuffer($input)) { - SWIG_exception_fail(SWIG_TypeError, - "in method '$symname', argument $argnum" - " does not support the buffer interface"); - } - if (PyObject_GetBuffer($input, &rgb_buffer, PyBUF_SIMPLE)) { - SWIG_exception_fail(SWIG_RuntimeError, - "in method '$symname', unable to get buffer view"); - } - $1 = ($1_ltype)rgb_buffer.buf; -} - -%typemap(freearg) const uint8_t* rgb { - PyBuffer_Release(&rgb_buffer$argnum); -} - -%define DECODE_AUTODOC(func) -%feature("autodoc", #func "(uint8_t data) -> (rgb, width, height)") func; -%enddef - -%feature("autodoc", "1"); -DECODE_AUTODOC(WebPDecodeRGB); -DECODE_AUTODOC(WebPDecodeRGBA); -DECODE_AUTODOC(WebPDecodeARGB); -DECODE_AUTODOC(WebPDecodeBGR); -DECODE_AUTODOC(WebPDecodeBGRA); -%feature("autodoc", "WebPGetInfo(uint8_t data) -> (width, height)") WebPGetInfo; -#endif /* SWIGPYTHON */ - -//------------------------------------------------------------------------------ -// Decoder specific - -%apply int* OUTPUT { int* width, int* height } - -int WebPGetDecoderVersion(void); -int WebPGetInfo(const uint8_t* data, size_t data_size, - int* width, int* height); - -#if defined(SWIGJAVA) || defined(SWIGPYTHON) - -// free the buffer returned by these functions after copying into -// the native type -%newobject WebPDecodeRGB; -%newobject WebPDecodeRGBA; -%newobject WebPDecodeARGB; -%newobject WebPDecodeBGR; -%newobject WebPDecodeBGRA; -%typemap(newfree) uint8_t* "free($1);" - -uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, - int* width, int* height); -uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, - int* width, int* height); -uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, - int* width, int* height); -uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, - int* width, int* height); -uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, - int* width, int* height); - -#endif /* SWIGJAVA || SWIGPYTHON */ - -//------------------------------------------------------------------------------ -// Encoder specific - -#if defined(SWIGJAVA) || defined(SWIGPYTHON) - -int WebPGetEncoderVersion(void); - -#endif /* SWIGJAVA || SWIGPYTHON */ - -//------------------------------------------------------------------------------ -// Wrapper code additions - -%{ -#include "webp/decode.h" -#include "webp/encode.h" -%} - -#ifdef SWIGJAVA -%{ -#define FillMeInAsSizeCannotBeDeterminedAutomatically \ - (result ? (jint)ReturnedBufferSize(__FUNCTION__, arg3, arg4) : 0) -%} -#endif /* SWIGJAVA */ - -#if defined(SWIGJAVA) || defined(SWIGPYTHON) -%{ -static size_t ReturnedBufferSize( - const char* function, int* width, int* height) { - static const struct sizemap { - const char* function; - int size_multiplier; - } size_map[] = { -#ifdef SWIGJAVA - { "Java_com_google_webp_libwebpJNI_WebPDecodeRGB", 3 }, - { "Java_com_google_webp_libwebpJNI_WebPDecodeRGBA", 4 }, - { "Java_com_google_webp_libwebpJNI_WebPDecodeARGB", 4 }, - { "Java_com_google_webp_libwebpJNI_WebPDecodeBGR", 3 }, - { "Java_com_google_webp_libwebpJNI_WebPDecodeBGRA", 4 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGB", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGR", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGBA", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGRA", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGB", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGR", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGBA", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGRA", 1 }, -#endif -#ifdef SWIGPYTHON - { "WebPDecodeRGB", 3 }, - { "WebPDecodeRGBA", 4 }, - { "WebPDecodeARGB", 4 }, - { "WebPDecodeBGR", 3 }, - { "WebPDecodeBGRA", 4 }, - { "wrap_WebPEncodeRGB", 1 }, - { "wrap_WebPEncodeBGR", 1 }, - { "wrap_WebPEncodeRGBA", 1 }, - { "wrap_WebPEncodeBGRA", 1 }, - { "wrap_WebPEncodeLosslessRGB", 1 }, - { "wrap_WebPEncodeLosslessBGR", 1 }, - { "wrap_WebPEncodeLosslessRGBA", 1 }, - { "wrap_WebPEncodeLosslessBGRA", 1 }, -#endif - { NULL, 0 } - }; - const struct sizemap* p; - size_t size = 0; - - for (p = size_map; p->function; ++p) { - if (!strcmp(function, p->function)) { - size = *width * *height * p->size_multiplier; - break; - } - } - - return size; -} -%} - -%{ -typedef size_t (*WebPEncodeFunction)(const uint8_t* rgb, - int width, int height, int stride, - float quality_factor, uint8_t** output); -typedef size_t (*WebPEncodeLosslessFunction)(const uint8_t* rgb, - int width, int height, int stride, - uint8_t** output); - -static uint8_t* EncodeLossy(const uint8_t* rgb, - int width, int height, int stride, - float quality_factor, - WebPEncodeFunction encfn, - int* output_size, int* unused) { - uint8_t* output = NULL; - const size_t image_size = - encfn(rgb, width, height, stride, quality_factor, &output); - // the values of following two will be interpreted by ReturnedBufferSize() - // as 'width' and 'height' in the size calculation. - *output_size = image_size; - *unused = 1; - return image_size ? output : NULL; -} - -static uint8_t* EncodeLossless(const uint8_t* rgb, - int width, int height, int stride, - WebPEncodeLosslessFunction encfn, - int* output_size, int* unused) { - uint8_t* output = NULL; - const size_t image_size = encfn(rgb, width, height, stride, &output); - // the values of the following two will be interpreted by - // ReturnedBufferSize() as 'width' and 'height' in the size calculation. - *output_size = image_size; - *unused = 1; - return image_size ? output : NULL; -} -%} - -#endif /* SWIGJAVA || SWIGPYTHON */ - -//------------------------------------------------------------------------------ -// libwebp/encode wrapper functions - -#if defined(SWIGJAVA) || defined(SWIGPYTHON) - -%apply int* INPUT { int* unused1, int* unused2 } -%apply int* OUTPUT { int* output_size } - -// free the buffer returned by these functions after copying into -// the native type -%newobject wrap_WebPEncodeRGB; -%newobject wrap_WebPEncodeBGR; -%newobject wrap_WebPEncodeRGBA; -%newobject wrap_WebPEncodeBGRA; -%newobject wrap_WebPEncodeLosslessRGB; -%newobject wrap_WebPEncodeLosslessBGR; -%newobject wrap_WebPEncodeLosslessRGBA; -%newobject wrap_WebPEncodeLosslessBGRA; - -#ifdef SWIGJAVA -// There's no reason to call these directly -%javamethodmodifiers wrap_WebPEncodeRGB "private"; -%javamethodmodifiers wrap_WebPEncodeBGR "private"; -%javamethodmodifiers wrap_WebPEncodeRGBA "private"; -%javamethodmodifiers wrap_WebPEncodeBGRA "private"; -%javamethodmodifiers wrap_WebPEncodeLosslessRGB "private"; -%javamethodmodifiers wrap_WebPEncodeLosslessBGR "private"; -%javamethodmodifiers wrap_WebPEncodeLosslessRGBA "private"; -%javamethodmodifiers wrap_WebPEncodeLosslessBGRA "private"; -#endif /* SWIGJAVA */ - -#ifdef SWIGPYTHON -// This autodoc will serve as a catch-all for wrap_*. -%feature("autodoc", "private, do not call directly."); -#endif - -%inline %{ -// Changes the return type of WebPEncode* to more closely match Decode*. -// This also makes it easier to wrap the output buffer in a native type rather -// than dealing with the return pointer. -// The additional parameters are to allow reuse of ReturnedBufferSize(), -// unused2 and output_size will be used in this case. -#define LOSSY_WRAPPER(FUNC) \ - static uint8_t* wrap_##FUNC( \ - const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \ - int width, int height, int stride, float quality_factor) { \ - return EncodeLossy(rgb, width, height, stride, quality_factor, \ - FUNC, output_size, unused2); \ - } \ - -LOSSY_WRAPPER(WebPEncodeRGB) -LOSSY_WRAPPER(WebPEncodeBGR) -LOSSY_WRAPPER(WebPEncodeRGBA) -LOSSY_WRAPPER(WebPEncodeBGRA) - -#undef LOSSY_WRAPPER - -#define LOSSLESS_WRAPPER(FUNC) \ - static uint8_t* wrap_##FUNC( \ - const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \ - int width, int height, int stride) { \ - return EncodeLossless(rgb, width, height, stride, \ - FUNC, output_size, unused2); \ - } \ - -LOSSLESS_WRAPPER(WebPEncodeLosslessRGB) -LOSSLESS_WRAPPER(WebPEncodeLosslessBGR) -LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA) -LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA) - -#undef LOSSLESS_WRAPPER - -%} - -#endif /* SWIGJAVA || SWIGPYTHON */ - -//------------------------------------------------------------------------------ -// Language specific - -#ifdef SWIGGO -%insert(go_wrapper) %{ - -// WebPGetInfo has 2 output parameters, provide a version in the more natural -// go idiom: -func WebPGetInfo(webp []byte) (ok bool, width int, height int) { - w := []int{0} - h := []int{0} - ok = Wrapped_WebPGetInfo(string(webp), w, h) != 0 - width = w[0] - height = h[0] - return -} - -%} -#endif /* SWIGGO */ - -#ifdef SWIGJAVA -%{ -/* Work around broken gcj jni.h */ -#ifdef __GCJ_JNI_H__ -# undef JNIEXPORT -# define JNIEXPORT -# undef JNICALL -# define JNICALL -#endif -%} - -%pragma(java) modulecode=%{ - private static final int UNUSED = 1; - private static int outputSize[] = { 0 }; -%} - - -%define CALL_ENCODE_LOSSY_WRAPPER(func) -%pragma(java) modulecode=%{ - public static byte[] func( - byte[] rgb, int width, int height, int stride, float quality_factor) { - return wrap_##func( - rgb, UNUSED, UNUSED, outputSize, width, height, stride, quality_factor); - } -%} -%enddef - -%define CALL_ENCODE_LOSSLESS_WRAPPER(func) -%pragma(java) modulecode=%{ - public static byte[] func( - byte[] rgb, int width, int height, int stride) { - return wrap_##func( - rgb, UNUSED, UNUSED, outputSize, width, height, stride); - } -%} -%enddef - -CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeRGB) -CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeRGBA) -CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeBGR) -CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeBGRA) -CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessRGB) -CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA) -CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessBGR) -CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA) -#endif /* SWIGJAVA */ - -#ifdef SWIGPYTHON -%pythoncode %{ -_UNUSED = 1 -%} - -%define CALL_ENCODE_LOSSY_WRAPPER(func) -%pythoncode %{ -def func(rgb, width, height, stride, quality_factor): - """func(uint8_t rgb, int width, int height, int stride, float quality_factor) -> lossy_webp""" - webp = wrap_##func( - rgb, _UNUSED, _UNUSED, width, height, stride, quality_factor) - if len(webp[0]) == 0: - return None - return webp[0] -%} -%enddef - -%define CALL_ENCODE_LOSSLESS_WRAPPER(func) -%pythoncode %{ -def func(rgb, width, height, stride): - """func(uint8_t rgb, int width, int height, int stride) -> lossless_webp""" - webp = wrap_##func(rgb, _UNUSED, _UNUSED, width, height, stride) - if len(webp[0]) == 0: - return None - return webp[0] -%} -%enddef - -CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeRGB) -CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeRGBA) -CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeBGR) -CALL_ENCODE_LOSSY_WRAPPER(WebPEncodeBGRA) -CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessRGB) -CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA) -CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessBGR) -CALL_ENCODE_LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA) -#endif /* SWIGPYTHON */ diff --git a/libwebp_src/swig/libwebp_gc.c b/libwebp_src/swig/libwebp_gc.c deleted file mode 100644 index 308b7f8..0000000 --- a/libwebp_src/swig/libwebp_gc.c +++ /dev/null @@ -1,52 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 2.0.10 - * - * This file is not intended to be easily readable and contains a number of - * coding conventions designed to improve portability and efficiency. Do not make - * changes to this file unless you know what you are doing--modify the SWIG - * interface file instead. - * ----------------------------------------------------------------------------- */ - -/* This file should be compiled with 6c/8c. */ -#pragma dynimport _ _ "libwebp_go.so" - -#include "runtime.h" -#include "cgocall.h" - -#ifdef _64BIT -#define SWIG_PARM_SIZE 8 -#else -#define SWIG_PARM_SIZE 4 -#endif - -#pragma dynimport _wrap_WebPGetDecoderVersion _wrap_WebPGetDecoderVersion "" -extern void (*_wrap_WebPGetDecoderVersion)(void*); -static void (*x_wrap_WebPGetDecoderVersion)(void*) = _wrap_WebPGetDecoderVersion; - -void -·WebPGetDecoderVersion(struct { - uint8 x[SWIG_PARM_SIZE]; -} p) - -{ - runtime·cgocall(x_wrap_WebPGetDecoderVersion, &p); -} - - - -#pragma dynimport _wrap_wrapped_WebPGetInfo _wrap_wrapped_WebPGetInfo "" -extern void (*_wrap_wrapped_WebPGetInfo)(void*); -static void (*x_wrap_wrapped_WebPGetInfo)(void*) = _wrap_wrapped_WebPGetInfo; - -void -·Wrapped_WebPGetInfo(struct { - uint8 x[(2 * SWIG_PARM_SIZE) + (3 * SWIG_PARM_SIZE) + (3 * SWIG_PARM_SIZE) + SWIG_PARM_SIZE]; -} p) - -{ - runtime·cgocall(x_wrap_wrapped_WebPGetInfo, &p); -} - - - diff --git a/libwebp_src/swig/libwebp_go_wrap.c b/libwebp_src/swig/libwebp_go_wrap.c deleted file mode 100644 index 351d523..0000000 --- a/libwebp_src/swig/libwebp_go_wrap.c +++ /dev/null @@ -1,274 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 2.0.10 - * - * This file is not intended to be easily readable and contains a number of - * coding conventions designed to improve portability and efficiency. Do not make - * changes to this file unless you know what you are doing--modify the SWIG - * interface file instead. - * ----------------------------------------------------------------------------- */ -#define SWIGMODULE libwebp -/* ----------------------------------------------------------------------------- - * This section contains generic SWIG labels for method/variable - * declarations/attributes, and other compiler dependent labels. - * ----------------------------------------------------------------------------- */ - -/* template workaround for compilers that cannot correctly implement the C++ standard */ -#ifndef SWIGTEMPLATEDISAMBIGUATOR -# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) -# define SWIGTEMPLATEDISAMBIGUATOR template -# elif defined(__HP_aCC) -/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ -/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ -# define SWIGTEMPLATEDISAMBIGUATOR template -# else -# define SWIGTEMPLATEDISAMBIGUATOR -# endif -#endif - -/* inline attribute */ -#ifndef SWIGINLINE -# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) -# define SWIGINLINE inline -# else -# define SWIGINLINE -# endif -#endif - -/* attribute recognised by some compilers to avoid 'unused' warnings */ -#ifndef SWIGUNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -# elif defined(__ICC) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -#endif - -#ifndef SWIG_MSC_UNSUPPRESS_4505 -# if defined(_MSC_VER) -# pragma warning(disable : 4505) /* unreferenced local function has been removed */ -# endif -#endif - -#ifndef SWIGUNUSEDPARM -# ifdef __cplusplus -# define SWIGUNUSEDPARM(p) -# else -# define SWIGUNUSEDPARM(p) p SWIGUNUSED -# endif -#endif - -/* internal SWIG method */ -#ifndef SWIGINTERN -# define SWIGINTERN static SWIGUNUSED -#endif - -/* internal inline SWIG method */ -#ifndef SWIGINTERNINLINE -# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE -#endif - -/* exporting methods */ -#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# ifndef GCC_HASCLASSVISIBILITY -# define GCC_HASCLASSVISIBILITY -# endif -#endif - -#ifndef SWIGEXPORT -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# if defined(STATIC_LINKED) -# define SWIGEXPORT -# else -# define SWIGEXPORT __declspec(dllexport) -# endif -# else -# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) -# define SWIGEXPORT __attribute__ ((visibility("default"))) -# else -# define SWIGEXPORT -# endif -# endif -#endif - -/* calling conventions for Windows */ -#ifndef SWIGSTDCALL -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# define SWIGSTDCALL __stdcall -# else -# define SWIGSTDCALL -# endif -#endif - -/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ -#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -# define _CRT_SECURE_NO_DEPRECATE -#endif - -/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ -#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) -# define _SCL_SECURE_NO_DEPRECATE -#endif - - - -#include -#include -#include -#include -#include - - - -typedef long long intgo; -typedef unsigned long long uintgo; - - - -typedef struct { char *p; intgo n; } _gostring_; -typedef struct { void* array; intgo len; intgo cap; } _goslice_; - - - - -#define swiggo_size_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; -#define swiggo_size_assert(t, n) swiggo_size_assert_eq(sizeof(t), n, swiggo_sizeof_##t##_is_not_##n) - -swiggo_size_assert(char, 1) -swiggo_size_assert(short, 2) -swiggo_size_assert(int, 4) -typedef long long swiggo_long_long; -swiggo_size_assert(swiggo_long_long, 8) -swiggo_size_assert(float, 4) -swiggo_size_assert(double, 8) - -#ifdef __cplusplus -extern "C" { -#endif -extern void crosscall2(void (*fn)(void *, int), void *, int); -extern void _cgo_allocate(void *, int); -extern void _cgo_panic(void *, int); -#ifdef __cplusplus -} -#endif - -static void *_swig_goallocate(size_t len) { - struct { - size_t len; - void *ret; - } a; - a.len = len; - crosscall2(_cgo_allocate, &a, (int) sizeof a); - return a.ret; -} - -static void _swig_gopanic(const char *p) { - struct { - const char *p; - } a; - a.p = p; - crosscall2(_cgo_panic, &a, (int) sizeof a); -} - - - - -static _gostring_ _swig_makegostring(const char *p, size_t l) { - _gostring_ ret; - ret.p = (char*)_swig_goallocate(l + 1); - memcpy(ret.p, p, l); - ret.n = l; - return ret; -} - -#define SWIG_contract_assert(expr, msg) \ - if (!(expr)) { _swig_gopanic(msg); } else - - -#define SWIG_exception(code, msg) _swig_gopanic(msg) - - -#include "webp/decode.h" -#include "webp/encode.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void -_wrap_WebPGetDecoderVersion(void *swig_v) -{ - int result; - - struct swigargs { - long : 0; - intgo result; - } *swig_a = (struct swigargs *) swig_v; - - - result = (int)WebPGetDecoderVersion(); - swig_a->result = result; -} - - -void -_wrap_wrapped_WebPGetInfo(void *swig_v) -{ - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int temp3 ; - int temp4 ; - int result; - - struct swigargs { - _gostring_ arg1; - _goslice_ arg3; - _goslice_ arg4; - long : 0; - intgo result; - } *swig_a = (struct swigargs *) swig_v; - - - arg1 = (uint8_t *)swig_a->arg1.p; - arg2 = (size_t)swig_a->arg1.n; - - { - if (swig_a->arg3.len == 0) { - _swig_gopanic("array must contain at least 1 element"); - } - arg3 = &temp3; - } - { - if (swig_a->arg4.len == 0) { - _swig_gopanic("array must contain at least 1 element"); - } - arg4 = &temp4; - } - - result = (int)WebPGetInfo((uint8_t const *)arg1,arg2,arg3,arg4); - swig_a->result = result; - { - int* a = (int *) swig_a->arg3.array; - a[0] = temp3; - } - { - int* a = (int *) swig_a->arg4.array; - a[0] = temp4; - } - - -} - - -#ifdef __cplusplus -} -#endif - diff --git a/libwebp_src/swig/libwebp_java_wrap.c b/libwebp_src/swig/libwebp_java_wrap.c deleted file mode 100644 index c8d4b13..0000000 --- a/libwebp_src/swig/libwebp_java_wrap.c +++ /dev/null @@ -1,1765 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 2.0.4 - * - * This file is not intended to be easily readable and contains a number of - * coding conventions designed to improve portability and efficiency. Do not make - * changes to this file unless you know what you are doing--modify the SWIG - * interface file instead. - * ----------------------------------------------------------------------------- */ - -#define SWIGJAVA - -/* ----------------------------------------------------------------------------- - * This section contains generic SWIG labels for method/variable - * declarations/attributes, and other compiler dependent labels. - * ----------------------------------------------------------------------------- */ - -/* template workaround for compilers that cannot correctly implement the C++ standard */ -#ifndef SWIGTEMPLATEDISAMBIGUATOR -# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) -# define SWIGTEMPLATEDISAMBIGUATOR template -# elif defined(__HP_aCC) -/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ -/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ -# define SWIGTEMPLATEDISAMBIGUATOR template -# else -# define SWIGTEMPLATEDISAMBIGUATOR -# endif -#endif - -/* inline attribute */ -#ifndef SWIGINLINE -# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) -# define SWIGINLINE inline -# else -# define SWIGINLINE -# endif -#endif - -/* attribute recognised by some compilers to avoid 'unused' warnings */ -#ifndef SWIGUNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -# elif defined(__ICC) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -#endif - -#ifndef SWIG_MSC_UNSUPPRESS_4505 -# if defined(_MSC_VER) -# pragma warning(disable : 4505) /* unreferenced local function has been removed */ -# endif -#endif - -#ifndef SWIGUNUSEDPARM -# ifdef __cplusplus -# define SWIGUNUSEDPARM(p) -# else -# define SWIGUNUSEDPARM(p) p SWIGUNUSED -# endif -#endif - -/* internal SWIG method */ -#ifndef SWIGINTERN -# define SWIGINTERN static SWIGUNUSED -#endif - -/* internal inline SWIG method */ -#ifndef SWIGINTERNINLINE -# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE -#endif - -/* exporting methods */ -#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# ifndef GCC_HASCLASSVISIBILITY -# define GCC_HASCLASSVISIBILITY -# endif -#endif - -#ifndef SWIGEXPORT -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# if defined(STATIC_LINKED) -# define SWIGEXPORT -# else -# define SWIGEXPORT __declspec(dllexport) -# endif -# else -# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) -# define SWIGEXPORT __attribute__ ((visibility("default"))) -# else -# define SWIGEXPORT -# endif -# endif -#endif - -/* calling conventions for Windows */ -#ifndef SWIGSTDCALL -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# define SWIGSTDCALL __stdcall -# else -# define SWIGSTDCALL -# endif -#endif - -/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ -#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -# define _CRT_SECURE_NO_DEPRECATE -#endif - -/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ -#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) -# define _SCL_SECURE_NO_DEPRECATE -#endif - - - -/* Fix for jlong on some versions of gcc on Windows */ -#if defined(__GNUC__) && !defined(__INTEL_COMPILER) - typedef long long __int64; -#endif - -/* Fix for jlong on 64-bit x86 Solaris */ -#if defined(__x86_64) -# ifdef _LP64 -# undef _LP64 -# endif -#endif - -#include -#include -#include - - -/* Support for throwing Java exceptions */ -typedef enum { - SWIG_JavaOutOfMemoryError = 1, - SWIG_JavaIOException, - SWIG_JavaRuntimeException, - SWIG_JavaIndexOutOfBoundsException, - SWIG_JavaArithmeticException, - SWIG_JavaIllegalArgumentException, - SWIG_JavaNullPointerException, - SWIG_JavaDirectorPureVirtual, - SWIG_JavaUnknownError -} SWIG_JavaExceptionCodes; - -typedef struct { - SWIG_JavaExceptionCodes code; - const char *java_exception; -} SWIG_JavaExceptions_t; - - -static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionCodes code, const char *msg) { - jclass excep; - static const SWIG_JavaExceptions_t java_exceptions[] = { - { SWIG_JavaOutOfMemoryError, "java/lang/OutOfMemoryError" }, - { SWIG_JavaIOException, "java/io/IOException" }, - { SWIG_JavaRuntimeException, "java/lang/RuntimeException" }, - { SWIG_JavaIndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException" }, - { SWIG_JavaArithmeticException, "java/lang/ArithmeticException" }, - { SWIG_JavaIllegalArgumentException, "java/lang/IllegalArgumentException" }, - { SWIG_JavaNullPointerException, "java/lang/NullPointerException" }, - { SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" }, - { SWIG_JavaUnknownError, "java/lang/UnknownError" }, - { (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" } - }; - const SWIG_JavaExceptions_t *except_ptr = java_exceptions; - - while (except_ptr->code != code && except_ptr->code) - except_ptr++; - - (*jenv)->ExceptionClear(jenv); - excep = (*jenv)->FindClass(jenv, except_ptr->java_exception); - if (excep) - (*jenv)->ThrowNew(jenv, excep, msg); -} - - -/* Contract support */ - -#define SWIG_contract_assert(nullreturn, expr, msg) if (!(expr)) {SWIG_JavaThrowException(jenv, SWIG_JavaIllegalArgumentException, msg); return nullreturn; } else - -/* Errors in SWIG */ -#define SWIG_UnknownError -1 -#define SWIG_IOError -2 -#define SWIG_RuntimeError -3 -#define SWIG_IndexError -4 -#define SWIG_TypeError -5 -#define SWIG_DivisionByZero -6 -#define SWIG_OverflowError -7 -#define SWIG_SyntaxError -8 -#define SWIG_ValueError -9 -#define SWIG_SystemError -10 -#define SWIG_AttributeError -11 -#define SWIG_MemoryError -12 -#define SWIG_NullReferenceError -13 - - - - -SWIGINTERN void SWIG_JavaException(JNIEnv *jenv, int code, const char *msg) { - SWIG_JavaExceptionCodes exception_code = SWIG_JavaUnknownError; - switch(code) { - case SWIG_MemoryError: - exception_code = SWIG_JavaOutOfMemoryError; - break; - case SWIG_IOError: - exception_code = SWIG_JavaIOException; - break; - case SWIG_SystemError: - case SWIG_RuntimeError: - exception_code = SWIG_JavaRuntimeException; - break; - case SWIG_OverflowError: - case SWIG_IndexError: - exception_code = SWIG_JavaIndexOutOfBoundsException; - break; - case SWIG_DivisionByZero: - exception_code = SWIG_JavaArithmeticException; - break; - case SWIG_SyntaxError: - case SWIG_ValueError: - case SWIG_TypeError: - exception_code = SWIG_JavaIllegalArgumentException; - break; - case SWIG_UnknownError: - default: - exception_code = SWIG_JavaUnknownError; - break; - } - SWIG_JavaThrowException(jenv, exception_code, msg); -} - - -#if defined(SWIG_NOINCLUDE) || defined(SWIG_NOARRAYS) - - -int SWIG_JavaArrayInSchar (JNIEnv *jenv, jbyte **jarr, signed char **carr, jbyteArray input); -void SWIG_JavaArrayArgoutSchar (JNIEnv *jenv, jbyte *jarr, signed char *carr, jbyteArray input); -jbyteArray SWIG_JavaArrayOutSchar (JNIEnv *jenv, signed char *result, jsize sz); - - -int SWIG_JavaArrayInUchar (JNIEnv *jenv, jshort **jarr, unsigned char **carr, jshortArray input); -void SWIG_JavaArrayArgoutUchar (JNIEnv *jenv, jshort *jarr, unsigned char *carr, jshortArray input); -jshortArray SWIG_JavaArrayOutUchar (JNIEnv *jenv, unsigned char *result, jsize sz); - - -int SWIG_JavaArrayInShort (JNIEnv *jenv, jshort **jarr, short **carr, jshortArray input); -void SWIG_JavaArrayArgoutShort (JNIEnv *jenv, jshort *jarr, short *carr, jshortArray input); -jshortArray SWIG_JavaArrayOutShort (JNIEnv *jenv, short *result, jsize sz); - - -int SWIG_JavaArrayInUshort (JNIEnv *jenv, jint **jarr, unsigned short **carr, jintArray input); -void SWIG_JavaArrayArgoutUshort (JNIEnv *jenv, jint *jarr, unsigned short *carr, jintArray input); -jintArray SWIG_JavaArrayOutUshort (JNIEnv *jenv, unsigned short *result, jsize sz); - - -int SWIG_JavaArrayInInt (JNIEnv *jenv, jint **jarr, int **carr, jintArray input); -void SWIG_JavaArrayArgoutInt (JNIEnv *jenv, jint *jarr, int *carr, jintArray input); -jintArray SWIG_JavaArrayOutInt (JNIEnv *jenv, int *result, jsize sz); - - -int SWIG_JavaArrayInUint (JNIEnv *jenv, jlong **jarr, unsigned int **carr, jlongArray input); -void SWIG_JavaArrayArgoutUint (JNIEnv *jenv, jlong *jarr, unsigned int *carr, jlongArray input); -jlongArray SWIG_JavaArrayOutUint (JNIEnv *jenv, unsigned int *result, jsize sz); - - -int SWIG_JavaArrayInLong (JNIEnv *jenv, jint **jarr, long **carr, jintArray input); -void SWIG_JavaArrayArgoutLong (JNIEnv *jenv, jint *jarr, long *carr, jintArray input); -jintArray SWIG_JavaArrayOutLong (JNIEnv *jenv, long *result, jsize sz); - - -int SWIG_JavaArrayInUlong (JNIEnv *jenv, jlong **jarr, unsigned long **carr, jlongArray input); -void SWIG_JavaArrayArgoutUlong (JNIEnv *jenv, jlong *jarr, unsigned long *carr, jlongArray input); -jlongArray SWIG_JavaArrayOutUlong (JNIEnv *jenv, unsigned long *result, jsize sz); - - -int SWIG_JavaArrayInLonglong (JNIEnv *jenv, jlong **jarr, jlong **carr, jlongArray input); -void SWIG_JavaArrayArgoutLonglong (JNIEnv *jenv, jlong *jarr, jlong *carr, jlongArray input); -jlongArray SWIG_JavaArrayOutLonglong (JNIEnv *jenv, jlong *result, jsize sz); - - -int SWIG_JavaArrayInFloat (JNIEnv *jenv, jfloat **jarr, float **carr, jfloatArray input); -void SWIG_JavaArrayArgoutFloat (JNIEnv *jenv, jfloat *jarr, float *carr, jfloatArray input); -jfloatArray SWIG_JavaArrayOutFloat (JNIEnv *jenv, float *result, jsize sz); - - -int SWIG_JavaArrayInDouble (JNIEnv *jenv, jdouble **jarr, double **carr, jdoubleArray input); -void SWIG_JavaArrayArgoutDouble (JNIEnv *jenv, jdouble *jarr, double *carr, jdoubleArray input); -jdoubleArray SWIG_JavaArrayOutDouble (JNIEnv *jenv, double *result, jsize sz); - - -#else - - -/* signed char[] support */ -int SWIG_JavaArrayInSchar (JNIEnv *jenv, jbyte **jarr, signed char **carr, jbyteArray input) { - int i; - jsize sz; - if (!input) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); - return 0; - } - sz = (*jenv)->GetArrayLength(jenv, input); - *jarr = (*jenv)->GetByteArrayElements(jenv, input, 0); - if (!*jarr) - return 0; - *carr = (signed char*) calloc(sz, sizeof(signed char)); - if (!*carr) { - SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); - return 0; - } - for (i=0; iGetArrayLength(jenv, input); - for (i=0; iReleaseByteArrayElements(jenv, input, jarr, 0); -} - -jbyteArray SWIG_JavaArrayOutSchar (JNIEnv *jenv, signed char *result, jsize sz) { - jbyte *arr; - int i; - jbyteArray jresult = (*jenv)->NewByteArray(jenv, sz); - if (!jresult) - return NULL; - arr = (*jenv)->GetByteArrayElements(jenv, jresult, 0); - if (!arr) - return NULL; - for (i=0; iReleaseByteArrayElements(jenv, jresult, arr, 0); - return jresult; -} - - -/* unsigned char[] support */ -int SWIG_JavaArrayInUchar (JNIEnv *jenv, jshort **jarr, unsigned char **carr, jshortArray input) { - int i; - jsize sz; - if (!input) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); - return 0; - } - sz = (*jenv)->GetArrayLength(jenv, input); - *jarr = (*jenv)->GetShortArrayElements(jenv, input, 0); - if (!*jarr) - return 0; - *carr = (unsigned char*) calloc(sz, sizeof(unsigned char)); - if (!*carr) { - SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); - return 0; - } - for (i=0; iGetArrayLength(jenv, input); - for (i=0; iReleaseShortArrayElements(jenv, input, jarr, 0); -} - -jshortArray SWIG_JavaArrayOutUchar (JNIEnv *jenv, unsigned char *result, jsize sz) { - jshort *arr; - int i; - jshortArray jresult = (*jenv)->NewShortArray(jenv, sz); - if (!jresult) - return NULL; - arr = (*jenv)->GetShortArrayElements(jenv, jresult, 0); - if (!arr) - return NULL; - for (i=0; iReleaseShortArrayElements(jenv, jresult, arr, 0); - return jresult; -} - - -/* short[] support */ -int SWIG_JavaArrayInShort (JNIEnv *jenv, jshort **jarr, short **carr, jshortArray input) { - int i; - jsize sz; - if (!input) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); - return 0; - } - sz = (*jenv)->GetArrayLength(jenv, input); - *jarr = (*jenv)->GetShortArrayElements(jenv, input, 0); - if (!*jarr) - return 0; - *carr = (short*) calloc(sz, sizeof(short)); - if (!*carr) { - SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); - return 0; - } - for (i=0; iGetArrayLength(jenv, input); - for (i=0; iReleaseShortArrayElements(jenv, input, jarr, 0); -} - -jshortArray SWIG_JavaArrayOutShort (JNIEnv *jenv, short *result, jsize sz) { - jshort *arr; - int i; - jshortArray jresult = (*jenv)->NewShortArray(jenv, sz); - if (!jresult) - return NULL; - arr = (*jenv)->GetShortArrayElements(jenv, jresult, 0); - if (!arr) - return NULL; - for (i=0; iReleaseShortArrayElements(jenv, jresult, arr, 0); - return jresult; -} - - -/* unsigned short[] support */ -int SWIG_JavaArrayInUshort (JNIEnv *jenv, jint **jarr, unsigned short **carr, jintArray input) { - int i; - jsize sz; - if (!input) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); - return 0; - } - sz = (*jenv)->GetArrayLength(jenv, input); - *jarr = (*jenv)->GetIntArrayElements(jenv, input, 0); - if (!*jarr) - return 0; - *carr = (unsigned short*) calloc(sz, sizeof(unsigned short)); - if (!*carr) { - SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); - return 0; - } - for (i=0; iGetArrayLength(jenv, input); - for (i=0; iReleaseIntArrayElements(jenv, input, jarr, 0); -} - -jintArray SWIG_JavaArrayOutUshort (JNIEnv *jenv, unsigned short *result, jsize sz) { - jint *arr; - int i; - jintArray jresult = (*jenv)->NewIntArray(jenv, sz); - if (!jresult) - return NULL; - arr = (*jenv)->GetIntArrayElements(jenv, jresult, 0); - if (!arr) - return NULL; - for (i=0; iReleaseIntArrayElements(jenv, jresult, arr, 0); - return jresult; -} - - -/* int[] support */ -int SWIG_JavaArrayInInt (JNIEnv *jenv, jint **jarr, int **carr, jintArray input) { - int i; - jsize sz; - if (!input) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); - return 0; - } - sz = (*jenv)->GetArrayLength(jenv, input); - *jarr = (*jenv)->GetIntArrayElements(jenv, input, 0); - if (!*jarr) - return 0; - *carr = (int*) calloc(sz, sizeof(int)); - if (!*carr) { - SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); - return 0; - } - for (i=0; iGetArrayLength(jenv, input); - for (i=0; iReleaseIntArrayElements(jenv, input, jarr, 0); -} - -jintArray SWIG_JavaArrayOutInt (JNIEnv *jenv, int *result, jsize sz) { - jint *arr; - int i; - jintArray jresult = (*jenv)->NewIntArray(jenv, sz); - if (!jresult) - return NULL; - arr = (*jenv)->GetIntArrayElements(jenv, jresult, 0); - if (!arr) - return NULL; - for (i=0; iReleaseIntArrayElements(jenv, jresult, arr, 0); - return jresult; -} - - -/* unsigned int[] support */ -int SWIG_JavaArrayInUint (JNIEnv *jenv, jlong **jarr, unsigned int **carr, jlongArray input) { - int i; - jsize sz; - if (!input) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); - return 0; - } - sz = (*jenv)->GetArrayLength(jenv, input); - *jarr = (*jenv)->GetLongArrayElements(jenv, input, 0); - if (!*jarr) - return 0; - *carr = (unsigned int*) calloc(sz, sizeof(unsigned int)); - if (!*carr) { - SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); - return 0; - } - for (i=0; iGetArrayLength(jenv, input); - for (i=0; iReleaseLongArrayElements(jenv, input, jarr, 0); -} - -jlongArray SWIG_JavaArrayOutUint (JNIEnv *jenv, unsigned int *result, jsize sz) { - jlong *arr; - int i; - jlongArray jresult = (*jenv)->NewLongArray(jenv, sz); - if (!jresult) - return NULL; - arr = (*jenv)->GetLongArrayElements(jenv, jresult, 0); - if (!arr) - return NULL; - for (i=0; iReleaseLongArrayElements(jenv, jresult, arr, 0); - return jresult; -} - - -/* long[] support */ -int SWIG_JavaArrayInLong (JNIEnv *jenv, jint **jarr, long **carr, jintArray input) { - int i; - jsize sz; - if (!input) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); - return 0; - } - sz = (*jenv)->GetArrayLength(jenv, input); - *jarr = (*jenv)->GetIntArrayElements(jenv, input, 0); - if (!*jarr) - return 0; - *carr = (long*) calloc(sz, sizeof(long)); - if (!*carr) { - SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); - return 0; - } - for (i=0; iGetArrayLength(jenv, input); - for (i=0; iReleaseIntArrayElements(jenv, input, jarr, 0); -} - -jintArray SWIG_JavaArrayOutLong (JNIEnv *jenv, long *result, jsize sz) { - jint *arr; - int i; - jintArray jresult = (*jenv)->NewIntArray(jenv, sz); - if (!jresult) - return NULL; - arr = (*jenv)->GetIntArrayElements(jenv, jresult, 0); - if (!arr) - return NULL; - for (i=0; iReleaseIntArrayElements(jenv, jresult, arr, 0); - return jresult; -} - - -/* unsigned long[] support */ -int SWIG_JavaArrayInUlong (JNIEnv *jenv, jlong **jarr, unsigned long **carr, jlongArray input) { - int i; - jsize sz; - if (!input) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); - return 0; - } - sz = (*jenv)->GetArrayLength(jenv, input); - *jarr = (*jenv)->GetLongArrayElements(jenv, input, 0); - if (!*jarr) - return 0; - *carr = (unsigned long*) calloc(sz, sizeof(unsigned long)); - if (!*carr) { - SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); - return 0; - } - for (i=0; iGetArrayLength(jenv, input); - for (i=0; iReleaseLongArrayElements(jenv, input, jarr, 0); -} - -jlongArray SWIG_JavaArrayOutUlong (JNIEnv *jenv, unsigned long *result, jsize sz) { - jlong *arr; - int i; - jlongArray jresult = (*jenv)->NewLongArray(jenv, sz); - if (!jresult) - return NULL; - arr = (*jenv)->GetLongArrayElements(jenv, jresult, 0); - if (!arr) - return NULL; - for (i=0; iReleaseLongArrayElements(jenv, jresult, arr, 0); - return jresult; -} - - -/* jlong[] support */ -int SWIG_JavaArrayInLonglong (JNIEnv *jenv, jlong **jarr, jlong **carr, jlongArray input) { - int i; - jsize sz; - if (!input) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); - return 0; - } - sz = (*jenv)->GetArrayLength(jenv, input); - *jarr = (*jenv)->GetLongArrayElements(jenv, input, 0); - if (!*jarr) - return 0; - *carr = (jlong*) calloc(sz, sizeof(jlong)); - if (!*carr) { - SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); - return 0; - } - for (i=0; iGetArrayLength(jenv, input); - for (i=0; iReleaseLongArrayElements(jenv, input, jarr, 0); -} - -jlongArray SWIG_JavaArrayOutLonglong (JNIEnv *jenv, jlong *result, jsize sz) { - jlong *arr; - int i; - jlongArray jresult = (*jenv)->NewLongArray(jenv, sz); - if (!jresult) - return NULL; - arr = (*jenv)->GetLongArrayElements(jenv, jresult, 0); - if (!arr) - return NULL; - for (i=0; iReleaseLongArrayElements(jenv, jresult, arr, 0); - return jresult; -} - - -/* float[] support */ -int SWIG_JavaArrayInFloat (JNIEnv *jenv, jfloat **jarr, float **carr, jfloatArray input) { - int i; - jsize sz; - if (!input) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); - return 0; - } - sz = (*jenv)->GetArrayLength(jenv, input); - *jarr = (*jenv)->GetFloatArrayElements(jenv, input, 0); - if (!*jarr) - return 0; - *carr = (float*) calloc(sz, sizeof(float)); - if (!*carr) { - SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); - return 0; - } - for (i=0; iGetArrayLength(jenv, input); - for (i=0; iReleaseFloatArrayElements(jenv, input, jarr, 0); -} - -jfloatArray SWIG_JavaArrayOutFloat (JNIEnv *jenv, float *result, jsize sz) { - jfloat *arr; - int i; - jfloatArray jresult = (*jenv)->NewFloatArray(jenv, sz); - if (!jresult) - return NULL; - arr = (*jenv)->GetFloatArrayElements(jenv, jresult, 0); - if (!arr) - return NULL; - for (i=0; iReleaseFloatArrayElements(jenv, jresult, arr, 0); - return jresult; -} - - -/* double[] support */ -int SWIG_JavaArrayInDouble (JNIEnv *jenv, jdouble **jarr, double **carr, jdoubleArray input) { - int i; - jsize sz; - if (!input) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); - return 0; - } - sz = (*jenv)->GetArrayLength(jenv, input); - *jarr = (*jenv)->GetDoubleArrayElements(jenv, input, 0); - if (!*jarr) - return 0; - *carr = (double*) calloc(sz, sizeof(double)); - if (!*carr) { - SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); - return 0; - } - for (i=0; iGetArrayLength(jenv, input); - for (i=0; iReleaseDoubleArrayElements(jenv, input, jarr, 0); -} - -jdoubleArray SWIG_JavaArrayOutDouble (JNIEnv *jenv, double *result, jsize sz) { - jdouble *arr; - int i; - jdoubleArray jresult = (*jenv)->NewDoubleArray(jenv, sz); - if (!jresult) - return NULL; - arr = (*jenv)->GetDoubleArrayElements(jenv, jresult, 0); - if (!arr) - return NULL; - for (i=0; iReleaseDoubleArrayElements(jenv, jresult, arr, 0); - return jresult; -} - - -#endif - - -#include "webp/types.h" - - -int SWIG_JavaArrayInUint8 (JNIEnv *jenv, jbyte **jarr, uint8_t **carr, jbyteArray input); -void SWIG_JavaArrayArgoutUint8 (JNIEnv *jenv, jbyte *jarr, uint8_t *carr, jbyteArray input); -jbyteArray SWIG_JavaArrayOutUint8 (JNIEnv *jenv, uint8_t *result, jsize sz); - - -/* uint8_t[] support */ -int SWIG_JavaArrayInUint8 (JNIEnv *jenv, jbyte **jarr, uint8_t **carr, jbyteArray input) { - int i; - jsize sz; - if (!input) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array"); - return 0; - } - sz = (*jenv)->GetArrayLength(jenv, input); - *jarr = (*jenv)->GetByteArrayElements(jenv, input, 0); - if (!*jarr) - return 0; - *carr = (uint8_t*) calloc(sz, sizeof(uint8_t)); - if (!*carr) { - SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed"); - return 0; - } - for (i=0; iGetArrayLength(jenv, input); - for (i=0; iReleaseByteArrayElements(jenv, input, jarr, 0); -} - -jbyteArray SWIG_JavaArrayOutUint8 (JNIEnv *jenv, uint8_t *result, jsize sz) { - jbyte *arr; - int i; - jbyteArray jresult = (*jenv)->NewByteArray(jenv, sz); - if (!jresult) - return NULL; - arr = (*jenv)->GetByteArrayElements(jenv, jresult, 0); - if (!arr) - return NULL; - for (i=0; iReleaseByteArrayElements(jenv, jresult, arr, 0); - return jresult; -} - - -#include "webp/decode.h" -#include "webp/encode.h" - - -#define FillMeInAsSizeCannotBeDeterminedAutomatically \ - (result ? (jint)ReturnedBufferSize(__FUNCTION__, arg3, arg4) : 0) - - -static size_t ReturnedBufferSize( - const char* function, int* width, int* height) { - static const struct sizemap { - const char* function; - int size_multiplier; - } size_map[] = { -#ifdef SWIGJAVA - { "Java_com_google_webp_libwebpJNI_WebPDecodeRGB", 3 }, - { "Java_com_google_webp_libwebpJNI_WebPDecodeRGBA", 4 }, - { "Java_com_google_webp_libwebpJNI_WebPDecodeARGB", 4 }, - { "Java_com_google_webp_libwebpJNI_WebPDecodeBGR", 3 }, - { "Java_com_google_webp_libwebpJNI_WebPDecodeBGRA", 4 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGB", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGR", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGBA", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGRA", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGB", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGR", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGBA", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGRA", 1 }, -#endif -#ifdef SWIGPYTHON - { "WebPDecodeRGB", 3 }, - { "WebPDecodeRGBA", 4 }, - { "WebPDecodeARGB", 4 }, - { "WebPDecodeBGR", 3 }, - { "WebPDecodeBGRA", 4 }, - { "wrap_WebPEncodeRGB", 1 }, - { "wrap_WebPEncodeBGR", 1 }, - { "wrap_WebPEncodeRGBA", 1 }, - { "wrap_WebPEncodeBGRA", 1 }, - { "wrap_WebPEncodeLosslessRGB", 1 }, - { "wrap_WebPEncodeLosslessBGR", 1 }, - { "wrap_WebPEncodeLosslessRGBA", 1 }, - { "wrap_WebPEncodeLosslessBGRA", 1 }, -#endif - { NULL, 0 } - }; - const struct sizemap* p; - size_t size = 0; - - for (p = size_map; p->function; ++p) { - if (!strcmp(function, p->function)) { - size = *width * *height * p->size_multiplier; - break; - } - } - - return size; -} - - -typedef size_t (*WebPEncodeFunction)(const uint8_t* rgb, - int width, int height, int stride, - float quality_factor, uint8_t** output); -typedef size_t (*WebPEncodeLosslessFunction)(const uint8_t* rgb, - int width, int height, int stride, - uint8_t** output); - -static uint8_t* EncodeLossy(const uint8_t* rgb, - int width, int height, int stride, - float quality_factor, - WebPEncodeFunction encfn, - int* output_size, int* unused) { - uint8_t* output = NULL; - const size_t image_size = - encfn(rgb, width, height, stride, quality_factor, &output); - // the values of following two will be interpreted by ReturnedBufferSize() - // as 'width' and 'height' in the size calculation. - *output_size = image_size; - *unused = 1; - return image_size ? output : NULL; -} - -static uint8_t* EncodeLossless(const uint8_t* rgb, - int width, int height, int stride, - WebPEncodeLosslessFunction encfn, - int* output_size, int* unused) { - uint8_t* output = NULL; - const size_t image_size = encfn(rgb, width, height, stride, &output); - // the values of the following two will be interpreted by - // ReturnedBufferSize() as 'width' and 'height' in the size calculation. - *output_size = image_size; - *unused = 1; - return image_size ? output : NULL; -} - - -// Changes the return type of WebPEncode* to more closely match Decode*. -// This also makes it easier to wrap the output buffer in a native type rather -// than dealing with the return pointer. -// The additional parameters are to allow reuse of ReturnedBufferSize(), -// unused2 and output_size will be used in this case. -#define LOSSY_WRAPPER(FUNC) \ - static uint8_t* wrap_##FUNC( \ - const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \ - int width, int height, int stride, float quality_factor) { \ - return EncodeLossy(rgb, width, height, stride, quality_factor, \ - FUNC, output_size, unused2); \ - } \ - -LOSSY_WRAPPER(WebPEncodeRGB) -LOSSY_WRAPPER(WebPEncodeBGR) -LOSSY_WRAPPER(WebPEncodeRGBA) -LOSSY_WRAPPER(WebPEncodeBGRA) - -#undef LOSSY_WRAPPER - -#define LOSSLESS_WRAPPER(FUNC) \ - static uint8_t* wrap_##FUNC( \ - const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \ - int width, int height, int stride) { \ - return EncodeLossless(rgb, width, height, stride, \ - FUNC, output_size, unused2); \ - } \ - -LOSSLESS_WRAPPER(WebPEncodeLosslessRGB) -LOSSLESS_WRAPPER(WebPEncodeLosslessBGR) -LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA) -LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA) - -#undef LOSSLESS_WRAPPER - - - -/* Work around broken gcj jni.h */ -#ifdef __GCJ_JNI_H__ -# undef JNIEXPORT -# define JNIEXPORT -# undef JNICALL -# define JNICALL -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -SWIGEXPORT jint JNICALL Java_com_google_webp_libwebpJNI_WebPGetDecoderVersion(JNIEnv *jenv, jclass jcls) { - jint jresult = 0 ; - int result; - - (void)jenv; - (void)jcls; - result = (int)WebPGetDecoderVersion(); - jresult = (jint)result; - return jresult; -} - - -SWIGEXPORT jint JNICALL Java_com_google_webp_libwebpJNI_WebPGetInfo(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) { - jint jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - jbyte *jarr1 ; - int temp3 ; - int temp4 ; - int result; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (size_t)jarg2; - { - if (!jarg3) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg3 = &temp3; - } - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - result = (int)WebPGetInfo((uint8_t const *)arg1,arg2,arg3,arg4); - jresult = (jint)result; - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp3; - (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); - } - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_WebPDecodeRGB(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - jbyte *jarr1 ; - int temp3 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (size_t)jarg2; - { - if (!jarg3) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg3 = &temp3; - } - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - result = (uint8_t *)WebPDecodeRGB((uint8_t const *)arg1,arg2,arg3,arg4); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp3; - (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); - } - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - free(result); - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_WebPDecodeRGBA(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - jbyte *jarr1 ; - int temp3 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (size_t)jarg2; - { - if (!jarg3) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg3 = &temp3; - } - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - result = (uint8_t *)WebPDecodeRGBA((uint8_t const *)arg1,arg2,arg3,arg4); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp3; - (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); - } - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - free(result); - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_WebPDecodeARGB(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - jbyte *jarr1 ; - int temp3 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (size_t)jarg2; - { - if (!jarg3) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg3 = &temp3; - } - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - result = (uint8_t *)WebPDecodeARGB((uint8_t const *)arg1,arg2,arg3,arg4); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp3; - (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); - } - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - free(result); - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_WebPDecodeBGR(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - jbyte *jarr1 ; - int temp3 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (size_t)jarg2; - { - if (!jarg3) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg3 = &temp3; - } - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - result = (uint8_t *)WebPDecodeBGR((uint8_t const *)arg1,arg2,arg3,arg4); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp3; - (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); - } - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - free(result); - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_WebPDecodeBGRA(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jlong jarg2, jintArray jarg3, jintArray jarg4) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - jbyte *jarr1 ; - int temp3 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (size_t)jarg2; - { - if (!jarg3) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg3 = &temp3; - } - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - result = (uint8_t *)WebPDecodeBGRA((uint8_t const *)arg1,arg2,arg3,arg4); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp3; - (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); - } - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - free(result); - return jresult; -} - - -SWIGEXPORT jint JNICALL Java_com_google_webp_libwebpJNI_WebPGetEncoderVersion(JNIEnv *jenv, jclass jcls) { - jint jresult = 0 ; - int result; - - (void)jenv; - (void)jcls; - result = (int)WebPGetEncoderVersion(); - jresult = (jint)result; - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGB(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7, jfloat jarg8) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - float arg8 ; - jbyte *jarr1 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (int *)&jarg2; - arg3 = (int *)&jarg3; - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - arg5 = (int)jarg5; - arg6 = (int)jarg6; - arg7 = (int)jarg7; - arg8 = (float)jarg8; - result = (uint8_t *)wrap_WebPEncodeRGB((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - - free(result); - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGR(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7, jfloat jarg8) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - float arg8 ; - jbyte *jarr1 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (int *)&jarg2; - arg3 = (int *)&jarg3; - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - arg5 = (int)jarg5; - arg6 = (int)jarg6; - arg7 = (int)jarg7; - arg8 = (float)jarg8; - result = (uint8_t *)wrap_WebPEncodeBGR((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - - free(result); - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGBA(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7, jfloat jarg8) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - float arg8 ; - jbyte *jarr1 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (int *)&jarg2; - arg3 = (int *)&jarg3; - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - arg5 = (int)jarg5; - arg6 = (int)jarg6; - arg7 = (int)jarg7; - arg8 = (float)jarg8; - result = (uint8_t *)wrap_WebPEncodeRGBA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - - free(result); - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGRA(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7, jfloat jarg8) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - float arg8 ; - jbyte *jarr1 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (int *)&jarg2; - arg3 = (int *)&jarg3; - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - arg5 = (int)jarg5; - arg6 = (int)jarg6; - arg7 = (int)jarg7; - arg8 = (float)jarg8; - result = (uint8_t *)wrap_WebPEncodeBGRA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - - free(result); - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGB(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - jbyte *jarr1 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (int *)&jarg2; - arg3 = (int *)&jarg3; - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - arg5 = (int)jarg5; - arg6 = (int)jarg6; - arg7 = (int)jarg7; - result = (uint8_t *)wrap_WebPEncodeLosslessRGB((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - - free(result); - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGR(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - jbyte *jarr1 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (int *)&jarg2; - arg3 = (int *)&jarg3; - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - arg5 = (int)jarg5; - arg6 = (int)jarg6; - arg7 = (int)jarg7; - result = (uint8_t *)wrap_WebPEncodeLosslessBGR((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - - free(result); - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGBA(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - jbyte *jarr1 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (int *)&jarg2; - arg3 = (int *)&jarg3; - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - arg5 = (int)jarg5; - arg6 = (int)jarg6; - arg7 = (int)jarg7; - result = (uint8_t *)wrap_WebPEncodeLosslessRGBA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - - free(result); - return jresult; -} - - -SWIGEXPORT jbyteArray JNICALL Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGRA(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jint jarg3, jintArray jarg4, jint jarg5, jint jarg6, jint jarg7) { - jbyteArray jresult = 0 ; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - jbyte *jarr1 ; - int temp4 ; - uint8_t *result = 0 ; - - (void)jenv; - (void)jcls; - if (!SWIG_JavaArrayInUint8(jenv, &jarr1, &arg1, jarg1)) return 0; - arg2 = (int *)&jarg2; - arg3 = (int *)&jarg3; - { - if (!jarg4) { - SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); - return 0; - } - if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { - SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); - return 0; - } - arg4 = &temp4; - } - arg5 = (int)jarg5; - arg6 = (int)jarg6; - arg7 = (int)jarg7; - result = (uint8_t *)wrap_WebPEncodeLosslessBGRA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); - jresult = SWIG_JavaArrayOutUint8(jenv, result, FillMeInAsSizeCannotBeDeterminedAutomatically); - SWIG_JavaArrayArgoutUint8(jenv, jarr1, arg1, jarg1); - { - jint jvalue = (jint)temp4; - (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); - } - free(arg1); - - - - free(result); - return jresult; -} - - -#ifdef __cplusplus -} -#endif - diff --git a/libwebp_src/swig/libwebp_python_wrap.c b/libwebp_src/swig/libwebp_python_wrap.c deleted file mode 100644 index 3aa2728..0000000 --- a/libwebp_src/swig/libwebp_python_wrap.c +++ /dev/null @@ -1,5628 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 3.0.12 - * - * This file is not intended to be easily readable and contains a number of - * coding conventions designed to improve portability and efficiency. Do not make - * changes to this file unless you know what you are doing--modify the SWIG - * interface file instead. - * ----------------------------------------------------------------------------- */ - -#define SWIG_PYTHON_STRICT_BYTE_CHAR - - - -#ifndef SWIGPYTHON -#define SWIGPYTHON -#endif - -#define SWIG_PYTHON_DIRECTOR_NO_VTABLE - -/* ----------------------------------------------------------------------------- - * This section contains generic SWIG labels for method/variable - * declarations/attributes, and other compiler dependent labels. - * ----------------------------------------------------------------------------- */ - -/* template workaround for compilers that cannot correctly implement the C++ standard */ -#ifndef SWIGTEMPLATEDISAMBIGUATOR -# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) -# define SWIGTEMPLATEDISAMBIGUATOR template -# elif defined(__HP_aCC) -/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ -/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ -# define SWIGTEMPLATEDISAMBIGUATOR template -# else -# define SWIGTEMPLATEDISAMBIGUATOR -# endif -#endif - -/* inline attribute */ -#ifndef SWIGINLINE -# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) -# define SWIGINLINE inline -# else -# define SWIGINLINE -# endif -#endif - -/* attribute recognised by some compilers to avoid 'unused' warnings */ -#ifndef SWIGUNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -# elif defined(__ICC) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -#endif - -#ifndef SWIG_MSC_UNSUPPRESS_4505 -# if defined(_MSC_VER) -# pragma warning(disable : 4505) /* unreferenced local function has been removed */ -# endif -#endif - -#ifndef SWIGUNUSEDPARM -# ifdef __cplusplus -# define SWIGUNUSEDPARM(p) -# else -# define SWIGUNUSEDPARM(p) p SWIGUNUSED -# endif -#endif - -/* internal SWIG method */ -#ifndef SWIGINTERN -# define SWIGINTERN static SWIGUNUSED -#endif - -/* internal inline SWIG method */ -#ifndef SWIGINTERNINLINE -# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE -#endif - -/* exporting methods */ -#if defined(__GNUC__) -# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# ifndef GCC_HASCLASSVISIBILITY -# define GCC_HASCLASSVISIBILITY -# endif -# endif -#endif - -#ifndef SWIGEXPORT -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# if defined(STATIC_LINKED) -# define SWIGEXPORT -# else -# define SWIGEXPORT __declspec(dllexport) -# endif -# else -# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) -# define SWIGEXPORT __attribute__ ((visibility("default"))) -# else -# define SWIGEXPORT -# endif -# endif -#endif - -/* calling conventions for Windows */ -#ifndef SWIGSTDCALL -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# define SWIGSTDCALL __stdcall -# else -# define SWIGSTDCALL -# endif -#endif - -/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ -#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -# define _CRT_SECURE_NO_DEPRECATE -#endif - -/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ -#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) -# define _SCL_SECURE_NO_DEPRECATE -#endif - -/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */ -#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) -# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 -#endif - -/* Intel's compiler complains if a variable which was never initialised is - * cast to void, which is a common idiom which we use to indicate that we - * are aware a variable isn't used. So we just silence that warning. - * See: https://github.com/swig/swig/issues/192 for more discussion. - */ -#ifdef __INTEL_COMPILER -# pragma warning disable 592 -#endif - - -#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG) -/* Use debug wrappers with the Python release dll */ -# undef _DEBUG -# include -# define _DEBUG -#else -# include -#endif - -/* ----------------------------------------------------------------------------- - * swigrun.swg - * - * This file contains generic C API SWIG runtime support for pointer - * type checking. - * ----------------------------------------------------------------------------- */ - -/* This should only be incremented when either the layout of swig_type_info changes, - or for whatever reason, the runtime changes incompatibly */ -#define SWIG_RUNTIME_VERSION "4" - -/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ -#ifdef SWIG_TYPE_TABLE -# define SWIG_QUOTE_STRING(x) #x -# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) -# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) -#else -# define SWIG_TYPE_TABLE_NAME -#endif - -/* - You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for - creating a static or dynamic library from the SWIG runtime code. - In 99.9% of the cases, SWIG just needs to declare them as 'static'. - - But only do this if strictly necessary, ie, if you have problems - with your compiler or suchlike. -*/ - -#ifndef SWIGRUNTIME -# define SWIGRUNTIME SWIGINTERN -#endif - -#ifndef SWIGRUNTIMEINLINE -# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE -#endif - -/* Generic buffer size */ -#ifndef SWIG_BUFFER_SIZE -# define SWIG_BUFFER_SIZE 1024 -#endif - -/* Flags for pointer conversions */ -#define SWIG_POINTER_DISOWN 0x1 -#define SWIG_CAST_NEW_MEMORY 0x2 - -/* Flags for new pointer objects */ -#define SWIG_POINTER_OWN 0x1 - - -/* - Flags/methods for returning states. - - The SWIG conversion methods, as ConvertPtr, return an integer - that tells if the conversion was successful or not. And if not, - an error code can be returned (see swigerrors.swg for the codes). - - Use the following macros/flags to set or process the returning - states. - - In old versions of SWIG, code such as the following was usually written: - - if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { - // success code - } else { - //fail code - } - - Now you can be more explicit: - - int res = SWIG_ConvertPtr(obj,vptr,ty.flags); - if (SWIG_IsOK(res)) { - // success code - } else { - // fail code - } - - which is the same really, but now you can also do - - Type *ptr; - int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); - if (SWIG_IsOK(res)) { - // success code - if (SWIG_IsNewObj(res) { - ... - delete *ptr; - } else { - ... - } - } else { - // fail code - } - - I.e., now SWIG_ConvertPtr can return new objects and you can - identify the case and take care of the deallocation. Of course that - also requires SWIG_ConvertPtr to return new result values, such as - - int SWIG_ConvertPtr(obj, ptr,...) { - if () { - if () { - *ptr = ; - return SWIG_NEWOBJ; - } else { - *ptr = ; - return SWIG_OLDOBJ; - } - } else { - return SWIG_BADOBJ; - } - } - - Of course, returning the plain '0(success)/-1(fail)' still works, but you can be - more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the - SWIG errors code. - - Finally, if the SWIG_CASTRANK_MODE is enabled, the result code - allows to return the 'cast rank', for example, if you have this - - int food(double) - int fooi(int); - - and you call - - food(1) // cast rank '1' (1 -> 1.0) - fooi(1) // cast rank '0' - - just use the SWIG_AddCast()/SWIG_CheckState() -*/ - -#define SWIG_OK (0) -#define SWIG_ERROR (-1) -#define SWIG_IsOK(r) (r >= 0) -#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) - -/* The CastRankLimit says how many bits are used for the cast rank */ -#define SWIG_CASTRANKLIMIT (1 << 8) -/* The NewMask denotes the object was created (using new/malloc) */ -#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) -/* The TmpMask is for in/out typemaps that use temporal objects */ -#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) -/* Simple returning values */ -#define SWIG_BADOBJ (SWIG_ERROR) -#define SWIG_OLDOBJ (SWIG_OK) -#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) -#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) -/* Check, add and del mask methods */ -#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) -#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) -#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) -#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) -#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) -#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) - -/* Cast-Rank Mode */ -#if defined(SWIG_CASTRANK_MODE) -# ifndef SWIG_TypeRank -# define SWIG_TypeRank unsigned long -# endif -# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ -# define SWIG_MAXCASTRANK (2) -# endif -# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) -# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) -SWIGINTERNINLINE int SWIG_AddCast(int r) { - return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; -} -SWIGINTERNINLINE int SWIG_CheckState(int r) { - return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; -} -#else /* no cast-rank mode */ -# define SWIG_AddCast(r) (r) -# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) -#endif - - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void *(*swig_converter_func)(void *, int *); -typedef struct swig_type_info *(*swig_dycast_func)(void **); - -/* Structure to store information on one type */ -typedef struct swig_type_info { - const char *name; /* mangled name of this type */ - const char *str; /* human readable name of this type */ - swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ - struct swig_cast_info *cast; /* linked list of types that can cast into this type */ - void *clientdata; /* language specific type data */ - int owndata; /* flag if the structure owns the clientdata */ -} swig_type_info; - -/* Structure to store a type and conversion function used for casting */ -typedef struct swig_cast_info { - swig_type_info *type; /* pointer to type that is equivalent to this type */ - swig_converter_func converter; /* function to cast the void pointers */ - struct swig_cast_info *next; /* pointer to next cast in linked list */ - struct swig_cast_info *prev; /* pointer to the previous cast */ -} swig_cast_info; - -/* Structure used to store module information - * Each module generates one structure like this, and the runtime collects - * all of these structures and stores them in a circularly linked list.*/ -typedef struct swig_module_info { - swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ - size_t size; /* Number of types in this module */ - struct swig_module_info *next; /* Pointer to next element in circularly linked list */ - swig_type_info **type_initial; /* Array of initially generated type structures */ - swig_cast_info **cast_initial; /* Array of initially generated casting structures */ - void *clientdata; /* Language specific module data */ -} swig_module_info; - -/* - Compare two type names skipping the space characters, therefore - "char*" == "char *" and "Class" == "Class", etc. - - Return 0 when the two name types are equivalent, as in - strncmp, but skipping ' '. -*/ -SWIGRUNTIME int -SWIG_TypeNameComp(const char *f1, const char *l1, - const char *f2, const char *l2) { - for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { - while ((*f1 == ' ') && (f1 != l1)) ++f1; - while ((*f2 == ' ') && (f2 != l2)) ++f2; - if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; - } - return (int)((l1 - f1) - (l2 - f2)); -} - -/* - Check type equivalence in a name list like ||... - Return 0 if equal, -1 if nb < tb, 1 if nb > tb -*/ -SWIGRUNTIME int -SWIG_TypeCmp(const char *nb, const char *tb) { - int equiv = 1; - const char* te = tb + strlen(tb); - const char* ne = nb; - while (equiv != 0 && *ne) { - for (nb = ne; *ne; ++ne) { - if (*ne == '|') break; - } - equiv = SWIG_TypeNameComp(nb, ne, tb, te); - if (*ne) ++ne; - } - return equiv; -} - -/* - Check type equivalence in a name list like ||... - Return 0 if not equal, 1 if equal -*/ -SWIGRUNTIME int -SWIG_TypeEquiv(const char *nb, const char *tb) { - return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0; -} - -/* - Check the typename -*/ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheck(const char *c, swig_type_info *ty) { - if (ty) { - swig_cast_info *iter = ty->cast; - while (iter) { - if (strcmp(iter->type->name, c) == 0) { - if (iter == ty->cast) - return iter; - /* Move iter to the top of the linked list */ - iter->prev->next = iter->next; - if (iter->next) - iter->next->prev = iter->prev; - iter->next = ty->cast; - iter->prev = 0; - if (ty->cast) ty->cast->prev = iter; - ty->cast = iter; - return iter; - } - iter = iter->next; - } - } - return 0; -} - -/* - Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison -*/ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) { - if (ty) { - swig_cast_info *iter = ty->cast; - while (iter) { - if (iter->type == from) { - if (iter == ty->cast) - return iter; - /* Move iter to the top of the linked list */ - iter->prev->next = iter->next; - if (iter->next) - iter->next->prev = iter->prev; - iter->next = ty->cast; - iter->prev = 0; - if (ty->cast) ty->cast->prev = iter; - ty->cast = iter; - return iter; - } - iter = iter->next; - } - } - return 0; -} - -/* - Cast a pointer up an inheritance hierarchy -*/ -SWIGRUNTIMEINLINE void * -SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) { - return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory); -} - -/* - Dynamic pointer casting. Down an inheritance hierarchy -*/ -SWIGRUNTIME swig_type_info * -SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { - swig_type_info *lastty = ty; - if (!ty || !ty->dcast) return ty; - while (ty && (ty->dcast)) { - ty = (*ty->dcast)(ptr); - if (ty) lastty = ty; - } - return lastty; -} - -/* - Return the name associated with this type -*/ -SWIGRUNTIMEINLINE const char * -SWIG_TypeName(const swig_type_info *ty) { - return ty->name; -} - -/* - Return the pretty name associated with this type, - that is an unmangled type name in a form presentable to the user. -*/ -SWIGRUNTIME const char * -SWIG_TypePrettyName(const swig_type_info *type) { - /* The "str" field contains the equivalent pretty names of the - type, separated by vertical-bar characters. We choose - to print the last name, as it is often (?) the most - specific. */ - if (!type) return NULL; - if (type->str != NULL) { - const char *last_name = type->str; - const char *s; - for (s = type->str; *s; s++) - if (*s == '|') last_name = s+1; - return last_name; - } - else - return type->name; -} - -/* - Set the clientdata field for a type -*/ -SWIGRUNTIME void -SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { - swig_cast_info *cast = ti->cast; - /* if (ti->clientdata == clientdata) return; */ - ti->clientdata = clientdata; - - while (cast) { - if (!cast->converter) { - swig_type_info *tc = cast->type; - if (!tc->clientdata) { - SWIG_TypeClientData(tc, clientdata); - } - } - cast = cast->next; - } -} -SWIGRUNTIME void -SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { - SWIG_TypeClientData(ti, clientdata); - ti->owndata = 1; -} - -/* - Search for a swig_type_info structure only by mangled name - Search is a O(log #types) - - We start searching at module start, and finish searching when start == end. - Note: if start == end at the beginning of the function, we go all the way around - the circular list. -*/ -SWIGRUNTIME swig_type_info * -SWIG_MangledTypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - swig_module_info *iter = start; - do { - if (iter->size) { - size_t l = 0; - size_t r = iter->size - 1; - do { - /* since l+r >= 0, we can (>> 1) instead (/ 2) */ - size_t i = (l + r) >> 1; - const char *iname = iter->types[i]->name; - if (iname) { - int compare = strcmp(name, iname); - if (compare == 0) { - return iter->types[i]; - } else if (compare < 0) { - if (i) { - r = i - 1; - } else { - break; - } - } else if (compare > 0) { - l = i + 1; - } - } else { - break; /* should never happen */ - } - } while (l <= r); - } - iter = iter->next; - } while (iter != end); - return 0; -} - -/* - Search for a swig_type_info structure for either a mangled name or a human readable name. - It first searches the mangled names of the types, which is a O(log #types) - If a type is not found it then searches the human readable names, which is O(#types). - - We start searching at module start, and finish searching when start == end. - Note: if start == end at the beginning of the function, we go all the way around - the circular list. -*/ -SWIGRUNTIME swig_type_info * -SWIG_TypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - /* STEP 1: Search the name field using binary search */ - swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); - if (ret) { - return ret; - } else { - /* STEP 2: If the type hasn't been found, do a complete search - of the str field (the human readable name) */ - swig_module_info *iter = start; - do { - size_t i = 0; - for (; i < iter->size; ++i) { - if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) - return iter->types[i]; - } - iter = iter->next; - } while (iter != end); - } - - /* neither found a match */ - return 0; -} - -/* - Pack binary data into a string -*/ -SWIGRUNTIME char * -SWIG_PackData(char *c, void *ptr, size_t sz) { - static const char hex[17] = "0123456789abcdef"; - const unsigned char *u = (unsigned char *) ptr; - const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - unsigned char uu = *u; - *(c++) = hex[(uu & 0xf0) >> 4]; - *(c++) = hex[uu & 0xf]; - } - return c; -} - -/* - Unpack binary data from a string -*/ -SWIGRUNTIME const char * -SWIG_UnpackData(const char *c, void *ptr, size_t sz) { - unsigned char *u = (unsigned char *) ptr; - const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - char d = *(c++); - unsigned char uu; - if ((d >= '0') && (d <= '9')) - uu = (unsigned char)((d - '0') << 4); - else if ((d >= 'a') && (d <= 'f')) - uu = (unsigned char)((d - ('a'-10)) << 4); - else - return (char *) 0; - d = *(c++); - if ((d >= '0') && (d <= '9')) - uu |= (unsigned char)(d - '0'); - else if ((d >= 'a') && (d <= 'f')) - uu |= (unsigned char)(d - ('a'-10)); - else - return (char *) 0; - *u = uu; - } - return c; -} - -/* - Pack 'void *' into a string buffer. -*/ -SWIGRUNTIME char * -SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { - char *r = buff; - if ((2*sizeof(void *) + 2) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,&ptr,sizeof(void *)); - if (strlen(name) + 1 > (bsz - (r - buff))) return 0; - strcpy(r,name); - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - *ptr = (void *) 0; - return name; - } else { - return 0; - } - } - return SWIG_UnpackData(++c,ptr,sizeof(void *)); -} - -SWIGRUNTIME char * -SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { - char *r = buff; - size_t lname = (name ? strlen(name) : 0); - if ((2*sz + 2 + lname) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,ptr,sz); - if (lname) { - strncpy(r,name,lname+1); - } else { - *r = 0; - } - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - memset(ptr,0,sz); - return name; - } else { - return 0; - } - } - return SWIG_UnpackData(++c,ptr,sz); -} - -#ifdef __cplusplus -} -#endif - -/* Errors in SWIG */ -#define SWIG_UnknownError -1 -#define SWIG_IOError -2 -#define SWIG_RuntimeError -3 -#define SWIG_IndexError -4 -#define SWIG_TypeError -5 -#define SWIG_DivisionByZero -6 -#define SWIG_OverflowError -7 -#define SWIG_SyntaxError -8 -#define SWIG_ValueError -9 -#define SWIG_SystemError -10 -#define SWIG_AttributeError -11 -#define SWIG_MemoryError -12 -#define SWIG_NullReferenceError -13 - - - -/* Compatibility macros for Python 3 */ -#if PY_VERSION_HEX >= 0x03000000 - -#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type) -#define PyInt_Check(x) PyLong_Check(x) -#define PyInt_AsLong(x) PyLong_AsLong(x) -#define PyInt_FromLong(x) PyLong_FromLong(x) -#define PyInt_FromSize_t(x) PyLong_FromSize_t(x) -#define PyString_Check(name) PyBytes_Check(name) -#define PyString_FromString(x) PyUnicode_FromString(x) -#define PyString_FromStringAndSize(x, y) PyBytes_FromStringAndSize(x, y) -#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args) -#define PyString_AsString(str) PyBytes_AsString(str) -#define PyString_Size(str) PyBytes_Size(str) -#define PyString_InternFromString(key) PyUnicode_InternFromString(key) -#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE -#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x) -#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x) - -#endif - -#ifndef Py_TYPE -# define Py_TYPE(op) ((op)->ob_type) -#endif - -/* SWIG APIs for compatibility of both Python 2 & 3 */ - -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_Python_str_FromFormat PyUnicode_FromFormat -#else -# define SWIG_Python_str_FromFormat PyString_FromFormat -#endif - - -/* Warning: This function will allocate a new string in Python 3, - * so please call SWIG_Python_str_DelForPy3(x) to free the space. - */ -SWIGINTERN char* -SWIG_Python_str_AsChar(PyObject *str) -{ -#if PY_VERSION_HEX >= 0x03000000 - char *cstr; - char *newstr; - Py_ssize_t len; - str = PyUnicode_AsUTF8String(str); - PyBytes_AsStringAndSize(str, &cstr, &len); - newstr = (char *) malloc(len+1); - memcpy(newstr, cstr, len+1); - Py_XDECREF(str); - return newstr; -#else - return PyString_AsString(str); -#endif -} - -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_Python_str_DelForPy3(x) free( (void*) (x) ) -#else -# define SWIG_Python_str_DelForPy3(x) -#endif - - -SWIGINTERN PyObject* -SWIG_Python_str_FromChar(const char *c) -{ -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_FromString(c); -#else - return PyString_FromString(c); -#endif -} - -/* Add PyOS_snprintf for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) -# define PyOS_snprintf _snprintf -# else -# define PyOS_snprintf snprintf -# endif -#endif - -/* A crude PyString_FromFormat implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 - -#ifndef SWIG_PYBUFFER_SIZE -# define SWIG_PYBUFFER_SIZE 1024 -#endif - -static PyObject * -PyString_FromFormat(const char *fmt, ...) { - va_list ap; - char buf[SWIG_PYBUFFER_SIZE * 2]; - int res; - va_start(ap, fmt); - res = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf); -} -#endif - -#ifndef PyObject_DEL -# define PyObject_DEL PyObject_Del -#endif - -/* A crude PyExc_StopIteration exception for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# ifndef PyExc_StopIteration -# define PyExc_StopIteration PyExc_RuntimeError -# endif -# ifndef PyObject_GenericGetAttr -# define PyObject_GenericGetAttr 0 -# endif -#endif - -/* Py_NotImplemented is defined in 2.1 and up. */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef Py_NotImplemented -# define Py_NotImplemented PyExc_RuntimeError -# endif -#endif - -/* A crude PyString_AsStringAndSize implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef PyString_AsStringAndSize -# define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;} -# endif -#endif - -/* PySequence_Size for old Pythons */ -#if PY_VERSION_HEX < 0x02000000 -# ifndef PySequence_Size -# define PySequence_Size PySequence_Length -# endif -#endif - -/* PyBool_FromLong for old Pythons */ -#if PY_VERSION_HEX < 0x02030000 -static -PyObject *PyBool_FromLong(long ok) -{ - PyObject *result = ok ? Py_True : Py_False; - Py_INCREF(result); - return result; -} -#endif - -/* Py_ssize_t for old Pythons */ -/* This code is as recommended by: */ -/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */ -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -# define PY_SSIZE_T_MAX INT_MAX -# define PY_SSIZE_T_MIN INT_MIN -typedef inquiry lenfunc; -typedef intargfunc ssizeargfunc; -typedef intintargfunc ssizessizeargfunc; -typedef intobjargproc ssizeobjargproc; -typedef intintobjargproc ssizessizeobjargproc; -typedef getreadbufferproc readbufferproc; -typedef getwritebufferproc writebufferproc; -typedef getsegcountproc segcountproc; -typedef getcharbufferproc charbufferproc; -static long PyNumber_AsSsize_t (PyObject *x, void *SWIGUNUSEDPARM(exc)) -{ - long result = 0; - PyObject *i = PyNumber_Int(x); - if (i) { - result = PyInt_AsLong(i); - Py_DECREF(i); - } - return result; -} -#endif - -#if PY_VERSION_HEX < 0x02050000 -#define PyInt_FromSize_t(x) PyInt_FromLong((long)x) -#endif - -#if PY_VERSION_HEX < 0x02040000 -#define Py_VISIT(op) \ - do { \ - if (op) { \ - int vret = visit((op), arg); \ - if (vret) \ - return vret; \ - } \ - } while (0) -#endif - -#if PY_VERSION_HEX < 0x02030000 -typedef struct { - PyTypeObject type; - PyNumberMethods as_number; - PyMappingMethods as_mapping; - PySequenceMethods as_sequence; - PyBufferProcs as_buffer; - PyObject *name, *slots; -} PyHeapTypeObject; -#endif - -#if PY_VERSION_HEX < 0x02030000 -typedef destructor freefunc; -#endif - -#if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 6) || \ - (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 0) || \ - (PY_MAJOR_VERSION > 3)) -# define SWIGPY_USE_CAPSULE -# define SWIGPY_CAPSULE_NAME ((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME) -#endif - -#if PY_VERSION_HEX < 0x03020000 -#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type) -#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name) -#define Py_hash_t long -#endif - -/* ----------------------------------------------------------------------------- - * error manipulation - * ----------------------------------------------------------------------------- */ - -SWIGRUNTIME PyObject* -SWIG_Python_ErrorType(int code) { - PyObject* type = 0; - switch(code) { - case SWIG_MemoryError: - type = PyExc_MemoryError; - break; - case SWIG_IOError: - type = PyExc_IOError; - break; - case SWIG_RuntimeError: - type = PyExc_RuntimeError; - break; - case SWIG_IndexError: - type = PyExc_IndexError; - break; - case SWIG_TypeError: - type = PyExc_TypeError; - break; - case SWIG_DivisionByZero: - type = PyExc_ZeroDivisionError; - break; - case SWIG_OverflowError: - type = PyExc_OverflowError; - break; - case SWIG_SyntaxError: - type = PyExc_SyntaxError; - break; - case SWIG_ValueError: - type = PyExc_ValueError; - break; - case SWIG_SystemError: - type = PyExc_SystemError; - break; - case SWIG_AttributeError: - type = PyExc_AttributeError; - break; - default: - type = PyExc_RuntimeError; - } - return type; -} - - -SWIGRUNTIME void -SWIG_Python_AddErrorMsg(const char* mesg) -{ - PyObject *type = 0; - PyObject *value = 0; - PyObject *traceback = 0; - - if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback); - if (value) { - char *tmp; - PyObject *old_str = PyObject_Str(value); - PyErr_Clear(); - Py_XINCREF(type); - - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(old_str); - Py_DECREF(value); - } else { - PyErr_SetString(PyExc_RuntimeError, mesg); - } -} - -#if defined(SWIG_PYTHON_NO_THREADS) -# if defined(SWIG_PYTHON_THREADS) -# undef SWIG_PYTHON_THREADS -# endif -#endif -#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */ -# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL) -# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */ -# define SWIG_PYTHON_USE_GIL -# endif -# endif -# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */ -# ifndef SWIG_PYTHON_INITIALIZE_THREADS -# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads() -# endif -# ifdef __cplusplus /* C++ code */ - class SWIG_Python_Thread_Block { - bool status; - PyGILState_STATE state; - public: - void end() { if (status) { PyGILState_Release(state); status = false;} } - SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {} - ~SWIG_Python_Thread_Block() { end(); } - }; - class SWIG_Python_Thread_Allow { - bool status; - PyThreadState *save; - public: - void end() { if (status) { PyEval_RestoreThread(save); status = false; }} - SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {} - ~SWIG_Python_Thread_Allow() { end(); } - }; -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block -# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end() -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow -# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end() -# else /* C code */ -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure() -# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block) -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread() -# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow) -# endif -# else /* Old thread way, not implemented, user must provide it */ -# if !defined(SWIG_PYTHON_INITIALIZE_THREADS) -# define SWIG_PYTHON_INITIALIZE_THREADS -# endif -# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK) -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK -# endif -# if !defined(SWIG_PYTHON_THREAD_END_BLOCK) -# define SWIG_PYTHON_THREAD_END_BLOCK -# endif -# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW) -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW -# endif -# if !defined(SWIG_PYTHON_THREAD_END_ALLOW) -# define SWIG_PYTHON_THREAD_END_ALLOW -# endif -# endif -#else /* No thread support */ -# define SWIG_PYTHON_INITIALIZE_THREADS -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK -# define SWIG_PYTHON_THREAD_END_BLOCK -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW -# define SWIG_PYTHON_THREAD_END_ALLOW -#endif - -/* ----------------------------------------------------------------------------- - * Python API portion that goes into the runtime - * ----------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* ----------------------------------------------------------------------------- - * Constant declarations - * ----------------------------------------------------------------------------- */ - -/* Constant Types */ -#define SWIG_PY_POINTER 4 -#define SWIG_PY_BINARY 5 - -/* Constant information structure */ -typedef struct swig_const_info { - int type; - char *name; - long lvalue; - double dvalue; - void *pvalue; - swig_type_info **ptype; -} swig_const_info; - - -/* ----------------------------------------------------------------------------- - * Wrapper of PyInstanceMethod_New() used in Python 3 - * It is exported to the generated module, used for -fastproxy - * ----------------------------------------------------------------------------- */ -#if PY_VERSION_HEX >= 0x03000000 -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func) -{ - return PyInstanceMethod_New(func); -} -#else -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func)) -{ - return NULL; -} -#endif - -#ifdef __cplusplus -} -#endif - - -/* ----------------------------------------------------------------------------- - * pyrun.swg - * - * This file contains the runtime support for Python modules - * and includes code for managing global variables and pointer - * type checking. - * - * ----------------------------------------------------------------------------- */ - -/* Common SWIG API */ - -/* for raw pointers */ -#define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) -#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) -#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) - -#ifdef SWIGPYTHON_BUILTIN -#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(self, ptr, type, flags) -#else -#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) -#endif - -#define SWIG_InternalNewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) - -#define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty) -#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) -#define swig_owntype int - -/* for raw packed data */ -#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) -#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) - -/* for class or struct pointers */ -#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) -#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) - -/* for C or C++ function pointers */ -#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) -#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(NULL, ptr, type, 0) - -/* for C++ member pointers, ie, member methods */ -#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) -#define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) - - -/* Runtime API */ - -#define SWIG_GetModule(clientdata) SWIG_Python_GetModule(clientdata) -#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer) -#define SWIG_NewClientData(obj) SwigPyClientData_New(obj) - -#define SWIG_SetErrorObj SWIG_Python_SetErrorObj -#define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg -#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code) -#define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) -#define SWIG_fail goto fail - - -/* Runtime API implementation */ - -/* Error manipulation */ - -SWIGINTERN void -SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetObject(errtype, obj); - Py_DECREF(obj); - SWIG_PYTHON_THREAD_END_BLOCK; -} - -SWIGINTERN void -SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(errtype, msg); - SWIG_PYTHON_THREAD_END_BLOCK; -} - -#define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj) - -/* Set a constant value */ - -#if defined(SWIGPYTHON_BUILTIN) - -SWIGINTERN void -SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) { - PyObject *s = PyString_InternFromString(key); - PyList_Append(seq, s); - Py_DECREF(s); -} - -SWIGINTERN void -SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) { -#if PY_VERSION_HEX < 0x02030000 - PyDict_SetItemString(d, (char *)name, obj); -#else - PyDict_SetItemString(d, name, obj); -#endif - Py_DECREF(obj); - if (public_interface) - SwigPyBuiltin_AddPublicSymbol(public_interface, name); -} - -#else - -SWIGINTERN void -SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { -#if PY_VERSION_HEX < 0x02030000 - PyDict_SetItemString(d, (char *)name, obj); -#else - PyDict_SetItemString(d, name, obj); -#endif - Py_DECREF(obj); -} - -#endif - -/* Append a value to the result obj */ - -SWIGINTERN PyObject* -SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { -#if !defined(SWIG_PYTHON_OUTPUT_TUPLE) - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyList_Check(result)) { - PyObject *o2 = result; - result = PyList_New(1); - PyList_SetItem(result, 0, o2); - } - PyList_Append(result,obj); - Py_DECREF(obj); - } - return result; -#else - PyObject* o2; - PyObject* o3; - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyTuple_Check(result)) { - o2 = result; - result = PyTuple_New(1); - PyTuple_SET_ITEM(result, 0, o2); - } - o3 = PyTuple_New(1); - PyTuple_SET_ITEM(o3, 0, obj); - o2 = result; - result = PySequence_Concat(o2, o3); - Py_DECREF(o2); - Py_DECREF(o3); - } - return result; -#endif -} - -/* Unpack the argument tuple */ - -SWIGINTERN Py_ssize_t -SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs) -{ - if (!args) { - if (!min && !max) { - return 1; - } else { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", - name, (min == max ? "" : "at least "), (int)min); - return 0; - } - } - if (!PyTuple_Check(args)) { - if (min <= 1 && max >= 1) { - Py_ssize_t i; - objs[0] = args; - for (i = 1; i < max; ++i) { - objs[i] = 0; - } - return 2; - } - PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple"); - return 0; - } else { - Py_ssize_t l = PyTuple_GET_SIZE(args); - if (l < min) { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", - name, (min == max ? "" : "at least "), (int)min, (int)l); - return 0; - } else if (l > max) { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", - name, (min == max ? "" : "at most "), (int)max, (int)l); - return 0; - } else { - Py_ssize_t i; - for (i = 0; i < l; ++i) { - objs[i] = PyTuple_GET_ITEM(args, i); - } - for (; l < max; ++l) { - objs[l] = 0; - } - return i + 1; - } - } -} - -/* A functor is a function object with one single object argument */ -#if PY_VERSION_HEX >= 0x02020000 -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL); -#else -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunction(functor, "O", obj); -#endif - -/* - Helper for static pointer initialization for both C and C++ code, for example - static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...); -*/ -#ifdef __cplusplus -#define SWIG_STATIC_POINTER(var) var -#else -#define SWIG_STATIC_POINTER(var) var = 0; if (!var) var -#endif - -/* ----------------------------------------------------------------------------- - * Pointer declarations - * ----------------------------------------------------------------------------- */ - -/* Flags for new pointer objects */ -#define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1) -#define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN) - -#define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1) - -#define SWIG_BUILTIN_TP_INIT (SWIG_POINTER_OWN << 2) -#define SWIG_BUILTIN_INIT (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN) - -#ifdef __cplusplus -extern "C" { -#endif - -/* How to access Py_None */ -#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# ifndef SWIG_PYTHON_NO_BUILD_NONE -# ifndef SWIG_PYTHON_BUILD_NONE -# define SWIG_PYTHON_BUILD_NONE -# endif -# endif -#endif - -#ifdef SWIG_PYTHON_BUILD_NONE -# ifdef Py_None -# undef Py_None -# define Py_None SWIG_Py_None() -# endif -SWIGRUNTIMEINLINE PyObject * -_SWIG_Py_None(void) -{ - PyObject *none = Py_BuildValue((char*)""); - Py_DECREF(none); - return none; -} -SWIGRUNTIME PyObject * -SWIG_Py_None(void) -{ - static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None(); - return none; -} -#endif - -/* The python void return value */ - -SWIGRUNTIMEINLINE PyObject * -SWIG_Py_Void(void) -{ - PyObject *none = Py_None; - Py_INCREF(none); - return none; -} - -/* SwigPyClientData */ - -typedef struct { - PyObject *klass; - PyObject *newraw; - PyObject *newargs; - PyObject *destroy; - int delargs; - int implicitconv; - PyTypeObject *pytype; -} SwigPyClientData; - -SWIGRUNTIMEINLINE int -SWIG_Python_CheckImplicit(swig_type_info *ty) -{ - SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; - return data ? data->implicitconv : 0; -} - -SWIGRUNTIMEINLINE PyObject * -SWIG_Python_ExceptionType(swig_type_info *desc) { - SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0; - PyObject *klass = data ? data->klass : 0; - return (klass ? klass : PyExc_RuntimeError); -} - - -SWIGRUNTIME SwigPyClientData * -SwigPyClientData_New(PyObject* obj) -{ - if (!obj) { - return 0; - } else { - SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData)); - /* the klass element */ - data->klass = obj; - Py_INCREF(data->klass); - /* the newraw method and newargs arguments used to create a new raw instance */ - if (PyClass_Check(obj)) { - data->newraw = 0; - data->newargs = obj; - Py_INCREF(obj); - } else { -#if (PY_VERSION_HEX < 0x02020000) - data->newraw = 0; -#else - data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__"); -#endif - if (data->newraw) { - Py_INCREF(data->newraw); - data->newargs = PyTuple_New(1); - PyTuple_SetItem(data->newargs, 0, obj); - } else { - data->newargs = obj; - } - Py_INCREF(data->newargs); - } - /* the destroy method, aka as the C++ delete method */ - data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__"); - if (PyErr_Occurred()) { - PyErr_Clear(); - data->destroy = 0; - } - if (data->destroy) { - int flags; - Py_INCREF(data->destroy); - flags = PyCFunction_GET_FLAGS(data->destroy); -#ifdef METH_O - data->delargs = !(flags & (METH_O)); -#else - data->delargs = 0; -#endif - } else { - data->delargs = 0; - } - data->implicitconv = 0; - data->pytype = 0; - return data; - } -} - -SWIGRUNTIME void -SwigPyClientData_Del(SwigPyClientData *data) { - Py_XDECREF(data->newraw); - Py_XDECREF(data->newargs); - Py_XDECREF(data->destroy); -} - -/* =============== SwigPyObject =====================*/ - -typedef struct { - PyObject_HEAD - void *ptr; - swig_type_info *ty; - int own; - PyObject *next; -#ifdef SWIGPYTHON_BUILTIN - PyObject *dict; -#endif -} SwigPyObject; - - -#ifdef SWIGPYTHON_BUILTIN - -SWIGRUNTIME PyObject * -SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args)) -{ - SwigPyObject *sobj = (SwigPyObject *)v; - - if (!sobj->dict) - sobj->dict = PyDict_New(); - - Py_INCREF(sobj->dict); - return sobj->dict; -} - -#endif - -SWIGRUNTIME PyObject * -SwigPyObject_long(SwigPyObject *v) -{ - return PyLong_FromVoidPtr(v->ptr); -} - -SWIGRUNTIME PyObject * -SwigPyObject_format(const char* fmt, SwigPyObject *v) -{ - PyObject *res = NULL; - PyObject *args = PyTuple_New(1); - if (args) { - if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) { - PyObject *ofmt = SWIG_Python_str_FromChar(fmt); - if (ofmt) { -#if PY_VERSION_HEX >= 0x03000000 - res = PyUnicode_Format(ofmt,args); -#else - res = PyString_Format(ofmt,args); -#endif - Py_DECREF(ofmt); - } - Py_DECREF(args); - } - } - return res; -} - -SWIGRUNTIME PyObject * -SwigPyObject_oct(SwigPyObject *v) -{ - return SwigPyObject_format("%o",v); -} - -SWIGRUNTIME PyObject * -SwigPyObject_hex(SwigPyObject *v) -{ - return SwigPyObject_format("%x",v); -} - -SWIGRUNTIME PyObject * -#ifdef METH_NOARGS -SwigPyObject_repr(SwigPyObject *v) -#else -SwigPyObject_repr(SwigPyObject *v, PyObject *args) -#endif -{ - const char *name = SWIG_TypePrettyName(v->ty); - PyObject *repr = SWIG_Python_str_FromFormat("", (name ? name : "unknown"), (void *)v); - if (v->next) { -# ifdef METH_NOARGS - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); -# else - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args); -# endif -# if PY_VERSION_HEX >= 0x03000000 - PyObject *joined = PyUnicode_Concat(repr, nrep); - Py_DecRef(repr); - Py_DecRef(nrep); - repr = joined; -# else - PyString_ConcatAndDel(&repr,nrep); -# endif - } - return repr; -} - -/* We need a version taking two PyObject* parameters so it's a valid - * PyCFunction to use in swigobject_methods[]. */ -SWIGRUNTIME PyObject * -SwigPyObject_repr2(PyObject *v, PyObject *SWIGUNUSEDPARM(args)) -{ - return SwigPyObject_repr((SwigPyObject*)v); -} - -SWIGRUNTIME int -SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w) -{ - void *i = v->ptr; - void *j = w->ptr; - return (i < j) ? -1 : ((i > j) ? 1 : 0); -} - -/* Added for Python 3.x, would it also be useful for Python 2.x? */ -SWIGRUNTIME PyObject* -SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op) -{ - PyObject* res; - if( op != Py_EQ && op != Py_NE ) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0); - return res; -} - - -SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void); - -#ifdef SWIGPYTHON_BUILTIN -static swig_type_info *SwigPyObject_stype = 0; -SWIGRUNTIME PyTypeObject* -SwigPyObject_type(void) { - SwigPyClientData *cd; - assert(SwigPyObject_stype); - cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; - assert(cd); - assert(cd->pytype); - return cd->pytype; -} -#else -SWIGRUNTIME PyTypeObject* -SwigPyObject_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce(); - return type; -} -#endif - -SWIGRUNTIMEINLINE int -SwigPyObject_Check(PyObject *op) { -#ifdef SWIGPYTHON_BUILTIN - PyTypeObject *target_tp = SwigPyObject_type(); - if (PyType_IsSubtype(op->ob_type, target_tp)) - return 1; - return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0); -#else - return (Py_TYPE(op) == SwigPyObject_type()) - || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0); -#endif -} - -SWIGRUNTIME PyObject * -SwigPyObject_New(void *ptr, swig_type_info *ty, int own); - -SWIGRUNTIME void -SwigPyObject_dealloc(PyObject *v) -{ - SwigPyObject *sobj = (SwigPyObject *) v; - PyObject *next = sobj->next; - if (sobj->own == SWIG_POINTER_OWN) { - swig_type_info *ty = sobj->ty; - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - PyObject *destroy = data ? data->destroy : 0; - if (destroy) { - /* destroy is always a VARARGS method */ - PyObject *res; - - /* PyObject_CallFunction() has the potential to silently drop - the active active exception. In cases of unnamed temporary - variable or where we just finished iterating over a generator - StopIteration will be active right now, and this needs to - remain true upon return from SwigPyObject_dealloc. So save - and restore. */ - - PyObject *val = NULL, *type = NULL, *tb = NULL; - PyErr_Fetch(&val, &type, &tb); - - if (data->delargs) { - /* we need to create a temporary object to carry the destroy operation */ - PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0); - res = SWIG_Python_CallFunctor(destroy, tmp); - Py_DECREF(tmp); - } else { - PyCFunction meth = PyCFunction_GET_FUNCTION(destroy); - PyObject *mself = PyCFunction_GET_SELF(destroy); - res = ((*meth)(mself, v)); - } - if (!res) - PyErr_WriteUnraisable(destroy); - - PyErr_Restore(val, type, tb); - - Py_XDECREF(res); - } -#if !defined(SWIG_PYTHON_SILENT_MEMLEAK) - else { - const char *name = SWIG_TypePrettyName(ty); - printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown")); - } -#endif - } - Py_XDECREF(next); - PyObject_DEL(v); -} - -SWIGRUNTIME PyObject* -SwigPyObject_append(PyObject* v, PyObject* next) -{ - SwigPyObject *sobj = (SwigPyObject *) v; -#ifndef METH_O - PyObject *tmp = 0; - if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL; - next = tmp; -#endif - if (!SwigPyObject_Check(next)) { - PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject"); - return NULL; - } - sobj->next = next; - Py_INCREF(next); - return SWIG_Py_Void(); -} - -SWIGRUNTIME PyObject* -SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -{ - SwigPyObject *sobj = (SwigPyObject *) v; - if (sobj->next) { - Py_INCREF(sobj->next); - return sobj->next; - } else { - return SWIG_Py_Void(); - } -} - -SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_disown(PyObject *v) -#else -SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *)v; - sobj->own = 0; - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_acquire(PyObject *v) -#else -SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *)v; - sobj->own = SWIG_POINTER_OWN; - return SWIG_Py_Void(); -} - -#ifdef METH_NOARGS -static PyObject* -SwigPyObject_disown2(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -{ - return SwigPyObject_disown(v); -} - -static PyObject* -SwigPyObject_acquire2(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -{ - return SwigPyObject_acquire(v); -} -#endif - -SWIGINTERN PyObject* -SwigPyObject_own(PyObject *v, PyObject *args) -{ - PyObject *val = 0; -#if (PY_VERSION_HEX < 0x02020000) - if (!PyArg_ParseTuple(args,(char *)"|O:own",&val)) -#elif (PY_VERSION_HEX < 0x02050000) - if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) -#else - if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) -#endif - { - return NULL; - } - else - { - SwigPyObject *sobj = (SwigPyObject *)v; - PyObject *obj = PyBool_FromLong(sobj->own); - if (val) { -#ifdef METH_NOARGS - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v); - } else { - SwigPyObject_disown(v); - } -#else - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v,args); - } else { - SwigPyObject_disown(v,args); - } -#endif - } - return obj; - } -} - -#ifdef METH_O -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown2, METH_NOARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire2,METH_NOARGS, (char *)"acquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_O, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_NOARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr2, METH_NOARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#else -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_VARARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS, (char *)"acquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_VARARGS, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_VARARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_VARARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#endif - -#if PY_VERSION_HEX < 0x02020000 -SWIGINTERN PyObject * -SwigPyObject_getattr(SwigPyObject *sobj,char *name) -{ - return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name); -} -#endif - -SWIGRUNTIME PyTypeObject* -SwigPyObject_TypeOnce(void) { - static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; - - static PyNumberMethods SwigPyObject_as_number = { - (binaryfunc)0, /*nb_add*/ - (binaryfunc)0, /*nb_subtract*/ - (binaryfunc)0, /*nb_multiply*/ - /* nb_divide removed in Python 3 */ -#if PY_VERSION_HEX < 0x03000000 - (binaryfunc)0, /*nb_divide*/ -#endif - (binaryfunc)0, /*nb_remainder*/ - (binaryfunc)0, /*nb_divmod*/ - (ternaryfunc)0,/*nb_power*/ - (unaryfunc)0, /*nb_negative*/ - (unaryfunc)0, /*nb_positive*/ - (unaryfunc)0, /*nb_absolute*/ - (inquiry)0, /*nb_nonzero*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ -#if PY_VERSION_HEX < 0x03000000 - 0, /*nb_coerce*/ -#endif - (unaryfunc)SwigPyObject_long, /*nb_int*/ -#if PY_VERSION_HEX < 0x03000000 - (unaryfunc)SwigPyObject_long, /*nb_long*/ -#else - 0, /*nb_reserved*/ -#endif - (unaryfunc)0, /*nb_float*/ -#if PY_VERSION_HEX < 0x03000000 - (unaryfunc)SwigPyObject_oct, /*nb_oct*/ - (unaryfunc)SwigPyObject_hex, /*nb_hex*/ -#endif -#if PY_VERSION_HEX >= 0x03050000 /* 3.5 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */ -#elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */ -#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */ -#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */ -#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */ - 0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */ -#endif - }; - - static PyTypeObject swigpyobject_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"SwigPyObject", /* tp_name */ - sizeof(SwigPyObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)SwigPyObject_dealloc, /* tp_dealloc */ - 0, /* tp_print */ -#if PY_VERSION_HEX < 0x02020000 - (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ -#else - (getattrfunc)0, /* tp_getattr */ -#endif - (setattrfunc)0, /* tp_setattr */ -#if PY_VERSION_HEX >= 0x03000000 - 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ -#else - (cmpfunc)SwigPyObject_compare, /* tp_compare */ -#endif - (reprfunc)SwigPyObject_repr, /* tp_repr */ - &SwigPyObject_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigobject_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0, /* tp_iter */ - 0, /* tp_iternext */ - swigobject_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 - 0, /* tp_version_tag */ -#endif -#if PY_VERSION_HEX >= 0x03040000 - 0, /* tp_finalize */ -#endif -#ifdef COUNT_ALLOCS - 0, /* tp_allocs */ - 0, /* tp_frees */ - 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 - 0, /* tp_prev */ -#endif - 0 /* tp_next */ -#endif - }; - swigpyobject_type = tmp; - type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - swigpyobject_type.ob_type = &PyType_Type; -#else - if (PyType_Ready(&swigpyobject_type) < 0) - return NULL; -#endif - } - return &swigpyobject_type; -} - -SWIGRUNTIME PyObject * -SwigPyObject_New(void *ptr, swig_type_info *ty, int own) -{ - SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type()); - if (sobj) { - sobj->ptr = ptr; - sobj->ty = ty; - sobj->own = own; - sobj->next = 0; - } - return (PyObject *)sobj; -} - -/* ----------------------------------------------------------------------------- - * Implements a simple Swig Packed type, and use it instead of string - * ----------------------------------------------------------------------------- */ - -typedef struct { - PyObject_HEAD - void *pack; - swig_type_info *ty; - size_t size; -} SwigPyPacked; - -SWIGRUNTIME int -SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags)) -{ - char result[SWIG_BUFFER_SIZE]; - fputs("pack, v->size, 0, sizeof(result))) { - fputs("at ", fp); - fputs(result, fp); - } - fputs(v->ty->name,fp); - fputs(">", fp); - return 0; -} - -SWIGRUNTIME PyObject * -SwigPyPacked_repr(SwigPyPacked *v) -{ - char result[SWIG_BUFFER_SIZE]; - if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) { - return SWIG_Python_str_FromFormat("", result, v->ty->name); - } else { - return SWIG_Python_str_FromFormat("", v->ty->name); - } -} - -SWIGRUNTIME PyObject * -SwigPyPacked_str(SwigPyPacked *v) -{ - char result[SWIG_BUFFER_SIZE]; - if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){ - return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name); - } else { - return SWIG_Python_str_FromChar(v->ty->name); - } -} - -SWIGRUNTIME int -SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) -{ - size_t i = v->size; - size_t j = w->size; - int s = (i < j) ? -1 : ((i > j) ? 1 : 0); - return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size); -} - -SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void); - -SWIGRUNTIME PyTypeObject* -SwigPyPacked_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce(); - return type; -} - -SWIGRUNTIMEINLINE int -SwigPyPacked_Check(PyObject *op) { - return ((op)->ob_type == SwigPyPacked_TypeOnce()) - || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0); -} - -SWIGRUNTIME void -SwigPyPacked_dealloc(PyObject *v) -{ - if (SwigPyPacked_Check(v)) { - SwigPyPacked *sobj = (SwigPyPacked *) v; - free(sobj->pack); - } - PyObject_DEL(v); -} - -SWIGRUNTIME PyTypeObject* -SwigPyPacked_TypeOnce(void) { - static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer"; - static PyTypeObject swigpypacked_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { -#if PY_VERSION_HEX>=0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"SwigPyPacked", /* tp_name */ - sizeof(SwigPyPacked), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ - (printfunc)SwigPyPacked_print, /* tp_print */ - (getattrfunc)0, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ -#if PY_VERSION_HEX>=0x03000000 - 0, /* tp_reserved in 3.0.1 */ -#else - (cmpfunc)SwigPyPacked_compare, /* tp_compare */ -#endif - (reprfunc)SwigPyPacked_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)SwigPyPacked_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigpacked_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 - 0, /* tp_version_tag */ -#endif -#if PY_VERSION_HEX >= 0x03040000 - 0, /* tp_finalize */ -#endif -#ifdef COUNT_ALLOCS - 0, /* tp_allocs */ - 0, /* tp_frees */ - 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 - 0, /* tp_prev */ -#endif - 0 /* tp_next */ -#endif - }; - swigpypacked_type = tmp; - type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - swigpypacked_type.ob_type = &PyType_Type; -#else - if (PyType_Ready(&swigpypacked_type) < 0) - return NULL; -#endif - } - return &swigpypacked_type; -} - -SWIGRUNTIME PyObject * -SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty) -{ - SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type()); - if (sobj) { - void *pack = malloc(size); - if (pack) { - memcpy(pack, ptr, size); - sobj->pack = pack; - sobj->ty = ty; - sobj->size = size; - } else { - PyObject_DEL((PyObject *) sobj); - sobj = 0; - } - } - return (PyObject *) sobj; -} - -SWIGRUNTIME swig_type_info * -SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size) -{ - if (SwigPyPacked_Check(obj)) { - SwigPyPacked *sobj = (SwigPyPacked *)obj; - if (sobj->size != size) return 0; - memcpy(ptr, sobj->pack, size); - return sobj->ty; - } else { - return 0; - } -} - -/* ----------------------------------------------------------------------------- - * pointers/data manipulation - * ----------------------------------------------------------------------------- */ - -SWIGRUNTIMEINLINE PyObject * -_SWIG_This(void) -{ - return SWIG_Python_str_FromChar("this"); -} - -static PyObject *swig_this = NULL; - -SWIGRUNTIME PyObject * -SWIG_This(void) -{ - if (swig_this == NULL) - swig_this = _SWIG_This(); - return swig_this; -} - -/* #define SWIG_PYTHON_SLOW_GETSET_THIS */ - -/* TODO: I don't know how to implement the fast getset in Python 3 right now */ -#if PY_VERSION_HEX>=0x03000000 -#define SWIG_PYTHON_SLOW_GETSET_THIS -#endif - -SWIGRUNTIME SwigPyObject * -SWIG_Python_GetSwigThis(PyObject *pyobj) -{ - PyObject *obj; - - if (SwigPyObject_Check(pyobj)) - return (SwigPyObject *) pyobj; - -#ifdef SWIGPYTHON_BUILTIN - (void)obj; -# ifdef PyWeakref_CheckProxy - if (PyWeakref_CheckProxy(pyobj)) { - pyobj = PyWeakref_GET_OBJECT(pyobj); - if (pyobj && SwigPyObject_Check(pyobj)) - return (SwigPyObject*) pyobj; - } -# endif - return NULL; -#else - - obj = 0; - -#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) - if (PyInstance_Check(pyobj)) { - obj = _PyInstance_Lookup(pyobj, SWIG_This()); - } else { - PyObject **dictptr = _PyObject_GetDictPtr(pyobj); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; - } else { -#ifdef PyWeakref_CheckProxy - if (PyWeakref_CheckProxy(pyobj)) { - PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); - return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; - } -#endif - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } - } - } -#else - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } -#endif - if (obj && !SwigPyObject_Check(obj)) { - /* a PyObject is called 'this', try to get the 'real this' - SwigPyObject from it */ - return SWIG_Python_GetSwigThis(obj); - } - return (SwigPyObject *)obj; -#endif -} - -/* Acquire a pointer value */ - -SWIGRUNTIME int -SWIG_Python_AcquirePtr(PyObject *obj, int own) { - if (own == SWIG_POINTER_OWN) { - SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); - if (sobj) { - int oldown = sobj->own; - sobj->own = own; - return oldown; - } - } - return 0; -} - -/* Convert a pointer value */ - -SWIGRUNTIME int -SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { - int res; - SwigPyObject *sobj; - int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0; - - if (!obj) - return SWIG_ERROR; - if (obj == Py_None && !implicit_conv) { - if (ptr) - *ptr = 0; - return SWIG_OK; - } - - res = SWIG_ERROR; - - sobj = SWIG_Python_GetSwigThis(obj); - if (own) - *own = 0; - while (sobj) { - void *vptr = sobj->ptr; - if (ty) { - swig_type_info *to = sobj->ty; - if (to == ty) { - /* no type cast needed */ - if (ptr) *ptr = vptr; - break; - } else { - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) { - sobj = (SwigPyObject *)sobj->next; - } else { - if (ptr) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - if (newmemory == SWIG_CAST_NEW_MEMORY) { - assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ - if (own) - *own = *own | SWIG_CAST_NEW_MEMORY; - } - } - break; - } - } - } else { - if (ptr) *ptr = vptr; - break; - } - } - if (sobj) { - if (own) - *own = *own | sobj->own; - if (flags & SWIG_POINTER_DISOWN) { - sobj->own = 0; - } - res = SWIG_OK; - } else { - if (implicit_conv) { - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - if (data && !data->implicitconv) { - PyObject *klass = data->klass; - if (klass) { - PyObject *impconv; - data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ - impconv = SWIG_Python_CallFunctor(klass, obj); - data->implicitconv = 0; - if (PyErr_Occurred()) { - PyErr_Clear(); - impconv = 0; - } - if (impconv) { - SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); - if (iobj) { - void *vptr; - res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); - if (SWIG_IsOK(res)) { - if (ptr) { - *ptr = vptr; - /* transfer the ownership to 'ptr' */ - iobj->own = 0; - res = SWIG_AddCast(res); - res = SWIG_AddNewMask(res); - } else { - res = SWIG_AddCast(res); - } - } - } - Py_DECREF(impconv); - } - } - } - } - if (!SWIG_IsOK(res) && obj == Py_None) { - if (ptr) - *ptr = 0; - if (PyErr_Occurred()) - PyErr_Clear(); - res = SWIG_OK; - } - } - return res; -} - -/* Convert a function ptr value */ - -SWIGRUNTIME int -SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { - if (!PyCFunction_Check(obj)) { - return SWIG_ConvertPtr(obj, ptr, ty, 0); - } else { - void *vptr = 0; - - /* here we get the method pointer for callbacks */ - const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); - const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; - if (desc) - desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; - if (!desc) - return SWIG_ERROR; - if (ty) { - swig_cast_info *tc = SWIG_TypeCheck(desc,ty); - if (tc) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ - } else { - return SWIG_ERROR; - } - } else { - *ptr = vptr; - } - return SWIG_OK; - } -} - -/* Convert a packed value value */ - -SWIGRUNTIME int -SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { - swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz); - if (!to) return SWIG_ERROR; - if (ty) { - if (to != ty) { - /* check type cast? */ - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) return SWIG_ERROR; - } - } - return SWIG_OK; -} - -/* ----------------------------------------------------------------------------- - * Create a new pointer object - * ----------------------------------------------------------------------------- */ - -/* - Create a new instance object, without calling __init__, and set the - 'this' attribute. -*/ - -SWIGRUNTIME PyObject* -SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) -{ -#if (PY_VERSION_HEX >= 0x02020000) - PyObject *inst = 0; - PyObject *newraw = data->newraw; - if (newraw) { - inst = PyObject_Call(newraw, data->newargs, NULL); - if (inst) { -#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) - PyObject **dictptr = _PyObject_GetDictPtr(inst); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - if (dict == NULL) { - dict = PyDict_New(); - *dictptr = dict; - PyDict_SetItem(dict, SWIG_This(), swig_this); - } - } -#else - PyObject *key = SWIG_This(); - PyObject_SetAttr(inst, key, swig_this); -#endif - } - } else { -#if PY_VERSION_HEX >= 0x03000000 - inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); - if (inst) { - PyObject_SetAttr(inst, SWIG_This(), swig_this); - Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; - } -#else - PyObject *dict = PyDict_New(); - if (dict) { - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); - } -#endif - } - return inst; -#else -#if (PY_VERSION_HEX >= 0x02010000) - PyObject *inst = 0; - PyObject *dict = PyDict_New(); - if (dict) { - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); - } - return (PyObject *) inst; -#else - PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type); - if (inst == NULL) { - return NULL; - } - inst->in_class = (PyClassObject *)data->newargs; - Py_INCREF(inst->in_class); - inst->in_dict = PyDict_New(); - if (inst->in_dict == NULL) { - Py_DECREF(inst); - return NULL; - } -#ifdef Py_TPFLAGS_HAVE_WEAKREFS - inst->in_weakreflist = NULL; -#endif -#ifdef Py_TPFLAGS_GC - PyObject_GC_Init(inst); -#endif - PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this); - return (PyObject *) inst; -#endif -#endif -} - -SWIGRUNTIME void -SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) -{ - PyObject *dict; -#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS) - PyObject **dictptr = _PyObject_GetDictPtr(inst); - if (dictptr != NULL) { - dict = *dictptr; - if (dict == NULL) { - dict = PyDict_New(); - *dictptr = dict; - } - PyDict_SetItem(dict, SWIG_This(), swig_this); - return; - } -#endif - dict = PyObject_GetAttrString(inst, (char*)"__dict__"); - PyDict_SetItem(dict, SWIG_This(), swig_this); - Py_DECREF(dict); -} - - -SWIGINTERN PyObject * -SWIG_Python_InitShadowInstance(PyObject *args) { - PyObject *obj[2]; - if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) { - return NULL; - } else { - SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]); - if (sthis) { - SwigPyObject_append((PyObject*) sthis, obj[1]); - } else { - SWIG_Python_SetSwigThis(obj[0], obj[1]); - } - return SWIG_Py_Void(); - } -} - -/* Create a new pointer object */ - -SWIGRUNTIME PyObject * -SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) { - SwigPyClientData *clientdata; - PyObject * robj; - int own; - - if (!ptr) - return SWIG_Py_Void(); - - clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; - own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; - if (clientdata && clientdata->pytype) { - SwigPyObject *newobj; - if (flags & SWIG_BUILTIN_TP_INIT) { - newobj = (SwigPyObject*) self; - if (newobj->ptr) { - PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0); - while (newobj->next) - newobj = (SwigPyObject *) newobj->next; - newobj->next = next_self; - newobj = (SwigPyObject *)next_self; -#ifdef SWIGPYTHON_BUILTIN - newobj->dict = 0; -#endif - } - } else { - newobj = PyObject_New(SwigPyObject, clientdata->pytype); -#ifdef SWIGPYTHON_BUILTIN - newobj->dict = 0; -#endif - } - if (newobj) { - newobj->ptr = ptr; - newobj->ty = type; - newobj->own = own; - newobj->next = 0; - return (PyObject*) newobj; - } - return SWIG_Py_Void(); - } - - assert(!(flags & SWIG_BUILTIN_TP_INIT)); - - robj = SwigPyObject_New(ptr, type, own); - if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { - PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); - Py_DECREF(robj); - robj = inst; - } - return robj; -} - -/* Create a new packed object */ - -SWIGRUNTIMEINLINE PyObject * -SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { - return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void(); -} - -/* -----------------------------------------------------------------------------* - * Get type list - * -----------------------------------------------------------------------------*/ - -#ifdef SWIG_LINK_RUNTIME -void *SWIG_ReturnGlobalTypeList(void *); -#endif - -SWIGRUNTIME swig_module_info * -SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) { - static void *type_pointer = (void *)0; - /* first check if module already created */ - if (!type_pointer) { -#ifdef SWIG_LINK_RUNTIME - type_pointer = SWIG_ReturnGlobalTypeList((void *)0); -#else -# ifdef SWIGPY_USE_CAPSULE - type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0); -# else - type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, - (char*)"type_pointer" SWIG_TYPE_TABLE_NAME); -# endif - if (PyErr_Occurred()) { - PyErr_Clear(); - type_pointer = (void *)0; - } -#endif - } - return (swig_module_info *) type_pointer; -} - -#if PY_MAJOR_VERSION < 2 -/* PyModule_AddObject function was introduced in Python 2.0. The following function - is copied out of Python/modsupport.c in python version 2.3.4 */ -SWIGINTERN int -PyModule_AddObject(PyObject *m, char *name, PyObject *o) -{ - PyObject *dict; - if (!PyModule_Check(m)) { - PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs module as first arg"); - return SWIG_ERROR; - } - if (!o) { - PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs non-NULL value"); - return SWIG_ERROR; - } - - dict = PyModule_GetDict(m); - if (dict == NULL) { - /* Internal error -- modules must have a dict! */ - PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", - PyModule_GetName(m)); - return SWIG_ERROR; - } - if (PyDict_SetItemString(dict, name, o)) - return SWIG_ERROR; - Py_DECREF(o); - return SWIG_OK; -} -#endif - -SWIGRUNTIME void -#ifdef SWIGPY_USE_CAPSULE -SWIG_Python_DestroyModule(PyObject *obj) -#else -SWIG_Python_DestroyModule(void *vptr) -#endif -{ -#ifdef SWIGPY_USE_CAPSULE - swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME); -#else - swig_module_info *swig_module = (swig_module_info *) vptr; -#endif - swig_type_info **types = swig_module->types; - size_t i; - for (i =0; i < swig_module->size; ++i) { - swig_type_info *ty = types[i]; - if (ty->owndata) { - SwigPyClientData *data = (SwigPyClientData *) ty->clientdata; - if (data) SwigPyClientData_Del(data); - } - } - Py_DECREF(SWIG_This()); - swig_this = NULL; -} - -SWIGRUNTIME void -SWIG_Python_SetModule(swig_module_info *swig_module) { -#if PY_VERSION_HEX >= 0x03000000 - /* Add a placeholder module object into sys.modules */ - PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION); -#else - static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */ - PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table); -#endif -#ifdef SWIGPY_USE_CAPSULE - PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule); - if (pointer && module) { - PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer); - } else { - Py_XDECREF(pointer); - } -#else - PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule); - if (pointer && module) { - PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer); - } else { - Py_XDECREF(pointer); - } -#endif -} - -/* The python cached type query */ -SWIGRUNTIME PyObject * -SWIG_Python_TypeCache(void) { - static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New(); - return cache; -} - -SWIGRUNTIME swig_type_info * -SWIG_Python_TypeQuery(const char *type) -{ - PyObject *cache = SWIG_Python_TypeCache(); - PyObject *key = SWIG_Python_str_FromChar(type); - PyObject *obj = PyDict_GetItem(cache, key); - swig_type_info *descriptor; - if (obj) { -#ifdef SWIGPY_USE_CAPSULE - descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL); -#else - descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj); -#endif - } else { - swig_module_info *swig_module = SWIG_GetModule(0); - descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type); - if (descriptor) { -#ifdef SWIGPY_USE_CAPSULE - obj = PyCapsule_New((void*) descriptor, NULL, NULL); -#else - obj = PyCObject_FromVoidPtr(descriptor, NULL); -#endif - PyDict_SetItem(cache, key, obj); - Py_DECREF(obj); - } - } - Py_DECREF(key); - return descriptor; -} - -/* - For backward compatibility only -*/ -#define SWIG_POINTER_EXCEPTION 0 -#define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg) -#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags) - -SWIGRUNTIME int -SWIG_Python_AddErrMesg(const char* mesg, int infront) -{ - if (PyErr_Occurred()) { - PyObject *type = 0; - PyObject *value = 0; - PyObject *traceback = 0; - PyErr_Fetch(&type, &value, &traceback); - if (value) { - char *tmp; - PyObject *old_str = PyObject_Str(value); - Py_XINCREF(type); - PyErr_Clear(); - if (infront) { - PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str)); - } else { - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); - } - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(old_str); - } - return 1; - } else { - return 0; - } -} - -SWIGRUNTIME int -SWIG_Python_ArgFail(int argnum) -{ - if (PyErr_Occurred()) { - /* add information about failing argument */ - char mesg[256]; - PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum); - return SWIG_Python_AddErrMesg(mesg, 1); - } else { - return 0; - } -} - -SWIGRUNTIMEINLINE const char * -SwigPyObject_GetDesc(PyObject *self) -{ - SwigPyObject *v = (SwigPyObject *)self; - swig_type_info *ty = v ? v->ty : 0; - return ty ? ty->str : ""; -} - -SWIGRUNTIME void -SWIG_Python_TypeError(const char *type, PyObject *obj) -{ - if (type) { -#if defined(SWIG_COBJECT_TYPES) - if (obj && SwigPyObject_Check(obj)) { - const char *otype = (const char *) SwigPyObject_GetDesc(obj); - if (otype) { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received", - type, otype); - return; - } - } else -#endif - { - const char *otype = (obj ? obj->ob_type->tp_name : 0); - if (otype) { - PyObject *str = PyObject_Str(obj); - const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0; - if (cstr) { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", - type, otype, cstr); - SWIG_Python_str_DelForPy3(cstr); - } else { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", - type, otype); - } - Py_XDECREF(str); - return; - } - } - PyErr_Format(PyExc_TypeError, "a '%s' is expected", type); - } else { - PyErr_Format(PyExc_TypeError, "unexpected type is received"); - } -} - - -/* Convert a pointer value, signal an exception on a type mismatch */ -SWIGRUNTIME void * -SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) { - void *result; - if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { - PyErr_Clear(); -#if SWIG_POINTER_EXCEPTION - if (flags) { - SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj); - SWIG_Python_ArgFail(argnum); - } -#endif - } - return result; -} - -#ifdef SWIGPYTHON_BUILTIN -SWIGRUNTIME int -SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) { - PyTypeObject *tp = obj->ob_type; - PyObject *descr; - PyObject *encoded_name; - descrsetfunc f; - int res = -1; - -# ifdef Py_USING_UNICODE - if (PyString_Check(name)) { - name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL); - if (!name) - return -1; - } else if (!PyUnicode_Check(name)) -# else - if (!PyString_Check(name)) -# endif - { - PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); - return -1; - } else { - Py_INCREF(name); - } - - if (!tp->tp_dict) { - if (PyType_Ready(tp) < 0) - goto done; - } - - descr = _PyType_Lookup(tp, name); - f = NULL; - if (descr != NULL) - f = descr->ob_type->tp_descr_set; - if (!f) { - if (PyString_Check(name)) { - encoded_name = name; - Py_INCREF(name); - } else { - encoded_name = PyUnicode_AsUTF8String(name); - } - PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name)); - Py_DECREF(encoded_name); - } else { - res = f(descr, obj, value); - } - - done: - Py_DECREF(name); - return res; -} -#endif - - -#ifdef __cplusplus -} -#endif - - - -#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) - -#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else - - - - #define SWIG_exception(code, msg) do { SWIG_Error(code, msg); SWIG_fail;; } while(0) - - -/* -------- TYPES TABLE (BEGIN) -------- */ - -#define SWIGTYPE_p_char swig_types[0] -#define SWIGTYPE_p_int swig_types[1] -#define SWIGTYPE_p_uint8_t swig_types[2] -static swig_type_info *swig_types[4]; -static swig_module_info swig_module = {swig_types, 3, 0, 0, 0, 0}; -#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) -#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) - -/* -------- TYPES TABLE (END) -------- */ - -#if (PY_VERSION_HEX <= 0x02000000) -# if !defined(SWIG_PYTHON_CLASSIC) -# error "This python version requires swig to be run with the '-classic' option" -# endif -#endif - -/*----------------------------------------------- - @(target):= _libwebp.so - ------------------------------------------------*/ -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_init PyInit__libwebp - -#else -# define SWIG_init init_libwebp - -#endif -#define SWIG_name "_libwebp" - -#define SWIGVERSION 0x030012 -#define SWIG_VERSION SWIGVERSION - - -#define SWIG_as_voidptr(a) (void *)((const void *)(a)) -#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) - - -SWIGINTERNINLINE PyObject* - SWIG_From_int (int value) -{ - return PyInt_FromLong((long) value); -} - - -SWIGINTERN swig_type_info* -SWIG_pchar_descriptor(void) -{ - static int init = 0; - static swig_type_info* info = 0; - if (!init) { - info = SWIG_TypeQuery("_p_char"); - init = 1; - } - return info; -} - - -SWIGINTERN int -SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) -{ -#if PY_VERSION_HEX>=0x03000000 -#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - if (PyBytes_Check(obj)) -#else - if (PyUnicode_Check(obj)) -#endif -#else - if (PyString_Check(obj)) -#endif - { - char *cstr; Py_ssize_t len; -#if PY_VERSION_HEX>=0x03000000 -#if !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - if (!alloc && cptr) { - /* We can't allow converting without allocation, since the internal - representation of string in Python 3 is UCS-2/UCS-4 but we require - a UTF-8 representation. - TODO(bhy) More detailed explanation */ - return SWIG_RuntimeError; - } - obj = PyUnicode_AsUTF8String(obj); - if(alloc) *alloc = SWIG_NEWOBJ; -#endif - PyBytes_AsStringAndSize(obj, &cstr, &len); -#else - PyString_AsStringAndSize(obj, &cstr, &len); -#endif - if (cptr) { - if (alloc) { - /* - In python the user should not be able to modify the inner - string representation. To warranty that, if you define - SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string - buffer is always returned. - - The default behavior is just to return the pointer value, - so, be careful. - */ -#if defined(SWIG_PYTHON_SAFE_CSTRINGS) - if (*alloc != SWIG_OLDOBJ) -#else - if (*alloc == SWIG_NEWOBJ) -#endif - { - *cptr = (char *)memcpy(malloc((len + 1)*sizeof(char)), cstr, sizeof(char)*(len + 1)); - *alloc = SWIG_NEWOBJ; - } else { - *cptr = cstr; - *alloc = SWIG_OLDOBJ; - } - } else { -#if PY_VERSION_HEX>=0x03000000 -#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - *cptr = PyBytes_AsString(obj); -#else - assert(0); /* Should never reach here with Unicode strings in Python 3 */ -#endif -#else - *cptr = SWIG_Python_str_AsChar(obj); -#endif - } - } - if (psize) *psize = len + 1; -#if PY_VERSION_HEX>=0x03000000 && !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - Py_XDECREF(obj); -#endif - return SWIG_OK; - } else { -#if defined(SWIG_PYTHON_2_UNICODE) -#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) -#error "Cannot use both SWIG_PYTHON_2_UNICODE and SWIG_PYTHON_STRICT_BYTE_CHAR at once" -#endif -#if PY_VERSION_HEX<0x03000000 - if (PyUnicode_Check(obj)) { - char *cstr; Py_ssize_t len; - if (!alloc && cptr) { - return SWIG_RuntimeError; - } - obj = PyUnicode_AsUTF8String(obj); - if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) { - if (cptr) { - if (alloc) *alloc = SWIG_NEWOBJ; - *cptr = (char *)memcpy(malloc((len + 1)*sizeof(char)), cstr, sizeof(char)*(len + 1)); - } - if (psize) *psize = len + 1; - - Py_XDECREF(obj); - return SWIG_OK; - } else { - Py_XDECREF(obj); - } - } -#endif -#endif - - swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); - if (pchar_descriptor) { - void* vptr = 0; - if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) { - if (cptr) *cptr = (char *) vptr; - if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0; - if (alloc) *alloc = SWIG_OLDOBJ; - return SWIG_OK; - } - } - } - return SWIG_TypeError; -} - - -SWIGINTERN int -SWIG_AsVal_double (PyObject *obj, double *val) -{ - int res = SWIG_TypeError; - if (PyFloat_Check(obj)) { - if (val) *val = PyFloat_AsDouble(obj); - return SWIG_OK; -#if PY_VERSION_HEX < 0x03000000 - } else if (PyInt_Check(obj)) { - if (val) *val = (double) PyInt_AsLong(obj); - return SWIG_OK; -#endif - } else if (PyLong_Check(obj)) { - double v = PyLong_AsDouble(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - double d = PyFloat_AsDouble(obj); - if (!PyErr_Occurred()) { - if (val) *val = d; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - long v = PyLong_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_AddCast(SWIG_OK)); - } else { - PyErr_Clear(); - } - } - } -#endif - return res; -} - - -#include - - -#include - - -SWIGINTERNINLINE int -SWIG_CanCastAsInteger(double *d, double min, double max) { - double x = *d; - if ((min <= x && x <= max)) { - double fx = floor(x); - double cx = ceil(x); - double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */ - if ((errno == EDOM) || (errno == ERANGE)) { - errno = 0; - } else { - double summ, reps, diff; - if (rd < x) { - diff = x - rd; - } else if (rd > x) { - diff = rd - x; - } else { - return 1; - } - summ = rd + x; - reps = diff/summ; - if (reps < 8*DBL_EPSILON) { - *d = rd; - return 1; - } - } - } - return 0; -} - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) -{ -#if PY_VERSION_HEX < 0x03000000 - if (PyInt_Check(obj)) { - long v = PyInt_AsLong(obj); - if (v >= 0) { - if (val) *val = v; - return SWIG_OK; - } else { - return SWIG_OverflowError; - } - } else -#endif - if (PyLong_Check(obj)) { - unsigned long v = PyLong_AsUnsignedLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - return SWIG_OverflowError; - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - unsigned long v = PyLong_AsUnsignedLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - double d; - int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) { - if (val) *val = (unsigned long)(d); - return res; - } - } - } -#endif - return SWIG_TypeError; -} - - -#include -#if !defined(SWIG_NO_LLONG_MAX) -# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) -# define LLONG_MAX __LONG_LONG_MAX__ -# define LLONG_MIN (-LLONG_MAX - 1LL) -# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) -# endif -#endif - - -#if defined(LLONG_MAX) && !defined(SWIG_LONG_LONG_AVAILABLE) -# define SWIG_LONG_LONG_AVAILABLE -#endif - - -#ifdef SWIG_LONG_LONG_AVAILABLE -SWIGINTERN int -SWIG_AsVal_unsigned_SS_long_SS_long (PyObject *obj, unsigned long long *val) -{ - int res = SWIG_TypeError; - if (PyLong_Check(obj)) { - unsigned long long v = PyLong_AsUnsignedLongLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - res = SWIG_OverflowError; - } - } else { - unsigned long v; - res = SWIG_AsVal_unsigned_SS_long (obj,&v); - if (SWIG_IsOK(res)) { - if (val) *val = v; - return res; - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - const double mant_max = 1LL << DBL_MANT_DIG; - double d; - res = SWIG_AsVal_double (obj,&d); - if (SWIG_IsOK(res) && !SWIG_CanCastAsInteger(&d, 0, mant_max)) - return SWIG_OverflowError; - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, mant_max)) { - if (val) *val = (unsigned long long)(d); - return SWIG_AddCast(res); - } - res = SWIG_TypeError; - } -#endif - return res; -} -#endif - - -SWIGINTERNINLINE int -SWIG_AsVal_size_t (PyObject * obj, size_t *val) -{ - int res = SWIG_TypeError; -#ifdef SWIG_LONG_LONG_AVAILABLE - if (sizeof(size_t) <= sizeof(unsigned long)) { -#endif - unsigned long v; - res = SWIG_AsVal_unsigned_SS_long (obj, val ? &v : 0); - if (SWIG_IsOK(res) && val) *val = (size_t)(v); -#ifdef SWIG_LONG_LONG_AVAILABLE - } else if (sizeof(size_t) <= sizeof(unsigned long long)) { - unsigned long long v; - res = SWIG_AsVal_unsigned_SS_long_SS_long (obj, val ? &v : 0); - if (SWIG_IsOK(res) && val) *val = (size_t)(v); - } -#endif - return res; -} - - -#include "webp/decode.h" -#include "webp/encode.h" - - -static size_t ReturnedBufferSize( - const char* function, int* width, int* height) { - static const struct sizemap { - const char* function; - int size_multiplier; - } size_map[] = { -#ifdef SWIGJAVA - { "Java_com_google_webp_libwebpJNI_WebPDecodeRGB", 3 }, - { "Java_com_google_webp_libwebpJNI_WebPDecodeRGBA", 4 }, - { "Java_com_google_webp_libwebpJNI_WebPDecodeARGB", 4 }, - { "Java_com_google_webp_libwebpJNI_WebPDecodeBGR", 3 }, - { "Java_com_google_webp_libwebpJNI_WebPDecodeBGRA", 4 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGB", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGR", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeRGBA", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeBGRA", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGB", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGR", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessRGBA", 1 }, - { "Java_com_google_webp_libwebpJNI_wrap_1WebPEncodeLosslessBGRA", 1 }, -#endif -#ifdef SWIGPYTHON - { "WebPDecodeRGB", 3 }, - { "WebPDecodeRGBA", 4 }, - { "WebPDecodeARGB", 4 }, - { "WebPDecodeBGR", 3 }, - { "WebPDecodeBGRA", 4 }, - { "wrap_WebPEncodeRGB", 1 }, - { "wrap_WebPEncodeBGR", 1 }, - { "wrap_WebPEncodeRGBA", 1 }, - { "wrap_WebPEncodeBGRA", 1 }, - { "wrap_WebPEncodeLosslessRGB", 1 }, - { "wrap_WebPEncodeLosslessBGR", 1 }, - { "wrap_WebPEncodeLosslessRGBA", 1 }, - { "wrap_WebPEncodeLosslessBGRA", 1 }, -#endif - { NULL, 0 } - }; - const struct sizemap* p; - size_t size = 0; - - for (p = size_map; p->function; ++p) { - if (!strcmp(function, p->function)) { - size = *width * *height * p->size_multiplier; - break; - } - } - - return size; -} - - -typedef size_t (*WebPEncodeFunction)(const uint8_t* rgb, - int width, int height, int stride, - float quality_factor, uint8_t** output); -typedef size_t (*WebPEncodeLosslessFunction)(const uint8_t* rgb, - int width, int height, int stride, - uint8_t** output); - -static uint8_t* EncodeLossy(const uint8_t* rgb, - int width, int height, int stride, - float quality_factor, - WebPEncodeFunction encfn, - int* output_size, int* unused) { - uint8_t* output = NULL; - const size_t image_size = - encfn(rgb, width, height, stride, quality_factor, &output); - // the values of following two will be interpreted by ReturnedBufferSize() - // as 'width' and 'height' in the size calculation. - *output_size = image_size; - *unused = 1; - return image_size ? output : NULL; -} - -static uint8_t* EncodeLossless(const uint8_t* rgb, - int width, int height, int stride, - WebPEncodeLosslessFunction encfn, - int* output_size, int* unused) { - uint8_t* output = NULL; - const size_t image_size = encfn(rgb, width, height, stride, &output); - // the values of the following two will be interpreted by - // ReturnedBufferSize() as 'width' and 'height' in the size calculation. - *output_size = image_size; - *unused = 1; - return image_size ? output : NULL; -} - - -// Changes the return type of WebPEncode* to more closely match Decode*. -// This also makes it easier to wrap the output buffer in a native type rather -// than dealing with the return pointer. -// The additional parameters are to allow reuse of ReturnedBufferSize(), -// unused2 and output_size will be used in this case. -#define LOSSY_WRAPPER(FUNC) \ - static uint8_t* wrap_##FUNC( \ - const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \ - int width, int height, int stride, float quality_factor) { \ - return EncodeLossy(rgb, width, height, stride, quality_factor, \ - FUNC, output_size, unused2); \ - } \ - -LOSSY_WRAPPER(WebPEncodeRGB) -LOSSY_WRAPPER(WebPEncodeBGR) -LOSSY_WRAPPER(WebPEncodeRGBA) -LOSSY_WRAPPER(WebPEncodeBGRA) - -#undef LOSSY_WRAPPER - -#define LOSSLESS_WRAPPER(FUNC) \ - static uint8_t* wrap_##FUNC( \ - const uint8_t* rgb, int* unused1, int* unused2, int* output_size, \ - int width, int height, int stride) { \ - return EncodeLossless(rgb, width, height, stride, \ - FUNC, output_size, unused2); \ - } \ - -LOSSLESS_WRAPPER(WebPEncodeLosslessRGB) -LOSSLESS_WRAPPER(WebPEncodeLosslessBGR) -LOSSLESS_WRAPPER(WebPEncodeLosslessRGBA) -LOSSLESS_WRAPPER(WebPEncodeLosslessBGRA) - -#undef LOSSLESS_WRAPPER - - - -SWIGINTERN int -SWIG_AsVal_long (PyObject *obj, long* val) -{ -#if PY_VERSION_HEX < 0x03000000 - if (PyInt_Check(obj)) { - if (val) *val = PyInt_AsLong(obj); - return SWIG_OK; - } else -#endif - if (PyLong_Check(obj)) { - long v = PyLong_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - return SWIG_OverflowError; - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - long v = PyInt_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - double d; - int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { - if (val) *val = (long)(d); - return res; - } - } - } -#endif - return SWIG_TypeError; -} - - -SWIGINTERN int -SWIG_AsVal_int (PyObject * obj, int *val) -{ - long v; - int res = SWIG_AsVal_long (obj, &v); - if (SWIG_IsOK(res)) { - if ((v < INT_MIN || v > INT_MAX)) { - return SWIG_OverflowError; - } else { - if (val) *val = (int)(v); - } - } - return res; -} - - -/* Getting isfinite working pre C99 across multiple platforms is non-trivial. Users can provide SWIG_isfinite on older platforms. */ -#ifndef SWIG_isfinite -/* isfinite() is a macro for C99 */ -# if defined(isfinite) -# define SWIG_isfinite(X) (isfinite(X)) -# elif defined __cplusplus && __cplusplus >= 201103L -/* Use a template so that this works whether isfinite() is std::isfinite() or - * in the global namespace. The reality seems to vary between compiler - * versions. - * - * Make sure namespace std exists to avoid compiler warnings. - * - * extern "C++" is required as this fragment can end up inside an extern "C" { } block - */ -namespace std { } -extern "C++" template -inline int SWIG_isfinite_func(T x) { - using namespace std; - return isfinite(x); -} -# define SWIG_isfinite(X) (SWIG_isfinite_func(X)) -# elif defined(_MSC_VER) -# define SWIG_isfinite(X) (_finite(X)) -# elif defined(__sun) && defined(__SVR4) -# include -# define SWIG_isfinite(X) (finite(X)) -# endif -#endif - - -/* Accept infinite as a valid float value unless we are unable to check if a value is finite */ -#ifdef SWIG_isfinite -# define SWIG_Float_Overflow_Check(X) ((X < -FLT_MAX || X > FLT_MAX) && SWIG_isfinite(X)) -#else -# define SWIG_Float_Overflow_Check(X) ((X < -FLT_MAX || X > FLT_MAX)) -#endif - - -SWIGINTERN int -SWIG_AsVal_float (PyObject * obj, float *val) -{ - double v; - int res = SWIG_AsVal_double (obj, &v); - if (SWIG_IsOK(res)) { - if (SWIG_Float_Overflow_Check(v)) { - return SWIG_OverflowError; - } else { - if (val) *val = (float)(v); - } - } - return res; -} - -#ifdef __cplusplus -extern "C" { -#endif -SWIGINTERN PyObject *_wrap_WebPGetDecoderVersion(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int result; - - if (!PyArg_ParseTuple(args,(char *)":WebPGetDecoderVersion")) SWIG_fail; - result = (int)WebPGetDecoderVersion(); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_WebPGetInfo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int res1 ; - char *buf1 = 0 ; - size_t size1 = 0 ; - int alloc1 = 0 ; - int temp3 ; - int res3 = SWIG_TMPOBJ ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - PyObject * obj0 = 0 ; - int result; - - arg3 = &temp3; - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"O:WebPGetInfo",&obj0)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, &size1, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "WebPGetInfo" "', argument " "1"" of type '" "uint8_t const *""'"); - } - arg1 = (uint8_t *)(buf1); - arg2 = (size_t)(size1 - 1); - result = (int)WebPGetInfo((uint8_t const *)arg1,arg2,arg3,arg4); - resultobj = SWIG_From_int((int)(result)); - if (SWIG_IsTmpObj(res3)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3))); - } else { - int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_WebPDecodeRGB(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int res1 ; - char *buf1 = 0 ; - size_t size1 = 0 ; - int alloc1 = 0 ; - int temp3 ; - int res3 = SWIG_TMPOBJ ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - PyObject * obj0 = 0 ; - uint8_t *result = 0 ; - - arg3 = &temp3; - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"O:WebPDecodeRGB",&obj0)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, &size1, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "WebPDecodeRGB" "', argument " "1"" of type '" "uint8_t const *""'"); - } - arg1 = (uint8_t *)(buf1); - arg2 = (size_t)(size1 - 1); - result = (uint8_t *)WebPDecodeRGB((uint8_t const *)arg1,arg2,arg3,arg4); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("WebPDecodeRGB", arg3, arg4)); - } - if (SWIG_IsTmpObj(res3)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3))); - } else { - int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - free(result); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_WebPDecodeRGBA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int res1 ; - char *buf1 = 0 ; - size_t size1 = 0 ; - int alloc1 = 0 ; - int temp3 ; - int res3 = SWIG_TMPOBJ ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - PyObject * obj0 = 0 ; - uint8_t *result = 0 ; - - arg3 = &temp3; - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"O:WebPDecodeRGBA",&obj0)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, &size1, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "WebPDecodeRGBA" "', argument " "1"" of type '" "uint8_t const *""'"); - } - arg1 = (uint8_t *)(buf1); - arg2 = (size_t)(size1 - 1); - result = (uint8_t *)WebPDecodeRGBA((uint8_t const *)arg1,arg2,arg3,arg4); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("WebPDecodeRGBA", arg3, arg4)); - } - if (SWIG_IsTmpObj(res3)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3))); - } else { - int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - free(result); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_WebPDecodeARGB(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int res1 ; - char *buf1 = 0 ; - size_t size1 = 0 ; - int alloc1 = 0 ; - int temp3 ; - int res3 = SWIG_TMPOBJ ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - PyObject * obj0 = 0 ; - uint8_t *result = 0 ; - - arg3 = &temp3; - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"O:WebPDecodeARGB",&obj0)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, &size1, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "WebPDecodeARGB" "', argument " "1"" of type '" "uint8_t const *""'"); - } - arg1 = (uint8_t *)(buf1); - arg2 = (size_t)(size1 - 1); - result = (uint8_t *)WebPDecodeARGB((uint8_t const *)arg1,arg2,arg3,arg4); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("WebPDecodeARGB", arg3, arg4)); - } - if (SWIG_IsTmpObj(res3)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3))); - } else { - int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - free(result); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_WebPDecodeBGR(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int res1 ; - char *buf1 = 0 ; - size_t size1 = 0 ; - int alloc1 = 0 ; - int temp3 ; - int res3 = SWIG_TMPOBJ ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - PyObject * obj0 = 0 ; - uint8_t *result = 0 ; - - arg3 = &temp3; - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"O:WebPDecodeBGR",&obj0)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, &size1, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "WebPDecodeBGR" "', argument " "1"" of type '" "uint8_t const *""'"); - } - arg1 = (uint8_t *)(buf1); - arg2 = (size_t)(size1 - 1); - result = (uint8_t *)WebPDecodeBGR((uint8_t const *)arg1,arg2,arg3,arg4); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("WebPDecodeBGR", arg3, arg4)); - } - if (SWIG_IsTmpObj(res3)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3))); - } else { - int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - free(result); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_WebPDecodeBGRA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - size_t arg2 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int res1 ; - char *buf1 = 0 ; - size_t size1 = 0 ; - int alloc1 = 0 ; - int temp3 ; - int res3 = SWIG_TMPOBJ ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - PyObject * obj0 = 0 ; - uint8_t *result = 0 ; - - arg3 = &temp3; - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"O:WebPDecodeBGRA",&obj0)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, &size1, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "WebPDecodeBGRA" "', argument " "1"" of type '" "uint8_t const *""'"); - } - arg1 = (uint8_t *)(buf1); - arg2 = (size_t)(size1 - 1); - result = (uint8_t *)WebPDecodeBGRA((uint8_t const *)arg1,arg2,arg3,arg4); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("WebPDecodeBGRA", arg3, arg4)); - } - if (SWIG_IsTmpObj(res3)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg3))); - } else { - int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - free(result); - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_WebPGetEncoderVersion(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int result; - - if (!PyArg_ParseTuple(args,(char *)":WebPGetEncoderVersion")) SWIG_fail; - result = (int)WebPGetEncoderVersion(); - resultobj = SWIG_From_int((int)(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_wrap_WebPEncodeRGB(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - float arg8 ; - Py_buffer rgb_buffer1 ; - int temp2 ; - int res2 = 0 ; - int temp3 ; - int res3 = 0 ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - float val8 ; - int ecode8 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - PyObject * obj5 = 0 ; - PyObject * obj6 = 0 ; - uint8_t *result = 0 ; - - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"OOOOOOO:wrap_WebPEncodeRGB",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail; - { - // NB: with Python < 2.6 the old style buffer protocol may be used: - // Py_ssize_t unused; - // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); - if (!PyObject_CheckBuffer(obj0)) { - SWIG_exception_fail(SWIG_TypeError, - "in method 'wrap_WebPEncodeRGB', argument 1" - " does not support the buffer interface"); - } - if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { - SWIG_exception_fail(SWIG_RuntimeError, - "in method 'wrap_WebPEncodeRGB', unable to get buffer view"); - } - arg1 = (uint8_t *)rgb_buffer1.buf; - } - if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj1, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeRGB" "', argument " "2"" of type '" "int""'"); - } - temp2 = (int)(val); - arg2 = &temp2; - res2 = SWIG_AddTmpMask(ecode); - } - if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj2, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeRGB" "', argument " "3"" of type '" "int""'"); - } - temp3 = (int)(val); - arg3 = &temp3; - res3 = SWIG_AddTmpMask(ecode); - } - ecode5 = SWIG_AsVal_int(obj3, &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeRGB" "', argument " "5"" of type '" "int""'"); - } - arg5 = (int)(val5); - ecode6 = SWIG_AsVal_int(obj4, &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeRGB" "', argument " "6"" of type '" "int""'"); - } - arg6 = (int)(val6); - ecode7 = SWIG_AsVal_int(obj5, &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeRGB" "', argument " "7"" of type '" "int""'"); - } - arg7 = (int)(val7); - ecode8 = SWIG_AsVal_float(obj6, &val8); - if (!SWIG_IsOK(ecode8)) { - SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "wrap_WebPEncodeRGB" "', argument " "8"" of type '" "float""'"); - } - arg8 = (float)(val8); - result = (uint8_t *)wrap_WebPEncodeRGB((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeRGB", arg3, arg4)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - free(result); - return resultobj; -fail: - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_wrap_WebPEncodeBGR(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - float arg8 ; - Py_buffer rgb_buffer1 ; - int temp2 ; - int res2 = 0 ; - int temp3 ; - int res3 = 0 ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - float val8 ; - int ecode8 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - PyObject * obj5 = 0 ; - PyObject * obj6 = 0 ; - uint8_t *result = 0 ; - - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"OOOOOOO:wrap_WebPEncodeBGR",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail; - { - // NB: with Python < 2.6 the old style buffer protocol may be used: - // Py_ssize_t unused; - // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); - if (!PyObject_CheckBuffer(obj0)) { - SWIG_exception_fail(SWIG_TypeError, - "in method 'wrap_WebPEncodeBGR', argument 1" - " does not support the buffer interface"); - } - if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { - SWIG_exception_fail(SWIG_RuntimeError, - "in method 'wrap_WebPEncodeBGR', unable to get buffer view"); - } - arg1 = (uint8_t *)rgb_buffer1.buf; - } - if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj1, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeBGR" "', argument " "2"" of type '" "int""'"); - } - temp2 = (int)(val); - arg2 = &temp2; - res2 = SWIG_AddTmpMask(ecode); - } - if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj2, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeBGR" "', argument " "3"" of type '" "int""'"); - } - temp3 = (int)(val); - arg3 = &temp3; - res3 = SWIG_AddTmpMask(ecode); - } - ecode5 = SWIG_AsVal_int(obj3, &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeBGR" "', argument " "5"" of type '" "int""'"); - } - arg5 = (int)(val5); - ecode6 = SWIG_AsVal_int(obj4, &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeBGR" "', argument " "6"" of type '" "int""'"); - } - arg6 = (int)(val6); - ecode7 = SWIG_AsVal_int(obj5, &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeBGR" "', argument " "7"" of type '" "int""'"); - } - arg7 = (int)(val7); - ecode8 = SWIG_AsVal_float(obj6, &val8); - if (!SWIG_IsOK(ecode8)) { - SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "wrap_WebPEncodeBGR" "', argument " "8"" of type '" "float""'"); - } - arg8 = (float)(val8); - result = (uint8_t *)wrap_WebPEncodeBGR((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeBGR", arg3, arg4)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - free(result); - return resultobj; -fail: - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_wrap_WebPEncodeRGBA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - float arg8 ; - Py_buffer rgb_buffer1 ; - int temp2 ; - int res2 = 0 ; - int temp3 ; - int res3 = 0 ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - float val8 ; - int ecode8 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - PyObject * obj5 = 0 ; - PyObject * obj6 = 0 ; - uint8_t *result = 0 ; - - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"OOOOOOO:wrap_WebPEncodeRGBA",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail; - { - // NB: with Python < 2.6 the old style buffer protocol may be used: - // Py_ssize_t unused; - // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); - if (!PyObject_CheckBuffer(obj0)) { - SWIG_exception_fail(SWIG_TypeError, - "in method 'wrap_WebPEncodeRGBA', argument 1" - " does not support the buffer interface"); - } - if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { - SWIG_exception_fail(SWIG_RuntimeError, - "in method 'wrap_WebPEncodeRGBA', unable to get buffer view"); - } - arg1 = (uint8_t *)rgb_buffer1.buf; - } - if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj1, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeRGBA" "', argument " "2"" of type '" "int""'"); - } - temp2 = (int)(val); - arg2 = &temp2; - res2 = SWIG_AddTmpMask(ecode); - } - if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj2, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeRGBA" "', argument " "3"" of type '" "int""'"); - } - temp3 = (int)(val); - arg3 = &temp3; - res3 = SWIG_AddTmpMask(ecode); - } - ecode5 = SWIG_AsVal_int(obj3, &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeRGBA" "', argument " "5"" of type '" "int""'"); - } - arg5 = (int)(val5); - ecode6 = SWIG_AsVal_int(obj4, &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeRGBA" "', argument " "6"" of type '" "int""'"); - } - arg6 = (int)(val6); - ecode7 = SWIG_AsVal_int(obj5, &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeRGBA" "', argument " "7"" of type '" "int""'"); - } - arg7 = (int)(val7); - ecode8 = SWIG_AsVal_float(obj6, &val8); - if (!SWIG_IsOK(ecode8)) { - SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "wrap_WebPEncodeRGBA" "', argument " "8"" of type '" "float""'"); - } - arg8 = (float)(val8); - result = (uint8_t *)wrap_WebPEncodeRGBA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeRGBA", arg3, arg4)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - free(result); - return resultobj; -fail: - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_wrap_WebPEncodeBGRA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - float arg8 ; - Py_buffer rgb_buffer1 ; - int temp2 ; - int res2 = 0 ; - int temp3 ; - int res3 = 0 ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - float val8 ; - int ecode8 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - PyObject * obj5 = 0 ; - PyObject * obj6 = 0 ; - uint8_t *result = 0 ; - - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"OOOOOOO:wrap_WebPEncodeBGRA",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail; - { - // NB: with Python < 2.6 the old style buffer protocol may be used: - // Py_ssize_t unused; - // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); - if (!PyObject_CheckBuffer(obj0)) { - SWIG_exception_fail(SWIG_TypeError, - "in method 'wrap_WebPEncodeBGRA', argument 1" - " does not support the buffer interface"); - } - if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { - SWIG_exception_fail(SWIG_RuntimeError, - "in method 'wrap_WebPEncodeBGRA', unable to get buffer view"); - } - arg1 = (uint8_t *)rgb_buffer1.buf; - } - if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj1, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeBGRA" "', argument " "2"" of type '" "int""'"); - } - temp2 = (int)(val); - arg2 = &temp2; - res2 = SWIG_AddTmpMask(ecode); - } - if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj2, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeBGRA" "', argument " "3"" of type '" "int""'"); - } - temp3 = (int)(val); - arg3 = &temp3; - res3 = SWIG_AddTmpMask(ecode); - } - ecode5 = SWIG_AsVal_int(obj3, &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeBGRA" "', argument " "5"" of type '" "int""'"); - } - arg5 = (int)(val5); - ecode6 = SWIG_AsVal_int(obj4, &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeBGRA" "', argument " "6"" of type '" "int""'"); - } - arg6 = (int)(val6); - ecode7 = SWIG_AsVal_int(obj5, &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeBGRA" "', argument " "7"" of type '" "int""'"); - } - arg7 = (int)(val7); - ecode8 = SWIG_AsVal_float(obj6, &val8); - if (!SWIG_IsOK(ecode8)) { - SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "wrap_WebPEncodeBGRA" "', argument " "8"" of type '" "float""'"); - } - arg8 = (float)(val8); - result = (uint8_t *)wrap_WebPEncodeBGRA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeBGRA", arg3, arg4)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - free(result); - return resultobj; -fail: - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_wrap_WebPEncodeLosslessRGB(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - Py_buffer rgb_buffer1 ; - int temp2 ; - int res2 = 0 ; - int temp3 ; - int res3 = 0 ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - PyObject * obj5 = 0 ; - uint8_t *result = 0 ; - - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"OOOOOO:wrap_WebPEncodeLosslessRGB",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail; - { - // NB: with Python < 2.6 the old style buffer protocol may be used: - // Py_ssize_t unused; - // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); - if (!PyObject_CheckBuffer(obj0)) { - SWIG_exception_fail(SWIG_TypeError, - "in method 'wrap_WebPEncodeLosslessRGB', argument 1" - " does not support the buffer interface"); - } - if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { - SWIG_exception_fail(SWIG_RuntimeError, - "in method 'wrap_WebPEncodeLosslessRGB', unable to get buffer view"); - } - arg1 = (uint8_t *)rgb_buffer1.buf; - } - if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj1, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessRGB" "', argument " "2"" of type '" "int""'"); - } - temp2 = (int)(val); - arg2 = &temp2; - res2 = SWIG_AddTmpMask(ecode); - } - if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj2, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessRGB" "', argument " "3"" of type '" "int""'"); - } - temp3 = (int)(val); - arg3 = &temp3; - res3 = SWIG_AddTmpMask(ecode); - } - ecode5 = SWIG_AsVal_int(obj3, &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeLosslessRGB" "', argument " "5"" of type '" "int""'"); - } - arg5 = (int)(val5); - ecode6 = SWIG_AsVal_int(obj4, &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeLosslessRGB" "', argument " "6"" of type '" "int""'"); - } - arg6 = (int)(val6); - ecode7 = SWIG_AsVal_int(obj5, &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeLosslessRGB" "', argument " "7"" of type '" "int""'"); - } - arg7 = (int)(val7); - result = (uint8_t *)wrap_WebPEncodeLosslessRGB((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeLosslessRGB", arg3, arg4)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - free(result); - return resultobj; -fail: - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_wrap_WebPEncodeLosslessBGR(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - Py_buffer rgb_buffer1 ; - int temp2 ; - int res2 = 0 ; - int temp3 ; - int res3 = 0 ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - PyObject * obj5 = 0 ; - uint8_t *result = 0 ; - - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"OOOOOO:wrap_WebPEncodeLosslessBGR",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail; - { - // NB: with Python < 2.6 the old style buffer protocol may be used: - // Py_ssize_t unused; - // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); - if (!PyObject_CheckBuffer(obj0)) { - SWIG_exception_fail(SWIG_TypeError, - "in method 'wrap_WebPEncodeLosslessBGR', argument 1" - " does not support the buffer interface"); - } - if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { - SWIG_exception_fail(SWIG_RuntimeError, - "in method 'wrap_WebPEncodeLosslessBGR', unable to get buffer view"); - } - arg1 = (uint8_t *)rgb_buffer1.buf; - } - if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj1, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessBGR" "', argument " "2"" of type '" "int""'"); - } - temp2 = (int)(val); - arg2 = &temp2; - res2 = SWIG_AddTmpMask(ecode); - } - if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj2, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessBGR" "', argument " "3"" of type '" "int""'"); - } - temp3 = (int)(val); - arg3 = &temp3; - res3 = SWIG_AddTmpMask(ecode); - } - ecode5 = SWIG_AsVal_int(obj3, &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeLosslessBGR" "', argument " "5"" of type '" "int""'"); - } - arg5 = (int)(val5); - ecode6 = SWIG_AsVal_int(obj4, &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeLosslessBGR" "', argument " "6"" of type '" "int""'"); - } - arg6 = (int)(val6); - ecode7 = SWIG_AsVal_int(obj5, &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeLosslessBGR" "', argument " "7"" of type '" "int""'"); - } - arg7 = (int)(val7); - result = (uint8_t *)wrap_WebPEncodeLosslessBGR((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeLosslessBGR", arg3, arg4)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - free(result); - return resultobj; -fail: - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_wrap_WebPEncodeLosslessRGBA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - Py_buffer rgb_buffer1 ; - int temp2 ; - int res2 = 0 ; - int temp3 ; - int res3 = 0 ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - PyObject * obj5 = 0 ; - uint8_t *result = 0 ; - - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"OOOOOO:wrap_WebPEncodeLosslessRGBA",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail; - { - // NB: with Python < 2.6 the old style buffer protocol may be used: - // Py_ssize_t unused; - // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); - if (!PyObject_CheckBuffer(obj0)) { - SWIG_exception_fail(SWIG_TypeError, - "in method 'wrap_WebPEncodeLosslessRGBA', argument 1" - " does not support the buffer interface"); - } - if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { - SWIG_exception_fail(SWIG_RuntimeError, - "in method 'wrap_WebPEncodeLosslessRGBA', unable to get buffer view"); - } - arg1 = (uint8_t *)rgb_buffer1.buf; - } - if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj1, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessRGBA" "', argument " "2"" of type '" "int""'"); - } - temp2 = (int)(val); - arg2 = &temp2; - res2 = SWIG_AddTmpMask(ecode); - } - if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj2, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessRGBA" "', argument " "3"" of type '" "int""'"); - } - temp3 = (int)(val); - arg3 = &temp3; - res3 = SWIG_AddTmpMask(ecode); - } - ecode5 = SWIG_AsVal_int(obj3, &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeLosslessRGBA" "', argument " "5"" of type '" "int""'"); - } - arg5 = (int)(val5); - ecode6 = SWIG_AsVal_int(obj4, &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeLosslessRGBA" "', argument " "6"" of type '" "int""'"); - } - arg6 = (int)(val6); - ecode7 = SWIG_AsVal_int(obj5, &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeLosslessRGBA" "', argument " "7"" of type '" "int""'"); - } - arg7 = (int)(val7); - result = (uint8_t *)wrap_WebPEncodeLosslessRGBA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeLosslessRGBA", arg3, arg4)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - free(result); - return resultobj; -fail: - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - return NULL; -} - - -SWIGINTERN PyObject *_wrap_wrap_WebPEncodeLosslessBGRA(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint8_t *arg1 = (uint8_t *) 0 ; - int *arg2 = (int *) 0 ; - int *arg3 = (int *) 0 ; - int *arg4 = (int *) 0 ; - int arg5 ; - int arg6 ; - int arg7 ; - Py_buffer rgb_buffer1 ; - int temp2 ; - int res2 = 0 ; - int temp3 ; - int res3 = 0 ; - int temp4 ; - int res4 = SWIG_TMPOBJ ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - PyObject * obj5 = 0 ; - uint8_t *result = 0 ; - - arg4 = &temp4; - if (!PyArg_ParseTuple(args,(char *)"OOOOOO:wrap_WebPEncodeLosslessBGRA",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail; - { - // NB: with Python < 2.6 the old style buffer protocol may be used: - // Py_ssize_t unused; - // PyObject_AsReadBuffer(obj0, (const void**)(&arg1), &unused); - if (!PyObject_CheckBuffer(obj0)) { - SWIG_exception_fail(SWIG_TypeError, - "in method 'wrap_WebPEncodeLosslessBGRA', argument 1" - " does not support the buffer interface"); - } - if (PyObject_GetBuffer(obj0, &rgb_buffer1, PyBUF_SIMPLE)) { - SWIG_exception_fail(SWIG_RuntimeError, - "in method 'wrap_WebPEncodeLosslessBGRA', unable to get buffer view"); - } - arg1 = (uint8_t *)rgb_buffer1.buf; - } - if (!(SWIG_IsOK((res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj1, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessBGRA" "', argument " "2"" of type '" "int""'"); - } - temp2 = (int)(val); - arg2 = &temp2; - res2 = SWIG_AddTmpMask(ecode); - } - if (!(SWIG_IsOK((res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3),SWIGTYPE_p_int,0))))) { - int val; - int ecode = SWIG_AsVal_int(obj2, &val); - if (!SWIG_IsOK(ecode)) { - SWIG_exception_fail(SWIG_ArgError(ecode), "in method '" "wrap_WebPEncodeLosslessBGRA" "', argument " "3"" of type '" "int""'"); - } - temp3 = (int)(val); - arg3 = &temp3; - res3 = SWIG_AddTmpMask(ecode); - } - ecode5 = SWIG_AsVal_int(obj3, &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "wrap_WebPEncodeLosslessBGRA" "', argument " "5"" of type '" "int""'"); - } - arg5 = (int)(val5); - ecode6 = SWIG_AsVal_int(obj4, &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "wrap_WebPEncodeLosslessBGRA" "', argument " "6"" of type '" "int""'"); - } - arg6 = (int)(val6); - ecode7 = SWIG_AsVal_int(obj5, &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "wrap_WebPEncodeLosslessBGRA" "', argument " "7"" of type '" "int""'"); - } - arg7 = (int)(val7); - result = (uint8_t *)wrap_WebPEncodeLosslessBGRA((uint8_t const *)arg1,arg2,arg3,arg4,arg5,arg6,arg7); - { - resultobj = PyString_FromStringAndSize( - (const char*)result, - (result == NULL) ? 0 : ReturnedBufferSize("wrap_WebPEncodeLosslessBGRA", arg3, arg4)); - } - if (SWIG_IsTmpObj(res4)) { - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_int((*arg4))); - } else { - int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0 ) : 0 ; - resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags)); - } - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - free(result); - return resultobj; -fail: - { - PyBuffer_Release(&rgb_buffer1); - } - if (SWIG_IsNewObj(res2)) free((char*)arg2); - if (SWIG_IsNewObj(res3)) free((char*)arg3); - return NULL; -} - - -static PyMethodDef SwigMethods[] = { - { "SWIG_PyInstanceMethod_New", SWIG_PyInstanceMethod_New, METH_O, NULL}, - { "WebPGetDecoderVersion", _wrap_WebPGetDecoderVersion, METH_VARARGS, (char *)"WebPGetDecoderVersion() -> int"}, - { "WebPGetInfo", _wrap_WebPGetInfo, METH_VARARGS, (char *)"WebPGetInfo(uint8_t data) -> (width, height)"}, - { "WebPDecodeRGB", _wrap_WebPDecodeRGB, METH_VARARGS, (char *)"WebPDecodeRGB(uint8_t data) -> (rgb, width, height)"}, - { "WebPDecodeRGBA", _wrap_WebPDecodeRGBA, METH_VARARGS, (char *)"WebPDecodeRGBA(uint8_t data) -> (rgb, width, height)"}, - { "WebPDecodeARGB", _wrap_WebPDecodeARGB, METH_VARARGS, (char *)"WebPDecodeARGB(uint8_t data) -> (rgb, width, height)"}, - { "WebPDecodeBGR", _wrap_WebPDecodeBGR, METH_VARARGS, (char *)"WebPDecodeBGR(uint8_t data) -> (rgb, width, height)"}, - { "WebPDecodeBGRA", _wrap_WebPDecodeBGRA, METH_VARARGS, (char *)"WebPDecodeBGRA(uint8_t data) -> (rgb, width, height)"}, - { "WebPGetEncoderVersion", _wrap_WebPGetEncoderVersion, METH_VARARGS, (char *)"WebPGetEncoderVersion() -> int"}, - { "wrap_WebPEncodeRGB", _wrap_wrap_WebPEncodeRGB, METH_VARARGS, (char *)"private, do not call directly."}, - { "wrap_WebPEncodeBGR", _wrap_wrap_WebPEncodeBGR, METH_VARARGS, (char *)"private, do not call directly."}, - { "wrap_WebPEncodeRGBA", _wrap_wrap_WebPEncodeRGBA, METH_VARARGS, (char *)"private, do not call directly."}, - { "wrap_WebPEncodeBGRA", _wrap_wrap_WebPEncodeBGRA, METH_VARARGS, (char *)"private, do not call directly."}, - { "wrap_WebPEncodeLosslessRGB", _wrap_wrap_WebPEncodeLosslessRGB, METH_VARARGS, (char *)"private, do not call directly."}, - { "wrap_WebPEncodeLosslessBGR", _wrap_wrap_WebPEncodeLosslessBGR, METH_VARARGS, (char *)"private, do not call directly."}, - { "wrap_WebPEncodeLosslessRGBA", _wrap_wrap_WebPEncodeLosslessRGBA, METH_VARARGS, (char *)"private, do not call directly."}, - { "wrap_WebPEncodeLosslessBGRA", _wrap_wrap_WebPEncodeLosslessBGRA, METH_VARARGS, (char *)"private, do not call directly."}, - { NULL, NULL, 0, NULL } -}; - - -/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ - -static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_int = {"_p_int", "int *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_uint8_t = {"_p_uint8_t", "uint8_t *", 0, 0, (void*)0, 0}; - -static swig_type_info *swig_type_initial[] = { - &_swigt__p_char, - &_swigt__p_int, - &_swigt__p_uint8_t, -}; - -static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_uint8_t[] = { {&_swigt__p_uint8_t, 0, 0, 0},{0, 0, 0, 0}}; - -static swig_cast_info *swig_cast_initial[] = { - _swigc__p_char, - _swigc__p_int, - _swigc__p_uint8_t, -}; - - -/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ - -static swig_const_info swig_const_table[] = { -{0, 0, 0, 0.0, 0, 0}}; - -#ifdef __cplusplus -} -#endif -/* ----------------------------------------------------------------------------- - * Type initialization: - * This problem is tough by the requirement that no dynamic - * memory is used. Also, since swig_type_info structures store pointers to - * swig_cast_info structures and swig_cast_info structures store pointers back - * to swig_type_info structures, we need some lookup code at initialization. - * The idea is that swig generates all the structures that are needed. - * The runtime then collects these partially filled structures. - * The SWIG_InitializeModule function takes these initial arrays out of - * swig_module, and does all the lookup, filling in the swig_module.types - * array with the correct data and linking the correct swig_cast_info - * structures together. - * - * The generated swig_type_info structures are assigned statically to an initial - * array. We just loop through that array, and handle each type individually. - * First we lookup if this type has been already loaded, and if so, use the - * loaded structure instead of the generated one. Then we have to fill in the - * cast linked list. The cast data is initially stored in something like a - * two-dimensional array. Each row corresponds to a type (there are the same - * number of rows as there are in the swig_type_initial array). Each entry in - * a column is one of the swig_cast_info structures for that type. - * The cast_initial array is actually an array of arrays, because each row has - * a variable number of columns. So to actually build the cast linked list, - * we find the array of casts associated with the type, and loop through it - * adding the casts to the list. The one last trick we need to do is making - * sure the type pointer in the swig_cast_info struct is correct. - * - * First off, we lookup the cast->type name to see if it is already loaded. - * There are three cases to handle: - * 1) If the cast->type has already been loaded AND the type we are adding - * casting info to has not been loaded (it is in this module), THEN we - * replace the cast->type pointer with the type pointer that has already - * been loaded. - * 2) If BOTH types (the one we are adding casting info to, and the - * cast->type) are loaded, THEN the cast info has already been loaded by - * the previous module so we just ignore it. - * 3) Finally, if cast->type has not already been loaded, then we add that - * swig_cast_info to the linked list (because the cast->type) pointer will - * be correct. - * ----------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#if 0 -} /* c-mode */ -#endif -#endif - -#if 0 -#define SWIGRUNTIME_DEBUG -#endif - - -SWIGRUNTIME void -SWIG_InitializeModule(void *clientdata) { - size_t i; - swig_module_info *module_head, *iter; - int init; - - /* check to see if the circular list has been setup, if not, set it up */ - if (swig_module.next==0) { - /* Initialize the swig_module */ - swig_module.type_initial = swig_type_initial; - swig_module.cast_initial = swig_cast_initial; - swig_module.next = &swig_module; - init = 1; - } else { - init = 0; - } - - /* Try and load any already created modules */ - module_head = SWIG_GetModule(clientdata); - if (!module_head) { - /* This is the first module loaded for this interpreter */ - /* so set the swig module into the interpreter */ - SWIG_SetModule(clientdata, &swig_module); - } else { - /* the interpreter has loaded a SWIG module, but has it loaded this one? */ - iter=module_head; - do { - if (iter==&swig_module) { - /* Our module is already in the list, so there's nothing more to do. */ - return; - } - iter=iter->next; - } while (iter!= module_head); - - /* otherwise we must add our module into the list */ - swig_module.next = module_head->next; - module_head->next = &swig_module; - } - - /* When multiple interpreters are used, a module could have already been initialized in - a different interpreter, but not yet have a pointer in this interpreter. - In this case, we do not want to continue adding types... everything should be - set up already */ - if (init == 0) return; - - /* Now work on filling in swig_module.types */ -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: size %d\n", swig_module.size); -#endif - for (i = 0; i < swig_module.size; ++i) { - swig_type_info *type = 0; - swig_type_info *ret; - swig_cast_info *cast; - -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); -#endif - - /* if there is another module already loaded */ - if (swig_module.next != &swig_module) { - type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); - } - if (type) { - /* Overwrite clientdata field */ -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found type %s\n", type->name); -#endif - if (swig_module.type_initial[i]->clientdata) { - type->clientdata = swig_module.type_initial[i]->clientdata; -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); -#endif - } - } else { - type = swig_module.type_initial[i]; - } - - /* Insert casting types */ - cast = swig_module.cast_initial[i]; - while (cast->type) { - /* Don't need to add information already in the list */ - ret = 0; -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); -#endif - if (swig_module.next != &swig_module) { - ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); -#ifdef SWIGRUNTIME_DEBUG - if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); -#endif - } - if (ret) { - if (type == swig_module.type_initial[i]) { -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: skip old type %s\n", ret->name); -#endif - cast->type = ret; - ret = 0; - } else { - /* Check for casting already in the list */ - swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); -#ifdef SWIGRUNTIME_DEBUG - if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); -#endif - if (!ocast) ret = 0; - } - } - - if (!ret) { -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); -#endif - if (type->cast) { - type->cast->prev = cast; - cast->next = type->cast; - } - type->cast = cast; - } - cast++; - } - /* Set entry in modules->types array equal to the type */ - swig_module.types[i] = type; - } - swig_module.types[i] = 0; - -#ifdef SWIGRUNTIME_DEBUG - printf("**** SWIG_InitializeModule: Cast List ******\n"); - for (i = 0; i < swig_module.size; ++i) { - int j = 0; - swig_cast_info *cast = swig_module.cast_initial[i]; - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); - while (cast->type) { - printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); - cast++; - ++j; - } - printf("---- Total casts: %d\n",j); - } - printf("**** SWIG_InitializeModule: Cast List ******\n"); -#endif -} - -/* This function will propagate the clientdata field of type to -* any new swig_type_info structures that have been added into the list -* of equivalent types. It is like calling -* SWIG_TypeClientData(type, clientdata) a second time. -*/ -SWIGRUNTIME void -SWIG_PropagateClientData(void) { - size_t i; - swig_cast_info *equiv; - static int init_run = 0; - - if (init_run) return; - init_run = 1; - - for (i = 0; i < swig_module.size; i++) { - if (swig_module.types[i]->clientdata) { - equiv = swig_module.types[i]->cast; - while (equiv) { - if (!equiv->converter) { - if (equiv->type && !equiv->type->clientdata) - SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); - } - equiv = equiv->next; - } - } - } -} - -#ifdef __cplusplus -#if 0 -{ - /* c-mode */ -#endif -} -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - - /* Python-specific SWIG API */ -#define SWIG_newvarlink() SWIG_Python_newvarlink() -#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) -#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants) - - /* ----------------------------------------------------------------------------- - * global variable support code. - * ----------------------------------------------------------------------------- */ - - typedef struct swig_globalvar { - char *name; /* Name of global variable */ - PyObject *(*get_attr)(void); /* Return the current value */ - int (*set_attr)(PyObject *); /* Set the value */ - struct swig_globalvar *next; - } swig_globalvar; - - typedef struct swig_varlinkobject { - PyObject_HEAD - swig_globalvar *vars; - } swig_varlinkobject; - - SWIGINTERN PyObject * - swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_InternFromString(""); -#else - return PyString_FromString(""); -#endif - } - - SWIGINTERN PyObject * - swig_varlink_str(swig_varlinkobject *v) { -#if PY_VERSION_HEX >= 0x03000000 - PyObject *str = PyUnicode_InternFromString("("); - PyObject *tail; - PyObject *joined; - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - tail = PyUnicode_FromString(var->name); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - if (var->next) { - tail = PyUnicode_InternFromString(", "); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - } - } - tail = PyUnicode_InternFromString(")"); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; -#else - PyObject *str = PyString_FromString("("); - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - PyString_ConcatAndDel(&str,PyString_FromString(var->name)); - if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", ")); - } - PyString_ConcatAndDel(&str,PyString_FromString(")")); -#endif - return str; - } - - SWIGINTERN int - swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { - char *tmp; - PyObject *str = swig_varlink_str(v); - fprintf(fp,"Swig global variables "); - fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str)); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(str); - return 0; - } - - SWIGINTERN void - swig_varlink_dealloc(swig_varlinkobject *v) { - swig_globalvar *var = v->vars; - while (var) { - swig_globalvar *n = var->next; - free(var->name); - free(var); - var = n; - } - } - - SWIGINTERN PyObject * - swig_varlink_getattr(swig_varlinkobject *v, char *n) { - PyObject *res = NULL; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->get_attr)(); - break; - } - var = var->next; - } - if (res == NULL && !PyErr_Occurred()) { - PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); - } - return res; - } - - SWIGINTERN int - swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { - int res = 1; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->set_attr)(p); - break; - } - var = var->next; - } - if (res == 1 && !PyErr_Occurred()) { - PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); - } - return res; - } - - SWIGINTERN PyTypeObject* - swig_varlink_type(void) { - static char varlink__doc__[] = "Swig var link object"; - static PyTypeObject varlink_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"swigvarlink", /* tp_name */ - sizeof(swig_varlinkobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) swig_varlink_dealloc, /* tp_dealloc */ - (printfunc) swig_varlink_print, /* tp_print */ - (getattrfunc) swig_varlink_getattr, /* tp_getattr */ - (setattrfunc) swig_varlink_setattr, /* tp_setattr */ - 0, /* tp_compare */ - (reprfunc) swig_varlink_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - (reprfunc) swig_varlink_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - 0, /* tp_flags */ - varlink__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 - 0, /* tp_version_tag */ -#endif -#if PY_VERSION_HEX >= 0x03040000 - 0, /* tp_finalize */ -#endif -#ifdef COUNT_ALLOCS - 0, /* tp_allocs */ - 0, /* tp_frees */ - 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 - 0, /* tp_prev */ -#endif - 0 /* tp_next */ -#endif - }; - varlink_type = tmp; - type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - varlink_type.ob_type = &PyType_Type; -#else - if (PyType_Ready(&varlink_type) < 0) - return NULL; -#endif - } - return &varlink_type; - } - - /* Create a variable linking object for use later */ - SWIGINTERN PyObject * - SWIG_Python_newvarlink(void) { - swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); - if (result) { - result->vars = 0; - } - return ((PyObject*) result); - } - - SWIGINTERN void - SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { - swig_varlinkobject *v = (swig_varlinkobject *) p; - swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); - if (gv) { - size_t size = strlen(name)+1; - gv->name = (char *)malloc(size); - if (gv->name) { - strncpy(gv->name,name,size); - gv->get_attr = get_attr; - gv->set_attr = set_attr; - gv->next = v->vars; - } - } - v->vars = gv; - } - - SWIGINTERN PyObject * - SWIG_globals(void) { - static PyObject *_SWIG_globals = 0; - if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink(); - return _SWIG_globals; - } - - /* ----------------------------------------------------------------------------- - * constants/methods manipulation - * ----------------------------------------------------------------------------- */ - - /* Install Constants */ - SWIGINTERN void - SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { - PyObject *obj = 0; - size_t i; - for (i = 0; constants[i].type; ++i) { - switch(constants[i].type) { - case SWIG_PY_POINTER: - obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); - break; - case SWIG_PY_BINARY: - obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); - break; - default: - obj = 0; - break; - } - if (obj) { - PyDict_SetItemString(d, constants[i].name, obj); - Py_DECREF(obj); - } - } - } - - /* -----------------------------------------------------------------------------*/ - /* Fix SwigMethods to carry the callback ptrs when needed */ - /* -----------------------------------------------------------------------------*/ - - SWIGINTERN void - SWIG_Python_FixMethods(PyMethodDef *methods, - swig_const_info *const_table, - swig_type_info **types, - swig_type_info **types_initial) { - size_t i; - for (i = 0; methods[i].ml_name; ++i) { - const char *c = methods[i].ml_doc; - if (!c) continue; - c = strstr(c, "swig_ptr: "); - if (c) { - int j; - swig_const_info *ci = 0; - const char *name = c + 10; - for (j = 0; const_table[j].type; ++j) { - if (strncmp(const_table[j].name, name, - strlen(const_table[j].name)) == 0) { - ci = &(const_table[j]); - break; - } - } - if (ci) { - void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; - if (ptr) { - size_t shift = (ci->ptype) - types; - swig_type_info *ty = types_initial[shift]; - size_t ldoc = (c - methods[i].ml_doc); - size_t lptr = strlen(ty->name)+2*sizeof(void*)+2; - char *ndoc = (char*)malloc(ldoc + lptr + 10); - if (ndoc) { - char *buff = ndoc; - memcpy(buff, methods[i].ml_doc, ldoc); - buff += ldoc; - memcpy(buff, "swig_ptr: ", 10); - buff += 10; - SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); - methods[i].ml_doc = ndoc; - } - } - } - } - } - } - -#ifdef __cplusplus -} -#endif - -/* -----------------------------------------------------------------------------* - * Partial Init method - * -----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" -#endif - -SWIGEXPORT -#if PY_VERSION_HEX >= 0x03000000 -PyObject* -#else -void -#endif -SWIG_init(void) { - PyObject *m, *d, *md; -#if PY_VERSION_HEX >= 0x03000000 - static struct PyModuleDef SWIG_module = { -# if PY_VERSION_HEX >= 0x03020000 - PyModuleDef_HEAD_INIT, -# else - { - PyObject_HEAD_INIT(NULL) - NULL, /* m_init */ - 0, /* m_index */ - NULL, /* m_copy */ - }, -# endif - (char *) SWIG_name, - NULL, - -1, - SwigMethods, - NULL, - NULL, - NULL, - NULL - }; -#endif - -#if defined(SWIGPYTHON_BUILTIN) - static SwigPyClientData SwigPyObject_clientdata = { - 0, 0, 0, 0, 0, 0, 0 - }; - static PyGetSetDef this_getset_def = { - (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL - }; - static SwigPyGetSet thisown_getset_closure = { - SwigPyObject_own, - SwigPyObject_own - }; - static PyGetSetDef thisown_getset_def = { - (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure - }; - PyTypeObject *builtin_pytype; - int builtin_base_count; - swig_type_info *builtin_basetype; - PyObject *tuple; - PyGetSetDescrObject *static_getset; - PyTypeObject *metatype; - PyTypeObject *swigpyobject; - SwigPyClientData *cd; - PyObject *public_interface, *public_symbol; - PyObject *this_descr; - PyObject *thisown_descr; - PyObject *self = 0; - int i; - - (void)builtin_pytype; - (void)builtin_base_count; - (void)builtin_basetype; - (void)tuple; - (void)static_getset; - (void)self; - - /* Metaclass is used to implement static member variables */ - metatype = SwigPyObjectType(); - assert(metatype); -#endif - - /* Fix SwigMethods to carry the callback ptrs when needed */ - SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial); - -#if PY_VERSION_HEX >= 0x03000000 - m = PyModule_Create(&SWIG_module); -#else - m = Py_InitModule((char *) SWIG_name, SwigMethods); -#endif - - md = d = PyModule_GetDict(m); - (void)md; - - SWIG_InitializeModule(0); - -#ifdef SWIGPYTHON_BUILTIN - swigpyobject = SwigPyObject_TypeOnce(); - - SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject"); - assert(SwigPyObject_stype); - cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; - if (!cd) { - SwigPyObject_stype->clientdata = &SwigPyObject_clientdata; - SwigPyObject_clientdata.pytype = swigpyobject; - } else if (swigpyobject->tp_basicsize != cd->pytype->tp_basicsize) { - PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules."); -# if PY_VERSION_HEX >= 0x03000000 - return NULL; -# else - return; -# endif - } - - /* All objects have a 'this' attribute */ - this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def); - (void)this_descr; - - /* All objects have a 'thisown' attribute */ - thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def); - (void)thisown_descr; - - public_interface = PyList_New(0); - public_symbol = 0; - (void)public_symbol; - - PyDict_SetItemString(md, "__all__", public_interface); - Py_DECREF(public_interface); - for (i = 0; SwigMethods[i].ml_name != NULL; ++i) - SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name); - for (i = 0; swig_const_table[i].name != 0; ++i) - SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name); -#endif - - SWIG_InstallConstants(d,swig_const_table); - -#if PY_VERSION_HEX >= 0x03000000 - return m; -#else - return; -#endif -} - diff --git a/libwebp_src/swig/setup.py b/libwebp_src/swig/setup.py deleted file mode 100644 index 3a3bfe1..0000000 --- a/libwebp_src/swig/setup.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/python - -"""distutils script for libwebp python module.""" - -from distutils.core import setup -from distutils.extension import Extension -import os -import shutil -import tempfile - -tmpdir = tempfile.mkdtemp() -package = "com.google.webp" -package_path = os.path.join(tmpdir, *package.split(".")) -os.makedirs(package_path) - -# Create __init_.py files along the package path. -initpy_path = tmpdir -for d in package.split("."): - initpy_path = os.path.join(initpy_path, d) - open(os.path.join(initpy_path, "__init__.py"), "w").close() - -shutil.copy2("libwebp.py", package_path) -setup(name="libwebp", - version="0.0", - description="libwebp python wrapper", - long_description="Provides access to 'simple' libwebp decode interface", - license="BSD", - url="http://developers.google.com/speed/webp", - ext_package=package, - ext_modules=[Extension("_libwebp", - ["libwebp_python_wrap.c"], - libraries=["webp"], - ), - ], - package_dir={"": tmpdir}, - packages=["com", "com.google", "com.google.webp"], - py_modules=[package + ".libwebp"], - ) - -shutil.rmtree(tmpdir) diff --git a/libwebp_src/tests/fuzzer/advanced_api_fuzzer.c b/libwebp_src/tests/fuzzer/advanced_api_fuzzer.c index c8fb176..22c689b 100644 --- a/libwebp_src/tests/fuzzer/advanced_api_fuzzer.c +++ b/libwebp_src/tests/fuzzer/advanced_api_fuzzer.c @@ -130,7 +130,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { } WebPIDelete(idec); } else { - WebPDecode(data, size, &config); + (void)WebPDecode(data, size, &config); } WebPFreeDecBuffer(&config.output); diff --git a/libwebp_src/tests/fuzzer/animdecoder_fuzzer.cc b/libwebp_src/tests/fuzzer/animdecoder_fuzzer.cc index a79712d..c3ea475 100644 --- a/libwebp_src/tests/fuzzer/animdecoder_fuzzer.cc +++ b/libwebp_src/tests/fuzzer/animdecoder_fuzzer.cc @@ -14,25 +14,34 @@ // //////////////////////////////////////////////////////////////////////////////// -#include "examples/anim_util.h" +#include +#include + #include "imageio/imageio_util.h" +#include "src/webp/decode.h" #include "src/webp/demux.h" +#include "src/webp/mux_types.h" -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // WebPAnimDecoderGetInfo() is too late to check the canvas size as // WebPAnimDecoderNew() will handle the allocations. + const size_t kMaxNumBytes = 2684354560; // RSS (resident set size) limit. + const size_t kMaxNumPixels = kMaxNumBytes / 4; // At most ARGB. + const size_t kMaxNumPixelsSafe = kMaxNumPixels / 2; // Allow one buffer copy. WebPBitstreamFeatures features; if (WebPGetFeatures(data, size, &features) == VP8_STATUS_OK) { if (!ImgIoUtilCheckSizeArgumentsOverflow(features.width * 4, - features.height)) { + features.height) || + static_cast(features.width) * features.height > + kMaxNumPixelsSafe) { return 0; } } // decode everything as an animation - WebPData webp_data = { data, size }; - WebPAnimDecoder* const dec = WebPAnimDecoderNew(&webp_data, NULL); - if (dec == NULL) return 0; + WebPData webp_data = {data, size}; + WebPAnimDecoder* const dec = WebPAnimDecoderNew(&webp_data, nullptr); + if (dec == nullptr) return 0; WebPAnimInfo info; if (!WebPAnimDecoderGetInfo(dec, &info)) goto End; @@ -46,7 +55,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { int timestamp; if (!WebPAnimDecoderGetNext(dec, &buf, ×tamp)) break; } - End: +End: WebPAnimDecoderDelete(dec); return 0; } diff --git a/libwebp_src/tests/fuzzer/animencoder_fuzzer.cc b/libwebp_src/tests/fuzzer/animencoder_fuzzer.cc index 1bd7871..ef6ec1e 100644 --- a/libwebp_src/tests/fuzzer/animencoder_fuzzer.cc +++ b/libwebp_src/tests/fuzzer/animencoder_fuzzer.cc @@ -47,6 +47,7 @@ int AddFrame(WebPAnimEncoder** const enc, // Read the source picture. if (!ExtractSourcePicture(&pic, data, size, bit_pos)) { const WebPEncodingError error_code = pic.error_code; + WebPAnimEncoderDelete(*enc); WebPPictureFree(&pic); if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return 0; fprintf(stderr, "Can't read input image. Error code: %d\n", error_code); @@ -108,7 +109,14 @@ int AddFrame(WebPAnimEncoder** const enc, const WebPEncodingError error_code = pic.error_code; WebPAnimEncoderDelete(*enc); WebPPictureFree(&pic); - if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return 0; + // Tolerate failures when running under the nallocfuzz engine as + // WebPAnimEncoderAdd() may fail due to memory allocation errors outside of + // the encoder; in muxer functions that return booleans for instance. + if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY || + error_code == VP8_ENC_ERROR_BAD_WRITE || + getenv("NALLOC_FUZZ_VERSION") != nullptr) { + return 0; + } fprintf(stderr, "WebPEncode failed. Error code: %d\n", error_code); abort(); } @@ -163,7 +171,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { } WebPData webp_data; WebPDataInit(&webp_data); - if (!WebPAnimEncoderAssemble(enc, &webp_data)) { + // Tolerate failures when running under the nallocfuzz engine as allocations + // during assembly may fail. + if (!WebPAnimEncoderAssemble(enc, &webp_data) && + getenv("NALLOC_FUZZ_VERSION") == nullptr) { fprintf(stderr, "WebPAnimEncoderAssemble failed: %s.\n", WebPAnimEncoderGetError(enc)); WebPAnimEncoderDelete(enc); diff --git a/libwebp_src/tests/fuzzer/enc_dec_fuzzer.cc b/libwebp_src/tests/fuzzer/enc_dec_fuzzer.cc index 187b516..c5d46ae 100644 --- a/libwebp_src/tests/fuzzer/enc_dec_fuzzer.cc +++ b/libwebp_src/tests/fuzzer/enc_dec_fuzzer.cc @@ -91,50 +91,70 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { const WebPEncodingError error_code = pic.error_code; WebPMemoryWriterClear(&memory_writer); WebPPictureFree(&pic); - if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return 0; + if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY || + error_code == VP8_ENC_ERROR_BAD_WRITE) { + return 0; + } fprintf(stderr, "WebPEncode failed. Error code: %d\n", error_code); abort(); } // Try decoding the result. - int w, h; const uint8_t* const out_data = memory_writer.mem; const size_t out_size = memory_writer.size; - uint8_t* const rgba = WebPDecodeBGRA(out_data, out_size, &w, &h); - if (rgba == nullptr || w != pic.width || h != pic.height) { - fprintf(stderr, "WebPDecodeBGRA failed.\n"); - WebPFree(rgba); + WebPDecoderConfig dec_config; + if (!WebPInitDecoderConfig(&dec_config)) { + fprintf(stderr, "WebPInitDecoderConfig failed.\n"); + WebPMemoryWriterClear(&memory_writer); + WebPPictureFree(&pic); + abort(); + } + + dec_config.output.colorspace = MODE_BGRA; + const VP8StatusCode status = WebPDecode(out_data, out_size, &dec_config); + if ((status != VP8_STATUS_OK && status != VP8_STATUS_OUT_OF_MEMORY && + status != VP8_STATUS_USER_ABORT) || + (status == VP8_STATUS_OK && (dec_config.output.width != pic.width || + dec_config.output.height != pic.height))) { + fprintf(stderr, "WebPDecode failed. status: %d.\n", status); + WebPFreeDecBuffer(&dec_config.output); WebPMemoryWriterClear(&memory_writer); WebPPictureFree(&pic); abort(); } - // Compare the results if exact encoding. - if (pic.use_argb && config.lossless && config.near_lossless == 100) { - const uint32_t* src1 = (const uint32_t*)rgba; - const uint32_t* src2 = pic.argb; - for (int y = 0; y < h; ++y, src1 += w, src2 += pic.argb_stride) { - for (int x = 0; x < w; ++x) { - uint32_t v1 = src1[x], v2 = src2[x]; - if (!config.exact) { - if ((v1 & 0xff000000u) == 0 || (v2 & 0xff000000u) == 0) { - // Only keep alpha for comparison of fully transparent area. - v1 &= 0xff000000u; - v2 &= 0xff000000u; + if (status == VP8_STATUS_OK) { + const uint8_t* const rgba = dec_config.output.u.RGBA.rgba; + const int w = dec_config.output.width; + const int h = dec_config.output.height; + + // Compare the results if exact encoding. + if (pic.use_argb && config.lossless && config.near_lossless == 100) { + const uint32_t* src1 = (const uint32_t*)rgba; + const uint32_t* src2 = pic.argb; + for (int y = 0; y < h; ++y, src1 += w, src2 += pic.argb_stride) { + for (int x = 0; x < w; ++x) { + uint32_t v1 = src1[x], v2 = src2[x]; + if (!config.exact) { + if ((v1 & 0xff000000u) == 0 || (v2 & 0xff000000u) == 0) { + // Only keep alpha for comparison of fully transparent area. + v1 &= 0xff000000u; + v2 &= 0xff000000u; + } + } + if (v1 != v2) { + fprintf(stderr, "Lossless compression failed pixel-exactness.\n"); + WebPFreeDecBuffer(&dec_config.output); + WebPMemoryWriterClear(&memory_writer); + WebPPictureFree(&pic); + abort(); } - } - if (v1 != v2) { - fprintf(stderr, "Lossless compression failed pixel-exactness.\n"); - WebPFree(rgba); - WebPMemoryWriterClear(&memory_writer); - WebPPictureFree(&pic); - abort(); } } } } - WebPFree(rgba); + WebPFreeDecBuffer(&dec_config.output); WebPMemoryWriterClear(&memory_writer); WebPPictureFree(&pic); return 0; diff --git a/libwebp_src/tests/fuzzer/huffman_fuzzer.c b/libwebp_src/tests/fuzzer/huffman_fuzzer.c new file mode 100644 index 0000000..03e1fdc --- /dev/null +++ b/libwebp_src/tests/fuzzer/huffman_fuzzer.c @@ -0,0 +1,65 @@ +// Copyright 2023 Google Inc. +// +// 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. +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "src/dec/vp8li_dec.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/huffman_utils.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" + +int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { + // Number of bits to initialize data. + static const int kColorCacheBitsBits = 4; + // 'num_htree_groups' is contained in the RG channel, hence 16 bits. + static const int kNumHtreeGroupsBits = 16; + if (size * sizeof(*data) < kColorCacheBitsBits + kNumHtreeGroupsBits) { + return 0; + } + + // A non-NULL mapping brings minor changes that are tested by the normal + // fuzzer. + int* const mapping = NULL; + HuffmanTables huffman_tables; + memset(&huffman_tables, 0, sizeof(huffman_tables)); + HTreeGroup* htree_groups = NULL; + + VP8LDecoder* dec = VP8LNew(); + if (dec == NULL) goto Error; + VP8LBitReader* const br = &dec->br_; + VP8LInitBitReader(br, data, size); + + const int color_cache_bits = VP8LReadBits(br, kColorCacheBitsBits); + if (color_cache_bits < 1 || color_cache_bits > MAX_CACHE_BITS) goto Error; + + const int num_htree_groups = VP8LReadBits(br, kNumHtreeGroupsBits); + // 'num_htree_groups' cannot be 0 as it is built from a non-empty image. + if (num_htree_groups == 0) goto Error; + // This variable is only useful when mapping is not NULL. + const int num_htree_groups_max = num_htree_groups; + (void)ReadHuffmanCodesHelper(color_cache_bits, num_htree_groups, + num_htree_groups_max, mapping, dec, + &huffman_tables, &htree_groups); + + Error: + WebPSafeFree(mapping); + VP8LHtreeGroupsFree(htree_groups); + VP8LHuffmanTablesDeallocate(&huffman_tables); + VP8LDelete(dec); + return 0; +} diff --git a/libwebp_src/tests/fuzzer/makefile.unix b/libwebp_src/tests/fuzzer/makefile.unix index 4a9bff3..3a3aff0 100644 --- a/libwebp_src/tests/fuzzer/makefile.unix +++ b/libwebp_src/tests/fuzzer/makefile.unix @@ -11,9 +11,9 @@ LDLIBS = ../../src/mux/libwebpmux.a ../../src/demux/libwebpdemux.a LDLIBS += ../../src/libwebp.a ../../imageio/libimageio_util.a LDLIBS += ../../sharpyuv/libsharpyuv.a -FUZZERS = advanced_api_fuzzer animation_api_fuzzer animencoder_fuzzer -FUZZERS += animdecoder_fuzzer mux_demux_api_fuzzer enc_dec_fuzzer -FUZZERS += simple_api_fuzzer +FUZZERS = advanced_api_fuzzer animation_api_fuzzer animdecoder_fuzzer +FUZZERS += animencoder_fuzzer enc_dec_fuzzer huffman_fuzzer +FUZZERS += mux_demux_api_fuzzer simple_api_fuzzer %.o: fuzz_utils.h img_alpha.h img_grid.h img_peak.h all: $(FUZZERS) diff --git a/libwebp_src/tests/fuzzer/mux_demux_api_fuzzer.c b/libwebp_src/tests/fuzzer/mux_demux_api_fuzzer.c index 4ed0142..f5983e8 100644 --- a/libwebp_src/tests/fuzzer/mux_demux_api_fuzzer.c +++ b/libwebp_src/tests/fuzzer/mux_demux_api_fuzzer.c @@ -33,15 +33,15 @@ int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { if (!mux) return 0; WebPData chunk; - WebPMuxGetChunk(mux, "EXIF", &chunk); - WebPMuxGetChunk(mux, "ICCP", &chunk); - WebPMuxGetChunk(mux, "FUZZ", &chunk); // unknown + (void)WebPMuxGetChunk(mux, "EXIF", &chunk); + (void)WebPMuxGetChunk(mux, "ICCP", &chunk); + (void)WebPMuxGetChunk(mux, "FUZZ", &chunk); // unknown uint32_t flags; - WebPMuxGetFeatures(mux, &flags); + (void)WebPMuxGetFeatures(mux, &flags); WebPMuxAnimParams params; - WebPMuxGetAnimationParams(mux, ¶ms); + (void)WebPMuxGetAnimationParams(mux, ¶ms); WebPMuxError status; WebPMuxFrameInfo info; @@ -72,11 +72,11 @@ int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { WebPChunkIterator chunk_iter; if (WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter)) { - WebPDemuxNextChunk(&chunk_iter); + (void)WebPDemuxNextChunk(&chunk_iter); } WebPDemuxReleaseChunkIterator(&chunk_iter); if (WebPDemuxGetChunk(demux, "ICCP", 0, &chunk_iter)) { // 0 == last - WebPDemuxPrevChunk(&chunk_iter); + (void)WebPDemuxPrevChunk(&chunk_iter); } WebPDemuxReleaseChunkIterator(&chunk_iter); // Skips FUZZ because the Demux API has no concept of (un)known chunks. diff --git a/libwebp_src/tests/fuzzer/simple_api_fuzzer.c b/libwebp_src/tests/fuzzer/simple_api_fuzzer.c index 7d2b7f8..3a4288a 100644 --- a/libwebp_src/tests/fuzzer/simple_api_fuzzer.c +++ b/libwebp_src/tests/fuzzer/simple_api_fuzzer.c @@ -49,17 +49,17 @@ int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { if (value % 0x10 == 0) buf_size--; uint8_t* const ext_buf = (uint8_t*)malloc(buf_size); if (value < 0x94) { - WebPDecodeRGBAInto(data, size, ext_buf, buf_size, stride); + (void)WebPDecodeRGBAInto(data, size, ext_buf, buf_size, stride); #if !defined(WEBP_REDUCE_CSP) } else if (value < 0xa9) { - WebPDecodeARGBInto(data, size, ext_buf, buf_size, stride); + (void)WebPDecodeARGBInto(data, size, ext_buf, buf_size, stride); } else if (value < 0xbe) { - WebPDecodeBGRInto(data, size, ext_buf, buf_size, stride); + (void)WebPDecodeBGRInto(data, size, ext_buf, buf_size, stride); } else if (value < 0xd3) { - WebPDecodeRGBInto(data, size, ext_buf, buf_size, stride); + (void)WebPDecodeRGBInto(data, size, ext_buf, buf_size, stride); #endif // !defined(WEBP_REDUCE_CSP) } else { - WebPDecodeBGRAInto(data, size, ext_buf, buf_size, stride); + (void)WebPDecodeBGRAInto(data, size, ext_buf, buf_size, stride); } free(ext_buf); } else { @@ -75,8 +75,9 @@ int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) { uint8_t* const luma_buf = (uint8_t*)malloc(luma_size); uint8_t* const u_buf = (uint8_t*)malloc(u_size); uint8_t* const v_buf = (uint8_t*)malloc(v_size); - WebPDecodeYUVInto(data, size, luma_buf, luma_size, w /* luma_stride */, - u_buf, u_size, uv_stride, v_buf, v_size, uv_stride); + (void)WebPDecodeYUVInto(data, size, luma_buf, luma_size, + w /* luma_stride */, u_buf, u_size, uv_stride, + v_buf, v_size, uv_stride); free(luma_buf); free(u_buf); free(v_buf); diff --git a/libwebp_src/webp_js/README.md b/libwebp_src/webp_js/README.md index 824afa0..ae9ce8f 100644 --- a/libwebp_src/webp_js/README.md +++ b/libwebp_src/webp_js/README.md @@ -20,8 +20,7 @@ Emscripten and CMake. ```shell cd webp_js && \ - emcmake cmake -DWEBP_BUILD_WEBP_JS=ON \ - ../ + emcmake cmake -DWEBP_BUILD_WEBP_JS=ON ../ ``` - compile webp.js using 'emmake make'. @@ -55,27 +54,7 @@ directory. See webp_js/index_wasm.html for a simple demo page using the WASM version of the library. -You will need a fairly recent version of Emscripten (at least 2.0.18, -latest-upstream is recommended) and of your WASM-enabled browser to run this -version. - ## Caveats - First decoding using the library is usually slower, due to just-in-time compilation. - -- Some versions of llvm produce the following compile error when SSE2 is - enabled. - - ``` - "Unsupported: %516 = bitcast <8 x i16> %481 to i128 - LLVM ERROR: BitCast Instruction not yet supported for integer types larger than 64 bits" - ``` - - The corresponding Emscripten bug is at: - https://github.com/kripken/emscripten/issues/3788 - - Therefore, SSE2 optimization is currently disabled in CMakeLists.txt. - -- If WEBP_ENABLE_SIMD is set to 1 the JavaScript version (webp.js) will be - disabled as wasm2js does not support SIMD. diff --git a/libwebp_src/webp_js/index.html b/libwebp_src/webp_js/index.html index 33cacb4..e7c3b65 100644 --- a/libwebp_src/webp_js/index.html +++ b/libwebp_src/webp_js/index.html @@ -29,6 +29,8 @@ // clear previous picture (if any) Module.canvas = canvas; canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height); + // Map this canvas to the default selector used by emscripten/SDL2. + specialHTMLTargets["#canvas"] = Module.canvas; // decode and measure timing var start = new Date(); var ret = WebpToCanvas(webp_data, webp_data.length); diff --git a/libwebp_src/webp_js/index_wasm.html b/libwebp_src/webp_js/index_wasm.html index 5d7c17e..29933ab 100644 --- a/libwebp_src/webp_js/index_wasm.html +++ b/libwebp_src/webp_js/index_wasm.html @@ -9,6 +9,7 @@ noInitialRun : true }; +